diff options
| author | Julius Ikkala <julius.ikkala@gmail.com> | 2025-09-23 06:17:01 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-23 03:17:01 +0000 |
| commit | 9e34c6d949e97fc87a0a7be4ab37092b586aee9d (patch) | |
| tree | dee1891fc3e5a2e0633d8d367747b932d9bf9922 | |
| parent | c35b763f811298a6e9c61a4a8eaf805ea98bd608 (diff) | |
Fix varying output structs in GLSL source (#8501)
Closes #8500.
`slang-ir-translate-global-varying-var.cpp` turns the global varying
outputs into a struct that's returned from the entry point. Currently,
there's a problem when one of the outputs is a struct. It always creates
a generic `IRTypeLayout`, even when a correct type layout already
exists. Somehow, this appears to work when the global varying outputs
aren't structs.
The crash occurs in
`slang-ir-glsl-legalize.cpp:createGLSLGlobalVaryingsImpl()`. It
correctly handles the generated outer struct, but when that contains an
inner struct, it's been given a non-struct type layout and crashes.
This PR uses the correct layout if found, instead of generating a broken
placeholder. This matches the behaviour that has already been
implemented for inputs.
Additionally, I removed a call to `addResourceUsage` from both the input
and output side. I can't see any way in which it would've affected
anything, the layout builder is never used after that call and it
doesn't retroactively modify the layout that was already created.
| -rw-r--r-- | source/slang/slang-ir-translate-global-varying-var.cpp | 33 | ||||
| -rw-r--r-- | tests/glsl/interface-block.glsl | 14 |
2 files changed, 32 insertions, 15 deletions
diff --git a/source/slang/slang-ir-translate-global-varying-var.cpp b/source/slang/slang-ir-translate-global-varying-var.cpp index c899de653..6b8c4842b 100644 --- a/source/slang/slang-ir-translate-global-varying-var.cpp +++ b/source/slang/slang-ir-translate-global-varying-var.cpp @@ -184,13 +184,6 @@ struct GlobalVarTranslationContext } else { - if (!hasExistingLayout) - { - fieldTypeLayoutBuilder.addResourceUsage( - LayoutResourceKind::VaryingInput, - LayoutSize(1)); - } - // Start off the offset as nextOffset. If the global "in"s have existing // offsetAttr's, we will add the offsets from those as well. auto resInfo = @@ -290,8 +283,27 @@ struct GlobalVarTranslationContext auto key = builder.createStructKey(); auto ptrType = as<IRPtrTypeBase>(output->getDataType()); builder.createStructField(resultType, key, ptrType->getValueType()); - IRTypeLayout::Builder fieldTypeLayout(&builder); - IRVarLayout::Builder varLayoutBuilder(&builder, fieldTypeLayout.build()); + + IRTypeLayout::Builder fieldTypeLayoutBuilder(&builder); + IRTypeLayout* fieldTypeLayout = nullptr; + bool hasExistingLayout = false; + if (auto existingLayoutDecoration = + output->findDecoration<IRLayoutDecoration>()) + { + if (auto existingVarLayout = + as<IRVarLayout>(existingLayoutDecoration->getLayout())) + { + fieldTypeLayout = existingVarLayout->getTypeLayout(); + hasExistingLayout = true; + } + } + + if (!hasExistingLayout) + { + fieldTypeLayout = fieldTypeLayoutBuilder.build(); + } + + IRVarLayout::Builder varLayoutBuilder(&builder, fieldTypeLayout); varLayoutBuilder.setStage(entryPointDecor->getProfile().getStage()); if (auto semanticDecor = output->findDecoration<IRSemanticDecoration>()) { @@ -301,9 +313,6 @@ struct GlobalVarTranslationContext } else { - fieldTypeLayout.addResourceUsage( - LayoutResourceKind::VaryingOutput, - LayoutSize(1)); if (auto layoutDecor = findVarLayout(output)) { if (auto offsetAttr = diff --git a/tests/glsl/interface-block.glsl b/tests/glsl/interface-block.glsl index 3d18db6c7..8378de7bf 100644 --- a/tests/glsl/interface-block.glsl +++ b/tests/glsl/interface-block.glsl @@ -1,7 +1,10 @@ //TEST:SIMPLE(filecheck=CHECK_GLSL): -target glsl -stage fragment -entry fragmentMain -allow-glsl //CHECK_GLSL: layout(location = 0) -//CHECK_GLSL: out vec4 entryPointParam_fragmentMain_out1_0; +//CHECK_GLSL: out vec4 entryPointParam_fragmentMain_cd_out1_0; + +//CHECK_GLSL: layout(location = 1) +//CHECK_GLSL: out vec4 entryPointParam_fragmentMain_cd_out2_0; //CHECK_GLSL: layout(location = 0) //CHECK_GLSL: in vec2 vd_texcoord_0_0; @@ -28,10 +31,15 @@ in VertexData innerData inner; } vd; -out vec4 out1; +out ColorData +{ + vec4 out1; + vec4 out2; +} cd; void fragmentMain() { - out1 = vec4(vd.texcoord_0, vd.texcoord_1.x, vd.inner.texcoord_2.y); + cd.out1 = vec4(vd.texcoord_0, vd.texcoord_1.x, vd.inner.texcoord_2.y); + cd.out2 = vec4(vd.texcoord_1, vd.texcoord_0.x, vd.inner.texcoord_2.y); } |
