mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated glslang.
This commit is contained in:
10
3rdparty/glslang/SPIRV/GlslangToSpv.cpp
vendored
10
3rdparty/glslang/SPIRV/GlslangToSpv.cpp
vendored
@@ -4400,7 +4400,6 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
|
||||
{
|
||||
// Name and decorate the non-hidden members
|
||||
int offset = -1;
|
||||
int locationOffset = 0; // for use within the members of this struct
|
||||
bool memberLocationInvalid = type.isArrayOfArrays() ||
|
||||
(type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false));
|
||||
for (int i = 0; i < (int)glslangMembers->size(); i++) {
|
||||
@@ -4458,10 +4457,6 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
|
||||
if (!memberLocationInvalid && memberQualifier.hasLocation())
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
|
||||
|
||||
if (qualifier.hasLocation()) // track for upcoming inheritance
|
||||
locationOffset += glslangIntermediate->computeTypeLocationSize(
|
||||
glslangMember, glslangIntermediate->getStage());
|
||||
|
||||
// component, XFB, others
|
||||
if (glslangMember.getQualifier().hasComponent())
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationComponent,
|
||||
@@ -5322,7 +5317,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
|
||||
int components = node->getType().getVectorSize();
|
||||
|
||||
if (node->getOp() == glslang::EOpTextureFetch) {
|
||||
if (node->getOp() == glslang::EOpImageLoad ||
|
||||
node->getOp() == glslang::EOpImageLoadLod ||
|
||||
node->getOp() == glslang::EOpTextureFetch ||
|
||||
node->getOp() == glslang::EOpTextureFetchOffset) {
|
||||
// These must produce 4 components, per SPIR-V spec. We'll add a conversion constructor if needed.
|
||||
// This will only happen through the HLSL path for operator[], so we do not have to handle e.g.
|
||||
// the EOpTexture/Proj/Lod/etc family. It would be harmless to do so, but would need more logic
|
||||
|
||||
93
3rdparty/glslang/SPIRV/SpvBuilder.cpp
vendored
93
3rdparty/glslang/SPIRV/SpvBuilder.cpp
vendored
@@ -743,6 +743,26 @@ Id Builder::getContainedTypeId(Id typeId, int member) const
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out the final resulting type of the access chain.
|
||||
Id Builder::getResultingAccessChainType() const
|
||||
{
|
||||
assert(accessChain.base != NoResult);
|
||||
Id typeId = getTypeId(accessChain.base);
|
||||
|
||||
assert(isPointerType(typeId));
|
||||
typeId = getContainedTypeId(typeId);
|
||||
|
||||
for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
|
||||
if (isStructType(typeId)) {
|
||||
assert(isConstantScalar(accessChain.indexChain[i]));
|
||||
typeId = getContainedTypeId(typeId, getConstantScalar(accessChain.indexChain[i]));
|
||||
} else
|
||||
typeId = getContainedTypeId(typeId, accessChain.indexChain[i]);
|
||||
}
|
||||
|
||||
return typeId;
|
||||
}
|
||||
|
||||
// Return the immediately contained type of a given composite type.
|
||||
Id Builder::getContainedTypeId(Id typeId) const
|
||||
{
|
||||
@@ -1585,16 +1605,7 @@ Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMa
|
||||
Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
|
||||
{
|
||||
// Figure out the final resulting type.
|
||||
spv::Id typeId = getTypeId(base);
|
||||
assert(isPointerType(typeId) && offsets.size() > 0);
|
||||
typeId = getContainedTypeId(typeId);
|
||||
for (int i = 0; i < (int)offsets.size(); ++i) {
|
||||
if (isStructType(typeId)) {
|
||||
assert(isConstantScalar(offsets[i]));
|
||||
typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
|
||||
} else
|
||||
typeId = getContainedTypeId(typeId, offsets[i]);
|
||||
}
|
||||
Id typeId = getResultingAccessChainType();
|
||||
typeId = makePointer(storageClass, typeId);
|
||||
|
||||
// Make the instruction
|
||||
@@ -2794,28 +2805,58 @@ void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAcce
|
||||
assert(accessChain.isRValue == false);
|
||||
|
||||
transferAccessChainSwizzle(true);
|
||||
Id base = collapseAccessChain();
|
||||
addDecoration(base, nonUniform);
|
||||
|
||||
Id source = rvalue;
|
||||
// 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() &&
|
||||
accessChain.component == NoResult) {
|
||||
for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
|
||||
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i]));
|
||||
|
||||
// dynamic component should be gone
|
||||
assert(accessChain.component == NoResult);
|
||||
Id base = collapseAccessChain();
|
||||
addDecoration(base, nonUniform);
|
||||
|
||||
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
|
||||
// extract and insert elements to perform writeMask and/or swizzle.
|
||||
if (accessChain.swizzle.size() > 0) {
|
||||
Id tempBaseId = createLoad(base, spv::NoPrecision);
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
|
||||
accessChain.indexChain.pop_back();
|
||||
accessChain.instr = NoResult;
|
||||
|
||||
// dynamic component should be gone
|
||||
assert(accessChain.component == NoResult);
|
||||
|
||||
Id source = createCompositeExtract(rvalue, getContainedTypeId(getTypeId(rvalue)), i);
|
||||
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope, alignment);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Id base = collapseAccessChain();
|
||||
addDecoration(base, nonUniform);
|
||||
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
Id source = rvalue;
|
||||
|
||||
// dynamic component should be gone
|
||||
assert(accessChain.component == NoResult);
|
||||
|
||||
// If swizzle still exists, it may be out-of-order, we must load the target vector,
|
||||
// extract and insert elements to perform writeMask and/or swizzle.
|
||||
if (accessChain.swizzle.size() > 0) {
|
||||
Id tempBaseId = createLoad(base, spv::NoPrecision);
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
|
||||
}
|
||||
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope, alignment);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope, alignment);
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
|
||||
1
3rdparty/glslang/SPIRV/SpvBuilder.h
vendored
1
3rdparty/glslang/SPIRV/SpvBuilder.h
vendored
@@ -202,6 +202,7 @@ public:
|
||||
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
|
||||
ImageFormat getImageTypeFormat(Id typeId) const
|
||||
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
|
||||
Id getResultingAccessChainType() const;
|
||||
|
||||
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
|
||||
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
|
||||
|
||||
6
3rdparty/glslang/StandAlone/StandAlone.cpp
vendored
6
3rdparty/glslang/StandAlone/StandAlone.cpp
vendored
@@ -347,13 +347,13 @@ void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res)
|
||||
lang = FindLanguage(argv[arg++], false);
|
||||
}
|
||||
|
||||
if ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) {
|
||||
if ((argc - arg) >= 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) {
|
||||
// Parse a per-set binding base
|
||||
while ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) {
|
||||
do {
|
||||
const int baseNum = atoi(argv[arg++]);
|
||||
const int setNum = atoi(argv[arg++]);
|
||||
perSetBase[setNum] = baseNum;
|
||||
}
|
||||
} while ((argc - arg) >= 2 && isdigit(argv[arg + 0][0]) && isdigit(argv[arg + 1][0]));
|
||||
} else {
|
||||
// Parse single binding base
|
||||
singleBase = atoi(argv[arg++]);
|
||||
|
||||
@@ -6689,12 +6689,6 @@ void HlslParseContext::globalQualifierFix(const TSourceLoc&, TQualifier& qualifi
|
||||
|
||||
//
|
||||
// Merge characteristics of the 'src' qualifier into the 'dst'.
|
||||
// If there is duplication, issue error messages, unless 'force'
|
||||
// is specified, which means to just override default settings.
|
||||
//
|
||||
// Also, when force is false, it will be assumed that 'src' follows
|
||||
// 'dst', for the purpose of error checking order for versions
|
||||
// that require specific orderings of qualifiers.
|
||||
//
|
||||
void HlslParseContext::mergeQualifiers(TQualifier& dst, const TQualifier& src)
|
||||
{
|
||||
@@ -6712,8 +6706,7 @@ void HlslParseContext::mergeQualifiers(TQualifier& dst, const TQualifier& src)
|
||||
mergeObjectLayoutQualifiers(dst, src, false);
|
||||
|
||||
// individual qualifiers
|
||||
bool repeated = false;
|
||||
#define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field;
|
||||
#define MERGE_SINGLETON(field) dst.field |= src.field;
|
||||
MERGE_SINGLETON(invariant);
|
||||
MERGE_SINGLETON(noContraction);
|
||||
MERGE_SINGLETON(centroid);
|
||||
|
||||
@@ -1739,7 +1739,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
|
||||
case EbtUint:
|
||||
switch (from) {
|
||||
case EbtInt:
|
||||
return version >= 400 || getSource() == EShSourceHlsl;
|
||||
return version >= 400 || getSource() == EShSourceHlsl || IsRequestedExtension(E_GL_ARB_gpu_shader5);
|
||||
case EbtBool:
|
||||
return getSource() == EShSourceHlsl;
|
||||
case EbtInt16:
|
||||
@@ -2676,7 +2676,11 @@ TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors<selectorType>& selecto
|
||||
// 'swizzleOkay' says whether or not it is okay to consider a swizzle
|
||||
// a valid part of the dereference chain.
|
||||
//
|
||||
const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay)
|
||||
// 'BufferReferenceOk' says if type is buffer_reference, the routine stop to find the most left node.
|
||||
//
|
||||
//
|
||||
|
||||
const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay , bool bufferReferenceOk)
|
||||
{
|
||||
do {
|
||||
const TIntermBinary* binary = node->getAsBinaryNode();
|
||||
@@ -2694,6 +2698,8 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
|
||||
return nullptr;
|
||||
}
|
||||
node = node->getAsBinaryNode()->getLeft();
|
||||
if (bufferReferenceOk && node->isReference())
|
||||
return node;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
@@ -327,6 +327,16 @@ void TParseContext::setAtomicCounterBlockDefaults(TType& block) const
|
||||
block.getQualifier().layoutMatrix = ElmRowMajor;
|
||||
}
|
||||
|
||||
void TParseContext::setInvariant(const TSourceLoc& loc, const char* builtin) {
|
||||
TSymbol* symbol = symbolTable.find(builtin);
|
||||
if (symbol && symbol->getType().getQualifier().isPipeOutput()) {
|
||||
if (intermediate.inIoAccessed(builtin))
|
||||
warn(loc, "changing qualification after use", "invariant", builtin);
|
||||
TSymbol* csymbol = symbolTable.copyUp(symbol);
|
||||
csymbol->getWritableType().getQualifier().invariant = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
|
||||
{
|
||||
#ifndef GLSLANG_WEB
|
||||
@@ -404,8 +414,33 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
|
||||
intermediate.setUseVariablePointers();
|
||||
} else if (tokens[0].compare("once") == 0) {
|
||||
warn(loc, "not implemented", "#pragma once", "");
|
||||
} else if (tokens[0].compare("glslang_binary_double_output") == 0)
|
||||
} else if (tokens[0].compare("glslang_binary_double_output") == 0) {
|
||||
intermediate.setBinaryDoubleOutput();
|
||||
} else if (spvVersion.spv > 0 && tokens[0].compare("STDGL") == 0 &&
|
||||
tokens[1].compare("invariant") == 0 && tokens[3].compare("all") == 0) {
|
||||
intermediate.setInvariantAll();
|
||||
// Set all builtin out variables invariant if declared
|
||||
setInvariant(loc, "gl_Position");
|
||||
setInvariant(loc, "gl_PointSize");
|
||||
setInvariant(loc, "gl_ClipDistance");
|
||||
setInvariant(loc, "gl_CullDistance");
|
||||
setInvariant(loc, "gl_TessLevelOuter");
|
||||
setInvariant(loc, "gl_TessLevelInner");
|
||||
setInvariant(loc, "gl_PrimitiveID");
|
||||
setInvariant(loc, "gl_Layer");
|
||||
setInvariant(loc, "gl_ViewportIndex");
|
||||
setInvariant(loc, "gl_FragDepth");
|
||||
setInvariant(loc, "gl_SampleMask");
|
||||
setInvariant(loc, "gl_ClipVertex");
|
||||
setInvariant(loc, "gl_FrontColor");
|
||||
setInvariant(loc, "gl_BackColor");
|
||||
setInvariant(loc, "gl_FrontSecondaryColor");
|
||||
setInvariant(loc, "gl_BackSecondaryColor");
|
||||
setInvariant(loc, "gl_TexCoord");
|
||||
setInvariant(loc, "gl_FogFragCoord");
|
||||
setInvariant(loc, "gl_FragColor");
|
||||
setInvariant(loc, "gl_FragData");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2409,6 +2444,14 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
|
||||
arg0->getType().isFloatingDomain()) {
|
||||
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str());
|
||||
}
|
||||
|
||||
const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true , true);
|
||||
const TType* refType = (base->getType().isReference()) ? base->getType().getReferentType() : nullptr;
|
||||
const TQualifier& qualifier = (refType != nullptr) ? refType->getQualifier() : base->getType().getQualifier();
|
||||
if (qualifier.storage != EvqShared && qualifier.storage != EvqBuffer)
|
||||
error(loc,"Atomic memory function can only be used for shader storage block member or shared variable.",
|
||||
fnCandidate.getName().c_str(), "");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3651,6 +3694,8 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
|
||||
profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs");
|
||||
profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs");
|
||||
qualifier.storage = EvqVaryingOut;
|
||||
if (intermediate.isInvariantAll())
|
||||
qualifier.invariant = true;
|
||||
break;
|
||||
case EvqInOut:
|
||||
qualifier.storage = EvqVaryingIn;
|
||||
@@ -3667,7 +3712,7 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
|
||||
if (blockName == nullptr &&
|
||||
qualifier.layoutPacking == ElpStd430)
|
||||
{
|
||||
error(loc, "it is invalid to declare std430 qualifier on uniform", "", "");
|
||||
requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "default std430 layout for uniform");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -241,6 +241,7 @@ protected:
|
||||
// override this to set the language-specific name
|
||||
virtual const char* getAtomicCounterBlockName() const { return ""; }
|
||||
virtual void setAtomicCounterBlockDefaults(TType&) const {}
|
||||
virtual void setInvariant(const TSourceLoc& loc, const char* builtin) {}
|
||||
virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
|
||||
bool isAtomicCounterBlock(const TSymbol& symbol) {
|
||||
const TVariable* var = symbol.getAsVariable();
|
||||
@@ -511,6 +512,7 @@ protected:
|
||||
virtual const char* getAtomicCounterBlockName() const override;
|
||||
virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
|
||||
virtual void setAtomicCounterBlockDefaults(TType& block) const override;
|
||||
virtual void setInvariant(const TSourceLoc& loc, const char* builtin) override;
|
||||
|
||||
public:
|
||||
//
|
||||
|
||||
@@ -316,6 +316,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
|
||||
MERGE_TRUE(useUnknownFormat);
|
||||
MERGE_TRUE(hlslOffsets);
|
||||
MERGE_TRUE(useStorageBuffer);
|
||||
MERGE_TRUE(invariantAll);
|
||||
MERGE_TRUE(hlslIoMapping);
|
||||
|
||||
// TODO: sourceFile
|
||||
|
||||
@@ -291,6 +291,7 @@ public:
|
||||
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
|
||||
invertY(false),
|
||||
useStorageBuffer(false),
|
||||
invariantAll(false),
|
||||
nanMinMaxClamp(false),
|
||||
depthReplacing(false),
|
||||
uniqueId(0),
|
||||
@@ -538,7 +539,7 @@ public:
|
||||
TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
|
||||
|
||||
// Tree ops
|
||||
static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay);
|
||||
static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false);
|
||||
|
||||
// Linkage related
|
||||
void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
|
||||
@@ -560,6 +561,8 @@ public:
|
||||
|
||||
void setUseStorageBuffer() { useStorageBuffer = true; }
|
||||
bool usingStorageBuffer() const { return useStorageBuffer; }
|
||||
void setInvariantAll() { invariantAll = true; }
|
||||
bool isInvariantAll() const { return invariantAll; }
|
||||
void setDepthReplacing() { depthReplacing = true; }
|
||||
bool isDepthReplacing() const { return depthReplacing; }
|
||||
bool setLocalSize(int dim, int size)
|
||||
@@ -926,6 +929,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsRequestedExtension(const char* extension) const
|
||||
{
|
||||
return (requestedExtensions.find(extension) != requestedExtensions.end());
|
||||
}
|
||||
|
||||
void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
|
||||
void merge(TInfoSink&, TIntermediate&);
|
||||
void finalCheck(TInfoSink&, bool keepUncalled);
|
||||
@@ -1063,6 +1071,7 @@ protected:
|
||||
bool recursive;
|
||||
bool invertY;
|
||||
bool useStorageBuffer;
|
||||
bool invariantAll;
|
||||
bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN
|
||||
bool depthReplacing;
|
||||
int localSize[3];
|
||||
|
||||
Reference in New Issue
Block a user