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
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 9e5676d..cb48d34 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -122,6 +122,7 @@
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::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 @@
{
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 @@
// 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);