SPV: More corrections of <id> versus "immediate" operands.

This commit is contained in:
John Kessenich 2018-08-14 13:31:43 -06:00
parent 228e964bcc
commit 149afc3930
4 changed files with 147 additions and 69 deletions

View File

@ -3630,9 +3630,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
// 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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
} 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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
} 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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
// 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 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
#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 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
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 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
case glslang::EOpMaxInvocationsNonUniform:
case glslang::EOpAddInvocationsNonUniform:
groupOperation = spv::GroupOperationReduce;
spvGroupOperands.push_back(groupOperation);
break;
case glslang::EOpMinInvocationsInclusiveScan:
case glslang::EOpMaxInvocationsInclusiveScan:
@ -5429,7 +5451,6 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
case glslang::EOpAddInvocationsInclusiveScanNonUniform:
groupOperation = spv::GroupOperationInclusiveScan;
spvGroupOperands.push_back(groupOperation);
break;
case glslang::EOpMinInvocationsExclusiveScan:
case glslang::EOpMaxInvocationsExclusiveScan:
@ -5438,16 +5459,23 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
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 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
}
// 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 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv
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 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv
}
// 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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
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);

View File

@ -81,6 +81,7 @@ Id Builder::import(const char* name)
{
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 @@ void Builder::createNoResultOp(Op opCode)
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 @@ void Builder::createNoResultOp(Op opCode, Id operand)
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 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
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);

View File

@ -295,13 +295,14 @@ public:
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);

View File

@ -79,6 +79,11 @@ const MemorySemanticsMask MemorySemanticsAllMemory =
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 @@ public:
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);