-
Notifications
You must be signed in to change notification settings - Fork 920
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
Robust Buffer Access conflicts with lazy initialization #1813
Comments
On Metal, Firefox always uses On Vulkan, the spec says:
Since that refers to "the bound range", not the buffer, and wgpu-core does initialize the bound range, I think it's impossible for shaders to see uninitialized buffer contents on Vulkan as well. I believe "the bound range" is what's established via the On D3D12, we don't implement any bounds checks at all, I believe because the platform promises WebGPU-compatible behavior itself. So I think this is not a bug. |
In the Vulkan spec:
|
So, if RBA2 is supported, we need to respect those access alignments for the purpose of range initialization. |
@kvark That seems to contradict the language in the description of I wonder why they didn't update that, especially with the mentions of |
Ahh, later the Vulkan spec says:
So Vulkan agrees with WebGPU on what is considered "out of bounds", but doesn't meet its requirements for how loads of such references should behave. |
@kvark You said:
Why would it be limited to storage buffers? Doesn't this mean that pretty much any buffer access could read uninitialized content from elsewhere in the buffer? It looks to me like this makes lazy initialization difficult to keep. |
Part of the rationale here is that it's assumed that, even if the platform's bounds-checking tools have some kind of required alignment, up to 256, for the enforcement, we can just round up [edit]
If we round up buffer sizes to these amounts, and then round up lazy initialization regions to these amounts, that should suffice to meet the spec's requirements. I think we want to handle this as follows:
|
Testing this is a problem. By definition, a test needs to be able to detect whether the change to the lazy initialization code is present or absent. That's tricky here, for a few reasons:
One approach to the second problem might be to add a I'm not sure how to get around the first problem. It doesn't help that Direct3D 12 lacks any way to fill buffers, short of dispatching a compute shader to write to them. |
Because every approach I can think of to test this is very involved, and this issue has been on our P0 list for a very long time, I'd like to land a fix without additional tests. |
One detail that's worth bringing up is that storage buffer bindings shouldn't be enlarged because they can contain runtime-sized arrays. The WebGPU spec does say this:
I think we should be fine here since the buffer binding size is already guaranteed to be a multiple of 4. Now for uniform buffers: The WebGPU spec only requires:
Given that uniform buffers can't contain runtime-sized arrays we can enlarge bindings EDIT: crossed sections that don't apply. The |
Okay, yes. To restate: the most lenient Vulkan
Then, Vulkan says, in describing
So |
Yes - we shouldn't actually change binding sizes. Rather, |
Ignore this comment #1813 (comment), I misunderstood what the spec was saying. The plan in #1813 (comment) makes sense to me now 👍 |
In `wgpu_hal`: - Document that `wgpu_hal` guarantees that shaders will not access buffer contents beyond the bindgroups' bound regions, rounded up to some adapter-specific alignment. Introduce the term "accessible region" for the portion of the buffer that shaders can actually get at. - Document that all bets are off if you disable bounds checks with `ShaderModuleDescriptor::runtime_checks`. - Provide this alignment in `wgpu_hal::Alignments`. Update all backends appropriately. - In the Vulkan backend, use Naga to inject bounds checks on buffer accesses unless `robustBufferAccess2` is available; `robustBufferAccess` is not sufficient. Retrieve `VK_EXT_robustness2`'s properties, as needed to discover the alignment above. In `wgpu_core`: - Use buffer bindings' accessible regions to determine which parts of the buffer need to be initialized. In `wgpu_types`: - Document some of the possible effects of using `ShaderBoundsChecks::unchecked`. Fixes gfx-rs#1813.
In `wgpu_hal`: - Document that `wgpu_hal` guarantees that shaders will not access buffer contents beyond the bindgroups' bound regions, rounded up to some adapter-specific alignment. Introduce the term "accessible region" for the portion of the buffer that shaders can actually get at. - Document that all bets are off if you disable bounds checks with `ShaderModuleDescriptor::runtime_checks`. - Provide this alignment in `wgpu_hal::Alignments`. Update all backends appropriately. - In the Vulkan backend, use Naga to inject bounds checks on buffer accesses unless `robustBufferAccess2` is available; `robustBufferAccess` is not sufficient. Retrieve `VK_EXT_robustness2`'s properties, as needed to discover the alignment above. In `wgpu_core`: - Use buffer bindings' accessible regions to determine which parts of the buffer need to be initialized. In `wgpu_types`: - Document some of the possible effects of using `ShaderBoundsChecks::unchecked`. Fixes gfx-rs#1813.
In `wgpu_hal`: - Document that `wgpu_hal` guarantees that shaders will not access buffer contents beyond the bindgroups' bound regions, rounded up to some adapter-specific alignment. Introduce the term "accessible region" for the portion of the buffer that shaders can actually get at. - Document that all bets are off if you disable bounds checks with `ShaderModuleDescriptor::runtime_checks`. - Provide this alignment in `wgpu_hal::Alignments`. Update all backends appropriately. - In the Vulkan backend, use Naga to inject bounds checks on buffer accesses unless `robustBufferAccess2` is available; `robustBufferAccess` is not sufficient. Retrieve `VK_EXT_robustness2`'s properties, as needed to discover the alignment above. In `wgpu_core`: - Use buffer bindings' accessible regions to determine which parts of the buffer need to be initialized. In `wgpu_types`: - Document some of the possible effects of using `ShaderBoundsChecks::unchecked`. Fixes gfx-rs#1813.
In `wgpu_hal`: - Document that `wgpu_hal` guarantees that shaders will not access buffer contents beyond the bindgroups' bound regions, rounded up to some adapter-specific alignment. Introduce the term "accessible region" for the portion of the buffer that shaders can actually get at. - Document that all bets are off if you disable bounds checks with `ShaderModuleDescriptor::runtime_checks`. - Provide this alignment in `wgpu_hal::Alignments`. Update all backends appropriately. - In the Vulkan backend, use Naga to inject bounds checks on buffer accesses unless `robustBufferAccess2` is available; `robustBufferAccess` is not sufficient. Retrieve `VK_EXT_robustness2`'s properties, as needed to discover the alignment above. In `wgpu_core`: - Use buffer bindings' accessible regions to determine which parts of the buffer need to be initialized. In `wgpu_types`: - Document some of the possible effects of using `ShaderBoundsChecks::unchecked`. Fixes gfx-rs#1813.
In `wgpu_hal`: - Document that `wgpu_hal` guarantees that shaders will not access buffer contents beyond the bindgroups' bound regions, rounded up to some adapter-specific alignment. Introduce the term "accessible region" for the portion of the buffer that shaders can actually get at. - Document that all bets are off if you disable bounds checks with `ShaderModuleDescriptor::runtime_checks`. - Provide this alignment in `wgpu_hal::Alignments`. Update all backends appropriately. - In the Vulkan backend, use Naga to inject bounds checks on buffer accesses unless `robustBufferAccess2` is available; `robustBufferAccess` is not sufficient. Retrieve `VK_EXT_robustness2`'s properties, as needed to discover the alignment above. In `wgpu_core`: - Use buffer bindings' accessible regions to determine which parts of the buffer need to be initialized. In `wgpu_types`: - Document some of the possible effects of using `ShaderBoundsChecks::unchecked`. Fixes #1813.
WebGPU allows for RBA behavior on out-of-bound accesses into buffers. This behavior says that 0, 1, or any value from the underlying buffer (not binding!) can be returned or written.
However, if the buffer ranges are lazily initialized to zero, we can end up in a situation where shader reads values outside of the initialized range. This is not acceptable.
A quick solution would be to consider any storage buffer bindings to cover the whole buffer for the purpose of lazy initialization. cc @Wumpf
Note also that the extent of the problem depends on the bounds checking policy:
wgpu/wgpu-hal/src/vulkan/adapter.rs
Line 843 in 3afab9c
ReadZeroSkipWrite
then we can keep doing what we do today. cc @jimblandyThe text was updated successfully, but these errors were encountered: