microsoft / DirectXShaderCompiler

This repo hosts the source for the DirectX Shader Compiler which is based on LLVM/Clang.
Other
3.09k stars 688 forks source link

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

Open ChunkTreasure1 opened 3 weeks ago

ChunkTreasure1 commented 3 weeks ago

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

s-perron commented 3 weeks ago

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.

ChunkTreasure1 commented 3 weeks ago

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!