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

[SPIR-V] Copying ConstantBuffer data doesn't actually copy anything. #6952

Closed
ChunkTreasure1 opened this issue Oct 8, 2024 · 4 comments
Closed
Labels
bug Bug, regression, crash spirv Work related to SPIR-V
Milestone

Comments

@ChunkTreasure1
Copy link

Description
I am trying to copy data from a ConstantBuffer fetched from the ResourceDescriptorHeap into another variable, however, the data always becomes zeroed.

I can see the ConstantBuffer in RenderDoc, but when debugging in RenderDoc, the copied values are zero.

Steps to Reproduce
Simple reproduction shader.

https://godbolt.org/z/axzMhz5MT

Actual Behavior
When copying from the ConstantBuffer into the temp variable the data becomes zero.

Environment

  • DXC version: Built from commit b48341e
  • Host Operating System: Windows 11.
@ChunkTreasure1 ChunkTreasure1 added bug Bug, regression, crash needs-triage Awaiting triage spirv Work related to SPIR-V labels Oct 8, 2024
@damyanp damyanp moved this to For Google in HLSL Triage Oct 9, 2024
@s-perron
Copy link
Collaborator

I do not see any problem in the SPIR-V. The copy is removed through copy propagation. The final spir-v is:

         %25 = OpAccessChain %_ptr_StorageBuffer_type_RWStructuredBuffer_uint %ResourceDescriptorHeap %uint_0
         %26 = OpAccessChain %_ptr_Uniform_type_ConstantBuffer_CBData %ResourceDescriptorHeap_0 %uint_1
         %27 = OpAccessChain %_ptr_Uniform_uint %26 %uint_1
         %28 = OpLoad %uint %27
         %29 = OpAccessChain %_ptr_StorageBuffer_uint %25 %int_0 %uint_0
               OpStore %29 %28

SPIR-V can be hard to read. It loads descriptor array ResourceDescriptorHeap_0 at index 1, and then loads the member at index 1, which is data1. That is then store to the first element in storage buffer at ResourceDescritporHeap[0].

I'm not sure how the code should be generated differently. This is the same code that is generated when the two resources are declared separately. See https://godbolt.org/z/TPj7qKn5h. This is also the came code as if the copy is removed: https://godbolt.org/z/rK1b7d6bb.

Note that this features requires VK_EXT_mutable_descriptor_type. Make sure that is enabled an correctly handled by the driver.

If the problem is that RenderDoc shows the value of tempData to be all zeros, even if the output from the shader is correct, that is because you did not generate the debug info. The compiler optimized away tempData so there is nothing for RenderDoc to see. If you want see the value even if it is optimized aways, you can try -fspv-debug=vulkan-with-source, which seem to be failing now (https://godbolt.org/z/fh9Gden6q).

We will be waiting to hear what the specific problem is.

@s-perron s-perron moved this from For Google to Triaged in HLSL Triage Oct 15, 2024
@s-perron s-perron moved this from New to Triaging in HLSL Roadmap Oct 15, 2024
@s-perron s-perron added this to the Backlog milestone Oct 15, 2024
@ChunkTreasure1
Copy link
Author

Hello!

Sorry, I might have been unclear.

When I do this:

struct CBData
{
 uint var;
};

ConstantBuffer<CBData> cb = ResourceDescriptorHeap[0];
RWStructuredBuffer<uint> sb = ResourceDescriptorHeap[1];

sb[0] = cb.var;

And var in the ConstantBuffer is set to for example 5, the output of the StructuredBuffer is 0.

But if I declare the ConstantBuffer as its own binding:

ConstantBuffer<CBData> cb : register(b0, space1);

The output of the StructuredBuffer is correct.

The extension is setup properly, if the SPIR-V looks correct to you, the issue is probably elsewhere, maybe something in the driver.
Thanks for looking it over!

@s-perron
Copy link
Collaborator

s-perron commented Jan 22, 2025

Now I understand the problem better. I still think the SPIR-V looks correct. However, this feature has a big caveat. It allocates two different resource arrays at the same binding, with different types. For this to work, you need to use "mutable descriptors" on the application side.

I'll close for now. Let me know if you come across a more specific problem in the spir-v that I am not seeing.

@github-project-automation github-project-automation bot moved this from Triaging to Done in HLSL Roadmap Jan 22, 2025
@s-perron s-perron removed the needs-triage Awaiting triage label Jan 22, 2025
@s-perron s-perron removed the status in HLSL Roadmap Jan 22, 2025
@Keenuts
Copy link
Collaborator

Keenuts commented Feb 4, 2025

Hello!

The 2 examples you gave are yielding different results:

  • the first one puts cb in the binding=0,descriptor=0, and sb in binging=1,descriptor=0
  • the second creates a single binding 0, and puts cb in DS=1, and sb in DS=0

I tried the following code, and tested in a small VK application and I do get the expected behavior: the CS contains my values, and the SB[0] entry gets written with the value in the CB.
(same result on both my AMD gpu and llvmpipe)

struct CBData
{
  uint value;
};

ConstantBuffer<CBData> cb = ResourceDescriptorHeap[0];
RWStructuredBuffer<uint> sb = ResourceDescriptorHeap[1];

[numthreads(WORKGROUP_SIZE,1,1)]
void main(uint3 threadID : SV_DispatchThreadID)
{
  sb[0] = cb.value;
}
  • Have you correctly marked all the descriptors as mutable etc? (validation layers should catch this).
  • double check your bindings/descriptor layouts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug, regression, crash spirv Work related to SPIR-V
Projects
Status: No status
Status: Triaged
Development

No branches or pull requests

3 participants