DirectXShaderCompiler
                                
                                 DirectXShaderCompiler copied to clipboard
                                
                                    DirectXShaderCompiler copied to clipboard
                            
                            
                            
                        [SPIR-V] vk::RawBufferStore fails to store fields of a struct at correct offsets
I noticed this issue today with the current implementation of vk::RawBufferStore.
Given this code:
struct PushConsts {
  uint64_t addr;
};
[[vk::push_constant]] PushConsts pushConsts;
struct MyStruct{
    uint32_t a;
    uint32_t b;
    uint32_t c;
};
[shader("compute")]
[numthreads(1, 1, 1)]
void test( uint3 DTid : SV_DispatchThreadID )
{
  MyStruct mystruct;
  mystruct.a = 1;
  mystruct.b = 2;
  mystruct.c = 3;
  vk::RawBufferStore<MyStruct >(
    pushConsts.addr + sizeof(MyStruct) * DTid.x,
    mystruct
  );
}
The resulting data in the buffer becomes
{
  a = 3;
  b = 0;
  c = 0;
}
So, vk::RawBufferStore doesn't seem to consider offsets when storing fields of a structure, and any struct field just ends up at the beginning of the struct.
Interestingly, if I replace a, b, and c with a single int3, then I do not see this issue.
As a temporary work around, I can add the offsets manually to the address parameter of vk::RawBufferStore, and then store each field individually. But I figured I'd write down this issue now so that we can get the ball rolling on a more permanent solution.
@natevm At the moment, loading structure data is not supported. See #4289
@BeastLe9enD
Sure, but the issue there is different. The issue there assumes we’re using a sophisticated memory layout for the struct. In most all applications I’m aware of, this isn’t the case.
We currently support loading normal structs of data by simply copying over sizeof(struct) contiguous bytes of data.
We should be able to support that same behavior with vk::RawBufferStore
Investigating further, this is an odd issue, and I'm wondering if it might perhaps be a driver bug rather than a compiler bug?
In intrinsics.vkrawbuufferstore.hlsl, we have the following test, which passes:
// CHECK:      [[addr:%\d+]] = OpLoad %ulong
 // CHECK-NEXT: [[xyzwval:%\d+]] = OpLoad %XYZW %xyzw
 // CHECK-NEXT: [[buf:%\d+]] = OpBitcast %_ptr_PhysicalStorageBuffer_XYZW [[addr]]
 // CHECK-NEXT: OpStore [[buf]] [[xyzwval]] Aligned 4
 XYZW xyzw;
 xyzw.x = 78;
 xyzw.y = 65;
 xyzw.z = 84;
 xyzw.w = 69;
 vk::RawBufferStore<XYZW>(Address, xyzw);
However, when I use the above code in a shader, the output is this when I download that value back on the host:
  xyzw.x = 69;
  xyzw.y = 0;
  xyzw.z = 0;
  xyzw.w = 0;
@Erfan-Ahmadi is your struct loading problem this but for a load instead of store?
@Erfan-Ahmadi is your struct loading problem this but for a load instead of store?
Yea @devshgraphicsprogramming ! Every field loads the first member.
I’ve discovered this seems to be some sort of driver bug on NVIDIA. On my Intel ARC card, everything works correctly, with the same SPIR-V.
@Erfan-Ahmadi do you have some code I could run on my Intel ARC card to see if your load works there?
I’ve discovered this seems to be some sort of driver bug on NVIDIA. On my Intel ARC card, everything works correctly, with the same SPIR-V.
@Erfan-Ahmadi do you have some code I could run on my Intel ARC card to see if your load works there?
Hey, I'm having the issue on Nvidia as well. I can give you an exe file to run
I’ve discovered this seems to be some sort of driver bug on NVIDIA. On my Intel ARC card, everything works correctly, with the same SPIR-V. @Erfan-Ahmadi do you have some code I could run on my Intel ARC card to see if your load works there?
Hey, I'm having the issue on Nvidia as well. I can give you an exe file to run
Just shot yea an email
Can confirm I'm experiencing this issue as well, also on Nvidia.
Haven’t had the chance, but since this seems to be an NVIDIA driver bug, we might want to submit a bug report to their developer forms. NVIDIA devs seem to be pretty active over there.
Thanks for the updates. Closing as it sounds like this is not a compiler bug.
I'll see if i can push NVIDIA to get this fixed in their driver.
btw this code snippet breaks in a new and fascinating way https://godbolt.org/z/ra9WeKM1a
fatal error: generated SPIR-V is invalid: Structure id 8 decorated as Block for variable in PhysicalStorageBuffer storage class must follow scalar storage buffer layout rules: member 0 is missing an Offset decoration
  %MyStruct = OpTypeStruct %uint %uint %uint
note: please file a bug report on https://github.com/Microsoft/DirectXShaderCompiler/issues with source code if possible