From ebe8ddefc48478307d5f206cd3e40c41d28a36e3 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 26 Sep 2023 23:56:06 -0700 Subject: Various SPIRV fixes. (#3231) * Various SPIRV fixes. - Geometry shader support (WIP). - Fix texture get dimension and load. - Fold global GetElement(MakeArray/MakeVector) insts. - Call spvopt to inline all functions. - Translate OpImageSubscript. - Emit struct member names and global variable names. - Fix lowering of OpBitNot -> OpNot, instead of OpBitReverse. * Fix test. * Fix geometry shader. * Fix geometry shader emit. * Add atomic Image access test. * Fix tests. * don't fail if spirv-opt fails. * Update comments. * Fix test. * Cleanups. * indentation --------- Co-authored-by: Yong He Co-authored-by: Ellie Hermaszewska --- tests/bugs/texture2d-ms.hlsl | 4 +- tests/compute/texture-sampling.slang | 17 +++++-- tests/compute/texture-sampling.slang.expected.txt | 6 ++- tests/cross-compile/texture-load.slang.glsl | 19 +------- tests/spirv/array-uniform-param.slang | 40 ++++++++++++++++ tests/spirv/atomic-image-access.slang | 24 ++++++++++ tests/spirv/bit-field.slang | 54 ++++++++++++++++++++++ tests/spirv/direct-spirv-emit.slang | 7 ++- tests/spirv/geometry-shader.slang | 39 ++++++++++++++++ tests/spirv/scalar-buffer-packing.slang | 56 +++++++++++++++++++++++ 10 files changed, 243 insertions(+), 23 deletions(-) create mode 100644 tests/spirv/array-uniform-param.slang create mode 100644 tests/spirv/atomic-image-access.slang create mode 100644 tests/spirv/bit-field.slang create mode 100644 tests/spirv/geometry-shader.slang create mode 100644 tests/spirv/scalar-buffer-packing.slang (limited to 'tests') diff --git a/tests/bugs/texture2d-ms.hlsl b/tests/bugs/texture2d-ms.hlsl index 3fb84f72d..2de9da7bf 100644 --- a/tests/bugs/texture2d-ms.hlsl +++ b/tests/bugs/texture2d-ms.hlsl @@ -1,10 +1,12 @@ -//TEST:CROSS_COMPILE: -profile lib_6_3 -entry main -stage compute -target spirv-assembly +//TEST:SIMPLE(filecheck=CHECK): -profile lib_6_3 -entry main -stage compute -target spirv [[vk::binding(0, 0)]] Texture2DMS tex : register(t1); RWStructuredBuffer outBuffer; +// CHECK: %{{.*}} = OpImageFetch %v4float %{{.*}} %{{.*}} Sample %int_0 + [numthreads(4, 4, 1)] void main(uint3 groupId : SV_GroupID) { diff --git a/tests/compute/texture-sampling.slang b/tests/compute/texture-sampling.slang index 12bdc80bf..9ef0075bb 100644 --- a/tests/compute/texture-sampling.slang +++ b/tests/compute/texture-sampling.slang @@ -1,4 +1,6 @@ -//TEST(compute):COMPARE_RENDER_COMPUTE: -shaderobj +//TEST(compute):COMPARE_RENDER_COMPUTE: -shaderobj -output-using-type +//TEST(compute):COMPARE_RENDER_COMPUTE: -shaderobj -output-using-type -vk + //TEST_INPUT: Texture1D(size=4, content = one):name=t1D //TEST_INPUT: Texture2D(size=4, content = one):name=t2D @@ -8,7 +10,7 @@ //TEST_INPUT: Texture2D(size=4, content = one, arrayLength=2):name=t2dArray //TEST_INPUT: TextureCube(size=4, content = one, arrayLength=2):name=tCubeArray //TEST_INPUT: Sampler:name=samplerState -//TEST_INPUT: ubuffer(data=[0], stride=4):out,name=outputBuffer +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer Texture1D t1D; Texture2D t2D; @@ -100,7 +102,16 @@ FragmentStageOutput fragmentMain(FragmentStageInput input) val += tCubeArray.Sample(samplerState, float4(uv, 0.5, 0.0)); val += tCube.Sample(samplerState, float3(uv, 0.5)); - + + val += t2D.Load(int3(0), int2(0)); + val += t2dArray.Load(int4(0)); + + val += t3D[int3(0)]; + outputBuffer[0] = val.x; + + int w, h, l, lods; + t2dArray.GetDimensions(0, w, h, l, lods); + outputBuffer[1] = w + h + l + lods; return output; } diff --git a/tests/compute/texture-sampling.slang.expected.txt b/tests/compute/texture-sampling.slang.expected.txt index acf037f69..1df249246 100644 --- a/tests/compute/texture-sampling.slang.expected.txt +++ b/tests/compute/texture-sampling.slang.expected.txt @@ -1 +1,5 @@ -40E00000 \ No newline at end of file +type: float +10.000000 +13.000000 +0.000000 +0.000000 diff --git a/tests/cross-compile/texture-load.slang.glsl b/tests/cross-compile/texture-load.slang.glsl index d9145cdbf..7d080a3cb 100644 --- a/tests/cross-compile/texture-load.slang.glsl +++ b/tests/cross-compile/texture-load.slang.glsl @@ -1,13 +1,8 @@ -// texture-load.slang.glsl -//TEST_IGNORE_FILE: - #version 450 - +#extension GL_EXT_samplerless_texture_functions : require layout(row_major) uniform; layout(row_major) buffer; -#extension GL_EXT_samplerless_texture_functions : require - struct SLANG_ParameterGroup_C_0 { ivec2 pos_0; @@ -31,16 +26,6 @@ layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main() { ivec3 _S2 = ivec3(C_0.pos_0, 0); - - vec2 tmp_0 = texelFetch( - inputTexture_0, - _S2.xy, - _S2.z).xy; - - imageStore( - outputTexture_0, - ivec2(uvec2(C_0.pos_0)), - vec4(tmp_0, float(0), float(0))); - + imageStore((outputTexture_0), ivec2((uvec2(C_0.pos_0))), vec4((texelFetch((inputTexture_0), ((_S2)).xy, ((_S2)).z).xy), float(0), float(0))); return; } diff --git a/tests/spirv/array-uniform-param.slang b/tests/spirv/array-uniform-param.slang new file mode 100644 index 000000000..235e85bbd --- /dev/null +++ b/tests/spirv/array-uniform-param.slang @@ -0,0 +1,40 @@ +// array-uniform-param.slang + +//TESTD:SIMPLE:-target spirv -entry computeMain -stage compute -emit-spirv-directly -force-glsl-scalar-layout +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUFFER):-vk -compute -output-using-type + +// Test direct SPIR-V emit on arrays in uniforms. + +//TEST_INPUT:set resultBuffer = out ubuffer(data=[0 0 0 0], stride=4) +RWStructuredBuffer resultBuffer; + +struct Data +{ + uint arr[4]; +} + +struct Data2 +{ + uint arr[4u]; +} + +//TEST_INPUT: set Uniforms.d = new Data{{1,2,3,4}}; +//TEST_INPUT: set Uniforms.d2 = new Data2{{1,2,3,4}}; + +cbuffer Uniforms +{ + Data d; + Data2 d2; +} + +// BUFFER: 3 + +[numthreads(4,1,1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + uint threadId = dispatchThreadID.x; + uint result = d.arr[1]; + var u2 = reinterpret(d2); + result += u2.arr[0]; + resultBuffer[threadId] = result; +} diff --git a/tests/spirv/atomic-image-access.slang b/tests/spirv/atomic-image-access.slang new file mode 100644 index 000000000..1fc7cd28f --- /dev/null +++ b/tests/spirv/atomic-image-access.slang @@ -0,0 +1,24 @@ +// atomic-image-access.slang +//TEST:SIMPLE(filecheck=CHECK): -target spirv -entry computeMain -stage compute -emit-spirv-directly + +// The executable test is disabled because it somehow doesn't work. Might be a gfx issue. +//TEST_DISABLED(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUFFER):-vk -compute -output-using-type + +// Test direct SPIR-V emit on image atomics. + +//TEST_INPUT:set resultBuffer = out ubuffer(data=[0 0 0 0], stride=4) +RWStructuredBuffer resultBuffer; + +// TEST_INPUT: set tex = RWTexture2D(format=R32_UINT, size=4, content=zero, mipMaps = 1) +[vk::image_format("r32ui")] +RWTexture2D tex; + +[numthreads(1,1,1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + // CHECK: OpImageTexelPointer + InterlockedAdd(tex[uint2(0, 0)], 1); + uint oldVal; + InterlockedAdd(tex[uint2(0, 0)], 1, oldVal); + resultBuffer[0] = oldVal; +} diff --git a/tests/spirv/bit-field.slang b/tests/spirv/bit-field.slang new file mode 100644 index 000000000..878b4483d --- /dev/null +++ b/tests/spirv/bit-field.slang @@ -0,0 +1,54 @@ +// bit-field.slang + +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUFFER):-vk -compute -output-using-type + +// Test direct SPIR-V emit on bit field operations. + +//TEST_INPUT:set resultBuffer = out ubuffer(data=[0 0 0 0], stride=4) +RWStructuredBuffer resultBuffer; + +enum Flag +{ + AAA = 1, + BBB = 2, + CCC = 4, +} +struct Data +{ + uint flags; + [mutating] void setFlag(Flag g, bool v) + { + const uint bit = uint(g) << 8; + if (v) flags |= bit; + else flags &= ~bit; + } + bool hasFlag(Flag g) + { + const uint bit = uint(g) << 8; + return (flags & bit) != 0; + } +} + +//TEST_INPUT: set Uniforms.d = new Data{0}; +cbuffer Uniforms +{ + Data d; +} + +// BUFFER: 1 +// BUFFER: 1 +// BUFFER: 1 +// BUFFER: 0 + +[numthreads(1,1,1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + Data d1 = d; + d1.setFlag(Flag.BBB, true); + d1.setFlag(Flag.AAA, true); + resultBuffer[0] = d1.hasFlag(Flag.AAA) ? 1 : 0; + resultBuffer[1] = d1.hasFlag(Flag.BBB) ? 1 : 0; + d1.setFlag(Flag.BBB, false); + resultBuffer[2] = d1.hasFlag(Flag.AAA) ? 1 : 0; + resultBuffer[3] = d1.hasFlag(Flag.BBB) ? 1 : 0; +} diff --git a/tests/spirv/direct-spirv-emit.slang b/tests/spirv/direct-spirv-emit.slang index 99507f795..4cf514a3d 100644 --- a/tests/spirv/direct-spirv-emit.slang +++ b/tests/spirv/direct-spirv-emit.slang @@ -1,9 +1,14 @@ // direct-spirv-emit.slang -//TEST:SIMPLE:-target spirv -entry computeMain -stage compute -emit-spirv-directly +//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry computeMain -stage compute -emit-spirv-directly // Test ability to directly output SPIR-V +// CHECK: OpCapability Shader +// CHECK: OpMemoryModel Logical GLSL450 +// CHECK: OpEntryPoint GLCompute %computeMain "main" +// CHECK: OpExecutionMode %computeMain LocalSize 4 1 1 + [numthreads(4,1,1)] void computeMain() {} diff --git a/tests/spirv/geometry-shader.slang b/tests/spirv/geometry-shader.slang new file mode 100644 index 000000000..08080ae59 --- /dev/null +++ b/tests/spirv/geometry-shader.slang @@ -0,0 +1,39 @@ +//TEST:SIMPLE(filecheck=CHECK):-entry gsMain -stage geometry -target spirv -emit-spirv-directly + +struct GsOut +{ + float2 uv : TexCoord; + float2 texelPos : TexelPosition; + float4 posH : SV_Position; +}; + +// CHECK-DAG: OpEntryPoint Geometry %gsMain "main" %[[OUT1:[A-Za-z0-9_]+]] %[[OUT2:[A-Za-z0-9_]+]] %gl_Position +// CHECK-DAG: %[[OUT1]] = OpVariable %_ptr_Output_v2float Output +// CHECK-DAG: %[[OUT2]] = OpVariable %_ptr_Output_v2float Output +// CHECK-DAG: %gl_Position = OpVariable %_ptr_Output_v4float Output + +// CHECK-DAG: OpExecutionMode %gsMain Invocations 1 +// CHECK-DAG: OpExecutionMode %gsMain OutputTriangleStrip +// CHECK-DAG: OpExecutionMode %gsMain Triangles +// CHECK-DAG: OpExecutionMode %gsMain OutputVertices 15 + +// CHECK: OpStore %gl_Position +// CHECK: OpEmitVertex +// CHECK: OpEndPrimitive + +[maxvertexcount(15)] +void gsMain(uint triIdx : SV_PrimitiveID, inout TriangleStream outStream) +{ + for (int j = 0; j < 5; j++) + { + for (int i = 0; i < 3; i++) + { + GsOut v; + v.uv = float2(j,i); + v.texelPos = float2(0,0); + v.posH = float4(j, i, 1, 1); + outStream.Append(v); + } + outStream.RestartStrip(); + } +} \ No newline at end of file diff --git a/tests/spirv/scalar-buffer-packing.slang b/tests/spirv/scalar-buffer-packing.slang new file mode 100644 index 000000000..bc42cfa39 --- /dev/null +++ b/tests/spirv/scalar-buffer-packing.slang @@ -0,0 +1,56 @@ +// scalar-buffer-packing.slang +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute +//TEST:SIMPLE(filecheck=SPIRV): -stage compute -entry computeMain -target spirv -emit-spirv-directly -force-glsl-scalar-layout +// Test ability to directly output SPIR-V + +//TEST_INPUT:set Uniforms.v0 = 1 +//TEST_INPUT:set Uniforms.v1 = { 1.0, 2.0, 3.0} + +cbuffer Uniforms +{ + bool v0; + float3 v1[3]; +} + +struct Val +{ + bool x; + int3 v1[2]; + [mutating] + void set(bool v) + { + x = v; + v1[0].x = 1; + v1[0].y = 2; + v1[0].z = 3; + v1[1].x = 4; + v1[1].y = 5; + v1[1].z = 6; + } +} + +//TEST_INPUT:set result = out ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0], stride=4) +RWStructuredBuffer result; +[numthreads(1,1,1)] +void computeMain() +{ + // CHECK: 1 + // CHECK: 0 + // CHECK: 0 + // CHECK: 0 + // CHECK: 1 + // CHECK: 2 + // CHECK: 3 + // CHECK: 0 + // CHECK: 4 + // CHECK: 5 + // CHECK: 6 + + result[0].set(v0); +} + +// SPIRV: OpEntryPoint GLCompute + +// SPIRV-DAG: %[[STRUCTNAME:[A-Za-z0-9_]+]] = OpTypeStruct %int %_Array_natural_int32 + +// SPIRV-DAG: OpMemberDecorate %[[STRUCTNAME:[A-Za-z0-9_]+]] 1 Offset 4 -- cgit v1.2.3