summaryrefslogtreecommitdiff
path: root/thirdparty/glslang/SPIRV/SpvBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/glslang/SPIRV/SpvBuilder.cpp')
-rw-r--r--thirdparty/glslang/SPIRV/SpvBuilder.cpp124
1 files changed, 97 insertions, 27 deletions
diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.cpp b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
index c8fbcc450e..e83306ebcb 100644
--- a/thirdparty/glslang/SPIRV/SpvBuilder.cpp
+++ b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
@@ -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
{
@@ -869,6 +889,30 @@ bool Builder::isSpecConstantOpCode(Op opcode) const
}
}
+Id Builder::makeNullConstant(Id typeId)
+{
+ Instruction* constant;
+
+ // See if we already made it.
+ Id existing = NoResult;
+ for (int i = 0; i < (int)nullConstants.size(); ++i) {
+ constant = nullConstants[i];
+ if (constant->getTypeId() == typeId)
+ existing = constant->getResultId();
+ }
+
+ if (existing != NoResult)
+ return existing;
+
+ // Make it
+ Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ nullConstants.push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+}
+
Id Builder::makeBoolConstant(bool b, bool specConstant)
{
Id typeId = makeBoolType();
@@ -1561,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
@@ -2519,7 +2554,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
int row = 0;
int col = 0;
- for (int arg = 0; arg < (int)sources.size(); ++arg) {
+ for (int arg = 0; arg < (int)sources.size() && col < numCols; ++arg) {
Id argComp = sources[arg];
for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
if (getNumComponents(sources[arg]) > 1) {
@@ -2531,6 +2566,10 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
row = 0;
col++;
}
+ if (col == numCols) {
+ // If more components are provided than fit the matrix, discard the rest.
+ break;
+ }
}
}
}
@@ -2766,28 +2805,59 @@ 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]));
+ accessChain.instr = NoResult;
- // 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);
+
+ // 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);
+ }
- createStore(source, base, memoryAccess, scope, alignment);
+ // 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