Non-functional. Rationalizations enabling future generalizations:
- Use much simpler method to update implicit array sizes.
The previous overly complicated method was error prone.
- Rationalize all use of unsized arrays.
- Combine decorations when generating SPIR-V, to simplify
adding extensions.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index d4eaa90..5d7350f 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -99,7 +99,13 @@
spv::Builder* builder_;
bool previous_flag_;
};
-}
+
+struct OpDecorations {
+ spv::Decoration precision;
+ spv::Decoration noContraction;
+};
+
+} // namespace
//
// The main holder of information for translating glslang to SPIR-V.
@@ -143,7 +149,8 @@
spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult);
void convertSwizzle(const glslang::TIntermAggregate&, std::vector<unsigned>& swizzle);
spv::Id convertGlslangToSpvType(const glslang::TType& type);
- spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&);
+ spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&,
+ bool lastBufferBlockMember);
bool filterMember(const glslang::TType& member);
spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct,
glslang::TLayoutPacking, const glslang::TQualifier&);
@@ -172,11 +179,15 @@
spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
- spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
- spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right);
- spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
- spv::Id createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
- spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id destTypeId, spv::Id operand, glslang::TBasicType typeProxy);
+ spv::Id createBinaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right,
+ glslang::TBasicType typeProxy, bool reduceComparison = true);
+ spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right);
+ spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand,
+ glslang::TBasicType typeProxy);
+ spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand,
+ glslang::TBasicType typeProxy);
+ spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand,
+ glslang::TBasicType typeProxy);
spv::Id createConversionOperation(glslang::TOperator op, spv::Id operand, int vectorSize);
spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
@@ -1275,8 +1286,9 @@
spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
// do the operation
- rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()),
- TranslateNoContractionDecoration(node->getType().getQualifier()),
+ OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
+ TranslateNoContractionDecoration(node->getType().getQualifier()) };
+ rValue = createBinaryOperation(node->getOp(), decorations,
convertGlslangToSpvType(node->getType()), leftRValue, rValue,
node->getType().getBasicType());
@@ -1403,8 +1415,9 @@
spv::Id right = accessChainLoad(node->getRight()->getType());
// get result
- spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()),
- TranslateNoContractionDecoration(node->getType().getQualifier()),
+ OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
+ TranslateNoContractionDecoration(node->getType().getQualifier()) };
+ spv::Id result = createBinaryOperation(node->getOp(), decorations,
convertGlslangToSpvType(node->getType()), left, right,
node->getLeft()->getType().getBasicType());
@@ -1445,7 +1458,7 @@
// 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.
- assert(node->getOperand()->getType().isRuntimeSizedArray());
+
glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
block->traverse(this);
unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst();
@@ -1482,20 +1495,20 @@
else
operand = accessChainLoad(node->getOperand()->getType());
- spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
- spv::Decoration noContraction = TranslateNoContractionDecoration(node->getType().getQualifier());
+ OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
+ TranslateNoContractionDecoration(node->getType().getQualifier()) };
// it could be a conversion
if (! result)
- result = createConversion(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType());
+ result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
// if not, then possibly an operation
if (! result)
- result = createUnaryOperation(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType());
+ result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
if (result) {
if (invertedType)
- result = createInvertedSwizzle(precision, *node->getOperand(), result);
+ result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result);
builder.clearAccessChain();
builder.setAccessChainRValue(result);
@@ -1533,8 +1546,7 @@
else
op = glslang::EOpSub;
- spv::Id result = createBinaryOperation(op, precision,
- TranslateNoContractionDecoration(node->getType().getQualifier()),
+ spv::Id result = createBinaryOperation(op, decorations,
convertGlslangToSpvType(node->getType()), operand, one,
node->getType().getBasicType());
assert(result != spv::NoResult);
@@ -1922,7 +1934,9 @@
spv::Id rightId = accessChainLoad(right->getType());
builder.setLine(node->getLoc().line);
- result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()),
+ OpDecorations decorations = { precision,
+ TranslateNoContractionDecoration(node->getType().getQualifier()) };
+ result = createBinaryOperation(binOp, decorations,
resultType(), leftId, rightId,
left->getType().getBasicType(), reduceComparison);
@@ -2020,11 +2034,14 @@
result = createNoArgOperation(node->getOp(), precision, resultType());
break;
case 1:
- result = createUnaryOperation(
- node->getOp(), precision,
- TranslateNoContractionDecoration(node->getType().getQualifier()),
- resultType(), operands.front(),
- glslangOperands[0]->getAsTyped()->getBasicType());
+ {
+ OpDecorations decorations = { precision,
+ TranslateNoContractionDecoration(node->getType().getQualifier()) };
+ result = createUnaryOperation(
+ node->getOp(), decorations,
+ resultType(), operands.front(),
+ glslangOperands[0]->getAsTyped()->getBasicType());
+ }
break;
default:
result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
@@ -2471,13 +2488,14 @@
// layout state rooted from the top-level type.
spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type)
{
- return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier());
+ return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false);
}
// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
// explicitLayout can be kept the same throughout the hierarchical recursive walk.
// Mutually recursive with convertGlslangStructToSpvType().
-spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier)
+spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type,
+ glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier, bool lastBufferBlockMember)
{
spv::Id spvType = spv::NoResult;
@@ -2630,13 +2648,12 @@
stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix);
}
- // Do the outer dimension, which might not be known for a runtime-sized array
- if (type.isRuntimeSizedArray()) {
- spvType = builder.makeRuntimeArray(spvType);
- } else {
- assert(type.getOuterArraySize() > 0);
+ // Do the outer dimension, which might not be known for a runtime-sized array.
+ // (Unsized arrays that survive through linking will be runtime-sized arrays)
+ if (type.isSizedArray())
spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride);
- }
+ else
+ spvType = builder.makeRuntimeArray(spvType);
if (stride > 0)
builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
}
@@ -2703,7 +2720,10 @@
memberQualifier.layoutLocation = qualifier.layoutLocation;
// recurse
- spvMembers.push_back(convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier));
+ bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer &&
+ i == (int)glslangMembers->size() - 1;
+ spvMembers.push_back(
+ convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember));
}
}
@@ -2805,6 +2825,12 @@
if (builtIn != spv::BuiltInMax)
builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
+ if (glslangIntermediate->getHlslFunctionality1() && memberQualifier.semanticName != nullptr) {
+ builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
+ builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
+ memberQualifier.semanticName);
+ }
+
#ifdef NV_EXTENSIONS
if (builtIn == spv::BuiltInLayer) {
// SPV_NV_viewport_array2 extension
@@ -2827,11 +2853,6 @@
builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
}
#endif
- if (glslangIntermediate->getHlslFunctionality1() && memberQualifier.semanticName != nullptr) {
- builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
- builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
- memberQualifier.semanticName);
- }
}
// Decorate the structure
@@ -3937,8 +3958,7 @@
}
// Translate AST operation to SPV operation, already having SPV-based operands/types.
-spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision,
- spv::Decoration noContraction,
+spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpDecorations& decorations,
spv::Id typeId, spv::Id left, spv::Id right,
glslang::TBasicType typeProxy, bool reduceComparison)
{
@@ -4075,15 +4095,15 @@
if (binOp != spv::OpNop) {
assert(comparison == false);
if (builder.isMatrix(left) || builder.isMatrix(right))
- return createBinaryMatrixOperation(binOp, precision, noContraction, typeId, left, right);
+ return createBinaryMatrixOperation(binOp, decorations, typeId, left, right);
// No matrix involved; make both operands be the same number of components, if needed
if (needMatchingVectors)
- builder.promoteScalar(precision, left, right);
+ builder.promoteScalar(decorations.precision, left, right);
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
- builder.addDecoration(result, noContraction);
- return builder.setPrecision(result, precision);
+ builder.addDecoration(result, decorations.noContraction);
+ return builder.setPrecision(result, decorations.precision);
}
if (! comparison)
@@ -4092,8 +4112,10 @@
// Handle comparison instructions
if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual)
- && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left)))
- return builder.createCompositeCompare(precision, left, right, op == glslang::EOpEqual);
+ && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) {
+ spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual);
+ return result;
+ }
switch (op) {
case glslang::EOpLessThan:
@@ -4152,8 +4174,8 @@
if (binOp != spv::OpNop) {
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
- builder.addDecoration(result, noContraction);
- return builder.setPrecision(result, precision);
+ builder.addDecoration(result, decorations.noContraction);
+ return builder.setPrecision(result, decorations.precision);
}
return 0;
@@ -4173,7 +4195,8 @@
// matrix op scalar op in {+, -, /}
// scalar op matrix op in {+, -, /}
//
-spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right)
+spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId,
+ spv::Id left, spv::Id right)
{
bool firstClass = true;
@@ -4212,8 +4235,8 @@
if (firstClass) {
spv::Id result = builder.createBinOp(op, typeId, left, right);
- builder.addDecoration(result, noContraction);
- return builder.setPrecision(result, precision);
+ builder.addDecoration(result, decorations.noContraction);
+ return builder.setPrecision(result, decorations.precision);
}
// Handle component-wise +, -, *, %, and / for all combinations of type.
@@ -4240,9 +4263,9 @@
std::vector<spv::Id> results;
spv::Id smearVec = spv::NoResult;
if (builder.isScalar(left))
- smearVec = builder.smearScalar(precision, left, vecType);
+ smearVec = builder.smearScalar(decorations.precision, left, vecType);
else if (builder.isScalar(right))
- smearVec = builder.smearScalar(precision, right, vecType);
+ smearVec = builder.smearScalar(decorations.precision, right, vecType);
// do each vector op
for (unsigned int c = 0; c < numCols; ++c) {
@@ -4251,12 +4274,13 @@
spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
- builder.addDecoration(result, noContraction);
- results.push_back(builder.setPrecision(result, precision));
+ builder.addDecoration(result, decorations.noContraction);
+ results.push_back(builder.setPrecision(result, decorations.precision));
}
// put the pieces together
- return builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision);
+ spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
+ return result;
}
default:
assert(0);
@@ -4264,7 +4288,8 @@
}
}
-spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId,
+ spv::Id operand, glslang::TBasicType typeProxy)
{
spv::Op unaryOp = spv::OpNop;
int extBuiltins = -1;
@@ -4277,7 +4302,7 @@
if (isFloat) {
unaryOp = spv::OpFNegate;
if (builder.isMatrixType(typeId))
- return createUnaryMatrixOperation(unaryOp, precision, noContraction, typeId, operand, typeProxy);
+ return createUnaryMatrixOperation(unaryOp, decorations, typeId, operand, typeProxy);
} else
unaryOp = spv::OpSNegate;
break;
@@ -4538,7 +4563,7 @@
// Handle all of the atomics in one place, in createAtomicOperation()
std::vector<spv::Id> operands;
operands.push_back(operand);
- return createAtomicOperation(op, precision, typeId, operands, typeProxy);
+ return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy);
}
case glslang::EOpBitFieldReverse:
@@ -4656,12 +4681,13 @@
id = builder.createUnaryOp(unaryOp, typeId, operand);
}
- builder.addDecoration(id, noContraction);
- return builder.setPrecision(id, precision);
+ builder.addDecoration(id, decorations.noContraction);
+ return builder.setPrecision(id, decorations.precision);
}
// Create a unary operation on a matrix
-spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType /* typeProxy */)
+spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId,
+ spv::Id operand, glslang::TBasicType /* typeProxy */)
{
// Handle unary operations vector by vector.
// The result type is the same type as the original type.
@@ -4683,12 +4709,13 @@
indexes.push_back(c);
spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes);
spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec);
- builder.addDecoration(destVec, noContraction);
- results.push_back(builder.setPrecision(destVec, precision));
+ builder.addDecoration(destVec, decorations.noContraction);
+ results.push_back(builder.setPrecision(destVec, decorations.precision));
}
// put the pieces together
- return builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision);
+ spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
+ return result;
}
spv::Id TGlslangToSpvTraverser::createConversionOperation(glslang::TOperator op, spv::Id operand, int vectorSize)
@@ -4808,7 +4835,8 @@
return result;
}
-spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id destType, spv::Id operand, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecorations& decorations, spv::Id destType,
+ spv::Id operand, glslang::TBasicType typeProxy)
{
spv::Op convOp = spv::OpNop;
spv::Id zero = 0;
@@ -4963,7 +4991,7 @@
case glslang::EOpConvFloat16ToFloat:
convOp = spv::OpFConvert;
if (builder.isMatrixType(destType))
- return createUnaryMatrixOperation(convOp, precision, noContraction, destType, operand, typeProxy);
+ return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy);
break;
case glslang::EOpConvFloat16ToInt8:
@@ -5143,7 +5171,8 @@
} else
result = builder.createUnaryOp(convOp, destType, operand);
- return builder.setPrecision(result, precision);
+ result = builder.setPrecision(result, decorations.precision);
+ return result;
}
spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize)