Skip to content

Commit c005fe9

Browse files
Emit OpExecutionMode SpacingEqual for Domain stage (shader-slang#5696)
Domain stage should emit one more `OpExecutionMode` with `SpacingEqual`, similary to how Hull stage does. Currently Hull stage emits four OpExecutionMode as following: OpExecutionMode %hullMain SpacingEqual OpExecutionMode %hullMain OutputVertices 4 OpExecutionMode %hullMain VertexOrderCw OpExecutionMode %hullMain Quads And Domain stage emits only one OpExecutionMode: OpExecutionMode %domainMain Quads This commit adds the following instruction for Domain stage: OpExecutionMode %domainMain SpacingEqual It is because the Vulkan Validation Layer prints error when the Domain shader didn't have `OpeExecutionMode SpacingEqual`. `SpacingEqual` corresponds to an attribute, `[partitioning("integer")]`, given to the Hull stage. Although Domain stage is not marked with same attribute, it is assumed to use the same value used for matching Hull Stage. The error message from VVL is following: ``` vkCreateShadersEXT(): pCreateInfos[2].stage is VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, but spacing is not specified. The Vulkan spec states: If codeType is VK_SHADER_CODE_TYPE_SPIRV_EXT, and stage is VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, pCode must contain an OpExecutionMode instruction specifying the spacing of segments on the edges of tessellated primitives (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-VkShaderCreateInfoEXT-codeType-08874) ``` Co-authored-by: Ellie Hermaszewska <[email protected]>
1 parent 0b92e1d commit c005fe9

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

source/slang/slang-emit-spirv.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -4267,6 +4267,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
42674267
ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_mesh_shader"));
42684268
break;
42694269
case Stage::Hull:
4270+
case Stage::Domain:
42704271
{
42714272
requireSPIRVCapability(SpvCapabilityTessellation);
42724273

@@ -4288,10 +4289,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
42884289
arg);
42894290
}
42904291
requireSPIRVExecutionMode(nullptr, getIRInstSpvID(entryPoint), mode);
4291-
break;
42924292
}
4293-
case Stage::Domain:
4294-
requireSPIRVCapability(SpvCapabilityTessellation);
42954293
break;
42964294
default:
42974295
break;

tests/spirv/tessellation.slang

+49-16
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
//TEST:SIMPLE(filecheck=CHECK): -target spirv
1+
//TEST:SIMPLE(filecheck=HULL): -target spirv -stage hull -entry hullMain
2+
//TEST:SIMPLE(filecheck=DOMAIN): -target spirv -stage domain -entry domainMain
23

3-
// CHECK-DAG: OpExecutionMode %main SpacingEqual
4+
// HULL-DAG: OpExecutionMode %hullMain SpacingEqual
5+
// HULL-DAG: OpExecutionMode %hullMain OutputVertices 4
6+
// HULL-DAG: OpExecutionMode %hullMain VertexOrderCw
7+
// HULL-DAG: OpExecutionMode %hullMain Quads
48

5-
// CHECK-DAG: OpExecutionMode %main OutputVertices 4
9+
// HULL: OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
10+
// HULL: OpDecorate %gl_TessLevelOuter Patch
11+
// HULL: OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
12+
// HULL: OpDecorate %gl_TessLevelInner Patch
613

7-
// CHECK-DAG: OpExecutionMode %main VertexOrderCw
14+
// HULL: OpControlBarrier %uint_2 %uint_4 %uint_0
815

9-
// CHECK-DAG: OpExecutionMode %main Quads
16+
// HULL: OpStore %gl_TessLevelOuter
17+
// HULL: OpStore %gl_TessLevelInner
1018

11-
// CHECK: OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
12-
// CHECK: OpDecorate %gl_TessLevelOuter Patch
13-
// CHECK: OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
14-
// CHECK: OpDecorate %gl_TessLevelInner Patch
15-
16-
// CHECK: OpControlBarrier %uint_2 %uint_4 %uint_0
17-
18-
// CHECK: OpStore %gl_TessLevelOuter
19-
// CHECK: OpStore %gl_TessLevelInner
19+
// DOMAIN-DAG: OpExecutionMode %domainMain SpacingEqual
20+
// DOMAIN-DAG: OpExecutionMode %domainMain Quads
2021

2122
struct VS_OUT
2223
{
@@ -34,13 +35,18 @@ struct HSC_OUT
3435
float InsideTessFactor[2] : SV_InsideTessFactor;
3536
};
3637

38+
struct DS_OUT
39+
{
40+
float4 position : SV_Position;
41+
};
42+
3743
// Hull Shader (HS)
3844
[domain("quad")]
3945
[partitioning("integer")]
4046
[outputtopology("triangle_cw")]
4147
[outputcontrolpoints(4)]
4248
[patchconstantfunc("constants")]
43-
HS_OUT main(InputPatch<VS_OUT, 4> patch, uint i : SV_OutputControlPointID)
49+
HS_OUT hullMain(InputPatch<VS_OUT, 4> patch, uint i : SV_OutputControlPointID)
4450
{
4551
HS_OUT o;
4652
o.position = patch[i].position;
@@ -62,4 +68,31 @@ HSC_OUT constants(InputPatch<VS_OUT, 4> patch)
6268
o.InsideTessFactor[0] = lerp(o.EdgeTessFactor[1], o.EdgeTessFactor[3], 0.5);
6369
o.InsideTessFactor[1] = lerp(o.EdgeTessFactor[0], o.EdgeTessFactor[2], 0.5);
6470
return o;
65-
}
71+
}
72+
73+
[domain("quad")]
74+
DS_OUT domainMain(
75+
float2 uv : SV_DomainLocation, // Tessellated coordinates (u, v)
76+
const OutputPatch<HS_OUT, 4> patch, // Control points from the hull shader
77+
const HSC_OUT patchConstants // Patch constants calculated by the hull shader
78+
)
79+
{
80+
DS_OUT o;
81+
82+
// Interpolate the position of the tessellated point within the patch
83+
float3 p0 = patch[0].position;
84+
float3 p1 = patch[1].position;
85+
float3 p2 = patch[2].position;
86+
float3 p3 = patch[3].position;
87+
88+
// Bilinear interpolation of the position in the quad
89+
float3 interpolatedPosition =
90+
p0 * (1 - uv.x) * (1 - uv.y)
91+
+ p1 * uv.x * (1 - uv.y)
92+
+ p3 * uv.x * uv.y
93+
+ p2 * (1 - uv.x) * uv.y;
94+
95+
// Output final position in clip space
96+
o.position = float4(interpolatedPosition, 1.0);
97+
return o;
98+
}

0 commit comments

Comments
 (0)