Updated glslang.

This commit is contained in:
Бранимир Караџић 2024-02-09 22:20:26 -08:00
parent 8ab5837546
commit 6ce4b76c9a
19 changed files with 1845 additions and 1596 deletions

View File

@ -1,5 +1,6 @@
/* /*
** Copyright (c) 2014-2020 The Khronos Group Inc. ** Copyright (c) 2014-2020 The Khronos Group Inc.
** Copyright (C) 2022-2024 Arm Limited.
** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. ** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
** **
** Permission is hereby granted, free of charge, to any person obtaining a copy ** Permission is hereby granted, free of charge, to any person obtaining a copy
@ -53,8 +54,11 @@ static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_termi
static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout"; 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_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_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric";
static const char* const E_SPV_KHR_quad_control = "SPV_KHR_quad_control";
static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests"; static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests";
static const char* const E_SPV_KHR_ray_tracing_position_fetch = "SPV_KHR_ray_tracing_position_fetch"; static const char* const E_SPV_KHR_ray_tracing_position_fetch = "SPV_KHR_ray_tracing_position_fetch";
static const char* const E_SPV_KHR_cooperative_matrix = "SPV_KHR_cooperative_matrix"; static const char* const E_SPV_KHR_cooperative_matrix = "SPV_KHR_cooperative_matrix";
static const char* const E_SPV_KHR_maximal_reconvergence = "SPV_KHR_maximal_reconvergence";
static const char* const E_SPV_KHR_subgroup_rotate = "SPV_KHR_subgroup_rotate";
#endif // #ifndef GLSLextKHR_H #endif // #ifndef GLSLextKHR_H

View File

@ -1,7 +1,7 @@
// //
// Copyright (C) 2014-2016 LunarG, Inc. // Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017, 2022-2024 Arm Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
@ -1558,8 +1558,13 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
this->options.generateDebugInfo = true; this->options.generateDebugInfo = true;
if (this->options.generateDebugInfo) { if (this->options.generateDebugInfo) {
builder.setEmitOpLines(); if (this->options.emitNonSemanticShaderDebugInfo) {
builder.setSourceFile(glslangIntermediate->getSourceFile()); builder.setEmitNonSemanticShaderDebugInfo(this->options.emitNonSemanticShaderDebugSource);
}
else {
builder.setEmitSpirvDebugInfo();
}
builder.setDebugSourceFile(glslangIntermediate->getSourceFile());
// Set the source shader's text. If for SPV version 1.0, include // Set the source shader's text. If for SPV version 1.0, include
// a preamble in comments stating the OpModuleProcessed instructions. // a preamble in comments stating the OpModuleProcessed instructions.
@ -1584,9 +1589,6 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
builder.addInclude(iItr->first, iItr->second); builder.addInclude(iItr->first, iItr->second);
} }
builder.setEmitNonSemanticShaderDebugInfo(this->options.emitNonSemanticShaderDebugInfo);
builder.setEmitNonSemanticShaderDebugSource(this->options.emitNonSemanticShaderDebugSource);
stdBuiltins = builder.import("GLSL.std.450"); stdBuiltins = builder.import("GLSL.std.450");
spv::AddressingModel addressingModel = spv::AddressingModelLogical; spv::AddressingModel addressingModel = spv::AddressingModelLogical;
@ -1635,6 +1637,24 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow); builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR); builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR);
} }
if (glslangIntermediate->getMaximallyReconverges()) {
builder.addExtension(spv::E_SPV_KHR_maximal_reconvergence);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeMaximallyReconvergesKHR);
}
if (glslangIntermediate->getQuadDerivMode())
{
builder.addCapability(spv::CapabilityQuadControlKHR);
builder.addExtension(spv::E_SPV_KHR_quad_control);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeQuadDerivativesKHR);
}
if (glslangIntermediate->getReqFullQuadsMode())
{
builder.addCapability(spv::CapabilityQuadControlKHR);
builder.addExtension(spv::E_SPV_KHR_quad_control);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeRequireFullQuadsKHR);
}
unsigned int mode; unsigned int mode;
switch (glslangIntermediate->getStage()) { switch (glslangIntermediate->getStage()) {
@ -2019,7 +2039,9 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
{ {
// We update the line information even though no code might be generated here // We update the line information even though no code might be generated here
// This is helpful to yield correct lines for control flow instructions // This is helpful to yield correct lines for control flow instructions
builder.setLine(symbol->getLoc().line, symbol->getLoc().getFilename()); if (!linkageOnly) {
builder.setDebugSourceLocation(symbol->getLoc().line, symbol->getLoc().getFilename());
}
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (symbol->getType().isStruct()) if (symbol->getType().isStruct())
@ -2128,7 +2150,7 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
{ {
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) { if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) {
glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId(); glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId();
} }
@ -2173,7 +2195,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
spv::Id rValue = accessChainLoad(node->getRight()->getType()); spv::Id rValue = accessChainLoad(node->getRight()->getType());
// reset line number for assignment // reset line number for assignment
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
if (node->getOp() != glslang::EOpAssign) { if (node->getOp() != glslang::EOpAssign) {
// the left is also an r-value // the left is also an r-value
@ -2506,7 +2528,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
{ {
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant()) if (node->getType().getQualifier().isSpecConstant())
@ -2894,11 +2916,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
return false; return false;
} else { } else {
if (node->getOp() == glslang::EOpScope) if (node->getOp() == glslang::EOpScope)
builder.enterScope(0); builder.enterLexicalBlock(0);
} }
} else { } else {
if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope) if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope)
builder.leaveScope(); builder.leaveLexicalBlock();
--sequenceDepth; --sequenceDepth;
} }
@ -2925,6 +2947,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
} }
case glslang::EOpFunction: case glslang::EOpFunction:
if (visit == glslang::EvPreVisit) { if (visit == glslang::EvPreVisit) {
if (options.generateDebugInfo) {
builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
}
if (isShaderEntryPoint(node)) { if (isShaderEntryPoint(node)) {
inEntryPoint = true; inEntryPoint = true;
builder.setBuildPoint(shaderEntry->getLastBlock()); builder.setBuildPoint(shaderEntry->getLastBlock());
@ -2933,10 +2958,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
} else { } else {
handleFunctionEntry(node); handleFunctionEntry(node);
} }
if (options.generateDebugInfo) { if (options.generateDebugInfo && !options.emitNonSemanticShaderDebugInfo) {
const auto& loc = node->getLoc(); const auto& loc = node->getLoc();
const char* sourceFileName = loc.getFilename(); const char* sourceFileName = loc.getFilename();
spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getSourceFile(); spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getMainFileId();
currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column); currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column);
} }
} else { } else {
@ -2954,7 +2979,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
return false; return false;
case glslang::EOpFunctionCall: case glslang::EOpFunctionCall:
{ {
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
if (node->isUserDefined()) if (node->isUserDefined())
result = handleUserFunctionCall(node); result = handleUserFunctionCall(node);
if (result) { if (result) {
@ -3075,7 +3100,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
case glslang::EOpConstructCooperativeMatrixNV: case glslang::EOpConstructCooperativeMatrixNV:
case glslang::EOpConstructCooperativeMatrixKHR: case glslang::EOpConstructCooperativeMatrixKHR:
{ {
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
std::vector<spv::Id> arguments; std::vector<spv::Id> arguments;
translateArguments(*node, arguments, lvalueCoherentFlags); translateArguments(*node, arguments, lvalueCoherentFlags);
spv::Id constructed; spv::Id constructed;
@ -3361,7 +3386,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
right->traverse(this); right->traverse(this);
spv::Id rightId = accessChainLoad(right->getType()); spv::Id rightId = accessChainLoad(right->getType());
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
OpDecorations decorations = { precision, OpDecorations decorations = { precision,
TranslateNoContractionDecoration(node->getType().getQualifier()), TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) }; TranslateNonUniformDecoration(node->getType().getQualifier()) };
@ -3596,7 +3621,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
lvalueCoherentFlags = builder.getAccessChain().coherentFlags; lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()); lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
} else { } else {
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
glslang::TOperator glslangOp = node->getOp(); glslang::TOperator glslangOp = node->getOp();
if (arg == 1 && if (arg == 1 &&
(glslangOp == glslang::EOpRayQueryGetIntersectionType || (glslangOp == glslang::EOpRayQueryGetIntersectionType ||
@ -3648,7 +3673,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
} }
} }
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
if (node->getOp() == glslang::EOpCooperativeMatrixLoad || if (node->getOp() == glslang::EOpCooperativeMatrixLoad ||
node->getOp() == glslang::EOpCooperativeMatrixLoadNV) { node->getOp() == glslang::EOpCooperativeMatrixLoadNV) {
std::vector<spv::IdImmediate> idImmOps; std::vector<spv::IdImmediate> idImmOps;
@ -3888,7 +3913,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
node->getFalseBlock()->traverse(this); node->getFalseBlock()->traverse(this);
spv::Id falseValue = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()); spv::Id falseValue = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType());
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
// done if void // done if void
if (node->getBasicType() == glslang::EbtVoid) if (node->getBasicType() == glslang::EbtVoid)
@ -4096,7 +4121,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
// instructions in it, since the body/test may have arbitrary instructions, // instructions in it, since the body/test may have arbitrary instructions,
// including merges of its own. // including merges of its own.
builder.setBuildPoint(&blocks.head); builder.setBuildPoint(&blocks.head);
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands); builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
if (node->testFirst() && node->getTest()) { if (node->testFirst() && node->getTest()) {
spv::Block& test = builder.makeNewBlock(); spv::Block& test = builder.makeNewBlock();
@ -4119,7 +4144,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
node->getTerminal()->traverse(this); node->getTerminal()->traverse(this);
builder.createBranch(&blocks.head); builder.createBranch(&blocks.head);
} else { } else {
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
builder.createBranch(&blocks.body); builder.createBranch(&blocks.body);
breakForLoop.push(true); breakForLoop.push(true);
@ -4154,7 +4179,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
if (node->getExpression()) if (node->getExpression())
node->getExpression()->traverse(this); node->getExpression()->traverse(this);
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
switch (node->getFlowOp()) { switch (node->getFlowOp()) {
case glslang::EOpKill: case glslang::EOpKill:
@ -5738,7 +5763,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
if (! node->isImage() && ! node->isTexture()) if (! node->isImage() && ! node->isTexture())
return spv::NoResult; return spv::NoResult;
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
// Process a GLSL texturing op (will be SPV image) // Process a GLSL texturing op (will be SPV image)
@ -7169,7 +7194,9 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
case glslang::EOpSubgroupExclusiveXor: case glslang::EOpSubgroupExclusiveXor:
case glslang::EOpSubgroupQuadSwapHorizontal: case glslang::EOpSubgroupQuadSwapHorizontal:
case glslang::EOpSubgroupQuadSwapVertical: case glslang::EOpSubgroupQuadSwapVertical:
case glslang::EOpSubgroupQuadSwapDiagonal: { case glslang::EOpSubgroupQuadSwapDiagonal:
case glslang::EOpSubgroupQuadAll:
case glslang::EOpSubgroupQuadAny: {
std::vector<spv::Id> operands; std::vector<spv::Id> operands;
operands.push_back(operand); operands.push_back(operand);
return createSubgroupOperation(op, typeId, operands, typeProxy); return createSubgroupOperation(op, typeId, operands, typeProxy);
@ -8274,6 +8301,11 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
case glslang::EOpSubgroupElect: case glslang::EOpSubgroupElect:
builder.addCapability(spv::CapabilityGroupNonUniform); builder.addCapability(spv::CapabilityGroupNonUniform);
break; break;
case glslang::EOpSubgroupQuadAll:
case glslang::EOpSubgroupQuadAny:
builder.addExtension(spv::E_SPV_KHR_quad_control);
builder.addCapability(spv::CapabilityQuadControlKHR);
// pass through
case glslang::EOpSubgroupAll: case glslang::EOpSubgroupAll:
case glslang::EOpSubgroupAny: case glslang::EOpSubgroupAny:
case glslang::EOpSubgroupAllEqual: case glslang::EOpSubgroupAllEqual:
@ -8293,6 +8325,11 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
builder.addCapability(spv::CapabilityGroupNonUniform); builder.addCapability(spv::CapabilityGroupNonUniform);
builder.addCapability(spv::CapabilityGroupNonUniformBallot); builder.addCapability(spv::CapabilityGroupNonUniformBallot);
break; break;
case glslang::EOpSubgroupRotate:
case glslang::EOpSubgroupClusteredRotate:
builder.addExtension(spv::E_SPV_KHR_subgroup_rotate);
builder.addCapability(spv::CapabilityGroupNonUniformRotateKHR);
break;
case glslang::EOpSubgroupShuffle: case glslang::EOpSubgroupShuffle:
case glslang::EOpSubgroupShuffleXor: case glslang::EOpSubgroupShuffleXor:
builder.addCapability(spv::CapabilityGroupNonUniform); builder.addCapability(spv::CapabilityGroupNonUniform);
@ -8381,7 +8418,9 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
// Figure out which opcode to use. // Figure out which opcode to use.
switch (op) { switch (op) {
case glslang::EOpSubgroupElect: opCode = spv::OpGroupNonUniformElect; break; case glslang::EOpSubgroupElect: opCode = spv::OpGroupNonUniformElect; break;
case glslang::EOpSubgroupQuadAll: opCode = spv::OpGroupNonUniformQuadAllKHR; break;
case glslang::EOpSubgroupAll: opCode = spv::OpGroupNonUniformAll; break; case glslang::EOpSubgroupAll: opCode = spv::OpGroupNonUniformAll; break;
case glslang::EOpSubgroupQuadAny: opCode = spv::OpGroupNonUniformQuadAnyKHR; break;
case glslang::EOpSubgroupAny: opCode = spv::OpGroupNonUniformAny; break; case glslang::EOpSubgroupAny: opCode = spv::OpGroupNonUniformAny; break;
case glslang::EOpSubgroupAllEqual: opCode = spv::OpGroupNonUniformAllEqual; break; case glslang::EOpSubgroupAllEqual: opCode = spv::OpGroupNonUniformAllEqual; break;
case glslang::EOpSubgroupBroadcast: opCode = spv::OpGroupNonUniformBroadcast; break; case glslang::EOpSubgroupBroadcast: opCode = spv::OpGroupNonUniformBroadcast; break;
@ -8398,6 +8437,8 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
case glslang::EOpSubgroupShuffleXor: opCode = spv::OpGroupNonUniformShuffleXor; break; case glslang::EOpSubgroupShuffleXor: opCode = spv::OpGroupNonUniformShuffleXor; break;
case glslang::EOpSubgroupShuffleUp: opCode = spv::OpGroupNonUniformShuffleUp; break; case glslang::EOpSubgroupShuffleUp: opCode = spv::OpGroupNonUniformShuffleUp; break;
case glslang::EOpSubgroupShuffleDown: opCode = spv::OpGroupNonUniformShuffleDown; break; case glslang::EOpSubgroupShuffleDown: opCode = spv::OpGroupNonUniformShuffleDown; break;
case glslang::EOpSubgroupRotate:
case glslang::EOpSubgroupClusteredRotate: opCode = spv::OpGroupNonUniformRotateKHR; break;
case glslang::EOpSubgroupAdd: case glslang::EOpSubgroupAdd:
case glslang::EOpSubgroupInclusiveAdd: case glslang::EOpSubgroupInclusiveAdd:
case glslang::EOpSubgroupExclusiveAdd: case glslang::EOpSubgroupExclusiveAdd:
@ -8578,7 +8619,10 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
// Every operation begins with the Execution Scope operand. // Every operation begins with the Execution Scope operand.
spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
spvGroupOperands.push_back(executionScope); // All other ops need the execution scope. Quad Control Ops don't need scope, it's always Quad.
if (opCode != spv::OpGroupNonUniformQuadAllKHR && opCode != spv::OpGroupNonUniformQuadAnyKHR) {
spvGroupOperands.push_back(executionScope);
}
// Next, for all operations that use a Group Operation, push that as an operand. // Next, for all operations that use a Group Operation, push that as an operand.
if (groupOperation != spv::GroupOperationMax) { if (groupOperation != spv::GroupOperationMax) {
@ -8821,6 +8865,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
case glslang::EOpSubgroupShuffleXor: case glslang::EOpSubgroupShuffleXor:
case glslang::EOpSubgroupShuffleUp: case glslang::EOpSubgroupShuffleUp:
case glslang::EOpSubgroupShuffleDown: case glslang::EOpSubgroupShuffleDown:
case glslang::EOpSubgroupRotate:
case glslang::EOpSubgroupClusteredRotate:
case glslang::EOpSubgroupClusteredAdd: case glslang::EOpSubgroupClusteredAdd:
case glslang::EOpSubgroupClusteredMul: case glslang::EOpSubgroupClusteredMul:
case glslang::EOpSubgroupClusteredMin: case glslang::EOpSubgroupClusteredMin:

View File

@ -58,13 +58,6 @@ Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogg
spvVersion(spvVersion), spvVersion(spvVersion),
sourceLang(SourceLanguageUnknown), sourceLang(SourceLanguageUnknown),
sourceVersion(0), sourceVersion(0),
sourceFileStringId(NoResult),
currentLine(0),
currentFile(nullptr),
currentFileId(NoResult),
lastDebugScopeId(NoResult),
emitOpLines(false),
emitNonSemanticShaderDebugInfo(false),
addressModel(AddressingModelLogical), addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450), memoryModel(MemoryModelGLSL450),
builderNumber(magicNumber), builderNumber(magicNumber),
@ -91,78 +84,6 @@ Id Builder::import(const char* name)
return import->getResultId(); return import->getResultId();
} }
// Emit instruction for non-filename-based #line directives (ie. no filename
// seen yet): emit an OpLine if we've been asked to emit OpLines and the line
// number has changed since the last time, and is a valid line number.
void Builder::setLine(int lineNum)
{
if (lineNum != 0 && lineNum != currentLine) {
currentLine = lineNum;
if (emitOpLines) {
if (emitNonSemanticShaderDebugInfo)
addDebugScopeAndLine(currentFileId, currentLine, 0);
else
addLine(sourceFileStringId, currentLine, 0);
}
}
}
// If no filename, do non-filename-based #line emit. Else do filename-based emit.
// Emit OpLine if we've been asked to emit OpLines and the line number or filename
// has changed since the last time, and line number is valid.
void Builder::setLine(int lineNum, const char* filename)
{
if (filename == nullptr) {
setLine(lineNum);
return;
}
if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr ||
strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) {
currentLine = lineNum;
currentFile = filename;
if (emitOpLines) {
spv::Id strId = getStringId(filename);
if (emitNonSemanticShaderDebugInfo)
addDebugScopeAndLine(strId, currentLine, 0);
else
addLine(strId, currentLine, 0);
}
}
}
void Builder::addLine(Id fileName, int lineNum, int column)
{
Instruction* line = new Instruction(OpLine);
line->addIdOperand(fileName);
line->addImmediateOperand(lineNum);
line->addImmediateOperand(column);
buildPoint->addInstruction(std::unique_ptr<Instruction>(line));
}
void Builder::addDebugScopeAndLine(Id fileName, int lineNum, int column)
{
assert(!currentDebugScopeId.empty());
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). // For creating new groupedTypes (will return old type if the requested one was already made).
Id Builder::makeVoidType() Id Builder::makeVoidType()
{ {
@ -1011,7 +932,7 @@ Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTy
type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember); type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember);
type->addIdOperand(getStringId(debugTypeLoc.name)); // name id type->addIdOperand(getStringId(debugTypeLoc.name)); // name id
type->addIdOperand(debugId[memberType]); // type id type->addIdOperand(debugId[memberType]); // type id
type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives type->addIdOperand(makeDebugSource(currentFileId)); // source id
type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero
type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id
type->addIdOperand(makeUintConstant(0)); // TODO: offset id type->addIdOperand(makeUintConstant(0)); // TODO: offset id
@ -1050,7 +971,7 @@ Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char cons
type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite); type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite);
type->addIdOperand(getStringId(name)); // name id type->addIdOperand(getStringId(name)); // name id
type->addIdOperand(makeUintConstant(tag)); // tag id type->addIdOperand(makeUintConstant(tag)); // tag id
type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives type->addIdOperand(makeDebugSource(currentFileId)); // source id
type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
type->addIdOperand(makeUintConstant(0)); // TODO: column id type->addIdOperand(makeUintConstant(0)); // TODO: column id
type->addIdOperand(makeDebugCompilationUnit()); // scope id type->addIdOperand(makeDebugCompilationUnit()); // scope id
@ -1113,14 +1034,19 @@ Id Builder::makeDebugSource(const Id fileName) {
sourceInst->addIdOperand(fileName); sourceInst->addIdOperand(fileName);
if (emitNonSemanticShaderDebugSource) { if (emitNonSemanticShaderDebugSource) {
spv::Id sourceId = 0; spv::Id sourceId = 0;
if (fileName == sourceFileStringId) { if (fileName == mainFileId) {
sourceId = getStringId(sourceText); sourceId = getStringId(sourceText);
} else { } else {
auto incItr = includeFiles.find(fileName); auto incItr = includeFiles.find(fileName);
assert(incItr != includeFiles.end()); if (incItr != includeFiles.end()) {
sourceId = getStringId(*incItr->second); sourceId = getStringId(*incItr->second);
}
}
// We omit the optional source text item if not available in glslang
if (sourceId != 0) {
sourceInst->addIdOperand(sourceId);
} }
sourceInst->addIdOperand(sourceId);
} }
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst)); constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
module.mapInstruction(sourceInst); module.mapInstruction(sourceInst);
@ -1137,7 +1063,7 @@ Id Builder::makeDebugCompilationUnit() {
sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit); sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit);
sourceInst->addIdOperand(makeUintConstant(1)); // TODO(greg-lunarg): Get rid of magic number 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(makeUintConstant(4)); // TODO(greg-lunarg): Get rid of magic number
sourceInst->addIdOperand(makeDebugSource(sourceFileStringId)); sourceInst->addIdOperand(makeDebugSource(mainFileId));
sourceInst->addIdOperand(makeUintConstant(sourceLang)); sourceInst->addIdOperand(makeUintConstant(sourceLang));
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst)); constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
module.mapInstruction(sourceInst); module.mapInstruction(sourceInst);
@ -1160,7 +1086,7 @@ Id Builder::createDebugGlobalVariable(Id const type, char const*const name, Id c
inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable); inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable);
inst->addIdOperand(getStringId(name)); // name id inst->addIdOperand(getStringId(name)); // name id
inst->addIdOperand(type); // type id inst->addIdOperand(type); // type id
inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id inst->addIdOperand(makeDebugSource(currentFileId)); // source id
inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
inst->addIdOperand(makeUintConstant(0)); // TODO: column id inst->addIdOperand(makeUintConstant(0)); // TODO: column id
inst->addIdOperand(makeDebugCompilationUnit()); // scope id inst->addIdOperand(makeDebugCompilationUnit()); // scope id
@ -1184,7 +1110,7 @@ Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t cons
inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable); inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable);
inst->addIdOperand(getStringId(name)); // name id inst->addIdOperand(getStringId(name)); // name id
inst->addIdOperand(type); // type id inst->addIdOperand(type); // type id
inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id inst->addIdOperand(makeDebugSource(currentFileId)); // source id
inst->addIdOperand(makeUintConstant(currentLine)); // line id inst->addIdOperand(makeUintConstant(currentLine)); // line id
inst->addIdOperand(makeUintConstant(0)); // TODO: column id inst->addIdOperand(makeUintConstant(0)); // TODO: column id
inst->addIdOperand(currentDebugScopeId.top()); // scope id inst->addIdOperand(currentDebugScopeId.top()); // scope id
@ -1224,7 +1150,7 @@ Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const pointer)
inst->addIdOperand(debugLocalVariable); // debug local variable id inst->addIdOperand(debugLocalVariable); // debug local variable id
inst->addIdOperand(pointer); // pointer to local variable id inst->addIdOperand(pointer); // pointer to local variable id
inst->addIdOperand(makeDebugExpression()); // expression id inst->addIdOperand(makeDebugExpression()); // expression id
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); addInstruction(std::unique_ptr<Instruction>(inst));
return inst->getResultId(); return inst->getResultId();
} }
@ -1237,7 +1163,7 @@ Id Builder::makeDebugValue(Id const debugLocalVariable, Id const value)
inst->addIdOperand(debugLocalVariable); // debug local variable id inst->addIdOperand(debugLocalVariable); // debug local variable id
inst->addIdOperand(value); // value of local variable id inst->addIdOperand(value); // value of local variable id
inst->addIdOperand(makeDebugExpression()); // expression id inst->addIdOperand(makeDebugExpression()); // expression id
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); addInstruction(std::unique_ptr<Instruction>(inst));
return inst->getResultId(); return inst->getResultId();
} }
@ -2103,6 +2029,49 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
decorations.push_back(std::unique_ptr<Instruction>(dec)); decorations.push_back(std::unique_ptr<Instruction>(dec));
} }
void Builder::addInstruction(std::unique_ptr<Instruction> inst) {
// Optionally insert OpDebugScope
if (emitNonSemanticShaderDebugInfo && dirtyScopeTracker) {
if (buildPoint->updateDebugScope(currentDebugScopeId.top())) {
auto scopeInst = std::make_unique<Instruction>(getUniqueId(), makeVoidType(), OpExtInst);
scopeInst->addIdOperand(nonSemanticShaderDebugInfo);
scopeInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugScope);
scopeInst->addIdOperand(currentDebugScopeId.top());
buildPoint->addInstruction(std::move(scopeInst));
}
dirtyScopeTracker = false;
}
// Insert OpLine/OpDebugLine if the debug source location has changed
if (trackDebugInfo && dirtyLineTracker) {
if (buildPoint->updateDebugSourceLocation(currentLine, 0, currentFileId)) {
if (emitSpirvDebugInfo) {
auto lineInst = std::make_unique<Instruction>(OpLine);
lineInst->addIdOperand(currentFileId);
lineInst->addImmediateOperand(currentLine);
lineInst->addImmediateOperand(0);
buildPoint->addInstruction(std::move(lineInst));
}
if (emitNonSemanticShaderDebugInfo) {
auto lineInst = std::make_unique<Instruction>(getUniqueId(), makeVoidType(), OpExtInst);
lineInst->addIdOperand(nonSemanticShaderDebugInfo);
lineInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLine);
lineInst->addIdOperand(makeDebugSource(currentFileId));
lineInst->addIdOperand(makeUintConstant(currentLine));
lineInst->addIdOperand(makeUintConstant(currentLine));
lineInst->addIdOperand(makeUintConstant(0));
lineInst->addIdOperand(makeUintConstant(0));
buildPoint->addInstruction(std::move(lineInst));
}
}
dirtyLineTracker = false;
}
buildPoint->addInstruction(std::move(inst));
}
// Comments in header // Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint) Function* Builder::makeEntryPoint(const char* entryPoint)
{ {
@ -2146,7 +2115,7 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
// reset last debug scope // reset last debug scope
if (emitNonSemanticShaderDebugInfo) { if (emitNonSemanticShaderDebugInfo) {
lastDebugScopeId = NoResult; dirtyScopeTracker = true;
} }
// CFG // CFG
@ -2186,8 +2155,6 @@ void Builder::setupDebugFunctionEntry(Function* function, const char* name, int
// DebugScope and DebugLine for parameter DebugDeclares // DebugScope and DebugLine for parameter DebugDeclares
assert(paramTypes.size() == paramNames.size()); assert(paramTypes.size() == paramNames.size());
if ((int)paramTypes.size() > 0) { if ((int)paramTypes.size() > 0) {
addDebugScopeAndLine(currentFileId, currentLine, 0);
Id firstParamId = function->getParamId(0); Id firstParamId = function->getParamId(0);
for (size_t p = 0; p < paramTypes.size(); ++p) { for (size_t p = 0; p < paramTypes.size(); ++p) {
@ -2276,29 +2243,29 @@ void Builder::makeReturn(bool implicit, Id retVal)
if (retVal) { if (retVal) {
Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue); Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
inst->addIdOperand(retVal); inst->addIdOperand(retVal);
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); addInstruction(std::unique_ptr<Instruction>(inst));
} else } else
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn))); addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn)));
if (! implicit) if (! implicit)
createAndSetNoPredecessorBlock("post-return"); createAndSetNoPredecessorBlock("post-return");
} }
// Comments in header // Comments in header
void Builder::enterScope(uint32_t line) void Builder::enterLexicalBlock(uint32_t line)
{ {
// Generate new lexical scope debug instruction // Generate new lexical scope debug instruction
Id lexId = makeDebugLexicalBlock(line); Id lexId = makeDebugLexicalBlock(line);
currentDebugScopeId.push(lexId); currentDebugScopeId.push(lexId);
lastDebugScopeId = NoResult; dirtyScopeTracker = true;
} }
// Comments in header // Comments in header
void Builder::leaveScope() void Builder::leaveLexicalBlock()
{ {
// Pop current scope from stack and clear current scope // Pop current scope from stack and clear current scope
currentDebugScopeId.pop(); currentDebugScopeId.pop();
lastDebugScopeId = NoResult; dirtyScopeTracker = true;
} }
// Comments in header // Comments in header
@ -2322,7 +2289,7 @@ void Builder::enterFunction(Function const* function)
defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition); defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition);
defInst->addIdOperand(debugId[funcId]); defInst->addIdOperand(debugId[funcId]);
defInst->addIdOperand(funcId); defInst->addIdOperand(funcId);
buildPoint->addInstruction(std::unique_ptr<Instruction>(defInst)); addInstruction(std::unique_ptr<Instruction>(defInst));
} }
if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) { if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) {
@ -2358,7 +2325,7 @@ void Builder::leaveFunction()
// Comments in header // Comments in header
void Builder::makeStatementTerminator(spv::Op opcode, const char *name) void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
{ {
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode))); addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode)));
createAndSetNoPredecessorBlock(name); createAndSetNoPredecessorBlock(name);
} }
@ -2420,7 +2387,7 @@ Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id t
Id Builder::createUndefined(Id type) Id Builder::createUndefined(Id type)
{ {
Instruction* inst = new Instruction(getUniqueId(), type, OpUndef); Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); addInstruction(std::unique_ptr<Instruction>(inst));
return inst->getResultId(); return inst->getResultId();
} }
@ -2464,7 +2431,7 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
} }
} }
buildPoint->addInstruction(std::unique_ptr<Instruction>(store)); addInstruction(std::unique_ptr<Instruction>(store));
} }
// Comments in header // Comments in header
@ -2486,7 +2453,7 @@ Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMa
} }
} }
buildPoint->addInstruction(std::unique_ptr<Instruction>(load)); addInstruction(std::unique_ptr<Instruction>(load));
setPrecision(load->getResultId(), precision); setPrecision(load->getResultId(), precision);
return load->getResultId(); return load->getResultId();
@ -2504,7 +2471,7 @@ Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vec
chain->addIdOperand(base); chain->addIdOperand(base);
for (int i = 0; i < (int)offsets.size(); ++i) for (int i = 0; i < (int)offsets.size(); ++i)
chain->addIdOperand(offsets[i]); chain->addIdOperand(offsets[i]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(chain)); addInstruction(std::unique_ptr<Instruction>(chain));
return chain->getResultId(); return chain->getResultId();
} }
@ -2515,7 +2482,7 @@ Id Builder::createArrayLength(Id base, unsigned int member)
Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength); Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength);
length->addIdOperand(base); length->addIdOperand(base);
length->addImmediateOperand(member); length->addImmediateOperand(member);
buildPoint->addInstruction(std::unique_ptr<Instruction>(length)); addInstruction(std::unique_ptr<Instruction>(length));
return length->getResultId(); return length->getResultId();
} }
@ -2532,7 +2499,7 @@ Id Builder::createCooperativeMatrixLengthKHR(Id type)
Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthKHR); Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthKHR);
length->addIdOperand(type); length->addIdOperand(type);
buildPoint->addInstruction(std::unique_ptr<Instruction>(length)); addInstruction(std::unique_ptr<Instruction>(length));
return length->getResultId(); return length->getResultId();
} }
@ -2549,7 +2516,7 @@ Id Builder::createCooperativeMatrixLengthNV(Id type)
Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV); Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV);
length->addIdOperand(type); length->addIdOperand(type);
buildPoint->addInstruction(std::unique_ptr<Instruction>(length)); addInstruction(std::unique_ptr<Instruction>(length));
return length->getResultId(); return length->getResultId();
} }
@ -2565,7 +2532,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite); extract->addIdOperand(composite);
extract->addImmediateOperand(index); extract->addImmediateOperand(index);
buildPoint->addInstruction(std::unique_ptr<Instruction>(extract)); addInstruction(std::unique_ptr<Instruction>(extract));
return extract->getResultId(); return extract->getResultId();
} }
@ -2581,7 +2548,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector<un
extract->addIdOperand(composite); extract->addIdOperand(composite);
for (int i = 0; i < (int)indexes.size(); ++i) for (int i = 0; i < (int)indexes.size(); ++i)
extract->addImmediateOperand(indexes[i]); extract->addImmediateOperand(indexes[i]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(extract)); addInstruction(std::unique_ptr<Instruction>(extract));
return extract->getResultId(); return extract->getResultId();
} }
@ -2592,7 +2559,7 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned i
insert->addIdOperand(object); insert->addIdOperand(object);
insert->addIdOperand(composite); insert->addIdOperand(composite);
insert->addImmediateOperand(index); insert->addImmediateOperand(index);
buildPoint->addInstruction(std::unique_ptr<Instruction>(insert)); addInstruction(std::unique_ptr<Instruction>(insert));
return insert->getResultId(); return insert->getResultId();
} }
@ -2604,7 +2571,7 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std:
insert->addIdOperand(composite); insert->addIdOperand(composite);
for (int i = 0; i < (int)indexes.size(); ++i) for (int i = 0; i < (int)indexes.size(); ++i)
insert->addImmediateOperand(indexes[i]); insert->addImmediateOperand(indexes[i]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(insert)); addInstruction(std::unique_ptr<Instruction>(insert));
return insert->getResultId(); return insert->getResultId();
} }
@ -2614,7 +2581,7 @@ Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic); Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
extract->addIdOperand(vector); extract->addIdOperand(vector);
extract->addIdOperand(componentIndex); extract->addIdOperand(componentIndex);
buildPoint->addInstruction(std::unique_ptr<Instruction>(extract)); addInstruction(std::unique_ptr<Instruction>(extract));
return extract->getResultId(); return extract->getResultId();
} }
@ -2625,7 +2592,7 @@ Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id com
insert->addIdOperand(vector); insert->addIdOperand(vector);
insert->addIdOperand(component); insert->addIdOperand(component);
insert->addIdOperand(componentIndex); insert->addIdOperand(componentIndex);
buildPoint->addInstruction(std::unique_ptr<Instruction>(insert)); addInstruction(std::unique_ptr<Instruction>(insert));
return insert->getResultId(); return insert->getResultId();
} }
@ -2634,7 +2601,7 @@ Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id com
void Builder::createNoResultOp(Op opCode) void Builder::createNoResultOp(Op opCode)
{ {
Instruction* op = new Instruction(opCode); Instruction* op = new Instruction(opCode);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
} }
// An opcode that has one id operand, no result id, and no type // An opcode that has one id operand, no result id, and no type
@ -2642,7 +2609,7 @@ void Builder::createNoResultOp(Op opCode, Id operand)
{ {
Instruction* op = new Instruction(opCode); Instruction* op = new Instruction(opCode);
op->addIdOperand(operand); op->addIdOperand(operand);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
} }
// An opcode that has one or more operands, no result id, and no type // An opcode that has one or more operands, no result id, and no type
@ -2652,7 +2619,7 @@ void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
for (auto it = operands.cbegin(); it != operands.cend(); ++it) { for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
op->addIdOperand(*it); op->addIdOperand(*it);
} }
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
} }
// An opcode that has multiple operands, no result id, and no type // An opcode that has multiple operands, no result id, and no type
@ -2665,7 +2632,7 @@ void Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operan
else else
op->addImmediateOperand(it->word); op->addImmediateOperand(it->word);
} }
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
} }
void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics) void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
@ -2674,7 +2641,7 @@ void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemantic
op->addIdOperand(makeUintConstant(execution)); op->addIdOperand(makeUintConstant(execution));
op->addIdOperand(makeUintConstant(memory)); op->addIdOperand(makeUintConstant(memory));
op->addIdOperand(makeUintConstant(semantics)); op->addIdOperand(makeUintConstant(semantics));
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
} }
void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics) void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
@ -2682,7 +2649,7 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant
Instruction* op = new Instruction(OpMemoryBarrier); Instruction* op = new Instruction(OpMemoryBarrier);
op->addIdOperand(makeUintConstant(executionScope)); op->addIdOperand(makeUintConstant(executionScope));
op->addIdOperand(makeUintConstant(memorySemantics)); op->addIdOperand(makeUintConstant(memorySemantics));
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
} }
// An opcode that has one operands, a result id, and a type // An opcode that has one operands, a result id, and a type
@ -2695,7 +2662,7 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
} }
Instruction* op = new Instruction(getUniqueId(), typeId, opCode); Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->addIdOperand(operand); op->addIdOperand(operand);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId(); return op->getResultId();
} }
@ -2712,7 +2679,7 @@ Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
Instruction* op = new Instruction(getUniqueId(), typeId, opCode); Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->addIdOperand(left); op->addIdOperand(left);
op->addIdOperand(right); op->addIdOperand(right);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId(); return op->getResultId();
} }
@ -2733,7 +2700,7 @@ Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
op->addIdOperand(op1); op->addIdOperand(op1);
op->addIdOperand(op2); op->addIdOperand(op2);
op->addIdOperand(op3); op->addIdOperand(op3);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId(); return op->getResultId();
} }
@ -2743,7 +2710,7 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
Instruction* op = new Instruction(getUniqueId(), typeId, opCode); Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
for (auto it = operands.cbegin(); it != operands.cend(); ++it) for (auto it = operands.cbegin(); it != operands.cend(); ++it)
op->addIdOperand(*it); op->addIdOperand(*it);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId(); return op->getResultId();
} }
@ -2757,7 +2724,7 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
else else
op->addImmediateOperand(it->word); op->addImmediateOperand(it->word);
} }
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId(); return op->getResultId();
} }
@ -2791,7 +2758,7 @@ Id Builder::createFunctionCall(spv::Function* function, const std::vector<spv::I
op->addIdOperand(function->getId()); op->addIdOperand(function->getId());
for (int a = 0; a < (int)args.size(); ++a) for (int a = 0; a < (int)args.size(); ++a)
op->addIdOperand(args[a]); op->addIdOperand(args[a]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId(); return op->getResultId();
} }
@ -2813,7 +2780,7 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, cons
swizzle->addIdOperand(source); swizzle->addIdOperand(source);
for (int i = 0; i < (int)channels.size(); ++i) for (int i = 0; i < (int)channels.size(); ++i)
swizzle->addImmediateOperand(channels[i]); swizzle->addImmediateOperand(channels[i]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle)); addInstruction(std::unique_ptr<Instruction>(swizzle));
return setPrecision(swizzle->getResultId(), precision); return setPrecision(swizzle->getResultId(), precision);
} }
@ -2846,7 +2813,7 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
// finish the instruction with these components selectors // finish the instruction with these components selectors
for (int i = 0; i < numTargetComponents; ++i) for (int i = 0; i < numTargetComponents; ++i)
swizzle->addImmediateOperand(components[i]); swizzle->addImmediateOperand(components[i]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle)); addInstruction(std::unique_ptr<Instruction>(swizzle));
return swizzle->getResultId(); return swizzle->getResultId();
} }
@ -2891,7 +2858,7 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
for (int c = 0; c < numComponents; ++c) for (int c = 0; c < numComponents; ++c)
smear->addIdOperand(scalar); smear->addIdOperand(scalar);
buildPoint->addInstruction(std::unique_ptr<Instruction>(smear)); addInstruction(std::unique_ptr<Instruction>(smear));
} }
return setPrecision(smear->getResultId(), precision); return setPrecision(smear->getResultId(), precision);
@ -2906,7 +2873,7 @@ Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const
for (int arg = 0; arg < (int)args.size(); ++arg) for (int arg = 0; arg < (int)args.size(); ++arg)
inst->addIdOperand(args[arg]); inst->addIdOperand(args[arg]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); addInstruction(std::unique_ptr<Instruction>(inst));
return inst->getResultId(); return inst->getResultId();
} }
@ -3102,7 +3069,7 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
for (size_t op = optArgNum + 1; op < texArgs.size(); ++op) for (size_t op = optArgNum + 1; op < texArgs.size(); ++op)
textureInst->addIdOperand(texArgs[op]); textureInst->addIdOperand(texArgs[op]);
setPrecision(textureInst->getResultId(), precision); setPrecision(textureInst->getResultId(), precision);
buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst)); addInstruction(std::unique_ptr<Instruction>(textureInst));
Id resultId = textureInst->getResultId(); Id resultId = textureInst->getResultId();
@ -3182,7 +3149,7 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
query->addIdOperand(parameters.coords); query->addIdOperand(parameters.coords);
if (parameters.lod) if (parameters.lod)
query->addIdOperand(parameters.lod); query->addIdOperand(parameters.lod);
buildPoint->addInstruction(std::unique_ptr<Instruction>(query)); addInstruction(std::unique_ptr<Instruction>(query));
addCapability(CapabilityImageQuery); addCapability(CapabilityImageQuery);
return query->getResultId(); return query->getResultId();
@ -3281,7 +3248,7 @@ Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constitue
Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct); Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
for (int c = 0; c < (int)constituents.size(); ++c) for (int c = 0; c < (int)constituents.size(); ++c)
op->addIdOperand(constituents[c]); op->addIdOperand(constituents[c]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId(); return op->getResultId();
} }
@ -3577,7 +3544,7 @@ void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, con
switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId()); switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint); segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint);
} }
buildPoint->addInstruction(std::unique_ptr<Instruction>(switchInst)); addInstruction(std::unique_ptr<Instruction>(switchInst));
// push the merge block // push the merge block
switchMerges.push(mergeBlock); switchMerges.push(mergeBlock);
@ -4096,7 +4063,7 @@ void Builder::createBranch(Block* block)
{ {
Instruction* branch = new Instruction(OpBranch); Instruction* branch = new Instruction(OpBranch);
branch->addIdOperand(block->getId()); branch->addIdOperand(block->getId());
buildPoint->addInstruction(std::unique_ptr<Instruction>(branch)); addInstruction(std::unique_ptr<Instruction>(branch));
block->addPredecessor(buildPoint); block->addPredecessor(buildPoint);
} }
@ -4105,7 +4072,7 @@ void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
Instruction* merge = new Instruction(OpSelectionMerge); Instruction* merge = new Instruction(OpSelectionMerge);
merge->addIdOperand(mergeBlock->getId()); merge->addIdOperand(mergeBlock->getId());
merge->addImmediateOperand(control); merge->addImmediateOperand(control);
buildPoint->addInstruction(std::unique_ptr<Instruction>(merge)); addInstruction(std::unique_ptr<Instruction>(merge));
} }
void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
@ -4117,7 +4084,7 @@ void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned
merge->addImmediateOperand(control); merge->addImmediateOperand(control);
for (int op = 0; op < (int)operands.size(); ++op) for (int op = 0; op < (int)operands.size(); ++op)
merge->addImmediateOperand(operands[op]); merge->addImmediateOperand(operands[op]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(merge)); addInstruction(std::unique_ptr<Instruction>(merge));
} }
void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock) void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
@ -4126,7 +4093,7 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
branch->addIdOperand(condition); branch->addIdOperand(condition);
branch->addIdOperand(thenBlock->getId()); branch->addIdOperand(thenBlock->getId());
branch->addIdOperand(elseBlock->getId()); branch->addIdOperand(elseBlock->getId());
buildPoint->addInstruction(std::unique_ptr<Instruction>(branch)); addInstruction(std::unique_ptr<Instruction>(branch));
thenBlock->addPredecessor(buildPoint); thenBlock->addPredecessor(buildPoint);
elseBlock->addPredecessor(buildPoint); elseBlock->addPredecessor(buildPoint);
} }
@ -4178,7 +4145,7 @@ void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& te
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
{ {
if (emitNonSemanticShaderDebugInfo) return; if (emitNonSemanticShaderDebugInfo) return;
dumpSourceInstructions(sourceFileStringId, sourceText, out); dumpSourceInstructions(mainFileId, sourceText, out);
for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr) for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr)
dumpSourceInstructions(iItr->first, *iItr->second, out); dumpSourceInstructions(iItr->first, *iItr->second, out);
} }

View File

@ -103,31 +103,53 @@ public:
stringIds[file_c_str] = strId; stringIds[file_c_str] = strId;
return strId; return strId;
} }
spv::Id getSourceFile() const
spv::Id getMainFileId() const { return mainFileId; }
// Initialize the main source file name
void setDebugSourceFile(const std::string& file)
{ {
return sourceFileStringId; if (trackDebugInfo) {
dirtyLineTracker = true;
mainFileId = getStringId(file);
currentFileId = mainFileId;
}
} }
void setSourceFile(const std::string& file)
// Set the debug source location tracker in the builder.
// The upcoming instructions in basic blocks will be associated to this location.
void setDebugSourceLocation(int line, const char* filename)
{ {
sourceFileStringId = getStringId(file); if (trackDebugInfo) {
currentFileId = sourceFileStringId; dirtyLineTracker = true;
if (line != 0) {
// TODO: This is special handling of some AST nodes having (untracked) line 0.
// But they should have a valid line number.
currentLine = line;
if (filename) {
currentFileId = getStringId(filename);
}
}
}
} }
void setSourceText(const std::string& text) { sourceText = text; } void setSourceText(const std::string& text) { sourceText = text; }
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
void setEmitOpLines() { emitOpLines = true; } void setEmitSpirvDebugInfo()
void setEmitNonSemanticShaderDebugInfo(bool const emit)
{ {
emitNonSemanticShaderDebugInfo = emit; trackDebugInfo = true;
emitSpirvDebugInfo = true;
if(emit)
{
importNonSemanticShaderDebugInfoInstructions();
}
} }
void setEmitNonSemanticShaderDebugSource(bool const src) void setEmitNonSemanticShaderDebugInfo(bool emitSourceText)
{ {
emitNonSemanticShaderDebugSource = src; trackDebugInfo = true;
emitNonSemanticShaderDebugInfo = true;
importNonSemanticShaderDebugInfoInstructions();
if (emitSourceText) {
emitNonSemanticShaderDebugSource = emitSourceText;
}
} }
void addExtension(const char* ext) { extensions.insert(ext); } void addExtension(const char* ext) { extensions.insert(ext); }
void removeExtension(const char* ext) void removeExtension(const char* ext)
@ -169,20 +191,6 @@ public:
return id; return id;
} }
// Generate OpLine for non-filename-based #line directives (ie no filename
// seen yet): Log the current line, and if different than the last one,
// issue a new OpLine using the new line and current source file name.
void setLine(int line);
// If filename null, generate OpLine for non-filename-based line directives,
// else do filename-based: Log the current line and file, and if different
// than the last one, issue a new OpLine using the new line and file
// name.
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). // For creating new types (will return old type if the requested one was already made).
Id makeVoidType(); Id makeVoidType();
Id makeBoolType(); Id makeBoolType();
@ -409,11 +417,16 @@ public:
// Also reset current last DebugScope and current source line to unknown // Also reset current last DebugScope and current source line to unknown
void setBuildPoint(Block* bp) { void setBuildPoint(Block* bp) {
buildPoint = bp; buildPoint = bp;
lastDebugScopeId = NoResult; // TODO: Technically, change of build point should set line tracker dirty. But we'll have bad line info for
currentLine = 0; // branch instructions. Commenting this for now because at least this matches the old behavior.
dirtyScopeTracker = true;
} }
Block* getBuildPoint() const { return buildPoint; } Block* getBuildPoint() const { return buildPoint; }
// Append an instruction to the end of the current build point.
// Optionally, additional debug info instructions may also be prepended.
void addInstruction(std::unique_ptr<Instruction> inst);
// Make the entry-point function. The returned pointer is only valid // Make the entry-point function. The returned pointer is only valid
// for the lifetime of this builder. // for the lifetime of this builder.
Function* makeEntryPoint(const char*); Function* makeEntryPoint(const char*);
@ -430,10 +443,10 @@ public:
void makeReturn(bool implicit, Id retVal = 0); void makeReturn(bool implicit, Id retVal = 0);
// Initialize state and generate instructions for new lexical scope // Initialize state and generate instructions for new lexical scope
void enterScope(uint32_t line); void enterLexicalBlock(uint32_t line);
// Set state and generate instructions to exit current lexical scope // Set state and generate instructions to exit current lexical scope
void leaveScope(); void leaveLexicalBlock();
// Prepare builder for generation of instructions for a function. // Prepare builder for generation of instructions for a function.
void enterFunction(Function const* function); void enterFunction(Function const* function);
@ -882,21 +895,37 @@ public:
unsigned int spvVersion; // the version of SPIR-V to emit in the header unsigned int spvVersion; // the version of SPIR-V to emit in the header
SourceLanguage sourceLang; SourceLanguage sourceLang;
int sourceVersion; int sourceVersion;
spv::Id sourceFileStringId;
spv::Id nonSemanticShaderCompilationUnitId {0}; spv::Id nonSemanticShaderCompilationUnitId {0};
spv::Id nonSemanticShaderDebugInfo {0}; spv::Id nonSemanticShaderDebugInfo {0};
spv::Id debugInfoNone {0}; spv::Id debugInfoNone {0};
spv::Id debugExpression {0}; // Debug expression with zero operations. spv::Id debugExpression {0}; // Debug expression with zero operations.
std::string sourceText; std::string sourceText;
int currentLine;
const char* currentFile; // True if an new OpLine/OpDebugLine may need to be inserted. Either:
spv::Id currentFileId; // 1. The current debug location changed
// 2. The current build point changed
bool dirtyLineTracker;
int currentLine = 0;
// OpString id of the current file name. Always 0 if debug info is off.
spv::Id currentFileId = 0;
// OpString id of the main file name. Always 0 if debug info is off.
spv::Id mainFileId = 0;
// True if an new OpDebugScope may need to be inserted. Either:
// 1. A new lexical block is pushed
// 2. The current build point changed
bool dirtyScopeTracker;
std::stack<spv::Id> currentDebugScopeId; std::stack<spv::Id> currentDebugScopeId;
spv::Id lastDebugScopeId;
bool emitOpLines; // This flag toggles tracking of debug info while building the SPIR-V.
bool emitNonSemanticShaderDebugInfo; bool trackDebugInfo = false;
bool restoreNonSemanticShaderDebugInfo; // This flag toggles emission of SPIR-V debug instructions, like OpLine and OpSource.
bool emitNonSemanticShaderDebugSource; bool emitSpirvDebugInfo = false;
// This flag toggles emission of Non-Semantic Debug extension debug instructions.
bool emitNonSemanticShaderDebugInfo = false;
bool restoreNonSemanticShaderDebugInfo = false;
bool emitNonSemanticShaderDebugSource = false;
std::set<std::string> extensions; std::set<std::string> extensions;
std::vector<const char*> sourceExtensions; std::vector<const char*> sourceExtensions;
std::vector<const char*> moduleProcesses; std::vector<const char*> moduleProcesses;

View File

@ -1,5 +1,6 @@
// //
// Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2022-2024 Arm Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
@ -198,6 +199,7 @@ const char* ExecutionModeString(int mode)
case ExecutionModeStencilRefGreaterBackAMD: return "StencilRefGreaterBackAMD"; case ExecutionModeStencilRefGreaterBackAMD: return "StencilRefGreaterBackAMD";
case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT"; case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT";
case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow"; case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow";
case ExecutionModeMaximallyReconvergesKHR: return "MaximallyReconverges";
case ExecutionModeOutputLinesNV: return "OutputLinesNV"; case ExecutionModeOutputLinesNV: return "OutputLinesNV";
case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV"; case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
@ -217,6 +219,9 @@ const char* ExecutionModeString(int mode)
case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL"; case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL";
case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL"; case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL";
case ExecutionModeRequireFullQuadsKHR: return "RequireFullQuadsKHR";
case ExecutionModeQuadDerivativesKHR: return "QuadDerivativesKHR";
case ExecutionModeNonCoherentColorAttachmentReadEXT: return "NonCoherentColorAttachmentReadEXT"; case ExecutionModeNonCoherentColorAttachmentReadEXT: return "NonCoherentColorAttachmentReadEXT";
case ExecutionModeNonCoherentDepthAttachmentReadEXT: return "NonCoherentDepthAttachmentReadEXT"; case ExecutionModeNonCoherentDepthAttachmentReadEXT: return "NonCoherentDepthAttachmentReadEXT";
case ExecutionModeNonCoherentStencilAttachmentReadEXT: return "NonCoherentStencilAttachmentReadEXT"; case ExecutionModeNonCoherentStencilAttachmentReadEXT: return "NonCoherentStencilAttachmentReadEXT";
@ -938,6 +943,7 @@ const char* CapabilityString(int info)
case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR"; case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR";
case CapabilityDrawParameters: return "DrawParameters"; case CapabilityDrawParameters: return "DrawParameters";
case CapabilitySubgroupVoteKHR: return "SubgroupVoteKHR"; case CapabilitySubgroupVoteKHR: return "SubgroupVoteKHR";
case CapabilityGroupNonUniformRotateKHR: return "CapabilityGroupNonUniformRotateKHR";
case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16"; case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16";
case CapabilityStorageUniform16: return "StorageUniform16"; case CapabilityStorageUniform16: return "StorageUniform16";
@ -1032,6 +1038,7 @@ const char* CapabilityString(int info)
case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT"; case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
case CapabilityShaderClockKHR: return "ShaderClockKHR"; case CapabilityShaderClockKHR: return "ShaderClockKHR";
case CapabilityQuadControlKHR: return "QuadControlKHR";
case CapabilityInt64ImageEXT: return "Int64ImageEXT"; case CapabilityInt64ImageEXT: return "Int64ImageEXT";
case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL"; case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL";
@ -1432,10 +1439,16 @@ const char* OpcodeString(int op)
case 4430: return "OpSubgroupAllEqualKHR"; case 4430: return "OpSubgroupAllEqualKHR";
case 4432: return "OpSubgroupReadInvocationKHR"; case 4432: return "OpSubgroupReadInvocationKHR";
case OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR";
case OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR";
case OpAtomicFAddEXT: return "OpAtomicFAddEXT"; case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
case OpAtomicFMinEXT: return "OpAtomicFMinEXT"; case OpAtomicFMinEXT: return "OpAtomicFMinEXT";
case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT"; case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT";
case OpAssumeTrueKHR: return "OpAssumeTrueKHR";
case OpExpectKHR: return "OpExpectKHR";
case 5000: return "OpGroupIAddNonUniformAMD"; case 5000: return "OpGroupIAddNonUniformAMD";
case 5001: return "OpGroupFAddNonUniformAMD"; case 5001: return "OpGroupFAddNonUniformAMD";
case 5002: return "OpGroupFMinNonUniformAMD"; case 5002: return "OpGroupFMinNonUniformAMD";
@ -1472,6 +1485,8 @@ const char* OpcodeString(int op)
case OpEmitMeshTasksEXT: return "OpEmitMeshTasksEXT"; case OpEmitMeshTasksEXT: return "OpEmitMeshTasksEXT";
case OpSetMeshOutputsEXT: return "OpSetMeshOutputsEXT"; case OpSetMeshOutputsEXT: return "OpSetMeshOutputsEXT";
case OpGroupNonUniformRotateKHR: return "OpGroupNonUniformRotateKHR";
case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR"; case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR";
case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR"; case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR";
case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR"; case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR";
@ -1678,7 +1693,7 @@ void Parameterize()
InstructionDesc[OpCooperativeMatrixStoreKHR].setResultAndType(false, false); InstructionDesc[OpCooperativeMatrixStoreKHR].setResultAndType(false, false);
InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false); InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false);
InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false); InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false);
InstructionDesc[OpAssumeTrueKHR].setResultAndType(false, false);
// Specific additional context-dependent operands // Specific additional context-dependent operands
ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <<Invocation,invocations>>'"); ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <<Invocation,invocations>>'");
@ -2457,6 +2472,11 @@ void Parameterize()
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'"); InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'");
InstructionDesc[OpAssumeTrueKHR].operands.push(OperandId, "'Condition'");
InstructionDesc[OpExpectKHR].operands.push(OperandId, "'Value'");
InstructionDesc[OpExpectKHR].operands.push(OperandId, "'ExpectedValue'");
InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'"); InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'"); InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
@ -2885,6 +2905,11 @@ void Parameterize()
InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'"); InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'"); InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'");
InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'X'");
InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'Delta'");
InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'ClusterSize'", true);
InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'"); InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'");
InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'"); InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'");
@ -2931,6 +2956,8 @@ void Parameterize()
InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
InstructionDesc[OpGroupNonUniformQuadAllKHR].operands.push(OperandId, "'Predicate'");
InstructionDesc[OpGroupNonUniformQuadAnyKHR].operands.push(OperandId, "'Predicate'");
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'");

View File

@ -174,6 +174,8 @@ enum ExecutionMode {
ExecutionModeStencilRefUnchangedBackAMD = 5082, ExecutionModeStencilRefUnchangedBackAMD = 5082,
ExecutionModeStencilRefGreaterBackAMD = 5083, ExecutionModeStencilRefGreaterBackAMD = 5083,
ExecutionModeStencilRefLessBackAMD = 5084, ExecutionModeStencilRefLessBackAMD = 5084,
ExecutionModeQuadDerivativesKHR = 5088,
ExecutionModeRequireFullQuadsKHR = 5089,
ExecutionModeOutputLinesEXT = 5269, ExecutionModeOutputLinesEXT = 5269,
ExecutionModeOutputLinesNV = 5269, ExecutionModeOutputLinesNV = 5269,
ExecutionModeOutputPrimitivesEXT = 5270, ExecutionModeOutputPrimitivesEXT = 5270,
@ -198,6 +200,7 @@ enum ExecutionMode {
ExecutionModeNoGlobalOffsetINTEL = 5895, ExecutionModeNoGlobalOffsetINTEL = 5895,
ExecutionModeNumSIMDWorkitemsINTEL = 5896, ExecutionModeNumSIMDWorkitemsINTEL = 5896,
ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903, ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
ExecutionModeMaximallyReconvergesKHR = 6023,
ExecutionModeStreamingInterfaceINTEL = 6154, ExecutionModeStreamingInterfaceINTEL = 6154,
ExecutionModeNamedBarrierCountINTEL = 6417, ExecutionModeNamedBarrierCountINTEL = 6417,
ExecutionModeMax = 0x7fffffff, ExecutionModeMax = 0x7fffffff,
@ -1039,6 +1042,7 @@ enum Capability {
CapabilityImageReadWriteLodAMD = 5015, CapabilityImageReadWriteLodAMD = 5015,
CapabilityInt64ImageEXT = 5016, CapabilityInt64ImageEXT = 5016,
CapabilityShaderClockKHR = 5055, CapabilityShaderClockKHR = 5055,
CapabilityQuadControlKHR = 5087,
CapabilitySampleMaskOverrideCoverageNV = 5249, CapabilitySampleMaskOverrideCoverageNV = 5249,
CapabilityGeometryShaderPassthroughNV = 5251, CapabilityGeometryShaderPassthroughNV = 5251,
CapabilityShaderViewportIndexLayerEXT = 5254, CapabilityShaderViewportIndexLayerEXT = 5254,
@ -1704,6 +1708,8 @@ enum Op {
OpFragmentMaskFetchAMD = 5011, OpFragmentMaskFetchAMD = 5011,
OpFragmentFetchAMD = 5012, OpFragmentFetchAMD = 5012,
OpReadClockKHR = 5056, OpReadClockKHR = 5056,
OpGroupNonUniformQuadAllKHR = 5110,
OpGroupNonUniformQuadAnyKHR = 5111,
OpHitObjectRecordHitMotionNV = 5249, OpHitObjectRecordHitMotionNV = 5249,
OpHitObjectRecordHitWithIndexMotionNV = 5250, OpHitObjectRecordHitWithIndexMotionNV = 5250,
OpHitObjectRecordMissMotionNV = 5251, OpHitObjectRecordMissMotionNV = 5251,
@ -2374,6 +2380,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break;
case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break;
case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break;
case OpGroupNonUniformQuadAllKHR: *hasResult = true; *hasResultType = true; break;
case OpGroupNonUniformQuadAnyKHR: *hasResult = true; *hasResultType = true; break;
case OpCopyLogical: *hasResult = true; *hasResultType = true; break; case OpCopyLogical: *hasResult = true; *hasResultType = true; break;
case OpPtrEqual: *hasResult = true; *hasResultType = true; break; case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;

View File

@ -56,6 +56,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <set> #include <set>
#include <optional>
namespace spv { namespace spv {
@ -190,6 +191,12 @@ protected:
// SPIR-V IR block. // SPIR-V IR block.
// //
struct DebugSourceLocation {
int line;
int column;
spv::Id fileId;
};
class Block { class Block {
public: public:
Block(Id id, Function& parent); Block(Id id, Function& parent);
@ -200,6 +207,28 @@ public:
Id getId() { return instructions.front()->getResultId(); } Id getId() { return instructions.front()->getResultId(); }
Function& getParent() const { return parent; } Function& getParent() const { return parent; }
// Returns true if the source location is actually updated.
// Note we still need the builder to insert the line marker instruction. This is just a tracker.
bool updateDebugSourceLocation(int line, int column, spv::Id fileId) {
if (currentSourceLoc && currentSourceLoc->line == line && currentSourceLoc->column == column &&
currentSourceLoc->fileId == fileId) {
return false;
}
currentSourceLoc = DebugSourceLocation{line, column, fileId};
return true;
}
// Returns true if the scope is actually updated.
// Note we still need the builder to insert the debug scope instruction. This is just a tracker.
bool updateDebugScope(spv::Id scopeId) {
assert(scopeId);
if (currentDebugScope && *currentDebugScope == scopeId) {
return false;
}
currentDebugScope = scopeId;
return true;
}
void addInstruction(std::unique_ptr<Instruction> inst); void addInstruction(std::unique_ptr<Instruction> inst);
void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); } void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
@ -292,6 +321,12 @@ protected:
std::vector<std::unique_ptr<Instruction> > localVariables; std::vector<std::unique_ptr<Instruction> > localVariables;
Function& parent; Function& parent;
// Track source location of the last source location marker instruction.
std::optional<DebugSourceLocation> currentSourceLoc;
// Track scope of the last debug scope instruction.
std::optional<spv::Id> currentDebugScope;
// track whether this block is known to be uncreachable (not necessarily // track whether this block is known to be uncreachable (not necessarily
// true for all unreachable blocks, but should be set at least // true for all unreachable blocks, but should be set at least
// for the extraneous ones introduced by the builder). // for the extraneous ones introduced by the builder).

View File

@ -852,6 +852,8 @@ public:
// -2048 as the default value indicating layoutSecondaryViewportRelative is not set // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
layoutSecondaryViewportRelativeOffset = -2048; layoutSecondaryViewportRelativeOffset = -2048;
layoutShaderRecord = false; layoutShaderRecord = false;
layoutFullQuads = false;
layoutQuadDeriv = false;
layoutHitObjectShaderRecordNV = false; layoutHitObjectShaderRecordNV = false;
layoutBindlessSampler = false; layoutBindlessSampler = false;
layoutBindlessImage = false; layoutBindlessImage = false;
@ -948,6 +950,8 @@ public:
bool layoutViewportRelative; bool layoutViewportRelative;
int layoutSecondaryViewportRelativeOffset; int layoutSecondaryViewportRelativeOffset;
bool layoutShaderRecord; bool layoutShaderRecord;
bool layoutFullQuads;
bool layoutQuadDeriv;
bool layoutHitObjectShaderRecordNV; bool layoutHitObjectShaderRecordNV;
// GL_EXT_spirv_intrinsics // GL_EXT_spirv_intrinsics
@ -1055,6 +1059,8 @@ public:
TLayoutFormat getFormat() const { return layoutFormat; } TLayoutFormat getFormat() const { return layoutFormat; }
bool isPushConstant() const { return layoutPushConstant; } bool isPushConstant() const { return layoutPushConstant; }
bool isShaderRecord() const { return layoutShaderRecord; } bool isShaderRecord() const { return layoutShaderRecord; }
bool isFullQuads() const { return layoutFullQuads; }
bool isQuadDeriv() const { return layoutQuadDeriv; }
bool hasHitObjectShaderRecordNV() const { return layoutHitObjectShaderRecordNV; } bool hasHitObjectShaderRecordNV() const { return layoutHitObjectShaderRecordNV; }
bool hasBufferReference() const { return layoutBufferReference; } bool hasBufferReference() const { return layoutBufferReference; }
bool hasBufferReferenceAlign() const bool hasBufferReferenceAlign() const
@ -2206,6 +2212,10 @@ public:
if (qualifier.layoutShaderRecord) if (qualifier.layoutShaderRecord)
appendStr(" shaderRecordNV"); appendStr(" shaderRecordNV");
if (qualifier.layoutFullQuads)
appendStr(" full_quads");
if (qualifier.layoutQuadDeriv)
appendStr(" quad_derivatives");
if (qualifier.layoutHitObjectShaderRecordNV) if (qualifier.layoutHitObjectShaderRecordNV)
appendStr(" hitobjectshaderrecordnv"); appendStr(" hitobjectshaderrecordnv");

View File

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017, 2022-2024 Arm Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
@ -506,6 +506,8 @@ enum TOperator {
EOpSubgroupShuffleXor, EOpSubgroupShuffleXor,
EOpSubgroupShuffleUp, EOpSubgroupShuffleUp,
EOpSubgroupShuffleDown, EOpSubgroupShuffleDown,
EOpSubgroupRotate,
EOpSubgroupClusteredRotate,
EOpSubgroupAdd, EOpSubgroupAdd,
EOpSubgroupMul, EOpSubgroupMul,
EOpSubgroupMin, EOpSubgroupMin,
@ -538,6 +540,8 @@ enum TOperator {
EOpSubgroupQuadSwapHorizontal, EOpSubgroupQuadSwapHorizontal,
EOpSubgroupQuadSwapVertical, EOpSubgroupQuadSwapVertical,
EOpSubgroupQuadSwapDiagonal, EOpSubgroupQuadSwapDiagonal,
EOpSubgroupQuadAll,
EOpSubgroupQuadAny,
EOpSubgroupPartition, EOpSubgroupPartition,
EOpSubgroupPartitionedAdd, EOpSubgroupPartitionedAdd,

View File

@ -2,7 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017, 2022-2024 Arm Limited.
// Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
@ -2099,6 +2099,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"%s subgroupShuffleXor(%s, uint);\n", "%s subgroupShuffleXor(%s, uint);\n",
"%s subgroupShuffleUp(%s, uint delta);\n", "%s subgroupShuffleUp(%s, uint delta);\n",
"%s subgroupShuffleDown(%s, uint delta);\n", "%s subgroupShuffleDown(%s, uint delta);\n",
"%s subgroupRotate(%s, uint);\n",
"%s subgroupClusteredRotate(%s, uint, uint);\n",
"%s subgroupAdd(%s);\n", "%s subgroupAdd(%s);\n",
"%s subgroupMul(%s);\n", "%s subgroupMul(%s);\n",
"%s subgroupMin(%s);\n", "%s subgroupMin(%s);\n",
@ -2227,6 +2229,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
); );
} }
// GL_EXT_shader_quad_control
if ((profile == EEsProfile && version >= 310) ||
(profile != EEsProfile && version >= 140)) {
commonBuiltins.append(
"bool subgroupQuadAll(bool);\n"
"bool subgroupQuadAny(bool);\n"
);
}
if (profile != EEsProfile && version >= 460) { if (profile != EEsProfile && version >= 460) {
commonBuiltins.append( commonBuiltins.append(
"bool anyInvocation(bool);" "bool anyInvocation(bool);"
@ -8661,6 +8672,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setFunctionExtensions("subgroupShuffleXor", 1, &E_GL_KHR_shader_subgroup_shuffle); symbolTable.setFunctionExtensions("subgroupShuffleXor", 1, &E_GL_KHR_shader_subgroup_shuffle);
symbolTable.setFunctionExtensions("subgroupShuffleUp", 1, &E_GL_KHR_shader_subgroup_shuffle_relative); symbolTable.setFunctionExtensions("subgroupShuffleUp", 1, &E_GL_KHR_shader_subgroup_shuffle_relative);
symbolTable.setFunctionExtensions("subgroupShuffleDown", 1, &E_GL_KHR_shader_subgroup_shuffle_relative); symbolTable.setFunctionExtensions("subgroupShuffleDown", 1, &E_GL_KHR_shader_subgroup_shuffle_relative);
symbolTable.setFunctionExtensions("subgroupRotate", 1, &E_GL_KHR_shader_subgroup_rotate);
symbolTable.setFunctionExtensions("subgroupClusteredRotate", 1, &E_GL_KHR_shader_subgroup_rotate);
symbolTable.setFunctionExtensions("subgroupAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic); symbolTable.setFunctionExtensions("subgroupAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic);
symbolTable.setFunctionExtensions("subgroupMul", 1, &E_GL_KHR_shader_subgroup_arithmetic); symbolTable.setFunctionExtensions("subgroupMul", 1, &E_GL_KHR_shader_subgroup_arithmetic);
symbolTable.setFunctionExtensions("subgroupMin", 1, &E_GL_KHR_shader_subgroup_arithmetic); symbolTable.setFunctionExtensions("subgroupMin", 1, &E_GL_KHR_shader_subgroup_arithmetic);
@ -8779,6 +8792,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
} }
// GL_EXT_shader_quad_control
if ((profile != EEsProfile && version >= 140) ||
(profile == EEsProfile && version >= 310)) {
symbolTable.setFunctionExtensions("subgroupQuadAll", 1, &E_GL_KHR_shader_subgroup_vote);
symbolTable.setFunctionExtensions("subgroupQuadAny", 1, &E_GL_KHR_shader_subgroup_vote);
}
// GL_EXT_shader_tile_image // GL_EXT_shader_tile_image
symbolTable.setFunctionExtensions("stencilAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); symbolTable.setFunctionExtensions("stencilAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image);
symbolTable.setFunctionExtensions("depthAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); symbolTable.setFunctionExtensions("depthAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image);
@ -9915,6 +9935,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.relateToOperator("subgroupShuffleXor", EOpSubgroupShuffleXor); symbolTable.relateToOperator("subgroupShuffleXor", EOpSubgroupShuffleXor);
symbolTable.relateToOperator("subgroupShuffleUp", EOpSubgroupShuffleUp); symbolTable.relateToOperator("subgroupShuffleUp", EOpSubgroupShuffleUp);
symbolTable.relateToOperator("subgroupShuffleDown", EOpSubgroupShuffleDown); symbolTable.relateToOperator("subgroupShuffleDown", EOpSubgroupShuffleDown);
symbolTable.relateToOperator("subgroupRotate", EOpSubgroupRotate);
symbolTable.relateToOperator("subgroupClusteredRotate", EOpSubgroupClusteredRotate);
symbolTable.relateToOperator("subgroupAdd", EOpSubgroupAdd); symbolTable.relateToOperator("subgroupAdd", EOpSubgroupAdd);
symbolTable.relateToOperator("subgroupMul", EOpSubgroupMul); symbolTable.relateToOperator("subgroupMul", EOpSubgroupMul);
symbolTable.relateToOperator("subgroupMin", EOpSubgroupMin); symbolTable.relateToOperator("subgroupMin", EOpSubgroupMin);
@ -9977,6 +9999,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.relateToOperator("shadow2DProjEXT", EOpTextureProj); symbolTable.relateToOperator("shadow2DProjEXT", EOpTextureProj);
} }
// GL_EXT_shader_quad_control
if ((profile == EEsProfile && version >= 310) ||
(profile != EEsProfile && version >= 140)) {
symbolTable.relateToOperator("subgroupQuadAll", EOpSubgroupQuadAll);
symbolTable.relateToOperator("subgroupQuadAny", EOpSubgroupQuadAny);
}
if ((profile == EEsProfile && version >= 310) || if ((profile == EEsProfile && version >= 310) ||
(profile != EEsProfile && version >= 140)) { (profile != EEsProfile && version >= 140)) {
symbolTable.relateToOperator("textureWeightedQCOM", EOpImageSampleWeightedQCOM); symbolTable.relateToOperator("textureWeightedQCOM", EOpImageSampleWeightedQCOM);

View File

@ -1351,6 +1351,10 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
// - a user function. // - a user function.
// Error check for a function requiring specific extensions present. // Error check for a function requiring specific extensions present.
if (builtIn &&
(fnCandidate->getBuiltInOp() == EOpSubgroupQuadAll || fnCandidate->getBuiltInOp() == EOpSubgroupQuadAny))
requireExtensions(loc, 1, &E_GL_EXT_shader_quad_control, fnCandidate->getName().c_str());
if (builtIn && fnCandidate->getNumExtensions()) if (builtIn && fnCandidate->getNumExtensions())
requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
@ -3986,6 +3990,18 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
// Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it. // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
if (!isMemberCheck || structNestingLevel > 0) if (!isMemberCheck || structNestingLevel > 0)
invariantCheck(loc, qualifier); invariantCheck(loc, qualifier);
if (qualifier.isFullQuads()) {
if (qualifier.storage != EvqVaryingIn)
error(loc, "can only apply to input layout", "full_quads ", "");
intermediate.setReqFullQuadsMode();
}
if (qualifier.isQuadDeriv()) {
if (qualifier.storage != EvqVaryingIn)
error(loc, "can only apply to input layout", "quad_derivatives", "");
intermediate.setQuadDerivMode();
}
} }
// //
@ -5859,6 +5875,15 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
publicType.shaderQualifiers.layoutOverrideCoverage = true; publicType.shaderQualifiers.layoutOverrideCoverage = true;
return; return;
} }
if (id == "full_quads")
{
const char* feature = "full_quads qualifier";
requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, feature);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 140, E_GL_EXT_shader_quad_control, feature);
profileRequires(loc, EEsProfile, 310, E_GL_EXT_shader_quad_control, feature);
publicType.qualifier.layoutFullQuads = true;
return;
}
} }
if (language == EShLangVertex || if (language == EShLangVertex ||
language == EShLangTessControl || language == EShLangTessControl ||
@ -5908,6 +5933,16 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
return; return;
} }
if (id == "quad_derivatives")
{
const char* feature = "quad_derivatives qualifier";
requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, feature);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 140, E_GL_EXT_shader_quad_control, feature);
profileRequires(loc, EEsProfile, 310, E_GL_EXT_shader_quad_control, feature);
publicType.qualifier.layoutQuadDeriv = true;
return;
}
error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
} }
@ -6336,6 +6371,10 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
if (src.layoutShaderRecord) if (src.layoutShaderRecord)
dst.layoutShaderRecord = true; dst.layoutShaderRecord = true;
if (src.layoutFullQuads)
dst.layoutFullQuads = true;
if (src.layoutQuadDeriv)
dst.layoutQuadDeriv = true;
if (src.layoutBindlessSampler) if (src.layoutBindlessSampler)
dst.layoutBindlessSampler = true; dst.layoutBindlessSampler = true;
if (src.layoutBindlessImage) if (src.layoutBindlessImage)

View File

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017, 2022-2024 Arm Limited.
// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
@ -235,6 +235,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_KHR_shader_subgroup_ballot] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_ballot] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_shuffle] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_shuffle] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_rotate] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_clustered] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_clustered] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_quad] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_quad] = EBhDisable;
extensionBehavior[E_GL_KHR_memory_scope_semantics] = EBhDisable; extensionBehavior[E_GL_KHR_memory_scope_semantics] = EBhDisable;
@ -258,6 +259,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable; extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable;
extensionBehavior[E_GL_EXT_maximal_reconvergence] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_shader_barycentric] = EBhDisable; extensionBehavior[E_GL_EXT_fragment_shader_barycentric] = EBhDisable;
@ -356,6 +358,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_spirv_intrinsics] = EBhDisable; extensionBehavior[E_GL_EXT_spirv_intrinsics] = EBhDisable;
extensionBehavior[E_GL_EXT_mesh_shader] = EBhDisable; extensionBehavior[E_GL_EXT_mesh_shader] = EBhDisable;
extensionBehavior[E_GL_EXT_opacity_micromap] = EBhDisable; extensionBehavior[E_GL_EXT_opacity_micromap] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_quad_control] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_tracing_position_fetch] = EBhDisable; extensionBehavior[E_GL_EXT_ray_tracing_position_fetch] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_tile_image] = EBhDisable; extensionBehavior[E_GL_EXT_shader_tile_image] = EBhDisable;
extensionBehavior[E_GL_EXT_texture_shadow_lod] = EBhDisable; extensionBehavior[E_GL_EXT_texture_shadow_lod] = EBhDisable;
@ -446,6 +449,7 @@ void TParseVersions::getPreamble(std::string& preamble)
if (version >= 310) { if (version >= 310) {
preamble += "#define GL_EXT_null_initializer 1\n"; preamble += "#define GL_EXT_null_initializer 1\n";
preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n"; preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
preamble += "#define GL_EXT_maximal_reconvergence 1\n";
} }
} else { // !isEsProfile() } else { // !isEsProfile()
@ -582,6 +586,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_atomic_float2 1\n" "#define GL_EXT_shader_atomic_float2 1\n"
"#define GL_EXT_fragment_shader_barycentric 1\n" "#define GL_EXT_fragment_shader_barycentric 1\n"
"#define GL_EXT_shader_quad_control 1\n"
"#define GL_EXT_texture_array 1\n" "#define GL_EXT_texture_array 1\n"
; ;
@ -599,6 +604,7 @@ void TParseVersions::getPreamble(std::string& preamble)
if (version >= 140) { if (version >= 140) {
preamble += "#define GL_EXT_null_initializer 1\n"; preamble += "#define GL_EXT_null_initializer 1\n";
preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n"; preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
preamble += "#define GL_EXT_maximal_reconvergence 1\n";
} }
if (version >= 130) { if (version >= 130) {
preamble +="#define GL_FRAGMENT_PRECISION_HIGH 1\n"; preamble +="#define GL_FRAGMENT_PRECISION_HIGH 1\n";

View File

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017, 2022-2024 Arm Limited.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
@ -171,6 +171,7 @@ const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_sub
const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot"; const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot";
const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle"; const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle";
const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
const char* const E_GL_KHR_shader_subgroup_rotate = "GL_KHR_shader_subgroup_rotate";
const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered";
const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad";
const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics"; const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics";
@ -215,8 +216,10 @@ const char* const E_GL_EXT_spirv_intrinsics = "GL_EXT_spirv_intr
const char* const E_GL_EXT_fragment_shader_barycentric = "GL_EXT_fragment_shader_barycentric"; const char* const E_GL_EXT_fragment_shader_barycentric = "GL_EXT_fragment_shader_barycentric";
const char* const E_GL_EXT_mesh_shader = "GL_EXT_mesh_shader"; const char* const E_GL_EXT_mesh_shader = "GL_EXT_mesh_shader";
const char* const E_GL_EXT_opacity_micromap = "GL_EXT_opacity_micromap"; const char* const E_GL_EXT_opacity_micromap = "GL_EXT_opacity_micromap";
const char* const E_GL_EXT_shader_quad_control = "GL_EXT_shader_quad_control";
const char* const E_GL_EXT_draw_instanced = "GL_EXT_draw_instanced"; const char* const E_GL_EXT_draw_instanced = "GL_EXT_draw_instanced";
const char* const E_GL_EXT_texture_array = "GL_EXT_texture_array"; const char* const E_GL_EXT_texture_array = "GL_EXT_texture_array";
const char* const E_GL_EXT_maximal_reconvergence = "GL_EXT_maximal_reconvergence";
// Arrays of extensions for the above viewportEXTs duplications // Arrays of extensions for the above viewportEXTs duplications

View File

@ -125,6 +125,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const
return EatSubgroupUniformControlFlow; return EatSubgroupUniformControlFlow;
else if (name == "export") else if (name == "export")
return EatExport; return EatExport;
else if (name == "maximally_reconverges")
return EatMaximallyReconverges;
else else
return EatNone; return EatNone;
} }
@ -360,6 +362,10 @@ void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttri
requireExtensions(loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); requireExtensions(loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
intermediate.setSubgroupUniformControlFlow(); intermediate.setSubgroupUniformControlFlow();
break; break;
case EatMaximallyReconverges:
requireExtensions(loc, 1, &E_GL_EXT_maximal_reconvergence, "attribute");
intermediate.setMaximallyReconverges();
break;
default: default:
warn(loc, "attribute does not apply to a function", "", ""); warn(loc, "attribute does not apply to a function", "", "");
break; break;

View File

@ -121,6 +121,7 @@ namespace glslang {
EatNonReadable, EatNonReadable,
EatSubgroupUniformControlFlow, EatSubgroupUniformControlFlow,
EatExport, EatExport,
EatMaximallyReconverges,
}; };
class TIntermAggregate; class TIntermAggregate;

View File

@ -964,18 +964,24 @@ function_prototype
$$.function = $1; $$.function = $1;
if (parseContext.compileOnly) $$.function->setExport(); if (parseContext.compileOnly) $$.function->setExport();
$$.loc = $2.loc; $$.loc = $2.loc;
const char * extensions[2] = { E_GL_EXT_subgroup_uniform_control_flow, E_GL_EXT_maximal_reconvergence };
parseContext.requireExtensions($2.loc, 2, extensions, "attribute");
parseContext.handleFunctionAttributes($2.loc, *$3); parseContext.handleFunctionAttributes($2.loc, *$3);
} }
| attribute function_declarator RIGHT_PAREN { | attribute function_declarator RIGHT_PAREN {
$$.function = $2; $$.function = $2;
if (parseContext.compileOnly) $$.function->setExport(); if (parseContext.compileOnly) $$.function->setExport();
$$.loc = $3.loc; $$.loc = $3.loc;
const char * extensions[2] = { E_GL_EXT_subgroup_uniform_control_flow, E_GL_EXT_maximal_reconvergence };
parseContext.requireExtensions($3.loc, 2, extensions, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1); parseContext.handleFunctionAttributes($3.loc, *$1);
} }
| attribute function_declarator RIGHT_PAREN attribute { | attribute function_declarator RIGHT_PAREN attribute {
$$.function = $2; $$.function = $2;
if (parseContext.compileOnly) $$.function->setExport(); if (parseContext.compileOnly) $$.function->setExport();
$$.loc = $3.loc; $$.loc = $3.loc;
const char * extensions[2] = { E_GL_EXT_subgroup_uniform_control_flow, E_GL_EXT_maximal_reconvergence };
parseContext.requireExtensions($3.loc, 2, extensions, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1); parseContext.handleFunctionAttributes($3.loc, *$1);
parseContext.handleFunctionAttributes($3.loc, *$4); parseContext.handleFunctionAttributes($3.loc, *$4);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017, 2022-2024 Arm Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
@ -565,6 +565,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break; case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break;
case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break; case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break;
case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break; case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break;
case EOpSubgroupRotate: out.debug << "subgroupRotate"; break;
case EOpSubgroupClusteredRotate: out.debug << "subgroupClusteredRotate"; break;
case EOpSubgroupAdd: out.debug << "subgroupAdd"; break; case EOpSubgroupAdd: out.debug << "subgroupAdd"; break;
case EOpSubgroupMul: out.debug << "subgroupMul"; break; case EOpSubgroupMul: out.debug << "subgroupMul"; break;
case EOpSubgroupMin: out.debug << "subgroupMin"; break; case EOpSubgroupMin: out.debug << "subgroupMin"; break;
@ -597,6 +599,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break;
case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break;
case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break;
case EOpSubgroupQuadAll: out.debug << "subgroupQuadAll"; break;
case EOpSubgroupQuadAny: out.debug << "subgroupQuadAny"; break;
case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break; case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break;
case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break; case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break;
@ -1000,6 +1004,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break; case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break;
case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break; case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break;
case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break; case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break;
case EOpSubgroupRotate: out.debug << "subgroupRotate"; break;
case EOpSubgroupClusteredRotate: out.debug << "subgroupClusteredRotate"; break;
case EOpSubgroupAdd: out.debug << "subgroupAdd"; break; case EOpSubgroupAdd: out.debug << "subgroupAdd"; break;
case EOpSubgroupMul: out.debug << "subgroupMul"; break; case EOpSubgroupMul: out.debug << "subgroupMul"; break;
case EOpSubgroupMin: out.debug << "subgroupMin"; break; case EOpSubgroupMin: out.debug << "subgroupMin"; break;
@ -1032,6 +1038,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break;
case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break;
case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break;
case EOpSubgroupQuadAll: out.debug << "subgroupQuadAll"; break;
case EOpSubgroupQuadAny: out.debug << "subgroupQuadAny"; break;
case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break; case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break;
case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break; case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break;
@ -1512,6 +1520,9 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
if (getSubgroupUniformControlFlow()) if (getSubgroupUniformControlFlow())
infoSink.debug << "subgroup_uniform_control_flow\n"; infoSink.debug << "subgroup_uniform_control_flow\n";
if (getMaximallyReconverges())
infoSink.debug << "maximally_reconverges\n";
switch (language) { switch (language) {
case EShLangVertex: case EShLangVertex:
break; break;

View File

@ -345,10 +345,12 @@ public:
needToLegalize(false), needToLegalize(false),
binaryDoubleOutput(false), binaryDoubleOutput(false),
subgroupUniformControlFlow(false), subgroupUniformControlFlow(false),
maximallyReconverges(false),
usePhysicalStorageBuffer(false), usePhysicalStorageBuffer(false),
spirvRequirement(nullptr), spirvRequirement(nullptr),
spirvExecutionMode(nullptr), spirvExecutionMode(nullptr),
uniformLocationBase(0) uniformLocationBase(0),
quadDerivMode(false), reqFullQuadsMode(false)
{ {
localSize[0] = 1; localSize[0] = 1;
localSize[1] = 1; localSize[1] = 1;
@ -857,6 +859,10 @@ public:
void setXfbMode() { xfbMode = true; } void setXfbMode() { xfbMode = true; }
bool getXfbMode() const { return xfbMode; } bool getXfbMode() const { return xfbMode; }
void setQuadDerivMode(bool mode = true) { quadDerivMode = mode; }
bool getQuadDerivMode() const { return quadDerivMode; }
void setReqFullQuadsMode(bool mode = true) { reqFullQuadsMode = mode; }
bool getReqFullQuadsMode() const { return reqFullQuadsMode; }
void setMultiStream() { multiStream = true; } void setMultiStream() { multiStream = true; }
bool isMultiStream() const { return multiStream; } bool isMultiStream() const { return multiStream; }
bool setOutputPrimitive(TLayoutGeometry p) bool setOutputPrimitive(TLayoutGeometry p)
@ -963,6 +969,9 @@ public:
void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; } void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; } bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
void setMaximallyReconverges() { maximallyReconverges = true; }
bool getMaximallyReconverges() const { return maximallyReconverges; }
// GL_EXT_spirv_intrinsics // GL_EXT_spirv_intrinsics
void insertSpirvRequirement(const TSpirvRequirement* spirvReq); void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
bool hasSpirvRequirement() const { return spirvRequirement != nullptr; } bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
@ -1226,6 +1235,7 @@ protected:
bool needToLegalize; bool needToLegalize;
bool binaryDoubleOutput; bool binaryDoubleOutput;
bool subgroupUniformControlFlow; bool subgroupUniformControlFlow;
bool maximallyReconverges;
bool usePhysicalStorageBuffer; bool usePhysicalStorageBuffer;
TSpirvRequirement* spirvRequirement; TSpirvRequirement* spirvRequirement;
@ -1234,6 +1244,8 @@ protected:
std::map<TString, AstRefType> bindlessImageModeCaller; std::map<TString, AstRefType> bindlessImageModeCaller;
std::unordered_map<std::string, int> uniformLocationOverrides; std::unordered_map<std::string, int> uniformLocationOverrides;
int uniformLocationBase; int uniformLocationBase;
bool quadDerivMode;
bool reqFullQuadsMode;
TNumericFeatures numericFeatures; TNumericFeatures numericFeatures;
std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides; std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;