Generate separate stores for partially swizzled memory stores
Full vector and fully specified vector swizzle stores are not affected by this change, only partial swizzles ie swizzles with fewer components than the vector being stored to. Previously the vector being stored to loaded and any components not specified in the swizzle were used to create a full store to the vector. While this change generates more SPIR-V instructions, it is necessary for correctness. Fixes #2518.
This commit is contained in:
parent
9158061398
commit
6d5b40f051
50 changed files with 31343 additions and 26594 deletions
|
|
@ -743,6 +743,26 @@ Id Builder::getContainedTypeId(Id typeId, int member) const
|
|||
}
|
||||
}
|
||||
|
||||
// Figure out the final resulting type of the access chain.
|
||||
Id Builder::getResultingAccessChainType() const
|
||||
{
|
||||
assert(accessChain.base != NoResult);
|
||||
Id typeId = getTypeId(accessChain.base);
|
||||
|
||||
assert(isPointerType(typeId));
|
||||
typeId = getContainedTypeId(typeId);
|
||||
|
||||
for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
|
||||
if (isStructType(typeId)) {
|
||||
assert(isConstantScalar(accessChain.indexChain[i]));
|
||||
typeId = getContainedTypeId(typeId, getConstantScalar(accessChain.indexChain[i]));
|
||||
} else
|
||||
typeId = getContainedTypeId(typeId, accessChain.indexChain[i]);
|
||||
}
|
||||
|
||||
return typeId;
|
||||
}
|
||||
|
||||
// Return the immediately contained type of a given composite type.
|
||||
Id Builder::getContainedTypeId(Id typeId) const
|
||||
{
|
||||
|
|
@ -1585,16 +1605,7 @@ Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMa
|
|||
Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
|
||||
{
|
||||
// Figure out the final resulting type.
|
||||
spv::Id typeId = getTypeId(base);
|
||||
assert(isPointerType(typeId) && offsets.size() > 0);
|
||||
typeId = getContainedTypeId(typeId);
|
||||
for (int i = 0; i < (int)offsets.size(); ++i) {
|
||||
if (isStructType(typeId)) {
|
||||
assert(isConstantScalar(offsets[i]));
|
||||
typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
|
||||
} else
|
||||
typeId = getContainedTypeId(typeId, offsets[i]);
|
||||
}
|
||||
Id typeId = getResultingAccessChainType();
|
||||
typeId = makePointer(storageClass, typeId);
|
||||
|
||||
// Make the instruction
|
||||
|
|
@ -2794,28 +2805,58 @@ void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAcce
|
|||
assert(accessChain.isRValue == false);
|
||||
|
||||
transferAccessChainSwizzle(true);
|
||||
Id base = collapseAccessChain();
|
||||
addDecoration(base, nonUniform);
|
||||
|
||||
Id source = rvalue;
|
||||
// If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores.
|
||||
if (accessChain.swizzle.size() > 0 &&
|
||||
getNumTypeComponents(getResultingAccessChainType()) != (int)accessChain.swizzle.size() &&
|
||||
accessChain.component == NoResult) {
|
||||
for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
|
||||
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i]));
|
||||
|
||||
// dynamic component should be gone
|
||||
assert(accessChain.component == NoResult);
|
||||
Id base = collapseAccessChain();
|
||||
addDecoration(base, nonUniform);
|
||||
|
||||
// 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.
|
||||
if (accessChain.swizzle.size() > 0) {
|
||||
Id tempBaseId = createLoad(base, spv::NoPrecision);
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
|
||||
accessChain.indexChain.pop_back();
|
||||
accessChain.instr = NoResult;
|
||||
|
||||
// dynamic component should be gone
|
||||
assert(accessChain.component == NoResult);
|
||||
|
||||
Id source = createCompositeExtract(rvalue, getContainedTypeId(getTypeId(rvalue)), i);
|
||||
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope, alignment);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Id base = collapseAccessChain();
|
||||
addDecoration(base, nonUniform);
|
||||
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
Id source = rvalue;
|
||||
|
||||
// dynamic component should be gone
|
||||
assert(accessChain.component == NoResult);
|
||||
|
||||
// If swizzle still exists, it may be out-of-order, we must load the target vector,
|
||||
// extract and insert elements to perform writeMask and/or swizzle.
|
||||
if (accessChain.swizzle.size() > 0) {
|
||||
Id tempBaseId = createLoad(base, spv::NoPrecision);
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
|
||||
}
|
||||
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope, alignment);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope, alignment);
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue