Skip to content
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

Shader translation from SPIR-V fails targeting DX12 #3983

Closed
radgeRayden opened this issue Jul 9, 2023 · 10 comments · Fixed by #3985
Closed

Shader translation from SPIR-V fails targeting DX12 #3983

radgeRayden opened this issue Jul 9, 2023 · 10 comments · Fixed by #3985
Labels
area: validation Issues related to validation, diagnostics, and error handling type: bug Something isn't working

Comments

@radgeRayden
Copy link
Contributor

radgeRayden commented Jul 9, 2023

I have previously filed an issue about this for wgpu-native: gfx-rs/wgpu-native#274
I also have an even smaller trace, it's just a very basic shader that indexes into a Storage Buffer. I've extracted the HLSL output for convenience, but the complete wgpu trace is below.
wgpu-trace.txt

Also the original shader (in SPIR-V form):
shader.zip

@teoxoy
Copy link
Member

teoxoy commented Jul 25, 2023

CreateGraphicsPipelineState is returning E_INVALIDARG which doesn't tell us much.

Could you post the trace of a debug build? We should get more info that way since the D3D12 debug layers are only enabled if cfg!(debug_assertions).

@radgeRayden
Copy link
Contributor Author

radgeRayden commented Jul 26, 2023

CreateGraphicsPipelineState is returning E_INVALIDARG which doesn't tell us much.

Could you post the trace of a debug build? We should get more info that way since the D3D12 debug layers are only enabled if cfg!(debug_assertions).

wgpu-trace.txt

(edited with non cutoff log)

@teoxoy
Copy link
Member

teoxoy commented Jul 26, 2023

From the log, these are the expected bindings for the Vertex shader:

var GlobalVariable { name: Some("input-data"), space: Storage { access: LOAD | STORE }, binding: Some(ResourceBinding { group: 0, binding: 1 }), ty: [6], init: None }
var GlobalVariable { name: Some("uniforms"), space: Uniform, binding: Some(ResourceBinding { group: 0, binding: 0 }), ty: [13], init: None }

What are the bindings you are passing to wgpu?

@radgeRayden
Copy link
Contributor Author

radgeRayden commented Jul 26, 2023

From the log, these are the expected bindings for the Vertex shader:

var GlobalVariable { name: Some("input-data"), space: Storage { access: LOAD | STORE }, binding: Some(ResourceBinding { group: 0, binding: 1 }), ty: [6], init: None }
var GlobalVariable { name: Some("uniforms"), space: Uniform, binding: Some(ResourceBinding { group: 0, binding: 0 }), ty: [13], init: None }

What are the bindings you are passing to wgpu?

Uniform Buffer at 0 and Storage Buffer at 1. Like I mentioned (in the other issue), my code works as expected on Vulkan.

@teoxoy
Copy link
Member

teoxoy commented Jul 26, 2023

For the storage buffer, is it a BufferBindingType::Storage { read_only: true } (i.e. is it read only on the API side)?

@radgeRayden
Copy link
Contributor Author

Currently I am using auto layouts, so it seems like I don't get to set that. The Buffer usage is wgpu.BufferUsage.Storage | wgpu.BufferUsage.CopyDst | wgpu.BufferUsage.CopySrc.

@teoxoy teoxoy transferred this issue from gfx-rs/naga Jul 27, 2023
@teoxoy
Copy link
Member

teoxoy commented Jul 27, 2023

What is happening here is that we derive the layout via how the global is used in the shader instead of how it's declared (in the shader).

read_only: !shader_usage.contains(GlobalUse::WRITE),

Relevant Spec Text:

image

This works fine for all other backends but not the dx12 backend as we will use either an SRV or an UAV for the buffer depending if it's read-only or not.

Bt::Buffer {
ty: wgt::BufferBindingType::Storage { read_only: true },
..
}
| Bt::Texture { .. } => d3d12::DescriptorRangeType::SRV,
Bt::Buffer {
ty: wgt::BufferBindingType::Storage { read_only: false },
..
}
| Bt::StorageTexture { .. } => d3d12::DescriptorRangeType::UAV,

Conclusion

  • You should add the NonWritable SPIR-V decoration to the storage buffer as the vertex stage only supports read-only storage buffers (without the VERTEX_WRITABLE_STORAGE wgpu feature enabled), which will in turn avoid the underlying issues and get things running.
  • We need to infer the binding type based on how it's declared in the shader instead of how it's used.

@teoxoy teoxoy added this to the WebGPU Specification V1 milestone Jul 27, 2023
@teoxoy teoxoy added type: bug Something isn't working area: validation Issues related to validation, diagnostics, and error handling labels Jul 27, 2023
@radgeRayden
Copy link
Contributor Author

Unfortunately after adding the NonWritable decoration to the buffer, I still get the same error. Maybe our generator is wrong, I can't tell yet (not an SPIR-V expert). Here's the shader disassembly followed by the trace.
wgpu-trace.txt

@teoxoy
Copy link
Member

teoxoy commented Jul 28, 2023

I see that the NonWritable decoration got added to the members of VertexAttributes and VertexAttributesBuffer. While that is allowed by the SPIR-V spec, naga will only take into account NonWritable decorations on the variable input-data itself.

For reference:

image

from https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Decoration

@radgeRayden
Copy link
Contributor Author

Thank you, I made the change you suggested and it worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: validation Issues related to validation, diagnostics, and error handling type: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants