Wgpu-rs: Weird flickering when using indirect indexed draws

Created on 21 May 2020  Â·  4Comments  Â·  Source: gfx-rs/wgpu-rs

I have a strange issue when amount of instances to draw changes incorrect models are being drawn instead of correct ones, but just for one frame.

I'm re-creating vertex buffer with instances on each render and rebinding with the new bind group. I'm sure that both instances and indirect command buffers are correct. There is no validation layer errors present.

More over, I have trouble debugging this with RenderDoc, since it sees no issue. On the capture preview screenshot bug is clearly represented, but swap chain image contains correct image (that I've never seen in the application itself).

This RenderDoc behavior and the fact that this "bug" magically disappears on the next frame makes me suspect that it is an issue with wgpu , since from code execution perspective nothing has really changed.


Old state

```
&self.indirect_commands = [
IndirectCommand {
index_count: 252,
instance_count: 1,
first_index: 0,
vertex_offset: 0,
first_instance: 0,
},
IndirectCommand {
index_count: 84,
instance_count: 1,
first_index: 252,
vertex_offset: 148,
first_instance: 1,
},
]
&self.instances = [
InstanceDescriptor {
transform: Matrix {
data: [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 11.0, 0.0, 0.0, 1.0],
},
color_offset: Matrix {
data: [0.0, 0.0, 0.0, 0.0],
},
},
InstanceDescriptor {
transform: Matrix {
data: [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 12.0, 0.002, 10.0, 1.0],
},
color_offset: Matrix {
data: [0.0, 0.0, 0.0, 0.0],
},
},
]


</details>

<details>
  <summary>New state</summary>

 ```
&indirect_commands = [
    IndirectCommand {
        index_count: 252,
        instance_count: 1,
        first_index: 0,
        vertex_offset: 0,
        first_instance: 0,
    },
    IndirectCommand {
        index_count: 84,
        instance_count: 0,
        first_index: 252,
        vertex_offset: 148,
        first_instance: 1,
    },
]
&instances = [
    InstanceDescriptor {
        transform: Matrix {
            data: [1.0, 0.0, 0.0, 0.0,  0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 11.0, 0.0, 0.0, 1.0],
        },
        color_offset: Matrix {
            data: [0.0,  0.0, 0.0,  0.0],
        },
    },
]



RD capture preview

2020-05-21-023828_1920x1062_scrot



RD swap chain image

2020-05-21-023844_1920x1062_scrot

bug

All 4 comments

Thank you for filing!
Here is what we can do to solve this:

  1. provide more information about your platform, i.e. Adapter::get_info() output, as well as the version of wgpu-rs that you are using
  2. provide a way for us to reproduce this
  3. if using wgpu-rs from crates.io, try testing after doing cargo update -p wgpu-core. We just published a cumulative patch for the released version.
  4. if using wgpu-rs from master, please provide a wgpu API trace. This is done by enabling the "trace" feature and passing a path to an existing folder to request_device. See also - our wiki entry.
  5. please provide the renderdoc captures (from good & bad frames).

One possible explanation is that there is a problem with our transition barriers, and it's not caught by the validation layers.

Thanks for a quick reply!

  1. Here is adapter.get_info() and platform information - Linux, X11
&adapter.get_info() = AdapterInfo {
    name: "GeForce GTX 1080",
    vendor: 4318,
    device: 7040,
    device_type: DiscreteGpu,
    backend: Vulkan,
}
  1. Updated, issue is still there
  2. Updated to master and issue persists. I've made a trace.zip. First frames are empty and it is ok because I had to drop wgpu_glyph dependency to update wgputo latest master and there is no more text there.
  3. RD captures. Unfortunately, it seems there is no way to see the screenshot RD takes at capture time, where issue is visible. Nothing in particular inside this captures looks wrong to me (except my SSAO implementation ☺, but it is unrelated to this issue)
    bad-capture.zip
    good-capture.zip

Couple side notes:

  • Adapter::get_info is stubbed on master, not sure, if it is intentional or not.
  • BufferSlice does spark joy. Hope to see it in the other places like CommandEncoder::copy_buffer_to_buffer.
  • I was not able to use player to replay my own trace. For some reason it tries to create window with (800, 600) size although swap chain descriptor in the trace clearly has size of (1920, 1080). I didn't investigate further.

It does indeed fail to play from player, unfortunately, and that's something we need to fix in the player.
Looking at your RenderDoc captures, however, I see something off:

sType                    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER           
pNext                    NULL                                              
srcAccessMask            VK_ACCESS_TRANSFER_WRITE_BIT                      
dstAccessMask            VkAccessFlagBits(0)                               
srcQueueFamilyIndex      -1                                                
dstQueueFamilyIndex      -1                                                
buffer                   ResourceId::692                                   
offset                   0                                                 
size                     UINT64_MAX                                        
[0]                      VkBufferMemoryBarrier()                           
commandBuffer            ResourceId::136                                   
srcStageMask             VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_HOST_BIT
destStageMask            VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_HOST_BIT
dependencyFlags          VkDependencyFlagBits(0)                           
memoryBarrierCount       0                                                 
pMemoryBarriers          VkMemoryBarrier[]                                 
bufferMemoryBarrierCount 1                                                 
pBufferMemoryBarriers    VkBufferMemoryBarrier[]                           
imageMemoryBarrierCount  0                                                 
pImageMemoryBarriers     VkImageMemoryBarrier[]                            
16                       vkCmdPipelineBarrier

This is the transition barrier for the indirect buffer right before the pass doing indirect calls. The suspicious bit here is the empty dstAccessMask. This needs to be VK_ACCESS_INDIRECT_COMMAND_READ_BIT. I guess the validation layers are missing a check for this :/

Seems to be working now. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JonathanWoollett-Light picture JonathanWoollett-Light  Â·  4Comments

rukai picture rukai  Â·  5Comments

inguar picture inguar  Â·  5Comments

dmilford picture dmilford  Â·  3Comments

sagacity picture sagacity  Â·  3Comments