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:
steve-lunarg
2017-05-02 20:14:50 -06:00
parent de1cc06c1d
commit f1709e7146
17 changed files with 334 additions and 17 deletions

View File

@@ -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::LoopControlMask TranslateLoopControl(glslang::TLoopControl) const;
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
spv::Id getSampledType(const glslang::TSampler&);
spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
@@ -767,6 +768,18 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
}
}
spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(glslang::TLoopControl loopControl) const
{
switch (loopControl) {
case glslang::ELoopControlNone: return spv::LoopControlMaskNone;
case glslang::ELoopControlUnroll: return spv::LoopControlUnrollMask;
case glslang::ELoopControlDontUnroll: return spv::LoopControlDontUnrollMask;
// TODO: DependencyInfinite
// TODO: DependencyLength
default: return spv::LoopControlMaskNone;
}
}
// Return whether or not the given type is something that should be tied to a
// descriptor set.
bool IsDescriptorResource(const glslang::TType& type)
@@ -1960,6 +1973,12 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
{
auto blocks = builder.makeNewLoop();
builder.createBranch(&blocks.head);
// Loop control:
const spv::LoopControlMask control = TranslateLoopControl(node->getLoopControl());
// TODO: dependency length
// 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
// conditions are met. By definition, it will contain OpLoopMerge, followed
@@ -1967,7 +1986,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
// instructions in it, since the body/test may have arbitrary instructions,
// including merges of its own.
builder.setBuildPoint(&blocks.head);
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, spv::LoopControlMaskNone);
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control);
if (node->testFirst() && node->getTest()) {
spv::Block& test = builder.makeNewBlock();
builder.createBranch(&test);