|
@@ -0,0 +1,202 @@
|
|
|
+// Run: %dxc -T ms_6_5 -E main
|
|
|
+
|
|
|
+// CHECK: OpCapability MeshShadingNV
|
|
|
+// CHECK: OpExtension "SPV_NV_mesh_shader"
|
|
|
+// CHECK: OpEntryPoint MeshNV %main "main"
|
|
|
+
|
|
|
+// CHECK: OpName %UserVertex "UserVertex"
|
|
|
+struct UserVertex {
|
|
|
+// CHECK: OpMemberName %UserVertex 0 "position"
|
|
|
+// CHECK: OpMemberName %UserVertex 1 "texcoord"
|
|
|
+// CHECK: OpMemberName %UserVertex 2 "color"
|
|
|
+ float3 position;
|
|
|
+ float2 texcoord;
|
|
|
+ float3 color;
|
|
|
+};
|
|
|
+
|
|
|
+// CHECK: OpName %Mesh "Mesh"
|
|
|
+struct Mesh {
|
|
|
+// CHECK: OpMemberName %Mesh 0 "firstSubmesh"
|
|
|
+// CHECK: OpMemberName %Mesh 1 "submeshCount"
|
|
|
+// CHECK: OpMemberName %Mesh 2 "dummy"
|
|
|
+ uint firstSubmesh;
|
|
|
+ uint submeshCount;
|
|
|
+ uint dummy[2];
|
|
|
+};
|
|
|
+
|
|
|
+// CHECK: OpName %SubMesh "SubMesh"
|
|
|
+struct SubMesh {
|
|
|
+// CHECK: OpMemberName %SubMesh 0 "vertexCount"
|
|
|
+// CHECK: OpMemberName %SubMesh 1 "vertexOffset"
|
|
|
+// CHECK: OpMemberName %SubMesh 2 "primitiveCount"
|
|
|
+// CHECK: OpMemberName %SubMesh 3 "indexOffset"
|
|
|
+// CHECK: OpMemberName %SubMesh 4 "boundingBox"
|
|
|
+ uint vertexCount;
|
|
|
+ uint vertexOffset;
|
|
|
+ uint primitiveCount;
|
|
|
+ uint indexOffset;
|
|
|
+ float4 boundingBox[8];
|
|
|
+};
|
|
|
+
|
|
|
+// CHECK: OpDecorate %userVertices DescriptorSet 0
|
|
|
+// CHECK: OpDecorate %userVertices Binding 0
|
|
|
+// CHECK: OpDecorate %userIndices DescriptorSet 0
|
|
|
+// CHECK: OpDecorate %userIndices Binding 1
|
|
|
+// CHECK: OpDecorate %meshes DescriptorSet 0
|
|
|
+// CHECK: OpDecorate %meshes Binding 2
|
|
|
+// CHECK: OpDecorate %submeshes DescriptorSet 0
|
|
|
+// CHECK: OpDecorate %submeshes Binding 3
|
|
|
+// CHECK: OpDecorate %UBO DescriptorSet 0
|
|
|
+// CHECK: OpDecorate %UBO Binding 4
|
|
|
+
|
|
|
+// CHECK: OpMemberDecorate %UserVertex 0 Offset 0
|
|
|
+// CHECK: OpMemberDecorate %UserVertex 1 Offset 16
|
|
|
+// CHECK: OpMemberDecorate %UserVertex 2 Offset 32
|
|
|
+// CHECK: OpDecorate %_runtimearr_UserVertex ArrayStride 48
|
|
|
+// CHECK: OpMemberDecorate %type_RWStructuredBuffer_UserVertex 0 Offset 0
|
|
|
+// CHECK: OpDecorate %type_RWStructuredBuffer_UserVertex BufferBlock
|
|
|
+
|
|
|
+// CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
|
|
|
+// CHECK: OpMemberDecorate %type_RWStructuredBuffer_uint 0 Offset 0
|
|
|
+// CHECK: OpDecorate %type_RWStructuredBuffer_uint BufferBlock
|
|
|
+
|
|
|
+// CHECK: OpMemberDecorate %Mesh 0 Offset 0
|
|
|
+// CHECK: OpMemberDecorate %Mesh 1 Offset 4
|
|
|
+// CHECK: OpMemberDecorate %Mesh 2 Offset 8
|
|
|
+// CHECK: OpDecorate %_runtimearr_Mesh ArrayStride 16
|
|
|
+// CHECK: OpMemberDecorate %type_RWStructuredBuffer_Mesh 0 Offset 0
|
|
|
+// CHECK: OpDecorate %type_RWStructuredBuffer_Mesh BufferBlock
|
|
|
+
|
|
|
+// CHECK: OpMemberDecorate %SubMesh 0 Offset 0
|
|
|
+// CHECK: OpMemberDecorate %SubMesh 1 Offset 4
|
|
|
+// CHECK: OpMemberDecorate %SubMesh 2 Offset 8
|
|
|
+// CHECK: OpMemberDecorate %SubMesh 3 Offset 12
|
|
|
+// CHECK: OpMemberDecorate %SubMesh 4 Offset 16
|
|
|
+// CHECK: OpDecorate %_runtimearr_SubMesh ArrayStride 144
|
|
|
+// CHECK: OpMemberDecorate %type_RWStructuredBuffer_SubMesh 0 Offset 0
|
|
|
+// CHECK: OpDecorate %type_RWStructuredBuffer_SubMesh BufferBlock
|
|
|
+
|
|
|
+// CHECK: OpMemberDecorate %type_UBO 0 Offset 0
|
|
|
+// CHECK: OpMemberDecorate %type_UBO 0 MatrixStride 16
|
|
|
+// CHECK: OpMemberDecorate %type_UBO 0 ColMajor
|
|
|
+// CHECK: OpDecorate %type_UBO Block
|
|
|
+
|
|
|
+// CHECK: %UserVertex = OpTypeStruct %v3float %v2float %v3float
|
|
|
+// CHECK: %_runtimearr_UserVertex = OpTypeRuntimeArray %UserVertex
|
|
|
+// CHECK: %type_RWStructuredBuffer_UserVertex = OpTypeStruct %_runtimearr_UserVertex
|
|
|
+// CHECK: %_ptr_Uniform_type_RWStructuredBuffer_UserVertex = OpTypePointer Uniform %type_RWStructuredBuffer_UserVertex
|
|
|
+[[vk::binding(0, 0)]]
|
|
|
+RWStructuredBuffer<UserVertex> userVertices;
|
|
|
+
|
|
|
+// CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
|
|
|
+// CHECK: %type_RWStructuredBuffer_uint = OpTypeStruct %_runtimearr_uint
|
|
|
+// CHECK: %_ptr_Uniform_type_RWStructuredBuffer_uint = OpTypePointer Uniform %type_RWStructuredBuffer_uint
|
|
|
+[[vk::binding(1, 0)]]
|
|
|
+RWStructuredBuffer<uint> userIndices;
|
|
|
+
|
|
|
+// CHECK: %_arr_uint_uint_2 = OpTypeArray %uint %uint_2
|
|
|
+// CHECK: %Mesh = OpTypeStruct %uint %uint %_arr_uint_uint_2
|
|
|
+// CHECK: %_runtimearr_Mesh = OpTypeRuntimeArray %Mesh
|
|
|
+// CHECK: %type_RWStructuredBuffer_Mesh = OpTypeStruct %_runtimearr_Mesh
|
|
|
+// CHECK: %_ptr_Uniform_type_RWStructuredBuffer_Mesh = OpTypePointer Uniform %type_RWStructuredBuffer_Mesh
|
|
|
+[[vk::binding(2, 0)]]
|
|
|
+RWStructuredBuffer<Mesh> meshes;
|
|
|
+
|
|
|
+// CHECK: %uint_8 = OpConstant %uint 8
|
|
|
+// CHECK: %v4float = OpTypeVector %float 4
|
|
|
+// CHECK: %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
|
|
|
+// CHECK: %SubMesh = OpTypeStruct %uint %uint %uint %uint %_arr_v4float_uint_8
|
|
|
+// CHECK: %_runtimearr_SubMesh = OpTypeRuntimeArray %SubMesh
|
|
|
+// CHECK: %type_RWStructuredBuffer_SubMesh = OpTypeStruct %_runtimearr_SubMesh
|
|
|
+// CHECK: %_ptr_Uniform_type_RWStructuredBuffer_SubMesh = OpTypePointer Uniform %type_RWStructuredBuffer_SubMesh
|
|
|
+[[vk::binding(3, 0)]]
|
|
|
+RWStructuredBuffer<SubMesh> submeshes;
|
|
|
+
|
|
|
+// CHECK: %mat4v4float = OpTypeMatrix %v4float 4
|
|
|
+// CHECK: %type_UBO = OpTypeStruct %mat4v4float
|
|
|
+// CHECK: %_ptr_Uniform_type_UBO = OpTypePointer Uniform %type_UBO
|
|
|
+[[vk::binding(4, 0)]]
|
|
|
+cbuffer UBO {
|
|
|
+ row_major float4x4 mvp;
|
|
|
+}
|
|
|
+
|
|
|
+struct PerVertex {
|
|
|
+ float4 position : SV_Position;
|
|
|
+ float2 texcoord : TEXCOORD;
|
|
|
+ float3 color : COLOR;
|
|
|
+};
|
|
|
+
|
|
|
+struct PerPrimitive {
|
|
|
+ float4 primcolor : PCOLOR;
|
|
|
+};
|
|
|
+
|
|
|
+struct SubMeshes {
|
|
|
+ uint submeshID[256] : SUBMESH;
|
|
|
+};
|
|
|
+
|
|
|
+static const uint vertsPerPrim = 3U;
|
|
|
+
|
|
|
+// CHECK: %userVertices = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_UserVertex Uniform
|
|
|
+// CHECK: %userIndices = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
|
|
|
+// CHECK: %meshes = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_Mesh Uniform
|
|
|
+// CHECK: %submeshes = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_SubMesh Uniform
|
|
|
+// CHECK: %UBO = OpVariable %_ptr_Uniform_type_UBO Uniform
|
|
|
+
|
|
|
+[outputtopology("triangle")]
|
|
|
+[numthreads(32, 1, 1)]
|
|
|
+void main(
|
|
|
+ out indices uint3 primIndices[128],
|
|
|
+ out vertices PerVertex verts[128],
|
|
|
+ out primitives PerPrimitive prims[128],
|
|
|
+ in payload SubMeshes taskmem,
|
|
|
+ in uint gid : SV_GroupID,
|
|
|
+ in uint tid : SV_GroupThreadID
|
|
|
+ )
|
|
|
+{
|
|
|
+ uint task = taskmem.submeshID[gid];
|
|
|
+// CHECK: %submesh = OpVariable %_ptr_Function_SubMesh_0 Function
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_SubMesh %submeshes %int_0 [[task:%\d+]]
|
|
|
+// CHECK: OpStore %submesh [[submeshVal:%\d+]]
|
|
|
+ SubMesh submesh = submeshes[task];
|
|
|
+// CHECK: OpAccessChain %_ptr_Function_uint %submesh %int_0
|
|
|
+ uint numPackedVertices = submesh.vertexCount;
|
|
|
+// CHECK: OpAccessChain %_ptr_Function_uint %submesh %int_2
|
|
|
+ uint numPackedPrimitives = submesh.primitiveCount;
|
|
|
+
|
|
|
+ SetMeshOutputCounts(numPackedVertices, numPackedPrimitives);
|
|
|
+
|
|
|
+ for (uint i = 0U; i < numPackedVertices; i += 32U) {
|
|
|
+ uint vid = i + tid;
|
|
|
+// CHECK: OpAccessChain %_ptr_Function_uint %submesh %int_1
|
|
|
+ uint svid = vid + submesh.vertexOffset;
|
|
|
+ if (vid >= numPackedVertices) continue;
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_v2float %userVertices %int_0 [[svid_1:%\d+]] %int_1
|
|
|
+ verts[vid].texcoord = userVertices[svid].texcoord;
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_v3float %userVertices %int_0 [[svid_2:%\d+]] %int_2
|
|
|
+ verts[vid].color = userVertices[svid].color;
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_v3float %userVertices %int_0 [[svid_0:%\d+]] %int_0
|
|
|
+ float3 position = userVertices[svid].position;
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_mat4v4float %UBO %int_0
|
|
|
+ verts[vid].position = mul(mvp, float4(position, 1.0));
|
|
|
+ }
|
|
|
+
|
|
|
+ GroupMemoryBarrier();
|
|
|
+
|
|
|
+ for (uint j = 0U; j < numPackedPrimitives; j += 32U) {
|
|
|
+ uint pid = j + tid;
|
|
|
+ uint didxoff = vertsPerPrim * pid;
|
|
|
+// CHECK: OpAccessChain %_ptr_Function_uint %submesh %int_3
|
|
|
+ uint sidxoff = submesh.indexOffset + didxoff;
|
|
|
+ if (pid >= numPackedPrimitives) continue;
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_uint %userIndices %int_0 [[sidxoff_0:%\d+]]
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_uint %userIndices %int_0 [[sidxoff_1:%\d+]]
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_uint %userIndices %int_0 [[sidxoff_2:%\d+]]
|
|
|
+ primIndices[pid] = uint3(userIndices[sidxoff], userIndices[sidxoff+1], userIndices[sidxoff+2]);
|
|
|
+// CHECK: OpAccessChain %_ptr_Function_uint %submesh %int_1
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_uint %userIndices %int_0 [[ind:%\d+]]
|
|
|
+ uint providx = submesh.vertexOffset + userIndices[sidxoff + vertsPerPrim - 1U];
|
|
|
+// CHECK: OpAccessChain %_ptr_Uniform_v3float %userVertices %int_0 [[providx:%\d+]] %int_2
|
|
|
+ prims[pid].primcolor = float4(userVertices[providx].color, 1.0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|