Merge pull request #2702 from jeremy-lunarg/hayes-2518
Generate separate stores for partially swizzled memory stores
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -202,6 +202,7 @@ public:
|
||||
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
|
||||
ImageFormat getImageTypeFormat(Id typeId) const
|
||||
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
|
||||
Id getResultingAccessChainType() const;
|
||||
|
||||
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
|
||||
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
|
||||
|
||||
Reference in New Issue
Block a user