Implement SPV_GOOGLE_hlsl_functionality1.

Enabled via -fhlsl_functionality1
This commit is contained in:
John Kessenich 2018-03-07 18:05:55 -07:00
parent cd23a47566
commit 5d610ee1dc
16 changed files with 402 additions and 150 deletions

View File

@ -126,6 +126,9 @@ public:
void dumpSpv(std::vector<unsigned int>& out); void dumpSpv(std::vector<unsigned int>& out);
protected: protected:
TGlslangToSpvTraverser(TGlslangToSpvTraverser&);
TGlslangToSpvTraverser& operator=(TGlslangToSpvTraverser&);
spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier); spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier); spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration); spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
@ -153,7 +156,8 @@ protected:
glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
int getMatrixStride(const glslang::TType& matrixType, 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); void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember);
bool isShaderEntryPoint(const glslang::TIntermAggregate* node); bool isShaderEntryPoint(const glslang::TIntermAggregate* node);
@ -182,10 +186,6 @@ protected:
spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy); 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 createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
spv::Id getSymbolId(const glslang::TIntermSymbol* node); 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 createSpvConstant(const glslang::TIntermTyped&);
spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivialLeaf(const glslang::TIntermTyped* node);
@ -222,8 +222,10 @@ protected:
std::unordered_set<int> rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer 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<std::string, spv::Function*> functionMap;
std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount]; 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::stack<bool> breakForLoop; // false means break for switch
std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
}; };
// //
@ -1195,6 +1197,36 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
else else
builder.setAccessChainLValue(id); 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) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
@ -2709,89 +2741,102 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
InheritQualifiers(memberQualifier, qualifier); InheritQualifiers(memberQualifier, qualifier);
// using -1 above to indicate a hidden member // using -1 above to indicate a hidden member
if (member >= 0) { if (member < 0)
builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str()); continue;
addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix));
addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember)); builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str());
// Add interpolation and auxiliary storage decorations only to top-level members of Input and Output storage classes builder.addMemberDecoration(spvType, member,
if (type.getQualifier().storage == glslang::EvqVaryingIn || TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix));
type.getQualifier().storage == glslang::EvqVaryingOut) { builder.addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember));
if (type.getBasicType() == glslang::EbtBlock || // Add interpolation and auxiliary storage decorations only to
glslangIntermediate->getSource() == glslang::EShSourceHlsl) { // top-level members of Input and Output storage classes
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier)); if (type.getQualifier().storage == glslang::EvqVaryingIn ||
addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier)); 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 && if (type.getBasicType() == glslang::EbtBlock &&
qualifier.storage == glslang::EvqBuffer) { qualifier.storage == glslang::EvqBuffer) {
// Add memory decorations only to top-level members of shader storage block // Add memory decorations only to top-level members of shader storage block
std::vector<spv::Decoration> memory; std::vector<spv::Decoration> memory;
TranslateMemoryDecoration(memberQualifier, memory); TranslateMemoryDecoration(memberQualifier, memory);
for (unsigned int i = 0; i < memory.size(); ++i) for (unsigned int i = 0; i < memory.size(); ++i)
addMemberDecoration(spvType, member, memory[i]); builder.addMemberDecoration(spvType, member, memory[i]);
} }
// Location assignment was already completed correctly by the front end, // Location assignment was already completed correctly by the front end,
// just track whether a member needs to be decorated. // just track whether a member needs to be decorated.
// Ignore member locations if the container is an array, as that's // Ignore member locations if the container is an array, as that's
// ill-specified and decisions have been made to not allow this. // ill-specified and decisions have been made to not allow this.
if (! type.isArray() && memberQualifier.hasLocation()) if (! type.isArray() && memberQualifier.hasLocation())
builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation); builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
if (qualifier.hasLocation()) // track for upcoming inheritance if (qualifier.hasLocation()) // track for upcoming inheritance
locationOffset += glslangIntermediate->computeTypeLocationSize( locationOffset += glslangIntermediate->computeTypeLocationSize(
glslangMember, glslangIntermediate->getStage()); glslangMember, glslangIntermediate->getStage());
// component, XFB, others // component, XFB, others
if (glslangMember.getQualifier().hasComponent()) if (glslangMember.getQualifier().hasComponent())
builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangMember.getQualifier().layoutComponent); builder.addMemberDecoration(spvType, member, spv::DecorationComponent,
if (glslangMember.getQualifier().hasXfbOffset()) glslangMember.getQualifier().layoutComponent);
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangMember.getQualifier().layoutXfbOffset); if (glslangMember.getQualifier().hasXfbOffset())
else if (explicitLayout != glslang::ElpNone) { builder.addMemberDecoration(spvType, member, spv::DecorationOffset,
// figure out what to do with offset, which is accumulating glslangMember.getQualifier().layoutXfbOffset);
int nextOffset; else if (explicitLayout != glslang::ElpNone) {
updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix); // figure out what to do with offset, which is accumulating
if (offset >= 0) int nextOffset;
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix);
offset = nextOffset; if (offset >= 0)
} builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
offset = nextOffset;
}
if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone) if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone)
builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix)); builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride,
getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix));
// built-in variable decorations // built-in variable decorations
spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true); spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true);
if (builtIn != spv::BuiltInMax) if (builtIn != spv::BuiltInMax)
addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
if (builtIn == spv::BuiltInLayer) { if (builtIn == spv::BuiltInLayer) {
// SPV_NV_viewport_array2 extension // SPV_NV_viewport_array2 extension
if (glslangMember.getQualifier().layoutViewportRelative){ if (glslangMember.getQualifier().layoutViewportRelative){
addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV); builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV);
builder.addCapability(spv::CapabilityShaderViewportMaskNV); builder.addCapability(spv::CapabilityShaderViewportMaskNV);
builder.addExtension(spv::E_SPV_NV_viewport_array2); 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 (glslangMember.getQualifier().layoutPassthrough) { if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){
addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV); builder.addMemberDecoration(spvType, member,
builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV,
builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); 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 #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 // Decorate the structure
addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); builder.addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix));
addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer())); builder.addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer()));
if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
builder.addCapability(spv::CapabilityGeometryStreams); builder.addCapability(spv::CapabilityGeometryStreams);
builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
@ -4037,7 +4082,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
builder.promoteScalar(precision, left, right); builder.promoteScalar(precision, left, right);
spv::Id result = builder.createBinOp(binOp, typeId, left, right); spv::Id result = builder.createBinOp(binOp, typeId, left, right);
addDecoration(result, noContraction); builder.addDecoration(result, noContraction);
return builder.setPrecision(result, precision); return builder.setPrecision(result, precision);
} }
@ -4107,7 +4152,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
if (binOp != spv::OpNop) { if (binOp != spv::OpNop) {
spv::Id result = builder.createBinOp(binOp, typeId, left, right); spv::Id result = builder.createBinOp(binOp, typeId, left, right);
addDecoration(result, noContraction); builder.addDecoration(result, noContraction);
return builder.setPrecision(result, precision); return builder.setPrecision(result, precision);
} }
@ -4167,7 +4212,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
if (firstClass) { if (firstClass) {
spv::Id result = builder.createBinOp(op, typeId, left, right); spv::Id result = builder.createBinOp(op, typeId, left, right);
addDecoration(result, noContraction); builder.addDecoration(result, noContraction);
return builder.setPrecision(result, precision); return builder.setPrecision(result, precision);
} }
@ -4206,7 +4251,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec; spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec; spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec); spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
addDecoration(result, noContraction); builder.addDecoration(result, noContraction);
results.push_back(builder.setPrecision(result, precision)); results.push_back(builder.setPrecision(result, precision));
} }
@ -4611,7 +4656,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
id = builder.createUnaryOp(unaryOp, typeId, operand); id = builder.createUnaryOp(unaryOp, typeId, operand);
} }
addDecoration(id, noContraction); builder.addDecoration(id, noContraction);
return builder.setPrecision(id, precision); return builder.setPrecision(id, precision);
} }
@ -4638,7 +4683,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Deco
indexes.push_back(c); indexes.push_back(c);
spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes); spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes);
spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec); spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec);
addDecoration(destVec, noContraction); builder.addDecoration(destVec, noContraction);
results.push_back(builder.setPrecision(destVec, precision)); results.push_back(builder.setPrecision(destVec, precision));
} }
@ -6147,11 +6192,11 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
symbolValues[symbol->getId()] = id; symbolValues[symbol->getId()] = id;
if (symbol->getBasicType() != glslang::EbtBlock) { if (symbol->getBasicType() != glslang::EbtBlock) {
addDecoration(id, TranslatePrecisionDecoration(symbol->getType())); builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier())); builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier())); builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier()));
if (symbol->getType().getQualifier().hasSpecConstantId()) 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()) if (symbol->getQualifier().hasIndex())
builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex); builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
if (symbol->getQualifier().hasComponent()) if (symbol->getQualifier().hasComponent())
@ -6163,7 +6208,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
if (symbol->getQualifier().hasLocation()) if (symbol->getQualifier().hasLocation())
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation); 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()) { if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
builder.addCapability(spv::CapabilityGeometryStreams); builder.addCapability(spv::CapabilityGeometryStreams);
builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream); builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream);
@ -6196,13 +6241,13 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
std::vector<spv::Decoration> memory; std::vector<spv::Decoration> memory;
TranslateMemoryDecoration(symbol->getType().getQualifier(), memory); TranslateMemoryDecoration(symbol->getType().getQualifier(), memory);
for (unsigned int i = 0; i < memory.size(); ++i) for (unsigned int i = 0; i < memory.size(); ++i)
addDecoration(id, memory[i]); builder.addDecoration(id, memory[i]);
} }
// built-in variable decorations // built-in variable decorations
spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
if (builtIn != spv::BuiltInMax) if (builtIn != spv::BuiltInMax)
addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
if (builtIn == spv::BuiltInSampleMask) { if (builtIn == spv::BuiltInSampleMask) {
@ -6212,7 +6257,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV; decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV;
else else
decoration = (spv::Decoration)spv::DecorationMax; decoration = (spv::Decoration)spv::DecorationMax;
addDecoration(id, decoration); builder.addDecoration(id, decoration);
if (decoration != spv::DecorationMax) { if (decoration != spv::DecorationMax) {
builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage); builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage);
} }
@ -6220,55 +6265,34 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
else if (builtIn == spv::BuiltInLayer) { else if (builtIn == spv::BuiltInLayer) {
// SPV_NV_viewport_array2 extension // SPV_NV_viewport_array2 extension
if (symbol->getQualifier().layoutViewportRelative) { if (symbol->getQualifier().layoutViewportRelative) {
addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV); builder.addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV);
builder.addCapability(spv::CapabilityShaderViewportMaskNV); builder.addCapability(spv::CapabilityShaderViewportMaskNV);
builder.addExtension(spv::E_SPV_NV_viewport_array2); builder.addExtension(spv::E_SPV_NV_viewport_array2);
} }
if (symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048) { 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.addCapability(spv::CapabilityShaderStereoViewNV);
builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
} }
} }
if (symbol->getQualifier().layoutPassthrough) { if (symbol->getQualifier().layoutPassthrough) {
addDecoration(id, spv::DecorationPassthroughNV); builder.addDecoration(id, spv::DecorationPassthroughNV);
builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
} }
#endif #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; 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, // Make a full tree of instructions to build a SPIR-V specialization constant,
// or regular constant if possible. // or regular constant if possible.
// //
@ -6301,8 +6325,10 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n
for (int dim = 0; dim < 3; ++dim) { for (int dim = 0; dim < 3; ++dim) {
bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
if (specConst) if (specConst) {
addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim)); builder.addDecoration(dimConstId.back(), spv::DecorationSpecId,
glslangIntermediate->getLocalSizeSpecId(dim));
}
} }
return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
} }

View File

@ -1010,6 +1010,7 @@ void Builder::addDecoration(Id id, Decoration decoration, int num)
{ {
if (decoration == spv::DecorationMax) if (decoration == spv::DecorationMax)
return; return;
Instruction* dec = new Instruction(OpDecorate); Instruction* dec = new Instruction(OpDecorate);
dec->addIdOperand(id); dec->addIdOperand(id);
dec->addImmediateOperand(decoration); dec->addImmediateOperand(decoration);
@ -1019,8 +1020,37 @@ void Builder::addDecoration(Id id, Decoration decoration, int num)
decorations.push_back(std::unique_ptr<Instruction>(dec)); 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) void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{ {
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpMemberDecorate); Instruction* dec = new Instruction(OpMemberDecorate);
dec->addIdOperand(id); dec->addIdOperand(id);
dec->addImmediateOperand(member); dec->addImmediateOperand(member);
@ -1031,6 +1061,20 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
decorations.push_back(std::unique_ptr<Instruction>(dec)); 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 // Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint) Function* Builder::makeEntryPoint(const char* entryPoint)
{ {

View File

@ -237,7 +237,10 @@ public:
void addName(Id, const char* name); void addName(Id, const char* name);
void addMemberName(Id, int member, const char* name); void addMemberName(Id, int member, const char* name);
void addDecoration(Id, Decoration, int num = -1); 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, int num = -1);
void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
// At the end of what block do the next create*() instructions go? // At the end of what block do the next create*() instructions go?
void setBuildPoint(Block* bp) { buildPoint = bp; } void setBuildPoint(Block* bp) { buildPoint = bp; }

View File

@ -269,6 +269,9 @@ const char* DecorationString(int decoration)
case 5252: return "ViewportRelativeNV"; case 5252: return "ViewportRelativeNV";
case 5256: return "SecondaryViewportRelativeNV"; case 5256: return "SecondaryViewportRelativeNV";
#endif #endif
case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE";
} }
} }
@ -1208,6 +1211,7 @@ const char* OpcodeString(int op)
case 320: return "OpImageSparseRead"; case 320: return "OpImageSparseRead";
case OpModuleProcessed: return "OpModuleProcessed"; case OpModuleProcessed: return "OpModuleProcessed";
case OpDecorateId: return "OpDecorateId";
case 333: return "OpGroupNonUniformElect"; case 333: return "OpGroupNonUniformElect";
case 334: return "OpGroupNonUniformAll"; case 334: return "OpGroupNonUniformAll";
@ -1265,6 +1269,9 @@ const char* OpcodeString(int op)
case 5012: return "OpFragmentFetchAMD"; case 5012: return "OpFragmentFetchAMD";
#endif #endif
case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE";
case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
case OpcodeCeiling: case OpcodeCeiling:
default: default:
return "Bad"; return "Bad";
@ -1356,7 +1363,10 @@ void Parameterize()
InstructionDesc[OpImageWrite].setResultAndType(false, false); InstructionDesc[OpImageWrite].setResultAndType(false, false);
InstructionDesc[OpDecorationGroup].setResultAndType(true, false); InstructionDesc[OpDecorationGroup].setResultAndType(true, false);
InstructionDesc[OpDecorate].setResultAndType(false, false); InstructionDesc[OpDecorate].setResultAndType(false, false);
InstructionDesc[OpDecorateId].setResultAndType(false, false);
InstructionDesc[OpDecorateStringGOOGLE].setResultAndType(false, false);
InstructionDesc[OpMemberDecorate].setResultAndType(false, false); InstructionDesc[OpMemberDecorate].setResultAndType(false, false);
InstructionDesc[OpMemberDecorateStringGOOGLE].setResultAndType(false, false);
InstructionDesc[OpGroupDecorate].setResultAndType(false, false); InstructionDesc[OpGroupDecorate].setResultAndType(false, false);
InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false); InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false);
InstructionDesc[OpName].setResultAndType(false, false); InstructionDesc[OpName].setResultAndType(false, false);
@ -1921,11 +1931,24 @@ void Parameterize()
InstructionDesc[OpDecorate].operands.push(OperandDecoration, ""); InstructionDesc[OpDecorate].operands.push(OperandDecoration, "");
InstructionDesc[OpDecorate].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>."); 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(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'"); InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'");
InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, ""); InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, "");
InstructionDesc[OpMemberDecorate].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>."); 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(OperandId, "'Decoration Group'");
InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'"); InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'");

View File

@ -101,6 +101,7 @@ enum TOptions {
EOptionInvertY = (1 << 30), EOptionInvertY = (1 << 30),
EOptionDumpBareVersion = (1 << 31), EOptionDumpBareVersion = (1 << 31),
}; };
bool targetHlslFunctionality1 = false;
// //
// Return codes from main/exit(). // Return codes from main/exit().
@ -523,7 +524,7 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
setOpenGlSpv(); setOpenGlSpv();
OpenGLClientVersion = glslang::EShTargetOpenGL_450; OpenGLClientVersion = glslang::EShTargetOpenGL_450;
} else } else
Error("--target-env expected vulkan1.0, opengl, or hlsl-16bit-types"); Error("--target-env expected vulkan1.0, vulkan1.1, or opengl");
} }
bumpArg(); bumpArg();
} else if (lowerword == "variable-name" || // synonyms } else if (lowerword == "variable-name" || // synonyms
@ -613,6 +614,12 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
Error("no <name> provided for -e"); Error("no <name> provided for -e");
bumpArg(); bumpArg();
break; break;
case 'f':
if (strcmp(&argv[0][2], "hlsl_functionality1") == 0)
targetHlslFunctionality1 = true;
else
Error("-f: expected hlsl_functionality1");
break;
case 'g': case 'g':
Options |= EOptionDebug; Options |= EOptionDebug;
break; break;
@ -874,14 +881,15 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
: glslang::EShSourceGlsl, : glslang::EShSourceGlsl,
compUnit.stage, glslang::EShClientVulkan, ClientInputSemanticsVersion); compUnit.stage, glslang::EShClientVulkan, ClientInputSemanticsVersion);
shader->setEnvClient(glslang::EShClientVulkan, VulkanClientVersion); shader->setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
shader->setEnvTarget(glslang::EShTargetSpv, TargetVersion);
} else { } else {
shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl
: glslang::EShSourceGlsl, : glslang::EShSourceGlsl,
compUnit.stage, glslang::EShClientOpenGL, ClientInputSemanticsVersion); compUnit.stage, glslang::EShClientOpenGL, ClientInputSemanticsVersion);
shader->setEnvClient(glslang::EShClientOpenGL, OpenGLClientVersion); shader->setEnvClient(glslang::EShClientOpenGL, OpenGLClientVersion);
shader->setEnvTarget(glslang::EshTargetSpv, TargetVersion);
} }
shader->setEnvTarget(glslang::EShTargetSpv, TargetVersion);
if (targetHlslFunctionality1)
shader->setEnvTargetHlslFunctionality1();
} }
shaders.push_back(shader); shaders.push_back(shader);
@ -1318,6 +1326,9 @@ void usage()
" -d default to desktop (#version 110) when there is no shader #version\n" " -d default to desktop (#version 110) when there is no shader #version\n"
" (default is ES version 100)\n" " (default is ES version 100)\n"
" -e <name> specify <name> as the entry-point name\n" " -e <name> specify <name> as the entry-point name\n"
" -f{hlsl_functionality1}\n"
" 'hlsl_functionality1' enables use of the\n"
" SPV_GOOGLE_hlsl_functionality1 extension\n"
" -g generate debug information\n" " -g generate debug information\n"
" -h print this usage message\n" " -h print this usage message\n"
" -i intermediate tree (glslang AST) is printed out\n" " -i intermediate tree (glslang AST) is printed out\n"
@ -1390,8 +1401,8 @@ void usage()
" set execution environment that emitted code\n" " set execution environment that emitted code\n"
" will execute in (as opposed to the language\n" " will execute in (as opposed to the language\n"
" semantics selected by --client) defaults:\n" " semantics selected by --client) defaults:\n"
" 'vulkan1.0' under '--client vulkan<ver>'\n" " 'vulkan1.0' under '--client vulkan<ver>'\n"
" 'opengl' under '--client opengl<ver>'\n" " 'opengl' under '--client opengl<ver>'\n"
" --variable-name <name> Creates a C header file that contains a\n" " --variable-name <name> Creates a C header file that contains a\n"
" uint32_t array named <name>\n" " uint32_t array named <name>\n"
" initialized with the shader binary code.\n" " initialized with the shader binary code.\n"

View File

@ -0,0 +1,125 @@
hlsl.structbuffer.incdec.frag
// Module Version 10000
// Generated by (magic number): 80006
// Id's are bound by 70
Capability Shader
Extension "SPV_GOOGLE_hlsl_functionality1"
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 63 66
ExecutionMode 4 OriginUpperLeft
Source HLSL 500
Name 4 "main"
Name 12 "@main(u1;"
Name 11 "pos"
Name 16 "result"
Name 20 "sbuf_rw_i"
MemberName 20(sbuf_rw_i) 0 "@data"
Name 22 "sbuf_rw_i"
Name 26 "sbuf_rw_d"
Name 27 "sbuf_rw_nocounter"
Name 33 "c1"
Name 34 "sbuf_rw_i@count"
MemberName 34(sbuf_rw_i@count) 0 "@count"
Name 36 "sbuf_rw_i@count"
Name 42 "c2"
Name 43 "sbuf_rw_d@count"
Name 61 "pos"
Name 63 "pos"
Name 66 "@entryPointOutput"
Name 67 "param"
Decorate 19 ArrayStride 16
MemberDecorate 20(sbuf_rw_i) 0 Offset 0
Decorate 20(sbuf_rw_i) BufferBlock
Decorate 22(sbuf_rw_i) DescriptorSet 0
Decorate 26(sbuf_rw_d) DescriptorSet 0
Decorate 27(sbuf_rw_nocounter) DescriptorSet 0
MemberDecorate 34(sbuf_rw_i@count) 0 Offset 0
Decorate 34(sbuf_rw_i@count) BufferBlock
Decorate 36(sbuf_rw_i@count) DescriptorSet 0
Decorate 43(sbuf_rw_d@count) DescriptorSet 0
Decorate 63(pos) Flat
Decorate 63(pos) Location 0
DecorateStringGOOGLE 63(pos) DecorationHlslSemanticGOOGLE "FOO"
Decorate 66(@entryPointOutput) Location 0
DecorateStringGOOGLE 66(@entryPointOutput) DecorationHlslSemanticGOOGLE "SV_TARGET0"
DecorateId 22(sbuf_rw_i) DecorationHlslCounterBufferGOOGLE 36(sbuf_rw_i@count)
DecorateId 26(sbuf_rw_d) DecorationHlslCounterBufferGOOGLE 43(sbuf_rw_d@count)
2: TypeVoid
3: TypeFunction 2
6: TypeInt 32 0
7: TypePointer Function 6(int)
8: TypeFloat 32
9: TypeVector 8(float) 4
10: TypeFunction 9(fvec4) 7(ptr)
14: TypeVector 6(int) 4
15: TypePointer Function 14(ivec4)
17: 6(int) Constant 0
18: 14(ivec4) ConstantComposite 17 17 17 17
19: TypeRuntimeArray 14(ivec4)
20(sbuf_rw_i): TypeStruct 19
21: TypePointer Uniform 20(sbuf_rw_i)
22(sbuf_rw_i): 21(ptr) Variable Uniform
23: TypeInt 32 1
24: 23(int) Constant 0
25: 23(int) Constant 7
26(sbuf_rw_d): 21(ptr) Variable Uniform
27(sbuf_rw_nocounter): 21(ptr) Variable Uniform
28: 23(int) Constant 5
29: 6(int) Constant 2
30: 14(ivec4) ConstantComposite 29 29 29 29
31: TypePointer Uniform 14(ivec4)
34(sbuf_rw_i@count): TypeStruct 23(int)
35: TypePointer Uniform 34(sbuf_rw_i@count)
36(sbuf_rw_i@count): 35(ptr) Variable Uniform
37: TypePointer Uniform 23(int)
39: 23(int) Constant 1
40: 6(int) Constant 1
43(sbuf_rw_d@count): 35(ptr) Variable Uniform
45: 23(int) Constant 4294967295
62: TypePointer Input 6(int)
63(pos): 62(ptr) Variable Input
65: TypePointer Output 9(fvec4)
66(@entryPointOutput): 65(ptr) Variable Output
4(main): 2 Function None 3
5: Label
61(pos): 7(ptr) Variable Function
67(param): 7(ptr) Variable Function
64: 6(int) Load 63(pos)
Store 61(pos) 64
68: 6(int) Load 61(pos)
Store 67(param) 68
69: 9(fvec4) FunctionCall 12(@main(u1;) 67(param)
Store 66(@entryPointOutput) 69
Return
FunctionEnd
12(@main(u1;): 9(fvec4) Function None 10
11(pos): 7(ptr) FunctionParameter
13: Label
16(result): 15(ptr) Variable Function
33(c1): 7(ptr) Variable Function
42(c2): 7(ptr) Variable Function
Store 16(result) 18
32: 31(ptr) AccessChain 27(sbuf_rw_nocounter) 24 28
Store 32 30
38: 37(ptr) AccessChain 36(sbuf_rw_i@count) 24
41: 6(int) AtomicIAdd 38 40 17 39
Store 33(c1) 41
44: 37(ptr) AccessChain 43(sbuf_rw_d@count) 24
46: 6(int) AtomicIAdd 44 40 17 45
47: 6(int) IAdd 46 45
Store 42(c2) 47
48: 7(ptr) AccessChain 16(result) 17
49: 6(int) Load 48
50: 8(float) ConvertUToF 49
51: 7(ptr) AccessChain 16(result) 40
52: 6(int) Load 51
53: 8(float) ConvertUToF 52
54: 6(int) Load 33(c1)
55: 8(float) ConvertUToF 54
56: 6(int) Load 42(c2)
57: 8(float) ConvertUToF 56
58: 9(fvec4) CompositeConstruct 50 53 55 57
ReturnValue 58
FunctionEnd

View File

@ -201,6 +201,13 @@ diff -b $BASEDIR/hlsl.y-negate-2.vert.out $TARGETDIR/hlsl.y-negate-2.vert.out ||
$EXE -H -e main -V -D -Od -H -i --invert-y hlsl.y-negate-3.vert > $TARGETDIR/hlsl.y-negate-3.vert.out $EXE -H -e main -V -D -Od -H -i --invert-y hlsl.y-negate-3.vert > $TARGETDIR/hlsl.y-negate-3.vert.out
diff -b $BASEDIR/hlsl.y-negate-3.vert.out $TARGETDIR/hlsl.y-negate-3.vert.out || HASERROR=1 diff -b $BASEDIR/hlsl.y-negate-3.vert.out $TARGETDIR/hlsl.y-negate-3.vert.out || HASERROR=1
#
# Testing hlsl_functionality1
#
$EXE -H -e main -D -Od -fhlsl_functionality1 hlsl.structbuffer.incdec.frag > \
$TARGETDIR/hlsl.structbuffer.incdec.frag.hlslfun1.out
diff -b $BASEDIR/hlsl.structbuffer.incdec.frag.hlslfun1.out $TARGETDIR/hlsl.structbuffer.incdec.frag.hlslfun1.out || HASERROR=1
# #
# Final checking # Final checking
# #

View File

@ -228,6 +228,7 @@ void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op,
// must still be valid. // must still be valid.
// It is okay if the symbol's type will be subsequently edited; // It is okay if the symbol's type will be subsequently edited;
// the modifications will be tracked. // the modifications will be tracked.
// Order is preserved, to avoid creating novel forward references.
void TParseContextBase::trackLinkage(TSymbol& symbol) void TParseContextBase::trackLinkage(TSymbol& symbol)
{ {
if (!parsingBuiltins) if (!parsingBuiltins)
@ -602,7 +603,7 @@ void TParseContextBase::finish()
if (parsingBuiltins) if (parsingBuiltins)
return; return;
// Transfer the linkage symbols to AST nodes // Transfer the linkage symbols to AST nodes, preserving order.
TIntermAggregate* linkage = new TIntermAggregate; TIntermAggregate* linkage = new TIntermAggregate;
for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i) for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
intermediate.addSymbolLinkageNode(linkage, **i); intermediate.addSymbolLinkageNode(linkage, **i);

View File

@ -187,7 +187,7 @@ protected:
TParseContextBase& operator=(TParseContextBase&); TParseContextBase& operator=(TParseContextBase&);
const bool parsingBuiltins; // true if parsing built-in symbols/functions const bool parsingBuiltins; // true if parsing built-in symbols/functions
TVector<TSymbol*> linkageSymbols; // these need to be transferred to 'linkage', after all editing is done TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving
TScanContext* scanContext; TScanContext* scanContext;
TPpContext* ppContext; TPpContext* ppContext;
TBuiltInResource resources; TBuiltInResource resources;

View File

@ -768,6 +768,8 @@ bool ProcessDeferred(
SpvVersion spvVersion; SpvVersion spvVersion;
EShLanguage stage = compiler->getLanguage(); EShLanguage stage = compiler->getLanguage();
TranslateEnvironment(environment, messages, source, stage, spvVersion); TranslateEnvironment(environment, messages, source, stage, spvVersion);
if (environment != nullptr && environment->target.hlslFunctionality1)
intermediate.setHlslFunctionality1();
// First, without using the preprocessor or parser, find the #version, so we know what // First, without using the preprocessor or parser, find the #version, so we know what
// symbol tables, processing rules, etc. to set up. This does not need the extra strings // symbol tables, processing rules, etc. to set up. This does not need the extra strings
@ -1629,6 +1631,7 @@ TShader::TShader(EShLanguage s)
environment.input.dialect = EShClientNone; environment.input.dialect = EShClientNone;
environment.client.client = EShClientNone; environment.client.client = EShClientNone;
environment.target.language = EShTargetNone; environment.target.language = EShTargetNone;
environment.target.hlslFunctionality1 = false;
} }
TShader::~TShader() TShader::~TShader()

View File

@ -210,7 +210,7 @@ class TVariable;
class TIntermediate { class TIntermediate {
public: public:
explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
implicitThisName("@this"), implicitThisName("@this"), implicitCounterName("@count"),
language(l), source(EShSourceNone), profile(p), version(v), treeRoot(0), language(l), source(EShSourceNone), profile(p), version(v), treeRoot(0),
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
@ -218,6 +218,7 @@ public:
pixelCenterInteger(false), originUpperLeft(false), pixelCenterInteger(false), originUpperLeft(false),
vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false),
postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false), postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false),
hlslFunctionality1(false),
blendEquations(0), xfbMode(false), multiStream(false), blendEquations(0), xfbMode(false), multiStream(false),
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
layoutOverrideCoverage(false), layoutOverrideCoverage(false),
@ -362,6 +363,13 @@ public:
} }
bool usingHlslIoMapping() { return hlslIoMapping; } bool usingHlslIoMapping() { return hlslIoMapping; }
template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
bool hasCounterBufferName(const TString& name) const {
size_t len = strlen(implicitCounterName);
return name.size() > len &&
name.compare(name.size() - len, len, implicitCounterName) == 0;
}
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
void setVersion(int v) { version = v; } void setVersion(int v) { version = v; }
@ -564,6 +572,9 @@ public:
void setDepthReplacing() { depthReplacing = true; } void setDepthReplacing() { depthReplacing = true; }
bool isDepthReplacing() const { return depthReplacing; } bool isDepthReplacing() const { return depthReplacing; }
void setHlslFunctionality1() { hlslFunctionality1 = true; }
bool getHlslFunctionality1() const { return hlslFunctionality1; }
void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
unsigned int getBlendEquations() const { return blendEquations; } unsigned int getBlendEquations() const { return blendEquations; }
@ -623,6 +634,7 @@ public:
bool needsLegalization() const { return needToLegalize; } bool needsLegalization() const { return needToLegalize; }
const char* const implicitThisName; const char* const implicitThisName;
const char* const implicitCounterName;
protected: protected:
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
@ -682,6 +694,7 @@ protected:
bool postDepthCoverage; bool postDepthCoverage;
TLayoutDepth depthLayout; TLayoutDepth depthLayout;
bool depthReplacing; bool depthReplacing;
bool hlslFunctionality1;
int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift
bool xfbMode; bool xfbMode;
bool multiStream; bool multiStream;

View File

@ -766,11 +766,11 @@ void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediat
} }
// build counter block index associations for buffers // build counter block index associations for buffers
void TReflection::buildCounterIndices() void TReflection::buildCounterIndices(const TIntermediate& intermediate)
{ {
// search for ones that have counters // search for ones that have counters
for (int i = 0; i < int(indexToUniformBlock.size()); ++i) { for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
const TString counterName(indexToUniformBlock[i].name + "@count"); const TString counterName(intermediate.addCounterBufferName(indexToUniformBlock[i].name));
const int index = getIndex(counterName); const int index = getIndex(counterName);
if (index >= 0) if (index >= 0)
@ -802,7 +802,7 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
function->traverse(&it); function->traverse(&it);
} }
buildCounterIndices(); buildCounterIndices(intermediate);
return true; return true;
} }

View File

@ -156,7 +156,7 @@ public:
protected: protected:
friend class glslang::TReflectionTraverser; friend class glslang::TReflectionTraverser;
void buildCounterIndices(); void buildCounterIndices(const TIntermediate&);
void buildAttributeReflection(EShLanguage, const TIntermediate&); void buildAttributeReflection(EShLanguage, const TIntermediate&);
// Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex; // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;

View File

@ -70,7 +70,7 @@
// This should always increase, as some paths to do not consume // This should always increase, as some paths to do not consume
// a more major number. // a more major number.
// It should increment by one when new functionality is added. // It should increment by one when new functionality is added.
#define GLSLANG_MINOR_VERSION 4 #define GLSLANG_MINOR_VERSION 5
// //
// Call before doing any other compiler/linker operations. // Call before doing any other compiler/linker operations.
@ -154,6 +154,7 @@ struct TClient {
struct TTarget { struct TTarget {
EShTargetLanguage language; EShTargetLanguage language;
EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header
bool hlslFunctionality1; // can target hlsl_functionality1 extension(s)
}; };
// All source/client/target versions and settings. // All source/client/target versions and settings.
@ -420,6 +421,8 @@ public:
environment.target.language = lang; environment.target.language = lang;
environment.target.version = version; environment.target.version = version;
} }
void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; }
bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; }
// Interface to #include handlers. // Interface to #include handlers.
// //

View File

@ -1608,7 +1608,7 @@ void HlslParseContext::addStructBufferHiddenCounterParam(const TSourceLoc& loc,
if (! hasStructBuffCounter(*param.type)) if (! hasStructBuffCounter(*param.type))
return; return;
const TString counterBlockName(getStructBuffCounterName(*param.name)); const TString counterBlockName(intermediate.addCounterBufferName(*param.name));
TType counterType; TType counterType;
counterBufferType(loc, counterType); counterBufferType(loc, counterType);
@ -3163,7 +3163,7 @@ void HlslParseContext::counterBufferType(const TSourceLoc& loc, TType& type)
{ {
// Counter type // Counter type
TType* counterType = new TType(EbtInt, EvqBuffer); TType* counterType = new TType(EbtInt, EvqBuffer);
counterType->setFieldName("@count"); counterType->setFieldName(intermediate.implicitCounterName);
TTypeList* blockStruct = new TTypeList; TTypeList* blockStruct = new TTypeList;
TTypeLoc member = { counterType, loc }; TTypeLoc member = { counterType, loc };
@ -3176,12 +3176,6 @@ void HlslParseContext::counterBufferType(const TSourceLoc& loc, TType& type)
shareStructBufferType(type); shareStructBufferType(type);
} }
// knowledge of how to construct block name, in one place instead of N places.
TString HlslParseContext::getStructBuffCounterName(const TString& blockName) const
{
return blockName + "@count";
}
// declare counter for a structured buffer type // declare counter for a structured buffer type
void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name) void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name)
{ {
@ -3195,9 +3189,9 @@ void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const T
TType blockType; TType blockType;
counterBufferType(loc, blockType); counterBufferType(loc, blockType);
TString* blockName = new TString(getStructBuffCounterName(name)); TString* blockName = new TString(intermediate.addCounterBufferName(name));
// Counter buffer does not have its own counter buffer. TODO: there should be a better way to track this. // Counter buffer is not yet in use
structBufferCounter[*blockName] = false; structBufferCounter[*blockName] = false;
shareStructBufferType(blockType); shareStructBufferType(blockType);
@ -3211,7 +3205,7 @@ TIntermTyped* HlslParseContext::getStructBufferCounter(const TSourceLoc& loc, TI
if (buffer == nullptr || ! isStructBufferType(buffer->getType())) if (buffer == nullptr || ! isStructBufferType(buffer->getType()))
return nullptr; return nullptr;
const TString counterBlockName(getStructBuffCounterName(buffer->getAsSymbolNode()->getName())); const TString counterBlockName(intermediate.addCounterBufferName(buffer->getAsSymbolNode()->getName()));
// Mark the counter as being used // Mark the counter as being used
structBufferCounter[counterBlockName] = true; structBufferCounter[counterBlockName] = true;
@ -3224,7 +3218,6 @@ TIntermTyped* HlslParseContext::getStructBufferCounter(const TSourceLoc& loc, TI
return counterMember; return counterMember;
} }
// //
// Decompose structure buffer methods into AST // Decompose structure buffer methods into AST
// //
@ -5743,12 +5736,11 @@ void HlslParseContext::addStructBuffArguments(const TSourceLoc& loc, TIntermAggr
TType counterType; TType counterType;
counterBufferType(loc, counterType); counterBufferType(loc, counterType);
const TString counterBlockName(getStructBuffCounterName(blockSym->getName())); const TString counterBlockName(intermediate.addCounterBufferName(blockSym->getName()));
TVariable* variable = makeInternalVariable(counterBlockName, counterType); TVariable* variable = makeInternalVariable(counterBlockName, counterType);
// Mark this buffer as requiring a counter block. TODO: there should be a better // Mark this buffer's counter block as being in use
// way to track it.
structBufferCounter[counterBlockName] = true; structBufferCounter[counterBlockName] = true;
TIntermSymbol* sym = intermediate.addSymbol(*variable, loc); TIntermSymbol* sym = intermediate.addSymbol(*variable, loc);
@ -9944,7 +9936,8 @@ void HlslParseContext::addPatchConstantInvocation()
} }
// Finalization step: remove unused buffer blocks from linkage (we don't know until the // Finalization step: remove unused buffer blocks from linkage (we don't know until the
// shader is entirely compiled) // shader is entirely compiled).
// Preserve order of remaining symbols.
void HlslParseContext::removeUnusedStructBufferCounters() void HlslParseContext::removeUnusedStructBufferCounters()
{ {
const auto endIt = std::remove_if(linkageSymbols.begin(), linkageSymbols.end(), const auto endIt = std::remove_if(linkageSymbols.begin(), linkageSymbols.end(),

View File

@ -405,7 +405,7 @@ protected:
// may fit in TSampler::structReturnIndex. // may fit in TSampler::structReturnIndex.
TVector<TTypeList*> textureReturnStruct; TVector<TTypeList*> textureReturnStruct;
TMap<TString, bool> structBufferCounter; TMap<TString, bool> structBufferCounter; // true if counter buffer is in use
// The built-in interstage IO map considers e.g, EvqPosition on input and output separately, so that we // The built-in interstage IO map considers e.g, EvqPosition on input and output separately, so that we
// can build the linkage correctly if position appears on both sides. Otherwise, multiple positions // can build the linkage correctly if position appears on both sides. Otherwise, multiple positions