|
|
@@ -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);
|
|
|
+ }
|
|
|
|
|
|
- // 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);
|
|
|
+
|
|
|
+ Id source = rvalue;
|
|
|
+
|
|
|
+ // dynamic component should be gone
|
|
|
+ assert(accessChain.component == NoResult);
|
|
|
|
|
|
- createStore(source, base, memoryAccess, scope, alignment);
|
|
|
+ // 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);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Comments in header
|