HLSL: add helper access methods to TAttributeMap
There was some code replication around getting string and integer values out of an attribute map. This adds new methods to the TAttributeMap class to encapsulate some accessor details.
This commit is contained in:
parent
bb79abccb3
commit
52c087ff53
@ -36,6 +36,7 @@
|
|||||||
#include "hlslAttributes.h"
|
#include "hlslAttributes.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
// Map the given string to an attribute enum from TAttributeType,
|
// Map the given string to an attribute enum from TAttributeType,
|
||||||
@ -131,4 +132,51 @@ namespace glslang {
|
|||||||
return attributes.find(attr) != attributes.end();
|
return attributes.find(attr) != attributes.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract integers out of attribute arguments stored in attribute aggregate
|
||||||
|
bool TAttributeMap::getInt(TAttributeType attr, int& value, int argNum) const
|
||||||
|
{
|
||||||
|
const TConstUnion* intConst = getConstUnion(attr, EbtInt, argNum);
|
||||||
|
|
||||||
|
if (intConst == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = intConst->getIConst();
|
||||||
|
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 TAttributeMap::getString(TAttributeType attr, TString& value, int argNum, bool convertToLower) const
|
||||||
|
{
|
||||||
|
const TConstUnion* stringConst = getConstUnion(attr, EbtString, argNum);
|
||||||
|
|
||||||
|
if (stringConst == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = *stringConst->getSConst();
|
||||||
|
|
||||||
|
// Convenience.
|
||||||
|
if (convertToLower)
|
||||||
|
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to get attribute const union. Returns nullptr on failure.
|
||||||
|
const TConstUnion* TAttributeMap::getConstUnion(TAttributeType attr, TBasicType basicType, int argNum) const
|
||||||
|
{
|
||||||
|
const TIntermAggregate* attrAgg = (*this)[attr];
|
||||||
|
if (attrAgg == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (argNum >= int(attrAgg->getSequence().size()))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const TConstUnion* constVal = &attrAgg->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
|
||||||
|
if (constVal == nullptr || constVal->getType() != basicType)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return constVal;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
@ -93,7 +93,16 @@ namespace glslang {
|
|||||||
// True if entry exists in map (even if value is nullptr)
|
// True if entry exists in map (even if value is nullptr)
|
||||||
bool contains(TAttributeType) const;
|
bool contains(TAttributeType) const;
|
||||||
|
|
||||||
|
// Obtain attribute as integer
|
||||||
|
bool getInt(TAttributeType attr, int& value, int argNum = 0) const;
|
||||||
|
|
||||||
|
// Obtain attribute as string, with optional to-lower transform
|
||||||
|
bool getString(TAttributeType attr, TString& value, int argNum = 0, bool convertToLower = true) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Helper to get attribute const union
|
||||||
|
const TConstUnion* getConstUnion(TAttributeType attr, TBasicType, int argNum) const;
|
||||||
|
|
||||||
// Find an attribute enum given its name.
|
// Find an attribute enum given its name.
|
||||||
static TAttributeType attributeFromName(const TString& nameSpace, const TString& name);
|
static TAttributeType attributeFromName(const TString& nameSpace, const TString& name);
|
||||||
|
|
||||||
|
@ -1717,36 +1717,33 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MaxVertexCount
|
// MaxVertexCount
|
||||||
const TIntermAggregate* maxVertexCount = attributes[EatMaxVertexCount];
|
if (attributes.contains(EatMaxVertexCount)) {
|
||||||
if (maxVertexCount != nullptr) {
|
int maxVertexCount;
|
||||||
if (! intermediate.setVertices(maxVertexCount->getSequence()[0]->getAsConstantUnion()->
|
|
||||||
getConstArray()[0].getIConst())) {
|
if (! attributes.getInt(EatMaxVertexCount, maxVertexCount)) {
|
||||||
|
error(loc, "invalid maxvertexcount", "", "");
|
||||||
|
} else {
|
||||||
|
if (! intermediate.setVertices(maxVertexCount))
|
||||||
error(loc, "cannot change previously set maxvertexcount attribute", "", "");
|
error(loc, "cannot change previously set maxvertexcount attribute", "", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle [patchconstantfunction("...")]
|
// Handle [patchconstantfunction("...")]
|
||||||
const TIntermAggregate* pcfAttr = attributes[EatPatchConstantFunc];
|
if (attributes.contains(EatPatchConstantFunc)) {
|
||||||
if (pcfAttr != nullptr) {
|
TString pcfName;
|
||||||
const TConstUnion& pcfName = pcfAttr->getSequence()[0]->getAsConstantUnion()->getConstArray()[0];
|
if (! attributes.getString(EatPatchConstantFunc, pcfName, 0, false)) {
|
||||||
|
|
||||||
if (pcfName.getType() != EbtString) {
|
|
||||||
error(loc, "invalid patch constant function", "", "");
|
error(loc, "invalid patch constant function", "", "");
|
||||||
} else {
|
} else {
|
||||||
patchConstantFunctionName = *pcfName.getSConst();
|
patchConstantFunctionName = pcfName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle [domain("...")]
|
// Handle [domain("...")]
|
||||||
const TIntermAggregate* domainAttr = attributes[EatDomain];
|
if (attributes.contains(EatDomain)) {
|
||||||
if (domainAttr != nullptr) {
|
TString domainStr;
|
||||||
const TConstUnion& domainType = domainAttr->getSequence()[0]->getAsConstantUnion()->getConstArray()[0];
|
if (! attributes.getString(EatDomain, domainStr)) {
|
||||||
if (domainType.getType() != EbtString) {
|
|
||||||
error(loc, "invalid domain", "", "");
|
error(loc, "invalid domain", "", "");
|
||||||
} else {
|
} else {
|
||||||
TString domainStr = *domainType.getSConst();
|
|
||||||
std::transform(domainStr.begin(), domainStr.end(), domainStr.begin(), ::tolower);
|
|
||||||
|
|
||||||
TLayoutGeometry domain = ElgNone;
|
TLayoutGeometry domain = ElgNone;
|
||||||
|
|
||||||
if (domainStr == "tri") {
|
if (domainStr == "tri") {
|
||||||
@ -1770,15 +1767,11 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle [outputtopology("...")]
|
// Handle [outputtopology("...")]
|
||||||
const TIntermAggregate* topologyAttr = attributes[EatOutputTopology];
|
if (attributes.contains(EatOutputTopology)) {
|
||||||
if (topologyAttr != nullptr) {
|
TString topologyStr;
|
||||||
const TConstUnion& topoType = topologyAttr->getSequence()[0]->getAsConstantUnion()->getConstArray()[0];
|
if (! attributes.getString(EatOutputTopology, topologyStr)) {
|
||||||
if (topoType.getType() != EbtString) {
|
|
||||||
error(loc, "invalid outputtopology", "", "");
|
error(loc, "invalid outputtopology", "", "");
|
||||||
} else {
|
} else {
|
||||||
TString topologyStr = *topoType.getSConst();
|
|
||||||
std::transform(topologyStr.begin(), topologyStr.end(), topologyStr.begin(), ::tolower);
|
|
||||||
|
|
||||||
TVertexOrder vertexOrder = EvoNone;
|
TVertexOrder vertexOrder = EvoNone;
|
||||||
TLayoutGeometry primitive = ElgNone;
|
TLayoutGeometry primitive = ElgNone;
|
||||||
|
|
||||||
@ -1808,15 +1801,11 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle [partitioning("...")]
|
// Handle [partitioning("...")]
|
||||||
const TIntermAggregate* partitionAttr = attributes[EatPartitioning];
|
if (attributes.contains(EatPartitioning)) {
|
||||||
if (partitionAttr != nullptr) {
|
TString partitionStr;
|
||||||
const TConstUnion& partType = partitionAttr->getSequence()[0]->getAsConstantUnion()->getConstArray()[0];
|
if (! attributes.getString(EatPartitioning, partitionStr)) {
|
||||||
if (partType.getType() != EbtString) {
|
|
||||||
error(loc, "invalid partitioning", "", "");
|
error(loc, "invalid partitioning", "", "");
|
||||||
} else {
|
} else {
|
||||||
TString partitionStr = *partType.getSConst();
|
|
||||||
std::transform(partitionStr.begin(), partitionStr.end(), partitionStr.begin(), ::tolower);
|
|
||||||
|
|
||||||
TVertexSpacing partitioning = EvsNone;
|
TVertexSpacing partitioning = EvsNone;
|
||||||
|
|
||||||
if (partitionStr == "integer") {
|
if (partitionStr == "integer") {
|
||||||
@ -1837,14 +1826,11 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle [outputcontrolpoints("...")]
|
// Handle [outputcontrolpoints("...")]
|
||||||
const TIntermAggregate* outputControlPoints = attributes[EatOutputControlPoints];
|
if (attributes.contains(EatOutputControlPoints)) {
|
||||||
if (outputControlPoints != nullptr) {
|
int ctrlPoints;
|
||||||
const TConstUnion& ctrlPointConst =
|
if (! attributes.getInt(EatOutputControlPoints, ctrlPoints)) {
|
||||||
outputControlPoints->getSequence()[0]->getAsConstantUnion()->getConstArray()[0];
|
|
||||||
if (ctrlPointConst.getType() != EbtInt) {
|
|
||||||
error(loc, "invalid outputcontrolpoints", "", "");
|
error(loc, "invalid outputcontrolpoints", "", "");
|
||||||
} else {
|
} else {
|
||||||
const int ctrlPoints = ctrlPointConst.getIConst();
|
|
||||||
if (! intermediate.setVertices(ctrlPoints)) {
|
if (! intermediate.setVertices(ctrlPoints)) {
|
||||||
error(loc, "cannot change previously set outputcontrolpoints attribute", "", "");
|
error(loc, "cannot change previously set outputcontrolpoints attribute", "", "");
|
||||||
}
|
}
|
||||||
@ -1856,37 +1842,23 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
// attributes.
|
// attributes.
|
||||||
void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, TType& type)
|
void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, TType& type)
|
||||||
{
|
{
|
||||||
// extract integers out of attribute arguments stored in attribute aggregate
|
|
||||||
const auto getInt = [&](TAttributeType attr, int argNum, int& value) -> bool {
|
|
||||||
const TIntermAggregate* attrAgg = attributes[attr];
|
|
||||||
if (attrAgg == nullptr)
|
|
||||||
return false;
|
|
||||||
if (argNum >= (int)attrAgg->getSequence().size())
|
|
||||||
return false;
|
|
||||||
const TConstUnion& intConst = attrAgg->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
|
|
||||||
if (intConst.getType() != EbtInt)
|
|
||||||
return false;
|
|
||||||
value = intConst.getIConst();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// location
|
// location
|
||||||
int value;
|
int value;
|
||||||
if (getInt(EatLocation, 0, value))
|
if (attributes.getInt(EatLocation, value))
|
||||||
type.getQualifier().layoutLocation = value;
|
type.getQualifier().layoutLocation = value;
|
||||||
|
|
||||||
// binding
|
// binding
|
||||||
if (getInt(EatBinding, 0, value)) {
|
if (attributes.getInt(EatBinding, value)) {
|
||||||
type.getQualifier().layoutBinding = value;
|
type.getQualifier().layoutBinding = value;
|
||||||
type.getQualifier().layoutSet = 0;
|
type.getQualifier().layoutSet = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set
|
// set
|
||||||
if (getInt(EatBinding, 1, value))
|
if (attributes.getInt(EatBinding, value, 1))
|
||||||
type.getQualifier().layoutSet = value;
|
type.getQualifier().layoutSet = value;
|
||||||
|
|
||||||
// input attachment
|
// input attachment
|
||||||
if (getInt(EatInputAttachment, 0, value))
|
if (attributes.getInt(EatInputAttachment, value))
|
||||||
type.getQualifier().layoutAttachment = value;
|
type.getQualifier().layoutAttachment = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user