summaryrefslogtreecommitdiff
path: root/thirdparty/glslang/SPIRV
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/glslang/SPIRV')
-rw-r--r--thirdparty/glslang/SPIRV/GLSL.ext.EXT.h1
-rw-r--r--thirdparty/glslang/SPIRV/GLSL.ext.KHR.h4
-rw-r--r--thirdparty/glslang/SPIRV/GlslangToSpv.cpp350
-rw-r--r--thirdparty/glslang/SPIRV/NonSemanticShaderDebugInfo100.h171
-rw-r--r--thirdparty/glslang/SPIRV/SPVRemapper.cpp35
-rw-r--r--thirdparty/glslang/SPIRV/SPVRemapper.h8
-rw-r--r--thirdparty/glslang/SPIRV/SpvBuilder.cpp746
-rw-r--r--thirdparty/glslang/SPIRV/SpvBuilder.h110
-rw-r--r--thirdparty/glslang/SPIRV/SpvTools.cpp2
-rw-r--r--thirdparty/glslang/SPIRV/SpvTools.h16
-rw-r--r--thirdparty/glslang/SPIRV/doc.cpp77
-rw-r--r--thirdparty/glslang/SPIRV/spirv.hpp42
-rw-r--r--thirdparty/glslang/SPIRV/spvIR.h18
13 files changed, 1424 insertions, 156 deletions
diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.EXT.h b/thirdparty/glslang/SPIRV/GLSL.ext.EXT.h
index f48f1304d6..a247b4cd13 100644
--- a/thirdparty/glslang/SPIRV/GLSL.ext.EXT.h
+++ b/thirdparty/glslang/SPIRV/GLSL.ext.EXT.h
@@ -39,5 +39,6 @@ static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_ato
static const char* const E_SPV_EXT_shader_atomic_float16_add = "SPV_EXT_shader_atomic_float16_add";
static const char* const E_SPV_EXT_shader_atomic_float_min_max = "SPV_EXT_shader_atomic_float_min_max";
static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
+static const char* const E_SPV_EXT_mesh_shader = "SPV_EXT_mesh_shader";
#endif // #ifndef GLSLextEXT_H
diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.KHR.h b/thirdparty/glslang/SPIRV/GLSL.ext.KHR.h
index 5eb3e94482..d5c670f0e1 100644
--- a/thirdparty/glslang/SPIRV/GLSL.ext.KHR.h
+++ b/thirdparty/glslang/SPIRV/GLSL.ext.KHR.h
@@ -29,7 +29,7 @@
#define GLSLextKHR_H
static const int GLSLextKHRVersion = 100;
-static const int GLSLextKHRRevision = 2;
+static const int GLSLextKHRRevision = 3;
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
@@ -52,5 +52,7 @@ static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragm
static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation";
static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow";
+static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric";
+static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests";
#endif // #ifndef GLSLextKHR_H
diff --git a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
index 39941d3752..ccb4602be2 100644
--- a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
+++ b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
@@ -260,6 +260,7 @@ protected:
std::unordered_map<std::string, spv::Id> extBuiltinMap;
std::unordered_map<long long, spv::Id> symbolValues;
+ std::unordered_map<uint32_t, spv::Id> builtInVariableIds;
std::unordered_set<long long> rValueParameters; // set of formal function parameters passed as rValues,
// rather than a pointer
std::unordered_map<std::string, spv::Function*> functionMap;
@@ -279,6 +280,9 @@ protected:
// Used later for generating OpTraceKHR/OpExecuteCallableKHR
std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[2];
+
+ // Used by Task shader while generating opearnds for OpEmitMeshTasksEXT
+ spv::Id taskPayloadID;
};
//
@@ -314,7 +318,7 @@ spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile
}
// Translate glslang language (stage) to SPIR-V execution model.
-spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
+spv::ExecutionModel TranslateExecutionModel(EShLanguage stage, bool isMeshShaderEXT = false)
{
switch (stage) {
case EShLangVertex: return spv::ExecutionModelVertex;
@@ -330,8 +334,8 @@ spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
case EShLangClosestHit: return spv::ExecutionModelClosestHitKHR;
case EShLangMiss: return spv::ExecutionModelMissKHR;
case EShLangCallable: return spv::ExecutionModelCallableKHR;
- case EShLangTaskNV: return spv::ExecutionModelTaskNV;
- case EShLangMeshNV: return spv::ExecutionModelMeshNV;
+ case EShLangTask: return (isMeshShaderEXT)? spv::ExecutionModelTaskEXT : spv::ExecutionModelTaskNV;
+ case EShLangMesh: return (isMeshShaderEXT)? spv::ExecutionModelMeshEXT: spv::ExecutionModelMeshNV;
#endif
default:
assert(0);
@@ -762,7 +766,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
return spv::BuiltInSampleMask;
case glslang::EbvLayer:
- if (glslangIntermediate->getStage() == EShLangMeshNV) {
+ if (glslangIntermediate->getStage() == EShLangMesh) {
return spv::BuiltInLayer;
}
if (glslangIntermediate->getStage() == EShLangGeometry ||
@@ -1007,6 +1011,8 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
return spv::BuiltInRayTminKHR;
case glslang::EbvRayTmax:
return spv::BuiltInRayTmaxKHR;
+ case glslang::EbvCullMask:
+ return spv::BuiltInCullMaskKHR;
case glslang::EbvInstanceCustomIndex:
return spv::BuiltInInstanceCustomIndexKHR;
case glslang::EbvHitT:
@@ -1048,6 +1054,15 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
builder.addCapability(spv::CapabilityFragmentBarycentricNV);
return spv::BuiltInBaryCoordNoPerspNV;
+ case glslang::EbvBaryCoordEXT:
+ builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric);
+ builder.addCapability(spv::CapabilityFragmentBarycentricKHR);
+ return spv::BuiltInBaryCoordKHR;
+ case glslang::EbvBaryCoordNoPerspEXT:
+ builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric);
+ builder.addCapability(spv::CapabilityFragmentBarycentricKHR);
+ return spv::BuiltInBaryCoordNoPerspKHR;
+
// mesh shaders
case glslang::EbvTaskCountNV:
return spv::BuiltInTaskCountNV;
@@ -1066,6 +1081,16 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
case glslang::EbvMeshViewIndicesNV:
return spv::BuiltInMeshViewIndicesNV;
+ // SPV_EXT_mesh_shader
+ case glslang::EbvPrimitivePointIndicesEXT:
+ return spv::BuiltInPrimitivePointIndicesEXT;
+ case glslang::EbvPrimitiveLineIndicesEXT:
+ return spv::BuiltInPrimitiveLineIndicesEXT;
+ case glslang::EbvPrimitiveTriangleIndicesEXT:
+ return spv::BuiltInPrimitiveTriangleIndicesEXT;
+ case glslang::EbvCullPrimitiveEXT:
+ return spv::BuiltInCullPrimitiveEXT;
+
// sm builtins
case glslang::EbvWarpsPerSM:
builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
@@ -1309,6 +1334,7 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
case glslang::EvqHitAttr: return spv::StorageClassHitAttributeKHR;
case glslang::EvqCallableData: return spv::StorageClassCallableDataKHR;
case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR;
+ case glslang::EvqtaskPayloadSharedEXT : return spv::StorageClassTaskPayloadWorkgroupEXT;
case glslang::EvqSpirvStorageClass: return static_cast<spv::StorageClass>(type.getQualifier().spirvStorageClass);
#endif
default:
@@ -1326,7 +1352,9 @@ void TGlslangToSpvTraverser::TranslateLiterals(const glslang::TVector<const glsl
for (auto constant : constants) {
if (constant->getBasicType() == glslang::EbtFloat) {
float floatValue = static_cast<float>(constant->getConstArray()[0].getDConst());
- unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
+ unsigned literal;
+ static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)");
+ memcpy(&literal, &floatValue, sizeof(literal));
literals.push_back(literal);
} else if (constant->getBasicType() == glslang::EbtInt) {
unsigned literal = constant->getConstArray()[0].getIConst();
@@ -1452,6 +1480,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa
child.perViewNV = true;
if (parent.perTaskNV)
child.perTaskNV = true;
+ if (parent.storage == glslang::EvqtaskPayloadSharedEXT)
+ child.storage = glslang::EvqtaskPayloadSharedEXT;
if (parent.patch)
child.patch = true;
if (parent.sample)
@@ -1511,9 +1541,12 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
glslangIntermediate(glslangIntermediate),
nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()),
- nonSemanticDebugPrintf(0)
+ nonSemanticDebugPrintf(0),
+ taskPayloadID(0)
{
- spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
+ bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) !=
+ glslangIntermediate->getRequestedExtensions().end());
+ spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage(), isMeshShaderExt);
builder.clearAccessChain();
builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()),
@@ -1545,6 +1578,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
for (auto iItr = include_txt.begin(); iItr != include_txt.end(); ++iItr)
builder.addInclude(iItr->first, iItr->second);
}
+
+ builder.setEmitNonSemanticShaderDebugInfo(options.emitNonSemanticShaderDebugInfo);
+ builder.setEmitNonSemanticShaderDebugSource(options.emitNonSemanticShaderDebugSource);
+
stdBuiltins = builder.import("GLSL.std.450");
spv::AddressingModel addressingModel = spv::AddressingModelLogical;
@@ -1611,6 +1648,12 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
if (glslangIntermediate->getEarlyFragmentTests())
builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests);
+ if (glslangIntermediate->getEarlyAndLateFragmentTestsAMD())
+ {
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyAndLateFragmentTestsAMD);
+ builder.addExtension(spv::E_SPV_AMD_shader_early_and_late_fragment_tests);
+ }
+
if (glslangIntermediate->getPostDepthCoverage()) {
builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage);
builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage);
@@ -1620,6 +1663,9 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
if (glslangIntermediate->isDepthReplacing())
builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
+ if (glslangIntermediate->isStencilReplacing())
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeStencilRefReplacingEXT);
+
#ifndef GLSLANG_WEB
switch(glslangIntermediate->getDepth()) {
@@ -1628,6 +1674,20 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break;
default: mode = spv::ExecutionModeMax; break;
}
+
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+
+ switch (glslangIntermediate->getStencil()) {
+ case glslang::ElsRefUnchangedFrontAMD: mode = spv::ExecutionModeStencilRefUnchangedFrontAMD; break;
+ case glslang::ElsRefGreaterFrontAMD: mode = spv::ExecutionModeStencilRefGreaterFrontAMD; break;
+ case glslang::ElsRefLessFrontAMD: mode = spv::ExecutionModeStencilRefLessFrontAMD; break;
+ case glslang::ElsRefUnchangedBackAMD: mode = spv::ExecutionModeStencilRefUnchangedBackAMD; break;
+ case glslang::ElsRefGreaterBackAMD: mode = spv::ExecutionModeStencilRefGreaterBackAMD; break;
+ case glslang::ElsRefLessBackAMD: mode = spv::ExecutionModeStencilRefLessBackAMD; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+
if (mode != spv::ExecutionModeMax)
builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
switch (glslangIntermediate->getInterlockOrdering()) {
@@ -1766,7 +1826,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
case EShLangAnyHit:
case EShLangClosestHit:
case EShLangMiss:
- case EShLangCallable:
+ case EShLangCallable:
{
auto& extensions = glslangIntermediate->getRequestedExtensions();
if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
@@ -1777,12 +1837,24 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
builder.addCapability(spv::CapabilityRayTracingNV);
builder.addExtension("SPV_NV_ray_tracing");
}
+ if (glslangIntermediate->getStage() != EShLangRayGen && glslangIntermediate->getStage() != EShLangCallable)
+ {
+ if (extensions.find("GL_EXT_ray_cull_mask") != extensions.end()) {
+ builder.addCapability(spv::CapabilityRayCullMaskKHR);
+ builder.addExtension("SPV_KHR_ray_cull_mask");
+ }
+ }
break;
}
- case EShLangTaskNV:
- case EShLangMeshNV:
- builder.addCapability(spv::CapabilityMeshShadingNV);
- builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ case EShLangTask:
+ case EShLangMesh:
+ if(isMeshShaderExt) {
+ builder.addCapability(spv::CapabilityMeshShadingEXT);
+ builder.addExtension(spv::E_SPV_EXT_mesh_shader);
+ } else {
+ builder.addCapability(spv::CapabilityMeshShadingNV);
+ builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ }
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
std::vector<spv::Id> dimConstId;
for (int dim = 0; dim < 3; ++dim) {
@@ -1799,7 +1871,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
}
- if (glslangIntermediate->getStage() == EShLangMeshNV) {
+ if (glslangIntermediate->getStage() == EShLangMesh) {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
glslangIntermediate->getVertices());
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV,
@@ -1918,7 +1990,6 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
if (symbol->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
-
#ifdef ENABLE_HLSL
// Skip symbol handling if it is string-typed
if (symbol->getBasicType() == glslang::EbtString)
@@ -1929,6 +2000,9 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
// Formal function parameters were mapped during makeFunctions().
spv::Id id = getSymbolId(symbol);
+ if (symbol->getType().getQualifier().isTaskPayload())
+ taskPayloadID = id; // cache the taskPayloadID to be used it as operand for OpEmitMeshTasksEXT
+
if (builder.isPointer(id)) {
if (!symbol->getType().getQualifier().isParamInput() &&
!symbol->getType().getQualifier().isParamOutput()) {
@@ -2456,6 +2530,14 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
return false;
}
+ // Force variable declaration - Debug Mode Only
+ if (node->getOp() == glslang::EOpDeclare) {
+ builder.clearAccessChain();
+ node->getOperand()->traverse(this);
+ builder.clearAccessChain();
+ return false;
+ }
+
// Start by evaluating the operand
// Does it need a swizzle inversion? If so, evaluation is inverted;
@@ -2472,7 +2554,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
operandNode = node->getOperand()->getAsBinaryNode()->getLeft();
else
operandNode = node->getOperand();
-
+
operandNode->traverse(this);
spv::Id operand = spv::NoResult;
@@ -2716,32 +2798,38 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
switch (node->getOp()) {
+ case glslang::EOpScope:
case glslang::EOpSequence:
{
- if (preVisit)
+ if (visit == glslang::EvPreVisit) {
++sequenceDepth;
- else
- --sequenceDepth;
-
- if (sequenceDepth == 1) {
- // If this is the parent node of all the functions, we want to see them
- // early, so all call points have actual SPIR-V functions to reference.
- // In all cases, still let the traverser visit the children for us.
- makeFunctions(node->getAsAggregate()->getSequence());
+ if (sequenceDepth == 1) {
+ // If this is the parent node of all the functions, we want to see them
+ // early, so all call points have actual SPIR-V functions to reference.
+ // In all cases, still let the traverser visit the children for us.
+ makeFunctions(node->getAsAggregate()->getSequence());
- // Also, we want all globals initializers to go into the beginning of the entry point, before
- // anything else gets there, so visit out of order, doing them all now.
- makeGlobalInitializers(node->getAsAggregate()->getSequence());
+ // Also, we want all globals initializers to go into the beginning of the entry point, before
+ // anything else gets there, so visit out of order, doing them all now.
+ makeGlobalInitializers(node->getAsAggregate()->getSequence());
- //Pre process linker objects for ray tracing stages
- if (glslangIntermediate->isRayTracingStage())
- collectRayTracingLinkerObjects();
+ //Pre process linker objects for ray tracing stages
+ if (glslangIntermediate->isRayTracingStage())
+ collectRayTracingLinkerObjects();
- // Initializers are done, don't want to visit again, but functions and link objects need to be processed,
- // so do them manually.
- visitFunctions(node->getAsAggregate()->getSequence());
+ // Initializers are done, don't want to visit again, but functions and link objects need to be processed,
+ // so do them manually.
+ visitFunctions(node->getAsAggregate()->getSequence());
- return false;
+ return false;
+ } else {
+ if (node->getOp() == glslang::EOpScope)
+ builder.enterScope(0);
+ }
+ } else {
+ if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope)
+ builder.leaveScope();
+ --sequenceDepth;
}
return true;
@@ -2770,10 +2858,17 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
if (isShaderEntryPoint(node)) {
inEntryPoint = true;
builder.setBuildPoint(shaderEntry->getLastBlock());
+ builder.enterFunction(shaderEntry);
currentFunction = shaderEntry;
} else {
handleFunctionEntry(node);
}
+ if (options.generateDebugInfo) {
+ const auto& loc = node->getLoc();
+ const char* sourceFileName = loc.getFilename();
+ spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getSourceFile();
+ currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column);
+ }
} else {
if (inEntryPoint)
entryPointTerminated = true;
@@ -2913,9 +3008,17 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
std::vector<spv::Id> arguments;
translateArguments(*node, arguments, lvalueCoherentFlags);
spv::Id constructed;
- if (node->getOp() == glslang::EOpConstructTextureSampler)
- constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments);
- else if (node->getOp() == glslang::EOpConstructStruct ||
+ if (node->getOp() == glslang::EOpConstructTextureSampler) {
+ const glslang::TType& texType = node->getSequence()[0]->getAsTyped()->getType();
+ if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6 &&
+ texType.getSampler().isBuffer()) {
+ // SamplerBuffer is not supported in spirv1.6 so
+ // `samplerBuffer(textureBuffer, sampler)` is a no-op
+ // and textureBuffer is the result going forward
+ constructed = arguments[0];
+ } else
+ constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments);
+ } else if (node->getOp() == glslang::EOpConstructStruct ||
node->getOp() == glslang::EOpConstructCooperativeMatrix ||
node->getType().isArray()) {
std::vector<spv::Id> constituents;
@@ -3055,6 +3158,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
case glslang::EOpExecuteCallableNV:
case glslang::EOpExecuteCallableKHR:
case glslang::EOpWritePackedPrimitiveIndices4x8NV:
+ case glslang::EOpEmitMeshTasksEXT:
+ case glslang::EOpSetMeshOutputsEXT:
noReturnValue = true;
break;
case glslang::EOpRayQueryInitialize:
@@ -3449,7 +3554,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
break;
case 1:
{
- OpDecorations decorations = { precision,
+ OpDecorations decorations = { precision,
TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) };
result = createUnaryOperation(
@@ -3571,7 +3676,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
// smear condition to vector, if necessary (AST is always scalar)
// Before 1.4, smear like for mix(), starting with 1.4, keep it scalar
if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) {
- condition = builder.smearScalar(spv::NoPrecision, condition,
+ condition = builder.smearScalar(spv::NoPrecision, condition,
builder.makeVectorType(builder.makeBoolType(),
builder.getNumComponents(trueValue)));
}
@@ -3742,8 +3847,8 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
// by a block-ending branch. But we don't want to put any other body/test
// instructions in it, since the body/test may have arbitrary instructions,
// including merges of its own.
- builder.setLine(node->getLoc().line, node->getLoc().getFilename());
builder.setBuildPoint(&blocks.head);
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
if (node->testFirst() && node->getTest()) {
spv::Block& test = builder.makeNewBlock();
@@ -3962,7 +4067,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
initializer = builder.makeNullConstant(spvType);
}
- return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer);
+ return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false);
}
// Return type Id of the sampled type.
@@ -4050,7 +4155,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
if (explicitLayout != glslang::ElpNone)
spvType = builder.makeUintType(32);
else
- spvType = builder.makeBoolType();
+ spvType = builder.makeBoolType(false);
break;
case glslang::EbtInt:
spvType = builder.makeIntType(32);
@@ -4150,8 +4255,10 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler),
sampler.isShadow(), sampler.isArrayed(), sampler.isMultiSample(),
sampler.isImageClass() ? 2 : 1, TranslateImageFormat(type));
- if (sampler.isCombined()) {
- // already has both image and sampler, make the combined type
+ if (sampler.isCombined() &&
+ (!sampler.isBuffer() || glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6)) {
+ // Already has both image and sampler, make the combined type. Only combine sampler to
+ // buffer if before SPIR-V 1.6.
spvType = builder.makeSampledImageType(spvType);
}
}
@@ -4191,7 +4298,9 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
if (typeParam.constant->isLiteral()) {
if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
- unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
+ unsigned literal;
+ static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)");
+ memcpy(&literal, &floatValue, sizeof(literal));
operands.push_back({false, literal});
} else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
@@ -4336,7 +4445,7 @@ bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member)
extensions.find("GL_NV_stereo_view_rendering") == extensions.end())
return true;
- if (glslangIntermediate->getStage() != EShLangMeshNV) {
+ if (glslangIntermediate->getStage() != EShLangMesh) {
if (member.getFieldName() == "gl_ViewportMask" &&
extensions.find("GL_NV_viewport_array2") == extensions.end())
return true;
@@ -4366,14 +4475,14 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
// except sometimes for blocks
std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
for (int i = 0; i < (int)glslangMembers->size(); i++) {
- glslang::TType& glslangMember = *(*glslangMembers)[i].type;
- if (glslangMember.hiddenMember()) {
+ auto& glslangMember = (*glslangMembers)[i];
+ if (glslangMember.type->hiddenMember()) {
++memberDelta;
if (type.getBasicType() == glslang::EbtBlock)
memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
} else {
if (type.getBasicType() == glslang::EbtBlock) {
- if (filterMember(glslangMember)) {
+ if (filterMember(*glslangMember.type)) {
memberDelta++;
memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
continue;
@@ -4381,7 +4490,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta;
}
// modify just this child's view of the qualifier
- glslang::TQualifier memberQualifier = glslangMember.getQualifier();
+ glslang::TQualifier memberQualifier = glslangMember.type->getQualifier();
InheritQualifiers(memberQualifier, qualifier);
// manually inherit location
@@ -4392,25 +4501,38 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer &&
i == (int)glslangMembers->size() - 1;
- // Make forward pointers for any pointer members, and create a list of members to
- // convert to spirv types after creating the struct.
- if (glslangMember.isReference()) {
- if (forwardPointers.find(glslangMember.getReferentType()) == forwardPointers.end()) {
- deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier));
- }
- spvMembers.push_back(
- convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
- true));
- } else {
- spvMembers.push_back(
- convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
- false));
+ // Make forward pointers for any pointer members.
+ if (glslangMember.type->isReference() &&
+ forwardPointers.find(glslangMember.type->getReferentType()) == forwardPointers.end()) {
+ deferredForwardPointers.push_back(std::make_pair(glslangMember.type, memberQualifier));
+ }
+
+ // Create the member type.
+ auto const spvMember = convertGlslangToSpvType(*glslangMember.type, explicitLayout, memberQualifier, lastBufferBlockMember,
+ glslangMember.type->isReference());
+ spvMembers.push_back(spvMember);
+
+ // Update the builder with the type's location so that we can create debug types for the structure members.
+ // There doesn't exist a "clean" entry point for this information to be passed along to the builder so, for now,
+ // it is stored in the builder and consumed during the construction of composite debug types.
+ // TODO: This probably warrants further investigation. This approach was decided to be the least ugly of the
+ // quick and dirty approaches that were tried.
+ // Advantages of this approach:
+ // + Relatively clean. No direct calls into debug type system.
+ // + Handles nested recursive structures.
+ // Disadvantages of this approach:
+ // + Not as clean as desired. Traverser queries/sets persistent state. This is fragile.
+ // + Table lookup during creation of composite debug types. This really shouldn't be necessary.
+ if(options.emitNonSemanticShaderDebugInfo) {
+ builder.debugTypeLocs[spvMember].name = glslangMember.type->getFieldName().c_str();
+ builder.debugTypeLocs[spvMember].line = glslangMember.loc.line;
+ builder.debugTypeLocs[spvMember].column = glslangMember.loc.column;
}
}
}
// Make the SPIR-V type
- spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str());
+ spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str(), false);
if (! HasNonLayoutQualifiers(type, qualifier))
structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType;
@@ -5004,6 +5126,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
// GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy.
std::vector<spv::Id> paramTypes;
+ std::vector<char const*> paramNames;
std::vector<std::vector<spv::Decoration>> paramDecorations; // list of decorations per parameter
glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
@@ -5028,10 +5151,14 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
paramTypes.push_back(typeId);
}
+ for (auto const parameter:parameters) {
+ paramNames.push_back(parameter->getAsSymbolNode()->getName().c_str());
+ }
+
spv::Block* functionBlock;
spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()),
convertGlslangToSpvType(glslFunction->getType()),
- glslFunction->getName().c_str(), paramTypes,
+ glslFunction->getName().c_str(), paramTypes, paramNames,
paramDecorations, &functionBlock);
if (implicitThis)
function->setImplicitThis();
@@ -5121,6 +5248,7 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate
currentFunction = functionMap[node->getName().c_str()];
spv::Block* functionBlock = currentFunction->getEntryBlock();
builder.setBuildPoint(functionBlock);
+ builder.enterFunction(currentFunction);
}
void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
@@ -5548,10 +5676,12 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
operands.push_back(sample);
spv::Id resultTypeId;
+ glslang::TBasicType typeProxy = node->getBasicType();
// imageAtomicStore has a void return type so base the pointer type on
// the type of the value operand.
if (node->getOp() == glslang::EOpImageAtomicStore) {
resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(*opIt));
+ typeProxy = node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler().type;
} else {
resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
}
@@ -5565,7 +5695,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
for (; opIt != arguments.end(); ++opIt)
operands.push_back(*opIt);
- return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
+ return createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy,
lvalueCoherentFlags);
}
}
@@ -5769,10 +5899,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
assert(builder.isStructType(resultStructType));
//resType (SPIR-V type) contains 6 elements:
- //Member 0 must be a Boolean type scalar(LOD),
- //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor),
- //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset),
- //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask),
+ //Member 0 must be a Boolean type scalar(LOD),
+ //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor),
+ //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset),
+ //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask),
//Member 4 must be a scalar of integer type, whose Signedness operand is 0(lod),
//Member 5 must be a scalar of integer type, whose Signedness operand is 0(granularity).
std::vector<spv::Id> members;
@@ -5785,7 +5915,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
//call ImageFootprintNV
spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj,
cracked.gather, noImplicitLod, params, signExtensionMask());
-
+
//copy resType (SPIR-V type) to resultStructType(OpenGL type)
for (int i = 0; i < 5; i++) {
builder.clearAccessChain();
@@ -5838,7 +5968,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
}
#endif
- std::vector<spv::Id> result( 1,
+ std::vector<spv::Id> result( 1,
builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather,
noImplicitLod, params, signExtensionMask())
);
@@ -7361,7 +7491,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
} else {
scopeId = builder.makeUintConstant(spv::ScopeDevice);
}
- // semantics default to relaxed
+ // semantics default to relaxed
spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() &&
glslangIntermediate->usingVulkanMemoryModel() ?
spv::MemorySemanticsVolatileMask :
@@ -8465,6 +8595,15 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
case glslang::EOpWritePackedPrimitiveIndices4x8NV:
builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands);
return 0;
+ case glslang::EOpEmitMeshTasksEXT:
+ if (taskPayloadID)
+ operands.push_back(taskPayloadID);
+ // As per SPV_EXT_mesh_shader make it a terminating instruction in the current block
+ builder.makeStatementTerminator(spv::OpEmitMeshTasksEXT, operands, "post-OpEmitMeshTasksEXT");
+ return 0;
+ case glslang::EOpSetMeshOutputsEXT:
+ builder.createNoResultOp(spv::OpSetMeshOutputsEXT, operands);
+ return 0;
case glslang::EOpCooperativeMatrixMulAdd:
opCode = spv::OpCooperativeMatrixMulAddNV;
break;
@@ -8728,7 +8867,32 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
// it was not found, create it
spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType());
+
+ // There are pairs of symbols that map to the same SPIR-V built-in:
+ // gl_ObjectToWorldEXT and gl_ObjectToWorld3x4EXT, and gl_WorldToObjectEXT
+ // and gl_WorldToObject3x4EXT. SPIR-V forbids having two OpVariables
+ // with the same BuiltIn in the same storage class, so we must re-use one.
+ const bool mayNeedToReuseBuiltIn =
+ builtIn == spv::BuiltInObjectToWorldKHR ||
+ builtIn == spv::BuiltInWorldToObjectKHR;
+
+ if (mayNeedToReuseBuiltIn) {
+ auto iter = builtInVariableIds.find(uint32_t(builtIn));
+ if (builtInVariableIds.end() != iter) {
+ id = iter->second;
+ symbolValues[symbol->getId()] = id;
+ if (forcedType.second != spv::NoType)
+ forceType[id] = forcedType.second;
+ return id;
+ }
+ }
+
id = createSpvVariable(symbol, forcedType.first);
+
+ if (mayNeedToReuseBuiltIn) {
+ builtInVariableIds.insert({uint32_t(builtIn), id});
+ }
+
symbolValues[symbol->getId()] = id;
if (forcedType.second != spv::NoType)
forceType[id] = forcedType.second;
@@ -8857,6 +9021,12 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
}
+ if (symbol->getQualifier().pervertexEXT) {
+ builder.addDecoration(id, spv::DecorationPerVertexKHR);
+ builder.addCapability(spv::CapabilityFragmentBarycentricKHR);
+ builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric);
+ }
+
if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) {
builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
@@ -8918,13 +9088,21 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
// add per-primitive, per-view. per-task decorations to a struct member (member >= 0) or an object
void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier)
{
+ bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) !=
+ glslangIntermediate->getRequestedExtensions().end());
+
if (member >= 0) {
if (qualifier.perPrimitiveNV) {
// Need to add capability/extension for fragment shader.
// Mesh shader already adds this by default.
if (glslangIntermediate->getStage() == EShLangFragment) {
- builder.addCapability(spv::CapabilityMeshShadingNV);
- builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ if(isMeshShaderExt) {
+ builder.addCapability(spv::CapabilityMeshShadingEXT);
+ builder.addExtension(spv::E_SPV_EXT_mesh_shader);
+ } else {
+ builder.addCapability(spv::CapabilityMeshShadingNV);
+ builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ }
}
builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerPrimitiveNV);
}
@@ -8937,8 +9115,13 @@ void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const g
// Need to add capability/extension for fragment shader.
// Mesh shader already adds this by default.
if (glslangIntermediate->getStage() == EShLangFragment) {
- builder.addCapability(spv::CapabilityMeshShadingNV);
- builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ if(isMeshShaderExt) {
+ builder.addCapability(spv::CapabilityMeshShadingEXT);
+ builder.addExtension(spv::E_SPV_EXT_mesh_shader);
+ } else {
+ builder.addCapability(spv::CapabilityMeshShadingNV);
+ builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ }
}
builder.addDecoration(id, spv::DecorationPerPrimitiveNV);
}
@@ -9078,15 +9261,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
break;
#ifndef GLSLANG_WEB
case glslang::EbtInt8:
+ builder.addCapability(spv::CapabilityInt8);
spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const()));
break;
case glslang::EbtUint8:
+ builder.addCapability(spv::CapabilityInt8);
spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const()));
break;
case glslang::EbtInt16:
+ builder.addCapability(spv::CapabilityInt16);
spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const()));
break;
case glslang::EbtUint16:
+ builder.addCapability(spv::CapabilityInt16);
spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const()));
break;
case glslang::EbtInt64:
@@ -9099,6 +9286,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst()));
break;
case glslang::EbtFloat16:
+ builder.addCapability(spv::CapabilityFloat16);
spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
break;
#endif
@@ -9127,15 +9315,19 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
break;
#ifndef GLSLANG_WEB
case glslang::EbtInt8:
+ builder.addCapability(spv::CapabilityInt8);
scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant);
break;
case glslang::EbtUint8:
+ builder.addCapability(spv::CapabilityInt8);
scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant);
break;
case glslang::EbtInt16:
+ builder.addCapability(spv::CapabilityInt16);
scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant);
break;
case glslang::EbtUint16:
+ builder.addCapability(spv::CapabilityInt16);
scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant);
break;
case glslang::EbtInt64:
@@ -9148,6 +9340,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
break;
case glslang::EbtFloat16:
+ builder.addCapability(spv::CapabilityFloat16);
scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
break;
case glslang::EbtReference:
@@ -9345,7 +9538,8 @@ int GetSpirvGeneratorVersion()
// return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent
// return 8; // switch to new dead block eliminator; use OpUnreachable
// return 9; // don't include opaque function parameters in OpEntryPoint global's operand list
- return 10; // Generate OpFUnordNotEqual for != comparisons
+ // return 10; // Generate OpFUnordNotEqual for != comparisons
+ return 11; // Make OpEmitMeshTasksEXT a terminal instruction
}
// Write SPIR-V out to a binary file
diff --git a/thirdparty/glslang/SPIRV/NonSemanticShaderDebugInfo100.h b/thirdparty/glslang/SPIRV/NonSemanticShaderDebugInfo100.h
new file mode 100644
index 0000000000..c52f32f809
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/NonSemanticShaderDebugInfo100.h
@@ -0,0 +1,171 @@
+// Copyright (c) 2018 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and/or associated documentation files (the "Materials"),
+// to deal in the Materials without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Materials, and to permit persons to whom the
+// Materials are furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+// IN THE MATERIALS.
+
+#ifndef SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_
+#define SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ NonSemanticShaderDebugInfo100Version = 100,
+ NonSemanticShaderDebugInfo100Version_BitWidthPadding = 0x7fffffff
+};
+enum {
+ NonSemanticShaderDebugInfo100Revision = 6,
+ NonSemanticShaderDebugInfo100Revision_BitWidthPadding = 0x7fffffff
+};
+
+enum NonSemanticShaderDebugInfo100Instructions {
+ NonSemanticShaderDebugInfo100DebugInfoNone = 0,
+ NonSemanticShaderDebugInfo100DebugCompilationUnit = 1,
+ NonSemanticShaderDebugInfo100DebugTypeBasic = 2,
+ NonSemanticShaderDebugInfo100DebugTypePointer = 3,
+ NonSemanticShaderDebugInfo100DebugTypeQualifier = 4,
+ NonSemanticShaderDebugInfo100DebugTypeArray = 5,
+ NonSemanticShaderDebugInfo100DebugTypeVector = 6,
+ NonSemanticShaderDebugInfo100DebugTypedef = 7,
+ NonSemanticShaderDebugInfo100DebugTypeFunction = 8,
+ NonSemanticShaderDebugInfo100DebugTypeEnum = 9,
+ NonSemanticShaderDebugInfo100DebugTypeComposite = 10,
+ NonSemanticShaderDebugInfo100DebugTypeMember = 11,
+ NonSemanticShaderDebugInfo100DebugTypeInheritance = 12,
+ NonSemanticShaderDebugInfo100DebugTypePtrToMember = 13,
+ NonSemanticShaderDebugInfo100DebugTypeTemplate = 14,
+ NonSemanticShaderDebugInfo100DebugTypeTemplateParameter = 15,
+ NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter = 16,
+ NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack = 17,
+ NonSemanticShaderDebugInfo100DebugGlobalVariable = 18,
+ NonSemanticShaderDebugInfo100DebugFunctionDeclaration = 19,
+ NonSemanticShaderDebugInfo100DebugFunction = 20,
+ NonSemanticShaderDebugInfo100DebugLexicalBlock = 21,
+ NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator = 22,
+ NonSemanticShaderDebugInfo100DebugScope = 23,
+ NonSemanticShaderDebugInfo100DebugNoScope = 24,
+ NonSemanticShaderDebugInfo100DebugInlinedAt = 25,
+ NonSemanticShaderDebugInfo100DebugLocalVariable = 26,
+ NonSemanticShaderDebugInfo100DebugInlinedVariable = 27,
+ NonSemanticShaderDebugInfo100DebugDeclare = 28,
+ NonSemanticShaderDebugInfo100DebugValue = 29,
+ NonSemanticShaderDebugInfo100DebugOperation = 30,
+ NonSemanticShaderDebugInfo100DebugExpression = 31,
+ NonSemanticShaderDebugInfo100DebugMacroDef = 32,
+ NonSemanticShaderDebugInfo100DebugMacroUndef = 33,
+ NonSemanticShaderDebugInfo100DebugImportedEntity = 34,
+ NonSemanticShaderDebugInfo100DebugSource = 35,
+ NonSemanticShaderDebugInfo100DebugFunctionDefinition = 101,
+ NonSemanticShaderDebugInfo100DebugSourceContinued = 102,
+ NonSemanticShaderDebugInfo100DebugLine = 103,
+ NonSemanticShaderDebugInfo100DebugNoLine = 104,
+ NonSemanticShaderDebugInfo100DebugBuildIdentifier = 105,
+ NonSemanticShaderDebugInfo100DebugStoragePath = 106,
+ NonSemanticShaderDebugInfo100DebugEntryPoint = 107,
+ NonSemanticShaderDebugInfo100DebugTypeMatrix = 108,
+ NonSemanticShaderDebugInfo100InstructionsMax = 0x7fffffff
+};
+
+
+enum NonSemanticShaderDebugInfo100DebugInfoFlags {
+ NonSemanticShaderDebugInfo100None = 0x0000,
+ NonSemanticShaderDebugInfo100FlagIsProtected = 0x01,
+ NonSemanticShaderDebugInfo100FlagIsPrivate = 0x02,
+ NonSemanticShaderDebugInfo100FlagIsPublic = 0x03,
+ NonSemanticShaderDebugInfo100FlagIsLocal = 0x04,
+ NonSemanticShaderDebugInfo100FlagIsDefinition = 0x08,
+ NonSemanticShaderDebugInfo100FlagFwdDecl = 0x10,
+ NonSemanticShaderDebugInfo100FlagArtificial = 0x20,
+ NonSemanticShaderDebugInfo100FlagExplicit = 0x40,
+ NonSemanticShaderDebugInfo100FlagPrototyped = 0x80,
+ NonSemanticShaderDebugInfo100FlagObjectPointer = 0x100,
+ NonSemanticShaderDebugInfo100FlagStaticMember = 0x200,
+ NonSemanticShaderDebugInfo100FlagIndirectVariable = 0x400,
+ NonSemanticShaderDebugInfo100FlagLValueReference = 0x800,
+ NonSemanticShaderDebugInfo100FlagRValueReference = 0x1000,
+ NonSemanticShaderDebugInfo100FlagIsOptimized = 0x2000,
+ NonSemanticShaderDebugInfo100FlagIsEnumClass = 0x4000,
+ NonSemanticShaderDebugInfo100FlagTypePassByValue = 0x8000,
+ NonSemanticShaderDebugInfo100FlagTypePassByReference = 0x10000,
+ NonSemanticShaderDebugInfo100FlagUnknownPhysicalLayout = 0x20000,
+ NonSemanticShaderDebugInfo100DebugInfoFlagsMax = 0x7fffffff
+};
+
+enum NonSemanticShaderDebugInfo100BuildIdentifierFlags {
+ NonSemanticShaderDebugInfo100IdentifierPossibleDuplicates = 0x01,
+ NonSemanticShaderDebugInfo100BuildIdentifierFlagsMax = 0x7fffffff
+};
+
+enum NonSemanticShaderDebugInfo100DebugBaseTypeAttributeEncoding {
+ NonSemanticShaderDebugInfo100Unspecified = 0,
+ NonSemanticShaderDebugInfo100Address = 1,
+ NonSemanticShaderDebugInfo100Boolean = 2,
+ NonSemanticShaderDebugInfo100Float = 3,
+ NonSemanticShaderDebugInfo100Signed = 4,
+ NonSemanticShaderDebugInfo100SignedChar = 5,
+ NonSemanticShaderDebugInfo100Unsigned = 6,
+ NonSemanticShaderDebugInfo100UnsignedChar = 7,
+ NonSemanticShaderDebugInfo100DebugBaseTypeAttributeEncodingMax = 0x7fffffff
+};
+
+enum NonSemanticShaderDebugInfo100DebugCompositeType {
+ NonSemanticShaderDebugInfo100Class = 0,
+ NonSemanticShaderDebugInfo100Structure = 1,
+ NonSemanticShaderDebugInfo100Union = 2,
+ NonSemanticShaderDebugInfo100DebugCompositeTypeMax = 0x7fffffff
+};
+
+enum NonSemanticShaderDebugInfo100DebugTypeQualifier {
+ NonSemanticShaderDebugInfo100ConstType = 0,
+ NonSemanticShaderDebugInfo100VolatileType = 1,
+ NonSemanticShaderDebugInfo100RestrictType = 2,
+ NonSemanticShaderDebugInfo100AtomicType = 3,
+ NonSemanticShaderDebugInfo100DebugTypeQualifierMax = 0x7fffffff
+};
+
+enum NonSemanticShaderDebugInfo100DebugOperation {
+ NonSemanticShaderDebugInfo100Deref = 0,
+ NonSemanticShaderDebugInfo100Plus = 1,
+ NonSemanticShaderDebugInfo100Minus = 2,
+ NonSemanticShaderDebugInfo100PlusUconst = 3,
+ NonSemanticShaderDebugInfo100BitPiece = 4,
+ NonSemanticShaderDebugInfo100Swap = 5,
+ NonSemanticShaderDebugInfo100Xderef = 6,
+ NonSemanticShaderDebugInfo100StackValue = 7,
+ NonSemanticShaderDebugInfo100Constu = 8,
+ NonSemanticShaderDebugInfo100Fragment = 9,
+ NonSemanticShaderDebugInfo100DebugOperationMax = 0x7fffffff
+};
+
+enum NonSemanticShaderDebugInfo100DebugImportedEntity {
+ NonSemanticShaderDebugInfo100ImportedModule = 0,
+ NonSemanticShaderDebugInfo100ImportedDeclaration = 1,
+ NonSemanticShaderDebugInfo100DebugImportedEntityMax = 0x7fffffff
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_
diff --git a/thirdparty/glslang/SPIRV/SPVRemapper.cpp b/thirdparty/glslang/SPIRV/SPVRemapper.cpp
index fdfbeb90cd..6aca8cbcf0 100644
--- a/thirdparty/glslang/SPIRV/SPVRemapper.cpp
+++ b/thirdparty/glslang/SPIRV/SPVRemapper.cpp
@@ -160,15 +160,29 @@ namespace spv {
}
// Is this an opcode we should remove when using --strip?
- bool spirvbin_t::isStripOp(spv::Op opCode) const
+ bool spirvbin_t::isStripOp(spv::Op opCode, unsigned start) const
{
switch (opCode) {
case spv::OpSource:
case spv::OpSourceExtension:
case spv::OpName:
case spv::OpMemberName:
- case spv::OpLine: return true;
- default: return false;
+ case spv::OpLine :
+ {
+ const std::string name = literalString(start + 2);
+
+ std::vector<std::string>::const_iterator it;
+ for (it = stripWhiteList.begin(); it < stripWhiteList.end(); it++)
+ {
+ if (name.find(*it) != std::string::npos) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ default :
+ return false;
}
}
@@ -372,7 +386,7 @@ namespace spv {
process(
[&](spv::Op opCode, unsigned start) {
// remember opcodes we want to strip later
- if (isStripOp(opCode))
+ if (isStripOp(opCode, start))
stripInst(start);
return true;
},
@@ -1494,13 +1508,24 @@ namespace spv {
}
// remap from a memory image
- void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, std::uint32_t opts)
+ void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, const std::vector<std::string>& whiteListStrings,
+ std::uint32_t opts)
{
+ stripWhiteList = whiteListStrings;
spv.swap(in_spv);
remap(opts);
spv.swap(in_spv);
}
+ // remap from a memory image - legacy interface without white list
+ void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, std::uint32_t opts)
+ {
+ stripWhiteList.clear();
+ spv.swap(in_spv);
+ remap(opts);
+ spv.swap(in_spv);
+ }
+
} // namespace SPV
#endif // defined (use_cpp11)
diff --git a/thirdparty/glslang/SPIRV/SPVRemapper.h b/thirdparty/glslang/SPIRV/SPVRemapper.h
index d6b9c346dd..d21694635a 100644
--- a/thirdparty/glslang/SPIRV/SPVRemapper.h
+++ b/thirdparty/glslang/SPIRV/SPVRemapper.h
@@ -118,6 +118,10 @@ public:
virtual ~spirvbin_t() { }
// remap on an existing binary in memory
+ void remap(std::vector<std::uint32_t>& spv, const std::vector<std::string>& whiteListStrings,
+ std::uint32_t opts = DO_EVERYTHING);
+
+ // remap on an existing binary in memory - legacy interface without white list
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
// Type for error/log handler functions
@@ -180,6 +184,8 @@ private:
unsigned typeSizeInWords(spv::Id id) const;
unsigned idTypeSizeInWords(spv::Id id) const;
+ bool isStripOp(spv::Op opCode, unsigned start) const;
+
spv::Id& asId(unsigned word) { return spv[word]; }
const spv::Id& asId(unsigned word) const { return spv[word]; }
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
@@ -249,6 +255,8 @@ private:
std::vector<spirword_t> spv; // SPIR words
+ std::vector<std::string> stripWhiteList;
+
namemap_t nameMap; // ID names from OpName
// Since we want to also do binary ops, we can't use std::vector<bool>. we could use
diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.cpp b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
index 36a3f09744..7c5ea874ba 100644
--- a/thirdparty/glslang/SPIRV/SpvBuilder.cpp
+++ b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
@@ -59,12 +59,15 @@ namespace spv {
Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) :
spvVersion(spvVersion),
- source(SourceLanguageUnknown),
+ sourceLang(SourceLanguageUnknown),
sourceVersion(0),
sourceFileStringId(NoResult),
currentLine(0),
currentFile(nullptr),
+ currentFileId(NoResult),
+ lastDebugScopeId(NoResult),
emitOpLines(false),
+ emitNonSemanticShaderDebugInfo(false),
addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450),
builderNumber(magicNumber),
@@ -98,8 +101,12 @@ void Builder::setLine(int lineNum)
{
if (lineNum != 0 && lineNum != currentLine) {
currentLine = lineNum;
- if (emitOpLines)
- addLine(sourceFileStringId, currentLine, 0);
+ if (emitOpLines) {
+ if (emitNonSemanticShaderDebugInfo)
+ addDebugScopeAndLine(currentFileId, currentLine, 0);
+ else
+ addLine(sourceFileStringId, currentLine, 0);
+ }
}
}
@@ -118,7 +125,10 @@ void Builder::setLine(int lineNum, const char* filename)
currentFile = filename;
if (emitOpLines) {
spv::Id strId = getStringId(filename);
- addLine(strId, currentLine, 0);
+ if (emitNonSemanticShaderDebugInfo)
+ addDebugScopeAndLine(strId, currentLine, 0);
+ else
+ addLine(strId, currentLine, 0);
}
}
}
@@ -132,22 +142,49 @@ void Builder::addLine(Id fileName, int lineNum, int column)
buildPoint->addInstruction(std::unique_ptr<Instruction>(line));
}
+void Builder::addDebugScopeAndLine(Id fileName, int lineNum, int column)
+{
+ if (currentDebugScopeId.top() != lastDebugScopeId) {
+ spv::Id resultId = getUniqueId();
+ Instruction* scopeInst = new Instruction(resultId, makeVoidType(), OpExtInst);
+ scopeInst->addIdOperand(nonSemanticShaderDebugInfo);
+ scopeInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugScope);
+ scopeInst->addIdOperand(currentDebugScopeId.top());
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(scopeInst));
+ lastDebugScopeId = currentDebugScopeId.top();
+ }
+ spv::Id resultId = getUniqueId();
+ Instruction* lineInst = new Instruction(resultId, makeVoidType(), OpExtInst);
+ lineInst->addIdOperand(nonSemanticShaderDebugInfo);
+ lineInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLine);
+ lineInst->addIdOperand(makeDebugSource(fileName));
+ lineInst->addIdOperand(makeUintConstant(lineNum));
+ lineInst->addIdOperand(makeUintConstant(lineNum));
+ lineInst->addIdOperand(makeUintConstant(column));
+ lineInst->addIdOperand(makeUintConstant(column));
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(lineInst));
+}
+
// For creating new groupedTypes (will return old type if the requested one was already made).
Id Builder::makeVoidType()
{
Instruction* type;
if (groupedTypes[OpTypeVoid].size() == 0) {
- type = new Instruction(getUniqueId(), NoType, OpTypeVoid);
+ Id typeId = getUniqueId();
+ type = new Instruction(typeId, NoType, OpTypeVoid);
groupedTypes[OpTypeVoid].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
+ // Core OpTypeVoid used for debug void type
+ if (emitNonSemanticShaderDebugInfo)
+ debugId[typeId] = typeId;
} else
type = groupedTypes[OpTypeVoid].back();
return type->getResultId();
}
-Id Builder::makeBoolType()
+Id Builder::makeBoolType(bool const compilerGenerated)
{
Instruction* type;
if (groupedTypes[OpTypeBool].size() == 0) {
@@ -158,6 +195,12 @@ Id Builder::makeBoolType()
} else
type = groupedTypes[OpTypeBool].back();
+ if (emitNonSemanticShaderDebugInfo && !compilerGenerated)
+ {
+ auto const debugResultId = makeBoolDebugType(32);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -172,6 +215,12 @@ Id Builder::makeSamplerType()
} else
type = groupedTypes[OpTypeSampler].back();
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeCompositeDebugType({}, "type.sampler", NonSemanticShaderDebugInfo100Structure, true);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -268,6 +317,12 @@ Id Builder::makeIntegerType(int width, bool hasSign)
break;
}
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeIntegerDebugType(width, hasSign);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -305,6 +360,12 @@ Id Builder::makeFloatType(int width)
break;
}
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeFloatDebugType(width);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -312,7 +373,7 @@ Id Builder::makeFloatType(int width)
// See makeStructResultType() for non-decorated structs
// needed as the result of some instructions, which does
// check for duplicates.
-Id Builder::makeStructType(const std::vector<Id>& members, const char* name)
+Id Builder::makeStructType(const std::vector<Id>& members, const char* name, bool const compilerGenerated)
{
// Don't look for previous one, because in the general case,
// structs can be duplicated except for decorations.
@@ -326,6 +387,12 @@ Id Builder::makeStructType(const std::vector<Id>& members, const char* name)
module.mapInstruction(type);
addName(type->getResultId(), name);
+ if (emitNonSemanticShaderDebugInfo && !compilerGenerated)
+ {
+ auto const debugResultId = makeCompositeDebugType(members, name, NonSemanticShaderDebugInfo100Structure);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -372,6 +439,12 @@ Id Builder::makeVectorType(Id component, int size)
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeVectorDebugType(component, size);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -398,6 +471,12 @@ Id Builder::makeMatrixType(Id component, int cols, int rows)
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeMatrixDebugType(column, cols);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -484,6 +563,12 @@ Id Builder::makeArrayType(Id element, Id sizeId, int stride)
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeArrayDebugType(element, sizeId);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -494,6 +579,12 @@ Id Builder::makeRuntimeArray(Id element)
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeArrayDebugType(element, makeUintConstant(0));
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -513,11 +604,25 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
}
}
if (! mismatch)
+ {
+ // If compiling HLSL, glslang will create a wrapper function around the entrypoint. Accordingly, a void(void)
+ // function type is created for the wrapper function. However, nonsemantic shader debug information is disabled
+ // while creating the HLSL wrapper. Consequently, if we encounter another void(void) function, we need to create
+ // the associated debug function type if it hasn't been created yet.
+ if(emitNonSemanticShaderDebugInfo && debugId[type->getResultId()] == 0) {
+ assert(sourceLang == spv::SourceLanguageHLSL);
+ assert(getTypeClass(returnType) == OpTypeVoid && paramTypes.size() == 0);
+
+ Id debugTypeId = makeDebugFunctionType(returnType, {});
+ debugId[type->getResultId()] = debugTypeId;
+ }
return type->getResultId();
+ }
}
// not found, make it
- type = new Instruction(getUniqueId(), NoType, OpTypeFunction);
+ Id typeId = getUniqueId();
+ type = new Instruction(typeId, NoType, OpTypeFunction);
type->addIdOperand(returnType);
for (int p = 0; p < (int)paramTypes.size(); ++p)
type->addIdOperand(paramTypes[p]);
@@ -525,9 +630,34 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
+ // make debug type and map it
+ if (emitNonSemanticShaderDebugInfo) {
+ Id debugTypeId = makeDebugFunctionType(returnType, paramTypes);
+ debugId[typeId] = debugTypeId;
+ }
+
return type->getResultId();
}
+Id Builder::makeDebugFunctionType(Id returnType, const std::vector<Id>& paramTypes)
+{
+ assert(debugId[returnType] != 0);
+
+ Id typeId = getUniqueId();
+ auto type = new Instruction(typeId, makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeFunction);
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic));
+ type->addIdOperand(debugId[returnType]);
+ for (auto const paramType : paramTypes) {
+ assert(isPointerType(paramType) || isArrayType(paramType));
+ type->addIdOperand(debugId[getContainedTypeId(paramType)]);
+ }
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+ return typeId;
+}
+
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
ImageFormat format)
{
@@ -609,6 +739,22 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo
}
#endif
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto TypeName = [&dim]() -> char const* {
+ switch (dim) {
+ case Dim1D: return "type.1d.image";
+ case Dim2D: return "type.2d.image";
+ case Dim3D: return "type.3d.image";
+ case DimCube: return "type.cube.image";
+ default: return "type.image";
+ }
+ };
+
+ auto const debugResultId = makeCompositeDebugType({}, TypeName(), NonSemanticShaderDebugInfo100Class, true);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
return type->getResultId();
}
@@ -630,9 +776,376 @@ Id Builder::makeSampledImageType(Id imageType)
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
+ if (emitNonSemanticShaderDebugInfo)
+ {
+ auto const debugResultId = makeCompositeDebugType({}, "type.sampled.image", NonSemanticShaderDebugInfo100Class, true);
+ debugId[type->getResultId()] = debugResultId;
+ }
+
+ return type->getResultId();
+}
+
+Id Builder::makeDebugInfoNone()
+{
+ if (debugInfoNone != 0)
+ return debugInfoNone;
+
+ Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ inst->addIdOperand(nonSemanticShaderDebugInfo);
+ inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugInfoNone);
+
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
+ module.mapInstruction(inst);
+
+ debugInfoNone = inst->getResultId();
+
+ return debugInfoNone;
+}
+
+Id Builder::makeBoolDebugType(int const size)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) {
+ type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t];
+ if (type->getIdOperand(0) == getStringId("bool") &&
+ type->getIdOperand(1) == static_cast<unsigned int>(size) &&
+ type->getIdOperand(2) == NonSemanticShaderDebugInfo100Boolean)
+ return type->getResultId();
+ }
+
+ type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic);
+
+ type->addIdOperand(getStringId("bool")); // name id
+ type->addIdOperand(makeUintConstant(size)); // size id
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Boolean)); // encoding id
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id
+
+ groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
return type->getResultId();
}
+Id Builder::makeIntegerDebugType(int const width, bool const hasSign)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) {
+ type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t];
+ if (type->getIdOperand(0) == (hasSign ? getStringId("int") : getStringId("uint")) &&
+ type->getIdOperand(1) == static_cast<unsigned int>(width) &&
+ type->getIdOperand(2) == (hasSign ? NonSemanticShaderDebugInfo100Signed : NonSemanticShaderDebugInfo100Unsigned))
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic);
+ if(hasSign == true) {
+ type->addIdOperand(getStringId("int")); // name id
+ } else {
+ type->addIdOperand(getStringId("uint")); // name id
+ }
+ type->addIdOperand(makeUintConstant(width)); // size id
+ if(hasSign == true) {
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Signed)); // encoding id
+ } else {
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Unsigned)); // encoding id
+ }
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id
+
+ groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeFloatDebugType(int const width)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) {
+ type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t];
+ if (type->getIdOperand(0) == getStringId("float") &&
+ type->getIdOperand(1) == static_cast<unsigned int>(width) &&
+ type->getIdOperand(2) == NonSemanticShaderDebugInfo100Float)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic);
+ type->addIdOperand(getStringId("float")); // name id
+ type->addIdOperand(makeUintConstant(width)); // size id
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Float)); // encoding id
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id
+
+ groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType)
+{
+ assert(sequenceType == NonSemanticShaderDebugInfo100DebugTypeArray ||
+ sequenceType == NonSemanticShaderDebugInfo100DebugTypeVector);
+
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedDebugTypes[sequenceType].size(); ++t) {
+ type = groupedDebugTypes[sequenceType][t];
+ if (type->getIdOperand(0) == baseType &&
+ type->getIdOperand(1) == makeUintConstant(componentCount))
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(sequenceType);
+ type->addIdOperand(debugId[baseType]); // base type
+ type->addIdOperand(componentCount); // component count
+
+ groupedDebugTypes[sequenceType].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeArrayDebugType(Id const baseType, Id const componentCount)
+{
+ return makeSequentialDebugType(baseType, componentCount, NonSemanticShaderDebugInfo100DebugTypeArray);
+}
+
+Id Builder::makeVectorDebugType(Id const baseType, int const componentCount)
+{
+ return makeSequentialDebugType(baseType, makeUintConstant(componentCount), NonSemanticShaderDebugInfo100DebugTypeVector);;
+}
+
+Id Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].size(); ++t) {
+ type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix][t];
+ if (type->getIdOperand(0) == vectorType &&
+ type->getIdOperand(1) == makeUintConstant(vectorCount))
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMatrix);
+ type->addIdOperand(debugId[vectorType]); // vector type id
+ type->addIdOperand(makeUintConstant(vectorCount)); // component count id
+ type->addIdOperand(makeBoolConstant(columnMajor)); // column-major id
+
+ groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc)
+{
+ assert(debugId[memberType] != 0);
+
+ Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember);
+ type->addIdOperand(getStringId(debugTypeLoc.name)); // name id
+ type->addIdOperand(debugId[memberType]); // type id
+ type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives
+ type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero
+ type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id
+ type->addIdOperand(makeUintConstant(0)); // TODO: offset id
+ type->addIdOperand(makeUintConstant(0)); // TODO: size id
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id
+
+ groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMember].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+// Note: To represent a source language opaque type, this instruction must have no Members operands, Size operand must be
+// DebugInfoNone, and Name must start with @ to avoid clashes with user defined names.
+Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char const*const name,
+ NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType)
+{
+ // Create the debug member types.
+ std::vector<Id> memberDebugTypes;
+ for(auto const memberType : memberTypes) {
+ assert(debugTypeLocs.find(memberType) != debugTypeLocs.end());
+
+ memberDebugTypes.emplace_back(makeMemberDebugType(memberType, debugTypeLocs[memberType]));
+
+ // TODO: Need to rethink this method of passing location information.
+ // debugTypeLocs.erase(memberType);
+ }
+
+ // Create The structure debug type.
+ Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite);
+ type->addIdOperand(getStringId(name)); // name id
+ type->addIdOperand(makeUintConstant(tag)); // tag id
+ type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives
+ type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
+ type->addIdOperand(makeUintConstant(0)); // TODO: column id
+ type->addIdOperand(makeDebugCompilationUnit()); // scope id
+ if(isOpaqueType == true) {
+ // Prepend '@' to opaque types.
+ type->addIdOperand(getStringId('@' + std::string(name))); // linkage name id
+ type->addIdOperand(makeDebugInfoNone()); // size id
+ } else {
+ type->addIdOperand(getStringId(name)); // linkage name id
+ type->addIdOperand(makeUintConstant(0)); // TODO: size id
+ }
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id
+ assert(isOpaqueType == false || (isOpaqueType == true && memberDebugTypes.empty()));
+ for(auto const memberDebugType : memberDebugTypes) {
+ type->addIdOperand(memberDebugType);
+ }
+
+ groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeComposite].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeDebugSource(const Id fileName) {
+ if (debugSourceId.find(fileName) != debugSourceId.end())
+ return debugSourceId[fileName];
+ spv::Id resultId = getUniqueId();
+ Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst);
+ sourceInst->addIdOperand(nonSemanticShaderDebugInfo);
+ sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugSource);
+ sourceInst->addIdOperand(fileName);
+ if (emitNonSemanticShaderDebugSource) {
+ spv::Id sourceId = 0;
+ if (fileName == sourceFileStringId) {
+ sourceId = getStringId(sourceText);
+ } else {
+ auto incItr = includeFiles.find(fileName);
+ assert(incItr != includeFiles.end());
+ sourceId = getStringId(*incItr->second);
+ }
+ sourceInst->addIdOperand(sourceId);
+ }
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
+ module.mapInstruction(sourceInst);
+ debugSourceId[fileName] = resultId;
+ return resultId;
+}
+
+Id Builder::makeDebugCompilationUnit() {
+ if (nonSemanticShaderCompilationUnitId != 0)
+ return nonSemanticShaderCompilationUnitId;
+ spv::Id resultId = getUniqueId();
+ Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst);
+ sourceInst->addIdOperand(nonSemanticShaderDebugInfo);
+ sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit);
+ sourceInst->addIdOperand(makeUintConstant(1)); // TODO(greg-lunarg): Get rid of magic number
+ sourceInst->addIdOperand(makeUintConstant(4)); // TODO(greg-lunarg): Get rid of magic number
+ sourceInst->addIdOperand(makeDebugSource(sourceFileStringId));
+ sourceInst->addIdOperand(makeUintConstant(sourceLang));
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
+ module.mapInstruction(sourceInst);
+ nonSemanticShaderCompilationUnitId = resultId;
+ return resultId;
+}
+
+Id Builder::createDebugGlobalVariable(Id const type, char const*const name, Id const variable)
+{
+ assert(type != 0);
+
+ Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ inst->addIdOperand(nonSemanticShaderDebugInfo);
+ inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable);
+ inst->addIdOperand(getStringId(name)); // name id
+ inst->addIdOperand(type); // type id
+ inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id
+ inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
+ inst->addIdOperand(makeUintConstant(0)); // TODO: column id
+ inst->addIdOperand(makeDebugCompilationUnit()); // scope id
+ inst->addIdOperand(getStringId(name)); // linkage name id
+ inst->addIdOperand(variable); // variable id
+ inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsDefinition)); // flags id
+
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
+ module.mapInstruction(inst);
+
+ return inst->getResultId();
+}
+
+Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t const argNumber)
+{
+ assert(name != nullptr);
+ Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ inst->addIdOperand(nonSemanticShaderDebugInfo);
+ inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable);
+ inst->addIdOperand(getStringId(name)); // name id
+ inst->addIdOperand(type); // type id
+ inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id
+ inst->addIdOperand(makeUintConstant(currentLine)); // line id
+ inst->addIdOperand(makeUintConstant(0)); // TODO: column id
+ inst->addIdOperand(currentDebugScopeId.top()); // scope id
+ inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsLocal)); // flags id
+ if(argNumber != 0) {
+ inst->addIdOperand(makeUintConstant(argNumber));
+ }
+
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
+ module.mapInstruction(inst);
+
+ return inst->getResultId();
+}
+
+Id Builder::makeDebugExpression()
+{
+ if (debugExpression != 0)
+ return debugExpression;
+
+ Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ inst->addIdOperand(nonSemanticShaderDebugInfo);
+ inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugExpression);
+
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
+ module.mapInstruction(inst);
+
+ debugExpression = inst->getResultId();
+
+ return debugExpression;
+}
+
+Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const localVariable)
+{
+ Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
+ inst->addIdOperand(nonSemanticShaderDebugInfo);
+ inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugDeclare);
+ inst->addIdOperand(debugLocalVariable); // debug local variable id
+ inst->addIdOperand(localVariable); // local variable id
+ inst->addIdOperand(makeDebugExpression()); // expression id
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+
+ return inst->getResultId();
+}
+
#ifndef GLSLANG_WEB
Id Builder::makeAccelerationStructureType()
{
@@ -920,6 +1433,17 @@ bool Builder::isSpecConstantOpCode(Op opcode) const
}
}
+bool Builder::isRayTracingOpCode(Op opcode) const
+{
+ switch (opcode) {
+ case OpTypeAccelerationStructureKHR:
+ case OpTypeRayQueryKHR:
+ return true;
+ default:
+ return false;
+ }
+}
+
Id Builder::makeNullConstant(Id typeId)
{
Instruction* constant;
@@ -1136,6 +1660,19 @@ Id Builder::makeFpConstant(Id type, double d, bool specConstant)
return NoResult;
}
+Id Builder::importNonSemanticShaderDebugInfoInstructions()
+{
+ assert(emitNonSemanticShaderDebugInfo == true);
+
+ if(nonSemanticShaderDebugInfo == 0)
+ {
+ this->addExtension(spv::E_SPV_KHR_non_semantic_info);
+ nonSemanticShaderDebugInfo = this->import("NonSemantic.Shader.DebugInfo.100");
+ }
+
+ return nonSemanticShaderDebugInfo;
+}
+
Id Builder::findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps)
{
Instruction* constant = 0;
@@ -1447,23 +1984,34 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
assert(! entryPointFunction);
Block* entry;
- std::vector<Id> params;
+ std::vector<Id> paramsTypes;
+ std::vector<char const*> paramNames;
std::vector<std::vector<Decoration>> decorations;
- entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry);
+ auto const returnType = makeVoidType();
+
+ restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo;
+ if(sourceLang == spv::SourceLanguageHLSL) {
+ emitNonSemanticShaderDebugInfo = false;
+ }
+
+ entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, paramsTypes, paramNames, decorations, &entry);
+
+ emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo;
return entryPointFunction;
}
// Comments in header
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
- const std::vector<Id>& paramTypes,
+ const std::vector<Id>& paramTypes, const std::vector<char const*>& paramNames,
const std::vector<std::vector<Decoration>>& decorations, Block **entry)
{
// Make the function and initial instructions in it
Id typeId = makeFunctionType(returnType, paramTypes);
Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size());
- Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module);
+ Id funcId = getUniqueId();
+ Function* function = new Function(funcId, returnType, typeId, firstParamId, module);
// Set up the precisions
setPrecision(function->getId(), precision);
@@ -1475,11 +2023,39 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
}
}
+ // Make the debug function instruction
+ if (emitNonSemanticShaderDebugInfo) {
+ Id nameId = getStringId(unmangleFunctionName(name));
+ Id debugFuncId = makeDebugFunction(function, nameId, typeId);
+ debugId[funcId] = debugFuncId;
+ currentDebugScopeId.push(debugFuncId);
+ lastDebugScopeId = NoResult;
+ }
+
// CFG
- if (entry) {
- *entry = new Block(getUniqueId(), *function);
- function->addBlock(*entry);
- setBuildPoint(*entry);
+ assert(entry != nullptr);
+ *entry = new Block(getUniqueId(), *function);
+ function->addBlock(*entry);
+ setBuildPoint(*entry);
+
+ // DebugScope and DebugLine for parameter DebugDeclares
+ if (emitNonSemanticShaderDebugInfo && (int)paramTypes.size() > 0) {
+ addDebugScopeAndLine(currentFileId, currentLine, 0);
+ }
+
+ if (emitNonSemanticShaderDebugInfo) {
+ assert(paramTypes.size() == paramNames.size());
+ for(size_t p = 0; p < paramTypes.size(); ++p)
+ {
+ auto const& paramType = paramTypes[p];
+ assert(isPointerType(paramType) || isArrayType(paramType));
+ assert(debugId[getContainedTypeId(paramType)] != 0);
+ auto const& paramName = paramNames[p];
+ auto const debugLocalVariableId = createDebugLocalVariable(debugId[getContainedTypeId(paramType)], paramName, p+1);
+ debugId[firstParamId + p] = debugLocalVariableId;
+
+ makeDebugDeclare(debugLocalVariableId, firstParamId + p);
+ }
}
if (name)
@@ -1487,9 +2063,62 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
functions.push_back(std::unique_ptr<Function>(function));
+ // Clear debug scope stack
+ if (emitNonSemanticShaderDebugInfo)
+ currentDebugScopeId.pop();
+
return function;
}
+Id Builder::makeDebugFunction(Function* function, Id nameId, Id funcTypeId) {
+ assert(function != nullptr);
+ assert(nameId != 0);
+ assert(funcTypeId != 0);
+ assert(debugId[funcTypeId] != 0);
+
+ Id funcId = getUniqueId();
+ auto type = new Instruction(funcId, makeVoidType(), OpExtInst);
+ type->addIdOperand(nonSemanticShaderDebugInfo);
+ type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunction);
+ type->addIdOperand(nameId);
+ type->addIdOperand(debugId[funcTypeId]);
+ type->addIdOperand(makeDebugSource(currentFileId)); // Will be fixed later when true filename available
+ type->addIdOperand(makeUintConstant(currentLine)); // Will be fixed later when true line available
+ type->addIdOperand(makeUintConstant(0)); // column
+ type->addIdOperand(makeDebugCompilationUnit()); // scope
+ type->addIdOperand(nameId); // linkage name
+ type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic));
+ type->addIdOperand(makeUintConstant(currentLine)); // TODO(greg-lunarg): correct scope line
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+ return funcId;
+}
+
+Id Builder::makeDebugLexicalBlock(uint32_t line) {
+ Id lexId = getUniqueId();
+ auto lex = new Instruction(lexId, makeVoidType(), OpExtInst);
+ lex->addIdOperand(nonSemanticShaderDebugInfo);
+ lex->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLexicalBlock);
+ lex->addIdOperand(makeDebugSource(currentFileId));
+ lex->addIdOperand(makeUintConstant(line));
+ lex->addIdOperand(makeUintConstant(0)); // column
+ lex->addIdOperand(currentDebugScopeId.top()); // scope
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(lex));
+ module.mapInstruction(lex);
+ return lexId;
+}
+
+std::string Builder::unmangleFunctionName(std::string const& name) const
+{
+ assert(name.length() > 0);
+
+ if(name.rfind('(') != std::string::npos) {
+ return name.substr(0, name.rfind('('));
+ } else {
+ return name;
+ }
+}
+
// Comments in header
void Builder::makeReturn(bool implicit, Id retVal)
{
@@ -1505,6 +2134,48 @@ void Builder::makeReturn(bool implicit, Id retVal)
}
// Comments in header
+void Builder::enterScope(uint32_t line)
+{
+ // Generate new lexical scope debug instruction
+ Id lexId = makeDebugLexicalBlock(line);
+ currentDebugScopeId.push(lexId);
+ lastDebugScopeId = NoResult;
+}
+
+// Comments in header
+void Builder::leaveScope()
+{
+ // Pop current scope from stack and clear current scope
+ currentDebugScopeId.pop();
+ lastDebugScopeId = NoResult;
+}
+
+// Comments in header
+void Builder::enterFunction(Function const* function)
+{
+ // Save and disable debugInfo for HLSL entry point function. It is a wrapper
+ // function with no user code in it.
+ restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo;
+ if (sourceLang == spv::SourceLanguageHLSL && function == entryPointFunction) {
+ emitNonSemanticShaderDebugInfo = false;
+ }
+
+ if (emitNonSemanticShaderDebugInfo) {
+ // Initialize scope state
+ Id funcId = function->getFuncId();
+ currentDebugScopeId.push(debugId[funcId]);
+ // Create DebugFunctionDefinition
+ spv::Id resultId = getUniqueId();
+ Instruction* defInst = new Instruction(resultId, makeVoidType(), OpExtInst);
+ defInst->addIdOperand(nonSemanticShaderDebugInfo);
+ defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition);
+ defInst->addIdOperand(debugId[funcId]);
+ defInst->addIdOperand(funcId);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(defInst));
+ }
+}
+
+// Comments in header
void Builder::leaveFunction()
{
Block* block = buildPoint;
@@ -1519,6 +2190,12 @@ void Builder::leaveFunction()
makeReturn(true, createUndefined(function.getReturnType()));
}
}
+
+ // Clear function scope from debug scope stack
+ if (emitNonSemanticShaderDebugInfo)
+ currentDebugScopeId.pop();
+
+ emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo;
}
// Comments in header
@@ -1529,7 +2206,18 @@ void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
}
// Comments in header
-Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer)
+void Builder::makeStatementTerminator(spv::Op opcode, const std::vector<Id>& operands, const char* name)
+{
+ // It's assumed that the terminator instruction is always of void return type
+ // However in future if there is a need for non void return type, new helper
+ // methods can be created.
+ createNoResultOp(opcode, operands);
+ createAndSetNoPredecessorBlock(name);
+}
+
+// Comments in header
+Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer,
+ bool const compilerGenerated)
{
Id pointerType = makePointer(storageClass, type);
Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
@@ -1541,11 +2229,26 @@ Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id t
case StorageClassFunction:
// Validation rules require the declaration in the entry block
buildPoint->getParent().addLocalVariable(std::unique_ptr<Instruction>(inst));
+
+ if (emitNonSemanticShaderDebugInfo && !compilerGenerated)
+ {
+ auto const debugLocalVariableId = createDebugLocalVariable(debugId[type], name);
+ debugId[inst->getResultId()] = debugLocalVariableId;
+
+ makeDebugDeclare(debugLocalVariableId, inst->getResultId());
+ }
+
break;
default:
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
module.mapInstruction(inst);
+
+ if (emitNonSemanticShaderDebugInfo && !isRayTracingOpCode(getOpCode(type)))
+ {
+ auto const debugResultId = createDebugGlobalVariable(debugId[type], name, inst->getResultId());
+ debugId[inst->getResultId()] = debugResultId;
+ }
break;
}
@@ -1575,7 +2278,7 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
case spv::StorageClassPhysicalStorageBufferEXT:
break;
default:
- memoryAccess = spv::MemoryAccessMask(memoryAccess &
+ memoryAccess = spv::MemoryAccessMask(memoryAccess &
~(spv::MemoryAccessMakePointerAvailableKHRMask |
spv::MemoryAccessMakePointerVisibleKHRMask |
spv::MemoryAccessNonPrivatePointerKHRMask));
@@ -2051,7 +2754,7 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
texArgs[numArgs++] = parameters.granularity;
if (parameters.coarse != NoResult)
texArgs[numArgs++] = parameters.coarse;
-#endif
+#endif
//
// Set up the optional arguments
@@ -3271,10 +3974,10 @@ void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& te
const int opSourceWordCount = 4;
const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1;
- if (source != SourceLanguageUnknown) {
+ if (sourceLang != SourceLanguageUnknown) {
// OpSource Language Version File Source
Instruction sourceInst(NoResult, NoType, OpSource);
- sourceInst.addImmediateOperand(source);
+ sourceInst.addImmediateOperand(sourceLang);
sourceInst.addImmediateOperand(sourceVersion);
// File operand
if (fileId != NoResult) {
@@ -3307,6 +4010,7 @@ void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& te
// Dump an OpSource[Continued] sequence for the source and every include file
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
{
+ if (emitNonSemanticShaderDebugInfo) return;
dumpSourceInstructions(sourceFileStringId, sourceText, out);
for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr)
dumpSourceInstructions(iItr->first, *iItr->second, out);
diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.h b/thirdparty/glslang/SPIRV/SpvBuilder.h
index c72d9b287e..f7fdc6ad84 100644
--- a/thirdparty/glslang/SPIRV/SpvBuilder.h
+++ b/thirdparty/glslang/SPIRV/SpvBuilder.h
@@ -50,6 +50,10 @@
#include "Logger.h"
#include "spirv.hpp"
#include "spvIR.h"
+namespace spv {
+ #include "GLSL.ext.KHR.h"
+ #include "NonSemanticShaderDebugInfo100.h"
+}
#include <algorithm>
#include <map>
@@ -82,7 +86,7 @@ public:
void setSource(spv::SourceLanguage lang, int version)
{
- source = lang;
+ sourceLang = lang;
sourceVersion = version;
}
spv::Id getStringId(const std::string& str)
@@ -99,14 +103,32 @@ public:
stringIds[file_c_str] = strId;
return strId;
}
+ spv::Id getSourceFile() const
+ {
+ return sourceFileStringId;
+ }
void setSourceFile(const std::string& file)
{
sourceFileStringId = getStringId(file);
+ currentFileId = sourceFileStringId;
}
void setSourceText(const std::string& text) { sourceText = text; }
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
void setEmitOpLines() { emitOpLines = true; }
+ void setEmitNonSemanticShaderDebugInfo(bool const emit)
+ {
+ emitNonSemanticShaderDebugInfo = emit;
+
+ if(emit)
+ {
+ importNonSemanticShaderDebugInfoInstructions();
+ }
+ }
+ void setEmitNonSemanticShaderDebugSource(bool const src)
+ {
+ emitNonSemanticShaderDebugSource = src;
+ }
void addExtension(const char* ext) { extensions.insert(ext); }
void removeExtension(const char* ext)
{
@@ -159,10 +181,11 @@ public:
void setLine(int line, const char* filename);
// Low-level OpLine. See setLine() for a layered helper.
void addLine(Id fileName, int line, int column);
+ void addDebugScopeAndLine(Id fileName, int line, int column);
// For creating new types (will return old type if the requested one was already made).
Id makeVoidType();
- Id makeBoolType();
+ Id makeBoolType(bool const compilerGenerated = true);
Id makePointer(StorageClass, Id pointee);
Id makeForwardPointer(StorageClass);
Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee);
@@ -170,7 +193,7 @@ public:
Id makeIntType(int width) { return makeIntegerType(width, true); }
Id makeUintType(int width) { return makeIntegerType(width, false); }
Id makeFloatType(int width);
- Id makeStructType(const std::vector<Id>& members, const char*);
+ Id makeStructType(const std::vector<Id>& members, const char* name, bool const compilerGenerated = true);
Id makeStructResultType(Id type0, Id type1);
Id makeVectorType(Id component, int size);
Id makeMatrixType(Id component, int cols, int rows);
@@ -183,6 +206,36 @@ public:
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
Id makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands);
+ // SPIR-V NonSemantic Shader DebugInfo Instructions
+ struct DebugTypeLoc {
+ std::string name {};
+ int line {0};
+ int column {0};
+ };
+ std::unordered_map<Id, DebugTypeLoc> debugTypeLocs;
+ Id makeDebugInfoNone();
+ Id makeBoolDebugType(int const size);
+ Id makeIntegerDebugType(int const width, bool const hasSign);
+ Id makeFloatDebugType(int const width);
+ Id makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType);
+ Id makeArrayDebugType(Id const baseType, Id const componentCount);
+ Id makeVectorDebugType(Id const baseType, int const componentCount);
+ Id makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor = true);
+ Id makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc);
+ Id makeCompositeDebugType(std::vector<Id> const& memberTypes, char const*const name,
+ NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType = false);
+ Id makeDebugSource(const Id fileName);
+ Id makeDebugCompilationUnit();
+ Id createDebugGlobalVariable(Id const type, char const*const name, Id const variable);
+ Id createDebugLocalVariable(Id type, char const*const name, size_t const argNumber = 0);
+ Id makeDebugExpression();
+ Id makeDebugDeclare(Id const debugLocalVariable, Id const localVariable);
+ Id makeDebugValue(Id const debugLocalVariable, Id const value);
+ Id makeDebugFunctionType(Id returnType, const std::vector<Id>& paramTypes);
+ Id makeDebugFunction(Function* function, Id nameId, Id funcTypeId);
+ Id makeDebugLexicalBlock(uint32_t line);
+ std::string unmangleFunctionName(std::string const& name) const;
+
// accelerationStructureNV type
Id makeAccelerationStructureType();
// rayQueryEXT type
@@ -257,6 +310,8 @@ public:
// See if a resultId is valid for use as an initializer.
bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); }
+ bool isRayTracingOpCode(Op opcode) const;
+
int getScalarTypeWidth(Id typeId) const
{
Id scalarTypeId = getScalarTypeId(typeId);
@@ -318,6 +373,8 @@ public:
Id makeFloat16Constant(float f16, bool specConstant = false);
Id makeFpConstant(Id type, double d, bool specConstant = false);
+ Id importNonSemanticShaderDebugInfoInstructions();
+
// Turn the array of constants into a proper spv constant of the requested type.
Id makeCompositeConstant(Id type, const std::vector<Id>& comps, bool specConst = false);
@@ -340,7 +397,12 @@ public:
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings);
// At the end of what block do the next create*() instructions go?
- void setBuildPoint(Block* bp) { buildPoint = bp; }
+ // Also reset current last DebugScope and current source line to unknown
+ void setBuildPoint(Block* bp) {
+ buildPoint = bp;
+ lastDebugScopeId = NoResult;
+ currentLine = 0;
+ }
Block* getBuildPoint() const { return buildPoint; }
// Make the entry-point function. The returned pointer is only valid
@@ -351,12 +413,22 @@ public:
// Return the function, pass back the entry.
// The returned pointer is only valid for the lifetime of this builder.
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
- const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
+ const std::vector<Id>& paramTypes, const std::vector<char const*>& paramNames,
+ const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source
// code. In the case of an implicit return, no post-return block is inserted.
void makeReturn(bool implicit, Id retVal = 0);
+ // Initialize state and generate instructions for new lexical scope
+ void enterScope(uint32_t line);
+
+ // Set state and generate instructions to exit current lexical scope
+ void leaveScope();
+
+ // Prepare builder for generation of instructions for a function.
+ void enterFunction(Function const* function);
+
// Generate all the code needed to finish up a function.
void leaveFunction();
@@ -364,9 +436,13 @@ public:
// discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT
void makeStatementTerminator(spv::Op opcode, const char *name);
+ // Create block terminator instruction for statements that have input operands
+ // such as OpEmitMeshTasksEXT
+ void makeStatementTerminator(spv::Op opcode, const std::vector<Id>& operands, const char* name);
+
// Create a global or function local or IO variable.
- Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
- Id initializer = NoResult);
+ Id createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name = nullptr,
+ Id initializer = NoResult, bool const compilerGenerated = true);
// Create an intermediate with an undefined value.
Id createUndefined(Id type);
@@ -801,13 +877,23 @@ public:
const;
unsigned int spvVersion; // the version of SPIR-V to emit in the header
- SourceLanguage source;
+ SourceLanguage sourceLang;
int sourceVersion;
spv::Id sourceFileStringId;
+ spv::Id nonSemanticShaderCompilationUnitId {0};
+ spv::Id nonSemanticShaderDebugInfo {0};
+ spv::Id debugInfoNone {0};
+ spv::Id debugExpression {0}; // Debug expression with zero operations.
std::string sourceText;
int currentLine;
const char* currentFile;
+ spv::Id currentFileId;
+ std::stack<spv::Id> currentDebugScopeId;
+ spv::Id lastDebugScopeId;
bool emitOpLines;
+ bool emitNonSemanticShaderDebugInfo;
+ bool restoreNonSemanticShaderDebugInfo;
+ bool emitNonSemanticShaderDebugSource;
std::set<std::string> extensions;
std::vector<const char*> sourceExtensions;
std::vector<const char*> moduleProcesses;
@@ -841,6 +927,8 @@ public:
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
// map type opcodes to type instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
+ // map type opcodes to debug type instructions
+ std::unordered_map<unsigned int, std::vector<Instruction*>> groupedDebugTypes;
// list of OpConstantNull instructions
std::vector<Instruction*> nullConstants;
@@ -856,6 +944,12 @@ public:
// map from include file name ids to their contents
std::map<spv::Id, const std::string*> includeFiles;
+ // map from core id to debug id
+ std::map <spv::Id, spv::Id> debugId;
+
+ // map from file name string id to DebugSource id
+ std::unordered_map<spv::Id, spv::Id> debugSourceId;
+
// The stream for outputting warnings and errors.
SpvBuildLogger* logger;
}; // end Builder class
diff --git a/thirdparty/glslang/SPIRV/SpvTools.cpp b/thirdparty/glslang/SPIRV/SpvTools.cpp
index e8f825119a..25299937a3 100644
--- a/thirdparty/glslang/SPIRV/SpvTools.cpp
+++ b/thirdparty/glslang/SPIRV/SpvTools.cpp
@@ -212,6 +212,8 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass());
if (options->optimizeSize) {
optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
+ if (intermediate.getStage() == EShLanguage::EShLangVertex)
+ optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsPass());
}
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
diff --git a/thirdparty/glslang/SPIRV/SpvTools.h b/thirdparty/glslang/SPIRV/SpvTools.h
index 3fb3cbacd3..5386048ab6 100644
--- a/thirdparty/glslang/SPIRV/SpvTools.h
+++ b/thirdparty/glslang/SPIRV/SpvTools.h
@@ -53,14 +53,14 @@
namespace glslang {
struct SpvOptions {
- SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
- optimizeSize(false), disassemble(false), validate(false) { }
- bool generateDebugInfo;
- bool stripDebugInfo;
- bool disableOptimizer;
- bool optimizeSize;
- bool disassemble;
- bool validate;
+ bool generateDebugInfo {false};
+ bool stripDebugInfo {false};
+ bool disableOptimizer {true};
+ bool optimizeSize {false};
+ bool disassemble {false};
+ bool validate {false};
+ bool emitNonSemanticShaderDebugInfo {false};
+ bool emitNonSemanticShaderDebugSource{ false };
};
#if ENABLE_OPT
diff --git a/thirdparty/glslang/SPIRV/doc.cpp b/thirdparty/glslang/SPIRV/doc.cpp
index 9a569e0d7f..b7fe3e7424 100644
--- a/thirdparty/glslang/SPIRV/doc.cpp
+++ b/thirdparty/glslang/SPIRV/doc.cpp
@@ -97,6 +97,8 @@ const char* ExecutionModelString(int model)
case 6: return "Kernel";
case ExecutionModelTaskNV: return "TaskNV";
case ExecutionModelMeshNV: return "MeshNV";
+ case ExecutionModelTaskEXT: return "TaskEXT";
+ case ExecutionModelMeshEXT: return "MeshEXT";
default: return "Bad";
@@ -173,28 +175,32 @@ const char* ExecutionModeString(int mode)
case 31: return "ContractionOff";
case 32: return "Bad";
- case ExecutionModeInitializer: return "Initializer";
- case ExecutionModeFinalizer: return "Finalizer";
- case ExecutionModeSubgroupSize: return "SubgroupSize";
- case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup";
- case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId";
- case ExecutionModeLocalSizeId: return "LocalSizeId";
- case ExecutionModeLocalSizeHintId: return "LocalSizeHintId";
-
- case ExecutionModePostDepthCoverage: return "PostDepthCoverage";
- case ExecutionModeDenormPreserve: return "DenormPreserve";
- case ExecutionModeDenormFlushToZero: return "DenormFlushToZero";
- case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
- case ExecutionModeRoundingModeRTE: return "RoundingModeRTE";
- case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ";
- case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT";
+ case ExecutionModeInitializer: return "Initializer";
+ case ExecutionModeFinalizer: return "Finalizer";
+ case ExecutionModeSubgroupSize: return "SubgroupSize";
+ case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup";
+ case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId";
+ case ExecutionModeLocalSizeId: return "LocalSizeId";
+ case ExecutionModeLocalSizeHintId: return "LocalSizeHintId";
+
+ case ExecutionModePostDepthCoverage: return "PostDepthCoverage";
+ case ExecutionModeDenormPreserve: return "DenormPreserve";
+ case ExecutionModeDenormFlushToZero: return "DenormFlushToZero";
+ case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
+ case ExecutionModeRoundingModeRTE: return "RoundingModeRTE";
+ case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ";
+ case ExecutionModeEarlyAndLateFragmentTestsAMD: return "EarlyAndLateFragmentTestsAMD";
+ case ExecutionModeStencilRefUnchangedFrontAMD: return "StencilRefUnchangedFrontAMD";
+ case ExecutionModeStencilRefLessFrontAMD: return "StencilRefLessFrontAMD";
+ case ExecutionModeStencilRefGreaterBackAMD: return "StencilRefGreaterBackAMD";
+ case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT";
case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow";
- case ExecutionModeOutputLinesNV: return "OutputLinesNV";
- case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
- case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV";
- case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV";
- case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV";
+ case ExecutionModeOutputLinesNV: return "OutputLinesNV";
+ case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
+ case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV";
+ case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV";
+ case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV";
case ExecutionModePixelInterlockOrderedEXT: return "PixelInterlockOrderedEXT";
case ExecutionModePixelInterlockUnorderedEXT: return "PixelInterlockUnorderedEXT";
@@ -238,7 +244,7 @@ const char* StorageClassString(int StorageClass)
case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR";
case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
-
+ case StorageClassTaskPayloadWorkgroupEXT: return "TaskPayloadWorkgroupEXT";
default: return "Bad";
}
}
@@ -305,7 +311,8 @@ const char* DecorationString(int decoration)
case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
case DecorationPerViewNV: return "PerViewNV";
case DecorationPerTaskNV: return "PerTaskNV";
- case DecorationPerVertexNV: return "PerVertexNV";
+
+ case DecorationPerVertexKHR: return "PerVertexKHR";
case DecorationNonUniformEXT: return "DecorationNonUniformEXT";
case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
@@ -392,6 +399,7 @@ const char* BuiltInString(int builtIn)
case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR";
case BuiltInRayTminKHR: return "RayTminKHR";
case BuiltInRayTmaxKHR: return "RayTmaxKHR";
+ case BuiltInCullMaskKHR: return "CullMaskKHR";
case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR";
case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR";
case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR";
@@ -406,8 +414,8 @@ const char* BuiltInString(int builtIn)
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT
// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
- case BuiltInBaryCoordNV: return "BaryCoordNV";
- case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
+ case BuiltInBaryCoordKHR: return "BaryCoordKHR";
+ case BuiltInBaryCoordNoPerspKHR: return "BaryCoordNoPerspKHR";
case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
@@ -427,6 +435,10 @@ const char* BuiltInString(int builtIn)
case BuiltInWarpIDNV: return "WarpIDNV";
case BuiltInSMIDNV: return "SMIDNV";
case BuiltInCurrentRayTimeNV: return "CurrentRayTimeNV";
+ case BuiltInPrimitivePointIndicesEXT: return "PrimitivePointIndicesEXT";
+ case BuiltInPrimitiveLineIndicesEXT: return "PrimitiveLineIndicesEXT";
+ case BuiltInPrimitiveTriangleIndicesEXT: return "PrimitiveTriangleIndicesEXT";
+ case BuiltInCullPrimitiveEXT: return "CullPrimitiveEXT";
default: return "Bad";
}
@@ -925,14 +937,16 @@ const char* CapabilityString(int info)
case CapabilityRayTracingNV: return "RayTracingNV";
case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV";
case CapabilityRayTracingKHR: return "RayTracingKHR";
+ case CapabilityRayCullMaskKHR: return "RayCullMaskKHR";
case CapabilityRayQueryKHR: return "RayQueryKHR";
case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR";
case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR";
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
- case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
+ case CapabilityFragmentBarycentricKHR: return "FragmentBarycentricKHR";
case CapabilityMeshShadingNV: return "MeshShadingNV";
case CapabilityImageFootprintNV: return "ImageFootprintNV";
+ case CapabilityMeshShadingEXT: return "MeshShadingEXT";
// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by FragmentDensityEXT
case CapabilitySampleMaskOverrideCoverageNV: return "SampleMaskOverrideCoverageNV";
case CapabilityFragmentDensityEXT: return "FragmentDensityEXT";
@@ -1400,6 +1414,8 @@ const char* OpcodeString(int op)
case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV";
case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV";
case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
+ case OpEmitMeshTasksEXT: return "OpEmitMeshTasksEXT";
+ case OpSetMeshOutputsEXT: return "OpSetMeshOutputsEXT";
case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR";
case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR";
@@ -2974,6 +2990,17 @@ void Parameterize()
InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Index Offset'");
InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Packed Indices'");
+ InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountX'");
+ InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountY'");
+ InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountZ'");
+ InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'Payload'");
+ InstructionDesc[OpEmitMeshTasksEXT].setResultAndType(false, false);
+
+ InstructionDesc[OpSetMeshOutputsEXT].operands.push(OperandId, "'vertexCount'");
+ InstructionDesc[OpSetMeshOutputsEXT].operands.push(OperandId, "'primitiveCount'");
+ InstructionDesc[OpSetMeshOutputsEXT].setResultAndType(false, false);
+
+
InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Component Type'");
InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Scope'");
InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Rows'");
diff --git a/thirdparty/glslang/SPIRV/spirv.hpp b/thirdparty/glslang/SPIRV/spirv.hpp
index 3d500ebbd9..f85469d441 100644
--- a/thirdparty/glslang/SPIRV/spirv.hpp
+++ b/thirdparty/glslang/SPIRV/spirv.hpp
@@ -1,19 +1,19 @@
// Copyright (c) 2014-2020 The Khronos Group Inc.
-//
+//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and/or associated documentation files (the "Materials"),
// to deal in the Materials without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Materials, and to permit persons to whom the
// Materials are furnished to do so, subject to the following conditions:
-//
+//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Materials.
-//
+//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
-// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
-//
+// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -27,7 +27,7 @@
// Enumeration tokens for SPIR-V, in various styles:
// C, C++, C++11, JSON, Lua, Python, C#, D
-//
+//
// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
@@ -36,7 +36,7 @@
// - C# will use enum classes in the Specification class located in the "Spv" namespace,
// e.g.: Spv.Specification.SourceLanguage.GLSL
// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL
-//
+//
// Some tokens act like mask values, which can be OR'd together,
// while others are mutually exclusive. The mask-like ones have
// "Mask" in their name, and a parallel enum that has the shift
@@ -91,6 +91,8 @@ enum ExecutionModel {
ExecutionModelMissNV = 5317,
ExecutionModelCallableKHR = 5318,
ExecutionModelCallableNV = 5318,
+ ExecutionModelTaskEXT = 5364,
+ ExecutionModelMeshEXT = 5365,
ExecutionModelMax = 0x7fffffff,
};
@@ -158,11 +160,21 @@ enum ExecutionMode {
ExecutionModeSignedZeroInfNanPreserve = 4461,
ExecutionModeRoundingModeRTE = 4462,
ExecutionModeRoundingModeRTZ = 4463,
+ ExecutionModeEarlyAndLateFragmentTestsAMD = 5017,
ExecutionModeStencilRefReplacingEXT = 5027,
+ ExecutionModeStencilRefUnchangedFrontAMD = 5079,
+ ExecutionModeStencilRefGreaterFrontAMD = 5080,
+ ExecutionModeStencilRefLessFrontAMD = 5081,
+ ExecutionModeStencilRefUnchangedBackAMD = 5082,
+ ExecutionModeStencilRefGreaterBackAMD = 5083,
+ ExecutionModeStencilRefLessBackAMD = 5084,
+ ExecutionModeOutputLinesEXT = 5269,
ExecutionModeOutputLinesNV = 5269,
+ ExecutionModeOutputPrimitivesEXT = 5270,
ExecutionModeOutputPrimitivesNV = 5270,
ExecutionModeDerivativeGroupQuadsNV = 5289,
ExecutionModeDerivativeGroupLinearNV = 5290,
+ ExecutionModeOutputTrianglesEXT = 5298,
ExecutionModeOutputTrianglesNV = 5298,
ExecutionModePixelInterlockOrderedEXT = 5366,
ExecutionModePixelInterlockUnorderedEXT = 5367,
@@ -211,6 +223,7 @@ enum StorageClass {
StorageClassShaderRecordBufferNV = 5343,
StorageClassPhysicalStorageBuffer = 5349,
StorageClassPhysicalStorageBufferEXT = 5349,
+ StorageClassTaskPayloadWorkgroupEXT = 5402,
StorageClassCodeSectionINTEL = 5605,
StorageClassDeviceOnlyINTEL = 5936,
StorageClassHostOnlyINTEL = 5937,
@@ -493,6 +506,7 @@ enum Decoration {
DecorationPassthroughNV = 5250,
DecorationViewportRelativeNV = 5252,
DecorationSecondaryViewportRelativeNV = 5256,
+ DecorationPerPrimitiveEXT = 5271,
DecorationPerPrimitiveNV = 5271,
DecorationPerViewNV = 5272,
DecorationPerTaskNV = 5273,
@@ -640,6 +654,10 @@ enum BuiltIn {
BuiltInFragmentSizeNV = 5292,
BuiltInFragInvocationCountEXT = 5293,
BuiltInInvocationsPerPixelNV = 5293,
+ BuiltInPrimitivePointIndicesEXT = 5294,
+ BuiltInPrimitiveLineIndicesEXT = 5295,
+ BuiltInPrimitiveTriangleIndicesEXT = 5296,
+ BuiltInCullPrimitiveEXT = 5299,
BuiltInLaunchIdKHR = 5319,
BuiltInLaunchIdNV = 5319,
BuiltInLaunchSizeKHR = 5320,
@@ -673,6 +691,7 @@ enum BuiltIn {
BuiltInSMCountNV = 5375,
BuiltInWarpIDNV = 5376,
BuiltInSMIDNV = 5377,
+ BuiltInCullMaskKHR = 6021,
BuiltInMax = 0x7fffffff,
};
@@ -975,7 +994,8 @@ enum Capability {
CapabilityFragmentFullyCoveredEXT = 5265,
CapabilityMeshShadingNV = 5266,
CapabilityImageFootprintNV = 5282,
- CapabilityFragmentBarycentricKHR = 5284,
+ CapabilityMeshShadingEXT = 5283,
+ CapabilityFragmentBarycentricKHR = 5284,
CapabilityFragmentBarycentricNV = 5284,
CapabilityComputeDerivativeGroupQuadsNV = 5288,
CapabilityFragmentDensityEXT = 5291,
@@ -1069,6 +1089,7 @@ enum Capability {
CapabilityDotProductInput4x8BitPackedKHR = 6018,
CapabilityDotProduct = 6019,
CapabilityDotProductKHR = 6019,
+ CapabilityRayCullMaskKHR = 6020,
CapabilityBitInstructions = 6025,
CapabilityAtomicFloat32AddEXT = 6033,
CapabilityAtomicFloat64AddEXT = 6034,
@@ -1568,6 +1589,8 @@ enum Op {
OpFragmentFetchAMD = 5012,
OpReadClockKHR = 5056,
OpImageSampleFootprintNV = 5283,
+ OpEmitMeshTasksEXT = 5294,
+ OpSetMeshOutputsEXT = 5295,
OpGroupNonUniformPartitionNV = 5296,
OpWritePackedPrimitiveIndices4x8NV = 5299,
OpReportIntersectionKHR = 5334,
@@ -2225,6 +2248,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpReadClockKHR: *hasResult = true; *hasResultType = true; break;
case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break;
case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break;
+ case OpEmitMeshTasksEXT: *hasResult = false; *hasResultType = false; break;
+ case OpSetMeshOutputsEXT: *hasResult = false; *hasResultType = false; break;
case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break;
case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break;
case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break;
@@ -2506,4 +2531,3 @@ inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShad
} // end namespace spv
#endif // #ifndef spirv_HPP
-
diff --git a/thirdparty/glslang/SPIRV/spvIR.h b/thirdparty/glslang/SPIRV/spvIR.h
index 5249a5ba73..09691273ab 100644
--- a/thirdparty/glslang/SPIRV/spvIR.h
+++ b/thirdparty/glslang/SPIRV/spvIR.h
@@ -349,6 +349,7 @@ public:
const std::vector<Block*>& getBlocks() const { return blocks; }
void addLocalVariable(std::unique_ptr<Instruction> inst);
Id getReturnType() const { return functionInstruction.getTypeId(); }
+ Id getFuncId() const { return functionInstruction.getResultId(); }
void setReturnPrecision(Decoration precision)
{
if (precision == DecorationRelaxedPrecision)
@@ -357,6 +358,14 @@ public:
Decoration getReturnPrecision() const
{ return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; }
+ void setDebugLineInfo(Id fileName, int line, int column) {
+ lineInstruction = std::unique_ptr<Instruction>{new Instruction(OpLine)};
+ lineInstruction->addIdOperand(fileName);
+ lineInstruction->addImmediateOperand(line);
+ lineInstruction->addImmediateOperand(column);
+ }
+ bool hasDebugLineInfo() const { return lineInstruction != nullptr; }
+
void setImplicitThis() { implicitThis = true; }
bool hasImplicitThis() const { return implicitThis; }
@@ -373,6 +382,11 @@ public:
void dump(std::vector<unsigned int>& out) const
{
+ // OpLine
+ if (lineInstruction != nullptr) {
+ lineInstruction->dump(out);
+ }
+
// OpFunction
functionInstruction.dump(out);
@@ -391,6 +405,7 @@ protected:
Function& operator=(Function&);
Module& parent;
+ std::unique_ptr<Instruction> lineInstruction;
Instruction functionInstruction;
std::vector<Instruction*> parameterInstructions;
std::vector<Block*> blocks;
@@ -457,7 +472,8 @@ protected:
// - the OpFunction instruction
// - all the OpFunctionParameter instructions
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
- : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false),
+ : parent(parent), lineInstruction(nullptr),
+ functionInstruction(id, resultType, OpFunction), implicitThis(false),
reducedPrecisionReturn(false)
{
// OpFunction