-
Notifications
You must be signed in to change notification settings - Fork 165
Open
Description
The following HLSL (compiled with DXC's flags for dx buffer layouts) produces incorrect spirv-reflect behavior:
struct Nicu {
float a, b;
uint64_t c;
uint16_t d;
float16_t e;
int16_t f;
};
RWStructuredBuffer<Nicu> _sbuffer0;
[[oxc::stage("compute")]]
[[oxc::extension("16BitTypes", "I64")]]
[numthreads(1, 1, 1)]
void main(uint id : SV_DispatchThreadID) {
_sbuffer0[id].a = 123;
}Turns into:
; SPIR-V
; Version: 1.5
; Generator: Google spiregg; 0
; Bound: 26
; Schema: 0
OpCapability Shader ; 0x00000014
OpCapability Int64 ; 0x0000001c
OpCapability Int16 ; 0x00000024
OpCapability Float16 ; 0x0000002c
OpMemoryModel Logical GLSL450 ; 0x00000034
OpEntryPoint GLCompute %1 "main" %gl_GlobalInvocationID %3 ; 0x00000040
OpExecutionMode %1 LocalSize 1 1 1 ; 0x0000005c
; Annotations
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId ; 0x00000074
OpDecorate %3 DescriptorSet 0 ; 0x00000084
OpDecorate %3 Binding 0 ; 0x00000094
OpMemberDecorate %_struct_5 0 Offset 0 ; 0x000000a4
OpMemberDecorate %_struct_5 1 Offset 4 ; 0x000000b8
OpMemberDecorate %_struct_5 2 Offset 8 ; 0x000000cc
OpMemberDecorate %_struct_5 3 Offset 16 ; 0x000000e0
OpMemberDecorate %_struct_5 4 Offset 18 ; 0x000000f4
OpMemberDecorate %_struct_5 5 Offset 20 ; 0x00000108
OpDecorate %_runtimearr__struct_5 ArrayStride 24 ; 0x0000011c
OpMemberDecorate %_struct_4 0 Offset 0 ; 0x0000012c
OpDecorate %_struct_4 Block ; 0x00000140
; Types, variables and constants
%float = OpTypeFloat 32 ; 0x0000014c
%float_123 = OpConstant %float 123 ; 0x00000158
%int = OpTypeInt 32 1 ; 0x00000168
%int_0 = OpConstant %int 0 ; 0x00000178
%ulong = OpTypeInt 64 0 ; 0x00000188
%ushort = OpTypeInt 16 0 ; 0x00000198
%half = OpTypeFloat 16 ; 0x000001a8
%short = OpTypeInt 16 1 ; 0x000001b4
%_struct_5 = OpTypeStruct %float %float %ulong %ushort %half %short ; 0x000001c4
%_runtimearr__struct_5 = OpTypeRuntimeArray %_struct_5 ; 0x000001e4, ArrayStride 24
%_struct_4 = OpTypeStruct %_runtimearr__struct_5 ; 0x000001f0, Block
%_ptr_StorageBuffer__struct_4 = OpTypePointer StorageBuffer %_struct_4 ; 0x000001fc
%uint = OpTypeInt 32 0 ; 0x0000020c
%v3uint = OpTypeVector %uint 3 ; 0x0000021c
%_ptr_Input_v3uint = OpTypePointer Input %v3uint ; 0x0000022c
%void = OpTypeVoid ; 0x0000023c
%20 = OpTypeFunction %void ; 0x00000244
%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float ; 0x00000250
%3 = OpVariable %_ptr_StorageBuffer__struct_4 StorageBuffer ; 0x00000260, DescriptorSet 0, Binding 0
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input ; 0x00000270, BuiltIn GlobalInvocationId
; Function 1
%1 = OpFunction %void None %20 ; 0x00000280
%22 = OpLabel ; 0x00000294
%23 = OpLoad %v3uint %gl_GlobalInvocationID ; 0x0000029c
%24 = OpCompositeExtract %uint %23 0 ; 0x000002ac
%25 = OpAccessChain %_ptr_StorageBuffer_float %3 %int_0 %24 %int_0 ; 0x000002c0
OpStore %25 %float_123 ; 0x000002dc
OpReturn ; 0x000002e8
OpFunctionEnd ; 0x000002ec
As the U32 at offset 0x0000011c says; the stride of _runtimearr__struct_5 is 24. However, when running this with spirv-reflect it will gaslight me that binding->block.members[0]->padded_size == 22:
SH Binary (compute): main
[[oxc::model(6.5)]]
[[oxc::extension( "I64" , "16BitTypes" )]]
[[oxc::uniforms()]
[[oxc::vendor()]] //(any vendor)
Binaries:
SPV: 752
Registers:
_sbuffer0 (SPV: Used)
RWStructuredBuffer
[[vk::binding(0, 0)]]
0x00000000: $Element (SPIRV: Used): Nicu (Stride: 22)
0x00000000: a (SPIRV & DXIL: Unused): F32
0x00000004: b (SPIRV & DXIL: Unused): F32
0x00000008: c (SPIRV & DXIL: Unused): U64
0x00000010: d (SPIRV & DXIL: Unused): U16
0x00000012: e (SPIRV & DXIL: Unused): F16
0x00000014: f (SPIRV & DXIL: Unused): I16
That doesn't match expected behavior and is likely because 22 = 0x14 + sizeof(I16) = 0x16. My best guess is it calculates the struct size rather than reflects it. If it does calculate it, then it should calculate it by taking the largest member (U64) and align the struct size to it. Doing that manually seems very confusing.
Metadata
Metadata
Assignees
Labels
No labels