Skip to content

Add support for gaps in bind group layouts & update relevant validation#9034

Merged
teoxoy merged 5 commits intogfx-rs:trunkfrom
teoxoy:null-bg-and-bgl
Feb 25, 2026
Merged

Add support for gaps in bind group layouts & update relevant validation#9034
teoxoy merged 5 commits intogfx-rs:trunkfrom
teoxoy:null-bg-and-bgl

Conversation

@teoxoy
Copy link
Member

@teoxoy teoxoy commented Feb 11, 2026

Connections
Fixes #4738.
Fixes #1489.
Fixes #7985.

Notable spec PRs:

Description
Allows pipeline layouts to contain gaps in BGLs.
Updates draw/dispatch bind group validation.
Pipelines with shaders that have gaps in @group attributes will result in derived layouts that have gaps in their BGLs.
Updated .get_bind_group_layout() & .create_pipeline_layout() to be in line with the CTS since the spec is unclear, see:

Testing
Enabled new CTS tests.

Squash or Rebase?
Squash.

@teoxoy
Copy link
Member Author

teoxoy commented Feb 11, 2026

Actually, I should do the wgpu plumbing as well or else it's not correct to say that this PR closes all the issues listed in the description.

@teoxoy
Copy link
Member Author

teoxoy commented Feb 11, 2026

@cwfitzgerald you might want to give the wgpu changes a quick look, I had to add a new trait to be able to still support passing BGLs by reference instead of by optional references.

@cwfitzgerald cwfitzgerald self-assigned this Feb 11, 2026
Copy link
Member

@cwfitzgerald cwfitzgerald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to type something here as I didn't make a review, I made individual comments.

Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up request: assuming that we do change the PipelineLayoutDescriptor's bind_group_layouts to be a slice of Options as Connor and I requested:

This is a big breaking change, so the changelog entry needs to be quite prominent. It should probably just be the top thing on the list, so that people are unlikely to miss it.

@teoxoy teoxoy force-pushed the null-bg-and-bgl branch 2 times, most recently from 6d5f8e3 to 9efbd33 Compare February 16, 2026 12:19
@teoxoy teoxoy requested a review from andyleiserson February 23, 2026 10:49
Copy link
Contributor

@andyleiserson andyleiserson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay, I didn't realize you were still waiting for my review until I got the ping.

self.update_rebind_start_index(index);
}

pub fn clear(&mut self, index: usize) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to update the start index?

In the case of setting and then clearing bind groups in a single pass/dispatch, it doesn't matter, because the bind group doesn't get set until the scope is finalized. But if the bind groups are carrying over from a previous pass/dispatch, do we need to clear it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have to clear bind groups at the wgpu-hal level since validation will ensure that the ones that have been cleared are not used.

I think we could do it for Vulkan (vkCmdBindDescriptorSets can take VK_NULL_HANDLE) and Metal (MTLComputeCommandEncoder's setX methods can take nullable resources) but I don't see a way to do it on D3D12 (ID3D12GraphicsCommandList's Set{Graphics,Compute}RootDescriptorTable & Set{Graphics,Compute}RootConstantBufferView methods don't seem to have nullable parameters).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the fact that we don't clear bound resources is preexisting on Metal and D3D12 since they don't have a 1:1 mapping for bind groups. Resources that have been previously set by a previous bind group at indices higher than ones used by a newly set bind group won't get cleared/overwritten.

I don't think this is an issue though, it would be more work for the driver to clear them and more code for us to maintain. I think relying on (correct) validation is the way to go.

@teoxoy teoxoy force-pushed the null-bg-and-bgl branch 3 times, most recently from 64555c9 to ad64484 Compare February 25, 2026 18:09
@teoxoy teoxoy merged commit e114d2f into gfx-rs:trunk Feb 25, 2026
58 checks passed
@teoxoy teoxoy deleted the null-bg-and-bgl branch February 25, 2026 18:47
@ChristopherBiscardi ChristopherBiscardi mentioned this pull request Mar 9, 2026
1 task
github-merge-queue bot pushed a commit to bevyengine/bevy that referenced this pull request Mar 24, 2026
wgpu update for v29.

I have tested on macos m1, m5, and windows. Linux testing is
appreciated.

- [x] before merge, naga_oil and dlss_wgpu need to be published, and the
patches referencing their respective PRs removed from the workspace
Cargo.toml

##### other PRs

- naga_oil: bevyengine/naga_oil#134
- dlss_wgpu: bevyengine/dlss_wgpu#27

##### Source of relevant changes

- `Dx12Compiler::DynamicDxc` no longer has `max_shader_model`
    - gfx-rs/wgpu#8607
- `Dx12BackendOptions::force_shader_model` comes from:
    - gfx-rs/wgpu#8984
- Allow optional `RawDisplayHandle` in `InstanceDescriptor`
    - gfx-rs/wgpu#8012
- Add `GlDebugFns` option to disable OpenGL debug functions
    - gfx-rs/wgpu#8931
- Add a DX12 backend option to force a certain shader model
    - gfx-rs/wgpu#8984
- Migrate validation from maxInterStageShaderComponents to
maxInterStageShaderVariables
    - gfx-rs/wgpu#8652
- gaps are now supported in bind group layouts
    - gfx-rs/wgpu#9034
- depth validation changed to option to match spec
    - gfx-rs/wgpu#8840
- SHADER_PRIMITIVE_INDEX is now PRIMITIVE_INDEX
  - gfx-rs/wgpu#9101
- Support for binding arrays of RT acceleration structures
  - gfx-rs/wgpu#8923
- Make HasDisplayHandle optional in WindowHandle
  - gfx-rs/wgpu#8782
- `QueueWriteBufferView` can no longer be dereferenced to `&mut [u8]`,
so use `WriteOnly`.
  - gfx-rs/wgpu#9042
- ~bevy_mesh currently has an added dependency on `wgpu`, can we move
`WriteOnly` to wgpu-types?~ (it is in wgpu-types now)
- Change max_*_buffer_binding_size type to match WebGPU spec (u32 ->
u64)
  - gfx-rs/wgpu#9146
- raw vulkan init `open_with_callback` takes Limits as argument now
  - gfx-rs/wgpu#8756

## Known Issues

There is currently one known issue with occlusion culling on macos,
which we've decided to disable on macos by checking the limits we
actually require. This makes it so that if wgpu releases a patch fix,
bevy 0.19 users will benefit from occlusion culling re-enabling for
them.

<details><summary>More details</summary>

On macos, the wpgu limits were changed to align with the spec and now
put the early and late GPU occlusion culling `StorageBuffer` limit at 8,
but we currently use 9. [Filed in wgpu
repo](gfx-rs/wgpu#9287)

```
2026-03-19T01:37:10.771117Z ERROR bevy_render::error_handler: Caught rendering error: Validation Error

Caused by:
  In Device::create_bind_group_layout, label = 'build mesh uniforms GPU late occlusion culling bind group layout'
    Too many bindings of type StorageBuffers in Stage ShaderStages(COMPUTE), limit is 8, count was 9. Check the limit `max_storage_buffers_per_shader_stage` passed to `Adapter::request_device`
```

</details>

solari working on wgpu 29:

<img width="1282" height="752" alt="image"
src="https://github.com/user-attachments/assets/4744faec-65c0-4a72-93e1-34a721fc26d8"
/>

---------

Co-authored-by: atlv <email@atlasdostal.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants