DirectXShaderCompiler icon indicating copy to clipboard operation
DirectXShaderCompiler copied to clipboard

[SPIR-V] vk::RawBufferStore fails to store fields of a struct at correct offsets

Open natevm opened this issue 3 years ago • 2 comments

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 avatar Aug 26 '22 19:08 natevm

@natevm At the moment, loading structure data is not supported. See #4289

BeastLe9enD avatar Sep 08 '22 20:09 BeastLe9enD

@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

natevm avatar Sep 08 '22 20:09 natevm

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;

natevm avatar Dec 25 '22 20:12 natevm

@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.

Erfan-Ahmadi avatar Feb 01 '23 01:02 Erfan-Ahmadi

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?

natevm avatar Feb 01 '23 01:02 natevm

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

Erfan-Ahmadi avatar Feb 01 '23 04:02 Erfan-Ahmadi

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

natevm avatar Feb 01 '23 04:02 natevm

Can confirm I'm experiencing this issue as well, also on Nvidia.

ashpil avatar Feb 27 '23 20:02 ashpil

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.

natevm avatar Feb 27 '23 20:02 natevm

Thanks for the updates. Closing as it sounds like this is not a compiler bug.

sudonatalie avatar Aug 09 '23 20:08 sudonatalie

I'll see if i can push NVIDIA to get this fixed in their driver.

natevm avatar Aug 10 '23 00:08 natevm

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