summaryrefslogtreecommitdiffstats
path: root/tests/pipeline
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-09-12 11:13:11 +0800
committerGitHub <noreply@github.com>2023-09-11 20:13:11 -0700
commit09854a4596019ddb3bb315b8836b5c88e718cdc7 (patch)
tree1556ae3e00da0fac91343f159b52cee1231a7fab /tests/pipeline
parent87bb0b503544f1b8c6ec818e25c695b31cda24b7 (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/pipeline')
-rw-r--r--tests/pipeline/rasterization/mesh/simple.slang86
-rw-r--r--tests/pipeline/rasterization/mesh/task-groupshared.slang109
-rw-r--r--tests/pipeline/rasterization/mesh/task-simple.slang106
3 files changed, 301 insertions, 0 deletions
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;
+}