SPV 1.4: Implement the 5 new loop controls.

This commit is contained in:
John Kessenich
2019-01-12 17:31:41 +07:00
parent 0c1e71a123
commit 1f4d04687b
12 changed files with 312 additions and 35 deletions

View File

@@ -135,7 +135,7 @@ protected:
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const;
spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, unsigned int& dependencyLength) const;
spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector<unsigned int>& operands) const;
spv::StorageClass TranslateStorageClass(const glslang::TType&);
void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType);
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
@@ -1055,7 +1055,7 @@ spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const g
// return a non-0 dependency if the dependency argument must be set
spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode,
unsigned int& dependencyLength) const
std::vector<unsigned int>& operands) const
{
spv::LoopControlMask control = spv::LoopControlMaskNone;
@@ -1067,7 +1067,29 @@ spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang:
control = control | spv::LoopControlDependencyInfiniteMask;
else if (loopNode.getLoopDependency() > 0) {
control = control | spv::LoopControlDependencyLengthMask;
dependencyLength = loopNode.getLoopDependency();
operands.push_back((unsigned int)loopNode.getLoopDependency());
}
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
if (loopNode.getMinIterations() > 0) {
control = control | spv::LoopControlMinIterationsMask;
operands.push_back(loopNode.getMinIterations());
}
if (loopNode.getMaxIterations() < glslang::TIntermLoop::iterationsInfinite) {
control = control | spv::LoopControlMaxIterationsMask;
operands.push_back(loopNode.getMaxIterations());
}
if (loopNode.getIterationMultiple() > 1) {
control = control | spv::LoopControlIterationMultipleMask;
operands.push_back(loopNode.getIterationMultiple());
}
if (loopNode.getPeelCount() > 0) {
control = control | spv::LoopControlPeelCountMask;
operands.push_back(loopNode.getPeelCount());
}
if (loopNode.getPartialCount() > 0) {
control = control | spv::LoopControlPartialCountMask;
operands.push_back(loopNode.getPartialCount());
}
}
return control;
@@ -2841,8 +2863,8 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
builder.createBranch(&blocks.head);
// Loop control:
unsigned int dependencyLength = glslang::TIntermLoop::dependencyInfinite;
const spv::LoopControlMask control = TranslateLoopControl(*node, dependencyLength);
std::vector<unsigned int> operands;
const spv::LoopControlMask control = TranslateLoopControl(*node, operands);
// Spec requires back edges to target header blocks, and every header block
// must dominate its merge block. Make a header block first to ensure these
@@ -2852,7 +2874,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
// including merges of its own.
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
builder.setBuildPoint(&blocks.head);
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, dependencyLength);
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
if (node->testFirst() && node->getTest()) {
spv::Block& test = builder.makeNewBlock();
builder.createBranch(&test);

View File

@@ -2956,14 +2956,14 @@ void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
}
void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
unsigned int dependencyLength)
const std::vector<unsigned int>& operands)
{
Instruction* merge = new Instruction(OpLoopMerge);
merge->addIdOperand(mergeBlock->getId());
merge->addIdOperand(continueBlock->getId());
merge->addImmediateOperand(control);
if ((control & LoopControlDependencyLengthMask) != 0)
merge->addImmediateOperand(dependencyLength);
for (int op = 0; op < (int)operands.size(); ++op)
merge->addImmediateOperand(operands[op]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
}

View File

@@ -662,7 +662,7 @@ public:
void createBranch(Block* block);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, unsigned int dependencyLength);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands);
// Sets to generate opcode for specialization constants.
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }

View File

@@ -674,15 +674,20 @@ const char* SelectControlString(int cont)
}
}
const int LoopControlCeiling = 4;
const int LoopControlCeiling = LoopControlPartialCountShift + 1;
const char* LoopControlString(int cont)
{
switch (cont) {
case 0: return "Unroll";
case 1: return "DontUnroll";
case 2: return "DependencyInfinite";
case 3: return "DependencyLength";
case LoopControlUnrollShift: return "Unroll";
case LoopControlDontUnrollShift: return "DontUnroll";
case LoopControlDependencyInfiniteShift: return "DependencyInfinite";
case LoopControlDependencyLengthShift: return "DependencyLength";
case LoopControlMinIterationsShift: return "MinIterations";
case LoopControlMaxIterationsShift: return "MaxIterations";
case LoopControlIterationMultipleShift: return "IterationMultiple";
case LoopControlPeelCountShift: return "PeelCount";
case LoopControlPartialCountShift: return "PartialCount";
case LoopControlCeiling:
default: return "Bad";