SPV: Reduce spurious type generation by removing intermediate types in the middle of access chains.
This generally simplifies access chain generation, with far fewer type conversions. It is particularly important to future SPIR-V changes where there is less aggregate type uniqueness due to carrying different layout information with the type.
This commit is contained in:
@@ -530,12 +530,12 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
||||
// evaluate the right
|
||||
builder.clearAccessChain();
|
||||
node->getRight()->traverse(this);
|
||||
spv::Id rValue = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
|
||||
spv::Id rValue = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
|
||||
|
||||
if (node->getOp() != glslang::EOpAssign) {
|
||||
// the left is also an r-value
|
||||
builder.setAccessChain(lValue);
|
||||
spv::Id leftRValue = builder.accessChainLoad(TranslatePrecisionDecoration(node->getLeft()->getType()));
|
||||
spv::Id leftRValue = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
|
||||
// do the operation
|
||||
rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
|
||||
@@ -587,10 +587,10 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
||||
// so short circuit the access-chain stuff with a swizzle.
|
||||
std::vector<unsigned> swizzle;
|
||||
swizzle.push_back(node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst());
|
||||
builder.accessChainPushSwizzle(swizzle);
|
||||
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
} else {
|
||||
// normal case for indexing array or structure or block
|
||||
builder.accessChainPush(builder.makeIntConstant(index), convertGlslangToSpvType(node->getType()));
|
||||
builder.accessChainPush(builder.makeIntConstant(index));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -611,15 +611,15 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
||||
// compute the next index in the chain
|
||||
builder.clearAccessChain();
|
||||
node->getRight()->traverse(this);
|
||||
spv::Id index = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
|
||||
spv::Id index = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
|
||||
|
||||
// restore the saved access chain
|
||||
builder.setAccessChain(partial);
|
||||
|
||||
if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
|
||||
builder.accessChainPushComponent(index);
|
||||
builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
else
|
||||
builder.accessChainPush(index, convertGlslangToSpvType(node->getType()));
|
||||
builder.accessChainPush(index);
|
||||
}
|
||||
return false;
|
||||
case glslang::EOpVectorSwizzle:
|
||||
@@ -629,7 +629,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
||||
std::vector<unsigned> swizzle;
|
||||
for (int i = 0; i < (int)swizzleSequence.size(); ++i)
|
||||
swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
|
||||
builder.accessChainPushSwizzle(swizzle);
|
||||
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
@@ -641,11 +641,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
||||
// Get the operands
|
||||
builder.clearAccessChain();
|
||||
node->getLeft()->traverse(this);
|
||||
spv::Id left = builder.accessChainLoad(TranslatePrecisionDecoration(node->getLeft()->getType()));
|
||||
spv::Id left = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
|
||||
builder.clearAccessChain();
|
||||
node->getRight()->traverse(this);
|
||||
spv::Id right = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
|
||||
spv::Id right = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
|
||||
|
||||
spv::Id result;
|
||||
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
|
||||
@@ -702,7 +702,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
||||
|
||||
builder.clearAccessChain();
|
||||
node->getOperand()->traverse(this);
|
||||
spv::Id operand = builder.accessChainLoad(TranslatePrecisionDecoration(node->getOperand()->getType()));
|
||||
spv::Id operand = builder.accessChainLoad(convertGlslangToSpvType(node->getOperand()->getType()));
|
||||
|
||||
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
|
||||
|
||||
@@ -1038,11 +1038,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
|
||||
builder.clearAccessChain();
|
||||
left->traverse(this);
|
||||
spv::Id leftId = builder.accessChainLoad(TranslatePrecisionDecoration(left->getType()));
|
||||
spv::Id leftId = builder.accessChainLoad(convertGlslangToSpvType(left->getType()));
|
||||
|
||||
builder.clearAccessChain();
|
||||
right->traverse(this);
|
||||
spv::Id rightId = builder.accessChainLoad(TranslatePrecisionDecoration(right->getType()));
|
||||
spv::Id rightId = builder.accessChainLoad(convertGlslangToSpvType(right->getType()));
|
||||
|
||||
result = createBinaryOperation(binOp, precision,
|
||||
convertGlslangToSpvType(node->getType()), leftId, rightId,
|
||||
@@ -1084,7 +1084,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
if (lvalue)
|
||||
operands.push_back(builder.accessChainGetLValue());
|
||||
else
|
||||
operands.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangOperands[arg]->getAsTyped()->getType())));
|
||||
operands.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangOperands[arg]->getAsTyped()->getType())));
|
||||
}
|
||||
|
||||
if (atomic) {
|
||||
@@ -1134,13 +1134,13 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
||||
node->getCondition()->traverse(this);
|
||||
|
||||
// make an "if" based on the value created by the condition
|
||||
spv::Builder::If ifBuilder(builder.accessChainLoad(spv::NoPrecision), builder);
|
||||
spv::Builder::If ifBuilder(builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getType())), builder);
|
||||
|
||||
if (node->getTrueBlock()) {
|
||||
// emit the "then" statement
|
||||
node->getTrueBlock()->traverse(this);
|
||||
if (result)
|
||||
builder.createStore(builder.accessChainLoad(TranslatePrecisionDecoration(node->getTrueBlock()->getAsTyped()->getType())), result);
|
||||
builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getTrueBlock()->getAsTyped()->getType())), result);
|
||||
}
|
||||
|
||||
if (node->getFalseBlock()) {
|
||||
@@ -1148,7 +1148,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
||||
// emit the "else" statement
|
||||
node->getFalseBlock()->traverse(this);
|
||||
if (result)
|
||||
builder.createStore(builder.accessChainLoad(TranslatePrecisionDecoration(node->getFalseBlock()->getAsTyped()->getType())), result);
|
||||
builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getFalseBlock()->getAsTyped()->getType())), result);
|
||||
}
|
||||
|
||||
ifBuilder.makeEndIf();
|
||||
@@ -1169,7 +1169,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
|
||||
{
|
||||
// emit and get the condition before doing anything with switch
|
||||
node->getCondition()->traverse(this);
|
||||
spv::Id selector = builder.accessChainLoad(TranslatePrecisionDecoration(node->getCondition()->getAsTyped()->getType()));
|
||||
spv::Id selector = builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getAsTyped()->getType()));
|
||||
|
||||
// browse the children to sort out code segments
|
||||
int defaultSegment = -1;
|
||||
@@ -1233,7 +1233,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
||||
if (node->getTest()) {
|
||||
node->getTest()->traverse(this);
|
||||
// the AST only contained the test computation, not the branch, we have to add it
|
||||
spv::Id condition = builder.accessChainLoad(TranslatePrecisionDecoration(node->getTest()->getType()));
|
||||
spv::Id condition = builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
|
||||
builder.createLoopTestBranch(condition);
|
||||
} else {
|
||||
builder.createBranchToBody();
|
||||
@@ -1279,7 +1279,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
|
||||
if (inMain)
|
||||
builder.makeMainReturn();
|
||||
else if (node->getExpression())
|
||||
builder.makeReturn(false, builder.accessChainLoad(TranslatePrecisionDecoration(node->getExpression()->getType())));
|
||||
builder.makeReturn(false, builder.accessChainLoad(convertGlslangToSpvType(node->getExpression()->getType())));
|
||||
else
|
||||
builder.makeReturn();
|
||||
|
||||
@@ -1664,7 +1664,7 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermSequence&
|
||||
for (int i = 0; i < (int)glslangArguments.size(); ++i) {
|
||||
builder.clearAccessChain();
|
||||
glslangArguments[i]->traverse(this);
|
||||
arguments.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangArguments[i]->getAsTyped()->getType())));
|
||||
arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangArguments[i]->getAsTyped()->getType())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1672,7 +1672,7 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std
|
||||
{
|
||||
builder.clearAccessChain();
|
||||
node.getOperand()->traverse(this);
|
||||
arguments.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(node.getAsTyped()->getType())));
|
||||
arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(node.getOperand()->getType())));
|
||||
}
|
||||
|
||||
spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
|
||||
@@ -1806,17 +1806,19 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
||||
// 1. Evaluate the arguments
|
||||
std::vector<spv::Builder::AccessChain> lValues;
|
||||
std::vector<spv::Id> rValues;
|
||||
std::vector<spv::Id> argTypes;
|
||||
for (int a = 0; a < (int)glslangArgs.size(); ++a) {
|
||||
// build l-value
|
||||
builder.clearAccessChain();
|
||||
glslangArgs[a]->traverse(this);
|
||||
argTypes.push_back(convertGlslangToSpvType(glslangArgs[a]->getAsTyped()->getType()));
|
||||
// keep outputs as l-values, evaluate input-only as r-values
|
||||
if (qualifiers[a] != glslang::EvqConstReadOnly) {
|
||||
// save l-value
|
||||
lValues.push_back(builder.getAccessChain());
|
||||
} else {
|
||||
// process r-value
|
||||
rValues.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangArgs[a]->getAsTyped()->getType())));
|
||||
rValues.push_back(builder.accessChainLoad(argTypes.back()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1836,7 +1838,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
||||
if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
|
||||
// need to copy the input into output space
|
||||
builder.setAccessChain(lValues[lValueCount]);
|
||||
spv::Id copy = builder.accessChainLoad(spv::NoPrecision); // TODO: get precision
|
||||
spv::Id copy = builder.accessChainLoad(argTypes[a]);
|
||||
builder.createStore(copy, arg);
|
||||
}
|
||||
++lValueCount;
|
||||
|
||||
@@ -1957,18 +1957,23 @@ void Builder::createBranchToLoopHeaderFromInside(const Loop& loop)
|
||||
|
||||
void Builder::clearAccessChain()
|
||||
{
|
||||
accessChain.base = 0;
|
||||
accessChain.base = NoResult;
|
||||
accessChain.indexChain.clear();
|
||||
accessChain.instr = 0;
|
||||
accessChain.instr = NoResult;
|
||||
accessChain.swizzle.clear();
|
||||
accessChain.component = 0;
|
||||
accessChain.resultType = NoType;
|
||||
accessChain.component = NoResult;
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
accessChain.isRValue = false;
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle)
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
|
||||
{
|
||||
// swizzles can be stacked in GLSL, but simplified to a single
|
||||
// one here; the base type doesn't change
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
|
||||
// if needed, propagate the swizzle for the current access chain
|
||||
if (accessChain.swizzle.size()) {
|
||||
std::vector<unsigned> oldSwizzle = accessChain.swizzle;
|
||||
@@ -1990,7 +1995,7 @@ void Builder::accessChainStore(Id rvalue)
|
||||
|
||||
Id base = collapseAccessChain();
|
||||
|
||||
if (accessChain.swizzle.size() && accessChain.component)
|
||||
if (accessChain.swizzle.size() && accessChain.component != NoResult)
|
||||
MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");
|
||||
|
||||
// If swizzle exists, it is out-of-order or not full, we must load the target vector,
|
||||
@@ -2002,7 +2007,7 @@ void Builder::accessChainStore(Id rvalue)
|
||||
}
|
||||
|
||||
// dynamic component selection
|
||||
if (accessChain.component) {
|
||||
if (accessChain.component != NoResult) {
|
||||
Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
|
||||
source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
|
||||
}
|
||||
@@ -2014,13 +2019,15 @@ void Builder::accessChainStore(Id rvalue)
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
Id Builder::accessChainLoad(Decoration /*precision*/)
|
||||
Id Builder::accessChainLoad(Id resultType)
|
||||
{
|
||||
Id id;
|
||||
|
||||
if (accessChain.isRValue) {
|
||||
if (accessChain.indexChain.size() > 0) {
|
||||
mergeAccessChainSwizzle(); // TODO: optimization: look at applying this optimization more widely
|
||||
Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
|
||||
|
||||
// if all the accesses are constants, we can use OpCompositeExtract
|
||||
std::vector<unsigned> indexes;
|
||||
bool constant = true;
|
||||
@@ -2034,7 +2041,7 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
|
||||
}
|
||||
|
||||
if (constant)
|
||||
id = createCompositeExtract(accessChain.base, accessChain.resultType, indexes);
|
||||
id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
|
||||
else {
|
||||
// make a new function variable for this r-value
|
||||
Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
|
||||
@@ -2057,24 +2064,22 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
|
||||
}
|
||||
|
||||
// Done, unless there are swizzles to do
|
||||
if (accessChain.swizzle.size() == 0 && accessChain.component == 0)
|
||||
if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
|
||||
return id;
|
||||
|
||||
Id componentType = getScalarTypeId(accessChain.resultType);
|
||||
|
||||
// Do remaining swizzling
|
||||
// First, static swizzling
|
||||
if (accessChain.swizzle.size()) {
|
||||
// static swizzle
|
||||
Id resultType = componentType;
|
||||
Id swizzledType = getScalarTypeId(getTypeId(id));
|
||||
if (accessChain.swizzle.size() > 1)
|
||||
resultType = makeVectorType(componentType, (int)accessChain.swizzle.size());
|
||||
id = createRvalueSwizzle(resultType, id, accessChain.swizzle);
|
||||
swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
|
||||
id = createRvalueSwizzle(swizzledType, id, accessChain.swizzle);
|
||||
}
|
||||
|
||||
// dynamic single-component selection
|
||||
if (accessChain.component)
|
||||
id = createVectorExtractDynamic(id, componentType, accessChain.component);
|
||||
if (accessChain.component != NoResult)
|
||||
id = createVectorExtractDynamic(id, resultType, accessChain.component);
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -2089,7 +2094,7 @@ Id Builder::accessChainGetLValue()
|
||||
// extract and insert elements to perform writeMask and/or swizzle. This does not
|
||||
// go with getting a direct l-value pointer.
|
||||
assert(accessChain.swizzle.size() == 0);
|
||||
assert(accessChain.component == spv::NoResult);
|
||||
assert(accessChain.component == NoResult);
|
||||
|
||||
return lvalue;
|
||||
}
|
||||
@@ -2170,7 +2175,7 @@ void Builder::simplifyAccessChainSwizzle()
|
||||
{
|
||||
// If the swizzle has fewer components than the vector, it is subsetting, and must stay
|
||||
// to preserve that fact.
|
||||
if (getNumTypeComponents(accessChain.resultType) > (int)accessChain.swizzle.size())
|
||||
if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size())
|
||||
return;
|
||||
|
||||
// if components are out of order, it is a swizzle
|
||||
@@ -2181,6 +2186,8 @@ void Builder::simplifyAccessChainSwizzle()
|
||||
|
||||
// otherwise, there is no need to track this swizzle
|
||||
accessChain.swizzle.clear();
|
||||
if (accessChain.component == NoResult)
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
}
|
||||
|
||||
// clear out swizzle if it can become part of the indexes
|
||||
@@ -2188,12 +2195,12 @@ void Builder::mergeAccessChainSwizzle()
|
||||
{
|
||||
// is there even a chance of doing something? Need a single-component swizzle
|
||||
if ((accessChain.swizzle.size() > 1) ||
|
||||
(accessChain.swizzle.size() == 0 && accessChain.component == 0))
|
||||
(accessChain.swizzle.size() == 0 && accessChain.component == NoResult))
|
||||
return;
|
||||
|
||||
// TODO: optimization: remove this, but for now confine this to non-dynamic accesses
|
||||
// (the above test is correct when this is removed.)
|
||||
if (accessChain.component)
|
||||
if (accessChain.component != NoResult)
|
||||
return;
|
||||
|
||||
// move the swizzle over to the indexes
|
||||
@@ -2201,10 +2208,10 @@ void Builder::mergeAccessChainSwizzle()
|
||||
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
|
||||
else
|
||||
accessChain.indexChain.push_back(accessChain.component);
|
||||
accessChain.resultType = getScalarTypeId(accessChain.resultType);
|
||||
|
||||
// now there is no need to track this swizzle
|
||||
accessChain.component = NoResult;
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
accessChain.swizzle.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ public:
|
||||
Id instr; // the instruction that generates this access chain
|
||||
std::vector<unsigned> swizzle;
|
||||
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle
|
||||
Id resultType; // dereferenced type, to be exclusive of swizzles
|
||||
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
|
||||
bool isRValue;
|
||||
};
|
||||
|
||||
@@ -452,7 +452,6 @@ public:
|
||||
{
|
||||
assert(isPointer(lValue));
|
||||
accessChain.base = lValue;
|
||||
accessChain.resultType = getContainedTypeId(getTypeId(lValue));
|
||||
}
|
||||
|
||||
// set new base value as an r-value
|
||||
@@ -460,27 +459,30 @@ public:
|
||||
{
|
||||
accessChain.isRValue = true;
|
||||
accessChain.base = rValue;
|
||||
accessChain.resultType = getTypeId(rValue);
|
||||
}
|
||||
|
||||
// push offset onto the end of the chain
|
||||
void accessChainPush(Id offset, Id newType)
|
||||
void accessChainPush(Id offset)
|
||||
{
|
||||
accessChain.indexChain.push_back(offset);
|
||||
accessChain.resultType = newType;
|
||||
}
|
||||
|
||||
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle);
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
|
||||
|
||||
// push a variable component selection onto the access chain; supporting only one, so unsided
|
||||
void accessChainPushComponent(Id component) { accessChain.component = component; }
|
||||
void accessChainPushComponent(Id component, Id preSwizzleBaseType)
|
||||
{
|
||||
accessChain.component = component;
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
}
|
||||
|
||||
// use accessChain and swizzle to store value
|
||||
void accessChainStore(Id rvalue);
|
||||
|
||||
// use accessChain and swizzle to load an r-value
|
||||
Id accessChainLoad(Decoration precision);
|
||||
Id accessChainLoad(Id ResultType);
|
||||
|
||||
// get the direct pointer for an l-value
|
||||
Id accessChainGetLValue();
|
||||
|
||||
Reference in New Issue
Block a user