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

SPIRV NonUniformResourceIndex - NonUniform Decoration missing for the array index variable #6010

Closed
andreasschultes opened this issue Jan 6, 2025 · 2 comments · Fixed by #6028
Assignees
Labels
goal:quality & productivity Quality issues and issues that impact our productivity coding day to day inside slang kind:bug something doesn't work like it should

Comments

@andreasschultes
Copy link

The output of the array access get currentlly the nonUniform decoration instead of the input index.
I attached two version of the fragment shader. The first version produces an invalid shader output because some drivers assumes that the index is uniform. The second shader variant works as expected.

Fragment shader

struct UTileBuffer {
    // int4 address;
    int3 stepX;
    int startX;
    int3 stepY;
    int startY;
    float scaleZ;
    int z;
    int pad0;
    int pad1;
    // float scaleXZ;
    uint lodDelta[4];
    int childNodeIndices[32];
    int heightmapIndices[32];
    int materialIndices[32];
};

struct VOut {
    float4 position : SV_POSITION;
    float3 worldPos;
    float2 texCoord;
    float4 debugColor;
}

[[vk_binding(1, 0)]]
StructuredBuffer<UTileBuffer, Std430DataLayout> tiles;
[[vk_binding(3, 0)]]
SamplerState diffuseSampler;
// layout(binding = 2,set = 0) uniform sampler diffuseSampler;

[[vk_binding(4, 0)]]
Texture2D<float4> images[128];

[[shader("fragment")]]
float4 main(VOut arg,uint primitiveID: SV_PrimitiveID) {

    int id = (primitiveID) / (64 * 64 * 2);

    let push = tiles[id]; 
    let index = push.materialIndices[push.z];

    let diffuseColor = images[NonUniformResourceIndex(index)].Sample(diffuseSampler, arg.texCoord);
    return diffuseColor;
}

Fragment spriv-dis

; SPIR-V
; Version: 1.5
; Generator: Khronos; 40
; Bound: 65
; Schema: 0
               OpCapability Geometry
               OpCapability ShaderNonUniform
               OpCapability Shader
               OpExtension "SPV_KHR_storage_buffer_storage_class"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %tiles %images %diffuseSampler %entryPointParam_main %arg_texCoord %gl_PrimitiveID
               OpExecutionMode %main OriginUpperLeft
               OpSource Slang 1
               OpName %id "id"
               OpName %_Array_std430_uint4 "_Array_std430_uint4"
               OpMemberName %_Array_std430_uint4 0 "data"
               OpName %_Array_std430_int32 "_Array_std430_int32"
               OpMemberName %_Array_std430_int32 0 "data"
               OpName %UTileBuffer_std430 "UTileBuffer_std430"
               OpMemberName %UTileBuffer_std430 0 "stepX"
               OpMemberName %UTileBuffer_std430 1 "startX"
               OpMemberName %UTileBuffer_std430 2 "stepY"
               OpMemberName %UTileBuffer_std430 3 "startY"
               OpMemberName %UTileBuffer_std430 4 "scaleZ"
               OpMemberName %UTileBuffer_std430 5 "z"
               OpMemberName %UTileBuffer_std430 6 "pad0"
               OpMemberName %UTileBuffer_std430 7 "pad1"
               OpMemberName %UTileBuffer_std430 8 "lodDelta"
               OpMemberName %UTileBuffer_std430 9 "childNodeIndices"
               OpMemberName %UTileBuffer_std430 10 "heightmapIndices"
               OpMemberName %UTileBuffer_std430 11 "materialIndices"
               OpName %StructuredBuffer "StructuredBuffer"
               OpName %tiles "tiles"
               OpName %images "images"
               OpName %diffuseSampler "diffuseSampler"
               OpName %arg_texCoord "arg.texCoord"
               OpName %sampledImage "sampledImage"
               OpName %sampled "sampled"
               OpName %entryPointParam_main "entryPointParam_main"
               OpName %main "main"
               OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
               OpDecorate %gl_PrimitiveID Flat
               OpDecorate %_arr_uint_int_4 ArrayStride 4
               OpMemberDecorate %_Array_std430_uint4 0 Offset 0
               OpDecorate %_arr_int_int_32 ArrayStride 4
               OpMemberDecorate %_Array_std430_int32 0 Offset 0
               OpMemberDecorate %UTileBuffer_std430 0 Offset 0
               OpMemberDecorate %UTileBuffer_std430 1 Offset 12
               OpMemberDecorate %UTileBuffer_std430 2 Offset 16
               OpMemberDecorate %UTileBuffer_std430 3 Offset 28
               OpMemberDecorate %UTileBuffer_std430 4 Offset 32
               OpMemberDecorate %UTileBuffer_std430 5 Offset 36
               OpMemberDecorate %UTileBuffer_std430 6 Offset 40
               OpMemberDecorate %UTileBuffer_std430 7 Offset 44
               OpMemberDecorate %UTileBuffer_std430 8 Offset 48
               OpMemberDecorate %UTileBuffer_std430 9 Offset 64
               OpMemberDecorate %UTileBuffer_std430 10 Offset 192
               OpMemberDecorate %UTileBuffer_std430 11 Offset 320
               OpDecorate %_runtimearr_UTileBuffer_std430 ArrayStride 448
               OpDecorate %StructuredBuffer Block
               OpMemberDecorate %StructuredBuffer 0 Offset 0
               OpDecorate %tiles Binding 1
               OpDecorate %tiles DescriptorSet 0
               OpDecorate %tiles NonWritable
               OpDecorate %_arr_42_int_128 ArrayStride 8
               OpDecorate %images Binding 4
               OpDecorate %images DescriptorSet 0
               OpDecorate %49 NonUniform
               OpDecorate %diffuseSampler Binding 3
               OpDecorate %diffuseSampler DescriptorSet 0
               OpDecorate %arg_texCoord Location 1
               OpDecorate %entryPointParam_main Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
        %int = OpTypeInt 32 1
%_ptr_Input_int = OpTypePointer Input %int
       %uint = OpTypeInt 32 0
  %uint_8192 = OpConstant %uint 8192
      %int_0 = OpConstant %int 0
      %v3int = OpTypeVector %int 3
      %float = OpTypeFloat 32
      %int_4 = OpConstant %int 4
%_arr_uint_int_4 = OpTypeArray %uint %int_4
%_Array_std430_uint4 = OpTypeStruct %_arr_uint_int_4
     %int_32 = OpConstant %int 32
%_arr_int_int_32 = OpTypeArray %int %int_32
%_Array_std430_int32 = OpTypeStruct %_arr_int_int_32
%UTileBuffer_std430 = OpTypeStruct %v3int %int %v3int %int %float %int %int %int %_Array_std430_uint4 %_Array_std430_int32 %_Array_std430_int32 %_Array_std430_int32
%_ptr_StorageBuffer_UTileBuffer_std430 = OpTypePointer StorageBuffer %UTileBuffer_std430
%_runtimearr_UTileBuffer_std430 = OpTypeRuntimeArray %UTileBuffer_std430
%StructuredBuffer = OpTypeStruct %_runtimearr_UTileBuffer_std430
%_ptr_StorageBuffer_StructuredBuffer = OpTypePointer StorageBuffer %StructuredBuffer
     %int_11 = OpConstant %int 11
%_ptr_StorageBuffer__Array_std430_int32 = OpTypePointer StorageBuffer %_Array_std430_int32
      %int_5 = OpConstant %int 5
%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
%_ptr_StorageBuffer__arr_int_int_32 = OpTypePointer StorageBuffer %_arr_int_int_32
         %42 = OpTypeImage %float 2D 2 0 0 1 Unknown
    %int_128 = OpConstant %int 128
%_arr_42_int_128 = OpTypeArray %42 %int_128
%_ptr_UniformConstant__arr_42_int_128 = OpTypePointer UniformConstant %_arr_42_int_128
%_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
         %50 = OpTypeSampler
%_ptr_UniformConstant_50 = OpTypePointer UniformConstant %50
    %v2float = OpTypeVector %float 2
%_ptr_Input_v2float = OpTypePointer Input %v2float
         %58 = OpTypeSampledImage %42
    %v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%gl_PrimitiveID = OpVariable %_ptr_Input_int Input
      %tiles = OpVariable %_ptr_StorageBuffer_StructuredBuffer StorageBuffer
     %images = OpVariable %_ptr_UniformConstant__arr_42_int_128 UniformConstant
%diffuseSampler = OpVariable %_ptr_UniformConstant_50 UniformConstant
%arg_texCoord = OpVariable %_ptr_Input_v2float Input
%entryPointParam_main = OpVariable %_ptr_Output_v4float Output
       %main = OpFunction %void None %3
          %4 = OpLabel
          %6 = OpLoad %int %gl_PrimitiveID
         %10 = OpBitcast %uint %6
         %11 = OpUDiv %uint %10 %uint_8192
         %id = OpBitcast %int %11
         %25 = OpAccessChain %_ptr_StorageBuffer_UTileBuffer_std430 %tiles %int_0 %id
         %32 = OpAccessChain %_ptr_StorageBuffer__Array_std430_int32 %25 %int_11
         %35 = OpAccessChain %_ptr_StorageBuffer_int %25 %int_5
         %36 = OpLoad %int %35
         %38 = OpAccessChain %_ptr_StorageBuffer__arr_int_int_32 %32 %int_0
         %39 = OpAccessChain %_ptr_StorageBuffer_int %38 %36
         %40 = OpLoad %int %39
         %47 = OpAccessChain %_ptr_UniformConstant_42 %images %40
         %49 = OpLoad %42 %47
         %51 = OpLoad %50 %diffuseSampler
         %55 = OpLoad %v2float %arg_texCoord
%sampledImage = OpSampledImage %58 %49 %51
    %sampled = OpImageSampleImplicitLod %v4float %sampledImage %55 None
               OpStore %entryPointParam_main %sampled
               OpReturn
               OpFunctionEnd

Workaround Fragment Shader

struct UTileBuffer {
    // int4 address;
    int3 stepX;
    int startX;
    int3 stepY;
    int startY;
    float scaleZ;
    int z;
    int pad0;
    int pad1;
    // float scaleXZ;
    uint lodDelta[4];
    int childNodeIndices[32];
    int heightmapIndices[32];
    int materialIndices[32];
};

struct VOut {
    float4 position : SV_POSITION;
    float3 worldPos;
    float2 texCoord;
    float4 debugColor;
}

[[vk_binding(1, 0)]]
StructuredBuffer<UTileBuffer, Std430DataLayout> tiles;
[[vk_binding(3, 0)]]
SamplerState diffuseSampler;
// layout(binding = 2,set = 0) uniform sampler diffuseSampler;

[[vk_binding(4, 0)]]
Texture2D<float4> images[128];

[ForceInline]
[require(spirv)]
T nonUniformA<T>(T index)
{
    __target_switch {
    case spirv:
        var indexCopy = __copyObject(index);
        spirv_asm
        {
        OpCapability ShaderNonUniform;
        OpDecorate $index NonUniform;
        OpDecorate $indexCopy NonUniform;
        };
        return indexCopy;
    default:
        return index;
    }
}

[[shader("fragment")]]
float4 main(VOut arg,uint primitiveID: SV_PrimitiveID) {

    int id = (primitiveID) / (64 * 64 * 2);

    let push = tiles[id]; 
    let index = push.materialIndices[push.z];

    let diffuseColor = images[nonUniformA(index)].Sample(diffuseSampler, arg.texCoord);
    return diffuseColor;
}

workaround spriv-dis

; SPIR-V
; Version: 1.5
; Generator: Khronos; 40
; Bound: 67
; Schema: 0
               OpCapability Geometry
               OpCapability ShaderNonUniform
               OpCapability Shader
               OpExtension "SPV_KHR_storage_buffer_storage_class"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %tiles %images %diffuseSampler %entryPointParam_main %arg_texCoord %gl_PrimitiveID
               OpExecutionMode %main OriginUpperLeft
               OpSource Slang 1
               OpName %id "id"
               OpName %_Array_std430_uint4 "_Array_std430_uint4"
               OpMemberName %_Array_std430_uint4 0 "data"
               OpName %_Array_std430_int32 "_Array_std430_int32"
               OpMemberName %_Array_std430_int32 0 "data"
               OpName %UTileBuffer_std430 "UTileBuffer_std430"
               OpMemberName %UTileBuffer_std430 0 "stepX"
               OpMemberName %UTileBuffer_std430 1 "startX"
               OpMemberName %UTileBuffer_std430 2 "stepY"
               OpMemberName %UTileBuffer_std430 3 "startY"
               OpMemberName %UTileBuffer_std430 4 "scaleZ"
               OpMemberName %UTileBuffer_std430 5 "z"
               OpMemberName %UTileBuffer_std430 6 "pad0"
               OpMemberName %UTileBuffer_std430 7 "pad1"
               OpMemberName %UTileBuffer_std430 8 "lodDelta"
               OpMemberName %UTileBuffer_std430 9 "childNodeIndices"
               OpMemberName %UTileBuffer_std430 10 "heightmapIndices"
               OpMemberName %UTileBuffer_std430 11 "materialIndices"
               OpName %StructuredBuffer "StructuredBuffer"
               OpName %tiles "tiles"
               OpName %images "images"
               OpName %diffuseSampler "diffuseSampler"
               OpName %arg_texCoord "arg.texCoord"
               OpName %sampledImage "sampledImage"
               OpName %sampled "sampled"
               OpName %entryPointParam_main "entryPointParam_main"
               OpName %main "main"
               OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
               OpDecorate %gl_PrimitiveID Flat
               OpDecorate %_arr_uint_int_4 ArrayStride 4
               OpMemberDecorate %_Array_std430_uint4 0 Offset 0
               OpDecorate %_arr_int_int_32 ArrayStride 4
               OpMemberDecorate %_Array_std430_int32 0 Offset 0
               OpMemberDecorate %UTileBuffer_std430 0 Offset 0
               OpMemberDecorate %UTileBuffer_std430 1 Offset 12
               OpMemberDecorate %UTileBuffer_std430 2 Offset 16
               OpMemberDecorate %UTileBuffer_std430 3 Offset 28
               OpMemberDecorate %UTileBuffer_std430 4 Offset 32
               OpMemberDecorate %UTileBuffer_std430 5 Offset 36
               OpMemberDecorate %UTileBuffer_std430 6 Offset 40
               OpMemberDecorate %UTileBuffer_std430 7 Offset 44
               OpMemberDecorate %UTileBuffer_std430 8 Offset 48
               OpMemberDecorate %UTileBuffer_std430 9 Offset 64
               OpMemberDecorate %UTileBuffer_std430 10 Offset 192
               OpMemberDecorate %UTileBuffer_std430 11 Offset 320
               OpDecorate %_runtimearr_UTileBuffer_std430 ArrayStride 448
               OpDecorate %StructuredBuffer Block
               OpMemberDecorate %StructuredBuffer 0 Offset 0
               OpDecorate %tiles Binding 1
               OpDecorate %tiles DescriptorSet 0
               OpDecorate %tiles NonWritable
               OpDecorate %40 NonUniform
               OpDecorate %_arr_44_int_128 ArrayStride 8
               OpDecorate %images Binding 4
               OpDecorate %images DescriptorSet 0
               OpDecorate %diffuseSampler Binding 3
               OpDecorate %diffuseSampler DescriptorSet 0
               OpDecorate %arg_texCoord Location 1
               OpDecorate %entryPointParam_main Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
        %int = OpTypeInt 32 1
%_ptr_Input_int = OpTypePointer Input %int
       %uint = OpTypeInt 32 0
  %uint_8192 = OpConstant %uint 8192
      %int_0 = OpConstant %int 0
      %v3int = OpTypeVector %int 3
      %float = OpTypeFloat 32
      %int_4 = OpConstant %int 4
%_arr_uint_int_4 = OpTypeArray %uint %int_4
%_Array_std430_uint4 = OpTypeStruct %_arr_uint_int_4
     %int_32 = OpConstant %int 32
%_arr_int_int_32 = OpTypeArray %int %int_32
%_Array_std430_int32 = OpTypeStruct %_arr_int_int_32
%UTileBuffer_std430 = OpTypeStruct %v3int %int %v3int %int %float %int %int %int %_Array_std430_uint4 %_Array_std430_int32 %_Array_std430_int32 %_Array_std430_int32
%_ptr_StorageBuffer_UTileBuffer_std430 = OpTypePointer StorageBuffer %UTileBuffer_std430
%_runtimearr_UTileBuffer_std430 = OpTypeRuntimeArray %UTileBuffer_std430
%StructuredBuffer = OpTypeStruct %_runtimearr_UTileBuffer_std430
%_ptr_StorageBuffer_StructuredBuffer = OpTypePointer StorageBuffer %StructuredBuffer
     %int_11 = OpConstant %int 11
%_ptr_StorageBuffer__Array_std430_int32 = OpTypePointer StorageBuffer %_Array_std430_int32
      %int_5 = OpConstant %int 5
%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
%_ptr_StorageBuffer__arr_int_int_32 = OpTypePointer StorageBuffer %_arr_int_int_32
         %44 = OpTypeImage %float 2D 2 0 0 1 Unknown
    %int_128 = OpConstant %int 128
%_arr_44_int_128 = OpTypeArray %44 %int_128
%_ptr_UniformConstant__arr_44_int_128 = OpTypePointer UniformConstant %_arr_44_int_128
%_ptr_UniformConstant_44 = OpTypePointer UniformConstant %44
         %52 = OpTypeSampler
%_ptr_UniformConstant_52 = OpTypePointer UniformConstant %52
    %v2float = OpTypeVector %float 2
%_ptr_Input_v2float = OpTypePointer Input %v2float
         %60 = OpTypeSampledImage %44
    %v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%gl_PrimitiveID = OpVariable %_ptr_Input_int Input
      %tiles = OpVariable %_ptr_StorageBuffer_StructuredBuffer StorageBuffer
     %images = OpVariable %_ptr_UniformConstant__arr_44_int_128 UniformConstant
%diffuseSampler = OpVariable %_ptr_UniformConstant_52 UniformConstant
%arg_texCoord = OpVariable %_ptr_Input_v2float Input
%entryPointParam_main = OpVariable %_ptr_Output_v4float Output
       %main = OpFunction %void None %3
          %4 = OpLabel
          %6 = OpLoad %int %gl_PrimitiveID
         %10 = OpBitcast %uint %6
         %11 = OpUDiv %uint %10 %uint_8192
         %id = OpBitcast %int %11
         %25 = OpAccessChain %_ptr_StorageBuffer_UTileBuffer_std430 %tiles %int_0 %id
         %32 = OpAccessChain %_ptr_StorageBuffer__Array_std430_int32 %25 %int_11
         %35 = OpAccessChain %_ptr_StorageBuffer_int %25 %int_5
         %36 = OpLoad %int %35
         %38 = OpAccessChain %_ptr_StorageBuffer__arr_int_int_32 %32 %int_0
         %39 = OpAccessChain %_ptr_StorageBuffer_int %38 %36
         %40 = OpLoad %int %39
         %49 = OpAccessChain %_ptr_UniformConstant_44 %images %40
         %51 = OpLoad %44 %49
         %53 = OpLoad %52 %diffuseSampler
         %57 = OpLoad %v2float %arg_texCoord
%sampledImage = OpSampledImage %60 %51 %53
    %sampled = OpImageSampleImplicitLod %v4float %sampledImage %57 None
               OpStore %entryPointParam_main %sampled
               OpReturn
               OpFunctionEnd
@andreasschultes
Copy link
Author

andreasschultes commented Jan 6, 2025

First variant summary

OpDecorate %49 NonUniform
 %47 = OpAccessChain %_ptr_UniformConstant_42 %images %40
 %49 = OpLoad %42 %47

Second variant summary

OpDecorate %40 NonUniform
 %49 = OpAccessChain %_ptr_UniformConstant_44 %images %40
 %51 = OpLoad %44 %49

@bmillsNV bmillsNV added kind:bug something doesn't work like it should goal:quality & productivity Quality issues and issues that impact our productivity coding day to day inside slang labels Jan 7, 2025
@bmillsNV bmillsNV added this to the Q1 2025 (Winter) milestone Jan 7, 2025
@csyonghe
Copy link
Collaborator

csyonghe commented Jan 9, 2025

Checking the output from GLSlang, it seems that NonUniform is being decorated on both the OpAccessChain and the OpLoad insts. I have fixed this issue along the way of implementing the DescriptorHandle proposal.

@csyonghe csyonghe assigned csyonghe and unassigned aleino-nv Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
goal:quality & productivity Quality issues and issues that impact our productivity coding day to day inside slang kind:bug something doesn't work like it should
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants