build: update glslang to latest version

This commit is contained in:
Kai Angulo 2024-10-23 23:26:46 -07:00
commit 413a51ee6d
710 changed files with 18932 additions and 14484 deletions

View file

@ -34,6 +34,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "glslang/Include/glslang_c_interface.h"
#include <cstring>
#include "glslang/Public/ShaderLang.h"
#include "SPIRV/GlslangToSpv.h"
#include "SPIRV/Logger.h"
#include "SPIRV/SpvTools.h"

View file

@ -31,41 +31,43 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
set(SOURCES
GlslangToSpv.cpp
InReadableOrder.cpp
Logger.cpp
SpvBuilder.cpp
SpvPostProcess.cpp
doc.cpp
SpvTools.cpp
disassemble.cpp
CInterface/spirv_c_interface.cpp)
set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/GlslangToSpv.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InReadableOrder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Logger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SpvBuilder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SpvPostProcess.cpp
${CMAKE_CURRENT_SOURCE_DIR}/doc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SpvTools.cpp
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CInterface/spirv_c_interface.cpp
PARENT_SCOPE)
set(SPVREMAP_SOURCES
SPVRemapper.cpp
doc.cpp)
set(HEADERS
bitutils.h
spirv.hpp
GLSL.std.450.h
GLSL.ext.EXT.h
GLSL.ext.KHR.h
GlslangToSpv.h
hex_float.h
Logger.h
SpvBuilder.h
spvIR.h
doc.h
SpvTools.h
disassemble.h
GLSL.ext.AMD.h
GLSL.ext.NV.h
GLSL.ext.ARM.h
GLSL.ext.QCOM.h
NonSemanticDebugPrintf.h
NonSemanticShaderDebugInfo100.h)
set(SPIRV_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/bitutils.h
${CMAKE_CURRENT_SOURCE_DIR}/spirv.hpp
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.std.450.h
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.EXT.h
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.KHR.h
${CMAKE_CURRENT_SOURCE_DIR}/GlslangToSpv.h
${CMAKE_CURRENT_SOURCE_DIR}/hex_float.h
${CMAKE_CURRENT_SOURCE_DIR}/Logger.h
${CMAKE_CURRENT_SOURCE_DIR}/SpvBuilder.h
${CMAKE_CURRENT_SOURCE_DIR}/spvIR.h
${CMAKE_CURRENT_SOURCE_DIR}/doc.h
${CMAKE_CURRENT_SOURCE_DIR}/SpvTools.h
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.h
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.AMD.h
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.NV.h
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.ARM.h
${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.QCOM.h
${CMAKE_CURRENT_SOURCE_DIR}/NonSemanticDebugPrintf.h
${CMAKE_CURRENT_SOURCE_DIR}/NonSemanticShaderDebugInfo100.h
PARENT_SCOPE)
set(SPVREMAP_HEADERS
SPVRemapper.h
@ -76,9 +78,10 @@ set(PUBLIC_HEADERS
disassemble.h
Logger.h
spirv.hpp
SPVRemapper.h)
SPVRemapper.h
SpvTools.h)
add_library(SPIRV ${LIB_TYPE} ${SOURCES} ${HEADERS})
add_library(SPIRV ${LIB_TYPE} ${CMAKE_CURRENT_SOURCE_DIR}/../glslang/stub.cpp)
add_library(glslang::SPIRV ALIAS SPIRV)
set_target_properties(SPIRV PROPERTIES
FOLDER glslang
@ -89,8 +92,6 @@ target_include_directories(SPIRV PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
glslang_add_build_info_dependency(SPIRV)
if (ENABLE_SPVREMAPPER)
add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
add_library(glslang::SPVRemapper ALIAS SPVRemapper)
@ -99,6 +100,7 @@ if (ENABLE_SPVREMAPPER)
POSITION_INDEPENDENT_CODE ON
VERSION "${GLSLANG_VERSION}"
SOVERSION "${GLSLANG_VERSION_MAJOR}")
glslang_only_export_explicit_symbols(SPVRemapper)
endif()
if(WIN32 AND BUILD_SHARED_LIBS)
@ -109,11 +111,11 @@ if(WIN32 AND BUILD_SHARED_LIBS)
endif()
if(ENABLE_OPT)
target_link_libraries(SPIRV PRIVATE MachineIndependent PUBLIC SPIRV-Tools-opt)
target_link_libraries(SPIRV PRIVATE glslang PUBLIC SPIRV-Tools-opt)
target_include_directories(SPIRV PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External>)
else()
target_link_libraries(SPIRV PRIVATE MachineIndependent)
target_link_libraries(SPIRV PRIVATE glslang)
endif()
if(WIN32)

95
SPIRV/GlslangToSpv.cpp Executable file → Normal file
View file

@ -1558,7 +1558,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
else {
builder.setEmitSpirvDebugInfo();
}
builder.setDebugSourceFile(glslangIntermediate->getSourceFile());
builder.setDebugMainSourceFile(glslangIntermediate->getSourceFile());
// Set the source shader's text. If for SPV version 1.0, include
// a preamble in comments stating the OpModuleProcessed instructions.
@ -2858,9 +2858,16 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
// SPIR-V, for an out parameter
std::vector<spv::Id> temporaryLvalues; // temporaries to pass, as proxies for complexLValues
auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
invertedType :
convertGlslangToSpvType(node->getType()); };
auto resultType = [&invertedType, &node, this](){
if (invertedType != spv::NoType) {
return invertedType;
} else {
auto ret = convertGlslangToSpvType(node->getType());
// convertGlslangToSpvType may clobber the debug location, reset it
builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
return ret;
}
};
// try texturing
result = createImageTextureFunctionCall(node);
@ -2917,8 +2924,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
return false;
} else {
if (node->getOp() == glslang::EOpScope)
builder.enterLexicalBlock(0);
if (node->getOp() == glslang::EOpScope) {
auto loc = node->getLoc();
builder.enterLexicalBlock(loc.line, loc.column);
}
}
} else {
if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope)
@ -2967,6 +2976,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column);
}
} else {
if (options.generateDebugInfo) {
if (glslangIntermediate->getSource() == glslang::EShSourceGlsl && node->getSequence().size() > 1) {
auto endLoc = node->getSequence()[1]->getAsAggregate()->getEndLoc();
builder.setDebugSourceLocation(endLoc.line, endLoc.getFilename());
}
}
if (inEntryPoint)
entryPointTerminated = true;
builder.leaveFunction();
@ -4120,7 +4135,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
if (codeSegments[s])
codeSegments[s]->traverse(this);
else
builder.addSwitchBreak();
builder.addSwitchBreak(true);
}
breakForLoop.pop();
@ -4144,7 +4159,7 @@ void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* n
bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node)
{
auto blocks = builder.makeNewLoop();
builder.createBranch(&blocks.head);
builder.createBranch(true, &blocks.head);
// Loop control:
std::vector<unsigned int> operands;
@ -4161,7 +4176,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
if (node->testFirst() && node->getTest()) {
spv::Block& test = builder.makeNewBlock();
builder.createBranch(&test);
builder.createBranch(true, &test);
builder.setBuildPoint(&test);
node->getTest()->traverse(this);
@ -4172,22 +4187,22 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
breakForLoop.push(true);
if (node->getBody())
node->getBody()->traverse(this);
builder.createBranch(&blocks.continue_target);
builder.createBranch(true, &blocks.continue_target);
breakForLoop.pop();
builder.setBuildPoint(&blocks.continue_target);
if (node->getTerminal())
node->getTerminal()->traverse(this);
builder.createBranch(&blocks.head);
builder.createBranch(true, &blocks.head);
} else {
builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
builder.createBranch(&blocks.body);
builder.createBranch(true, &blocks.body);
breakForLoop.push(true);
builder.setBuildPoint(&blocks.body);
if (node->getBody())
node->getBody()->traverse(this);
builder.createBranch(&blocks.continue_target);
builder.createBranch(true, &blocks.continue_target);
breakForLoop.pop();
builder.setBuildPoint(&blocks.continue_target);
@ -4202,7 +4217,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
// TODO: unless there was a break/return/discard instruction
// somewhere in the body, this is an infinite loop, so we should
// issue a warning.
builder.createBranch(&blocks.head);
builder.createBranch(true, &blocks.head);
}
}
builder.setBuildPoint(&blocks.merge);
@ -4238,7 +4253,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
if (breakForLoop.top())
builder.createLoopExit();
else
builder.addSwitchBreak();
builder.addSwitchBreak(false);
break;
case glslang::EOpContinue:
builder.createLoopContinue();
@ -4372,7 +4387,14 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
initializer = builder.makeNullConstant(spvType);
}
return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false);
spv::Id var = builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false);
std::vector<spv::Decoration> topLevelDecorations;
glslang::TQualifier typeQualifier = node->getType().getQualifier();
TranslateMemoryDecoration(typeQualifier, topLevelDecorations, glslangIntermediate->usingVulkanMemoryModel());
for (auto deco : topLevelDecorations) {
builder.addDecoration(var, deco);
}
return var;
}
// Return type Id of the sampled type.
@ -4861,7 +4883,7 @@ bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member)
}
return false;
};
}
// Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id.
// explicitLayout can be kept the same throughout the hierarchical recursive walk.
@ -5404,13 +5426,16 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType
memberAlignment = componentAlignment;
// Don't add unnecessary padding after this member
if (memberType.isMatrix()) {
if (matrixLayout == glslang::ElmRowMajor)
memberSize -= componentSize * (4 - memberType.getMatrixCols());
else
memberSize -= componentSize * (4 - memberType.getMatrixRows());
} else if (memberType.isArray())
memberSize -= componentSize * (4 - memberType.getVectorSize());
// (undo std140 bumping size to a mutliple of vec4)
if (explicitLayout == glslang::ElpStd140) {
if (memberType.isMatrix()) {
if (matrixLayout == glslang::ElmRowMajor)
memberSize -= componentSize * (4 - memberType.getMatrixCols());
else
memberSize -= componentSize * (4 - memberType.getMatrixRows());
} else if (memberType.isArray())
memberSize -= componentSize * (4 - memberType.getVectorSize());
}
}
// Bump up to member alignment
@ -5518,12 +5543,16 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate();
if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction)
continue;
builder.setDebugSourceLocation(glslFunction->getLoc().line, glslFunction->getLoc().getFilename());
if (isShaderEntryPoint(glslFunction)) {
// For HLSL, the entry function is actually a compiler generated function to resolve the difference of
// entry function signature between HLSL and SPIR-V. So we don't emit debug information for that.
if (glslangIntermediate->getSource() != glslang::EShSourceHlsl) {
builder.setupDebugFunctionEntry(shaderEntry, glslangIntermediate->getEntryPointMangledName().c_str(),
glslFunction->getLoc().line,
std::vector<spv::Id>(), // main function has no param
std::vector<char const*>());
builder.setupFunctionDebugInfo(shaderEntry, glslangIntermediate->getEntryPointMangledName().c_str(),
std::vector<spv::Id>(), // main function has no param
std::vector<char const*>());
}
continue;
}
@ -5576,8 +5605,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()),
glslFunction->getName().c_str(), convertGlslangLinkageToSpv(glslFunction->getLinkType()), paramTypes,
paramDecorations, &functionBlock);
builder.setupDebugFunctionEntry(function, glslFunction->getName().c_str(), glslFunction->getLoc().line,
paramTypes, paramNames);
builder.setupFunctionDebugInfo(function, glslFunction->getName().c_str(), paramTypes, paramNames);
if (implicitThis)
function->setImplicitThis();
@ -6441,6 +6469,9 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
}
}
// Reset source location to the function call location after argument evaluation
builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
// 2. Allocate space for anything needing a copy, and if it's "in" or "inout"
// copy the original into that space.
//
@ -10280,7 +10311,7 @@ spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name)
}
}
}; // end anonymous namespace
} // end anonymous namespace
namespace glslang {
@ -10417,4 +10448,4 @@ void GlslangToSpv(const TIntermediate& intermediate, std::vector<unsigned int>&
GetThreadPoolAllocator().pop();
}
}; // end namespace glslang
} // end namespace glslang

View file

@ -39,6 +39,7 @@
#include <vector>
#include "Logger.h"
#include "glslang/Include/visibility.h"
namespace glslang {
class TIntermediate;
@ -53,15 +54,16 @@ struct SpvOptions {
bool emitNonSemanticShaderDebugInfo {false};
bool emitNonSemanticShaderDebugSource{ false };
bool compileOnly{false};
bool optimizerAllowExpandedIDBound{false};
};
void GetSpirvVersion(std::string&);
int GetSpirvGeneratorVersion();
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
SpvOptions* options = nullptr);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
bool OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
bool OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
GLSLANG_EXPORT void GetSpirvVersion(std::string&);
GLSLANG_EXPORT int GetSpirvGeneratorVersion();
GLSLANG_EXPORT void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
SpvOptions* options = nullptr);
GLSLANG_EXPORT void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
GLSLANG_EXPORT bool OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
GLSLANG_EXPORT bool OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
}

View file

@ -37,12 +37,13 @@
#include <string>
#include <vector>
#include "glslang/Include/visibility.h"
namespace spv {
// A class for holding all SPIR-V build status messages, including
// missing/TBD functionalities, warnings, and errors.
class SpvBuildLogger {
class GLSLANG_EXPORT SpvBuildLogger {
public:
SpvBuildLogger() {}

View file

@ -38,7 +38,6 @@
#include <algorithm>
#include <cassert>
#include "../glslang/Include/Common.h"
namespace spv {

View file

@ -41,6 +41,21 @@
#include <cstdlib>
#include <exception>
#ifdef GLSLANG_IS_SHARED_LIBRARY
#ifdef _WIN32
#ifdef GLSLANG_EXPORTING
#define GLSLANG_EXPORT __declspec(dllexport)
#else
#define GLSLANG_EXPORT __declspec(dllimport)
#endif
#elif __GNUC__ >= 4
#define GLSLANG_EXPORT __attribute__((visibility("default")))
#endif
#endif // GLSLANG_IS_SHARED_LIBRARY
#ifndef GLSLANG_EXPORT
#define GLSLANG_EXPORT
#endif
namespace spv {
class spirvbin_base_t
@ -79,10 +94,11 @@ public:
#include "spirv.hpp"
namespace spv {
const Id NoResult = 0;
static inline constexpr Id NoResult = 0;
// class to hold SPIR-V binary data for remapping, DCE, and debug stripping
class spirvbin_t : public spirvbin_base_t
class GLSLANG_EXPORT spirvbin_t : public spirvbin_base_t
{
public:
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false)

View file

@ -439,6 +439,43 @@ Id Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id col
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
if (emitNonSemanticShaderDebugInfo)
{
// Find a name for one of the parameters. It can either come from debuginfo for another
// type, or an OpName from a constant.
auto const findName = [&](Id id) {
Id id2 = debugId[id];
for (auto &t : groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic]) {
if (t->getResultId() == id2) {
for (auto &s : strings) {
if (s->getResultId() == t->getIdOperand(2)) {
return s->getNameString();
}
}
}
}
for (auto &t : names) {
if (t->getIdOperand(0) == id) {
return t->getNameString();
}
}
return "unknown";
};
std::string debugName = "coopmat<";
debugName += std::string(findName(component)) + ", ";
if (isConstantScalar(scope)) {
debugName += std::string("gl_Scope") + std::string(spv::ScopeToString((spv::Scope)getConstantScalar(scope))) + ", ";
} else {
debugName += std::string(findName(scope)) + ", ";
}
debugName += std::string(findName(rows)) + ", ";
debugName += std::string(findName(cols)) + ">";
// There's no nonsemantic debug info instruction for cooperative matrix types,
// use opaque composite instead.
auto const debugResultId = makeCompositeDebugType({}, debugName.c_str(), NonSemanticShaderDebugInfo100Structure, true);
debugId[type->getResultId()] = debugResultId;
}
return type->getResultId();
}
@ -1312,7 +1349,7 @@ Op Builder::getMostBasicTypeClass(Id typeId) const
}
}
int Builder::getNumTypeConstituents(Id typeId) const
unsigned int Builder::getNumTypeConstituents(Id typeId) const
{
Instruction* instr = module.getInstruction(typeId);
@ -1979,7 +2016,7 @@ void Builder::addDecoration(Id id, Decoration decoration, int num)
if (num >= 0)
dec->addImmediateOperand(num);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const char* s)
@ -1993,7 +2030,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
dec->addImmediateOperand(decoration);
dec->addStringOperand(s);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsigned>& literals)
@ -2008,7 +2045,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsi
for (auto literal : literals)
dec->addImmediateOperand(literal);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<const char*>& strings)
@ -2023,7 +2060,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const std::vector<cons
for (auto string : strings)
dec->addStringOperand(string);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType) {
@ -2034,7 +2071,7 @@ void Builder::addLinkageDecoration(Id id, const char* name, spv::LinkageType lin
dec->addStringOperand(name);
dec->addImmediateOperand(linkType);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
@ -2048,7 +2085,7 @@ void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
dec->addImmediateOperand(decoration);
dec->addIdOperand(idDecoration);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id>& operandIds)
@ -2064,7 +2101,7 @@ void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id
for (auto operandId : operandIds)
dec->addIdOperand(operandId);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
@ -2080,7 +2117,7 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
if (num >= 0)
dec->addImmediateOperand(num);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s)
@ -2095,7 +2132,7 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
dec->addImmediateOperand(decoration);
dec->addStringOperand(s);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<unsigned>& literals)
@ -2111,7 +2148,7 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
for (auto literal : literals)
dec->addImmediateOperand(literal);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<const char*>& strings)
@ -2127,10 +2164,16 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
for (auto string : strings)
dec->addStringOperand(string);
decorations.push_back(std::unique_ptr<Instruction>(dec));
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addInstruction(std::unique_ptr<Instruction> inst) {
// Phis must appear first in their block, don't insert line tracking instructions
// in front of them, just add the OpPhi and return.
if (inst->getOpCode() == OpPhi) {
buildPoint->addInstruction(std::move(inst));
return;
}
// Optionally insert OpDebugScope
if (emitNonSemanticShaderDebugInfo && dirtyScopeTracker) {
if (buildPoint->updateDebugScope(currentDebugScopeId.top())) {
@ -2176,6 +2219,10 @@ void Builder::addInstruction(std::unique_ptr<Instruction> inst) {
buildPoint->addInstruction(std::move(inst));
}
void Builder::addInstructionNoDebugInfo(std::unique_ptr<Instruction> inst) {
buildPoint->addInstruction(std::move(inst));
}
// Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint)
{
@ -2236,14 +2283,13 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
return function;
}
void Builder::setupDebugFunctionEntry(Function* function, const char* name, int line, const std::vector<Id>& paramTypes,
const std::vector<char const*>& paramNames)
void Builder::setupFunctionDebugInfo(Function* function, const char* name, const std::vector<Id>& paramTypes,
const std::vector<char const*>& paramNames)
{
if (!emitNonSemanticShaderDebugInfo)
return;
currentLine = line;
Id nameId = getStringId(unmangleFunctionName(name));
Id funcTypeId = function->getFuncTypeId();
assert(debugId[funcTypeId] != 0);
@ -2315,7 +2361,7 @@ Id Builder::makeDebugFunction([[maybe_unused]] Function* function, Id nameId, Id
return funcId;
}
Id Builder::makeDebugLexicalBlock(uint32_t line) {
Id Builder::makeDebugLexicalBlock(uint32_t line, uint32_t column) {
assert(!currentDebugScopeId.empty());
Id lexId = getUniqueId();
@ -2325,7 +2371,7 @@ Id Builder::makeDebugLexicalBlock(uint32_t line) {
lex->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLexicalBlock);
lex->addIdOperand(makeDebugSource(currentFileId));
lex->addIdOperand(makeUintConstant(line));
lex->addIdOperand(makeUintConstant(0)); // column
lex->addIdOperand(makeUintConstant(column)); // column
lex->addIdOperand(currentDebugScopeId.top()); // scope
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(lex));
module.mapInstruction(lex);
@ -2358,10 +2404,14 @@ void Builder::makeReturn(bool implicit, Id retVal)
}
// Comments in header
void Builder::enterLexicalBlock(uint32_t line)
void Builder::enterLexicalBlock(uint32_t line, uint32_t column)
{
if (!emitNonSemanticShaderDebugInfo) {
return;
}
// Generate new lexical scope debug instruction
Id lexId = makeDebugLexicalBlock(line);
Id lexId = makeDebugLexicalBlock(line, column);
currentDebugScopeId.push(lexId);
dirtyScopeTracker = true;
}
@ -2369,6 +2419,10 @@ void Builder::enterLexicalBlock(uint32_t line)
// Comments in header
void Builder::leaveLexicalBlock()
{
if (!emitNonSemanticShaderDebugInfo) {
return;
}
// Pop current scope from stack and clear current scope
currentDebugScopeId.pop();
dirtyScopeTracker = true;
@ -2924,7 +2978,7 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
swizzle->reserveOperands(2);
swizzle->addIdOperand(target);
assert(getNumComponents(source) == (int)channels.size());
assert(getNumComponents(source) == channels.size());
assert(isVector(source));
swizzle->addIdOperand(source);
@ -3371,7 +3425,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
{
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
getNumTypeConstituents(typeId) == (int)constituents.size()));
getNumTypeConstituents(typeId) == constituents.size()));
if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be
@ -3424,6 +3478,12 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1)
return smearScalar(precision, sources[0], resultTypeId);
// Special case: 2 vectors of equal size
if (sources.size() == 1 && isVector(sources[0]) && numTargetComponents == getNumComponents(sources[0])) {
assert(resultTypeId == getTypeId(sources[0]));
return sources[0];
}
// accumulate the arguments for OpCompositeConstruct
std::vector<Id> constituents;
Id scalarTypeId = getScalarTypeId(resultTypeId);
@ -3458,8 +3518,8 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
if (sourcesToUse + targetComponent > numTargetComponents)
sourcesToUse = numTargetComponents - targetComponent;
int col = 0;
int row = 0;
unsigned int col = 0;
unsigned int row = 0;
for (unsigned int s = 0; s < sourcesToUse; ++s) {
if (row >= getNumRows(sourceArg)) {
row = 0;
@ -3504,8 +3564,8 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
{
Id componentTypeId = getScalarTypeId(resultTypeId);
int numCols = getTypeNumColumns(resultTypeId);
int numRows = getTypeNumRows(resultTypeId);
unsigned int numCols = getTypeNumColumns(resultTypeId);
unsigned int numRows = getTypeNumRows(resultTypeId);
Instruction* instr = module.getInstruction(componentTypeId);
const unsigned bitCount = instr->getImmediateOperand(0);
@ -3520,11 +3580,11 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
Id sourceColumnTypeId = getContainedTypeId(getTypeId(matrix));
std::vector<unsigned> channels;
for (int row = 0; row < numRows; ++row)
for (unsigned int row = 0; row < numRows; ++row)
channels.push_back(row);
std::vector<Id> matrixColumns;
for (int col = 0; col < numCols; ++col) {
for (unsigned int col = 0; col < numCols; ++col) {
std::vector<unsigned> indexes;
indexes.push_back(col);
Id colv = createCompositeExtract(matrix, sourceColumnTypeId, indexes);
@ -3542,7 +3602,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
// Detect a matrix being constructed from a repeated vector of the correct size.
// Create the composite directly from it.
if ((int)sources.size() == numCols && isVector(sources[0]) && getNumComponents(sources[0]) == numRows &&
if (sources.size() == numCols && isVector(sources[0]) && getNumComponents(sources[0]) == numRows &&
std::equal(sources.begin() + 1, sources.end(), sources.begin())) {
return setPrecision(createCompositeConstruct(resultTypeId, sources), precision);
}
@ -3574,12 +3634,12 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
} else if (isMatrix(sources[0])) {
// constructing from another matrix; copy over the parts that exist in both the argument and constructee
Id matrix = sources[0];
int minCols = std::min(numCols, getNumColumns(matrix));
int minRows = std::min(numRows, getNumRows(matrix));
for (int col = 0; col < minCols; ++col) {
unsigned int minCols = std::min(numCols, getNumColumns(matrix));
unsigned int minRows = std::min(numRows, getNumRows(matrix));
for (unsigned int col = 0; col < minCols; ++col) {
std::vector<unsigned> indexes;
indexes.push_back(col);
for (int row = 0; row < minRows; ++row) {
for (unsigned int row = 0; row < minRows; ++row) {
indexes.push_back(row);
ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes);
indexes.pop_back();
@ -3588,12 +3648,12 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
}
} else {
// fill in the matrix in column-major order with whatever argument components are available
int row = 0;
int col = 0;
unsigned int row = 0;
unsigned int col = 0;
for (int arg = 0; arg < (int)sources.size() && col < numCols; ++arg) {
for (unsigned int arg = 0; arg < sources.size() && col < numCols; ++arg) {
Id argComp = sources[arg];
for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
for (unsigned int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
if (getNumComponents(sources[arg]) > 1) {
argComp = createCompositeExtract(sources[arg], componentTypeId, comp);
setPrecision(argComp, precision);
@ -3617,9 +3677,9 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
// make the column vectors
Id columnTypeId = getContainedTypeId(resultTypeId);
std::vector<Id> matrixColumns;
for (int col = 0; col < numCols; ++col) {
for (unsigned int col = 0; col < numCols; ++col) {
std::vector<Id> vectorComponents;
for (int row = 0; row < numRows; ++row)
for (unsigned int row = 0; row < numRows; ++row)
vectorComponents.push_back(ids[col][row]);
Id column = createCompositeConstruct(columnTypeId, vectorComponents);
setPrecision(column, precision);
@ -3648,6 +3708,7 @@ Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) :
// Save the current block, so that we can add in the flow control split when
// makeEndIf is called.
headerBlock = builder.getBuildPoint();
builder.createSelectionMerge(mergeBlock, control);
function->addBlock(thenBlock);
builder.setBuildPoint(thenBlock);
@ -3657,7 +3718,7 @@ Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) :
void Builder::If::makeBeginElse()
{
// Close out the "then" by having it jump to the mergeBlock
builder.createBranch(mergeBlock);
builder.createBranch(true, mergeBlock);
// Make the first else block and add it to the function
elseBlock = new Block(builder.getUniqueId(), *function);
@ -3671,11 +3732,10 @@ void Builder::If::makeBeginElse()
void Builder::If::makeEndIf()
{
// jump to the merge block
builder.createBranch(mergeBlock);
builder.createBranch(true, mergeBlock);
// Go back to the headerBlock and make the flow control split
builder.setBuildPoint(headerBlock);
builder.createSelectionMerge(mergeBlock, control);
if (elseBlock)
builder.createConditionalBranch(condition, thenBlock, elseBlock);
else
@ -3721,10 +3781,10 @@ void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, con
}
// Comments in header
void Builder::addSwitchBreak()
void Builder::addSwitchBreak(bool implicit)
{
// branch to the top of the merge block stack
createBranch(switchMerges.top());
createBranch(implicit, switchMerges.top());
createAndSetNoPredecessorBlock("post-switch-break");
}
@ -3735,7 +3795,7 @@ void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegme
if (lastSegment >= 0) {
// Close out previous segment by jumping, if necessary, to next segment
if (! buildPoint->isTerminated())
createBranch(segmentBlock[nextSegment]);
createBranch(true, segmentBlock[nextSegment]);
}
Block* block = segmentBlock[nextSegment];
block->getParent().addBlock(block);
@ -3747,7 +3807,7 @@ void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
{
// Close out previous segment by jumping, if necessary, to next segment
if (! buildPoint->isTerminated())
addSwitchBreak();
addSwitchBreak(true);
switchMerges.top()->getParent().addBlock(switchMerges.top());
setBuildPoint(switchMerges.top());
@ -3780,14 +3840,14 @@ Builder::LoopBlocks& Builder::makeNewLoop()
void Builder::createLoopContinue()
{
createBranch(&loops.top().continue_target);
createBranch(false, &loops.top().continue_target);
// Set up a block for dead code.
createAndSetNoPredecessorBlock("post-loop-continue");
}
void Builder::createLoopExit()
{
createBranch(&loops.top().merge);
createBranch(false, &loops.top().merge);
// Set up a block for dead code.
createAndSetNoPredecessorBlock("post-loop-break");
}
@ -3846,7 +3906,7 @@ void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAcce
// If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores.
if (accessChain.swizzle.size() > 0 &&
getNumTypeComponents(getResultingAccessChainType()) != (int)accessChain.swizzle.size() &&
getNumTypeComponents(getResultingAccessChainType()) != accessChain.swizzle.size() &&
accessChain.component == NoResult) {
for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i]));
@ -4166,7 +4226,7 @@ void Builder::simplifyAccessChainSwizzle()
{
// If the swizzle has fewer components than the vector, it is subsetting, and must stay
// to preserve that fact.
if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size())
if (getNumTypeComponents(accessChain.preSwizzleBaseType) > accessChain.swizzle.size())
return;
// if components are out of order, it is a swizzle
@ -4229,11 +4289,16 @@ void Builder::createAndSetNoPredecessorBlock(const char* /*name*/)
}
// Comments in header
void Builder::createBranch(Block* block)
void Builder::createBranch(bool implicit, Block* block)
{
Instruction* branch = new Instruction(OpBranch);
branch->addIdOperand(block->getId());
addInstruction(std::unique_ptr<Instruction>(branch));
if (implicit) {
addInstructionNoDebugInfo(std::unique_ptr<Instruction>(branch));
}
else {
addInstruction(std::unique_ptr<Instruction>(branch));
}
block->addPredecessor(buildPoint);
}
@ -4266,7 +4331,10 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
branch->addIdOperand(condition);
branch->addIdOperand(thenBlock->getId());
branch->addIdOperand(elseBlock->getId());
addInstruction(std::unique_ptr<Instruction>(branch));
// A conditional branch is always attached to a condition expression
addInstructionNoDebugInfo(std::unique_ptr<Instruction>(branch));
thenBlock->addPredecessor(buildPoint);
elseBlock->addPredecessor(buildPoint);
}
@ -4324,11 +4392,10 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
dumpSourceInstructions(iItr->first, *iItr->second, out);
}
void Builder::dumpInstructions(std::vector<unsigned int>& out,
const std::vector<std::unique_ptr<Instruction> >& instructions) const
template <class Range> void Builder::dumpInstructions(std::vector<unsigned int>& out, const Range& instructions) const
{
for (int i = 0; i < (int)instructions.size(); ++i) {
instructions[i]->dump(out);
for (const auto& inst : instructions) {
inst->dump(out);
}
}
@ -4341,4 +4408,40 @@ void Builder::dumpModuleProcesses(std::vector<unsigned int>& out) const
}
}
bool Builder::DecorationInstructionLessThan::operator()(const std::unique_ptr<Instruction>& lhs,
const std::unique_ptr<Instruction>& rhs) const
{
// Order by the id to which the decoration applies first. This is more intuitive.
assert(lhs->isIdOperand(0) && rhs->isIdOperand(0));
if (lhs->getIdOperand(0) != rhs->getIdOperand(0)) {
return lhs->getIdOperand(0) < rhs->getIdOperand(0);
}
if (lhs->getOpCode() != rhs->getOpCode())
return lhs->getOpCode() < rhs->getOpCode();
// Now compare the operands.
int minSize = std::min(lhs->getNumOperands(), rhs->getNumOperands());
for (int i = 1; i < minSize; ++i) {
if (lhs->isIdOperand(i) != rhs->isIdOperand(i)) {
return lhs->isIdOperand(i) < rhs->isIdOperand(i);
}
if (lhs->isIdOperand(i)) {
if (lhs->getIdOperand(i) != rhs->getIdOperand(i)) {
return lhs->getIdOperand(i) < rhs->getIdOperand(i);
}
} else {
if (lhs->getImmediateOperand(i) != rhs->getImmediateOperand(i)) {
return lhs->getImmediateOperand(i) < rhs->getImmediateOperand(i);
}
}
}
if (lhs->getNumOperands() != rhs->getNumOperands())
return lhs->getNumOperands() < rhs->getNumOperands();
// In this case they are equal.
return false;
}
} // end spv namespace

View file

@ -48,6 +48,7 @@
#define SpvBuilder_H
#include "Logger.h"
#define SPV_ENABLE_UTILITY_CODE
#include "spirv.hpp"
#include "spvIR.h"
namespace spv {
@ -56,6 +57,7 @@ namespace spv {
}
#include <algorithm>
#include <cstdint>
#include <map>
#include <memory>
#include <set>
@ -107,7 +109,7 @@ public:
spv::Id getMainFileId() const { return mainFileId; }
// Initialize the main source file name
void setDebugSourceFile(const std::string& file)
void setDebugMainSourceFile(const std::string& file)
{
if (trackDebugInfo) {
dirtyLineTracker = true;
@ -245,11 +247,14 @@ public:
Id makeDebugValue(Id const debugLocalVariable, Id const value);
Id makeDebugFunctionType(Id returnType, const std::vector<Id>& paramTypes);
Id makeDebugFunction(Function* function, Id nameId, Id funcTypeId);
Id makeDebugLexicalBlock(uint32_t line);
Id makeDebugLexicalBlock(uint32_t line, uint32_t column);
std::string unmangleFunctionName(std::string const& name) const;
void setupDebugFunctionEntry(Function* function, const char* name, int line,
const std::vector<Id>& paramTypes,
const std::vector<char const*>& paramNames);
// Initialize non-semantic debug information for a function, including those of:
// - The function definition
// - The function parameters
void setupFunctionDebugInfo(Function* function, const char* name, const std::vector<Id>& paramTypes,
const std::vector<char const*>& paramNames);
// accelerationStructureNV type
Id makeAccelerationStructureType();
@ -264,9 +269,9 @@ public:
Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
Op getMostBasicTypeClass(Id typeId) const;
int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
int getNumTypeConstituents(Id typeId) const;
int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
unsigned int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
unsigned int getNumTypeConstituents(Id typeId) const;
unsigned int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
Id getScalarTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId, int) const;
@ -334,18 +339,18 @@ public:
return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
}
int getTypeNumColumns(Id typeId) const
unsigned int getTypeNumColumns(Id typeId) const
{
assert(isMatrixType(typeId));
return getNumTypeConstituents(typeId);
}
int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
int getTypeNumRows(Id typeId) const
unsigned int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
unsigned int getTypeNumRows(Id typeId) const
{
assert(isMatrixType(typeId));
return getNumTypeComponents(getContainedTypeId(typeId));
}
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
unsigned int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
Dim getTypeDimensionality(Id typeId) const
{
@ -416,8 +421,7 @@ public:
// Also reset current last DebugScope and current source line to unknown
void setBuildPoint(Block* bp) {
buildPoint = bp;
// TODO: Technically, change of build point should set line tracker dirty. But we'll have bad line info for
// branch instructions. Commenting this for now because at least this matches the old behavior.
dirtyLineTracker = true;
dirtyScopeTracker = true;
}
Block* getBuildPoint() const { return buildPoint; }
@ -426,6 +430,11 @@ public:
// Optionally, additional debug info instructions may also be prepended.
void addInstruction(std::unique_ptr<Instruction> inst);
// Append an instruction to the end of the current build point without prepending any debug instructions.
// This is useful for insertion of some debug info instructions themselves or some control flow instructions
// that are attached to its predecessor instruction.
void addInstructionNoDebugInfo(std::unique_ptr<Instruction> inst);
// Make the entry-point function. The returned pointer is only valid
// for the lifetime of this builder.
Function* makeEntryPoint(const char*);
@ -442,7 +451,7 @@ public:
void makeReturn(bool implicit, Id retVal = 0);
// Initialize state and generate instructions for new lexical scope
void enterLexicalBlock(uint32_t line);
void enterLexicalBlock(uint32_t line, uint32_t column);
// Set state and generate instructions to exit current lexical scope
void leaveLexicalBlock();
@ -639,7 +648,7 @@ public:
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
// Add a branch to the innermost switch's merge block.
void addSwitchBreak();
void addSwitchBreak(bool implicit);
// Move to the next code segment, passing in the return argument in makeSwitch()
void nextSwitchSegment(std::vector<Block*>& segmentBB, int segment);
@ -861,7 +870,9 @@ public:
void dump(std::vector<unsigned int>&) const;
void createBranch(Block* block);
// Add a branch to the target block.
// If set implicit, the branch instruction shouldn't have debug source location.
void createBranch(bool implicit, Block* block);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
const std::vector<unsigned int>& operands);
@ -890,10 +901,13 @@ public:
void createSelectionMerge(Block* mergeBlock, unsigned int control);
void dumpSourceInstructions(std::vector<unsigned int>&) const;
void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
template <class Range> void dumpInstructions(std::vector<unsigned int>& out, const Range& instructions) const;
void dumpModuleProcesses(std::vector<unsigned int>&) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const;
struct DecorationInstructionLessThan {
bool operator()(const std::unique_ptr<Instruction>& lhs, const std::unique_ptr<Instruction>& rhs) const;
};
unsigned int spvVersion; // the version of SPIR-V to emit in the header
SourceLanguage sourceLang;
@ -950,7 +964,7 @@ public:
std::vector<std::unique_ptr<Instruction> > entryPoints;
std::vector<std::unique_ptr<Instruction> > executionModes;
std::vector<std::unique_ptr<Instruction> > names;
std::vector<std::unique_ptr<Instruction> > decorations;
std::set<std::unique_ptr<Instruction>, DecorationInstructionLessThan> decorations;
std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
std::vector<std::unique_ptr<Instruction> > externals;
std::vector<std::unique_ptr<Function> > functions;
@ -990,6 +1004,6 @@ public:
SpvBuildLogger* logger;
}; // end Builder class
}; // end spv namespace
} // end spv namespace
#endif // SpvBuilder_H

View file

@ -387,12 +387,14 @@ void Builder::postProcessCFG()
}
// Remove unneeded decorations, for unreachable instructions
decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
[&unreachableDefinitions](std::unique_ptr<Instruction>& I) -> bool {
Id decoration_id = I.get()->getIdOperand(0);
return unreachableDefinitions.count(decoration_id) != 0;
}),
decorations.end());
for (auto decorationIter = decorations.begin(); decorationIter != decorations.end();) {
Id decorationId = (*decorationIter)->getIdOperand(0);
if (unreachableDefinitions.count(decorationId) != 0) {
decorationIter = decorations.erase(decorationIter);
} else {
++decorationIter;
}
}
}
// comment in header
@ -546,4 +548,4 @@ void Builder::postProcess(bool compileOnly)
postProcessSamplers();
}
}; // end spv namespace
} // end spv namespace

View file

@ -44,6 +44,7 @@
#include "SpvTools.h"
#include "spirv-tools/optimizer.hpp"
#include "glslang/MachineIndependent/localintermediate.h"
namespace glslang {
@ -81,6 +82,11 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
}
spv_target_env MapToSpirvToolsEnv(const glslang::TIntermediate& intermediate, spv::SpvBuildLogger* logger)
{
return MapToSpirvToolsEnv(intermediate.getSpv(), logger);
}
// Callback passed to spvtools::Optimizer::SetMessageConsumer
void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
const spv_position_t &position, const char *message)
@ -218,9 +224,20 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
spvtools::OptimizerOptions spvOptOptions;
if (options->optimizerAllowExpandedIDBound)
spvOptOptions.set_max_id_bound(0x3FFFFFFF);
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
if (options->optimizerAllowExpandedIDBound) {
if (spirv.size() > 3 && spirv[3] > kDefaultMaxIdBound) {
spvtools::Optimizer optimizer2(target_env);
optimizer2.SetMessageConsumer(OptimizerMesssageConsumer);
optimizer2.RegisterPass(spvtools::CreateCompactIdsPass());
optimizer2.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}
}
}
bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector<unsigned int>& spirv,
@ -292,6 +309,6 @@ void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}
}; // end namespace glslang
} // end namespace glslang
#endif

View file

@ -44,10 +44,12 @@
#if ENABLE_OPT
#include <vector>
#include <ostream>
#include <unordered_set>
#include "spirv-tools/libspirv.h"
#endif
#include "glslang/MachineIndependent/localintermediate.h"
#include "glslang/MachineIndependent/Versions.h"
#include "glslang/Include/visibility.h"
#include "GlslangToSpv.h"
#include "Logger.h"
@ -55,45 +57,50 @@ namespace glslang {
#if ENABLE_OPT
class TIntermediate;
// Translate glslang's view of target versioning to what SPIRV-Tools uses.
spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger);
GLSLANG_EXPORT spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger);
GLSLANG_EXPORT spv_target_env MapToSpirvToolsEnv(const glslang::TIntermediate& intermediate, spv::SpvBuildLogger* logger);
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
GLSLANG_EXPORT void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
spv_target_env requested_context);
GLSLANG_EXPORT void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
spv_target_env requested_context);
// Apply the SPIRV-Tools validator to generated SPIR-V.
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, bool prelegalization);
GLSLANG_EXPORT void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, bool prelegalization);
// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions*);
GLSLANG_EXPORT void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions*);
// Apply the SPIRV-Tools EliminateDeadInputComponents pass to generated SPIR-V. Put result in |spirv|.
void SpirvToolsEliminateDeadInputComponents(spv_target_env target_env, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*);
GLSLANG_EXPORT void SpirvToolsEliminateDeadInputComponents(spv_target_env target_env, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*);
// Apply the SPIRV-Tools AnalyzeDeadOutputStores pass to generated SPIR-V. Put result in |live_locs|.
// Return true if the result is valid.
bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector<unsigned int>& spirv,
std::unordered_set<uint32_t>* live_locs,
std::unordered_set<uint32_t>* live_builtins, spv::SpvBuildLogger*);
GLSLANG_EXPORT bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector<unsigned int>& spirv,
std::unordered_set<uint32_t>* live_locs,
std::unordered_set<uint32_t>* live_builtins,
spv::SpvBuildLogger*);
// Apply the SPIRV-Tools EliminateDeadOutputStores and AggressiveDeadCodeElimination passes to generated SPIR-V using
// |live_locs|. Put result in |spirv|.
void SpirvToolsEliminateDeadOutputStores(spv_target_env target_env, std::vector<unsigned int>& spirv,
std::unordered_set<uint32_t>* live_locs,
std::unordered_set<uint32_t>* live_builtins, spv::SpvBuildLogger*);
GLSLANG_EXPORT void SpirvToolsEliminateDeadOutputStores(spv_target_env target_env, std::vector<unsigned int>& spirv,
std::unordered_set<uint32_t>* live_locs,
std::unordered_set<uint32_t>* live_builtins,
spv::SpvBuildLogger*);
// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
// optimization is disabled.
void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
GLSLANG_EXPORT void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
#endif

