From b16d4e955fdba3d68d156f944260f8b7a157fd4d Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 22 Jul 2025 14:29:57 -0700 Subject: Fix scalar to array conversion for tessellation factors (#7837) * Fix scalar to array conversion for tessellation factors in GLSL legalization Add scalar-to-array conversion support in adaptType() function to handle cases where users declare scalar tessellation factors (e.g., float TessLevelInner) but GLSL requires arrays (float[2] for gl_TessLevelInner). This prevents the generation of BuiltinCast instructions that crash the SPIR-V emitter. Fixes crash: "unimplemented: Unhandled local inst in spirv-emit: BuiltinCast" - Add scalar-to-array case in slang-ir-glsl-legalize.cpp adaptType() - Fill all array elements with the scalar value for tessellation factors - Add test case for scalar tessellation factor conversion Fixes #7000 Co-authored-by: Yong He * Apply review feedback fixes - Change test directive to TEST:SIMPLE - Use IRArrayType instead of IRArrayTypeBase - Use MakeArrayFromElement for cleaner scalar-to-array conversion Co-authored-by: Yong He * Fix type conversion in scalar-to-array tessellation factor conversion Convert scalar value to array element type before creating array to handle cases where scalar type differs from array element type (e.g., int to float[3]). Co-authored-by: Yong He * Use CHECK-DAG for order-independent tessellation factor checks Co-authored-by: Yong He --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Yong He --- source/slang/slang-ir-glsl-legalize.cpp | 12 +++++ .../tessellation/scalar-tessellation-factor.slang | 52 ++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 tests/pipeline/tessellation/scalar-tessellation-factor.slang diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index f001384a4..ac4d5c336 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -2094,6 +2094,18 @@ ScalarizedVal adaptType(IRBuilder* builder, IRInst* val, IRType* toType, IRType* } } } + else if (auto toArray = as(toType)) + { + // Handle scalar-to-array conversion for tessellation factors + if (as(fromType)) + { + // Convert the scalar value to the array's element type first + auto arrayElementType = toArray->getElementType(); + auto convertedVal = builder->emitCast(arrayElementType, val); + val = builder->emitMakeArrayFromElement(toType, convertedVal); + return ScalarizedVal::value(val); + } + } // TODO: actually consider what needs to go on here... return ScalarizedVal::value(builder->emitCast(toType, val)); } diff --git a/tests/pipeline/tessellation/scalar-tessellation-factor.slang b/tests/pipeline/tessellation/scalar-tessellation-factor.slang new file mode 100644 index 000000000..9fc97732d --- /dev/null +++ b/tests/pipeline/tessellation/scalar-tessellation-factor.slang @@ -0,0 +1,52 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -stage hull -entry hullMain -warnings-disable 39001 + +// Test for issue #7000: scalar tessellation factors should convert to arrays properly + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 Normal; + float2 UV; +}; + +struct HSOutput +{ + float4 Pos : SV_POSITION; + float3 Normal; + float2 UV; +}; + +struct ConstantsHSOutput +{ + float TessLevelOuter[3] : SV_TessFactor; + float TessLevelInner : SV_InsideTessFactor; // Scalar (should convert to float[2] for GLSL) +}; + +ConstantsHSOutput ConstantsHS() +{ + ConstantsHSOutput output; + output.TessLevelInner = 4.0; + output.TessLevelOuter[0] = 4.0; + output.TessLevelOuter[1] = 4.0; + output.TessLevelOuter[2] = 4.0; + return output; +} + +[shader("hull")] +[domain("tri")] +[partitioning("integer")] +[outputtopology("triangle_cw")] +[outputcontrolpoints(3)] +[patchconstantfunc("ConstantsHS")] +HSOutput hullMain(InputPatch patch, uint InvocationID: SV_OutputControlPointID) +{ + HSOutput output; + output.Pos = patch[InvocationID].Pos; + output.Normal = patch[InvocationID].Normal; + output.UV = patch[InvocationID].UV; + return output; +} + +// CHECK: OpExecutionMode +// CHECK-DAG: OpDecorate {{.*}} BuiltIn TessLevelInner +// CHECK-DAG: OpDecorate {{.*}} BuiltIn TessLevelOuter \ No newline at end of file -- cgit v1.2.3