Front-ends: Non-functional: Rationalize vector and matrix swizzles.

This reduces code duplication in a few ways, and better encapsulates
vector swizzle representation.
This commit is contained in:
John Kessenich 2017-01-13 19:34:22 -07:00
parent 0a76a1870c
commit c142c88967
12 changed files with 269 additions and 340 deletions

View file

@ -258,106 +258,6 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
}
}
///////////////////////////////////////////////////////////////////////
//
// Sub- vector and matrix fields
//
////////////////////////////////////////////////////////////////////////
//
// Look at a '.' field selector string and change it into offsets
// for a vector or scalar
//
// Returns true if there is no error.
//
bool TParseContext::parseVectorFields(const TSourceLoc& loc, const TString& compString, int vecSize, TVectorFields& fields)
{
fields.num = (int)compString.size();
if (fields.num > 4) {
error(loc, "illegal vector field selection", compString.c_str(), "");
return false;
}
enum {
exyzw,
ergba,
estpq,
} fieldSet[4];
for (int i = 0; i < fields.num; ++i) {
switch (compString[i]) {
case 'x':
fields.offsets[i] = 0;
fieldSet[i] = exyzw;
break;
case 'r':
fields.offsets[i] = 0;
fieldSet[i] = ergba;
break;
case 's':
fields.offsets[i] = 0;
fieldSet[i] = estpq;
break;
case 'y':
fields.offsets[i] = 1;
fieldSet[i] = exyzw;
break;
case 'g':
fields.offsets[i] = 1;
fieldSet[i] = ergba;
break;
case 't':
fields.offsets[i] = 1;
fieldSet[i] = estpq;
break;
case 'z':
fields.offsets[i] = 2;
fieldSet[i] = exyzw;
break;
case 'b':
fields.offsets[i] = 2;
fieldSet[i] = ergba;
break;
case 'p':
fields.offsets[i] = 2;
fieldSet[i] = estpq;
break;
case 'w':
fields.offsets[i] = 3;
fieldSet[i] = exyzw;
break;
case 'a':
fields.offsets[i] = 3;
fieldSet[i] = ergba;
break;
case 'q':
fields.offsets[i] = 3;
fieldSet[i] = estpq;
break;
default:
error(loc, "illegal vector field selection", compString.c_str(), "");
return false;
}
}
for (int i = 0; i < fields.num; ++i) {
if (fields.offsets[i] >= vecSize) {
error(loc, "vector field selection out of range", compString.c_str(), "");
return false;
}
if (i > 0) {
if (fieldSet[i] != fieldSet[i-1]) {
error(loc, "illegal - vector component fields not from the same set", compString.c_str(), "");
return false;
}
}
}
return true;
}
//
// Handle seeing a variable identifier in the grammar.
//
@ -781,17 +681,14 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
}
TVectorFields fields;
if (! parseVectorFields(loc, field, base->getVectorSize(), fields)) {
fields.num = 1;
fields.offsets[0] = 0;
}
TSwizzleSelectors<TVectorSelector> selectors;
parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
if (base->isScalar()) {
if (fields.num == 1)
if (selectors.size() == 1)
return result;
else {
TType type(base->getBasicType(), EvqTemporary, fields.num);
TType type(base->getBasicType(), EvqTemporary, selectors.size());
// Swizzle operations propagate specialization-constantness
if (base->getQualifier().isSpecConstant())
type.getQualifier().makeSpecConstant();
@ -800,17 +697,16 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
}
if (base->getType().getQualifier().isFrontEndConstant())
result = intermediate.foldSwizzle(base, fields, loc);
result = intermediate.foldSwizzle(base, selectors, loc);
else {
if (fields.num == 1) {
TIntermTyped* index = intermediate.addConstantUnion(fields.offsets[0], loc);
if (selectors.size() == 1) {
TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc);
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
} else {
TString vectorString = field;
TIntermTyped* index = intermediate.addSwizzle(fields, loc);
TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, (int)vectorString.size()));
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
}
// Swizzle operations propagate specialization-constantness
if (base->getType().getQualifier().isSpecConstant())