KhronosGroup / glslang

Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator.
Other
2.95k stars 819 forks source link

Cannot call InterlockedAdd() method on a RWByteAddressBuffer in HLSL #2066

Open Ryp opened 4 years ago

Ryp commented 4 years ago

Here's my repro case:

RWByteAddressBuffer MyBuffer;

[numthreads(1, 1, 1)]
void main()
{
    uint previous_value;
    MyBuffer.InterlockedAdd(0, 1, previous_value);
}

This shader compiles to SPIR-V with the following command:

$ glslangValidator --target-env spirv1.3 -g -e main -V -D test_interlocked.comp.hlsl -o test_interlocked.comp.spv.unoptimized
$ spirv-opt test_interlocked.comp.spv.unoptimized --legalize-hlsl -Os -o test_interlocked.comp.spv
$ glslangValidator --version
Glslang Version: 8.13.3559
ESSL Version: OpenGL ES GLSL 3.20 glslang Khronos. 13.3559
GLSL Version: 4.60 glslang Khronos. 13.3559
SPIR-V Version 0x00010400, Revision 1
GLSL.std.450 Version 100, Revision 1
Khronos Tool ID 8
SPIR-V Generator Version 8
GL_KHR_vulkan_glsl version 100
ARB_GL_gl_spirv version 100

The compilation fails when spirv-opt is invoked with the following message:

error: line 51: AtomicIAdd: expected Value to be of type Result Type
  %25 = OpAtomicIAdd %uint %21 %uint_1 %uint_0 %int_1

I'm not sure if this problem comes from glslang or spirv-opt, maybe you guys have more info on this. As a reference, here is what dxc outputs at the atomic instruction for my example:

%14 = OpAtomicIAdd %uint %13 %uint_1 %uint_0 %uint_1

EDIT: So I slept on it and tried to force constants to the uint type. Here's the changed part:

MyBuffer.InterlockedAdd(0, uint(1), previous_value);

This successfully compiles with glslang. I still think there's a bug here though.

Andreyogld3d commented 4 years ago

@Ryp you can use a temporary solution:

MyBuffer.InterlockedAdd(0, 1u, previous_value);