WebGPU: Allow read_write storage buffers and atomic ops in non-compute stages#33626
Open
SebastianBaltes wants to merge 2 commits into
Open
WebGPU: Allow read_write storage buffers and atomic ops in non-compute stages#33626SebastianBaltes wants to merge 2 commits into
SebastianBaltes wants to merge 2 commits into
Conversation
…e stages The WebGPU spec explicitly allows GPUBufferBindingType.Storage (read_write) in vertex and fragment shader stages. However, two places in three.js currently restrict storage buffer write access and atomic operations to compute shaders only: 1. WGSLNodeBuilder.getNodeAccess() logs a warning claiming atomic ops are "only supported in compute shaders" — this is incorrect per the spec. The code already returns the correct READ_WRITE access; only the misleading warning is removed. 2. WebGPUBindingUtils creates the GPU binding layout based on shader stage visibility rather than the node's declared access. Non-compute stages always received ReadOnlyStorage, even when READ_WRITE was requested. The fix uses the node's access property directly, matching the logic already used for compute stages. This enables use cases such as deferred rendering pipelines that use atomicOr() in fragment shaders to collect per-pixel data into storage buffers — a pattern that is valid per the WebGPU specification. Related: mrdoob#31478 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
…e stages The previous change was too broad — it set GPUBufferBindingType.Storage for all READ_WRITE storage buffers regardless of shader stage. This caused GPUValidationError in compute+render examples because the WGSL code uses var<storage, read> in non-compute stages, which requires ReadOnlyStorage in the binding layout. The fix keeps the GPUShaderStage.COMPUTE check for the general case and adds a targeted condition for atomic buffers: when binding.nodeUniform is atomic, the fragment shader uses var<storage, read_write> and needs GPUBufferBindingType.Storage in the layout to match. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Did you test it in the vertex shader? https://www.w3.org/TR/WGSL/#atomic-builtin-functions
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Related issue: #31478
Description
The WebGPU specification explicitly allows
GPUBufferBindingType.Storage(read_write) in vertex and fragment shader stages — not only in compute. However, two places in three.js currently restrict storage buffer write access and atomic operations to compute shaders only.Changes
1.
WGSLNodeBuilder.getNodeAccess()— Remove incorrect warningThe method already returns
NodeAccess.READ_WRITEfor atomic nodes in non-compute stages, which is the correct behavior. But it also logs:This warning is misleading — atomic operations on storage buffers are valid in all shader stages per the WebGPU spec (§ Buffer Binding Types). The warning is removed; the logic is unchanged.
2.
WebGPUBindingUtils— Use node access instead of stage visibility for buffer binding typePreviously, the GPU binding layout was chosen based on
GPUShaderStage.COMPUTEvisibility:binding.access(Storage vs ReadOnlyStorage)ReadOnlyStorageThis prevented vertex/fragment shaders from getting
GPUBufferBindingType.Storageeven whenREAD_WRITEaccess was explicitly requested. The fix usesbinding.accessdirectly regardless of stage — the same logic that was already used for the compute path.Use case
This enables patterns such as deferred rendering pipelines where fragment shaders use
atomicOr()to collect per-pixel bitmasks into storage buffers. Without this fix, any use of atomic operations or read_write storage buffers outside compute shaders is silently broken at the binding level.Spec reference
"storage"is allowed for vertex and fragment stagestype: "storage"