View file

@ -825,4 +825,4 @@ void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
SpirvStream.processInstructions();
}
}; // end namespace spv
} // end namespace spv

View file

@ -43,10 +43,12 @@
#include <iostream>
#include <vector>
#include "glslang/Include/visibility.h"
namespace spv {
// disassemble with glslang custom disassembler
void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
GLSLANG_EXPORT void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
} // end namespace spv

2
SPIRV/doc.cpp Executable file → Normal file
View file

@ -3491,4 +3491,4 @@ void Parameterize()
});
}
}; // end spv namespace
} // end spv namespace

View file

@ -385,7 +385,7 @@ enum ImageOperandsShift {
ImageOperandsMax = 0x7fffffff,
};
enum ImageOperandsMask {
enum ImageOperandsMask : unsigned {
ImageOperandsMaskNone = 0,
ImageOperandsBiasMask = 0x00000001,
ImageOperandsLodMask = 0x00000002,
@ -420,7 +420,7 @@ enum FPFastMathModeShift {
FPFastMathModeMax = 0x7fffffff,
};
enum FPFastMathModeMask {
enum FPFastMathModeMask : unsigned {
FPFastMathModeMaskNone = 0,
FPFastMathModeNotNaNMask = 0x00000001,
FPFastMathModeNotInfMask = 0x00000002,
@ -745,7 +745,7 @@ enum SelectionControlShift {
SelectionControlMax = 0x7fffffff,
};
enum SelectionControlMask {
enum SelectionControlMask : unsigned {
SelectionControlMaskNone = 0,
SelectionControlFlattenMask = 0x00000001,
SelectionControlDontFlattenMask = 0x00000002,
@ -774,7 +774,7 @@ enum LoopControlShift {
LoopControlMax = 0x7fffffff,
};
enum LoopControlMask {
enum LoopControlMask : unsigned {
LoopControlMaskNone = 0,
LoopControlUnrollMask = 0x00000001,
LoopControlDontUnrollMask = 0x00000002,
@ -806,7 +806,7 @@ enum FunctionControlShift {
FunctionControlMax = 0x7fffffff,
};
enum FunctionControlMask {
enum FunctionControlMask : unsigned {
FunctionControlMaskNone = 0,
FunctionControlInlineMask = 0x00000001,
FunctionControlDontInlineMask = 0x00000002,
@ -836,7 +836,7 @@ enum MemorySemanticsShift {
MemorySemanticsMax = 0x7fffffff,
};
enum MemorySemanticsMask {
enum MemorySemanticsMask : unsigned {
MemorySemanticsMaskNone = 0,
MemorySemanticsAcquireMask = 0x00000002,
MemorySemanticsReleaseMask = 0x00000004,
@ -872,7 +872,7 @@ enum MemoryAccessShift {
MemoryAccessMax = 0x7fffffff,
};
enum MemoryAccessMask {
enum MemoryAccessMask : unsigned {
MemoryAccessMaskNone = 0,
MemoryAccessVolatileMask = 0x00000001,
MemoryAccessAlignedMask = 0x00000002,
@ -922,7 +922,7 @@ enum KernelProfilingInfoShift {
KernelProfilingInfoMax = 0x7fffffff,
};
enum KernelProfilingInfoMask {
enum KernelProfilingInfoMask : unsigned {
KernelProfilingInfoMaskNone = 0,
KernelProfilingInfoCmdExecTimeMask = 0x00000001,
};
@ -1163,7 +1163,7 @@ enum Capability {
CapabilityDotProduct = 6019,
CapabilityDotProductKHR = 6019,
CapabilityRayCullMaskKHR = 6020,
CapabilityCooperativeMatrixKHR = 6022,
CapabilityCooperativeMatrixKHR = 6022,
CapabilityReplicatedCompositesEXT = 6024,
CapabilityBitInstructions = 6025,
CapabilityGroupNonUniformRotateKHR = 6026,
@ -1194,7 +1194,7 @@ enum RayFlagsShift {
RayFlagsMax = 0x7fffffff,
};
enum RayFlagsMask {
enum RayFlagsMask : unsigned {
RayFlagsMaskNone = 0,
RayFlagsOpaqueKHRMask = 0x00000001,
RayFlagsNoOpaqueKHRMask = 0x00000002,
@ -1236,7 +1236,7 @@ enum FragmentShadingRateShift {
FragmentShadingRateMax = 0x7fffffff,
};
enum FragmentShadingRateMask {
enum FragmentShadingRateMask : unsigned {
FragmentShadingRateMaskNone = 0,
FragmentShadingRateVertical2PixelsMask = 0x00000001,
FragmentShadingRateVertical4PixelsMask = 0x00000002,
@ -1291,7 +1291,7 @@ enum CooperativeMatrixOperandsShift {
CooperativeMatrixOperandsMax = 0x7fffffff,
};
enum CooperativeMatrixOperandsMask {
enum CooperativeMatrixOperandsMask : unsigned {
CooperativeMatrixOperandsMaskNone = 0,
CooperativeMatrixOperandsMatrixASignedComponentsKHRMask = 0x00000001,
CooperativeMatrixOperandsMatrixBSignedComponentsKHRMask = 0x00000002,
@ -1693,9 +1693,9 @@ enum Op {
OpCooperativeMatrixLoadKHR = 4457,
OpCooperativeMatrixStoreKHR = 4458,
OpCooperativeMatrixMulAddKHR = 4459,
OpCooperativeMatrixLengthKHR = 4460,
OpConstantCompositeReplicateEXT = 4461,
OpSpecConstantCompositeReplicateEXT = 4462,
OpCooperativeMatrixLengthKHR = 4460,
OpConstantCompositeReplicateEXT = 4461,
OpSpecConstantCompositeReplicateEXT = 4462,
OpCompositeConstructReplicateEXT = 4463,
OpTypeRayQueryKHR = 4472,
OpRayQueryInitializeKHR = 4473,
@ -2426,9 +2426,9 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpCooperativeMatrixLoadKHR: *hasResult = true; *hasResultType = true; break;
case OpCooperativeMatrixStoreKHR: *hasResult = false; *hasResultType = false; break;
case OpCooperativeMatrixMulAddKHR: *hasResult = true; *hasResultType = true; break;
case OpCooperativeMatrixLengthKHR: *hasResult = true; *hasResultType = true; break;
case OpConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break;
case OpSpecConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break;
case OpCooperativeMatrixLengthKHR: *hasResult = true; *hasResultType = true; break;
case OpConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break;
case OpSpecConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break;
case OpCompositeConstructReplicateEXT: *hasResult = true; *hasResultType = true; break;
case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
@ -2772,6 +2772,20 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpGroupLogicalXorKHR: *hasResult = true; *hasResultType = true; break;
}
}
inline const char* ScopeToString(Scope value) {
switch (value) {
case ScopeCrossDevice: return "CrossDevice";
case ScopeDevice: return "Device";
case ScopeWorkgroup: return "Workgroup";
case ScopeSubgroup: return "Subgroup";
case ScopeInvocation: return "Invocation";
case ScopeQueueFamily: return "QueueFamily";
case ScopeShaderCallKHR: return "ShaderCallKHR";
default: return "Unknown";
}
}
#endif /* SPV_ENABLE_UTILITY_CODE */
// Overload bitwise operators for mask bit combining

View file

@ -189,6 +189,15 @@ public:
out.push_back(operands[op]);
}
const char *getNameString() const {
if (opCode == OpString) {
return (const char *)&operands[0];
} else {
assert(opCode == OpName);
return (const char *)&operands[1];
}
}
protected:
Instruction(const Instruction&);
Id resultId;