SPV: More corrections of <id> versus "immediate" operands.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 81f7f08..d8369d2 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -3630,9 +3630,10 @@
// Check for image functions other than queries
if (node->isImage()) {
- std::vector<spv::Id> operands;
+ std::vector<spv::IdImmediate> operands;
auto opIt = arguments.begin();
- operands.push_back(*(opIt++));
+ spv::IdImmediate image = { true, *(opIt++) };
+ operands.push_back(image);
// Handle subpass operations
// TODO: GLSL should change to have the "MS" only on the type rather than the
@@ -3643,38 +3644,47 @@
std::vector<spv::Id> comps;
comps.push_back(zero);
comps.push_back(zero);
- operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps));
+ spv::IdImmediate coord = { true,
+ builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps) };
+ operands.push_back(coord);
if (sampler.ms) {
- operands.push_back(spv::ImageOperandsSampleMask);
- operands.push_back(*(opIt++));
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsSampleMask };
+ operands.push_back(imageOperands);
+ spv::IdImmediate imageOperand = { true, *(opIt++) };
+ operands.push_back(imageOperand);
}
spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands);
builder.setPrecision(result, precision);
return result;
}
- operands.push_back(*(opIt++));
+ spv::IdImmediate coord = { true, *(opIt++) };
+ operands.push_back(coord);
#ifdef AMD_EXTENSIONS
if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) {
#else
if (node->getOp() == glslang::EOpImageLoad) {
#endif
if (sampler.ms) {
- operands.push_back(spv::ImageOperandsSampleMask);
- operands.push_back(*opIt);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsSampleMask };
+ operands.push_back(imageOperands);
+ spv::IdImmediate imageOperand = { true, *opIt };
+ operands.push_back(imageOperand);
#ifdef AMD_EXTENSIONS
} else if (cracked.lod) {
builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
- operands.push_back(spv::ImageOperandsLodMask);
- operands.push_back(*opIt);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsLodMask };
+ operands.push_back(imageOperands);
+ spv::IdImmediate imageOperand = { true, *opIt };
+ operands.push_back(imageOperand);
#endif
}
- if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown)
+ if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
- std::vector<spv::Id> result( 1, builder.createOp(spv::OpImageRead, resultType(), operands) );
+ std::vector<spv::Id> result(1, builder.createOp(spv::OpImageRead, resultType(), operands));
builder.setPrecision(result[0], precision);
// If needed, add a conversion constructor to the proper size.
@@ -3688,22 +3698,30 @@
} else if (node->getOp() == glslang::EOpImageStore) {
#endif
if (sampler.ms) {
- operands.push_back(*(opIt + 1));
- operands.push_back(spv::ImageOperandsSampleMask);
- operands.push_back(*opIt);
+ spv::IdImmediate texel = { true, *(opIt + 1) };
+ operands.push_back(texel);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsSampleMask };
+ operands.push_back(imageOperands);
+ spv::IdImmediate imageOperand = { true, *opIt };
+ operands.push_back(imageOperand);
#ifdef AMD_EXTENSIONS
} else if (cracked.lod) {
builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
- operands.push_back(*(opIt + 1));
- operands.push_back(spv::ImageOperandsLodMask);
- operands.push_back(*opIt);
+ spv::IdImmediate texel = { true, *(opIt + 1) };
+ operands.push_back(texel);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsLodMask };
+ operands.push_back(imageOperands);
+ spv::IdImmediate imageOperand = { true, *opIt };
+ operands.push_back(imageOperand);
#endif
- } else
- operands.push_back(*opIt);
+ } else {
+ spv::IdImmediate texel = { true, *opIt };
+ operands.push_back(texel);
+ }
builder.createNoResultOp(spv::OpImageWrite, operands);
- if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown)
+ if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat);
return spv::NoResult;
#ifdef AMD_EXTENSIONS
@@ -3712,19 +3730,23 @@
} else if (node->getOp() == glslang::EOpSparseImageLoad) {
#endif
builder.addCapability(spv::CapabilitySparseResidency);
- if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown)
+ if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
if (sampler.ms) {
- operands.push_back(spv::ImageOperandsSampleMask);
- operands.push_back(*opIt++);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsSampleMask };
+ operands.push_back(imageOperands);
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
#ifdef AMD_EXTENSIONS
} else if (cracked.lod) {
builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
- operands.push_back(spv::ImageOperandsLodMask);
- operands.push_back(*opIt++);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsLodMask };
+ operands.push_back(imageOperands);
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
#endif
}
@@ -3744,7 +3766,9 @@
// GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer,
// as the first source operand, is required by SPIR-V atomic operations.
- operands.push_back(sampler.ms ? *(opIt++) : builder.makeUintConstant(0)); // For non-MS, the value should be 0
+ // For non-MS, the sample value should be 0
+ spv::IdImmediate sample = { true, sampler.ms ? *(opIt++) : builder.makeUintConstant(0) };
+ operands.push_back(sample);
spv::Id resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
@@ -5383,7 +5407,7 @@
#endif
spv::Op opCode = spv::OpNop;
- std::vector<spv::Id> spvGroupOperands;
+ std::vector<spv::IdImmediate> spvGroupOperands;
spv::GroupOperation groupOperation = spv::GroupOperationMax;
if (op == glslang::EOpBallot || op == glslang::EOpReadFirstInvocation ||
@@ -5410,7 +5434,6 @@
builder.addExtension(spv::E_SPV_AMD_shader_ballot);
#endif
- spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
#ifdef AMD_EXTENSIONS
switch (op) {
case glslang::EOpMinInvocations:
@@ -5420,7 +5443,6 @@
case glslang::EOpMaxInvocationsNonUniform:
case glslang::EOpAddInvocationsNonUniform:
groupOperation = spv::GroupOperationReduce;
- spvGroupOperands.push_back(groupOperation);
break;
case glslang::EOpMinInvocationsInclusiveScan:
case glslang::EOpMaxInvocationsInclusiveScan:
@@ -5429,7 +5451,6 @@
case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
case glslang::EOpAddInvocationsInclusiveScanNonUniform:
groupOperation = spv::GroupOperationInclusiveScan;
- spvGroupOperands.push_back(groupOperation);
break;
case glslang::EOpMinInvocationsExclusiveScan:
case glslang::EOpMaxInvocationsExclusiveScan:
@@ -5438,16 +5459,23 @@
case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
case glslang::EOpAddInvocationsExclusiveScanNonUniform:
groupOperation = spv::GroupOperationExclusiveScan;
- spvGroupOperands.push_back(groupOperation);
break;
default:
break;
}
+ spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(scope);
+ if (groupOperation != spv::GroupOperationMax) {
+ spv::IdImmediate groupOp = { false, groupOperation };
+ spvGroupOperands.push_back(groupOp);
+ }
#endif
}
- for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt)
- spvGroupOperands.push_back(*opIt);
+ for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) {
+ spv::IdImmediate op = { true, *opIt };
+ spvGroupOperands.push_back(op);
+ }
switch (op) {
case glslang::EOpAnyInvocation:
@@ -5586,7 +5614,8 @@
}
// Create group invocation operations on a vector
-spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands)
+spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation,
+ spv::Id typeId, std::vector<spv::Id>& operands)
{
#ifdef AMD_EXTENSIONS
assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
@@ -5619,18 +5648,23 @@
for (int comp = 0; comp < numComponents; ++comp) {
std::vector<unsigned int> indexes;
indexes.push_back(comp);
- spv::Id scalar = builder.createCompositeExtract(operands[0], scalarType, indexes);
- std::vector<spv::Id> spvGroupOperands;
+ spv::IdImmediate scalar = { true, builder.createCompositeExtract(operands[0], scalarType, indexes) };
+ std::vector<spv::IdImmediate> spvGroupOperands;
if (op == spv::OpSubgroupReadInvocationKHR) {
spvGroupOperands.push_back(scalar);
- spvGroupOperands.push_back(operands[1]);
+ spv::IdImmediate operand = { true, operands[1] };
+ spvGroupOperands.push_back(operand);
} else if (op == spv::OpGroupBroadcast) {
- spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
+ spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(scope);
spvGroupOperands.push_back(scalar);
- spvGroupOperands.push_back(operands[1]);
+ spv::IdImmediate operand = { true, operands[1] };
+ spvGroupOperands.push_back(operand);
} else {
- spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
- spvGroupOperands.push_back(groupOperation);
+ spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(scope);
+ spv::IdImmediate groupOp = { false, groupOperation };
+ spvGroupOperands.push_back(groupOp);
spvGroupOperands.push_back(scalar);
}
@@ -5642,7 +5676,8 @@
}
// Create subgroup invocation operations.
-spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, spv::Id typeId,
+ std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
{
// Add the required capabilities.
switch (op) {
@@ -5890,14 +5925,11 @@
default: assert(0 && "Unhandled subgroup operation!");
}
- std::vector<spv::Id> spvGroupOperands;
-
- // Every operation begins with the Execution Scope operand.
- spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
-
- // Next, for all operations that use a Group Operation, push that as an operand.
+ // get the right Group Operation
+ spv::GroupOperation groupOperation = spv::GroupOperationMax;
switch (op) {
- default: break;
+ default:
+ break;
case glslang::EOpSubgroupBallotBitCount:
case glslang::EOpSubgroupAdd:
case glslang::EOpSubgroupMul:
@@ -5906,7 +5938,7 @@
case glslang::EOpSubgroupAnd:
case glslang::EOpSubgroupOr:
case glslang::EOpSubgroupXor:
- spvGroupOperands.push_back(spv::GroupOperationReduce);
+ groupOperation = spv::GroupOperationReduce;
break;
case glslang::EOpSubgroupBallotInclusiveBitCount:
case glslang::EOpSubgroupInclusiveAdd:
@@ -5916,7 +5948,7 @@
case glslang::EOpSubgroupInclusiveAnd:
case glslang::EOpSubgroupInclusiveOr:
case glslang::EOpSubgroupInclusiveXor:
- spvGroupOperands.push_back(spv::GroupOperationInclusiveScan);
+ groupOperation = spv::GroupOperationInclusiveScan;
break;
case glslang::EOpSubgroupBallotExclusiveBitCount:
case glslang::EOpSubgroupExclusiveAdd:
@@ -5926,7 +5958,7 @@
case glslang::EOpSubgroupExclusiveAnd:
case glslang::EOpSubgroupExclusiveOr:
case glslang::EOpSubgroupExclusiveXor:
- spvGroupOperands.push_back(spv::GroupOperationExclusiveScan);
+ groupOperation = spv::GroupOperationExclusiveScan;
break;
case glslang::EOpSubgroupClusteredAdd:
case glslang::EOpSubgroupClusteredMul:
@@ -5935,7 +5967,7 @@
case glslang::EOpSubgroupClusteredAnd:
case glslang::EOpSubgroupClusteredOr:
case glslang::EOpSubgroupClusteredXor:
- spvGroupOperands.push_back(spv::GroupOperationClusteredReduce);
+ groupOperation = spv::GroupOperationClusteredReduce;
break;
#ifdef NV_EXTENSIONS
case glslang::EOpSubgroupPartitionedAdd:
@@ -5945,7 +5977,7 @@
case glslang::EOpSubgroupPartitionedAnd:
case glslang::EOpSubgroupPartitionedOr:
case glslang::EOpSubgroupPartitionedXor:
- spvGroupOperands.push_back(spv::GroupOperationPartitionedReduceNV);
+ groupOperation = spv::GroupOperationPartitionedReduceNV;
break;
case glslang::EOpSubgroupPartitionedInclusiveAdd:
case glslang::EOpSubgroupPartitionedInclusiveMul:
@@ -5954,7 +5986,7 @@
case glslang::EOpSubgroupPartitionedInclusiveAnd:
case glslang::EOpSubgroupPartitionedInclusiveOr:
case glslang::EOpSubgroupPartitionedInclusiveXor:
- spvGroupOperands.push_back(spv::GroupOperationPartitionedInclusiveScanNV);
+ groupOperation = spv::GroupOperationPartitionedInclusiveScanNV;
break;
case glslang::EOpSubgroupPartitionedExclusiveAdd:
case glslang::EOpSubgroupPartitionedExclusiveMul:
@@ -5963,22 +5995,41 @@
case glslang::EOpSubgroupPartitionedExclusiveAnd:
case glslang::EOpSubgroupPartitionedExclusiveOr:
case glslang::EOpSubgroupPartitionedExclusiveXor:
- spvGroupOperands.push_back(spv::GroupOperationPartitionedExclusiveScanNV);
+ groupOperation = spv::GroupOperationPartitionedExclusiveScanNV;
break;
#endif
}
+ // build the instruction
+ std::vector<spv::IdImmediate> spvGroupOperands;
+
+ // Every operation begins with the Execution Scope operand.
+ spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(executionScope);
+
+ // Next, for all operations that use a Group Operation, push that as an operand.
+ if (groupOperation != spv::GroupOperationMax) {
+ spv::IdImmediate groupOperand = { false, groupOperation };
+ spvGroupOperands.push_back(groupOperand);
+ }
+
// Push back the operands next.
- for (auto opIt : operands) {
- spvGroupOperands.push_back(opIt);
+ for (auto opIt = operands.cbegin(); opIt != operands.cend(); ++opIt) {
+ spv::IdImmediate operand = { true, *opIt };
+ spvGroupOperands.push_back(operand);
}
// Some opcodes have additional operands.
+ spv::Id directionId = spv::NoResult;
switch (op) {
default: break;
- case glslang::EOpSubgroupQuadSwapHorizontal: spvGroupOperands.push_back(builder.makeUintConstant(0)); break;
- case glslang::EOpSubgroupQuadSwapVertical: spvGroupOperands.push_back(builder.makeUintConstant(1)); break;
- case glslang::EOpSubgroupQuadSwapDiagonal: spvGroupOperands.push_back(builder.makeUintConstant(2)); break;
+ case glslang::EOpSubgroupQuadSwapHorizontal: directionId = builder.makeUintConstant(0); break;
+ case glslang::EOpSubgroupQuadSwapVertical: directionId = builder.makeUintConstant(1); break;
+ case glslang::EOpSubgroupQuadSwapDiagonal: directionId = builder.makeUintConstant(2); break;
+ }
+ if (directionId != spv::NoResult) {
+ spv::IdImmediate direction = { true, directionId };
+ spvGroupOperands.push_back(direction);
}
return builder.createOp(opCode, typeId, spvGroupOperands);
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index c20641c..5a7bb5c 100755
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -81,6 +81,7 @@
{
Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
import->addStringOperand(name);
+ module.mapInstruction(import);
imports.push_back(std::unique_ptr<Instruction>(import));
return import->getResultId();
@@ -1331,7 +1332,7 @@
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
}
-// An opcode that has one operand, no result id, and no type
+// An opcode that has one id operand, no result id, and no type
void Builder::createNoResultOp(Op opCode, Id operand)
{
Instruction* op = new Instruction(opCode);
@@ -1339,12 +1340,16 @@
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
}
-// An opcode that has one operand, no result id, and no type
-void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
+// An opcode that has multiple operands, no result id, and no type
+void Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operands)
{
Instruction* op = new Instruction(opCode);
- for (auto it = operands.cbegin(); it != operands.cend(); ++it)
- op->addIdOperand(*it);
+ for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
+ if (it->isId)
+ op->addIdOperand(it->word);
+ else
+ op->addImmediateOperand(it->word);
+ }
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
}
@@ -1428,6 +1433,20 @@
return op->getResultId();
}
+Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& operands)
+{
+ Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
+ for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
+ if (it->isId)
+ op->addIdOperand(it->word);
+ else
+ op->addImmediateOperand(it->word);
+ }
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
{
Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 8894f01..01698b3 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -295,13 +295,14 @@
void createNoResultOp(Op);
void createNoResultOp(Op, Id operand);
- void createNoResultOp(Op, const std::vector<Id>& operands);
+ void createNoResultOp(Op, const std::vector<IdImmediate>& operands);
void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask);
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
Id createUnaryOp(Op, Id typeId, Id operand);
Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
Id createOp(Op, Id typeId, const std::vector<Id>& operands);
+ Id createOp(Op, Id typeId, const std::vector<IdImmediate>& operands);
Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&);
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h
index c126b4f..14d997d 100755
--- a/SPIRV/spvIR.h
+++ b/SPIRV/spvIR.h
@@ -79,6 +79,11 @@
MemorySemanticsAtomicCounterMemoryMask |
MemorySemanticsImageMemoryMask);
+struct IdImmediate {
+ bool isId; // true if word is an Id, false if word is an immediate
+ unsigned word;
+};
+
//
// SPIR-V IR instruction.
//
@@ -349,7 +354,9 @@
Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
const std::vector<Function*>& getFunctions() const { return functions; }
- spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); }
+ spv::Id getTypeId(Id resultId) const {
+ return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId();
+ }
StorageClass getStorageClass(Id typeId) const
{
assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer);