Updated glslang.

This commit is contained in:
Бранимир Караџић
2025-10-21 19:22:15 -07:00
parent f1a138b847
commit e9bdf630f7
21 changed files with 420 additions and 2541 deletions

View File

@@ -13,9 +13,6 @@ Other parts, outside of glslang proper, include:
- update_glslang_sources.py, which is not part of the project proper and does
not need to be used.
- the SPIR-V "remapper", which is optional, but has the same license as
glslang proper
- Google tests and SPIR-V tools, and anything in the external subdirectory
are external and optional; see them for their respective licenses.

View File

@@ -5596,6 +5596,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0,
// except sometimes for blocks
std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
std::vector<spv::StructMemberDebugInfo> memberDebugInfo;
for (int i = 0; i < (int)glslangMembers->size(); i++) {
auto& glslangMember = (*glslangMembers)[i];
if (glslangMember.type->hiddenMember()) {
@@ -5646,15 +5647,39 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
// + Not as clean as desired. Traverser queries/sets persistent state. This is fragile.
// + Table lookup during creation of composite debug types. This really shouldn't be necessary.
if(options.emitNonSemanticShaderDebugInfo) {
builder.debugTypeLocs[spvMember].name = glslangMember.type->getFieldName().c_str();
builder.debugTypeLocs[spvMember].line = glslangMember.loc.line;
builder.debugTypeLocs[spvMember].column = glslangMember.loc.column;
spv::StructMemberDebugInfo debugInfo{};
debugInfo.name = glslangMember.type->getFieldName();
debugInfo.line = glslangMember.loc.line;
debugInfo.column = glslangMember.loc.column;
// Per the GLSL spec, bool variables inside of a uniform or buffer block are generated as uint.
// But for debug info, we want to represent them as bool because that is the original type in
// the source code. The bool type can be nested within a vector or a multidimensional array,
// so we must construct the chain of types up from the scalar bool.
if (glslangIntermediate->getSource() == glslang::EShSourceGlsl && explicitLayout != glslang::ElpNone &&
glslangMember.type->getBasicType() == glslang::EbtBool) {
auto typeId = builder.makeBoolType();
if (glslangMember.type->isVector()) {
typeId = builder.makeVectorType(typeId, glslangMember.type->getVectorSize());
}
if (glslangMember.type->isArray()) {
const auto* arraySizes = glslangMember.type->getArraySizes();
int dims = arraySizes->getNumDims();
for (int i = dims - 1; i >= 0; --i) {
spv::Id size = builder.makeIntConstant(arraySizes->getDimSize(i));
typeId = builder.makeArrayType(typeId, size, 0);
}
}
debugInfo.debugTypeOverride = builder.getDebugType(typeId);
}
memberDebugInfo.push_back(debugInfo);
}
}
}
// Make the SPIR-V type
spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str(), false);
spv::Id spvType = builder.makeStructType(spvMembers, memberDebugInfo, type.getTypeName().c_str(), false);
if (! HasNonLayoutQualifiers(type, qualifier))
structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType;
@@ -7073,7 +7098,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
for (int i = 0; i < 5; i++) {
members.push_back(builder.getContainedTypeId(resultStructType, i));
}
spv::Id resType = builder.makeStructType(members, "ResType");
spv::Id resType = builder.makeStructType(members, {}, "ResType");
//call ImageFootprintNV
spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj,

File diff suppressed because it is too large Load Diff

View File

@@ -1,300 +0,0 @@
//
// Copyright (C) 2015 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.
//
#ifndef SPIRVREMAPPER_H
#define SPIRVREMAPPER_H
#include <string>
#include <vector>
#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
{
public:
enum Options {
NONE = 0,
STRIP = (1<<0),
MAP_TYPES = (1<<1),
MAP_NAMES = (1<<2),
MAP_FUNCS = (1<<3),
DCE_FUNCS = (1<<4),
DCE_VARS = (1<<5),
DCE_TYPES = (1<<6),
OPT_LOADSTORE = (1<<7),
OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV
MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS),
DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES),
OPT_ALL = (OPT_LOADSTORE),
ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL),
DO_EVERYTHING = (STRIP | ALL_BUT_STRIP)
};
};
} // namespace SPV
#include <functional>
#include <cstdint>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <cassert>
#include "spirv.hpp11"
namespace spv {
static inline constexpr Id NoResult = 0;
// class to hold SPIR-V binary data for remapping, DCE, and debug stripping
class GLSLANG_EXPORT spirvbin_t : public spirvbin_base_t
{
public:
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false)
{ }
virtual ~spirvbin_t() { }
// remap on an existing binary in memory
void remap(std::vector<std::uint32_t>& spv, const std::vector<std::string>& whiteListStrings,
std::uint32_t opts = DO_EVERYTHING);
// remap on an existing binary in memory - legacy interface without white list
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
// Type for error/log handler functions
typedef std::function<void(const std::string&)> errorfn_t;
typedef std::function<void(const std::string&)> logfn_t;
// Register error/log handling functions (can be lambda fn / functor / etc)
static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; }
static void registerLogHandler(logfn_t handler) { logHandler = handler; }
protected:
// This can be overridden to provide other message behavior if needed
virtual void msg(int minVerbosity, int indent, const std::string& txt) const;
private:
// Local to global, or global to local ID map
typedef std::unordered_map<spv::Id, spv::Id> idmap_t;
typedef std::unordered_set<spv::Id> idset_t;
typedef std::unordered_map<spv::Id, int> blockmap_t;
void remap(std::uint32_t opts = DO_EVERYTHING);
// Map of names to IDs
typedef std::unordered_map<std::string, spv::Id> namemap_t;
typedef std::uint32_t spirword_t;
typedef std::pair<unsigned, unsigned> range_t;
typedef std::function<void(spv::Id&)> idfn_t;
typedef std::function<bool(spv::Op, unsigned start)> instfn_t;
// Special Values for ID map:
static const spv::Id unmapped; // unchanged from default value
static const spv::Id unused; // unused ID
static const int header_size; // SPIR header = 5 words
class id_iterator_t;
// For mapping type entries between different shaders
typedef std::vector<spirword_t> typeentry_t;
typedef std::map<spv::Id, typeentry_t> globaltypes_t;
// A set that preserves position order, and a reverse map
typedef std::set<int> posmap_t;
typedef std::unordered_map<spv::Id, int> posmap_rev_t;
// Maps and ID to the size of its base type, if known.
typedef std::unordered_map<spv::Id, unsigned> typesize_map_t;
// handle error
void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); }
bool isConstOp(spv::Op opCode) const;
bool isTypeOp(spv::Op opCode) const;
bool isStripOp(spv::Op opCode) const;
bool isFlowCtrl(spv::Op opCode) const;
range_t literalRange(spv::Op opCode) const;
range_t typeRange(spv::Op opCode) const;
range_t constRange(spv::Op opCode) const;
unsigned typeSizeInWords(spv::Id id) const;
unsigned idTypeSizeInWords(spv::Id id) const;
bool isStripOp(spv::Op opCode, unsigned start) const;
spv::Id& asId(unsigned word) { return spv[word]; }
const spv::Id& asId(unsigned word) const { return spv[word]; }
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
std::uint32_t asOpCodeHash(unsigned word);
spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); }
spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); }
unsigned idPos(spv::Id id) const;
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
// Header access & set methods
spirword_t magic() const { return spv[0]; } // return magic number
spirword_t bound() const { return spv[3]; } // return Id bound from header
spirword_t bound(spirword_t b) { return spv[3] = b; }
spirword_t genmagic() const { return spv[2]; } // generator magic
spirword_t genmagic(spirword_t m) { return spv[2] = m; }
spirword_t schemaNum() const { return spv[4]; } // schema number from header
// Mapping fns: get
spv::Id localId(spv::Id id) const { return idMapL[id]; }
// Mapping fns: set
inline spv::Id localId(spv::Id id, spv::Id newId);
void countIds(spv::Id id);
// Return next unused new local ID.
// NOTE: boost::dynamic_bitset would be more efficient due to find_next(),
// which std::vector<bool> doens't have.
inline spv::Id nextUnusedId(spv::Id id);
void buildLocalMaps();
std::string literalString(unsigned word) const; // Return literal as a std::string
int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; }
bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); }
bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; }
bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; }
bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); }
bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); }
// bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const;
// spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const;
std::uint32_t hashType(unsigned typeStart) const;
spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0);
int processInstruction(unsigned word, instfn_t, idfn_t);
void validate() const;
void mapTypeConst();
void mapFnBodies();
void optLoadStore();
void dceFuncs();
void dceVars();
void dceTypes();
void mapNames();
void foldIds(); // fold IDs to smallest space
void forwardLoadStores(); // load store forwarding (EXPERIMENTAL)
void offsetIds(); // create relative offset IDs
void applyMap(); // remap per local name map
void mapRemainder(); // map any IDs we haven't touched yet
void stripDebug(); // strip all debug info
void stripDeadRefs(); // strips debug info for now-dead references after DCE
void strip(); // remove debug symbols
std::vector<spirword_t> spv; // SPIR words
std::vector<std::string> stripWhiteList;
namemap_t nameMap; // ID names from OpName
// Since we want to also do binary ops, we can't use std::vector<bool>. we could use
// boost::dynamic_bitset, but we're trying to avoid a boost dependency.
typedef std::uint64_t bits_t;
std::vector<bits_t> mapped; // which new IDs have been mapped
static const int mBits = sizeof(bits_t) * 4;
bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); }
void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); }
void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); }
size_t maxMappedId() const { return mapped.size() * mBits; }
// Add a strip range for a given instruction starting at 'start'
// Note: avoiding brace initializers to please older versions os MSVC.
void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); }
// Function start and end. use unordered_map because we'll have
// many fewer functions than IDs.
std::unordered_map<spv::Id, range_t> fnPos;
// Which functions are called, anywhere in the module, with a call count
std::unordered_map<spv::Id, int> fnCalls;
posmap_t typeConstPos; // word positions that define types & consts (ordered)
posmap_rev_t idPosR; // reverse map from IDs to positions
typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known.
std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
spv::Id entryPoint; // module entry point
spv::Id largestNewId; // biggest new ID we have mapped anything to
// Sections of the binary to strip, given as [begin,end)
std::vector<range_t> stripRange;
// processing options:
std::uint32_t options;
int verbose; // verbosity level
// Error latch: this is set if the error handler is ever executed. It would be better to
// use a try/catch block and throw, but that's not desired for certain environments, so
// this is the alternative.
mutable bool errorLatch;
static errorfn_t errorHandler;
static logfn_t logHandler;
};
} // namespace SPV
#endif // SPIRVREMAPPER_H

View File

@@ -138,7 +138,7 @@ Id Builder::makeSamplerType()
if (emitNonSemanticShaderDebugInfo)
{
auto const debugResultId = makeCompositeDebugType({}, "type.sampler", NonSemanticShaderDebugInfo100Structure, true);
auto const debugResultId = makeOpaqueDebugType("type.sampler");
debugId[type->getResultId()] = debugResultId;
}
@@ -419,7 +419,9 @@ Id Builder::makeFloatE4M3Type()
// See makeStructResultType() for non-decorated structs
// needed as the result of some instructions, which does
// check for duplicates.
Id Builder::makeStructType(const std::vector<Id>& members, const char* name, bool const compilerGenerated)
// For compiler-generated structs, debug info is ignored.
Id Builder::makeStructType(const std::vector<Id>& members, const std::vector<spv::StructMemberDebugInfo>& memberDebugInfo,
const char* name, bool const compilerGenerated)
{
// Don't look for previous one, because in the general case,
// structs can be duplicated except for decorations.
@@ -433,9 +435,10 @@ Id Builder::makeStructType(const std::vector<Id>& members, const char* name, boo
module.mapInstruction(type);
addName(type->getResultId(), name);
if (emitNonSemanticShaderDebugInfo && !compilerGenerated)
{
auto const debugResultId = makeCompositeDebugType(members, name, NonSemanticShaderDebugInfo100Structure);
if (emitNonSemanticShaderDebugInfo && !compilerGenerated) {
assert(members.size() == memberDebugInfo.size());
auto const debugResultId =
makeCompositeDebugType(members, memberDebugInfo, name, NonSemanticShaderDebugInfo100Structure);
debugId[type->getResultId()] = debugResultId;
}
@@ -463,7 +466,7 @@ Id Builder::makeStructResultType(Id type0, Id type1)
members.push_back(type0);
members.push_back(type1);
return makeStructType(members, "ResType");
return makeStructType(members, {}, "ResType");
}
Id Builder::makeVectorType(Id component, int size)
@@ -587,7 +590,7 @@ Id Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id col
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);
auto const debugResultId = makeOpaqueDebugType(debugName.c_str());
debugId[type->getResultId()] = debugResultId;
}
@@ -929,7 +932,7 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo
}
};
auto const debugResultId = makeCompositeDebugType({}, TypeName(), NonSemanticShaderDebugInfo100Class, true);
auto const debugResultId = makeOpaqueDebugType(TypeName());
debugId[type->getResultId()] = debugResultId;
}
@@ -956,7 +959,7 @@ Id Builder::makeSampledImageType(Id imageType)
if (emitNonSemanticShaderDebugInfo)
{
auto const debugResultId = makeCompositeDebugType({}, "type.sampled.image", NonSemanticShaderDebugInfo100Class, true);
auto const debugResultId = makeOpaqueDebugType("type.sampled.image");
debugId[type->getResultId()] = debugResultId;
}
@@ -1153,7 +1156,7 @@ Id Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool
return type->getResultId();
}
Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc)
Id Builder::makeMemberDebugType(Id const memberType, StructMemberDebugInfo const& debugTypeLoc)
{
assert(debugId[memberType] != 0);
@@ -1162,12 +1165,13 @@ Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTy
type->addIdOperand(nonSemanticShaderDebugInfo);
type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember);
type->addIdOperand(getStringId(debugTypeLoc.name)); // name id
type->addIdOperand(debugId[memberType]); // type id
type->addIdOperand(makeDebugSource(currentFileId)); // source id
type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero
type->addIdOperand(debugTypeLoc.debugTypeOverride != 0 ? debugTypeLoc.debugTypeOverride
: debugId[memberType]); // type id
type->addIdOperand(makeDebugSource(currentFileId)); // source id
type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero
type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id
type->addIdOperand(makeUintConstant(0)); // TODO: offset id
type->addIdOperand(makeUintConstant(0)); // TODO: size id
type->addIdOperand(makeUintConstant(0)); // TODO: offset id
type->addIdOperand(makeUintConstant(0)); // TODO: size id
type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id
groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMember].push_back(type);
@@ -1177,23 +1181,16 @@ Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTy
return type->getResultId();
}
// Note: To represent a source language opaque type, this instruction must have no Members operands, Size operand must be
// DebugInfoNone, and Name must start with @ to avoid clashes with user defined names.
Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char const*const name,
NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType)
Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, std::vector<StructMemberDebugInfo> const& memberDebugInfo,
char const* const name, NonSemanticShaderDebugInfo100DebugCompositeType const tag)
{
// Create the debug member types.
std::vector<Id> memberDebugTypes;
for(auto const memberType : memberTypes) {
assert(debugTypeLocs.find(memberType) != debugTypeLocs.end());
// There _should_ be debug types for all the member types but currently buffer references
// do not have member debug info generated.
if (debugId[memberType])
memberDebugTypes.emplace_back(makeMemberDebugType(memberType, debugTypeLocs[memberType]));
// TODO: Need to rethink this method of passing location information.
// debugTypeLocs.erase(memberType);
assert(memberTypes.size() == memberDebugInfo.size());
for (size_t i = 0; i < memberTypes.size(); i++) {
if (debugId[memberTypes[i]]) {
memberDebugTypes.emplace_back(makeMemberDebugType(memberTypes[i], memberDebugInfo[i]));
}
}
// Create The structure debug type.
@@ -1207,16 +1204,9 @@ Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char cons
type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
type->addIdOperand(makeUintConstant(0)); // TODO: column id
type->addIdOperand(makeDebugCompilationUnit()); // scope id
if(isOpaqueType == true) {
// Prepend '@' to opaque types.
type->addIdOperand(getStringId('@' + std::string(name))); // linkage name id
type->addIdOperand(makeDebugInfoNone()); // size id
} else {
type->addIdOperand(getStringId(name)); // linkage name id
type->addIdOperand(makeUintConstant(0)); // TODO: size id
}
type->addIdOperand(getStringId(name)); // linkage name id
type->addIdOperand(makeUintConstant(0)); // TODO: size id
type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id
assert(isOpaqueType == false || (isOpaqueType == true && memberDebugTypes.empty()));
for(auto const memberDebugType : memberDebugTypes) {
type->addIdOperand(memberDebugType);
}
@@ -1228,6 +1218,34 @@ Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char cons
return type->getResultId();
}
// The NonSemantic Shader Debug Info doesn't really have a dedicated opcode for opaque types. Instead, we use DebugTypeComposite.
// To represent a source language opaque type, this instruction must have no Members operands, Size operand must be
// DebugInfoNone, and Name must start with @ to avoid clashes with user defined names.
Id Builder::makeOpaqueDebugType(char const* const name)
{
// Create The structure debug type.
Instruction* type = new Instruction(getUniqueId(), makeVoidType(), Op::OpExtInst);
type->reserveOperands(11);
type->addIdOperand(nonSemanticShaderDebugInfo);
type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite);
type->addIdOperand(getStringId(name)); // name id
type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Structure)); // tag id
type->addIdOperand(makeDebugSource(currentFileId)); // source id
type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero?
type->addIdOperand(makeUintConstant(0)); // TODO: column id
type->addIdOperand(makeDebugCompilationUnit()); // scope id
// Prepend '@' to opaque types.
type->addIdOperand(getStringId('@' + std::string(name))); // linkage name id
type->addIdOperand(makeDebugInfoNone()); // size id
type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id
groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeComposite].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
Id Builder::makePointerDebugType(StorageClass storageClass, Id const baseType)
{
const Id debugBaseType = debugId[baseType];
@@ -1401,7 +1419,7 @@ Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t cons
inst->addIdOperand(currentDebugScopeId.top()); // scope id
inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsLocal)); // flags id
if(argNumber != 0) {
inst->addIdOperand(makeUintConstant(argNumber));
inst->addIdOperand(makeUintConstant(static_cast<unsigned int>(argNumber)));
}
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
@@ -1465,7 +1483,7 @@ Id Builder::makeAccelerationStructureType()
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
if (emitNonSemanticShaderDebugInfo) {
spv::Id debugType = makeCompositeDebugType({}, "accelerationStructure", NonSemanticShaderDebugInfo100Structure, true);
spv::Id debugType = makeOpaqueDebugType("accelerationStructure");
debugId[type->getResultId()] = debugType;
}
} else {
@@ -1484,7 +1502,7 @@ Id Builder::makeRayQueryType()
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
if (emitNonSemanticShaderDebugInfo) {
spv::Id debugType = makeCompositeDebugType({}, "rayQuery", NonSemanticShaderDebugInfo100Structure, true);
spv::Id debugType = makeOpaqueDebugType("rayQuery");
debugId[type->getResultId()] = debugType;
}
} else {

View File

@@ -82,6 +82,14 @@ typedef enum {
Spv_1_6 = (1 << 16) | (6 << 8),
} SpvVersion;
struct StructMemberDebugInfo {
std::string name {};
int line {0};
int column {0};
// Set if the caller knows a better debug type than what is associated with the functional SPIR-V type.
spv::Id debugTypeOverride {0};
};
class Builder {
public:
Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
@@ -198,6 +206,14 @@ public:
return id;
}
// Maps the given OpType Id to a Non-Semantic DebugType Id.
Id getDebugType(Id type) {
if (emitNonSemanticShaderDebugInfo) {
return debugId[type];
}
return 0;
}
// For creating new types (will return old type if the requested one was already made).
Id makeVoidType();
Id makeBoolType();
@@ -211,7 +227,8 @@ public:
Id makeBFloat16Type();
Id makeFloatE5M2Type();
Id makeFloatE4M3Type();
Id makeStructType(const std::vector<Id>& members, const char* name, bool const compilerGenerated = true);
Id makeStructType(const std::vector<Id>& members, const std::vector<spv::StructMemberDebugInfo>& memberDebugInfo,
const char* name, bool const compilerGenerated = true);
Id makeStructResultType(Id type0, Id type1);
Id makeVectorType(Id component, int size);
Id makeMatrixType(Id component, int cols, int rows);
@@ -229,12 +246,6 @@ public:
Id makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands);
// SPIR-V NonSemantic Shader DebugInfo Instructions
struct DebugTypeLoc {
std::string name {};
int line {0};
int column {0};
};
std::unordered_map<Id, DebugTypeLoc> debugTypeLocs;
Id makeDebugInfoNone();
Id makeBoolDebugType(int const size);
Id makeIntegerDebugType(int const width, bool const hasSign);
@@ -243,9 +254,10 @@ public:
Id makeArrayDebugType(Id const baseType, Id const componentCount);
Id makeVectorDebugType(Id const baseType, int const componentCount);
Id makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor = true);
Id makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc);
Id makeCompositeDebugType(std::vector<Id> const& memberTypes, char const*const name,
NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType = false);
Id makeMemberDebugType(Id const memberType, StructMemberDebugInfo const& debugTypeLoc);
Id makeCompositeDebugType(std::vector<Id> const& memberTypes, std::vector<StructMemberDebugInfo> const& memberDebugInfo,
char const* const name, NonSemanticShaderDebugInfo100DebugCompositeType const tag);
Id makeOpaqueDebugType(char const* const name);
Id makePointerDebugType(StorageClass storageClass, Id const baseType);
Id makeForwardPointerDebugType(StorageClass storageClass);
Id makeDebugSource(const Id fileName);

View File

@@ -815,6 +815,14 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
lowerword == "shift-ssbo-binding" ||
lowerword == "sbb") {
ProcessBindingBase(argc, argv, glslang::EResSsbo);
} else if (lowerword == "shift-combined-sampler-bindings" ||
lowerword == "shift-combined-sampler-binding" ||
lowerword == "scsb") {
ProcessBindingBase(argc, argv, glslang::EResCombinedSampler);
} else if (lowerword == "shift-as-bindings" ||
lowerword == "shift-as-binding" ||
lowerword == "sab") {
ProcessBindingBase(argc, argv, glslang::EResAs);
} else if (lowerword == "source-entrypoint" || // synonyms
lowerword == "sep") {
if (argc <= 1)
@@ -874,7 +882,7 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
TargetVersion = glslang::EShTargetSpv_1_6;
} else
Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2,\n"
"vulkan1.3, opengl, spirv1.0, spirv1.1, spirv1.2, spirv1.3,\n"
"vulkan1.3, vulkan1.4, opengl, spirv1.0, spirv1.1, spirv1.2, spirv1.3,\n"
"spirv1.4, spirv1.5 or spirv1.6");
}
bumpArg();
@@ -1972,47 +1980,45 @@ void usage()
" rcall for a ray callable shader\n"
"2) .<stage>.glsl or .<stage>.hlsl compound suffix, where stage options are\n"
" described above\n"
"3) .conf, to provide a config file that replaces the default configuration\n"
" (see -c option below for generating a template)\n"
"3) .conf, to provide a config file that replaces the default configuration (see\n"
" -c option below for generating a template)\n"
"\n"
"Options:\n"
" -C cascading errors; risk crash from accumulation of error recoveries\n"
" -D input is HLSL (this is the default when any suffix is .hlsl)\n"
" -D<name[=def]> | --define-macro <name[=def]> | --D <name[=def]>\n"
" -D<name[=def]> | --D <name[=def]> | --define-macro <name[=def]>\n"
" define a pre-processor macro\n"
" -E print pre-processed GLSL; cannot be used with -l;\n"
" errors will appear on stderr\n"
" -G[ver] create SPIR-V binary, under OpenGL semantics; turns on -l;\n"
" default file name is <stage>.spv (-o overrides this);\n"
" 'ver', when present, is the version of the input semantics,\n"
" which will appear in #define GL_SPIRV ver;\n"
" '--client opengl100' is the same as -G100;\n"
" a '--target-env' for OpenGL will also imply '-G';\n"
" currently only supports GLSL\n"
" -E print pre-processed GLSL; cannot be used with -l; errors will\n"
" appear on stderr\n"
" -G[ver] create SPIR-V binary under OpenGL semantics; turns on -l; default\n"
" file name is <stage>.spv (-o overrides this); ver, when present,\n"
" is the version of the input semantics which will appear in\n"
" '#define GL_SPIRV ver'; --client opengl100 is the same as -G100; a\n"
" --target-env for OpenGL will also imply -G; currently only\n"
" supports GLSL\n"
" -H print human readable form of SPIR-V; turns on -V\n"
" -I<dir> add dir to the include search path; includer's directory\n"
" is searched first, followed by left-to-right order of -I\n"
" -I<dir> add <dir> to the include search path; includer's directory is\n"
" searched first, followed by left-to-right order of -I\n"
" -Od disables optimization; may cause illegal SPIR-V for HLSL\n"
" -Os optimizes SPIR-V to minimize size\n"
" -P<text> | --preamble-text <text> | --P <text>\n"
" inject custom preamble text, which is treated as if it\n"
" appeared immediately after the version declaration (if any).\n"
" -P<text> | --P <text> | --preamble-text <text>\n"
" inject custom preamble text which is treated as if it appeared\n"
" immediately after the version declaration (if any)\n"
" -R use relaxed verification rules for generating Vulkan SPIR-V,\n"
" allowing the use of default uniforms, atomic_uints, and\n"
" gl_VertexID and gl_InstanceID keywords.\n"
" -S <stage> uses specified stage rather than parsing the file extension\n"
" choices for <stage> include vert, tesc, tese, geom, frag, comp.\n"
" A full list of options is given above."
" allowing the use of default uniforms, atomic_uints, and the\n"
" gl_VertexID and gl_InstanceID keywords\n"
" -S <stage> uses the specified <stage> rather than parsing the file extension;\n"
" choices for <stage> include vert, tesc, tese, geom, frag, and\n"
" comp; a full list of options is given above\n"
" -U<name> | --undef-macro <name> | --U <name>\n"
" undefine a pre-processor macro\n"
" -V[ver] create SPIR-V binary, under Vulkan semantics; turns on -l;\n"
" default file name is <stage>.spv (-o overrides this)\n"
" 'ver', when present, is the version of the input semantics,\n"
" which will appear in #define VULKAN ver\n"
" '--client vulkan100' is the same as -V100\n"
" a '--target-env' for Vulkan will also imply '-V'\n"
" -c configuration dump;\n"
" creates the default configuration file (redirect to a .conf file)\n"
" -V[ver] create SPIR-V binary under Vulkan semantics; turns on -l; default\n"
" file name is <stage>.spv (-o overrides this); ver, when present,\n"
" is the version of the input semantics which will appear in\n"
" '#define VULKAN ver'; --client vulkan100 is the same as -V100; a\n"
" '--target-env' for Vulkan will also imply '-V'\n"
" -c configuration dump; creates the default configuration file\n"
" (redirect to a .conf file)\n"
" -d default to desktop (#version 110) when there is no shader #version\n"
" (default is ES version 100)\n"
" -e <name> | --entry-point <name>\n"
@@ -2024,148 +2030,170 @@ void usage()
" -g0 strip debug information\n"
" -gV generate nonsemantic shader debug information\n"
" -gVS generate nonsemantic shader debug information with source\n"
" -h print this usage message\n"
" -h | --help print this usage message\n"
" -i intermediate tree (glslang AST) is printed out\n"
" -l link all input files together to form a single module\n"
" -m memory leak mode\n"
" -o <file> save binary to <file>, requires a binary option (e.g., -V)\n"
" -o <file> save binary to <file>; requires a binary option (e.g., -V)\n"
" -q dump reflection query database; requires -l for linking\n"
" -r | --relaxed-errors\n"
" relaxed GLSL semantic error-checking mode\n"
" -s silence syntax and semantic error reporting\n"
" -t multi-threaded mode\n"
" -u<name>:<loc>\n"
" specify a uniform location override for --aml\n"
" -v | --version\n"
" print version strings\n"
" -w | --suppress-warnings\n"
" suppress GLSL warnings, except as required by \"#extension : warn\"\n"
" suppress GLSL warnings, except as required by '#extension : warn'\n"
" -x save binary output as text-based 32-bit hexadecimal numbers\n"
" -u<name>:<loc> specify a uniform location override for --aml\n"
" --uniform-base <base> set a base to use for generated uniform locations\n"
" --auto-map-bindings | --amb automatically bind uniform variables\n"
" without explicit bindings\n"
" --absolute-path prints absolute path for messages\n"
" --auto-map-binding | --auto-map-bindings | --amb\n"
" automatically bind uniform variables without\n"
" explicit bindings\n"
" --auto-map-locations | --aml automatically locate input/output lacking\n"
" 'location' (fragile, not cross stage)\n"
" --absolute-path Prints absolute path for messages\n"
" --auto-sampled-textures Removes sampler variables and converts\n"
" --auto-sampled-textures removes sampler variables and converts\n"
" existing textures to sampled textures\n"
" --client {vulkan<ver>|opengl<ver>} see -V and -G\n"
" --client {vulkan<ver> | opengl<ver>}\n"
" see -V and -G\n"
" --depfile <file> writes depfile for build systems\n"
" --dump-builtin-symbols prints builtin symbol table prior each compile\n"
" --dump-builtin-symbols prints builtin symbol table prior each\n"
" compile\n"
" -dumpfullversion | -dumpversion print bare major.minor.patchlevel\n"
" --flatten-uniform-arrays | --fua flatten uniform texture/sampler arrays to\n"
" --enhanced-msgs print more readable error messages (GLSL\n"
" only)\n"
" --error-column display the column of the error along the\n"
" line\n"
" --flatten-uniform-array | --flatten-uniform-arrays | --fua\n"
" flatten uniform texture/sampler arrays to\n"
" scalars\n"
" --glsl-version {100 | 110 | 120 | 130 | 140 | 150 |\n"
" 300es | 310es | 320es | 330\n"
" 300es | 310es | 320es | 330 |\n"
" 400 | 410 | 420 | 430 | 440 | 450 | 460}\n"
" set GLSL version, overrides #version\n"
" in shader source\n"
" --hlsl-offsets allow block offsets to follow HLSL rules\n"
" works independently of source language\n"
" --hlsl-iomap perform IO mapping in HLSL register space\n"
" --hlsl-enable-16bit-types allow 16-bit types in SPIR-V for HLSL\n"
" set GLSL version; overrides #version in\n"
" shader source\n"
" --hlsl-dx-position-w W component of SV_Position in HLSL fragment\n"
" shaders compatible with DirectX\n"
" --hlsl-dx9-compatible interprets sampler declarations as a\n"
" texture/sampler combo like DirectX9 would,\n"
" and recognizes DirectX9-specific semantics\n"
" --hlsl-dx-position-w W component of SV_Position in HLSL fragment\n"
" shaders compatible with DirectX\n"
" --hlsl-enable-16bit-types allow 16-bit types in SPIR-V for HLSL\n"
" --hlsl-iomap | --hlsl-iomapper | --hlsl-iomapping\n"
" perform IO mapping in HLSL register space\n"
" --hlsl-offsets allow block offsets to follow HLSL rules;\n"
" works independently of source language\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"
" --lto perform link time optimization\n"
" --nan-clamp favor non-NaN operand in min, max, and clamp\n"
" --no-link only compile shader; do not link (GLSL only)\n"
" NOTE: this option will set the export\n"
" linkage attribute on all functions\n"
" --no-storage-format | --nsf use Unknown image format\n"
" --quiet do not print anything to stdout, unless\n"
" --quiet do not print anything to stdout unless\n"
" requested by another option\n"
" --reflect-strict-array-suffix use strict array suffix rules when\n"
" reflecting\n"
" --reflect-all-block-variables reflect all variables in blocks, whether\n"
" inactive or active\n"
" --reflect-basic-array-suffix arrays of basic types will have trailing [0]\n"
" --reflect-intermediate-io reflection includes inputs/outputs of linked\n"
" shaders rather than just vertex/fragment\n"
" --reflect-separate-buffers reflect buffer variables and blocks\n"
" separately to uniforms\n"
" --reflect-all-block-variables reflect all variables in blocks, whether\n"
" inactive or active\n"
" --reflect-strict-array-suffix use strict array suffix rules when\n"
" reflecting\n"
" --reflect-unwrap-io-blocks unwrap input/output blocks the same as\n"
" uniform blocks\n"
" --resource-set-binding [stage] name set binding\n"
" --resource-set-binding <stage> [name] <set> [binding]...\n"
" set descriptor set and binding for\n"
" individual resources\n"
" --resource-set-binding [stage] set\n"
" --resource-set-binding [stage] <set>\n"
" set descriptor set for all resources\n"
" --rsb synonym for --resource-set-binding\n"
" --set-block-backing name {uniform|buffer|push_constant}\n"
" changes the backing type of a uniform, buffer,\n"
" or push_constant block declared in\n"
" in the program, when using -R option.\n"
" This can be used to change the backing\n"
" for existing blocks as well as implicit ones\n"
" such as 'gl_DefaultUniformBlock'.\n"
" --sbs synonym for set-block-storage\n"
" --set-atomic-counter-block name set\n"
" set name, and descriptor set for\n"
" atomic counter blocks, with -R opt\n"
" --resource-set-bindings | --rsb synonyms for --resource-set-binding\n"
" --set-atomic-counter-block <name> <set>\n"
" set name and descriptor set for atomic\n"
" counter blocks with -R opt\n"
" --sacb synonym for set-atomic-counter-block\n"
" --set-default-uniform-block name set binding\n"
" --set-block-backing name {uniform | buffer | push_constant}\n"
" changes the backing type of a uniform,\n"
" buffer, or push_constant block declared in\n"
" the program when using the -R option; this\n"
" can be used to change the backing for\n"
" existing blocks as well as implicit ones\n"
" such as 'gl_DefaultUniformBlock'\n"
" --set-default-uniform-block <name> <set> <binding>\n"
" set name, descriptor set, and binding for\n"
" global default-uniform-block, with -R opt\n"
" global default-uniform-block with -R opt\n"
" --sdub synonym for set-default-uniform-block\n"
" --shift-image-binding [stage] num\n"
" base binding number for images (uav)\n"
" --shift-image-binding [stage] [num set]...\n"
" --shift-image-binding [stage] <num>\n"
" base binding number for images (UAV)\n"
" --shift-image-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --sib synonym for --shift-image-binding\n"
" --shift-sampler-binding [stage] num\n"
" --shift-image-bindings | --sib synonyms for --shift-image-binding\n"
" --shift-sampler-binding [stage] <num>\n"
" base binding number for samplers\n"
" --shift-sampler-binding [stage] [num set]...\n"
" --shift-sampler-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --ssb synonym for --shift-sampler-binding\n"
" --shift-ssbo-binding [stage] num base binding number for SSBOs\n"
" --shift-ssbo-binding [stage] [num set]...\n"
" --shift-sampler-bindings | --ssb synonyms for --shift-sampler-binding\n"
" --shift-ssbo-binding [stage] <num>\n"
" base binding number for SSBOs\n"
" --shift-ssbo-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --sbb synonym for --shift-ssbo-binding\n"
" --shift-texture-binding [stage] num\n"
" --shift-ssbo-bindings | --sbb synonyms for --shift-ssbo-binding\n"
" --shift-texture-binding [stage] <num>\n"
" base binding number for textures\n"
" --shift-texture-binding [stage] [num set]...\n"
" --shift-texture-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --stb synonym for --shift-texture-binding\n"
" --shift-uav-binding [stage] num base binding number for UAVs\n"
" --shift-uav-binding [stage] [num set]...\n"
" --shift-texture-bindings | --stb synonyms for --shift-texture-binding\n"
" --shift-uav-binding [stage] <num> base binding number for UAVs\n"
" --shift-uav-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --suavb synonym for --shift-uav-binding\n"
" --shift-UBO-binding [stage] num base binding number for UBOs\n"
" --shift-UBO-binding [stage] [num set]...\n"
" --shift-uav-bindings | --suavb synonyms for --shift-uav-binding\n"
" --shift-ubo-binding [stage] <num> base binding number for UBOs\n"
" --shift-ubo-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --sub synonym for --shift-UBO-binding\n"
" --shift-cbuffer-binding | --scb synonyms for --shift-UBO-binding\n"
" --shift-ubo-bindings | --sub |\n"
" --shift-cbuffer-binding | --shift-cbuffer-bindings | --scb\n"
" synonyms for --shift-ubo-binding\n"
" --shift-combined-sampler-binding [stage] <num>\n"
" base binding number for combined samplers\n"
" --shift-combined-sampler-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --shift-combined-sampler-bindings | --scsb\n"
" synonyms for --shift-combined-sampler-binding\n"
" --shift-as-binding [stage] <num>\n"
" base binding number for acceleration structures\n"
" --shift-as-binding [stage] <num> <set>...\n"
" per-descriptor-set shift values\n"
" --shift-as-bindings | --sab\n"
" synonyms for --shift-as-binding\n"
" --spirv-dis output standard-form disassembly; works only\n"
" when a SPIR-V generation option is also used\n"
" --spirv-val execute the SPIRV-Tools validator\n"
" --source-entrypoint <name> the given shader source function is\n"
" renamed to be the <name> given in -e\n"
" --sep synonym for --source-entrypoint\n"
" --source-entrypoint <name> | --sep <name>\n"
" the given shader source function is renamed\n"
" to be the <name> given in -e\n"
" --stdin read from stdin instead of from a file;\n"
" requires providing the shader stage using -S\n"
" --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | vulkan1.3 | opengl |\n"
" spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 |\n"
" spirv1.5 | spirv1.6}\n"
" Set the execution environment that the\n"
" generated code will be executed in.\n"
" Defaults to:\n"
" --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | vulkan1.3 | vulkan1.4 |\n"
" opengl | spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 |\n"
" spirv1.4 | spirv1.5 | spirv1.6}\n"
" set the execution environment the generated\n"
" code will be executed in; defaults to:\n"
" * vulkan1.0 under --client vulkan<ver>\n"
" * opengl under --client opengl<ver>\n"
" * spirv1.0 under --target-env vulkan1.0\n"
" * spirv1.3 under --target-env vulkan1.1\n"
" * spirv1.5 under --target-env vulkan1.2\n"
" * spirv1.6 under --target-env vulkan1.3\n"
" Multiple --target-env can be specified.\n"
" --variable-name <name>\n"
" --vn <name> creates a C header file that contains a\n"
" uint32_t array named <name>\n"
" initialized with the shader binary code\n"
" --no-link Only compile shader; do not link (GLSL-only)\n"
" NOTE: this option will set the export linkage\n"
" attribute on all functions\n"
" --lto perform link time optimization\n"
" * spirv1.6 under --target-env vulkan1.4\n"
" multiple --target-env can be specified\n"
" --uniform-base <base> set a base to use for generated uniform\n"
" locations\n"
" --variable-name <name> | --vn <name>\n"
" creates a C header file that contains a\n"
" uint32_t array named <name> initialized with\n"
" the shader binary code\n"
" --validate-io validate cross stage IO\n");
exit(EFailUsage);

View File

@@ -1,402 +0,0 @@
//
// Copyright (C) 2015 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.
//
#include <iostream>
#include <fstream>
#include <cstring>
#include <stdexcept>
#include <filesystem>
//
// Include remapper
//
#include "../SPIRV/SPVRemapper.h"
namespace {
typedef unsigned int SpvWord;
// Poor man's basename: given a complete path, return file portion.
// E.g:
// Linux: /foo/bar/test -> test
// Win: c:\foo\bar\test -> test
// It's not very efficient, but that doesn't matter for our minimal-duty use.
// Using boost::filesystem would be better in many ways, but want to avoid that dependency.
// OS dependent path separator (avoiding boost::filesystem dependency)
#if defined(_WIN32)
char path_sep_char() { return '\\'; }
#else
char path_sep_char() { return '/'; }
#endif
std::string basename(const std::string filename)
{
const size_t sepLoc = filename.find_last_of(path_sep_char());
return (sepLoc == filename.npos) ? filename : filename.substr(sepLoc+1);
}
void errHandler(const std::string& str) {
std::cout << str << std::endl;
exit(5);
}
void logHandler(const std::string& str) {
std::cout << str << std::endl;
}
// Read word stream from disk
void read(std::vector<SpvWord>& spv, const std::string& inFilename, int verbosity)
{
std::ifstream fp;
if (verbosity > 0)
logHandler(std::string(" reading: ") + inFilename);
spv.clear();
fp.open(inFilename, std::fstream::in | std::fstream::binary);
if (fp.fail())
errHandler("error opening file for read: ");
// Reserve space (for efficiency, not for correctness)
fp.seekg(0, fp.end);
spv.reserve(size_t(fp.tellg()) / sizeof(SpvWord));
fp.seekg(0, fp.beg);
while (!fp.eof()) {
SpvWord inWord;
fp.read((char *)&inWord, sizeof(inWord));
if (!fp.eof()) {
spv.push_back(inWord);
if (fp.fail())
errHandler(std::string("error reading file: ") + inFilename);
}
}
}
// Read strings from a file
void read(std::vector<std::string>& strings, const std::string& inFilename, int verbosity)
{
std::ifstream fp;
if (verbosity > 0)
logHandler(std::string(" reading: ") + inFilename);
strings.clear();
fp.open(inFilename, std::fstream::in);
if (fp.fail())
errHandler("error opening file for read: ");
std::string line;
while (std::getline(fp, line))
{
// Ignore empty lines and lines starting with the comment marker '#'.
if (line.length() == 0 || line[0] == '#') {
continue;
}
strings.push_back(line);
}
}
void write(std::vector<SpvWord>& spv, const std::string& outFile, int verbosity)
{
if (outFile.empty())
errHandler("missing output filename.");
std::ofstream fp;
if (verbosity > 0)
logHandler(std::string(" writing: ") + outFile);
fp.open(outFile, std::fstream::out | std::fstream::binary);
if (fp.fail())
errHandler(std::string("error opening file for write: ") + outFile);
for (auto it = spv.cbegin(); it != spv.cend(); ++it) {
SpvWord word = *it;
fp.write((char *)&word, sizeof(word));
if (fp.fail())
errHandler(std::string("error writing file: ") + outFile);
}
// file is closed by destructor
}
// Print helpful usage message to stdout, and exit
void usage(const char* const name, const char* const msg = nullptr)
{
if (msg)
std::cout << msg << std::endl << std::endl;
std::cout << "Usage: " << std::endl;
std::cout << " " << basename(name)
<< " [-v[v[...]] | --verbose [int]]"
<< " [--map (all|types|names|funcs)]"
<< " [--dce (all|types|funcs)]"
<< " [--opt (all|loadstore)]"
<< " [--strip-all | --strip all | -s]"
<< " [--strip-white-list]"
<< " [--do-everything]"
<< " --input | -i file1 [file2...] --output|-o DESTDIR | destfile1 [destfile2...]"
<< std::endl;
std::cout << " " << basename(name) << " [--version | -V]" << std::endl;
std::cout << " " << basename(name) << " [--help | -?]" << std::endl;
exit(0);
}
// grind through each SPIR in turn
void execute(const std::vector<std::string>& inputFiles,
const std::vector<std::string>& outputDirOrFiles,
const bool isSingleOutputDir,
const std::string& whiteListFile,
int opts,
int verbosity)
{
std::vector<std::string> whiteListStrings;
if (!whiteListFile.empty())
read(whiteListStrings, whiteListFile, verbosity);
for (std::size_t ii=0; ii<inputFiles.size(); ii++) {
std::vector<SpvWord> spv;
read(spv, inputFiles[ii], verbosity);
spv::spirvbin_t(verbosity).remap(spv, whiteListStrings, opts);
if (isSingleOutputDir) {
// write all outputs to same directory
const std::string outFile = outputDirOrFiles[0] + path_sep_char() + basename(inputFiles[ii]);
write(spv, outFile, verbosity);
} else {
// write each input to its associated output
write(spv, outputDirOrFiles[ii], verbosity);
}
}
if (verbosity > 0)
std::cout << "Done: " << inputFiles.size() << " file(s) processed" << std::endl;
}
// Parse command line options
void parseCmdLine(int argc,
char** argv,
std::vector<std::string>& inputFiles,
std::vector<std::string>& outputDirOrFiles,
std::string& stripWhiteListFile,
int& options,
int& verbosity)
{
if (argc < 2)
usage(argv[0]);
verbosity = 0;
options = spv::spirvbin_t::NONE;
// Parse command line.
// boost::program_options would be quite a bit nicer, but we don't want to
// introduce a dependency on boost.
for (int a=1; a<argc; ) {
const std::string arg = argv[a];
if (arg == "--output" || arg == "-o") {
// Collect output dirs or files
for (++a; a < argc && argv[a][0] != '-'; ++a)
outputDirOrFiles.push_back(argv[a]);
if (outputDirOrFiles.size() == 0)
usage(argv[0], "--output requires an argument");
// Remove trailing directory separator characters from all paths
for (std::size_t ii=0; ii<outputDirOrFiles.size(); ii++) {
auto path = outputDirOrFiles[ii];
while (!path.empty() && path.back() == path_sep_char())
path.pop_back();
}
}
else if (arg == "-vv") { verbosity = 2; ++a; } // verbosity shortcuts
else if (arg == "-vvv") { verbosity = 3; ++a; } // ...
else if (arg == "-vvvv") { verbosity = 4; ++a; } // ...
else if (arg == "-vvvvv") { verbosity = 5; ++a; } // ...
else if (arg == "--verbose" || arg == "-v") {
++a;
verbosity = 1;
if (a < argc) {
char* end_ptr = nullptr;
int verb = ::strtol(argv[a], &end_ptr, 10);
// If we have not read to the end of the string or
// the string contained no elements, then we do not want to
// store the value.
if (*end_ptr == '\0' && end_ptr != argv[a]) {
verbosity = verb;
++a;
}
}
}
else if (arg == "--version" || arg == "-V") {
std::cout << basename(argv[0]) << " version 0.97" << std::endl;
exit(0);
} else if (arg == "--input" || arg == "-i") {
// Collect input files
for (++a; a < argc && argv[a][0] != '-'; ++a)
inputFiles.push_back(argv[a]);
} else if (arg == "--do-everything") {
++a;
options = options | spv::spirvbin_t::DO_EVERYTHING;
} else if (arg == "--strip-all" || arg == "-s") {
++a;
options = options | spv::spirvbin_t::STRIP;
} else if (arg == "--strip") {
++a;
if (strncmp(argv[a], "all", 3) == 0) {
options = options | spv::spirvbin_t::STRIP;
++a;
}
} else if (arg == "--strip-white-list") {
++a;
stripWhiteListFile = argv[a++];
} else if (arg == "--dce") {
// Parse comma (or colon, etc) separated list of things to dce
++a;
for (const char* c = argv[a]; *c; ++c) {
if (strncmp(c, "all", 3) == 0) {
options = (options | spv::spirvbin_t::DCE_ALL);
c += 3;
} else if (strncmp(c, "*", 1) == 0) {
options = (options | spv::spirvbin_t::DCE_ALL);
c += 1;
} else if (strncmp(c, "funcs", 5) == 0) {
options = (options | spv::spirvbin_t::DCE_FUNCS);
c += 5;
} else if (strncmp(c, "types", 5) == 0) {
options = (options | spv::spirvbin_t::DCE_TYPES);
c += 5;
}
}
++a;
} else if (arg == "--map") {
// Parse comma (or colon, etc) separated list of things to map
++a;
for (const char* c = argv[a]; *c; ++c) {
if (strncmp(c, "all", 3) == 0) {
options = (options | spv::spirvbin_t::MAP_ALL);
c += 3;
} else if (strncmp(c, "*", 1) == 0) {
options = (options | spv::spirvbin_t::MAP_ALL);
c += 1;
} else if (strncmp(c, "types", 5) == 0) {
options = (options | spv::spirvbin_t::MAP_TYPES);
c += 5;
} else if (strncmp(c, "names", 5) == 0) {
options = (options | spv::spirvbin_t::MAP_NAMES);
c += 5;
} else if (strncmp(c, "funcs", 5) == 0) {
options = (options | spv::spirvbin_t::MAP_FUNCS);
c += 5;
}
}
++a;
} else if (arg == "--opt") {
++a;
for (const char* c = argv[a]; *c; ++c) {
if (strncmp(c, "all", 3) == 0) {
options = (options | spv::spirvbin_t::OPT_ALL);
c += 3;
} else if (strncmp(c, "*", 1) == 0) {
options = (options | spv::spirvbin_t::OPT_ALL);
c += 1;
} else if (strncmp(c, "loadstore", 9) == 0) {
options = (options | spv::spirvbin_t::OPT_LOADSTORE);
c += 9;
}
}
++a;
} else if (arg == "--help" || arg == "-?") {
usage(argv[0]);
} else {
usage(argv[0], "Unknown command line option");
}
}
}
} // namespace
int main(int argc, char** argv)
{
std::vector<std::string> inputFiles;
std::vector<std::string> outputDirOrFiles;
std::string whiteListFile;
int opts;
int verbosity;
// handle errors by exiting
spv::spirvbin_t::registerErrorHandler(errHandler);
// Log messages to std::cout
spv::spirvbin_t::registerLogHandler(logHandler);
if (argc < 2)
usage(argv[0]);
parseCmdLine(argc, argv, inputFiles, outputDirOrFiles, whiteListFile, opts, verbosity);
if (outputDirOrFiles.empty())
usage(argv[0], "Output directory or file(s) required.");
const bool isMultiInput = inputFiles.size() > 1;
const bool isMultiOutput = outputDirOrFiles.size() > 1;
const bool isSingleOutputDir = !isMultiOutput && std::filesystem::is_directory(outputDirOrFiles[0]);
if (isMultiInput && !isMultiOutput && !isSingleOutputDir)
usage(argv[0], "Output is not a directory.");
if (isMultiInput && isMultiOutput && (outputDirOrFiles.size() != inputFiles.size()))
usage(argv[0], "Output must be either a single directory or one output file per input.");
// Main operations: read, remap, and write.
execute(inputFiles, outputDirOrFiles, isSingleOutputDir, whiteListFile, opts, verbosity);
// If we get here, everything went OK! Nothing more to be done.
}

View File

@@ -34,8 +34,8 @@
#ifndef GLSLANG_BUILD_INFO
#define GLSLANG_BUILD_INFO
#define GLSLANG_VERSION_MAJOR 15
#define GLSLANG_VERSION_MINOR 4
#define GLSLANG_VERSION_MAJOR 16
#define GLSLANG_VERSION_MINOR 0
#define GLSLANG_VERSION_PATCH 0
#define GLSLANG_VERSION_FLAVOR ""

View File

@@ -351,6 +351,14 @@ GLSLANG_EXPORT void glslang_shader_set_preamble(glslang_shader_t* shader, const
shader->shader->setPreamble(s);
}
GLSLANG_EXPORT void glslang_shader_set_entry_point(glslang_shader_t* shader, const char* s) {
shader->shader->setEntryPoint(s);
}
GLSLANG_EXPORT void glslang_shader_set_invert_y(glslang_shader_t* shader, bool y) {
shader->shader->setInvertY(y);
}
GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base)
{
const glslang::TResourceType res_type = glslang::TResourceType(res);

View File

@@ -293,7 +293,6 @@ public:
template<class Other>
pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
GLSLANG_EXPORT_FOR_TESTS
pointer allocate(size_type n) {
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
pointer allocate(size_type n, const void*) {

View File

@@ -253,6 +253,8 @@ GLSLANG_EXPORT void glslang_finalize_process(void);
GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader);
GLSLANG_EXPORT void glslang_shader_set_preamble(glslang_shader_t* shader, const char* s);
GLSLANG_EXPORT void glslang_shader_set_entry_point(glslang_shader_t* shader, const char* s);
GLSLANG_EXPORT void glslang_shader_set_invert_y(glslang_shader_t* shader, bool y);
GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base);
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

View File

@@ -224,6 +224,9 @@ typedef enum {
GLSLANG_RESOURCE_TYPE_UBO,
GLSLANG_RESOURCE_TYPE_SSBO,
GLSLANG_RESOURCE_TYPE_UAV,
GLSLANG_RESOURCE_TYPE_COMBINED_SAMPLER,
GLSLANG_RESOURCE_TYPE_AS,
GLSLANG_RESOURCE_TYPE_TENSOR,
LAST_ELEMENT_MARKER(GLSLANG_RESOURCE_TYPE_COUNT),
} glslang_resource_type_t;

View File

@@ -51,4 +51,8 @@
// Symbols marked with this macro are only meant for public use by the test suite
// and do not appear in publicly installed headers. They are not considered to be
// part of the glslang library ABI.
#define GLSLANG_EXPORT_FOR_TESTS GLSLANG_EXPORT
#ifdef GLSLANG_TEST_BUILD
#define GLSLANG_EXPORT_FOR_TESTS GLSLANG_EXPORT
#else
#define GLSLANG_EXPORT_FOR_TESTS
#endif

View File

@@ -3904,12 +3904,15 @@ void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TInterm
const char* TIntermediate::getResourceName(TResourceType res)
{
switch (res) {
case EResSampler: return "shift-sampler-binding";
case EResTexture: return "shift-texture-binding";
case EResImage: return "shift-image-binding";
case EResUbo: return "shift-UBO-binding";
case EResSsbo: return "shift-ssbo-binding";
case EResUav: return "shift-uav-binding";
case EResSampler: return "shift-sampler-binding";
case EResTexture: return "shift-texture-binding";
case EResImage: return "shift-image-binding";
case EResUbo: return "shift-ubo-binding";
case EResSsbo: return "shift-ssbo-binding";
case EResUav: return "shift-uav-binding";
case EResCombinedSampler: return "shift-combined-sampler-binding";
case EResAs: return "shift-as-binding";
case EResTensor: return nullptr;
default:
assert(0); // internal error: should only be called with valid resource types.
return nullptr;

View File

@@ -1862,8 +1862,8 @@ void TParseContext::handleVector2CoopMatConversionCall(const TSourceLoc& loc, co
error(loc, "source and destination element types are not compatible", "", "");
uint32_t scope = spv_Scope_Subgroup;
uint32_t coopMatKHRuse = -1u;
uint32_t coopMatNumRows = -1u, coopMatNumCols = -1u;
uint32_t coopMatKHRuse = !0u;
uint32_t coopMatNumRows = !0u, coopMatNumCols = !0u;
TIntermTyped *nodeNumRows = nullptr, *nodeNumCols = nullptr;
const TTypeParameters* dstTypeParameters = dstType.getTypeParameters();
if (dstTypeParameters->arraySizes == nullptr || dstTypeParameters->arraySizes->getNumDims() != 4) {
@@ -1946,7 +1946,7 @@ void TParseContext::handleVector2CoopMatConversionCall(const TSourceLoc& loc, co
error(loc, "source and destination element types are not compatible", "", "");
uint32_t scope = spv_Scope_Subgroup;
unsigned coopMatKHRuse = -1u;
unsigned coopMatKHRuse = !0u;
const TTypeParameters* srcTypeParameters = srcType.getTypeParameters();
if (srcTypeParameters->arraySizes == nullptr || srcTypeParameters->arraySizes->getNumDims() != 4) {
error(loc, "source cooperative matrix has an unsupported type", "", "");
@@ -2008,7 +2008,7 @@ void TParseContext::handleVector2CoopMatConversionCall(const TSourceLoc& loc, co
{
//int coopMatKHRuse = srcTypeParameters->arraySizes->getDimSize(3);
uint32_t index = -1u;
uint32_t index = !0u;
if (coopMatKHRuse == CM_MatrixUseA) {
index = 2;
} else if (coopMatKHRuse == CM_MatrixUseB) {
@@ -8642,7 +8642,7 @@ static void ForEachOpaque(const TType& type, const TString& path, Function callb
for (size_t dimIndex = 0; dimIndex < indices.size(); ++dimIndex)
{
++indices[dimIndex];
if (indices[dimIndex] < type.getArraySizes()->getDimSize(dimIndex))
if (indices[dimIndex] < type.getArraySizes()->getDimSize(static_cast<int>(dimIndex)))
break;
else
indices[dimIndex] = 0;

View File

@@ -1019,6 +1019,7 @@ uint32_t TDefaultIoResolverBase::computeTypeLocationSize(const TType& type, EShL
//TDefaultGlslIoResolver
TResourceType TDefaultGlslIoResolver::getResourceType(const glslang::TType& type) {
assert(isValidGlslType(type));
if (isImageType(type)) {
return EResImage;
}
@@ -1034,6 +1035,15 @@ TResourceType TDefaultGlslIoResolver::getResourceType(const glslang::TType& type
if (isUboType(type)) {
return EResUbo;
}
if (isCombinedSamplerType(type)) {
return EResCombinedSampler;
}
if (isAsType(type)) {
return EResAs;
}
if (isTensorType(type)) {
return EResTensor;
}
return EResCount;
}
@@ -1383,6 +1393,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
TResourceType getResourceType(const glslang::TType& type) override {
assert(isValidGlslType(type));
if (isImageType(type)) {
return EResImage;
}
@@ -1398,6 +1409,15 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
if (isUboType(type)) {
return EResUbo;
}
if (isCombinedSamplerType(type)) {
return EResCombinedSampler;
}
if (isAsType(type)) {
return EResAs;
}
if (isTensorType(type)) {
return EResTensor;
}
return EResCount;
}
@@ -1483,6 +1503,11 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
if (isUboType(type)) {
return EResUbo;
}
// no support for combined samplers in HLSL
if (isAsType(type)) {
return EResAs;
}
// no support for tensors in HLSL
return EResCount;
}

View File

@@ -120,12 +120,12 @@ protected:
}
static bool isTextureType(const glslang::TType& type) {
return (type.getBasicType() == glslang::EbtSampler &&
return (type.getBasicType() == glslang::EbtSampler && !type.getSampler().isCombined() &&
(type.getSampler().isTexture() || type.getSampler().isSubpass()));
}
static bool isUboType(const glslang::TType& type) {
return type.getQualifier().storage == EvqUniform;
return type.getQualifier().storage == EvqUniform && type.isStruct();
}
static bool isImageType(const glslang::TType& type) {
@@ -136,6 +136,24 @@ protected:
return type.getQualifier().storage == EvqBuffer;
}
static bool isCombinedSamplerType(const glslang::TType& type) {
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isCombined();
}
static bool isAsType(const glslang::TType& type) {
return type.getBasicType() == glslang::EbtAccStruct;
}
static bool isTensorType(const glslang::TType& type) {
return type.isTensorARM();
}
static bool isValidGlslType(const glslang::TType& type) {
// at most one must be true
return (isSamplerType(type) + isTextureType(type) + isUboType(type) + isImageType(type) +
isSsboType(type) + isCombinedSamplerType(type) + isAsType(type) + isTensorType(type)) <= 1;
}
// Return true if this is a SRV (shader resource view) type:
static bool isSrvType(const glslang::TType& type) {
return isTextureType(type) || type.getQualifier().storage == EvqBuffer;

View File

@@ -434,6 +434,9 @@ enum TResourceType {
EResUbo,
EResSsbo,
EResUav,
EResCombinedSampler,
EResAs,
EResTensor,
EResCount
};
@@ -463,59 +466,59 @@ enum TBlockStorageClass
//
// N.B.: Destruct a linked program *before* destructing the shaders linked into it.
//
class TShader {
class GLSLANG_EXPORT TShader {
public:
GLSLANG_EXPORT explicit TShader(EShLanguage);
GLSLANG_EXPORT virtual ~TShader();
GLSLANG_EXPORT void setStrings(const char* const* s, int n);
GLSLANG_EXPORT void setStringsWithLengths(
explicit TShader(EShLanguage);
virtual ~TShader();
void setStrings(const char* const* s, int n);
void setStringsWithLengths(
const char* const* s, const int* l, int n);
GLSLANG_EXPORT void setStringsWithLengthsAndNames(
void setStringsWithLengthsAndNames(
const char* const* s, const int* l, const char* const* names, int n);
void setPreamble(const char* s) { preamble = s; }
GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
GLSLANG_EXPORT void setUniqueId(unsigned long long id);
GLSLANG_EXPORT void setOverrideVersion(int version);
GLSLANG_EXPORT void setDebugInfo(bool debugInfo);
void setEntryPoint(const char* entryPoint);
void setSourceEntryPoint(const char* sourceEntryPointName);
void addProcesses(const std::vector<std::string>&);
void setUniqueId(unsigned long long id);
void setOverrideVersion(int version);
void setDebugInfo(bool debugInfo);
// IO resolver binding data: see comments in ShaderLang.cpp
GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
GLSLANG_EXPORT void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
GLSLANG_EXPORT void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
GLSLANG_EXPORT void setResourceSetBinding(const std::vector<std::string>& base);
GLSLANG_EXPORT void setAutoMapBindings(bool map);
GLSLANG_EXPORT void setAutoMapLocations(bool map);
GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc);
GLSLANG_EXPORT void setUniformLocationBase(int base);
GLSLANG_EXPORT void setInvertY(bool invert);
GLSLANG_EXPORT void setDxPositionW(bool dxPosW);
GLSLANG_EXPORT void setEnhancedMsgs();
void setShiftBinding(TResourceType res, unsigned int base);
void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
void setResourceSetBinding(const std::vector<std::string>& base);
void setAutoMapBindings(bool map);
void setAutoMapLocations(bool map);
void addUniformLocationOverride(const char* name, int loc);
void setUniformLocationBase(int base);
void setInvertY(bool invert);
void setDxPositionW(bool dxPosW);
void setEnhancedMsgs();
#ifdef ENABLE_HLSL
GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap);
GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten);
void setHlslIoMapping(bool hlslIoMap);
void setFlattenUniformArrays(bool flatten);
#endif
GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing);
void setNoStorageFormat(bool useUnknownFormat);
void setNanMinMaxClamp(bool nanMinMaxClamp);
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing);
GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name);
GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name);
GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set);
GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding);
GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set);
GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding);
void setGlobalUniformBlockName(const char* name);
void setAtomicCounterBlockName(const char* name);
void setGlobalUniformSet(unsigned int set);
void setGlobalUniformBinding(unsigned int binding);
void setAtomicCounterBlockSet(unsigned int set);
void setAtomicCounterBlockBinding(unsigned int binding);
GLSLANG_EXPORT void addSourceText(const char* text, size_t len);
GLSLANG_EXPORT void setSourceFile(const char* file);
void addSourceText(const char* text, size_t len);
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
@@ -664,7 +667,7 @@ public:
virtual void releaseInclude(IncludeResult*) override { }
};
GLSLANG_EXPORT bool parse(
bool parse(
const TBuiltInResource*, int defaultVersion, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forwardCompatible,
EShMessages, Includer&);
@@ -690,14 +693,14 @@ public:
// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
// is not an officially supported or fully working path.
GLSLANG_EXPORT bool preprocess(
bool preprocess(
const TBuiltInResource* builtInResources, int defaultVersion,
EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages message, std::string* outputString,
Includer& includer);
GLSLANG_EXPORT const char* getInfoLog();
GLSLANG_EXPORT const char* getInfoDebugLog();
const char* getInfoLog();
const char* getInfoDebugLog();
EShLanguage getStage() const { return stage; }
TIntermediate* getIntermediate() const { return intermediate; }
@@ -744,16 +747,16 @@ private:
//
// Data needed for just a single object at the granularity exchanged by the reflection API
class TObjectReflection {
class GLSLANG_EXPORT TObjectReflection {
public:
GLSLANG_EXPORT TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
const TType* getType() const { return type; }
GLSLANG_EXPORT int getBinding() const;
GLSLANG_EXPORT void dump() const;
int getBinding() const;
void dump() const;
static TObjectReflection badReflection() { return TObjectReflection(); }
GLSLANG_EXPORT unsigned int layoutLocation() const;
unsigned int layoutLocation() const;
std::string name;
int offset;
@@ -804,8 +807,7 @@ struct TVarEntryInfo;
//
// NOTE: that still limit checks are applied to bindings and sets
// and may result in an error.
class TIoMapResolver
{
class GLSLANG_EXPORT TIoMapResolver {
public:
virtual ~TIoMapResolver() {}
@@ -877,41 +879,41 @@ GLSLANG_EXPORT TIoMapper* GetGlslIoMapper();
//
// N.B.: Destruct a linked program *before* destructing the shaders linked into it.
//
class TProgram {
class GLSLANG_EXPORT TProgram {
public:
GLSLANG_EXPORT TProgram();
GLSLANG_EXPORT virtual ~TProgram();
TProgram();
virtual ~TProgram();
void addShader(TShader* shader) { stages[shader->stage].push_back(shader); }
std::list<TShader*>& getShaders(EShLanguage stage) { return stages[stage]; }
// Link Validation interface
GLSLANG_EXPORT bool link(EShMessages);
GLSLANG_EXPORT const char* getInfoLog();
GLSLANG_EXPORT const char* getInfoDebugLog();
bool link(EShMessages);
const char* getInfoLog();
const char* getInfoDebugLog();
TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; }
// Reflection Interface
// call first, to do liveness analysis, index mapping, etc.; returns false on failure
GLSLANG_EXPORT bool buildReflection(int opts = EShReflectionDefault);
GLSLANG_EXPORT unsigned getLocalSize(int dim) const; // return dim'th local size
GLSLANG_EXPORT unsigned getTileShadingRateQCOM(int dim) const; // return dim'th tile shading rate QCOM
GLSLANG_EXPORT int getReflectionIndex(const char *name) const;
GLSLANG_EXPORT int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
GLSLANG_EXPORT int getNumUniformVariables() const;
GLSLANG_EXPORT const TObjectReflection& getUniform(int index) const;
GLSLANG_EXPORT int getNumUniformBlocks() const;
GLSLANG_EXPORT const TObjectReflection& getUniformBlock(int index) const;
GLSLANG_EXPORT int getNumPipeInputs() const;
GLSLANG_EXPORT const TObjectReflection& getPipeInput(int index) const;
GLSLANG_EXPORT int getNumPipeOutputs() const;
GLSLANG_EXPORT const TObjectReflection& getPipeOutput(int index) const;
GLSLANG_EXPORT int getNumBufferVariables() const;
GLSLANG_EXPORT const TObjectReflection& getBufferVariable(int index) const;
GLSLANG_EXPORT int getNumBufferBlocks() const;
GLSLANG_EXPORT const TObjectReflection& getBufferBlock(int index) const;
GLSLANG_EXPORT int getNumAtomicCounters() const;
GLSLANG_EXPORT const TObjectReflection& getAtomicCounter(int index) const;
bool buildReflection(int opts = EShReflectionDefault);
unsigned getLocalSize(int dim) const; // return dim'th local size
unsigned getTileShadingRateQCOM(int dim) const; // return dim'th tile shading rate QCOM
int getReflectionIndex(const char *name) const;
int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
int getNumUniformVariables() const;
const TObjectReflection& getUniform(int index) const;
int getNumUniformBlocks() const;
const TObjectReflection& getUniformBlock(int index) const;
int getNumPipeInputs() const;
const TObjectReflection& getPipeInput(int index) const;
int getNumPipeOutputs() const;
const TObjectReflection& getPipeOutput(int index) const;
int getNumBufferVariables() const;
const TObjectReflection& getBufferVariable(int index) const;
int getNumBufferBlocks() const;
const TObjectReflection& getBufferBlock(int index) const;
int getNumAtomicCounters() const;
const TObjectReflection& getAtomicCounter(int index) const;
// Legacy Reflection Interface - expressed in terms of above interface
@@ -978,19 +980,19 @@ public:
// returns a TType*
const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); }
GLSLANG_EXPORT void dumpReflection();
void dumpReflection();
// Get the IO resolver to use for mapIO
GLSLANG_EXPORT TIoMapResolver* getGlslIoResolver(EShLanguage stage);
TIoMapResolver* getGlslIoResolver(EShLanguage stage);
// I/O mapping: apply base offsets and map live unbound variables
// If resolver is not provided it uses the previous approach
// and respects auto assignment and offsets.
GLSLANG_EXPORT bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
protected:
GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
GLSLANG_EXPORT bool crossStageCheck(EShMessages);
bool linkStage(EShLanguage, EShMessages);
bool crossStageCheck(EShMessages);
TPoolAllocator* pool;
std::list<TShader*> stages[EShLangCount];

View File

@@ -46,7 +46,7 @@ GLSLANG_EXPORT const glslang_resource_t* glslang_default_resource(void);
// Returns the DefaultTBuiltInResource as a human-readable string.
// NOTE: User is responsible for freeing this string.
GLSLANG_EXPORT const char* glslang_default_resource_string();
GLSLANG_EXPORT const char* glslang_default_resource_string(void);
// Decodes the resource limits from |config| to |resources|.
GLSLANG_EXPORT void glslang_decode_resource_limits(glslang_resource_t* resources, char* config);

View File

@@ -42,7 +42,7 @@ const glslang_resource_t* glslang_default_resource(void)
return reinterpret_cast<const glslang_resource_t*>(GetDefaultResources());
}
const char* glslang_default_resource_string()
const char* glslang_default_resource_string(void)
{
std::string cpp_str = GetDefaultTBuiltInResourceString();
char* c_str = (char*)malloc(cpp_str.length() + 1);