diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2023-09-12 11:13:11 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-11 20:13:11 -0700 |
| commit | 09854a4596019ddb3bb315b8836b5c88e718cdc7 (patch) | |
| tree | 1556ae3e00da0fac91343f159b52cee1231a7fab /tests | |
| parent | 87bb0b503544f1b8c6ec818e25c695b31cda24b7 (diff) | |
Add Mesh and Task shader support to GFX (#3190)
* Bump vulkan headers
Also just use vulkan-headers as a submodule
* Add drawMeshTasks to gfx graphics pipelines
* Add DispatchMesh overload with no payload, with GLSL intrinsic
* Require spirv 1.4 for mesh shaders
* Add vulkan mesh shader feature discovery
* Add mesh shader stage bits to vk-util
* Add mesh and task shader support to render-test
* Add mesh and task tests
* Preserve "payload" specifier in task shaders
* Add mesh shader pipeline support to gfx
* Add TODO
* Add numThreads attribute for amplification stage
* Add payload to task shader test
* Drop dependency on d3dx12
* Allow passing payloads from task to mesh shaders
* regenerate vs projects
* check DispatchMesh name correctly
* Add mesh shader tests to failing tests
* Detect wave-ops feature on vulkan
* Add fuse-product to expected failures
This fails because the global varaible `count` is not initialized
* Add required extension to WaveMaskMatch SPIR-V impl
* Remove meshShader member from pipeline desc
* Identify mesh shader support on d3d12
Diffstat (limited to 'tests')
8 files changed, 314 insertions, 13 deletions
diff --git a/tests/expected-failure.txt b/tests/expected-failure.txt index 281d79391..0acf97262 100644 --- a/tests/expected-failure.txt +++ b/tests/expected-failure.txt @@ -6,4 +6,8 @@ tests/compute/ray-tracing-inline.slang.1 (vk) tests/language-feature/constants/constexpr-loop.slang.1 (vk) tests/optimization/func-resource-result/func-resource-result-complex.slang.1 (vk) tests/type/texture-sampler/texture-sampler-2d.slang (vk) -tests/hlsl-intrinsic/texture-lod-shadow.slang.1
\ No newline at end of file +tests/hlsl-intrinsic/texture-lod-shadow.slang.1 +tests/pipeline/rasterization/mesh/task-groupshared.slang.1 (vk) +tests/pipeline/rasterization/mesh/task-simple.slang.1 (vk) +tests/pipeline/rasterization/mesh/simple.slang.1 (vk) +tests/language-feature/saturated-cooperation/fuse-product.slang (vk) diff --git a/tests/language-feature/saturated-cooperation/fuse-product.slang b/tests/language-feature/saturated-cooperation/fuse-product.slang index 2d1029140..d59df2db3 100644 --- a/tests/language-feature/saturated-cooperation/fuse-product.slang +++ b/tests/language-feature/saturated-cooperation/fuse-product.slang @@ -1,8 +1,7 @@ -//DISABLED_TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type +//TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -render-features wave-ops +//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type -render-features wave-ops //TEST:SIMPLE(filecheck=CHECK):-target hlsl -profile cs_6_5 -entry computeMain -line-directive-mode none //TEST:SIMPLE(filecheck=CHECK):-target glsl -profile cs_6_5 -entry computeMain -line-directive-mode none -// Disabled because some testing infra (swiftshader) doens't support the necessary wave ops // // This test checks that we fuse calls to saturated cooperation, even with different input values diff --git a/tests/language-feature/saturated-cooperation/fuse.slang b/tests/language-feature/saturated-cooperation/fuse.slang index 1492be4f3..5feb46e2e 100644 --- a/tests/language-feature/saturated-cooperation/fuse.slang +++ b/tests/language-feature/saturated-cooperation/fuse.slang @@ -1,6 +1,5 @@ -//DISABLED_TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type -// Disabled because some testing infra (swiftshader) doens't support the necessary wave ops +//TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -render-features wave-ops +//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type -render-features wave-ops // // This test checks whether adjacent calls to saturated_cooperation are fused diff --git a/tests/language-feature/saturated-cooperation/fuse3.slang b/tests/language-feature/saturated-cooperation/fuse3.slang index 6d5fd9e06..884f65652 100644 --- a/tests/language-feature/saturated-cooperation/fuse3.slang +++ b/tests/language-feature/saturated-cooperation/fuse3.slang @@ -1,6 +1,5 @@ -//DISABLED_TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type -// Disabled because some testing infra (swiftshader) doens't support the necessary wave ops +//TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -render-features wave-ops +//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type -render-features wave-ops // // This test checks whether more than 2 adjacent calls to saturated_cooperation diff --git a/tests/language-feature/saturated-cooperation/simple.slang b/tests/language-feature/saturated-cooperation/simple.slang index 3b9fb24e7..d2ea6faed 100644 --- a/tests/language-feature/saturated-cooperation/simple.slang +++ b/tests/language-feature/saturated-cooperation/simple.slang @@ -1,6 +1,5 @@ -//DISABLED_TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type -// Disabled because some testing infra (swiftshader) doens't support the necessary wave ops +//TEST(compute, vulkan):COMPARE_COMPUTE_EX():-vk -compute -shaderobj -output-using-type -render-features wave-ops +//TEST(compute):COMPARE_COMPUTE_EX():-dx12 -profile sm_6_5 -use-dxil -compute -shaderobj -output-using-type -render-features wave-ops //TEST_INPUT:ubuffer(data=[0 3 2 2], stride=4):out,name=outputBuffer RWStructuredBuffer<uint> outputBuffer; diff --git a/tests/pipeline/rasterization/mesh/simple.slang b/tests/pipeline/rasterization/mesh/simple.slang new file mode 100644 index 000000000..00047aaad --- /dev/null +++ b/tests/pipeline/rasterization/mesh/simple.slang @@ -0,0 +1,86 @@ +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -mesh -output-using-type -dx12 -use-dxil -profile sm_6_6 -render-features mesh-shader +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -mesh -output-using-type -vk -profile glsl_450+spirv_1_4 -render-features mesh-shader + +// To test a simple mesh shader, we'll generate 4 triangles, the vertices of +// each one will hold the triangle index and a value (the square). The fragment +// shader will write the value to the specified index of the output buffer. + +// CHECK: 0 +// CHECK-NEXT: 1 +// CHECK-NEXT: 4 +// CHECK-NEXT: 9 + +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer + +RWStructuredBuffer<float> outputBuffer; + +cbuffer Uniforms +{ + float4x4 modelViewProjection; +} + +// +// Mesh shader +// + +const static float2 positions[3] = { + float2(0.0, -0.5), + float2(0.5, 0.5), + float2(-0.5, 0.5) +}; + +const static float3 colors[3] = { + float3(1.0, 1.0, 0.0), + float3(0.0, 1.0, 1.0), + float3(1.0, 0.0, 1.0) +}; + +struct Vertex +{ + float4 pos : SV_Position; + float3 color : Color; + int index : Index; + int value : Value; +}; + +const static uint MAX_VERTS = 12; +const static uint MAX_PRIMS = 4; + +[outputtopology("triangle")] +[numthreads(12, 1, 1)] +void meshMain( + in uint tig : SV_GroupIndex, + out Vertices<Vertex, MAX_VERTS> verts, + out Indices<uint3, MAX_PRIMS> triangles) +{ + const uint numVertices = 12; + const uint numPrimitives = 4; + SetMeshOutputCounts(numVertices, numPrimitives); + + if(tig < numVertices) + { + const int tri = tig / 3; + verts[tig] = {float4(positions[tig % 3], 0, 1), colors[tig % 3], tri, tri*tri}; + } + + if(tig < numPrimitives) + triangles[tig] = tig * 3 + uint3(0,1,2); +} + +// +// Fragment Shader +// + +struct Fragment +{ + float4 color : SV_Target; +}; + +Fragment fragmentMain(Vertex input) +{ + outputBuffer[input.index] = input.value; + + Fragment output; + output.color = float4(input.color, 1.0); + return output; +} diff --git a/tests/pipeline/rasterization/mesh/task-groupshared.slang b/tests/pipeline/rasterization/mesh/task-groupshared.slang new file mode 100644 index 000000000..5690735cd --- /dev/null +++ b/tests/pipeline/rasterization/mesh/task-groupshared.slang @@ -0,0 +1,109 @@ +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -task -output-using-type -dx12 -use-dxil -profile sm_6_6 -render-features mesh-shader +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -task -output-using-type -vk -profile glsl_450+spirv_1_4 -render-features mesh-shader + +// Similar to task-simple, except that the payload is declared as a groupshared +// variable. During lowerin to GLSL and SPIR-V we'll have to identify this as +// the variable being passed to DispatchMesh and emit it using the +// taskPayloadSharedEXT rate. + +// CHECK: 0 +// CHECK-NEXT: 1 +// CHECK-NEXT: 8 +// CHECK-NEXT: 27 + +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer + +RWStructuredBuffer<float> outputBuffer; + +cbuffer Uniforms +{ + float4x4 modelViewProjection; +} + +// +// Task shader +// + +struct MeshPayload +{ + int exponent; +}; + +groupshared MeshPayload p; + +[outputtopology("triangle")] +[numthreads(1, 1, 1)] +void taskMain(in uint tig : SV_GroupIndex) +{ + p.exponent = 3; + DispatchMesh(1,1,1,p); +} + + +// +// Mesh shader +// + +const static float2 positions[3] = { + float2(0.0, -0.5), + float2(0.5, 0.5), + float2(-0.5, 0.5) +}; + +const static float3 colors[3] = { + float3(1.0, 1.0, 0.0), + float3(0.0, 1.0, 1.0), + float3(1.0, 0.0, 1.0) +}; + +struct Vertex +{ + float4 pos : SV_Position; + float3 color : Color; + int index : Index; + int value : Value; +}; + +const static uint MAX_VERTS = 12; +const static uint MAX_PRIMS = 4; + +[outputtopology("triangle")] +[numthreads(12, 1, 1)] +void meshMain( + in uint tig : SV_GroupIndex, + in payload MeshPayload meshPayload, + out Vertices<Vertex, MAX_VERTS> verts, + out Indices<uint3, MAX_PRIMS> triangles) +{ + const uint numVertices = 12; + const uint numPrimitives = 4; + SetMeshOutputCounts(numVertices, numPrimitives); + + if(tig < numVertices) + { + const int tri = tig / 3; + verts[tig] = {float4(positions[tig % 3], 0, 1), colors[tig % 3], tri, int(pow(tri, meshPayload.exponent))}; + } + + if(tig < numPrimitives) + triangles[tig] = tig * 3 + uint3(0,1,2); +} + +// +// Fragment Shader +// + +struct Fragment +{ + float4 color : SV_Target; +}; + +Fragment fragmentMain(Vertex input) +{ + outputBuffer[input.index] = input.value; + + Fragment output; + output.color = float4(input.color, 1.0); + return output; +} + diff --git a/tests/pipeline/rasterization/mesh/task-simple.slang b/tests/pipeline/rasterization/mesh/task-simple.slang new file mode 100644 index 000000000..7da9ed32b --- /dev/null +++ b/tests/pipeline/rasterization/mesh/task-simple.slang @@ -0,0 +1,106 @@ +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -task -output-using-type -dx12 -use-dxil -profile sm_6_6 -render-features mesh-shader +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -task -output-using-type -vk -profile glsl_450+spirv_1_4 -render-features mesh-shader + +// To test a simple mesh shader, we'll generate 4 triangles, the vertices of +// each one will hold the triangle index and a value (the square). The fragment +// shader will write the value to the specified index of the output buffer. + +// CHECK: 0 +// CHECK-NEXT: 1 +// CHECK-NEXT: 8 +// CHECK-NEXT: 27 + +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer + +RWStructuredBuffer<float> outputBuffer; + +cbuffer Uniforms +{ + float4x4 modelViewProjection; +} + +// +// Task shader +// + +struct MeshPayload +{ + int exponent; +}; + +[outputtopology("triangle")] +[numthreads(1, 1, 1)] +void taskMain(in uint tig : SV_GroupIndex) +{ + MeshPayload p; + p.exponent = 3; + DispatchMesh(1,1,1,p); +} + + +// +// Mesh shader +// + +const static float2 positions[3] = { + float2(0.0, -0.5), + float2(0.5, 0.5), + float2(-0.5, 0.5) +}; + +const static float3 colors[3] = { + float3(1.0, 1.0, 0.0), + float3(0.0, 1.0, 1.0), + float3(1.0, 0.0, 1.0) +}; + +struct Vertex +{ + float4 pos : SV_Position; + float3 color : Color; + int index : Index; + int value : Value; +}; + +const static uint MAX_VERTS = 12; +const static uint MAX_PRIMS = 4; + +[outputtopology("triangle")] +[numthreads(12, 1, 1)] +void meshMain( + in uint tig : SV_GroupIndex, + in payload MeshPayload meshPayload, + out Vertices<Vertex, MAX_VERTS> verts, + out Indices<uint3, MAX_PRIMS> triangles) +{ + const uint numVertices = 12; + const uint numPrimitives = 4; + SetMeshOutputCounts(numVertices, numPrimitives); + + if(tig < numVertices) + { + const int tri = tig / 3; + verts[tig] = {float4(positions[tig % 3], 0, 1), colors[tig % 3], tri, int(pow(tri, meshPayload.exponent))}; + } + + if(tig < numPrimitives) + triangles[tig] = tig * 3 + uint3(0,1,2); +} + +// +// Fragment Shader +// + +struct Fragment +{ + float4 color : SV_Target; +}; + +Fragment fragmentMain(Vertex input) +{ + outputBuffer[input.index] = input.value; + + Fragment output; + output.color = float4(input.color, 1.0); + return output; +} |
