diff options
| author | Lujin Wang <143145775+lujinwangnv@users.noreply.github.com> | 2025-08-22 13:48:20 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-22 20:48:20 +0000 |
| commit | cd9e1f67184c1361558e18993e5cb392dc1131f0 (patch) | |
| tree | 109e42e28618a4db785b474891ba58b2ffb7ee05 | |
| parent | 3ca2e47514e3fce133a6ac7d1aca88a3b679c551 (diff) | |
Fix mesh shader OutputIndices subscript error by adding missing ref accessor (#7929)
Fixes the Slang compiler internal error "subscript had no getter" when
reading from mesh shader output index arrays (e.g., `triangles[0].x`).
## Problem
The `OutputIndices` struct was missing a `ref` accessor in its
`__subscript` implementation, causing the compiler to fail when trying
to materialize subscript expressions as r-values.
## Solution
Added the missing `ref` accessor to `OutputIndices.__subscript` using
the `kIROp_MeshOutputRef` intrinsic operation, matching the pattern used
in `OutputVertices` and `OutputPrimitives`.
## Files Changed
- `source/slang/core.meta.slang` - Added missing `ref` accessor
- `tests/bugs/gh-7925.slang` - Test case to reproduce and verify the fix
Fixes #7925
Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Lujin Wang <lujinwangnv@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: slangbot <ellieh+slangbot@nvidia.com>
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
| -rw-r--r-- | source/slang/core.meta.slang | 5 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 16 | ||||
| -rw-r--r-- | tests/bugs/gh-7925.slang | 54 |
3 files changed, 75 insertions, 0 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 2c6bf04d1..3306403f5 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -2349,6 +2349,11 @@ struct OutputIndices case spirv: __setIndices(this, index, newValue); } } + + // If a 'OutputIndices[index]' is referred to by a '__ref', call 'kIROp_MeshOutputRef(index)' + [require(glsl_hlsl_metal_spirv, meshshading)] + __intrinsic_op($(kIROp_MeshOutputRef)) + ref; } }; diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index d6f4ac176..0facaac3f 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -4032,6 +4032,9 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex case kIROp_GetOffsetPtr: result = emitGetOffsetPtr(parent, inst); break; + case kIROp_MeshOutputRef: + result = emitMeshOutputRef(parent, inst); + break; case kIROp_GetElement: result = emitGetElement(parent, as<IRGetElement>(inst)); break; @@ -7002,6 +7005,19 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex makeArray(inst->getIndex())); } + SpvInst* emitMeshOutputRef(SpvInstParent* parent, IRInst* inst) + { + // MeshOutputRef takes two operands: the mesh output array and the index + // It should return a reference (address) to the element at that index + auto base = inst->getOperand(0); + auto index = inst->getOperand(1); + + const SpvWord baseId = getID(ensureInst(base)); + + // Use OpAccessChain to get the address of the element + return emitOpAccessChain(parent, inst, inst->getFullType(), baseId, makeArray(index)); + } + SpvInst* emitGetElement(SpvInstParent* parent, IRGetElement* inst) { requireVariableBufferCapabilityIfNeeded(inst->getDataType()); diff --git a/tests/bugs/gh-7925.slang b/tests/bugs/gh-7925.slang new file mode 100644 index 000000000..470a039c3 --- /dev/null +++ b/tests/bugs/gh-7925.slang @@ -0,0 +1,54 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -profile sm_6_6 -stage mesh -entry main + +struct MeshOutput +{ + float4 position : SV_Position; + float3 color : COLOR0; +} + +// Uniform variable for time-based animation +uniform uint iTime; + +[shader("mesh")] +[outputtopology("triangle")] +[numthreads(1, 1, 1)] +void main( + in uint tig : SV_GroupIndex, + OutputVertices<MeshOutput, 3> vertices, + OutputIndices<uint3, 1> triangles +) +{ + // Set the number of vertices and primitives + SetMeshOutputCounts(3, 1); + + // Define the triangle indices + triangles[0] = uint3(0, 1, 2); + + // Use uiColor as in the original shader + // This line should now work after the fix - it was causing the "subscript had no getter" error + uint uiColor = triangles[0].x + iTime; + + // Create triangle vertices with time-based animation + float timeOffset = float(iTime) * 0.01; // Convert to float and scale + float colorOffset = float(uiColor) * 0.005; // Use uiColor for color variation + + // Vertex 0 - Red vertex (top) with uiColor influence + vertices[0].position = float4(0.0, 0.5 + sin(timeOffset) * 0.1, 0.0, 1.0); + vertices[0].color = float3(1.0, (sin(colorOffset) + 1.0) * 0.5, 0.0); // Red with green modulation from uiColor + + // Vertex 1 - Green vertex (bottom left) + vertices[1].position = float4(-0.5, -0.5, 0.0, 1.0); + vertices[1].color = float3(0.0, 1.0, 0.0); // Green + + // Vertex 2 - Blue vertex (bottom right) + vertices[2].position = float4(0.5, -0.5, 0.0, 1.0); + vertices[2].color = float3(0.0, 0.0, 1.0); // Blue +} + +// CHECK: OpCapability MeshShadingEXT +// CHECK: OpExtension "SPV_EXT_mesh_shader" +// CHECK: OpEntryPoint MeshEXT %main "main" +// CHECK: OpExecutionMode %main OutputPrimitivesEXT 1 +// CHECK: OpExecutionMode %main OutputVertices 3 +// CHECK: OpExecutionMode %main LocalSize 1 1 1 +// CHECK: OpExecutionMode %main OutputTrianglesEXT |
