glslang -> SPV: Improvements in swizzles on access chains: Bug 14007 (wrong type), simplications, tests, support mixed swizzle with dynamic component selection.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@31277 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
6b3fd19d89
commit
06e1d0b434
9 changed files with 531 additions and 54 deletions
|
|
@ -573,7 +573,7 @@ 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, node->getLeft()->getVectorSize(), convertGlslangToSpvType(node->getType()));
|
||||
builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize());
|
||||
} else {
|
||||
// normal case for indexing array or structure or block
|
||||
builder.accessChainPush(builder.makeIntConstant(index), convertGlslangToSpvType(node->getType()));
|
||||
|
|
@ -615,7 +615,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, node->getLeft()->getVectorSize(), convertGlslangToSpvType(node->getType()));
|
||||
builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize());
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -907,6 +907,27 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vecto
|
|||
return insert->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
|
||||
{
|
||||
Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
|
||||
extract->addIdOperand(vector);
|
||||
extract->addIdOperand(componentIndex);
|
||||
buildPoint->addInstruction(extract);
|
||||
|
||||
return extract->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
|
||||
{
|
||||
Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic);
|
||||
insert->addIdOperand(vector);
|
||||
insert->addIdOperand(component);
|
||||
insert->addIdOperand(componentIndex);
|
||||
buildPoint->addInstruction(insert);
|
||||
|
||||
return insert->getResultId();
|
||||
}
|
||||
|
||||
// An opcode that has no operands, no result id, and no type
|
||||
void Builder::createNoResultOp(Op opCode)
|
||||
{
|
||||
|
|
@ -997,6 +1018,7 @@ Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& cha
|
|||
return createCompositeExtract(source, typeId, channels.front());
|
||||
|
||||
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
|
||||
assert(isVector(source));
|
||||
swizzle->addIdOperand(source);
|
||||
swizzle->addIdOperand(source);
|
||||
for (int i = 0; i < (int)channels.size(); ++i)
|
||||
|
|
@ -1014,6 +1036,8 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<uns
|
|||
return createCompositeInsert(source, target, typeId, channels.front());
|
||||
|
||||
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
|
||||
assert(isVector(source));
|
||||
assert(isVector(target));
|
||||
swizzle->addIdOperand(target);
|
||||
swizzle->addIdOperand(source);
|
||||
|
||||
|
|
@ -1813,13 +1837,12 @@ void Builder::clearAccessChain()
|
|||
accessChain.instr = 0;
|
||||
accessChain.swizzle.clear();
|
||||
accessChain.component = 0;
|
||||
accessChain.swizzleTargetWidth = 0;
|
||||
accessChain.resultType = NoType;
|
||||
accessChain.isRValue = false;
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width, Id type)
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width)
|
||||
{
|
||||
// if needed, propagate the swizzle for the current access chain
|
||||
if (accessChain.swizzle.size()) {
|
||||
|
|
@ -1828,15 +1851,8 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width,
|
|||
for (unsigned int i = 0; i < swizzle.size(); ++i) {
|
||||
accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
accessChain.swizzle = swizzle;
|
||||
}
|
||||
|
||||
// track width the swizzle operates on; once known, it does not change
|
||||
if (accessChain.swizzleTargetWidth == 0)
|
||||
accessChain.swizzleTargetWidth = width;
|
||||
|
||||
accessChain.resultType = type;
|
||||
|
||||
// determine if we need to track this swizzle anymore
|
||||
simplifyAccessChainSwizzle();
|
||||
|
|
@ -1849,23 +1865,24 @@ void Builder::accessChainStore(Id rvalue)
|
|||
|
||||
Id base = collapseAccessChain();
|
||||
|
||||
if (accessChain.swizzle.size() && accessChain.component)
|
||||
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,
|
||||
// extract and insert elements to perform writeMask and/or swizzle.
|
||||
Id source;
|
||||
|
||||
Id source = NoResult;
|
||||
if (accessChain.swizzle.size()) {
|
||||
Id tempBaseId = createLoad(base);
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
|
||||
} else if (accessChain.component) {
|
||||
Id tempBaseId = createLoad(base);
|
||||
Instruction* vectorInsert = new Instruction(getUniqueId(), getTypeId(tempBaseId), OpVectorInsertDynamic);
|
||||
vectorInsert->addIdOperand(tempBaseId);
|
||||
vectorInsert->addIdOperand(rvalue);
|
||||
vectorInsert->addIdOperand(accessChain.component);
|
||||
buildPoint->addInstruction(vectorInsert);
|
||||
}
|
||||
|
||||
source = vectorInsert->getResultId();
|
||||
} else
|
||||
// dynamic component selection
|
||||
if (accessChain.component) {
|
||||
Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
|
||||
source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
|
||||
}
|
||||
|
||||
if (source == NoResult)
|
||||
source = rvalue;
|
||||
|
||||
createStore(source, base);
|
||||
|
|
@ -1878,6 +1895,7 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
|
|||
|
||||
if (accessChain.isRValue) {
|
||||
if (accessChain.indexChain.size() > 0) {
|
||||
mergeAccessChainSwizzle(); // TODO: optimization: look at applying this optimization more widely
|
||||
// if all the accesses are constants, we can use OpCompositeExtract
|
||||
std::vector<unsigned> indexes;
|
||||
bool constant = true;
|
||||
|
|
@ -1913,14 +1931,25 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
|
|||
id = createLoad(collapseAccessChain());
|
||||
}
|
||||
|
||||
if (accessChain.component) {
|
||||
Instruction* vectorExtract = new Instruction(getUniqueId(), getScalarTypeId(getTypeId(id)), OpVectorExtractDynamic);
|
||||
vectorExtract->addIdOperand(id);
|
||||
vectorExtract->addIdOperand(accessChain.component);
|
||||
buildPoint->addInstruction(vectorExtract);
|
||||
id = vectorExtract->getResultId();
|
||||
} else if (accessChain.swizzle.size())
|
||||
id = createRvalueSwizzle(accessChain.resultType, id, accessChain.swizzle);
|
||||
// Done, unless there are swizzles to do
|
||||
if (accessChain.swizzle.size() == 0 && accessChain.component == 0)
|
||||
return id;
|
||||
|
||||
Id componentType = getScalarTypeId(accessChain.resultType);
|
||||
|
||||
// Do remaining swizzling
|
||||
// First, static swizzling
|
||||
if (accessChain.swizzle.size()) {
|
||||
// static swizzle
|
||||
Id resultType = componentType;
|
||||
if (accessChain.swizzle.size() > 1)
|
||||
resultType = makeVectorType(componentType, accessChain.swizzle.size());
|
||||
id = createRvalueSwizzle(resultType, id, accessChain.swizzle);
|
||||
}
|
||||
|
||||
// dynamic single-component selection
|
||||
if (accessChain.component)
|
||||
id = createVectorExtractDynamic(id, componentType, accessChain.component);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
|
@ -2005,8 +2034,9 @@ Id Builder::collapseAccessChain()
|
|||
// clear out swizzle if it is redundant
|
||||
void Builder::simplifyAccessChainSwizzle()
|
||||
{
|
||||
// if swizzle has fewer components than our target, it is a writemask
|
||||
if (accessChain.swizzleTargetWidth > (int)accessChain.swizzle.size())
|
||||
// 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())
|
||||
return;
|
||||
|
||||
// if components are out of order, it is a swizzle
|
||||
|
|
@ -2017,7 +2047,31 @@ void Builder::simplifyAccessChainSwizzle()
|
|||
|
||||
// otherwise, there is no need to track this swizzle
|
||||
accessChain.swizzle.clear();
|
||||
accessChain.swizzleTargetWidth = 0;
|
||||
}
|
||||
|
||||
// clear out swizzle if it can become part of the indexes
|
||||
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)
|
||||
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)
|
||||
return;
|
||||
|
||||
// move the swizzle over to the indexes
|
||||
if (accessChain.swizzle.size() == 1)
|
||||
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.swizzle.clear();
|
||||
}
|
||||
|
||||
// Utility method for creating a new block and setting the insert point to
|
||||
|
|
|
|||
|
|
@ -228,6 +228,9 @@ public:
|
|||
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
|
||||
|
||||
Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
|
||||
Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
|
||||
|
||||
void createNoResultOp(Op);
|
||||
void createNoResultOp(Op, Id operand);
|
||||
void createControlBarrier(unsigned executionScope);
|
||||
|
|
@ -244,7 +247,7 @@ public:
|
|||
|
||||
// Take a copy of an lvalue (target) and a source of components, and set the
|
||||
// source components into the lvalue where the 'channels' say to put them.
|
||||
// An update version of the target is returned.
|
||||
// An updated version of the target is returned.
|
||||
// (No true lvalue or stores are used.)
|
||||
Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
|
||||
|
||||
|
|
@ -426,9 +429,8 @@ public:
|
|||
std::vector<Id> indexChain;
|
||||
Id instr; // the instruction that generates this access chain
|
||||
std::vector<unsigned> swizzle;
|
||||
Id component; // a dynamic component index
|
||||
int swizzleTargetWidth;
|
||||
Id resultType; // dereferenced type, to be inclusive of swizzles, which can't have a pointer
|
||||
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle
|
||||
Id resultType; // dereferenced type, to be exclusive of swizzles
|
||||
bool isRValue;
|
||||
};
|
||||
|
||||
|
|
@ -449,6 +451,7 @@ public:
|
|||
{
|
||||
assert(isPointer(lValue));
|
||||
accessChain.base = lValue;
|
||||
accessChain.resultType = getContainedTypeId(getTypeId(lValue));
|
||||
}
|
||||
|
||||
// set new base value as an r-value
|
||||
|
|
@ -467,7 +470,7 @@ public:
|
|||
}
|
||||
|
||||
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width, Id type);
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width);
|
||||
|
||||
// push a variable component selection onto the access chain; supporting only one, so unsided
|
||||
void accessChainPushComponent(Id component) { accessChain.component = component; }
|
||||
|
|
@ -489,6 +492,7 @@ protected:
|
|||
Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
|
||||
Id collapseAccessChain();
|
||||
void simplifyAccessChainSwizzle();
|
||||
void mergeAccessChainSwizzle();
|
||||
void createAndSetNoPredecessorBlock(const char*);
|
||||
void createBranch(Block* block);
|
||||
void createMerge(Op, Block*, unsigned int control);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue