From b9af45ff3f2288e2aa325c1d910544e368eb9538 Mon Sep 17 00:00:00 2001 From: Darren Wihandi <65404740+fairywreath@users.noreply.github.com> Date: Sun, 13 Apr 2025 11:09:01 -0600 Subject: Fix pointer field/member access for GLSL (#6798) * Fix pointer field access for GLSL * Add test * Fix SPIRV test * add spirv via glsl test --- source/slang/slang-emit-glsl.cpp | 12 +++++-- tests/spirv/pointer-2.slang | 76 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 tests/spirv/pointer-2.slang diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index ac98a0a3c..51a22c4e2 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -2139,7 +2139,15 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu EmitOpInfo outerPrec = inOuterPrec; bool needClose = maybeEmitParens(outerPrec, prec); emitOperand(inst->getOperand(0), prec); - m_writer->emit("._data"); + + // `_data` member extraction is not required for `FieldAddress` instructions because + // it is already emitted alongside the user requested field during `FieldAddress` + // emit. See `kIROp_FieldAddress` case below. + if (!as(addr)) + { + m_writer->emit("._data"); + } + maybeCloseParens(needClose); return true; } @@ -2158,7 +2166,7 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu bool needClose = maybeEmitParens(outerPrec, prec); emitOperand(inst->getOperand(0), prec); m_writer->emit("._data."); - emitOperand(inst->getOperand(1), getInfo(EmitOp::General)); + m_writer->emit(getName(as(inst)->getField())); maybeCloseParens(needClose); return true; } diff --git a/tests/spirv/pointer-2.slang b/tests/spirv/pointer-2.slang new file mode 100644 index 000000000..201d97001 --- /dev/null +++ b/tests/spirv/pointer-2.slang @@ -0,0 +1,76 @@ +//TEST:SIMPLE(filecheck=CHECK_SPV): -entry vertexMain -stage vertex -emit-spirv-directly -target spirv +//TEST:SIMPLE(filecheck=CHECK_SPV_VIA_GLSL): -entry vertexMain -stage vertex -emit-spirv-via-glsl -target spirv +//TEST:SIMPLE(filecheck=CHECK_GLSL): -entry vertexMain -stage vertex -target glsl + +struct Inner1 +{ + float4 position; + Inner2* inner; +} + +struct Inner2 +{ + float4 position; +} + +struct Vertex +{ + float4 position; + Inner1* inner; +} + +struct VSOutput +{ + float4 position : SV_Position; +} + +struct PushConstants +{ + float a; + Vertex* verts; +}; + +[[vk::push_constant]] +PushConstants pushConstants; + +ConstantBuffer constantBuffer; + +// CHECK_SPV: OpEntryPoint +// CHECK_SPV: OpTypePointer PhysicalStorageBuffer +// CHECK_SPV: OpPtrAccessChain + +// CHECK_SPV_VIA_GLSL: Glslang +// CHECK_SPV_VIA_GLSL: OpEntryPoint +// CHECK_SPV_VIA_GLSL: OpTypePointer PhysicalStorageBuffer + +[shader("vertex")] +VSOutput vertexMain(int vertexIndex: SV_VertexID) +{ + // + // Test field access chains. + // + + // CHECK_GLSL: (((((pushConstants_0.verts_0 + gl_VertexIndex)._data.inner_1) + 1)._data.inner_0) + 5)._data.position_0 + let position1 = pushConstants.verts[vertexIndex].inner[1].inner[5].position; + + // CHECK_GLSL: (((((constantBuffer_0.verts_0 + 7)._data.inner_1) + 3)._data.inner_0) + 4)._data.position_0 + let position2 = constantBuffer.verts[7].inner[3].inner[4].position; + + // CHECK_GLSL: (((constantBuffer_0.verts_0 + gl_VertexIndex)._data.inner_1) + 12)._data.position_1 + let position3 = constantBuffer.verts[vertexIndex].inner[12].position; + + // + // Test accesing from a variable. + // + + // CHECK_GLSL: ((((pushConstants_0.verts_0 + 8)._data.inner_1 + 6)._data.inner_0))._data.position_0 + let vertex = pushConstants.verts[8]; + let position4 = vertex.inner[6].inner.position; + + VSOutput output; + output.position = position1 + position2 + position3 + position4; + output.position *= pushConstants.a; + + return output; +} + -- cgit v1.2.3