diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 04ddee9909..90d0db5d74 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -4267,6 +4267,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_mesh_shader")); break; case Stage::Hull: + case Stage::Domain: { requireSPIRVCapability(SpvCapabilityTessellation); @@ -4288,10 +4289,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex arg); } requireSPIRVExecutionMode(nullptr, getIRInstSpvID(entryPoint), mode); - break; } - case Stage::Domain: - requireSPIRVCapability(SpvCapabilityTessellation); break; default: break; diff --git a/tests/spirv/tessellation.slang b/tests/spirv/tessellation.slang index deb6ed2989..9ac5860f9f 100644 --- a/tests/spirv/tessellation.slang +++ b/tests/spirv/tessellation.slang @@ -1,22 +1,23 @@ -//TEST:SIMPLE(filecheck=CHECK): -target spirv +//TEST:SIMPLE(filecheck=HULL): -target spirv -stage hull -entry hullMain +//TEST:SIMPLE(filecheck=DOMAIN): -target spirv -stage domain -entry domainMain -// CHECK-DAG: OpExecutionMode %main SpacingEqual +// HULL-DAG: OpExecutionMode %hullMain SpacingEqual +// HULL-DAG: OpExecutionMode %hullMain OutputVertices 4 +// HULL-DAG: OpExecutionMode %hullMain VertexOrderCw +// HULL-DAG: OpExecutionMode %hullMain Quads -// CHECK-DAG: OpExecutionMode %main OutputVertices 4 +// HULL: OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter +// HULL: OpDecorate %gl_TessLevelOuter Patch +// HULL: OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner +// HULL: OpDecorate %gl_TessLevelInner Patch -// CHECK-DAG: OpExecutionMode %main VertexOrderCw +// HULL: OpControlBarrier %uint_2 %uint_4 %uint_0 -// CHECK-DAG: OpExecutionMode %main Quads +// HULL: OpStore %gl_TessLevelOuter +// HULL: OpStore %gl_TessLevelInner -// CHECK: OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter -// CHECK: OpDecorate %gl_TessLevelOuter Patch -// CHECK: OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner -// CHECK: OpDecorate %gl_TessLevelInner Patch - -// CHECK: OpControlBarrier %uint_2 %uint_4 %uint_0 - -// CHECK: OpStore %gl_TessLevelOuter -// CHECK: OpStore %gl_TessLevelInner +// DOMAIN-DAG: OpExecutionMode %domainMain SpacingEqual +// DOMAIN-DAG: OpExecutionMode %domainMain Quads struct VS_OUT { @@ -34,13 +35,18 @@ struct HSC_OUT float InsideTessFactor[2] : SV_InsideTessFactor; }; +struct DS_OUT +{ + float4 position : SV_Position; +}; + // Hull Shader (HS) [domain("quad")] [partitioning("integer")] [outputtopology("triangle_cw")] [outputcontrolpoints(4)] [patchconstantfunc("constants")] -HS_OUT main(InputPatch patch, uint i : SV_OutputControlPointID) +HS_OUT hullMain(InputPatch patch, uint i : SV_OutputControlPointID) { HS_OUT o; o.position = patch[i].position; @@ -62,4 +68,31 @@ HSC_OUT constants(InputPatch patch) o.InsideTessFactor[0] = lerp(o.EdgeTessFactor[1], o.EdgeTessFactor[3], 0.5); o.InsideTessFactor[1] = lerp(o.EdgeTessFactor[0], o.EdgeTessFactor[2], 0.5); return o; -} \ No newline at end of file +} + +[domain("quad")] +DS_OUT domainMain( + float2 uv : SV_DomainLocation, // Tessellated coordinates (u, v) + const OutputPatch patch, // Control points from the hull shader + const HSC_OUT patchConstants // Patch constants calculated by the hull shader +) +{ + DS_OUT o; + + // Interpolate the position of the tessellated point within the patch + float3 p0 = patch[0].position; + float3 p1 = patch[1].position; + float3 p2 = patch[2].position; + float3 p3 = patch[3].position; + + // Bilinear interpolation of the position in the quad + float3 interpolatedPosition = + p0 * (1 - uv.x) * (1 - uv.y) + + p1 * uv.x * (1 - uv.y) + + p3 * uv.x * uv.y + + p2 * (1 - uv.x) * uv.y; + + // Output final position in clip space + o.position = float4(interpolatedPosition, 1.0); + return o; +}