GLSL/SPV: Implement SPV_EXT_descriptor_indexing and GL_EXT_nonuniform_qualifier

This commit is contained in:
John Kessenich
2018-04-05 11:25:02 -06:00
parent 0b5e5da7e7
commit 5611c6d27b
31 changed files with 5887 additions and 4668 deletions

View File

@@ -102,6 +102,7 @@ private:
struct OpDecorations {
spv::Decoration precision;
spv::Decoration noContraction;
spv::Decoration nonUniform;
};
} // namespace
@@ -136,12 +137,14 @@ protected:
spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier);
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const;
spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, unsigned int& dependencyLength) const;
spv::StorageClass TranslateStorageClass(const glslang::TType&);
void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType);
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
spv::Id getSampledType(const glslang::TSampler&);
spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
@@ -443,6 +446,17 @@ spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qual
return spv::DecorationMax;
}
// If glslang type is nonUniform, return SPIR-V NonUniform decoration.
spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glslang::TQualifier& qualifier)
{
if (qualifier.isNonUniform()) {
builder.addExtension("SPV_EXT_descriptor_indexing");
builder.addCapability(spv::CapabilityShaderNonUniformEXT);
return spv::DecorationNonUniformEXT;
} else
return spv::DecorationMax;
}
// Translate a glslang built-in variable to a SPIR-V built in decoration. Also generate
// associated capabilities when required. For some built-in variables, a capability
// is generated only when using the variable in an executable instruction, but not when
@@ -889,6 +903,42 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
return spv::StorageClassFunction;
}
// Add capabilities pertaining to how an array is indexed.
void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType,
const glslang::TType& indexType)
{
if (indexType.getQualifier().isNonUniform()) {
// deal with an asserted non-uniform index
if (baseType.getBasicType() == glslang::EbtSampler) {
if (baseType.getQualifier().hasAttachment())
builder.addCapability(spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT);
else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer)
builder.addCapability(spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT);
else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer)
builder.addCapability(spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT);
else if (baseType.isImage())
builder.addCapability(spv::CapabilityStorageImageArrayNonUniformIndexingEXT);
else if (baseType.isTexture())
builder.addCapability(spv::CapabilitySampledImageArrayNonUniformIndexingEXT);
} else if (baseType.getBasicType() == glslang::EbtBlock) {
if (baseType.getQualifier().storage == glslang::EvqBuffer)
builder.addCapability(spv::CapabilityStorageBufferArrayNonUniformIndexingEXT);
else if (baseType.getQualifier().storage == glslang::EvqUniform)
builder.addCapability(spv::CapabilityUniformBufferArrayNonUniformIndexingEXT);
}
} else {
// assume a dynamically uniform index
if (baseType.getBasicType() == glslang::EbtSampler) {
if (baseType.getQualifier().hasAttachment())
builder.addCapability(spv::CapabilityInputAttachmentArrayDynamicIndexingEXT);
else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer)
builder.addCapability(spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT);
else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer)
builder.addCapability(spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT);
}
}
}
// Return whether or not the given type is something that should be tied to a
// descriptor set.
bool IsDescriptorResource(const glslang::TType& type)
@@ -1286,7 +1336,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// do the operation
OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
TranslateNoContractionDecoration(node->getType().getQualifier()) };
TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) };
rValue = createBinaryOperation(node->getOp(), decorations,
convertGlslangToSpvType(node->getType()), leftRValue, rValue,
node->getType().getBasicType());
@@ -1362,6 +1413,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
node->getRight()->traverse(this);
spv::Id index = accessChainLoad(node->getRight()->getType());
addIndirectionIndexCapabilities(node->getLeft()->getType(), node->getRight()->getType());
// restore the saved access chain
builder.setAccessChain(partial);
@@ -1415,7 +1468,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// get result
OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
TranslateNoContractionDecoration(node->getType().getQualifier()) };
TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) };
spv::Id result = createBinaryOperation(node->getOp(), decorations,
convertGlslangToSpvType(node->getType()), left, right,
node->getLeft()->getType().getBasicType());
@@ -1454,6 +1508,11 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
if (node->getOp() == glslang::EOpArrayLength) {
// Quite special; won't want to evaluate the operand.
// Currently, the front-end does not allow .length() on an array until it is sized,
// except for the last block membeor of an SSBO.
// TODO: If this changes, link-time sized arrays might show up here, and need their
// size extracted.
// Normal .length() would have been constant folded by the front-end.
// So, this has to be block.lastMember.length().
// SPV wants "block" and member number as the operands, go get them.
@@ -1495,7 +1554,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
operand = accessChainLoad(node->getOperand()->getType());
OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
TranslateNoContractionDecoration(node->getType().getQualifier()) };
TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) };
// it could be a conversion
if (! result)
@@ -1506,8 +1566,10 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
if (result) {
if (invertedType)
if (invertedType) {
result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result);
builder.addDecoration(result, decorations.nonUniform);
}
builder.clearAccessChain();
builder.setAccessChainRValue(result);
@@ -1934,7 +1996,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
builder.setLine(node->getLoc().line);
OpDecorations decorations = { precision,
TranslateNoContractionDecoration(node->getType().getQualifier()) };
TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) };
result = createBinaryOperation(binOp, decorations,
resultType(), leftId, rightId,
left->getType().getBasicType(), reduceComparison);
@@ -2035,7 +2098,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
case 1:
{
OpDecorations decorations = { precision,
TranslateNoContractionDecoration(node->getType().getQualifier()) };
TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) };
result = createUnaryOperation(
node->getOp(), decorations,
resultType(), operands.front(),
@@ -2651,8 +2715,13 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
// (Unsized arrays that survive through linking will be runtime-sized arrays)
if (type.isSizedArray())
spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride);
else
else {
if (!lastBufferBlockMember) {
builder.addExtension("SPV_EXT_descriptor_indexing");
builder.addCapability(spv::CapabilityRuntimeDescriptorArrayEXT);
}
spvType = builder.makeRuntimeArray(spvType);
}
if (stride > 0)
builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
}
@@ -2824,6 +2893,9 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
if (builtIn != spv::BuiltInMax)
builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
// nonuniform
builder.addMemberDecoration(spvType, member, TranslateNonUniformDecoration(glslangMember.getQualifier()));
if (glslangIntermediate->getHlslFunctionality1() && memberQualifier.semanticName != nullptr) {
builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
@@ -2891,7 +2963,8 @@ spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arra
spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
{
spv::Id nominalTypeId = builder.accessChainGetInferredType();
spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), nominalTypeId);
spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
TranslateNonUniformDecoration(type.getQualifier()), nominalTypeId);
// Need to convert to abstract types when necessary
if (type.getBasicType() == glslang::EbtBool) {
@@ -4102,6 +4175,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
builder.addDecoration(result, decorations.noContraction);
builder.addDecoration(result, decorations.nonUniform);
return builder.setPrecision(result, decorations.precision);
}
@@ -4113,6 +4187,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD
if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual)
&& (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) {
spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual);
builder.addDecoration(result, decorations.nonUniform);
return result;
}
@@ -4174,6 +4249,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD
if (binOp != spv::OpNop) {
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
builder.addDecoration(result, decorations.noContraction);
builder.addDecoration(result, decorations.nonUniform);
return builder.setPrecision(result, decorations.precision);
}
@@ -4235,6 +4311,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora
if (firstClass) {
spv::Id result = builder.createBinOp(op, typeId, left, right);
builder.addDecoration(result, decorations.noContraction);
builder.addDecoration(result, decorations.nonUniform);
return builder.setPrecision(result, decorations.precision);
}
@@ -4274,11 +4351,13 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora
spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
builder.addDecoration(result, decorations.noContraction);
builder.addDecoration(result, decorations.nonUniform);
results.push_back(builder.setPrecision(result, decorations.precision));
}
// put the pieces together
spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
builder.addDecoration(result, decorations.nonUniform);
return result;
}
default:
@@ -4687,6 +4766,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
}
builder.addDecoration(id, decorations.noContraction);
builder.addDecoration(id, decorations.nonUniform);
return builder.setPrecision(id, decorations.precision);
}
@@ -4715,11 +4795,13 @@ spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, OpDecorat
spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes);
spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec);
builder.addDecoration(destVec, decorations.noContraction);
builder.addDecoration(destVec, decorations.nonUniform);
results.push_back(builder.setPrecision(destVec, decorations.precision));
}
// put the pieces together
spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
builder.addDecoration(result, decorations.nonUniform);
return result;
}
@@ -5177,6 +5259,7 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora
result = builder.createUnaryOp(convOp, destType, operand);
result = builder.setPrecision(result, decorations.precision);
builder.addDecoration(result, decorations.nonUniform);
return result;
}
@@ -6396,6 +6479,9 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
if (builtIn != spv::BuiltInMax)
builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
// nonuniform
builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier()));
#ifdef NV_EXTENSIONS
if (builtIn == spv::BuiltInSampleMask) {
spv::Decoration decoration;

View File

@@ -2331,7 +2331,7 @@ void Builder::accessChainStore(Id rvalue)
}
// Comments in header
Id Builder::accessChainLoad(Decoration precision, Id resultType)
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType)
{
Id id;
@@ -2377,6 +2377,7 @@ Id Builder::accessChainLoad(Decoration precision, Id resultType)
// load through the access chain
id = createLoad(collapseAccessChain());
setPrecision(id, precision);
addDecoration(id, nonUniform);
}
// Done, unless there are swizzles to do
@@ -2397,6 +2398,7 @@ Id Builder::accessChainLoad(Decoration precision, Id resultType)
if (accessChain.component != NoResult)
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
addDecoration(id, nonUniform);
return id;
}

View File

@@ -554,7 +554,7 @@ public:
void accessChainStore(Id rvalue);
// use accessChain and swizzle to load an r-value
Id accessChainLoad(Decoration precision, Id ResultType);
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType);
// get the direct pointer for an l-value
Id accessChainGetLValue();

View File

@@ -255,6 +255,7 @@ const char* DecorationString(int decoration)
case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
#endif
case DecorationNonUniformEXT: return "DecorationNonUniformEXT";
case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE";
}
@@ -815,6 +816,19 @@ const char* CapabilityString(int info)
case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT";
case CapabilityShaderNonUniformEXT: return "CapabilityShaderNonUniformEXT";
case CapabilityRuntimeDescriptorArrayEXT: return "CapabilityRuntimeDescriptorArrayEXT";
case CapabilityInputAttachmentArrayDynamicIndexingEXT: return "CapabilityInputAttachmentArrayDynamicIndexingEXT";
case CapabilityUniformTexelBufferArrayDynamicIndexingEXT: return "CapabilityUniformTexelBufferArrayDynamicIndexingEXT";
case CapabilityStorageTexelBufferArrayDynamicIndexingEXT: return "CapabilityStorageTexelBufferArrayDynamicIndexingEXT";
case CapabilityUniformBufferArrayNonUniformIndexingEXT: return "CapabilityUniformBufferArrayNonUniformIndexingEXT";
case CapabilitySampledImageArrayNonUniformIndexingEXT: return "CapabilitySampledImageArrayNonUniformIndexingEXT";
case CapabilityStorageBufferArrayNonUniformIndexingEXT: return "CapabilityStorageBufferArrayNonUniformIndexingEXT";
case CapabilityStorageImageArrayNonUniformIndexingEXT: return "CapabilityStorageImageArrayNonUniformIndexingEXT";
case CapabilityInputAttachmentArrayNonUniformIndexingEXT: return "CapabilityInputAttachmentArrayNonUniformIndexingEXT";
case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "CapabilityUniformTexelBufferArrayNonUniformIndexingEXT";
case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "CapabilityStorageTexelBufferArrayNonUniformIndexingEXT";
default: return "Bad";
}
}

