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?
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()]);
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.
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?
With zero-initialization you'd only be able to see the triangle in a single frame (i.e. once) 鈥撀燼ll 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.
With zero-initialization you'd only be able to see the triangle in a single frame (i.e. once) 鈥撀燼ll 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.
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.
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.
This still causes vulkan validation errors on master. Transferring to wgpu repo.
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)
This would be in "we need to initialize all resources to zero" bin.
Most helpful comment
This would be in "we need to initialize all resources to zero" bin.