HLSL: Translate directive [flatten] and [branch] to SPV control mask.
This commit is contained in:
parent
423fae4858
commit
57e65929e4
15 changed files with 92 additions and 35 deletions
|
|
@ -122,6 +122,7 @@ protected:
|
|||
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
|
||||
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
|
||||
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
|
||||
spv::SelectionControlMask TranslateSelectionControl(glslang::TSelectionControl) const;
|
||||
spv::LoopControlMask TranslateLoopControl(glslang::TLoopControl) const;
|
||||
spv::StorageClass TranslateStorageClass(const glslang::TType&);
|
||||
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
|
||||
|
|
@ -741,6 +742,16 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
|
|||
}
|
||||
}
|
||||
|
||||
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(glslang::TSelectionControl selectionControl) const
|
||||
{
|
||||
switch (selectionControl) {
|
||||
case glslang::ESelectionControlNone: return spv::SelectionControlMaskNone;
|
||||
case glslang::ESelectionControlFlatten: return spv::SelectionControlFlattenMask;
|
||||
case glslang::ESelectionControlDontFlatten: return spv::SelectionControlDontFlattenMask;
|
||||
default: return spv::SelectionControlMaskNone;
|
||||
}
|
||||
}
|
||||
|
||||
spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(glslang::TLoopControl loopControl) const
|
||||
{
|
||||
switch (loopControl) {
|
||||
|
|
@ -1941,8 +1952,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||
return false;
|
||||
}
|
||||
|
||||
// Instead, emit control flow...
|
||||
|
||||
// Instead, emit control flow...
|
||||
// Don't handle results as temporaries, because there will be two names
|
||||
// and better to leave SSA to later passes.
|
||||
spv::Id result = (node->getBasicType() == glslang::EbtVoid)
|
||||
|
|
@ -1952,8 +1962,11 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||
// emit the condition before doing anything with selection
|
||||
node->getCondition()->traverse(this);
|
||||
|
||||
// Selection control:
|
||||
const spv::SelectionControlMask control = TranslateSelectionControl(node->getSelectionControl());
|
||||
|
||||
// make an "if" based on the value created by the condition
|
||||
spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), builder);
|
||||
spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), control, builder);
|
||||
|
||||
// emit the "then" statement
|
||||
if (node->getTrueBlock() != nullptr) {
|
||||
|
|
@ -1991,6 +2004,9 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
|
|||
node->getCondition()->traverse(this);
|
||||
spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType());
|
||||
|
||||
// Selection control:
|
||||
const spv::SelectionControlMask control = TranslateSelectionControl(node->getSelectionControl());
|
||||
|
||||
// browse the children to sort out code segments
|
||||
int defaultSegment = -1;
|
||||
std::vector<TIntermNode*> codeSegments;
|
||||
|
|
@ -2016,7 +2032,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
|
|||
|
||||
// make the switch statement
|
||||
std::vector<spv::Block*> segmentBlocks; // returned, as the blocks allocated in the call
|
||||
builder.makeSwitch(selector, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
|
||||
builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
|
||||
|
||||
// emit all the code in the segments
|
||||
breakForLoop.push(false);
|
||||
|
|
@ -5707,7 +5723,7 @@ spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslan
|
|||
leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId);
|
||||
|
||||
// make an "if" based on the left value
|
||||
spv::Builder::If ifBuilder(leftId, builder);
|
||||
spv::Builder::If ifBuilder(leftId, spv::SelectionControlMaskNone, builder);
|
||||
|
||||
// emit right operand as the "then" part of the "if"
|
||||
builder.clearAccessChain();
|
||||
|
|
|
|||
|
|
@ -2009,9 +2009,10 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
|
|||
}
|
||||
|
||||
// Comments in header
|
||||
Builder::If::If(Id cond, Builder& gb) :
|
||||
Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) :
|
||||
builder(gb),
|
||||
condition(cond),
|
||||
control(ctrl),
|
||||
elseBlock(0)
|
||||
{
|
||||
function = &builder.getBuildPoint()->getParent();
|
||||
|
|
@ -2052,7 +2053,7 @@ void Builder::If::makeEndIf()
|
|||
|
||||
// Go back to the headerBlock and make the flow control split
|
||||
builder.setBuildPoint(headerBlock);
|
||||
builder.createSelectionMerge(mergeBlock, SelectionControlMaskNone);
|
||||
builder.createSelectionMerge(mergeBlock, control);
|
||||
if (elseBlock)
|
||||
builder.createConditionalBranch(condition, thenBlock, elseBlock);
|
||||
else
|
||||
|
|
@ -2064,7 +2065,7 @@ void Builder::If::makeEndIf()
|
|||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::makeSwitch(Id selector, int numSegments, const std::vector<int>& caseValues,
|
||||
void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector<int>& caseValues,
|
||||
const std::vector<int>& valueIndexToSegment, int defaultSegment,
|
||||
std::vector<Block*>& segmentBlocks)
|
||||
{
|
||||
|
|
@ -2077,7 +2078,7 @@ void Builder::makeSwitch(Id selector, int numSegments, const std::vector<int>& c
|
|||
Block* mergeBlock = new Block(getUniqueId(), function);
|
||||
|
||||
// make and insert the switch's selection-merge instruction
|
||||
createSelectionMerge(mergeBlock, SelectionControlMaskNone);
|
||||
createSelectionMerge(mergeBlock, control);
|
||||
|
||||
// make the switch instruction
|
||||
Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ public:
|
|||
// Helper to use for building nested control flow with if-then-else.
|
||||
class If {
|
||||
public:
|
||||
If(Id condition, Builder& builder);
|
||||
If(Id condition, unsigned int ctrl, Builder& builder);
|
||||
~If() {}
|
||||
|
||||
void makeBeginElse();
|
||||
|
|
@ -397,6 +397,7 @@ public:
|
|||
|
||||
Builder& builder;
|
||||
Id condition;
|
||||
unsigned int control;
|
||||
Function* function;
|
||||
Block* headerBlock;
|
||||
Block* thenBlock;
|
||||
|
|
@ -416,7 +417,7 @@ public:
|
|||
// Returns the right set of basic blocks to start each code segment with, so that the caller's
|
||||
// recursion stack can hold the memory for it.
|
||||
//
|
||||
void makeSwitch(Id condition, int numSegments, const std::vector<int>& caseValues,
|
||||
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
|
||||
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
|
||||
|
||||
// Add a branch to the innermost switch's merge block.
|
||||
|
|
|
|||
|
|
@ -637,13 +637,15 @@ const char* SelectControlString(int cont)
|
|||
}
|
||||
}
|
||||
|
||||
const int LoopControlCeiling = 2;
|
||||
const int LoopControlCeiling = 4;
|
||||
|
||||
const char* LoopControlString(int cont)
|
||||
{
|
||||
switch (cont) {
|
||||
case 0: return "Unroll";
|
||||
case 1: return "DontUnroll";
|
||||
case 2: return "DependencyInfinite";
|
||||
case 3: return "DependencyLength";
|
||||
|
||||
case LoopControlCeiling:
|
||||
default: return "Bad";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue