diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/core.meta.slang | 5 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 3 | ||||
| -rw-r--r-- | source/slang/slang-ast-modifier.h | 7 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 64 | ||||
| -rw-r--r-- | source/slang/slang-ir-inline.cpp | 20 | ||||
| -rw-r--r-- | source/slang/slang-ir-inline.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 4 |
10 files changed, 78 insertions, 33 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index d8b5c38d3..f8012af1d 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -2636,4 +2636,7 @@ __attributeTarget(FuncDecl) attribute_syntax [DerivativeGroupQuad] : DerivativeGroupQuadAttribute; __attributeTarget(FuncDecl) -attribute_syntax [DerivativeGroupLinear] : DerivativeGroupLinearAttribute;
\ No newline at end of file +attribute_syntax [DerivativeGroupLinear] : DerivativeGroupLinearAttribute; + +__attributeTarget(FuncDecl) +attribute_syntax [noRefInline] : NoRefInlineAttribute;
\ No newline at end of file diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 77a224b61..919796943 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -11580,8 +11580,11 @@ void SetMeshOutputCounts(uint vertexCount, uint primitiveCount) // // This function doesn't return. // +// This function cannot be inlined due to a legalization pass happening mid-way through processing +// and later more processing happening to the function which requires eventual inlining. [KnownBuiltin("DispatchMesh")] [require(glsl_hlsl_spirv, meshshading)] +[noRefInline] void DispatchMesh<P>(uint threadGroupCountX, uint threadGroupCountY, uint threadGroupCountZ, __ref P meshPayload) { __target_switch diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 1126e84ef..9a27b3c06 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -1447,6 +1447,13 @@ class NoInlineAttribute : public Attribute SLANG_AST_CLASS(NoInlineAttribute) }; + /// A `[noRefInline]` attribute represents a request to not force inline a + /// function specifically due to a refType parameter. +class NoRefInlineAttribute : public Attribute +{ + SLANG_AST_CLASS(NoRefInlineAttribute) +}; + class DerivativeGroupQuadAttribute : public Attribute { SLANG_AST_CLASS(DerivativeGroupQuadAttribute) diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 5cfcde0c9..9369afbc5 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -492,7 +492,7 @@ Result linkAndOptimizeIR( { // We could fail because // 1) It's not inlinable for some reason (for example if it's recursive) - SLANG_RETURN_ON_FAIL(performStringInlining(irModule, sink)); + SLANG_RETURN_ON_FAIL(performTypeInlining(irModule, sink)); } lowerReinterpret(targetProgram, irModule, sink); diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index 54af7a746..7a970589e 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -2725,19 +2725,18 @@ void legalizeEntryPointParameterForGLSL( codeGenContext, builder, paramType, paramLayout, LayoutResourceKind::VaryingInput, stage, pp); - // Next we need to replace uses of the parameter with - // references to the variable(s). We are going to do that - // somewhat naively, by simply materializing the - // variables at the start. + // we have a simple struct which represents all materialized GlobalParams, this + // struct will replace the no longer needed global variable which proxied as a + // GlobalParam. IRInst* materialized = materializeValue(builder, globalValue); + // We next need to replace all uses of the proxy variable with the actual GlobalParam pp->replaceUsesWith(materialized); - // We finally need to replace all global variable references of a global - // parameter with the actual global parameter for all function calls. - // Global parameters are used with a OpStore to copy its data into a global - // variable intermediary. We will follow the uses of a global parameter until - // we find this OpStore, then we will replace uses of the intermediary object. + // GlobalParams use use a OpStore to copy its data into a global + // variable intermediary. We will follow the uses of this intermediary + // and replace all some of the uses (function calls and SPIRV Operands) + Dictionary<IRBlock*, IRInst*> blockToMaterialized; IRBuilder replaceBuilder(materialized); for (auto dec : pp->getDecorations()) { @@ -2747,27 +2746,48 @@ void legalizeEntryPointParameterForGLSL( auto globalVarType = cast<IRPtrTypeBase>(globalVar->getDataType())->getValueType(); auto key = dec->getOperand(1); - // we will be replacing uses of `globalVarToReplace`, we need globalVarToReplaceNextUse - // to catch the next use before it is removed from the list of uses + // we will be replacing uses of `globalVarToReplace`. We need globalVarToReplaceNextUse + // to catch the next use before it is removed from the list of uses. IRUse* globalVarToReplaceNextUse; for (auto globalVarUse = globalVar->firstUse; globalVarUse; globalVarUse = globalVarToReplaceNextUse) { globalVarToReplaceNextUse = globalVarUse->nextUse; auto user = globalVarUse->getUser(); - if (user->getOp() != kIROp_Call) - continue; - for (Slang::UInt operandIndex = 0; operandIndex < user->getOperandCount(); - operandIndex++) + switch (user->getOp()) { - auto operand = user->getOperand(operandIndex); - auto operandUse = user->getOperands() + operandIndex; - if (operand != globalVar) - continue; - replaceBuilder.setInsertBefore(user); - auto field = replaceBuilder.emitFieldExtract(globalVarType, materialized, key); - replaceBuilder.replaceOperand(operandUse, field); + case kIROp_SPIRVAsmOperandInst: + case kIROp_Call: + { + for (Slang::UInt operandIndex = 0; operandIndex < user->getOperandCount(); + operandIndex++) + { + auto operand = user->getOperand(operandIndex); + auto operandUse = user->getOperands() + operandIndex; + if (operand != globalVar) + continue; + + // a GlobalParam may be used across functions/blocks, we need to + // materialize at a minimum 1 struct per block. + auto callingBlock = getBlock(user); + bool found = blockToMaterialized.tryGetValue(callingBlock, materialized); + if (!found) + { + replaceBuilder.setInsertBefore(callingBlock->getFirstInst()); + materialized = materializeValue(&replaceBuilder, globalValue); + blockToMaterialized.set(callingBlock, materialized); + } + + replaceBuilder.setInsertBefore(user); + auto field = replaceBuilder.emitFieldExtract(globalVarType, materialized, key); + replaceBuilder.replaceOperand(operandUse, field); + break; + } + break; + } + default: break; } + continue; } } } diff --git a/source/slang/slang-ir-inline.cpp b/source/slang/slang-ir-inline.cpp index a5538425f..1e8c1462f 100644 --- a/source/slang/slang-ir-inline.cpp +++ b/source/slang/slang-ir-inline.cpp @@ -709,15 +709,15 @@ void performMandatoryEarlyInlining(IRModule* module) namespace { // anonymous // Inlines calls that involve String types -struct StringInliningPass : InliningPassBase +struct TypeInliningPass : InliningPassBase { typedef InliningPassBase Super; - StringInliningPass(IRModule* module) + TypeInliningPass(IRModule* module) : Super(module) {} - bool doesTypeRequireInline(IRType* type) + bool doesTypeRequireInline(IRType* type, IRFunc* callee) { // TODO(JS): // I guess there is a question here about what type around string requires @@ -727,6 +727,12 @@ struct StringInliningPass : InliningPassBase const auto op = type->getOp(); switch (op) { + case kIROp_RefType: + { + if(callee->findDecoration<IRNoRefInlineDecoration>()) + return false; + return true; + } case kIROp_StringType: case kIROp_NativeStringType: { @@ -742,7 +748,7 @@ struct StringInliningPass : InliningPassBase { auto callee = info.callee; - if (doesTypeRequireInline(callee->getResultType())) + if (doesTypeRequireInline(callee->getResultType(), callee)) { return true; } @@ -750,7 +756,7 @@ struct StringInliningPass : InliningPassBase const auto count = Count(callee->getParamCount()); for (Index i = 0; i < count; ++i) { - if (doesTypeRequireInline(callee->getParamType(UInt(i)))) + if (doesTypeRequireInline(callee->getParamType(UInt(i)), callee)) { return true; } @@ -762,7 +768,7 @@ struct StringInliningPass : InliningPassBase } // anonymous -Result performStringInlining(IRModule* module, DiagnosticSink* sink) +Result performTypeInlining(IRModule* module, DiagnosticSink* sink) { SLANG_UNUSED(sink); @@ -780,7 +786,7 @@ Result performStringInlining(IRModule* module, DiagnosticSink* sink) // while(true) { - StringInliningPass pass(module); + TypeInliningPass pass(module); if (pass.considerAllCallSites()) { // If there was a change try inlining again diff --git a/source/slang/slang-ir-inline.h b/source/slang/slang-ir-inline.h index a15887b00..c5b457a65 100644 --- a/source/slang/slang-ir-inline.h +++ b/source/slang/slang-ir-inline.h @@ -10,8 +10,8 @@ namespace Slang struct IRGlobalValueWithCode; class DiagnosticSink; - /// Any call to a function that takes or returns a string parameter is inlined - Result performStringInlining(IRModule* module, DiagnosticSink* sink); + /// Any call to a function that takes or returns a string/RefType parameter is inlined + Result performTypeInlining(IRModule* module, DiagnosticSink* sink); /// Inline any call sites to functions marked `[unsafeForceInlineEarly]` void performMandatoryEarlyInlining(IRModule* module); diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 2aad3bf8e..f4954375d 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -862,6 +862,7 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace) /// Applie to an IR function and signals that inlining should not be performed unless unavoidable. INST(NoInlineDecoration, noInline, 0, 0) + INST(NoRefInlineDecoration, noRefInline, 0, 0) INST(DerivativeGroupQuadDecoration, DerivativeGroupQuad, 0, 0) INST(DerivativeGroupLinearDecoration, DerivativeGroupLinear, 0, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 0d66efb14..eae025c96 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -393,6 +393,7 @@ IR_SIMPLE_DECORATION(HLSLExportDecoration) IR_SIMPLE_DECORATION(KeepAliveDecoration) IR_SIMPLE_DECORATION(RequiresNVAPIDecoration) IR_SIMPLE_DECORATION(NoInlineDecoration) +IR_SIMPLE_DECORATION(NoRefInlineDecoration) IR_SIMPLE_DECORATION(DerivativeGroupQuadDecoration) IR_SIMPLE_DECORATION(DerivativeGroupLinearDecoration) IR_SIMPLE_DECORATION(AlwaysFoldIntoUseSiteDecoration) diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index e4fc33e33..a78110a84 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -9738,6 +9738,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> { derivativeGroupLinearDecor = getBuilder()->addSimpleDecoration<IRDerivativeGroupLinearDecoration>(irFunc); } + else if (auto noRefInlineAttribute = as<NoRefInlineAttribute>(modifier)) + { + getBuilder()->addSimpleDecoration<IRNoRefInlineDecoration>(irFunc); + } else if (auto instanceAttr = as<InstanceAttribute>(modifier)) { IRIntLit* intLit = _getIntLitFromAttribute(getBuilder(), instanceAttr); |
