HLSL: implement [unroll] and [loop] attributes
This adds infrastructure suitable for any front end to create SPIR-V loop control flags. The only current front end doing so is HLSL. [unroll] turns into spv::LoopControlUnrollMask [loop] turns into spv::LoopControlDontUnrollMask no specification means spv::LoopControlMaskNone
This commit is contained in:
@@ -80,6 +80,8 @@ namespace glslang {
|
||||
return EatPatchConstantFunc;
|
||||
else if (lowername == "unroll")
|
||||
return EatUnroll;
|
||||
else if (lowername == "loop")
|
||||
return EatLoop;
|
||||
else
|
||||
return EatNone;
|
||||
}
|
||||
@@ -107,4 +109,10 @@ namespace glslang {
|
||||
return (entry == attributes.end()) ? nullptr : entry->second;
|
||||
}
|
||||
|
||||
// True if entry exists in map (even if value is nullptr)
|
||||
bool TAttributeMap::contains(TAttributeType attr) const
|
||||
{
|
||||
return attributes.find(attr) != attributes.end();
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
@@ -62,6 +62,7 @@ namespace glslang {
|
||||
EatPatchConstantFunc,
|
||||
EatPatchSize,
|
||||
EatUnroll,
|
||||
EatLoop,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,6 +87,9 @@ namespace glslang {
|
||||
// Const lookup: search for (but do not modify) the attribute in the map.
|
||||
const TIntermAggregate* operator[](TAttributeType) const;
|
||||
|
||||
// True if entry exists in map (even if value is nullptr)
|
||||
bool contains(TAttributeType) const;
|
||||
|
||||
protected:
|
||||
// Find an attribute enum given its name.
|
||||
static TAttributeType attributeFromName(const TString&);
|
||||
|
||||
@@ -3127,7 +3127,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
|
||||
case EHTokFor:
|
||||
case EHTokDo:
|
||||
case EHTokWhile:
|
||||
return acceptIterationStatement(statement);
|
||||
return acceptIterationStatement(statement, attributes);
|
||||
|
||||
case EHTokContinue:
|
||||
case EHTokBreak:
|
||||
@@ -3336,7 +3336,7 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
|
||||
// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
|
||||
//
|
||||
// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
|
||||
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
|
||||
{
|
||||
TSourceLoc loc = token.loc;
|
||||
TIntermTyped* condition = nullptr;
|
||||
@@ -3346,6 +3346,8 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
|
||||
// WHILE or DO or FOR
|
||||
advanceToken();
|
||||
|
||||
const TLoopControl control = parseContext.handleLoopControl(attributes);
|
||||
|
||||
switch (loop) {
|
||||
case EHTokWhile:
|
||||
@@ -3370,7 +3372,7 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
parseContext.unnestLooping();
|
||||
parseContext.popScope();
|
||||
|
||||
statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
|
||||
statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -3402,7 +3404,7 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
|
||||
parseContext.unnestLooping();
|
||||
|
||||
statement = intermediate.addLoop(statement, condition, 0, false, loc);
|
||||
statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -3451,7 +3453,7 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
return false;
|
||||
}
|
||||
|
||||
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
|
||||
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
|
||||
|
||||
parseContext.popScope();
|
||||
parseContext.unnestLooping();
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace glslang {
|
||||
void acceptAttributes(TAttributeMap&);
|
||||
bool acceptSelectionStatement(TIntermNode*&);
|
||||
bool acceptSwitchStatement(TIntermNode*&);
|
||||
bool acceptIterationStatement(TIntermNode*&);
|
||||
bool acceptIterationStatement(TIntermNode*&, const TAttributeMap&);
|
||||
bool acceptJumpStatement(TIntermNode*&);
|
||||
bool acceptCaseLabel(TIntermNode*&);
|
||||
bool acceptDefaultLabel(TIntermNode*&);
|
||||
|
||||
@@ -7568,6 +7568,20 @@ bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayout
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop hints
|
||||
//
|
||||
TLoopControl HlslParseContext::handleLoopControl(const TAttributeMap& attributes) const
|
||||
{
|
||||
if (attributes.contains(EatUnroll))
|
||||
return ELoopControlUnroll;
|
||||
else if (attributes.contains(EatLoop))
|
||||
return ELoopControlDontUnroll;
|
||||
else
|
||||
return ELoopControlNone;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Updating default qualifier for the case of a declaration with just a qualifier,
|
||||
// no type, block, or identifier.
|
||||
|
||||
@@ -192,6 +192,9 @@ public:
|
||||
bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
||||
bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
||||
|
||||
// Determine loop control from attributes
|
||||
TLoopControl handleLoopControl(const TAttributeMap& attributes) const;
|
||||
|
||||
// Potentially rename shader entry point function
|
||||
void renameShaderFunction(const TString*& name) const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user