diff options
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 87 | ||||
| -rw-r--r-- | source/slang/slang-ir-translate-glsl-global-var.cpp | 33 | ||||
| -rw-r--r-- | tests/glsl/interface-block.glsl | 37 |
3 files changed, 121 insertions, 36 deletions
diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index 3ca441f96..67300dbe6 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -2923,6 +2923,22 @@ void tryReplaceUsesOfStageInput( fieldVal = element.val; break; } + if (auto tupleValType = + as<ScalarizedTupleValImpl>(element.val.impl)) + { + for (auto tupleElement : tupleValType->elements) + { + if (tupleElement.key == fieldKey) + { + fieldVal = tupleElement.val; + break; + } + } + } + if (fieldVal.flavor != ScalarizedVal::Flavor::none) + { + break; + } } if (fieldVal.flavor != ScalarizedVal::Flavor::none) { @@ -3290,45 +3306,54 @@ void legalizeEntryPointParameterForGLSL( if (dec->getOp() != kIROp_GlobalVariableShadowingGlobalParameterDecoration) continue; auto globalVar = dec->getOperand(0); - auto key = dec->getOperand(1); - IRInst* realGlobalVar = nullptr; - if (globalValue.flavor != ScalarizedVal::Flavor::tuple) - continue; - if (auto tupleVal = as<ScalarizedTupleValImpl>(globalValue.impl)) + auto globalVarType = cast<IRPtrTypeBase>(globalVar->getDataType())->getValueType(); + if (as<IRStructType>(globalVarType)) { - for (auto elem : tupleVal->elements) - { - if (elem.key == key) - { - realGlobalVar = elem.val.irValue; - break; - } - } + tryReplaceUsesOfStageInput(context, globalValue, globalVar); } - SLANG_ASSERT(realGlobalVar); + else + { - // Remove all stores into the global var introduced during - // the initial glsl global var translation pass since we are - // going to replace the global var with a pointer to the real - // input, and it makes no sense to store values into such real - // input locations. - traverseUses( - globalVar, - [&](IRUse* use) + auto key = dec->getOperand(1); + IRInst* realGlobalVar = nullptr; + if (globalValue.flavor != ScalarizedVal::Flavor::tuple) + continue; + if (auto tupleVal = as<ScalarizedTupleValImpl>(globalValue.impl)) { - auto user = use->getUser(); - if (auto store = as<IRStore>(user)) + for (auto elem : tupleVal->elements) { - if (store->getPtrUse() == use) + if (elem.key == key) { - store->removeAndDeallocate(); + realGlobalVar = elem.val.irValue; + break; } } - }); - // we will be replacing uses of `globalVarToReplace`. We need - // globalVarToReplaceNextUse to catch the next use before it is removed from the - // list of uses. - globalVar->replaceUsesWith(realGlobalVar); + } + SLANG_ASSERT(realGlobalVar); + + // Remove all stores into the global var introduced during + // the initial glsl global var translation pass since we are + // going to replace the global var with a pointer to the real + // input, and it makes no sense to store values into such real + // input locations. + traverseUses( + globalVar, + [&](IRUse* use) + { + auto user = use->getUser(); + if (auto store = as<IRStore>(user)) + { + if (store->getPtrUse() == use) + { + store->removeAndDeallocate(); + } + } + }); + // we will be replacing uses of `globalVarToReplace`. We need + // globalVarToReplaceNextUse to catch the next use before it is removed from the + // list of uses. + globalVar->replaceUsesWith(realGlobalVar); + } globalVar->removeAndDeallocate(); } } diff --git a/source/slang/slang-ir-translate-glsl-global-var.cpp b/source/slang/slang-ir-translate-glsl-global-var.cpp index 7b2b8d1ee..80ed3c3e4 100644 --- a/source/slang/slang-ir-translate-glsl-global-var.cpp +++ b/source/slang/slang-ir-translate-glsl-global-var.cpp @@ -83,8 +83,26 @@ struct GlobalVarTranslationContext auto key = builder.createStructKey(); inputKeys.add(key); builder.createStructField(inputStructType, key, inputType); - IRTypeLayout::Builder fieldTypeLayout(&builder); - IRVarLayout::Builder varLayoutBuilder(&builder, fieldTypeLayout.build()); + + IRTypeLayout::Builder fieldTypeLayoutBuilder(&builder); + IRTypeLayout* fieldTypeLayout = nullptr; + bool hasExistingLayout = false; + if (auto existingLayoutDecoration = input->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 = input->findDecoration<IRSemanticDecoration>()) { @@ -94,9 +112,12 @@ struct GlobalVarTranslationContext } else { - fieldTypeLayout.addResourceUsage( - LayoutResourceKind::VaryingInput, - LayoutSize(1)); + if (!hasExistingLayout) + { + fieldTypeLayoutBuilder.addResourceUsage( + LayoutResourceKind::VaryingInput, + LayoutSize(1)); + } if (auto layoutDecor = findVarLayout(input)) { if (auto offsetAttr = @@ -137,6 +158,8 @@ struct GlobalVarTranslationContext auto input = inputVars[i]; setInsertBeforeOrdinaryInst(&builder, firstBlock->getFirstOrdinaryInst()); auto inputType = cast<IRPtrTypeBase>(input->getDataType())->getValueType(); + // TODO: This could be more efficient as a Load(FieldAddress(inputParam, i)) + // operation instead of a FieldExtract(Load(inputParam)). builder.emitStore( input, builder diff --git a/tests/glsl/interface-block.glsl b/tests/glsl/interface-block.glsl new file mode 100644 index 000000000..3d18db6c7 --- /dev/null +++ b/tests/glsl/interface-block.glsl @@ -0,0 +1,37 @@ +//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: layout(location = 0) +//CHECK_GLSL: in vec2 vd_texcoord_0_0; + +//CHECK_GLSL: layout(location = 1) +//CHECK_GLSL: in vec2 vd_texcoord_1_0; + +//CHECK_GLSL: layout(location = 2) +//CHECK_GLSL: in vec4 vd_inner_texcoord_2_0; + +import glsl; + +#version 400 + +struct innerData +{ + vec4 texcoord_2; +}; + +in VertexData +{ + vec2 texcoord_0; + vec2 texcoord_1; + innerData inner; +} vd; + +out vec4 out1; + +void fragmentMain() +{ + out1 = vec4(vd.texcoord_0, vd.texcoord_1.x, vd.inner.texcoord_2.y); +} + |
