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

@ -1116,7 +1116,12 @@ public:
first(testFirst),
unroll(false),
dontUnroll(false),
dependency(0)
dependency(0),
minIterations(0),
maxIterations(iterationsInfinite),
iterationMultiple(1),
peelCount(0),
partialCount(0)
{ }
virtual TIntermLoop* getAsLoopNode() { return this; }
@ -1128,14 +1133,36 @@ public:
bool testFirst() const { return first; }
void setUnroll() { unroll = true; }
void setDontUnroll() { dontUnroll = true; }
void setDontUnroll() {
dontUnroll = true;
peelCount = 0;
partialCount = 0;
}
bool getUnroll() const { return unroll; }
bool getDontUnroll() const { return dontUnroll; }
static const unsigned int dependencyInfinite = 0xFFFFFFFF;
static const unsigned int iterationsInfinite = 0xFFFFFFFF;
void setLoopDependency(int d) { dependency = d; }
int getLoopDependency() const { return dependency; }
void setMinIterations(unsigned int v) { minIterations = v; }
unsigned int getMinIterations() const { return minIterations; }
void setMaxIterations(unsigned int v) { maxIterations = v; }
unsigned int getMaxIterations() const { return maxIterations; }
void setIterationMultiple(unsigned int v) { iterationMultiple = v; }
unsigned int getIterationMultiple() const { return iterationMultiple; }
void setPeelCount(unsigned int v) {
peelCount = v;
dontUnroll = false;
}
unsigned int getPeelCount() const { return peelCount; }
void setPartialCount(unsigned int v) {
partialCount = v;
dontUnroll = false;
}
unsigned int getPartialCount() const { return partialCount; }
protected:
TIntermNode* body; // code to loop over
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
@ -1144,6 +1171,11 @@ protected:
bool unroll; // true if unroll requested
bool dontUnroll; // true if request to not unroll
unsigned int dependency; // loop dependency hint; 0 means not set or unknown
unsigned int minIterations; // as per the SPIR-V specification
unsigned int maxIterations; // as per the SPIR-V specification
unsigned int iterationMultiple; // as per the SPIR-V specification
unsigned int peelCount; // as per the SPIR-V specification
unsigned int partialCount; // as per the SPIR-V specification
};
//

View file

@ -52,6 +52,7 @@ bool TAttributeArgs::getInt(int& value, int argNum) const
return true;
}
// extract strings out of attribute arguments stored in attribute aggregate.
// convert to lower case if converToLower is true (for case-insensitive compare convenience)
bool TAttributeArgs::getString(TString& value, int argNum, bool convertToLower) const
@ -110,6 +111,16 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const
return EatDependencyInfinite;
else if (name == "dependency_length")
return EatDependencyLength;
else if (name == "min_iterations")
return EatMinIterations;
else if (name == "max_iterations")
return EatMaxIterations;
else if (name == "iteration_multiple")
return EatIterationMultiple;
else if (name == "peel_count")
return EatPeelCount;
else if (name == "partial_count")
return EatPartialCount;
else
return EatNone;
}
@ -225,29 +236,101 @@ void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermN
}
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
if (it->name != EatDependencyLength && it->size() > 0) {
warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
continue;
}
int value;
const auto noArgument = [&](const char* feature) {
if (it->size() > 0) {
warn(node->getLoc(), "expected no arguments", feature, "");
return false;
}
return true;
};
const auto positiveSignedArgument = [&](const char* feature, int& value) {
if (it->size() == 1 && it->getInt(value)) {
if (value <= 0) {
error(node->getLoc(), "must be positive", feature, "");
return false;
}
} else {
warn(node->getLoc(), "expected a single integer argument", feature, "");
return false;
}
return true;
};
const auto unsignedArgument = [&](const char* feature, unsigned int& uiValue) {
int value;
if (!(it->size() == 1 && it->getInt(value))) {
warn(node->getLoc(), "expected a single integer argument", feature, "");
return false;
}
uiValue = (unsigned int)value;
return true;
};
const auto positiveUnsignedArgument = [&](const char* feature, unsigned int& uiValue) {
int value;
if (it->size() == 1 && it->getInt(value)) {
if (value == 0) {
error(node->getLoc(), "must be greater than or equal to 1", feature, "");
return false;
}
} else {
warn(node->getLoc(), "expected a single integer argument", feature, "");
return false;
}
uiValue = (unsigned int)value;
return true;
};
const auto spirv14 = [&](const char* feature) {
if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4)
warn(node->getLoc(), "attribute requires a SPIR-V 1.4 target-env", feature, "");
};
int value = 0;
unsigned uiValue = 0;
switch (it->name) {
case EatUnroll:
loop->setUnroll();
if (noArgument("unroll"))
loop->setUnroll();
break;
case EatLoop:
loop->setDontUnroll();
if (noArgument("dont_unroll"))
loop->setDontUnroll();
break;
case EatDependencyInfinite:
loop->setLoopDependency(TIntermLoop::dependencyInfinite);
if (noArgument("dependency_infinite"))
loop->setLoopDependency(TIntermLoop::dependencyInfinite);
break;
case EatDependencyLength:
if (it->size() == 1 && it->getInt(value)) {
if (value <= 0)
error(node->getLoc(), "must be positive", "dependency_length", "");
if (positiveSignedArgument("dependency_length", value))
loop->setLoopDependency(value);
} else
warn(node->getLoc(), "expected a single integer argument", "dependency_length", "");
break;
case EatMinIterations:
spirv14("min_iterations");
if (unsignedArgument("min_iterations", uiValue))
loop->setMinIterations(uiValue);
break;
case EatMaxIterations:
spirv14("max_iterations");
if (unsignedArgument("max_iterations", uiValue))
loop->setMaxIterations(uiValue);
break;
case EatIterationMultiple:
spirv14("iteration_multiple");
if (positiveUnsignedArgument("iteration_multiple", uiValue))
loop->setIterationMultiple(uiValue);
break;
case EatPeelCount:
spirv14("peel_count");
if (unsignedArgument("peel_count", uiValue))
loop->setPeelCount(uiValue);
break;
case EatPartialCount:
spirv14("partial_count");
if (unsignedArgument("partial_count", uiValue))
loop->setPartialCount(uiValue);
break;
default:
warn(node->getLoc(), "attribute does not apply to a loop", "", "");

View file

@ -71,7 +71,12 @@ namespace glslang {
EatPushConstant,
EatConstantId,
EatDependencyInfinite,
EatDependencyLength
EatDependencyLength,
EatMinIterations,
EatMaxIterations,
EatIterationMultiple,
EatPeelCount,
EatPartialCount
};
class TIntermAggregate;