13
SPIRV/spirv.hpp Executable file → Normal file
View File

@@ -393,6 +393,7 @@ enum Decoration {
DecorationPassthroughNV = 5250,
DecorationViewportRelativeNV = 5252,
DecorationSecondaryViewportRelativeNV = 5256,
DecorationNonUniformEXT = 5300,
DecorationHlslCounterBufferGOOGLE = 5634,
DecorationHlslSemanticGOOGLE = 5635,
DecorationMax = 0x7fffffff,
@@ -692,6 +693,18 @@ enum Capability {
CapabilityPerViewAttributesNV = 5260,
CapabilityFragmentFullyCoveredEXT = 5265,
CapabilityGroupNonUniformPartitionedNV = 5297,
CapabilityShaderNonUniformEXT = 5301,
CapabilityRuntimeDescriptorArrayEXT = 5302,
CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303,
CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304,
CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305,
CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306,
CapabilitySampledImageArrayNonUniformIndexingEXT = 5307,
CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308,
CapabilityStorageImageArrayNonUniformIndexingEXT = 5309,
CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310,
CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311,
CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,
CapabilitySubgroupShuffleINTEL = 5568,
CapabilitySubgroupBufferBlockIOINTEL = 5569,
CapabilitySubgroupImageBlockIOINTEL = 5570,