Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialize texture sub-resources to zero #1102

Closed
cloudhead opened this issue Jul 2, 2019 · 10 comments · Fixed by #1688
Closed

Initialize texture sub-resources to zero #1102

cloudhead opened this issue Jul 2, 2019 · 10 comments · Fixed by #1688
Labels
area: validation Issues related to validation, diagnostics, and error handling help required We need community help to make this happen. type: bug Something isn't working

Comments

@cloudhead
Copy link
Contributor

If the hello_triangle example is changed slightly to only draw the triangle once, and we change the color attachment's load_op to wgpu::LoadOp::Load instead of Clear, my expectation is that the result is the same, except that the green clear color is gone. However the result is that the red triangle only shows up every other frame, with blank frames in between.

Is this expected behavior?

@cloudhead
Copy link
Contributor Author

cloudhead commented Jul 2, 2019

Here's a diff of what I changed:

diff --git a/examples/hello-triangle/main.rs b/examples/hello-triangle/main.rs
index ceacf4e..71daf82 100644
--- a/examples/hello-triangle/main.rs
+++ b/examples/hello-triangle/main.rs
@@ -113,6 +108,7 @@ fn main() {
         },
     );
     let mut running = true;
+    let mut once = true;
     while running {
         events_loop.poll_events(|event| match event {
             Event::WindowEvent { event, .. } => match event {
@@ -142,15 +138,18 @@ fn main() {
                 color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
                     attachment: &frame.view,
                     resolve_target: None,
-                    load_op: wgpu::LoadOp::Clear,
+                    load_op: wgpu::LoadOp::Load,
                     store_op: wgpu::StoreOp::Store,
                     clear_color: wgpu::Color::GREEN,
                 }],
                 depth_stencil_attachment: None,
             });
             rpass.set_pipeline(&render_pipeline);
-            rpass.set_bind_group(0, &bind_group, &[]);
-            rpass.draw(0 .. 3, 0 .. 1);
+            if once {
+                rpass.set_bind_group(0, &bind_group, &[]);
+                rpass.draw(0..3, 0..1);
+                once = false;
+            }
         }

         device.get_queue().submit(&[encoder.finish()]);

@kvark
Copy link
Member

kvark commented Jul 2, 2019

Thank you for filing the issue!

By design WebGPU is required to zero-clear all resources. It doesn't allow uninitialized data to be used for anything. Newly acquired frames are also considered "new" resources and should be cleared unless the user does a LoadOp::Clear operation themselves (so that we know it's cleared).

Currently, this zero-initialization semantics isn't implemented here (in wgpu-native), but it should be.

@cloudhead
Copy link
Contributor Author

Hmm, are you sure that is the issue? If the zero-initialization semantics were implemented it would mean that my frames would be zero-initialized (since I don't use LoadOp::Clear) - but I don't see how that would cause the triangle to show up on every frame?

I did another experiment which is to draw the triangle twice, on two consecutive frames, and then never again. This yields the correct result, of showing the triangle on every frame thereafter. This leads me to believe that it could have to do with double-buffering. The explanation in this case would be that in my first experiment, the triangle is only drawn on frame 0, and therefore only shows up on even frames, while the odd frames never show the triangle, since they are using a different swap chain texture. Am I missing something?

@grovesNL
Copy link
Collaborator

grovesNL commented Jul 2, 2019

With zero-initialization you'd only be able to see the triangle in a single frame (i.e. once) – all later frames would be empty (because they would be cleared by default).

If you want the triangle to continue being displayed, you'd continue rendering it each frame or store the result of rendering somewhere and restore it each frame.

@cloudhead
Copy link
Contributor Author

cloudhead commented Jul 3, 2019

With zero-initialization you'd only be able to see the triangle in a single frame (i.e. once) – all later frames would be empty (because they would be cleared by default).

If you want the triangle to continue being displayed, you'd continue rendering it each frame or store the result of rendering somewhere and restore it each frame.

Yes, this much is clear, and is how LoadOp::Clear behaves right now too.

I was however under the assumption that LoadOp::Load would behave differently, and preserve the previously drawn image, acting like the vulkan counterpart (link) so that I wouldn't have to copy the framebuffer and redraw it.

@kvark
Copy link
Member

kvark commented Jul 3, 2019

Having the Load of the previous frame (one of the previous frames) doesn't sound quite nice to me. It's slow on mobile GPUs, and the benefit is quite arguable.

@cloudhead
Copy link
Contributor Author

Yeah, I mean I guess it can't work due to double-buffering, but actually works fine when writing to an off-screen texture, which I guess is the intended use-case.

@cwfitzgerald
Copy link
Member

This still causes vulkan validation errors on master. Transferring to wgpu repo.

@cwfitzgerald cwfitzgerald transferred this issue from gfx-rs/wgpu-rs Dec 21, 2020
@cwfitzgerald cwfitzgerald added area: validation Issues related to validation, diagnostics, and error handling good first issue Good for newcomers help required We need community help to make this happen. type: bug Something isn't working labels Dec 21, 2020
@cwfitzgerald
Copy link
Member

VALIDATION [UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (1303270965)] : Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout ] Object 0: handle = 0x16cfab0b1d0, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x4dae5635 | Submit
ted command buffer expects VkImage 0xa540ac0000000009[] (subresource: aspectMask 0x1 array layer 0, mip level 0) to be in layout VK_IMAGE_LAYOUT_PRESENT_SRC_KHR--instead, current layout is VK_IMAGE_LAYOUT_UNDEFINED.
object info: (type: COMMAND_BUFFER, hndl: 1567573979600)

@kvark
Copy link
Member

kvark commented Dec 21, 2020

This would be in "we need to initialize all resources to zero" bin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: validation Issues related to validation, diagnostics, and error handling help required We need community help to make this happen. type: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants