Updated glslang.

This commit is contained in:
Бранимир Караџић 2024-08-30 20:20:38 -07:00
parent 0c26b42851
commit cb50d2873f
40 changed files with 698 additions and 327 deletions

View File

@ -32,6 +32,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"

44
3rdparty/glslang/SPIRV/GlslangToSpv.cpp vendored Executable file → Normal file
View File

@ -4372,7 +4372,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.
@ -5404,13 +5411,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 +5528,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 +5590,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 +6454,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.
//

View File

@ -53,6 +53,7 @@ struct SpvOptions {
bool emitNonSemanticShaderDebugInfo {false};
bool emitNonSemanticShaderDebugSource{ false };
bool compileOnly{false};
bool optimizerAllowExpandedIDBound{false};
};
void GetSpirvVersion(std::string&);

View File

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

View File

@ -79,7 +79,8 @@ 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

View File

@ -1312,7 +1312,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 +1979,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 +1993,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 +2008,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 +2023,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 +2034,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 +2048,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 +2064,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 +2080,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 +2095,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 +2111,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 +2127,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())) {
@ -2236,14 +2242,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);
@ -2924,7 +2929,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 +3376,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 +3429,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 +3469,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 +3515,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 +3531,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 +3553,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 +3585,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 +3599,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 +3628,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);
@ -3846,7 +3857,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 +4177,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
@ -4324,11 +4335,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 +4351,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

@ -56,6 +56,7 @@ namespace spv {
}
#include <algorithm>
#include <cstdint>
#include <map>
#include <memory>
#include <set>
@ -247,9 +248,12 @@ public:
Id makeDebugFunction(Function* function, Id nameId, Id funcTypeId);
Id makeDebugLexicalBlock(uint32_t line);
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 +268,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 +338,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
{
@ -890,10 +894,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 +957,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;

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

View File

@ -44,6 +44,7 @@
#include "SpvTools.h"
#include "spirv-tools/optimizer.hpp"
#include "glslang/MachineIndependent/localintermediate.h"
namespace glslang {
@ -218,9 +219,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,

View File

@ -44,10 +44,11 @@
#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 "GlslangToSpv.h"
#include "Logger.h"
@ -55,6 +56,8 @@ 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);

0
3rdparty/glslang/SPIRV/doc.cpp vendored Executable file → Normal file
View File

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,
};
@ -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,

View File

@ -44,12 +44,10 @@
#include "glslang/Public/ResourceLimits.h"
#include "Worklist.h"
#include "DirStackFileIncluder.h"
#include "./../glslang/Include/ShHandle.h"
#include "./../glslang/Public/ShaderLang.h"
#include "../glslang/MachineIndependent/localintermediate.h"
#include "../SPIRV/GlslangToSpv.h"
#include "../SPIRV/GLSL.std.450.h"
#include "../SPIRV/doc.h"
#include "../SPIRV/disassemble.h"
#include <array>
@ -110,6 +108,7 @@ enum TOptions : uint64_t {
EOptionInvertY = (1ull << 30),
EOptionDumpBareVersion = (1ull << 31),
EOptionCompileOnly = (1ull << 32),
EOptionDisplayErrorColumn = (1ull << 33),
};
bool targetHlslFunctionality1 = false;
bool SpvToolsDisassembler = false;
@ -898,6 +897,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
Options |= EOptionDumpVersions;
} else if (lowerword == "no-link") {
Options |= EOptionCompileOnly;
} else if (lowerword == "error-column") {
Options |= EOptionDisplayErrorColumn;
} else if (lowerword == "help") {
usage();
break;
@ -1164,6 +1165,8 @@ void SetMessageOptions(EShMessages& messages)
messages = (EShMessages)(messages | EShMsgEnhanced);
if (AbsolutePath)
messages = (EShMessages)(messages | EShMsgAbsolutePath);
if (Options & EOptionDisplayErrorColumn)
messages = (EShMessages)(messages | EShMsgDisplayErrorColumn);
}
//
@ -1504,6 +1507,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
std::vector<std::string> outputFiles;
#ifdef ENABLE_SPIRV
// Dump SPIR-V
if (Options & EOptionSpv) {
CompileOrLinkFailed.fetch_or(CompileFailed);
@ -1566,6 +1570,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
}
}
}
#endif
CompileOrLinkFailed.fetch_or(CompileFailed);
CompileOrLinkFailed.fetch_or(LinkFailed);
@ -1664,21 +1669,31 @@ int singleMain()
}
if (Options & EOptionDumpBareVersion) {
printf("%d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR, GLSLANG_VERSION_MINOR,
int spirvGeneratorVersion = 0;
#ifdef ENABLE_SPIRV
spirvGeneratorVersion = glslang::GetSpirvGeneratorVersion();
#endif
printf("%d:%d.%d.%d%s\n", spirvGeneratorVersion, GLSLANG_VERSION_MAJOR, GLSLANG_VERSION_MINOR,
GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR);
if (workList.empty())
return ESuccess;
} else if (Options & EOptionDumpVersions) {
printf("Glslang Version: %d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR,
int spirvGeneratorVersion = 0;
#ifdef ENABLE_SPIRV
spirvGeneratorVersion = glslang::GetSpirvGeneratorVersion();
#endif
printf("Glslang Version: %d:%d.%d.%d%s\n", spirvGeneratorVersion, GLSLANG_VERSION_MAJOR,
GLSLANG_VERSION_MINOR, GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR);
printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
std::string spirvVersion;
#if ENABLE_SPIRV
glslang::GetSpirvVersion(spirvVersion);
#endif
printf("SPIR-V Version %s\n", spirvVersion.c_str());
printf("GLSL.std.450 Version %d, Revision %d\n", GLSLstd450Version, GLSLstd450Revision);
printf("Khronos Tool ID %d\n", glslang::GetKhronosToolId());
printf("SPIR-V Generator Version %d\n", glslang::GetSpirvGeneratorVersion());
printf("SPIR-V Generator Version %d\n", spirvGeneratorVersion);
printf("GL_KHR_vulkan_glsl version %d\n", 100);
printf("ARB_GL_gl_spirv version %d\n", 100);
if (workList.empty())
@ -2024,6 +2039,7 @@ void usage()
" shaders compatible with DirectX\n"
" --invert-y | --iy invert position.Y output in vertex shader\n"
" --enhanced-msgs print more readable error messages (GLSL only)\n"
" --error-column display the column of the error along the line\n"
" --keep-uncalled | --ku don't eliminate uncalled functions\n"
" --nan-clamp favor non-NaN operand in min, max, and clamp\n"
" --no-storage-format | --nsf use Unknown image format\n"

View File

@ -35,7 +35,6 @@
#ifndef WORKLIST_H_INCLUDED
#define WORKLIST_H_INCLUDED
#include "../glslang/OSDependent/osinclude.h"
#include <list>
#include <mutex>
#include <string>

View File

@ -35,7 +35,7 @@
#define GLSLANG_BUILD_INFO
#define GLSLANG_VERSION_MAJOR 14
#define GLSLANG_VERSION_MINOR 2
#define GLSLANG_VERSION_MINOR 3
#define GLSLANG_VERSION_PATCH 0
#define GLSLANG_VERSION_FLAVOR ""

View File

@ -34,9 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StandAlone/DirStackFileIncluder.h"
#include "glslang/Public/ResourceLimits.h"
#include "glslang/Public/ShaderLang.h"
#include "glslang/Include/ShHandle.h"
#include "glslang/Include/BaseTypes.h"
#include "glslang/Include/ResourceLimits.h"
#include "glslang/Include/Types.h"
#include "glslang/MachineIndependent/iomapper.h"
#include "glslang/MachineIndependent/Versions.h"
#include "glslang/MachineIndependent/localintermediate.h"
@ -54,6 +58,7 @@ static_assert(int(GLSLANG_REFLECTION_COUNT) == EShReflectionCount, "");
static_assert(int(GLSLANG_PROFILE_COUNT) == EProfileCount, "");
static_assert(sizeof(glslang_limits_t) == sizeof(TLimits), "");
static_assert(sizeof(glslang_resource_t) == sizeof(TBuiltInResource), "");
static_assert(sizeof(glslang_version_t) == sizeof(glslang::Version), "");
typedef struct glslang_shader_s {
glslang::TShader* shader;
@ -141,6 +146,11 @@ private:
void* context;
};
GLSLANG_EXPORT void glslang_get_version(glslang_version_t* version)
{
*reinterpret_cast<glslang::Version*>(version) = glslang::GetVersion();
}
GLSLANG_EXPORT int glslang_initialize_process() { return static_cast<int>(glslang::InitializeProcess()); }
GLSLANG_EXPORT void glslang_finalize_process() { glslang::FinalizeProcess(); }
@ -205,7 +215,9 @@ static int c_shader_messages(glslang_messages_t messages)
CONVERT_MSG(GLSLANG_MSG_HLSL_LEGALIZATION_BIT, EShMsgHlslLegalization);
CONVERT_MSG(GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT, EShMsgHlslDX9Compatible);
CONVERT_MSG(GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT, EShMsgBuiltinSymbolTable);
CONVERT_MSG(GLSLANG_MSG_ENHANCED, EShMsgEnhanced);
CONVERT_MSG(GLSLANG_MSG_ABSOLUTE_PATH, EShMsgAbsolutePath);
CONVERT_MSG(GLSLANG_MSG_DISPLAY_ERROR_COLUMN, EShMsgDisplayErrorColumn);
return res;
#undef CONVERT_MSG
}
@ -368,11 +380,25 @@ GLSLANG_EXPORT void glslang_shader_set_glsl_version(glslang_shader_t* shader, in
shader->shader->setOverrideVersion(version);
}
GLSLANG_EXPORT void glslang_shader_set_default_uniform_block_set_and_binding(glslang_shader_t* shader, unsigned int set, unsigned int binding) {
shader->shader->setGlobalUniformSet(set);
shader->shader->setGlobalUniformBinding(binding);
}
GLSLANG_EXPORT void glslang_shader_set_default_uniform_block_name(glslang_shader_t* shader, const char *name) {
shader->shader->setGlobalUniformBlockName(name);
}
GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader)
{
return shader->preprocessedGLSL.c_str();
}
GLSLANG_EXPORT void glslang_shader_set_preprocessed_code(glslang_shader_t* shader, const char* code)
{
shader->preprocessedGLSL.assign(code);
}
GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input)
{
DirStackFileIncluder dirStackFileIncluder;
@ -459,6 +485,11 @@ GLSLANG_EXPORT int glslang_program_map_io(glslang_program_t* program)
return (int)program->program->mapIO();
}
GLSLANG_EXPORT int glslang_program_map_io_with_resolver_and_mapper(glslang_program_t* program, glslang_resolver_t* resolver, glslang_mapper_t* mapper)
{
return (int)program->program->mapIO(reinterpret_cast<glslang::TDefaultGlslIoResolver*>(resolver), reinterpret_cast<glslang::TGlslIoMapper*>(mapper));
}
GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program)
{
return program->program->getInfoLog();
@ -468,3 +499,30 @@ GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t*
{
return program->program->getInfoDebugLog();
}
GLSLANG_EXPORT glslang_mapper_t* glslang_glsl_mapper_create()
{
return reinterpret_cast<glslang_mapper_t*>(new glslang::TGlslIoMapper());
}
GLSLANG_EXPORT void glslang_glsl_mapper_delete(glslang_mapper_t* mapper)
{
if (!mapper)
return;
delete reinterpret_cast<glslang::TGlslIoMapper* >(mapper);
}
GLSLANG_EXPORT glslang_resolver_t* glslang_glsl_resolver_create(glslang_program_t* program, glslang_stage_t stage)
{
glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage));
return reinterpret_cast<glslang_resolver_t*>(new glslang::TDefaultGlslIoResolver(reinterpret_cast<const glslang::TIntermediate&>(*intermediate)));
}
GLSLANG_EXPORT void glslang_glsl_resolver_delete(glslang_resolver_t* resolver)
{
if (!resolver)
return;
delete reinterpret_cast<glslang::TDefaultGlslIoResolver* >(resolver);
}

View File

@ -43,8 +43,6 @@
#include "../MachineIndependent/Scan.h"
#include "../MachineIndependent/preprocessor/PpContext.h"
#include "../OSDependent/osinclude.h"
#include <algorithm>
#include <functional>
#include <cctype>
@ -6059,7 +6057,7 @@ void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fn
unaryArg = callNode.getAsUnaryNode()->getOperand();
arg0 = unaryArg;
}
const TIntermSequence& aggArgs = *argp; // only valid when unaryArg is nullptr
const TIntermSequence& aggArgs = argp ? *argp : TIntermSequence(); // only valid when unaryArg is nullptr
switch (callNode.getOp()) {
case EOpTextureGather:

View File

@ -42,8 +42,6 @@
#include "../MachineIndependent/Scan.h"
#include "../MachineIndependent/preprocessor/PpContext.h"
#include "../OSDependent/osinclude.h"
#include <algorithm>
#include <array>
#include <cctype>

0
3rdparty/glslang/glslang/Include/BaseTypes.h vendored Executable file → Normal file
View File

View File

@ -96,6 +96,11 @@ std::string to_string(const T& val) {
#pragma warning(disable : 4201) // nameless union
#endif
// Allow compilation to WASI which does not support threads yet.
#ifdef __wasi__
#define DISABLE_THREAD_SUPPORT
#endif
#include "PoolAlloc.h"
//

View File

@ -95,10 +95,14 @@ public:
default: append("UNKNOWN ERROR: "); break;
}
}
void location(const TSourceLoc& loc, bool absolute = false) {
void location(const TSourceLoc& loc, bool absolute = false, bool displayColumn = false) {
const int maxSize = 24;
char locText[maxSize];
snprintf(locText, maxSize, ":%d", loc.line);
if (displayColumn) {
snprintf(locText, maxSize, ":%d:%d", loc.line, loc.column);
} else {
snprintf(locText, maxSize, ":%d", loc.line);
}
if(loc.getFilename() == nullptr && shaderFileName != nullptr && absolute) {
append(std::filesystem::absolute(shaderFileName).string());
@ -119,9 +123,11 @@ public:
append(s);
append("\n");
}
void message(TPrefixType message, const char* s, const TSourceLoc& loc) {
void message(TPrefixType message, const char* s, const TSourceLoc& loc, bool absolute = false,
bool displayColumn = false)
{
prefix(message);
location(loc);
location(loc, absolute, displayColumn);
append(s);
append("\n");
}

View File

@ -37,9 +37,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
#include "glslang_c_shader_types.h"
#include "visibility.h"
typedef struct glslang_shader_s glslang_shader_t;
typedef struct glslang_program_s glslang_program_t;
typedef struct glslang_mapper_s glslang_mapper_t;
typedef struct glslang_resolver_s glslang_resolver_t;
/* Version counterpart */
typedef struct glslang_version_s {
int major;
int minor;
int patch;
const char* flavor;
} glslang_version_t;
/* TLimits counterpart */
typedef struct glslang_limits_s {
@ -227,27 +238,14 @@ typedef struct glslang_spv_options_s {
bool emit_nonsemantic_shader_debug_info;
bool emit_nonsemantic_shader_debug_source;
bool compile_only;
bool optimize_allow_expanded_id_bound;
} glslang_spv_options_t;
#ifdef __cplusplus
extern "C" {
#endif
#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
GLSLANG_EXPORT void glslang_get_version(glslang_version_t* version);
GLSLANG_EXPORT int glslang_initialize_process(void);
GLSLANG_EXPORT void glslang_finalize_process(void);
@ -259,9 +257,12 @@ GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glsla
GLSLANG_EXPORT void glslang_shader_shift_binding_for_set(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base, unsigned int set);
GLSLANG_EXPORT void glslang_shader_set_options(glslang_shader_t* shader, int options); // glslang_shader_options_t
GLSLANG_EXPORT void glslang_shader_set_glsl_version(glslang_shader_t* shader, int version);
GLSLANG_EXPORT void glslang_shader_set_default_uniform_block_set_and_binding(glslang_shader_t* shader, unsigned int set, unsigned int binding);
GLSLANG_EXPORT void glslang_shader_set_default_uniform_block_name(glslang_shader_t* shader, const char *name);
GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
GLSLANG_EXPORT void glslang_shader_set_preprocessed_code(glslang_shader_t* shader, const char* code);
GLSLANG_EXPORT const char* glslang_shader_get_info_log(glslang_shader_t* shader);
GLSLANG_EXPORT const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader);
@ -272,6 +273,7 @@ GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages
GLSLANG_EXPORT void glslang_program_add_source_text(glslang_program_t* program, glslang_stage_t stage, const char* text, size_t len);
GLSLANG_EXPORT void glslang_program_set_source_file(glslang_program_t* program, glslang_stage_t stage, const char* file);
GLSLANG_EXPORT int glslang_program_map_io(glslang_program_t* program);
GLSLANG_EXPORT int glslang_program_map_io_with_resolver_and_mapper(glslang_program_t* program, glslang_resolver_t* resolver, glslang_mapper_t* mapper);
GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
GLSLANG_EXPORT void glslang_program_SPIRV_generate_with_options(glslang_program_t* program, glslang_stage_t stage, glslang_spv_options_t* spv_options);
GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
@ -281,6 +283,12 @@ GLSLANG_EXPORT const char* glslang_program_SPIRV_get_messages(glslang_program_t*
GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program);
GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t* program);
GLSLANG_EXPORT glslang_mapper_t* glslang_glsl_mapper_create();
GLSLANG_EXPORT void glslang_glsl_mapper_delete(glslang_mapper_t* mapper);
GLSLANG_EXPORT glslang_resolver_t* glslang_glsl_resolver_create(glslang_program_t* program, glslang_stage_t stage);
GLSLANG_EXPORT void glslang_glsl_resolver_delete(glslang_resolver_t* resolver);
#ifdef __cplusplus
}
#endif

View File

@ -175,6 +175,7 @@ typedef enum {
GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14),
GLSLANG_MSG_ENHANCED = (1 << 15),
GLSLANG_MSG_ABSOLUTE_PATH = (1 << 16),
GLSLANG_MSG_DISPLAY_ERROR_COLUMN = (1 << 17),
LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT),
} glslang_messages_t;

View File

@ -0,0 +1,51 @@
//
// Copyright (C) 2023 LunarG, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#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

View File

@ -507,7 +507,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
case EbtInt64: {
int64_t i64val = unionArray[i].getI64Const();
newConstArray[i].setI64Const(i64val == INT64_MIN ? INT64_MIN : -i64val);
break;
}
case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
default:
return nullptr;
@ -1009,6 +1013,12 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
children[2]->getAsTyped()->getType().getVectorSize());
break;
case EOpMul:
{
TIntermConstantUnion* left = children[0]->getAsConstantUnion();
TIntermConstantUnion* right = children[1]->getAsConstantUnion();
return left->fold(EOpMul, right);
}
default:
return aggrNode;
}

0
3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp vendored Executable file → Normal file
View File

View File

@ -59,7 +59,7 @@ void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReaso
safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
infoSink.info.prefix(prefix);
infoSink.info.location(loc, messages & EShMsgAbsolutePath);
infoSink.info.location(loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
if (prefix == EPrefixError) {

View File

@ -4,6 +4,7 @@
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2017, 2019 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// Modifications Copyright (C) 2024 Ravi Prakash Singh.
//
// All rights reserved.
//
@ -41,7 +42,6 @@
#include "Initialize.h"
#include "Scan.h"
#include "../OSDependent/osinclude.h"
#include <algorithm>
#include "preprocessor/PpContext.h"
@ -3935,6 +3935,18 @@ void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, con
}
void TParseContext::hitObjectNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier)
{
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtHitObjectNV)) {
error(loc, "struct is not allowed to contain hitObjectNV:", type.getTypeName().c_str(), identifier.c_str());
} else if (type.getBasicType() == EbtHitObjectNV) {
TStorageQualifier qualifier = type.getQualifier().storage;
if (qualifier != EvqGlobal && qualifier != EvqTemporary) {
error(loc, "hitObjectNV can only be declared in global or function scope with no storage qualifier:", "hitObjectNV", identifier.c_str());
}
}
}
void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
{
if (parsingBuiltins)
@ -7386,7 +7398,7 @@ TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, T
}
} else if (function->getName() == "atomicCounter") {
// change atomicCounter into a direct read of the variable
if (arguments->getAsTyped()) {
if (arguments && arguments->getAsTyped()) {
result = arguments->getAsTyped();
}
}
@ -7874,6 +7886,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
transparentOpaqueCheck(loc, type, identifier);
atomicUintCheck(loc, type, identifier);
accStructCheck(loc, type, identifier);
hitObjectNVCheck(loc, type, identifier);
checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false);
if (type.getQualifier().storage == EvqConst && type.containsReference()) {
error(loc, "variables with reference type can't have qualifier 'const'", "qualifier", "");
@ -8538,9 +8551,10 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
case EOpConstructF16Mat4x4:
case EOpConstructFloat16:
basicOp = EOpConstructFloat16;
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
// 8/16-bit storage extensions don't support direct constructing composites of 8/16-bit types,
// so construct a 32-bit type and convert
if (!intermediate.getArithemeticFloat16Enabled()) {
// and do not generate any conversion if it is an identity conversion, i.e. float16_t(<float16_t> var)
if (!intermediate.getArithemeticFloat16Enabled() && (node->getBasicType() != EbtFloat16)) {
TType tempType(EbtFloat, EvqTemporary, type.getVectorSize());
newNode = node;
if (tempType != newNode->getType()) {
@ -8561,9 +8575,10 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
case EOpConstructI8Vec4:
case EOpConstructInt8:
basicOp = EOpConstructInt8;
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
// 8/16-bit storage extensions don't support direct constructing composites of 8/16-bit types,
// so construct a 32-bit type and convert
if (!intermediate.getArithemeticInt8Enabled()) {
// and do not generate any conversion if it is an identity conversion, i.e. int8_t(<int8_t> var)
if (!intermediate.getArithemeticInt8Enabled() && (node->getBasicType() != EbtInt8)) {
TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
newNode = node;
if (tempType != newNode->getType()) {
@ -8584,9 +8599,10 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
case EOpConstructU8Vec4:
case EOpConstructUint8:
basicOp = EOpConstructUint8;
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
// 8/16-bit storage extensions don't support direct constructing composites of 8/16-bit types,
// so construct a 32-bit type and convert
if (!intermediate.getArithemeticInt8Enabled()) {
// and do not generate any conversion if it is an identity conversion, i.e. uint8_t(<uint8_t> var)
if (!intermediate.getArithemeticInt8Enabled() && (node->getBasicType() != EbtUint8)) {
TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
newNode = node;
if (tempType != newNode->getType()) {
@ -8607,9 +8623,10 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
case EOpConstructI16Vec4:
case EOpConstructInt16:
basicOp = EOpConstructInt16;
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
// 8/16-bit storage extensions don't support direct constructing composites of 8/16-bit types,
// so construct a 32-bit type and convert
if (!intermediate.getArithemeticInt16Enabled()) {
// and do not generate any conversion if it is an identity conversion, i.e. int16_t(<int16_t> var)
if (!intermediate.getArithemeticInt16Enabled() && (node->getBasicType() != EbtInt16)) {
TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
newNode = node;
if (tempType != newNode->getType()) {
@ -8630,9 +8647,10 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
case EOpConstructU16Vec4:
case EOpConstructUint16:
basicOp = EOpConstructUint16;
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
// 8/16-bit storage extensions don't support direct constructing composites of 8/16-bit types,
// so construct a 32-bit type and convert
if (!intermediate.getArithemeticInt16Enabled()) {
// and do not generate any conversion if it is an identity conversion, i.e. uint16_t(<uint16_t> var)
if (!intermediate.getArithemeticInt16Enabled() && (node->getBasicType() != EbtUint16)) {
TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
newNode = node;
if (tempType != newNode->getType()) {

View File

@ -397,6 +397,7 @@ public:
void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void hitObjectNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
void memberQualifierCheck(glslang::TPublicType&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false, const TPublicType* publicType = nullptr);

View File

@ -35,14 +35,21 @@
#include "../Include/Common.h"
#include "../Include/PoolAlloc.h"
// Mostly here for target that do not support threads such as WASI.
#ifdef DISABLE_THREAD_SUPPORT
#define THREAD_LOCAL
#else
#define THREAD_LOCAL thread_local
#endif
namespace glslang {
namespace {
thread_local TPoolAllocator* threadPoolAllocator = nullptr;
THREAD_LOCAL TPoolAllocator* threadPoolAllocator = nullptr;
TPoolAllocator* GetDefaultThreadPoolAllocator()
{
thread_local TPoolAllocator defaultAllocator;
THREAD_LOCAL TPoolAllocator defaultAllocator;
return &defaultAllocator;
}
} // anonymous namespace

View File

@ -82,7 +82,10 @@ namespace { // anonymous namespace for file-local functions and symbols
int NumberOfClients = 0;
// global initialization lock
#ifndef DISABLE_THREAD_SUPPORT
std::mutex init_lock;
#endif
using namespace glslang;
@ -420,7 +423,9 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
TInfoSink infoSink;
// Make sure only one thread tries to do this at a time
#ifndef DISABLE_THREAD_SUPPORT
const std::lock_guard<std::mutex> lock(init_lock);
#endif
// See if it's already been done for this version/profile combination
int versionIndex = MapVersionToIndex(version);
@ -1311,7 +1316,9 @@ bool CompileDeferred(
//
int ShInitialize()
{
#ifndef DISABLE_THREAD_SUPPORT
const std::lock_guard<std::mutex> lock(init_lock);
#endif
++NumberOfClients;
if (PerProcessGPA == nullptr)
@ -1371,7 +1378,9 @@ void ShDestruct(ShHandle handle)
//
int ShFinalize()
{
#ifndef DISABLE_THREAD_SUPPORT
const std::lock_guard<std::mutex> lock(init_lock);
#endif
--NumberOfClients;
assert(NumberOfClients >= 0);
if (NumberOfClients > 0)
@ -1849,6 +1858,9 @@ void TShader::setGlobalUniformBinding(unsigned int binding) { intermediate->setG
void TShader::setAtomicCounterBlockName(const char* name) { intermediate->setAtomicCounterBlockName(name); }
void TShader::setAtomicCounterBlockSet(unsigned int set) { intermediate->setAtomicCounterBlockSet(set); }
void TShader::addSourceText(const char* text, size_t len) { intermediate->addSourceText(text, len); }
void TShader::setSourceFile(const char* file) { intermediate->setSourceFile(file); }
#ifdef ENABLE_HLSL
// See comment above TDefaultHlslIoMapper in iomapper.cpp:
void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
@ -2112,6 +2124,8 @@ bool TProgram::buildReflection(int opts)
if (! linked || reflection != nullptr)
return false;
SetThreadPoolAllocator(pool);
int firstStage = EShLangVertex, lastStage = EShLangFragment;
if (opts & EShReflectionIntermediateIO) {
@ -2167,6 +2181,9 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper)
{
if (! linked)
return false;
SetThreadPoolAllocator(pool);
TIoMapper* ioMapper = nullptr;
TIoMapper defaultIOMapper;
if (pIoMapper == nullptr)

View File

@ -775,7 +775,7 @@ void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int
for (int i = 0; i < numExtensions; ++i) {
switch (getExtensionBehavior(extensions[i])) {
case EBhWarn:
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
[[fallthrough]];
case EBhRequire:
case EBhEnable:
@ -813,7 +813,8 @@ void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int
error(loc, "deprecated, may be removed in future release", featureDesc, "");
else if (! suppressWarnings())
infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
String(depVersion) + "; may be removed in future release").c_str(), loc);
String(depVersion) + "; may be removed in future release").c_str(),
loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
}
}
}
@ -850,11 +851,14 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte
for (int i = 0; i < numExtensions; ++i) {
TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
if (behavior == EBhDisable && relaxedErrors()) {
infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc);
infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc,
messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
behavior = EBhWarn;
}
if (behavior == EBhWarn) {
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
infoSink.info.message(EPrefixWarning,
("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(),
loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
warned = true;
}
}

0
3rdparty/glslang/glslang/MachineIndependent/Versions.h vendored Executable file → Normal file
View File

View File

@ -39,6 +39,7 @@
#include "gl_types.h"
#include "iomapper.h"
#include "LiveTraverser.h"
#include "SymbolTable.h"
//
@ -60,6 +61,108 @@
namespace glslang {
struct TVarEntryInfo {
long long id;
TIntermSymbol* symbol;
bool live;
bool upgradedToPushConstant;
int newBinding;
int newSet;
int newLocation;
int newComponent;
int newIndex;
EShLanguage stage;
void clearNewAssignments() {
upgradedToPushConstant = false;
newBinding = -1;
newSet = -1;
newLocation = -1;
newComponent = -1;
newIndex = -1;
}
struct TOrderById {
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
};
struct TOrderByPriority {
// ordering:
// 1) has both binding and set
// 2) has binding but no set
// 3) has no binding but set
// 4) has no binding and no set
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
const TQualifier& lq = l.symbol->getQualifier();
const TQualifier& rq = r.symbol->getQualifier();
// simple rules:
// has binding gives 2 points
// has set gives 1 point
// who has the most points is more important.
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
if (lPoints == rPoints)
return l.id < r.id;
return lPoints > rPoints;
}
};
struct TOrderByPriorityAndLive {
// ordering:
// 1) do live variables first
// 2) has both binding and set
// 3) has binding but no set
// 4) has no binding but set
// 5) has no binding and no set
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
const TQualifier& lq = l.symbol->getQualifier();
const TQualifier& rq = r.symbol->getQualifier();
// simple rules:
// has binding gives 2 points
// has set gives 1 point
// who has the most points is more important.
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
if (l.live != r.live)
return l.live > r.live;
if (lPoints != rPoints)
return lPoints > rPoints;
return l.id < r.id;
}
};
};
// override function "operator=", if a vector<const _Kty, _Ty> being sort,
// when use vc++, the sort function will call :
// pair& operator=(const pair<_Other1, _Other2>& _Right)
// {
// first = _Right.first;
// second = _Right.second;
// return (*this);
// }
// that will make a const type handing on left.
// override this function can avoid a compiler error.
// In the future, if the vc++ compiler can handle such a situation,
// this part of the code will be removed.
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
TVarLivePair& operator=(const TVarLivePair& _Right) {
const_cast<TString&>(first) = _Right.first;
second = _Right.second;
return (*this);
}
TVarLivePair(const TVarLivePair& src) : pair(src) { }
};
typedef std::vector<TVarLivePair> TVarLiveVector;
class TVarGatherTraverser : public TLiveTraverser {
public:
TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList)
@ -1497,6 +1600,36 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
return !hadError;
}
TGlslIoMapper::TGlslIoMapper() {
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount);
profile = ENoProfile;
version = 0;
autoPushConstantMaxSize = 128;
autoPushConstantBlockPacking = ElpStd430;
}
TGlslIoMapper::~TGlslIoMapper() {
for (size_t stage = 0; stage < EShLangCount; stage++) {
if (inVarMaps[stage] != nullptr) {
delete inVarMaps[stage];
inVarMaps[stage] = nullptr;
}
if (outVarMaps[stage] != nullptr) {
delete outVarMaps[stage];
outVarMaps[stage] = nullptr;
}
if (uniformVarMap[stage] != nullptr) {
delete uniformVarMap[stage];
uniformVarMap[stage] = nullptr;
}
if (intermediates[stage] != nullptr)
intermediates[stage] = nullptr;
}
}
// Map I/O variables to provided offsets, and make bindings for
// unbound but live variables.
//

View File

@ -37,7 +37,6 @@
#define _IOMAPPER_INCLUDED
#include <cstdint>
#include "LiveTraverser.h"
#include <unordered_map>
#include <unordered_set>
//
@ -49,84 +48,7 @@ class TInfoSink;
namespace glslang {
class TIntermediate;
struct TVarEntryInfo {
long long id;
TIntermSymbol* symbol;
bool live;
bool upgradedToPushConstant;
int newBinding;
int newSet;
int newLocation;
int newComponent;
int newIndex;
EShLanguage stage;
void clearNewAssignments() {
upgradedToPushConstant = false;
newBinding = -1;
newSet = -1;
newLocation = -1;
newComponent = -1;
newIndex = -1;
}
struct TOrderById {
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
};
struct TOrderByPriority {
// ordering:
// 1) has both binding and set
// 2) has binding but no set
// 3) has no binding but set
// 4) has no binding and no set
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
const TQualifier& lq = l.symbol->getQualifier();
const TQualifier& rq = r.symbol->getQualifier();
// simple rules:
// has binding gives 2 points
// has set gives 1 point
// who has the most points is more important.
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
if (lPoints == rPoints)
return l.id < r.id;
return lPoints > rPoints;
}
};
struct TOrderByPriorityAndLive {
// ordering:
// 1) do live variables first
// 2) has both binding and set
// 3) has binding but no set
// 4) has no binding but set
// 5) has no binding and no set
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
const TQualifier& lq = l.symbol->getQualifier();
const TQualifier& rq = r.symbol->getQualifier();
// simple rules:
// has binding gives 2 points
// has set gives 1 point
// who has the most points is more important.
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
if (l.live != r.live)
return l.live > r.live;
if (lPoints != rPoints)
return lPoints > rPoints;
return l.id < r.id;
}
};
};
struct TVarEntryInfo;
// Base class for shared TIoMapResolver services, used by several derivations.
struct TDefaultIoResolverBase : public glslang::TIoMapResolver {
public:
@ -267,29 +189,6 @@ protected:
typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
// override function "operator=", if a vector<const _Kty, _Ty> being sort,
// when use vc++, the sort function will call :
// pair& operator=(const pair<_Other1, _Other2>& _Right)
// {
// first = _Right.first;
// second = _Right.second;
// return (*this);
// }
// that will make a const type handing on left.
// override this function can avoid a compiler error.
// In the future, if the vc++ compiler can handle such a situation,
// this part of the code will be removed.
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
TVarLivePair& operator=(const TVarLivePair& _Right) {
const_cast<TString&>(first) = _Right.first;
second = _Right.second;
return (*this);
}
TVarLivePair(const TVarLivePair& src) : pair(src) { }
};
typedef std::vector<TVarLivePair> TVarLiveVector;
// I/O mapper
class TIoMapper {
public:
@ -303,34 +202,8 @@ public:
// I/O mapper for GLSL
class TGlslIoMapper : public TIoMapper {
public:
TGlslIoMapper() {
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
profile = ENoProfile;
version = 0;
autoPushConstantMaxSize = 128;
autoPushConstantBlockPacking = ElpStd430;
}
virtual ~TGlslIoMapper() {
for (size_t stage = 0; stage < EShLangCount; stage++) {
if (inVarMaps[stage] != nullptr) {
delete inVarMaps[stage];
inVarMaps[stage] = nullptr;
}
if (outVarMaps[stage] != nullptr) {
delete outVarMaps[stage];
outVarMaps[stage] = nullptr;
}
if (uniformVarMap[stage] != nullptr) {
delete uniformVarMap[stage];
uniformVarMap[stage] = nullptr;
}
if (intermediates[stage] != nullptr)
intermediates[stage] = nullptr;
}
}
TGlslIoMapper();
virtual ~TGlslIoMapper();
// If set, the uniform block with the given name will be changed to be backed by
// push_constant if it's size is <= maxSize
void setAutoPushConstantBlock(const char* name, unsigned int maxSize, TLayoutPacking packing) {
@ -341,8 +214,6 @@ public:
// grow the reflection stage by stage
bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
bool doMap(TIoMapResolver*, TInfoSink&) override;
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount],
*uniformVarMap[EShLangCount];
TIntermediate* intermediates[EShLangCount];
bool hadError = false;
EProfile profile;
@ -352,6 +223,8 @@ private:
TString autoPushConstantBlockName;
unsigned int autoPushConstantMaxSize;
TLayoutPacking autoPushConstantBlockPacking;
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount],
*uniformVarMap[EShLangCount];
};
} // end namespace glslang

View File

@ -113,6 +113,28 @@ void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
}
static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) {
return // 1) same stage and same shader interface
(stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) ||
// 2) accross stages and both are uniform or buffer
(symbol->getQualifier().storage == EvqUniform && unitSymbol->getQualifier().storage == EvqUniform) ||
(symbol->getQualifier().storage == EvqBuffer && unitSymbol->getQualifier().storage == EvqBuffer) ||
// 3) in/out matched across stage boundary
(stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut && unitSymbol->getQualifier().storage == EvqVaryingIn) ||
(unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut);
}
static bool isSameSymbol(TIntermSymbol* symbol1, EShLanguage stage1, TIntermSymbol* symbol2, EShLanguage stage2) {
// If they are both blocks in the same shader interface,
// match by the block-name, not the identifier name.
if (symbol1->getType().getBasicType() == EbtBlock && symbol2->getType().getBasicType() == EbtBlock) {
if (isSameInterface(symbol1, stage1, symbol2, stage2)) {
return symbol1->getType().getTypeName() == symbol2->getType().getTypeName();
}
} else if (symbol1->getName() == symbol2->getName())
return true;
return false;
}
//
// do error checking on the shader boundary in / out vars
//
@ -137,7 +159,32 @@ void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) {
// do matching and error checking
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
// TODO: final check; make sure that any statically used `in` have matching `out` written to
// Check that all of our inputs have matching outputs from the previous stage.
// Only do this for Vulkan, since GL_ARB_separate_shader_objects allows for
// the in/out to not match
if (spvVersion.vulkan > 0) {
for (auto& nextStageInterm : unitLinkerObjects) {
auto* nextStageSymbol = nextStageInterm->getAsSymbolNode();
bool found = false;
for (auto& curStageInterm : linkerObjects) {
if (isSameSymbol(curStageInterm->getAsSymbolNode(), getStage(), nextStageSymbol, unit.getStage())) {
found = true;
break;
}
}
if (!found) {
TString errmsg;
errmsg.append("Input '");
if (nextStageSymbol->getType().getBasicType() == EbtBlock)
errmsg.append(nextStageSymbol->getType().getTypeName());
else
errmsg.append(nextStageSymbol->getName());
errmsg.append("' in ").append(StageName(unit.getStage()));
errmsg.append(" shader has no corresponding output in ").append(StageName(getStage())).append(" shader.");
error(infoSink, errmsg.c_str(), unit.getStage());
}
}
}
}
void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
@ -511,17 +558,6 @@ void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, c
globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
}
static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) {
return // 1) same stage and same shader interface
(stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) ||
// 2) accross stages and both are uniform or buffer
(symbol->getQualifier().storage == EvqUniform && unitSymbol->getQualifier().storage == EvqUniform) ||
(symbol->getQualifier().storage == EvqBuffer && unitSymbol->getQualifier().storage == EvqBuffer) ||
// 3) in/out matched across stage boundary
(stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut && unitSymbol->getQualifier().storage == EvqVaryingIn) ||
(unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut);
}
//
// Global Unfiform block stores any default uniforms (i.e. uniforms without a block)
// If two linked stages declare the same member, they are meant to be the same uniform
@ -707,24 +743,18 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
// Error check and merge the linker objects (duplicates should not be created)
std::size_t initialNumLinkerObjects = linkerObjects.size();
for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) {
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
bool merge = true;
// Don't merge inputs backwards into previous stages
if (getStage() != unitStage && unitSymbol->getQualifier().storage == EvqVaryingIn)
merge = false;
for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
assert(symbol && unitSymbol);
bool isSameSymbol = false;
// If they are both blocks in the same shader interface,
// match by the block-name, not the identifier name.
if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
}
}
else if (symbol->getName() == unitSymbol->getName())
isSameSymbol = true;
if (isSameSymbol) {
if (isSameSymbol(symbol, getStage(), unitSymbol, unitStage)) {
// filter out copy
merge = false;
@ -1689,7 +1719,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
// First range:
TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation);
TRange componentRange(0, 3);
TIoRange range(locationRange, componentRange, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat);
TIoRange range(locationRange, componentRange, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat, qualifier.sample, qualifier.patch);
// check for collisions
collision = checkLocationRange(set, range, type, typeCollision);
@ -1699,7 +1729,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
// Second range:
TRange locationRange2(qualifier.layoutLocation + 1, qualifier.layoutLocation + 1);
TRange componentRange2(0, 1);
TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat);
TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat, qualifier.sample, qualifier.patch);
// check for collisions
collision = checkLocationRange(set, range2, type, typeCollision);
@ -1725,7 +1755,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
TBasicType basicTy = type.getBasicType();
if (basicTy == EbtSampler && type.getSampler().isAttachmentEXT())
basicTy = type.getSampler().type;
TIoRange range(locationRange, componentRange, basicTy, qualifier.hasIndex() ? qualifier.getIndex() : 0, qualifier.centroid, qualifier.smooth, qualifier.flat);
TIoRange range(locationRange, componentRange, basicTy, qualifier.hasIndex() ? qualifier.getIndex() : 0, qualifier.centroid, qualifier.smooth, qualifier.flat, qualifier.sample, qualifier.patch);
// check for collisions, except for vertex inputs on desktop targeting OpenGL
if (! (!isEsProfile() && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0)
@ -1737,6 +1767,24 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
return collision;
}
// Check that two types can be stored in different components in the same location.
// They must be the same type, except signed/unsigned integers are considered compatible.
static bool checkCompatibleTypes(TBasicType t1, TBasicType t2) {
if (t1 != t2) {
if ((t1 == EbtInt8 && t2 == EbtUint8) ||
(t2 == EbtInt8 && t1 == EbtUint8) ||
(t1 == EbtInt16 && t2 == EbtUint16) ||
(t2 == EbtInt16 && t1 == EbtUint16)||
(t1 == EbtInt && t2 == EbtUint) ||
(t2 == EbtInt && t1 == EbtUint)||
(t1 == EbtInt64 && t2 == EbtUint64) ||
(t2 == EbtInt64 && t1 == EbtUint64)) {
return true;
}
}
return t1 == t2;
}
// Compare a new (the passed in) 'range' against the existing set, and see
// if there are any collisions.
//
@ -1749,10 +1797,12 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp
// there is a collision; pick one
return std::max(range.location.start, usedIo[set][r].location.start);
} else if (range.location.overlap(usedIo[set][r].location) &&
(type.getBasicType() != usedIo[set][r].basicType ||
(!checkCompatibleTypes(type.getBasicType(), usedIo[set][r].basicType) ||
type.getQualifier().centroid != usedIo[set][r].centroid ||
type.getQualifier().smooth != usedIo[set][r].smooth ||
type.getQualifier().flat != usedIo[set][r].flat)) {
type.getQualifier().flat != usedIo[set][r].flat ||
type.getQualifier().sample != usedIo[set][r].sample ||
type.getQualifier().patch != usedIo[set][r].patch)) {
// aliased-type mismatch
typeCollision = true;
return std::max(range.location.start, usedIo[set][r].location.start);

View File

@ -99,7 +99,8 @@ private:
// A "call" is a pair: <caller, callee>.
// There can be duplicates. General assumption is the list is small.
struct TCall {
TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
TCall(const TString& pCaller, const TString& pCallee)
: caller(pCaller), callee(pCallee), visited(false), currentPath(false), errorGiven(false) { }
TString caller;
TString callee;
bool visited;
@ -123,8 +124,8 @@ struct TRange {
// within the same location range, component range, and index value. Locations don't alias unless
// all other dimensions of their range overlap.
struct TIoRange {
TIoRange(TRange location, TRange component, TBasicType basicType, int index, bool centroid, bool smooth, bool flat)
: location(location), component(component), basicType(basicType), index(index), centroid(centroid), smooth(smooth), flat(flat)
TIoRange(TRange location, TRange component, TBasicType basicType, int index, bool centroid, bool smooth, bool flat, bool sample, bool patch)
: location(location), component(component), basicType(basicType), index(index), centroid(centroid), smooth(smooth), flat(flat), sample(sample), patch(patch)
{
}
bool overlap(const TIoRange& rhs) const
@ -138,6 +139,8 @@ struct TIoRange {
bool centroid;
bool smooth;
bool flat;
bool sample;
bool patch;
};
// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying

View File

@ -374,7 +374,7 @@ namespace {
int op_div(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a / b; }
int op_mod(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a % b; }
int op_pos(int a) { return a; }
int op_neg(int a) { return -a; }
int op_neg(int a) { return a == INT_MIN ? INT_MIN : -a; }
int op_cmpl(int a) { return ~a; }
int op_not(int a) { return !a; }

View File

@ -38,6 +38,7 @@
#define _COMPILER_INTERFACE_INCLUDED_
#include "../Include/ResourceLimits.h"
#include "../Include/visibility.h"
#include "../MachineIndependent/Versions.h"
#include <cstring>
@ -49,22 +50,6 @@
#define C_DECL
#endif
#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
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler/linker.
@ -270,6 +255,7 @@ enum EShMessages : unsigned {
EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
EShMsgEnhanced = (1 << 15), // enhanced message readability
EShMsgAbsolutePath = (1 << 16), // Output Absolute path for messages
EShMsgDisplayErrorColumn = (1 << 17), // Display error message column aswell as line
LAST_ELEMENT_MARKER(EShMsgCount),
};
@ -509,6 +495,9 @@ public:
GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set);
GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding);
GLSLANG_EXPORT void addSourceText(const char* text, size_t len);
GLSLANG_EXPORT void setSourceFile(const char* file);
// For setting up the environment (cleared to nothingness in the constructor).
// These must be called so that parsing is done for the right source language and
// target environment, either indirectly through TranslateEnvironment() based on

37
3rdparty/glslang/glslang/stub.cpp vendored Normal file
View File

@ -0,0 +1,37 @@
//
// Copyright (C) 2024 The Khronos Group Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// This empty source file exists to support building stubbed versions of
// deprecated libraries which have been integrated into the main glslang
// library. It should be deleted once the stub libraries are fully removed.