diff options
| author | Jay Kwak <82421531+jkwak-work@users.noreply.github.com> | 2024-11-28 23:56:47 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-29 15:56:47 +0800 |
| commit | c005fe9978ec7d432f0a72c0b38f545f215e1244 (patch) | |
| tree | 7ca3a8945cd18e6842aacd1ff2418a325bd1893a | |
| parent | 0b92e1de87cf805888127615457eea906fd0bc39 (diff) | |
Emit OpExecutionMode SpacingEqual for Domain stage (#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 <ellieh@nvidia.com>
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 4 | ||||
| -rw-r--r-- | tests/spirv/tessellation.slang | 65 |
2 files changed, 50 insertions, 19 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 04ddee990..90d0db5d7 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 deb6ed298..9ac5860f9 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<VS_OUT, 4> patch, uint i : SV_OutputControlPointID) +HS_OUT hullMain(InputPatch<VS_OUT, 4> patch, uint i : SV_OutputControlPointID) { HS_OUT o; o.position = patch[i].position; @@ -62,4 +68,31 @@ HSC_OUT constants(InputPatch<VS_OUT, 4> 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<HS_OUT, 4> 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; +} |
