SPV: Create more access chains addressing a few swizzling issues.
- Fixes #1233 - Treats local bools like anything else - more consistently deals with a dynamic component selection
This commit is contained in:
parent
2651ccaec8
commit
5c3eed542d
8 changed files with 764 additions and 716 deletions
|
|
@ -1388,16 +1388,13 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
|
|||
return createCompositeInsert(source, target, typeId, channels.front());
|
||||
|
||||
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
|
||||
|
||||
assert(isVector(target));
|
||||
swizzle->addIdOperand(target);
|
||||
if (accessChain.component != NoResult)
|
||||
// For dynamic component selection, source does not involve in l-value swizzle
|
||||
swizzle->addIdOperand(target);
|
||||
else {
|
||||
assert(getNumComponents(source) == (int)channels.size());
|
||||
assert(isVector(source));
|
||||
swizzle->addIdOperand(source);
|
||||
}
|
||||
|
||||
assert(getNumComponents(source) == (int)channels.size());
|
||||
assert(isVector(source));
|
||||
swizzle->addIdOperand(source);
|
||||
|
||||
// Set up an identity shuffle from the base value to the result value
|
||||
unsigned int components[4];
|
||||
|
|
@ -1406,12 +1403,8 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
|
|||
components[i] = i;
|
||||
|
||||
// Punch in the l-value swizzle
|
||||
for (int i = 0; i < (int)channels.size(); ++i) {
|
||||
if (accessChain.component != NoResult)
|
||||
components[i] = channels[i]; // Only shuffle the base value
|
||||
else
|
||||
components[channels[i]] = numTargetComponents + i;
|
||||
}
|
||||
for (int i = 0; i < (int)channels.size(); ++i)
|
||||
components[channels[i]] = numTargetComponents + i;
|
||||
|
||||
// finish the instruction with these components selectors
|
||||
for (int i = 0; i < numTargetComponents; ++i)
|
||||
|
|
@ -2203,7 +2196,7 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
|
|||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
|
||||
// if needed, propagate the swizzle for the current access chain
|
||||
if (accessChain.swizzle.size()) {
|
||||
if (accessChain.swizzle.size() > 0) {
|
||||
std::vector<unsigned> oldSwizzle = accessChain.swizzle;
|
||||
accessChain.swizzle.resize(0);
|
||||
for (unsigned int i = 0; i < swizzle.size(); ++i) {
|
||||
|
|
@ -2224,24 +2217,18 @@ void Builder::accessChainStore(Id rvalue)
|
|||
|
||||
transferAccessChainSwizzle(true);
|
||||
Id base = collapseAccessChain();
|
||||
Id source = rvalue;
|
||||
|
||||
// dynamic component should be gone
|
||||
assert(accessChain.component == NoResult);
|
||||
|
||||
// If swizzle still 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 = NoResult;
|
||||
if (accessChain.swizzle.size()) {
|
||||
if (accessChain.swizzle.size() > 0) {
|
||||
Id tempBaseId = createLoad(base);
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
|
||||
}
|
||||
|
||||
// dynamic component selection
|
||||
if (accessChain.component != NoResult) {
|
||||
Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
|
||||
source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
|
||||
}
|
||||
|
||||
if (source == NoResult)
|
||||
source = rvalue;
|
||||
|
||||
createStore(source, base);
|
||||
}
|
||||
|
||||
|
|
@ -2251,7 +2238,7 @@ Id Builder::accessChainLoad(Decoration precision, Id resultType)
|
|||
Id id;
|
||||
|
||||
if (accessChain.isRValue) {
|
||||
// transfer access chain, but keep it static, so we can stay in registers
|
||||
// transfer access chain, but try to stay in registers
|
||||
transferAccessChainSwizzle(false);
|
||||
if (accessChain.indexChain.size() > 0) {
|
||||
Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
|
||||
|
|
@ -2299,16 +2286,16 @@ Id Builder::accessChainLoad(Decoration precision, Id resultType)
|
|||
return id;
|
||||
|
||||
// Do remaining swizzling
|
||||
// First, static swizzling
|
||||
if (accessChain.swizzle.size()) {
|
||||
// static swizzle
|
||||
|
||||
// Do the basic swizzle
|
||||
if (accessChain.swizzle.size() > 0) {
|
||||
Id swizzledType = getScalarTypeId(getTypeId(id));
|
||||
if (accessChain.swizzle.size() > 1)
|
||||
swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
|
||||
id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle);
|
||||
}
|
||||
|
||||
// dynamic single-component selection
|
||||
// Do the dynamic component
|
||||
if (accessChain.component != NoResult)
|
||||
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
|
||||
|
||||
|
|
@ -2458,26 +2445,66 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
|||
// Protected methods.
|
||||
//
|
||||
|
||||
// Turn the described access chain in 'accessChain' into an instruction
|
||||
// Turn the described access chain in 'accessChain' into an instruction(s)
|
||||
// computing its address. This *cannot* include complex swizzles, which must
|
||||
// be handled after this is called, but it does include swizzles that select
|
||||
// an individual element, as a single address of a scalar type can be
|
||||
// computed by an OpAccessChain instruction.
|
||||
// be handled after this is called.
|
||||
//
|
||||
// Can generate code.
|
||||
Id Builder::collapseAccessChain()
|
||||
{
|
||||
assert(accessChain.isRValue == false);
|
||||
|
||||
if (accessChain.indexChain.size() > 0) {
|
||||
if (accessChain.instr == 0) {
|
||||
StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
|
||||
accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
|
||||
}
|
||||
|
||||
// did we already emit an access chain for this?
|
||||
if (accessChain.instr != NoResult)
|
||||
return accessChain.instr;
|
||||
} else
|
||||
|
||||
// If we have a dynamic component, we can still transfer
|
||||
// that into a final operand to the access chain. We need to remap the
|
||||
// dynamic component through the swizzle to get a new dynamic component to
|
||||
// update.
|
||||
//
|
||||
// This was not done in transferAccessChainSwizzle() because it might
|
||||
// generate code.
|
||||
remapDynamicSwizzle();
|
||||
if (accessChain.component != NoResult) {
|
||||
// transfer the dynamic component to the access chain
|
||||
accessChain.indexChain.push_back(accessChain.component);
|
||||
accessChain.component = NoResult;
|
||||
}
|
||||
|
||||
// note that non-trivial swizzling is left pending
|
||||
|
||||
// do we have an access chain?
|
||||
if (accessChain.indexChain.size() == 0)
|
||||
return accessChain.base;
|
||||
|
||||
// note that non-trivial swizzling is left pending...
|
||||
// emit the access chain
|
||||
StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
|
||||
accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
|
||||
|
||||
return accessChain.instr;
|
||||
}
|
||||
|
||||
// For a dynamic component selection of a swizzle.
|
||||
//
|
||||
// Turn the swizzle and dynamic component into just a dynamic component.
|
||||
//
|
||||
// Generates code.
|
||||
void Builder::remapDynamicSwizzle()
|
||||
{
|
||||
// do we have a swizzle to remap a dynamic component through?
|
||||
if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) {
|
||||
// build a vector of the swizzle for the component to map into
|
||||
std::vector<Id> components;
|
||||
for (int c = 0; c < accessChain.swizzle.size(); ++c)
|
||||
components.push_back(makeUintConstant(accessChain.swizzle[c]));
|
||||
Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size());
|
||||
Id map = makeCompositeConstant(mapType, components);
|
||||
|
||||
// use it
|
||||
accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component);
|
||||
accessChain.swizzle.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// clear out swizzle if it is redundant, that is reselecting the same components
|
||||
|
|
@ -2503,38 +2530,30 @@ void Builder::simplifyAccessChainSwizzle()
|
|||
|
||||
// To the extent any swizzling can become part of the chain
|
||||
// of accesses instead of a post operation, make it so.
|
||||
// If 'dynamic' is true, include transferring a non-static component index,
|
||||
// otherwise, only transfer static indexes.
|
||||
// If 'dynamic' is true, include transferring the dynamic component,
|
||||
// otherwise, leave it pending.
|
||||
//
|
||||
// Also, Boolean vectors are likely to be special. While
|
||||
// for external storage, they should only be integer types,
|
||||
// function-local bool vectors could use sub-word indexing,
|
||||
// so keep that as a separate Insert/Extract on a loaded vector.
|
||||
// Does not generate code. just updates the access chain.
|
||||
void Builder::transferAccessChainSwizzle(bool dynamic)
|
||||
{
|
||||
// too complex?
|
||||
if (accessChain.swizzle.size() > 1)
|
||||
return;
|
||||
|
||||
// non existent?
|
||||
if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
|
||||
return;
|
||||
|
||||
// single component...
|
||||
|
||||
// skip doing it for Boolean vectors
|
||||
if (isBoolType(getContainedTypeId(accessChain.preSwizzleBaseType)))
|
||||
// too complex?
|
||||
// (this requires either a swizzle, or generating code for a dynamic component)
|
||||
if (accessChain.swizzle.size() > 1)
|
||||
return;
|
||||
|
||||
// single component, either in the swizzle and/or dynamic component
|
||||
if (accessChain.swizzle.size() == 1) {
|
||||
// handle static component
|
||||
assert(accessChain.component == NoResult);
|
||||
// handle static component selection
|
||||
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
|
||||
accessChain.swizzle.clear();
|
||||
// note, the only valid remaining dynamic access would be to this one
|
||||
// component, so don't bother even looking at accessChain.component
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
accessChain.component = NoResult;
|
||||
} else if (dynamic && accessChain.component != NoResult) {
|
||||
assert(accessChain.swizzle.size() == 0);
|
||||
// handle dynamic component
|
||||
accessChain.indexChain.push_back(accessChain.component);
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue