Implement SPV_GOOGLE_hlsl_functionality1.
Enabled via -fhlsl_functionality1
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 11257f0..b0eff21 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -126,6 +126,9 @@
void dumpSpv(std::vector<unsigned int>& out);
protected:
+ TGlslangToSpvTraverser(TGlslangToSpvTraverser&);
+ TGlslangToSpvTraverser& operator=(TGlslangToSpvTraverser&);
+
spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
@@ -153,7 +156,8 @@
glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
- void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix);
+ void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset,
+ int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix);
void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember);
bool isShaderEntryPoint(const glslang::TIntermAggregate* node);
@@ -182,10 +186,6 @@
spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
spv::Id getSymbolId(const glslang::TIntermSymbol* node);
- void addDecoration(spv::Id id, spv::Decoration dec);
- void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
- void addMemberDecoration(spv::Id id, int member, spv::Decoration dec);
- void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value);
spv::Id createSpvConstant(const glslang::TIntermTyped&);
spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
bool isTrivialLeaf(const glslang::TIntermTyped* node);
@@ -222,8 +222,10 @@
std::unordered_set<int> rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer
std::unordered_map<std::string, spv::Function*> functionMap;
std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
- std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper; // for mapping glslang block indices to spv indices (e.g., due to hidden members)
+ // for mapping glslang block indices to spv indices (e.g., due to hidden members):
+ std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper;
std::stack<bool> breakForLoop; // false means break for switch
+ std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
};
//
@@ -1195,6 +1197,36 @@
else
builder.setAccessChainLValue(id);
}
+
+ // Process linkage-only nodes for any special additional interface work.
+ if (linkageOnly) {
+ if (glslangIntermediate->getHlslFunctionality1()) {
+ // Map implicit counter buffers to their originating buffers, which should have been
+ // seen by now, given earlier pruning of unused counters, and preservation of order
+ // of declaration.
+ if (symbol->getType().getQualifier().isUniformOrBuffer()) {
+ if (!glslangIntermediate->hasCounterBufferName(symbol->getName())) {
+ // Save possible originating buffers for counter buffers, keyed by
+ // making the potential counter-buffer name.
+ std::string keyName = symbol->getName().c_str();
+ keyName = glslangIntermediate->addCounterBufferName(keyName);
+ counterOriginator[keyName] = symbol;
+ } else {
+ // Handle a counter buffer, by finding the saved originating buffer.
+ std::string keyName = symbol->getName().c_str();
+ auto it = counterOriginator.find(keyName);
+ if (it != counterOriginator.end()) {
+ id = getSymbolId(it->second);
+ if (id != spv::NoResult) {
+ spv::Id counterId = getSymbolId(symbol);
+ if (counterId != spv::NoResult)
+ builder.addDecorationId(id, spv::DecorationHlslCounterBufferGOOGLE, counterId);
+ }
+ }
+ }
+ }
+ }
+ }
}
bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
@@ -2709,89 +2741,102 @@
InheritQualifiers(memberQualifier, qualifier);
// using -1 above to indicate a hidden member
- if (member >= 0) {
- builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str());
- addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix));
- addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember));
- // Add interpolation and auxiliary storage decorations only to top-level members of Input and Output storage classes
- if (type.getQualifier().storage == glslang::EvqVaryingIn ||
- type.getQualifier().storage == glslang::EvqVaryingOut) {
- if (type.getBasicType() == glslang::EbtBlock ||
- glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
- addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier));
- addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier));
- }
+ if (member < 0)
+ continue;
+
+ builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str());
+ builder.addMemberDecoration(spvType, member,
+ TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix));
+ builder.addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember));
+ // Add interpolation and auxiliary storage decorations only to
+ // top-level members of Input and Output storage classes
+ if (type.getQualifier().storage == glslang::EvqVaryingIn ||
+ type.getQualifier().storage == glslang::EvqVaryingOut) {
+ if (type.getBasicType() == glslang::EbtBlock ||
+ glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
+ builder.addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier));
+ builder.addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier));
}
- addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier));
+ }
+ builder.addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier));
- if (type.getBasicType() == glslang::EbtBlock &&
- qualifier.storage == glslang::EvqBuffer) {
- // Add memory decorations only to top-level members of shader storage block
- std::vector<spv::Decoration> memory;
- TranslateMemoryDecoration(memberQualifier, memory);
- for (unsigned int i = 0; i < memory.size(); ++i)
- addMemberDecoration(spvType, member, memory[i]);
- }
+ if (type.getBasicType() == glslang::EbtBlock &&
+ qualifier.storage == glslang::EvqBuffer) {
+ // Add memory decorations only to top-level members of shader storage block
+ std::vector<spv::Decoration> memory;
+ TranslateMemoryDecoration(memberQualifier, memory);
+ for (unsigned int i = 0; i < memory.size(); ++i)
+ builder.addMemberDecoration(spvType, member, memory[i]);
+ }
- // Location assignment was already completed correctly by the front end,
- // just track whether a member needs to be decorated.
- // Ignore member locations if the container is an array, as that's
- // ill-specified and decisions have been made to not allow this.
- if (! type.isArray() && memberQualifier.hasLocation())
- builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
+ // Location assignment was already completed correctly by the front end,
+ // just track whether a member needs to be decorated.
+ // Ignore member locations if the container is an array, as that's
+ // ill-specified and decisions have been made to not allow this.
+ if (! type.isArray() && memberQualifier.hasLocation())
+ builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
- if (qualifier.hasLocation()) // track for upcoming inheritance
- locationOffset += glslangIntermediate->computeTypeLocationSize(
- glslangMember, glslangIntermediate->getStage());
+ if (qualifier.hasLocation()) // track for upcoming inheritance
+ locationOffset += glslangIntermediate->computeTypeLocationSize(
+ glslangMember, glslangIntermediate->getStage());
- // component, XFB, others
- if (glslangMember.getQualifier().hasComponent())
- builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangMember.getQualifier().layoutComponent);
- if (glslangMember.getQualifier().hasXfbOffset())
- builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangMember.getQualifier().layoutXfbOffset);
- else if (explicitLayout != glslang::ElpNone) {
- // figure out what to do with offset, which is accumulating
- int nextOffset;
- updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix);
- if (offset >= 0)
- builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
- offset = nextOffset;
- }
+ // component, XFB, others
+ if (glslangMember.getQualifier().hasComponent())
+ builder.addMemberDecoration(spvType, member, spv::DecorationComponent,
+ glslangMember.getQualifier().layoutComponent);
+ if (glslangMember.getQualifier().hasXfbOffset())
+ builder.addMemberDecoration(spvType, member, spv::DecorationOffset,
+ glslangMember.getQualifier().layoutXfbOffset);
+ else if (explicitLayout != glslang::ElpNone) {
+ // figure out what to do with offset, which is accumulating
+ int nextOffset;
+ updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix);
+ if (offset >= 0)
+ builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
+ offset = nextOffset;
+ }
- if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone)
- builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix));
+ if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone)
+ builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride,
+ getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix));
- // built-in variable decorations
- spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true);
- if (builtIn != spv::BuiltInMax)
- addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
+ // built-in variable decorations
+ spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true);
+ if (builtIn != spv::BuiltInMax)
+ builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
#ifdef NV_EXTENSIONS
- if (builtIn == spv::BuiltInLayer) {
- // SPV_NV_viewport_array2 extension
- if (glslangMember.getQualifier().layoutViewportRelative){
- addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV);
- builder.addCapability(spv::CapabilityShaderViewportMaskNV);
- builder.addExtension(spv::E_SPV_NV_viewport_array2);
- }
- if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){
- addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset);
- builder.addCapability(spv::CapabilityShaderStereoViewNV);
- builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
- }
+ if (builtIn == spv::BuiltInLayer) {
+ // SPV_NV_viewport_array2 extension
+ if (glslangMember.getQualifier().layoutViewportRelative){
+ builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV);
+ builder.addCapability(spv::CapabilityShaderViewportMaskNV);
+ builder.addExtension(spv::E_SPV_NV_viewport_array2);
}
- if (glslangMember.getQualifier().layoutPassthrough) {
- addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV);
- builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
- builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
+ if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){
+ builder.addMemberDecoration(spvType, member,
+ (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV,
+ glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset);
+ builder.addCapability(spv::CapabilityShaderStereoViewNV);
+ builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
}
+ }
+ if (glslangMember.getQualifier().layoutPassthrough) {
+ builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV);
+ builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
+ 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
- addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix));
- addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer()));
+ builder.addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix));
+ builder.addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer()));
if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
builder.addCapability(spv::CapabilityGeometryStreams);
builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
@@ -4037,7 +4082,7 @@
builder.promoteScalar(precision, left, right);
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
- addDecoration(result, noContraction);
+ builder.addDecoration(result, noContraction);
return builder.setPrecision(result, precision);
}
@@ -4107,7 +4152,7 @@
if (binOp != spv::OpNop) {
spv::Id result = builder.createBinOp(binOp, typeId, left, right);
- addDecoration(result, noContraction);
+ builder.addDecoration(result, noContraction);
return builder.setPrecision(result, precision);
}
@@ -4167,7 +4212,7 @@
if (firstClass) {
spv::Id result = builder.createBinOp(op, typeId, left, right);
- addDecoration(result, noContraction);
+ builder.addDecoration(result, noContraction);
return builder.setPrecision(result, precision);
}
@@ -4206,7 +4251,7 @@
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);
- addDecoration(result, noContraction);
+ builder.addDecoration(result, noContraction);
results.push_back(builder.setPrecision(result, precision));
}
@@ -4611,7 +4656,7 @@
id = builder.createUnaryOp(unaryOp, typeId, operand);
}
- addDecoration(id, noContraction);
+ builder.addDecoration(id, noContraction);
return builder.setPrecision(id, precision);
}
@@ -4638,7 +4683,7 @@
indexes.push_back(c);
spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes);
spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec);
- addDecoration(destVec, noContraction);
+ builder.addDecoration(destVec, noContraction);
results.push_back(builder.setPrecision(destVec, precision));
}
@@ -6147,11 +6192,11 @@
symbolValues[symbol->getId()] = id;
if (symbol->getBasicType() != glslang::EbtBlock) {
- addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
- addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
- addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier()));
+ builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
+ builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
+ builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier()));
if (symbol->getType().getQualifier().hasSpecConstantId())
- addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId);
+ builder.addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId);
if (symbol->getQualifier().hasIndex())
builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
if (symbol->getQualifier().hasComponent())
@@ -6163,7 +6208,7 @@
if (symbol->getQualifier().hasLocation())
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
- addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
+ builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
builder.addCapability(spv::CapabilityGeometryStreams);
builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream);
@@ -6196,13 +6241,13 @@
std::vector<spv::Decoration> memory;
TranslateMemoryDecoration(symbol->getType().getQualifier(), memory);
for (unsigned int i = 0; i < memory.size(); ++i)
- addDecoration(id, memory[i]);
+ builder.addDecoration(id, memory[i]);
}
// built-in variable decorations
spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
if (builtIn != spv::BuiltInMax)
- addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
+ builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
#ifdef NV_EXTENSIONS
if (builtIn == spv::BuiltInSampleMask) {
@@ -6212,7 +6257,7 @@
decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV;
else
decoration = (spv::Decoration)spv::DecorationMax;
- addDecoration(id, decoration);
+ builder.addDecoration(id, decoration);
if (decoration != spv::DecorationMax) {
builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage);
}
@@ -6220,55 +6265,34 @@
else if (builtIn == spv::BuiltInLayer) {
// SPV_NV_viewport_array2 extension
if (symbol->getQualifier().layoutViewportRelative) {
- addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV);
+ builder.addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV);
builder.addCapability(spv::CapabilityShaderViewportMaskNV);
builder.addExtension(spv::E_SPV_NV_viewport_array2);
}
if (symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048) {
- addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, symbol->getQualifier().layoutSecondaryViewportRelativeOffset);
+ builder.addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV,
+ symbol->getQualifier().layoutSecondaryViewportRelativeOffset);
builder.addCapability(spv::CapabilityShaderStereoViewNV);
builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
}
}
if (symbol->getQualifier().layoutPassthrough) {
- addDecoration(id, spv::DecorationPassthroughNV);
+ builder.addDecoration(id, spv::DecorationPassthroughNV);
builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
}
#endif
+ if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) {
+ builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
+ builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
+ symbol->getType().getQualifier().semanticName);
+ }
+
return id;
}
-// If 'dec' is valid, add no-operand decoration to an object
-void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec)
-{
- if (dec != spv::DecorationMax)
- builder.addDecoration(id, dec);
-}
-
-// If 'dec' is valid, add a one-operand decoration to an object
-void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec, unsigned value)
-{
- if (dec != spv::DecorationMax)
- builder.addDecoration(id, dec, value);
-}
-
-// If 'dec' is valid, add a no-operand decoration to a struct member
-void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec)
-{
- if (dec != spv::DecorationMax)
- builder.addMemberDecoration(id, (unsigned)member, dec);
-}
-
-// If 'dec' is valid, add a one-operand decoration to a struct member
-void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value)
-{
- if (dec != spv::DecorationMax)
- builder.addMemberDecoration(id, (unsigned)member, dec, value);
-}
-
// Make a full tree of instructions to build a SPIR-V specialization constant,
// or regular constant if possible.
//
@@ -6301,8 +6325,10 @@
for (int dim = 0; dim < 3; ++dim) {
bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
- if (specConst)
- addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim));
+ if (specConst) {
+ builder.addDecoration(dimConstId.back(), spv::DecorationSpecId,
+ glslangIntermediate->getLocalSizeSpecId(dim));
+ }
}
return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
}
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 66330b0..6e78b79 100644
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -1010,6 +1010,7 @@
{
if (decoration == spv::DecorationMax)
return;
+
Instruction* dec = new Instruction(OpDecorate);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
@@ -1019,8 +1020,37 @@
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
+void Builder::addDecoration(Id id, Decoration decoration, const char* s)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpDecorateStringGOOGLE);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(decoration);
+ dec->addStringOperand(s);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpDecorateId);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(decoration);
+ dec->addIdOperand(idDecoration);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{
+ if (decoration == spv::DecorationMax)
+ return;
+
Instruction* dec = new Instruction(OpMemberDecorate);
dec->addIdOperand(id);
dec->addImmediateOperand(member);
@@ -1031,6 +1061,20 @@
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
+void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpMemberDecorateStringGOOGLE);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(member);
+ dec->addImmediateOperand(decoration);
+ dec->addStringOperand(s);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
// Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint)
{
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 25495fb..dc76dae 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -237,7 +237,10 @@
void addName(Id, const char* name);
void addMemberName(Id, int member, const char* name);
void addDecoration(Id, Decoration, int num = -1);
+ void addDecoration(Id, Decoration, const char*);
+ void addDecorationId(Id id, Decoration, Id idDecoration);
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
+ void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
// At the end of what block do the next create*() instructions go?
void setBuildPoint(Block* bp) { buildPoint = bp; }
diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp
index 6171873..bfe9f7a 100644
--- a/SPIRV/doc.cpp
+++ b/SPIRV/doc.cpp
@@ -269,6 +269,9 @@
case 5252: return "ViewportRelativeNV";
case 5256: return "SecondaryViewportRelativeNV";
#endif
+
+ case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
+ case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE";
}
}
@@ -1208,6 +1211,7 @@
case 320: return "OpImageSparseRead";
case OpModuleProcessed: return "OpModuleProcessed";
+ case OpDecorateId: return "OpDecorateId";
case 333: return "OpGroupNonUniformElect";
case 334: return "OpGroupNonUniformAll";
@@ -1265,6 +1269,9 @@
case 5012: return "OpFragmentFetchAMD";
#endif
+ case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE";
+ case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
+
case OpcodeCeiling:
default:
return "Bad";
@@ -1356,7 +1363,10 @@
InstructionDesc[OpImageWrite].setResultAndType(false, false);
InstructionDesc[OpDecorationGroup].setResultAndType(true, false);
InstructionDesc[OpDecorate].setResultAndType(false, false);
+ InstructionDesc[OpDecorateId].setResultAndType(false, false);
+ InstructionDesc[OpDecorateStringGOOGLE].setResultAndType(false, false);
InstructionDesc[OpMemberDecorate].setResultAndType(false, false);
+ InstructionDesc[OpMemberDecorateStringGOOGLE].setResultAndType(false, false);
InstructionDesc[OpGroupDecorate].setResultAndType(false, false);
InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false);
InstructionDesc[OpName].setResultAndType(false, false);
@@ -1921,11 +1931,24 @@
InstructionDesc[OpDecorate].operands.push(OperandDecoration, "");
InstructionDesc[OpDecorate].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>.");
+ InstructionDesc[OpDecorateId].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpDecorateId].operands.push(OperandDecoration, "");
+ InstructionDesc[OpDecorateId].operands.push(OperandVariableIds, "See <<Decoration,'Decoration'>>.");
+
+ InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, "");
+ InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
+
InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'");
InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, "");
InstructionDesc[OpMemberDecorate].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>.");
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'");
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'");
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, "");
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
+
InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'");
InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'");