From 0460eb6a0b9e62c3145ab9c43d03751e19a49d8e Mon Sep 17 00:00:00 2001 From: Jay Kwak <82421531+jkwak-work@users.noreply.github.com> Date: Wed, 19 Feb 2025 20:43:00 -0800 Subject: Force inline functions that takes InputPatch and OutputPatch (#6407) This commit inlines functions that takes InputPatch and OutputPatch as the function parameter. Co-authored-by: Yong He --- source/slang/slang-ir-specialize-resources.cpp | 4 + source/slang/slang-ir.cpp | 5 ++ tests/spirv/tessellation-patch-as-argument.slang | 100 +++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 tests/spirv/tessellation-patch-as-argument.slang diff --git a/source/slang/slang-ir-specialize-resources.cpp b/source/slang/slang-ir-specialize-resources.cpp index 2aafaaf31..871ba2c24 100644 --- a/source/slang/slang-ir-specialize-resources.cpp +++ b/source/slang/slang-ir-specialize-resources.cpp @@ -1359,6 +1359,10 @@ bool isIllegalGLSLParameterType(IRType* type) return true; if (as(type)) return true; + if (as(type)) + return true; + if (as(type)) + return true; return false; } diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 07e8b2742..cdabb1ac2 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -5259,6 +5259,11 @@ IRInst* IRBuilder::emitElementAddress(IRInst* basePtr, IRInst* index) SLANG_ASSERT(as(index)); type = (IRType*)tupleType->getOperand(getIntVal(index)); } + else if (auto hlslInputPatchType = as(valueType)) + { + type = hlslInputPatchType->getElementType(); + } + SLANG_RELEASE_ASSERT(type); auto inst = createInst( this, diff --git a/tests/spirv/tessellation-patch-as-argument.slang b/tests/spirv/tessellation-patch-as-argument.slang new file mode 100644 index 000000000..685a8d632 --- /dev/null +++ b/tests/spirv/tessellation-patch-as-argument.slang @@ -0,0 +1,100 @@ +//TEST:SIMPLE(filecheck=HULL): -target spirv -stage hull -entry hullMain +//TEST:SIMPLE(filecheck=DOMAIN): -target spirv -stage domain -entry domainMain + +// Testing if `InputPatch` and `OutputPatch` can be used as function arguments. +// `[ForceInline]` can be used to workaround but it should work without it. + +// HULL: OpEntryPoint TessellationControl %hullMain +// HULL: = OpVariable %{{[a-zA-Z_0-9]*}} Input + +// DOMAIN: OpEntryPoint TessellationEvaluation %domainMain +// DOMAIN: = OpVariable %{{[a-zA-Z_0-9]*}} Output + +struct VS_OUT +{ + float3 position : POSITION; +}; + +struct HS_OUT +{ + float3 position : POSITION; +}; + +struct HSC_OUT +{ + float EdgeTessFactor[4] : SV_TessFactor; + float InsideTessFactor[2] : SV_InsideTessFactor; +}; + +struct DS_OUT +{ + float4 position : SV_Position; +}; + + +VS_OUT GetInputPatch(InputPatch patch, int index) +{ + return patch[index]; +} + +// Hull Shader (HS) +[domain("quad")] +[partitioning("integer")] +[outputtopology("triangle_cw")] +[outputcontrolpoints(4)] +[patchconstantfunc("constants")] +HS_OUT hullMain(InputPatch patch, uint i : SV_OutputControlPointID) +{ + HS_OUT o; + o.position = patch[i].position; + return o; +} + +HSC_OUT constants(InputPatch patch) +{ + float3 p0 = GetInputPatch(patch, 0).position; + float3 p1 = patch[1].position; + float3 p2 = patch[2].position; + float3 p3 = patch[3].position; + + HSC_OUT o; + o.EdgeTessFactor[0] = dot(p0, p1); + o.EdgeTessFactor[1] = dot(p0, p3); + o.EdgeTessFactor[2] = dot(p2, p3); + o.EdgeTessFactor[3] = dot(p1, p2); + 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; +} + +HS_OUT GetOutputPatch(const OutputPatch patch, int index) +{ + return patch[index]; +} + +[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 = GetOutputPatch(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; +} -- cgit v1.2.3