summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-bind-existentials.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-ir-bind-existentials.cpp')
-rw-r--r--source/slang/slang-ir-bind-existentials.cpp92
1 files changed, 48 insertions, 44 deletions
diff --git a/source/slang/slang-ir-bind-existentials.cpp b/source/slang/slang-ir-bind-existentials.cpp
index e426e6e92..a99da3410 100644
--- a/source/slang/slang-ir-bind-existentials.cpp
+++ b/source/slang/slang-ir-bind-existentials.cpp
@@ -69,24 +69,8 @@ struct BindExistentialSlots
void processGlobalExistentialSlots()
{
- // If there are any global existential slots, we will expect
- // to find a `bindGlobalExistentialSlots` instruction at module scope.
- //
- // We will start out by finding that instruction, if it exists.
- //
- IRInst* bindGlobalExistentialSlotsInst = nullptr;
- for( auto inst : module->getGlobalInsts() )
- {
- if( inst->op == kIROp_BindGlobalExistentialSlots )
- {
- bindGlobalExistentialSlotsInst = inst;
- break;
- }
- }
-
- // Now we will start looking for global shader parameters that make
- // use of existential slots (we can determine this from their
- // layout).
+ // We will search for global shader parameters that make
+ // use of existential specialization parameters.
//
for( auto inst : module->getGlobalInsts() )
{
@@ -96,23 +80,27 @@ struct BindExistentialSlots
if(!globalParam)
continue;
- // We will delegate to a subroutine for the meat
- // of the work, since much of it can be shared
- // with the case for entry-point existential
- // parameters.
+ // We only care about global shader parameters
+ // that have existential specialization parameters,
+ // and we expect all such parameters to have a
+ // `[bindExistentialSlots(...)]` decoration that
+ // was added during IR linking.
//
- processParameter(globalParam, bindGlobalExistentialSlotsInst);
- }
+ auto bindSlotsInst = globalParam->findDecorationImpl(kIROp_BindExistentialSlotsDecoration);
+ if(!bindSlotsInst)
+ continue;
- // Once we are done looping over global shader parameters,
- // all of the relevant information from the
- // `bindGlobalExistentialSlots` instruction will have
- // been moved to the parameters themselves, so we
- // can eliminate the binding instruction.
- //
- if( bindGlobalExistentialSlotsInst )
- {
- bindGlobalExistentialSlotsInst->removeAndDeallocate();
+ replaceTypeUsingExistentialSlots(
+ globalParam,
+ bindSlotsInst->getOperandCount(),
+ bindSlotsInst->getOperands());
+
+ // Once we have propagated the information from
+ // the `[bindExistentialSlots(...)]` decoration
+ // down into the parameter's type, we no longer
+ // need the decoration.
+ //
+ bindSlotsInst->removeAndDeallocate();
}
}
@@ -150,9 +138,25 @@ struct BindExistentialSlots
// We then need to process each of the entry-point
// parameters just like we did for global parameters.
//
+ // Because the existential slot arguments for *all* of the parameters
+ // are attached in a single `[bindExistentialSlots(...)]` decoration,
+ // we need to carve them up appropriately across the parameters.
+ // The way we do this is a bit of a kludge, in that we track a
+ // single `slotOffset` and increment it for each parameter by the
+ // number of arguments it consumed.
+ //
+ // Note: a better approach here might rely on the layout information
+ // for the parameters, which should directly encode an offset for
+ // the existential specialization parameters it uses. The challenge
+ // with this is that we'd need to correctly interpret the offset
+ // relative to any global-scope specialization parameters or
+ // generic specialization parameters of the entry point.
+ // Ultimately the simplistic counter approach is less complicated.
+ //
+ Index slotOffset = 0;
for( auto param : func->getParams() )
{
- processParameter(param, bindEntryPointExistentialSlotsInst);
+ processEntryPointParameter(param, bindEntryPointExistentialSlotsInst, slotOffset);
}
// TODO: We would need to consider what to do if
@@ -181,9 +185,10 @@ struct BindExistentialSlots
// function `param` and a `[bindExistentialSlots(...)]`
// decoration; both use the same subroutine.
//
- void processParameter(
+ void processEntryPointParameter(
IRInst* param,
- IRInst* bindSlotsInst)
+ IRInst* bindSlotsInst,
+ Index& ioSlotOperandOffset)
{
// We expect all shader parameters to have layout information,
// but to be defensive we will skip any that don't.
@@ -206,7 +211,6 @@ struct BindExistentialSlots
// find out the stating slot, and the information on
// the type to find out the number of slots.
//
- UInt firstSlot = resInfo->index;
UInt slotCount = 0;
if(auto typeResInfo = varLayout->getTypeLayout()->FindResourceInfo(LayoutResourceKind::ExistentialTypeParam))
slotCount = UInt(typeResInfo->count.getFiniteValue());
@@ -233,7 +237,8 @@ struct BindExistentialSlots
// this parameter.
//
UInt bindOperandCount = bindSlotsInst->getOperandCount();
- if( 2*(firstSlot + slotCount) > bindOperandCount )
+ UInt slotOperandCount = 2*slotCount;
+ if( (ioSlotOperandOffset + slotOperandCount) > bindOperandCount )
{
sink->diagnose(param->sourceLoc, Diagnostics::missingExistentialBindingsForParameter);
return;
@@ -244,7 +249,7 @@ struct BindExistentialSlots
// keeping in mind that each slot accounts for two
// operands.
//
- auto operandsForInst = bindSlotsInst->getOperands() + firstSlot;
+ auto operandsForInst = bindSlotsInst->getOperands() + ioSlotOperandOffset;
// Once we've found the operands that are relevent to
// the slots used by `param`, we will defer to a routine
@@ -253,17 +258,17 @@ struct BindExistentialSlots
//
replaceTypeUsingExistentialSlots(
param,
- slotCount,
+ slotOperandCount,
operandsForInst);
+
+ ioSlotOperandOffset += slotOperandCount;
}
void replaceTypeUsingExistentialSlots(
IRInst* inst,
- UInt slotCount,
+ UInt slotOperandCount,
IRUse const* slotArgs)
{
- SLANG_UNUSED(slotCount);
-
// We are going to alter the type of the
// given `inst` based on information in
// the `slotArgs`.
@@ -282,7 +287,6 @@ struct BindExistentialSlots
// a witness table, so the total number of operands
// is twice the number of slots we are filling.
//
- UInt slotOperandCount = slotCount*2;
List<IRInst*> slotOperands;
for(UInt ii = 0; ii < slotOperandCount; ++ii)
slotOperands.add(slotArgs[ii].get());