Updated glslang.

This commit is contained in:
Бранимир Караџић 2020-11-07 14:45:59 -08:00
parent e4fdbb8264
commit bdcdf600c2
26 changed files with 5059 additions and 3843 deletions

View File

@ -36,5 +36,6 @@ static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fu
static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
#endif // #ifndef GLSLextEXT_H

View File

@ -714,8 +714,12 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
glslangIntermediate->getStage() == EShLangTessControl ||
glslangIntermediate->getStage() == EShLangTessEvaluation) {
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
if (builder.getSpvVersion() < spv::Spv_1_5) {
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
}
else
builder.addCapability(spv::CapabilityShaderViewportIndex);
}
return spv::BuiltInViewportIndex;
@ -739,8 +743,11 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
glslangIntermediate->getStage() == EShLangTessControl ||
glslangIntermediate->getStage() == EShLangTessEvaluation) {
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
if (builder.getSpvVersion() < spv::Spv_1_5) {
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
} else
builder.addCapability(spv::CapabilityShaderLayer);
}
return spv::BuiltInLayer;
@ -1081,6 +1088,10 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
builder.addCapability(spv::CapabilityStorageImageExtendedFormats);
break;
case glslang::ElfR64ui:
case glslang::ElfR64i:
builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
builder.addCapability(spv::CapabilityInt64ImageEXT);
default:
break;
}
@ -1127,6 +1138,8 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
case glslang::ElfRg8ui: return spv::ImageFormatRg8ui;
case glslang::ElfR16ui: return spv::ImageFormatR16ui;
case glslang::ElfR8ui: return spv::ImageFormatR8ui;
case glslang::ElfR64ui: return spv::ImageFormatR64ui;
case glslang::ElfR64i: return spv::ImageFormatR64i;
default: return spv::ImageFormatMax;
}
}
@ -3587,6 +3600,12 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
builder.addCapability(spv::CapabilityFloat16ImageAMD);
return builder.makeFloatType(16);
case glslang::EbtInt64: return builder.makeIntType(64);
builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
builder.addCapability(spv::CapabilityFloat16ImageAMD);
case glslang::EbtUint64: return builder.makeUintType(64);
builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
builder.addCapability(spv::CapabilityFloat16ImageAMD);
#endif
default:
assert(0);
@ -3952,6 +3971,8 @@ 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++) {
glslang::TType& glslangMember = *(*glslangMembers)[i].type;
int member = i;
@ -4004,7 +4025,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
// just track whether a member needs to be decorated.
// Ignore member locations if the container is an array, as that's
// ill-specified and decisions have been made to not allow this.
if (! type.isArray() && memberQualifier.hasLocation())
if (!memberLocationInvalid && memberQualifier.hasLocation())
builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
if (qualifier.hasLocation()) // track for upcoming inheritance

View File

@ -44,7 +44,6 @@
#include "SpvTools.h"
#include "spirv-tools/optimizer.hpp"
#include "spirv-tools/libspirv.h"
namespace glslang {
@ -114,11 +113,18 @@ void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
out << std::endl;
}
// Use the SPIRV-Tools disassembler to print SPIR-V.
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
{
SpirvToolsDisassemble(out, spirv, spv_target_env::SPV_ENV_UNIVERSAL_1_3);
}
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
spv_target_env requested_context)
{
// disassemble
spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
spv_context context = spvContextCreate(requested_context);
spv_text text;
spv_diagnostic diagnostic = nullptr;
spvBinaryToText(context, spirv.data(), spirv.size(),
@ -174,10 +180,7 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
// line information into all SPIR-V instructions. This avoids loss of
// information when instructions are deleted or moved. Later, remove
// redundant information to minimize final SPRIR-V size.
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
}
else if (options->stripDebugInfo) {
if (options->stripDebugInfo) {
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
}
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
@ -207,9 +210,6 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
}
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
}
spvtools::OptimizerOptions spvOptOptions;
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));

View File

@ -41,9 +41,10 @@
#ifndef GLSLANG_SPV_TOOLS_H
#define GLSLANG_SPV_TOOLS_H
#ifdef ENABLE_OPT
#if ENABLE_OPT
#include <vector>
#include <ostream>
#include "spirv-tools/libspirv.h"
#endif
#include "glslang/MachineIndependent/localintermediate.h"
@ -62,11 +63,15 @@ struct SpvOptions {
bool validate;
};
#ifdef ENABLE_OPT
#if ENABLE_OPT
// Use the SPIRV-Tools disassembler to print SPIR-V.
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
spv_target_env requested_context);
// Apply the SPIRV-Tools validator to generated SPIR-V.
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, bool prelegalization);

View File

@ -523,6 +523,8 @@ const char* ImageFormatString(int format)
case 37: return "Rg8ui";
case 38: return "R16ui";
case 39: return "R8ui";
case 40: return "R64ui";
case 41: return "R64i";
default:
return "Bad";
@ -958,6 +960,7 @@ const char* CapabilityString(int info)
case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
case CapabilityShaderClockKHR: return "ShaderClockKHR";
case CapabilityInt64ImageEXT: return "Int64ImageEXT";
case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL";

View File

@ -41,7 +41,6 @@ target_include_directories(glslang-default-resource-limits
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)
set(SOURCES StandAlone.cpp DirStackFileIncluder.h)
add_executable(glslangValidator ${SOURCES})
@ -70,6 +69,12 @@ target_include_directories(glslangValidator PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/External>)
if(ENABLE_OPT)
target_include_directories(glslangValidator
PRIVATE ${spirv-tools_SOURCE_DIR}/include
)
endif(ENABLE_OPT)
if(ENABLE_SPVREMAPPER)
set(REMAPPER_SOURCES spirv-remap.cpp)
add_executable(spirv-remap ${REMAPPER_SOURCES})

View File

@ -406,6 +406,7 @@ enum TLayoutFormat {
ElfRg8i,
ElfR16i,
ElfR8i,
ElfR64i,
ElfIntGuard, // to help with comparisons
@ -423,6 +424,7 @@ enum TLayoutFormat {
ElfRg8ui,
ElfR16ui,
ElfR8ui,
ElfR64ui,
ElfCount
};
@ -1117,6 +1119,8 @@ public:
case ElfR32ui: return "r32ui";
case ElfR16ui: return "r16ui";
case ElfR8ui: return "r8ui";
case ElfR64ui: return "r64ui";
case ElfR64i: return "r64i";
default: return "none";
}
}

View File

@ -1282,6 +1282,8 @@ public:
TIntermTyped* getConstSubtree() const { return constSubtree; }
#ifndef GLSLANG_WEB
void setFlattenSubset(int subset) { flattenSubset = subset; }
virtual const TString& getAccessName() const;
int getFlattenSubset() const { return flattenSubset; } // -1 means full object
#endif

View File

@ -509,6 +509,8 @@ TBuiltIns::TBuiltIns()
prefixes[EbtUint8] = "u8";
prefixes[EbtInt16] = "i16";
prefixes[EbtUint16] = "u16";
prefixes[EbtInt64] = "i64";
prefixes[EbtUint64] = "u64";
#endif
postfixes[2] = "2";
@ -5724,6 +5726,45 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag4HorizontalPixelsEXT = 8;\n");
}
}
// GL_EXT_shader_image_int64
if ((profile != EEsProfile && version >= 420) ||
(profile == EEsProfile && version >= 310)) {
const TBasicType bTypes[] = { EbtInt64, EbtUint64 };
for (int ms = 0; ms <= 1; ++ms) { // loop over "bool" multisample or not
for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not
for (int dim = Esd1D; dim < EsdSubpass; ++dim) { // 1D, ..., buffer
if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile)
continue;
if ((dim == Esd3D || dim == EsdRect || dim == EsdBuffer) && arrayed)
continue;
if (dim != Esd2D && ms)
continue;
// Loop over the bTypes
for (size_t bType = 0; bType < sizeof(bTypes)/sizeof(TBasicType); ++bType) {
//
// Now, make all the function prototypes for the type we just built...
//
TSampler sampler;
sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false,
false,
ms ? true : false);
TString typeName = sampler.getString();
addQueryFunctions(sampler, typeName, version, profile);
addImageFunctions(sampler, typeName, version, profile);
}
}
}
}
}
#endif // !GLSLANG_WEB
// printf("%s\n", commonBuiltins.c_str());
@ -5820,7 +5861,6 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c
#endif
if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint))
continue;
//
// Now, make all the function prototypes for the type we just built...
//
@ -6045,8 +6085,16 @@ void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int
if ( profile != EEsProfile ||
(profile == EEsProfile && version >= 310)) {
if (sampler.type == EbtInt || sampler.type == EbtUint) {
const char* dataType = sampler.type == EbtInt ? "highp int" : "highp uint";
if (sampler.type == EbtInt || sampler.type == EbtUint || sampler.type == EbtInt64 || sampler.type == EbtUint64 ) {
const char* dataType;
switch (sampler.type) {
case(EbtInt): dataType = "highp int"; break;
case(EbtUint): dataType = "highp uint"; break;
case(EbtInt64): dataType = "highp int64_t"; break;
case(EbtUint64): dataType = "highp uint64_t"; break;
default: dataType = "";
}
const int numBuiltins = 7;

View File

@ -71,6 +71,13 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it)
it->visitConstantUnion(this);
}
const TString& TIntermSymbol::getAccessName() const {
if (getBasicType() == EbtBlock)
return getType().getTypeName();
else
return getName();
}
//
// Traverse a binary node.
//

View File

@ -127,22 +127,6 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
{
TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) {
switch(binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect: // fall through
case EOpIndexDirectStruct: // fall through
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
return lValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
}
error(loc, " l-value required", op, "", "");
return true;
}
const char* symbol = nullptr;
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode != nullptr)
@ -203,15 +187,40 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
// Everything else is okay, no error.
//
if (message == nullptr)
{
if (binaryNode) {
switch (binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect: // fall through
case EOpIndexDirectStruct: // fall through
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
return lValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
}
error(loc, " l-value required", op, "", "");
return true;
}
return false;
}
//
// If we get here, we have an error and a message.
//
const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
if (symNode)
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
else
error(loc, " l-value required", op, "(%s)", message);
if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct)
if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message);
else
error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message);
else
error(loc, " l-value required", op, "(%s)", message);
return true;
}
@ -219,28 +228,41 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
// Test for and give an error if the node can't be read from.
void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
{
TIntermBinary* binaryNode = node->getAsBinaryNode();
const TIntermSymbol* symNode = node->getAsSymbolNode();
if (! node)
return;
TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) {
switch(binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect:
case EOpIndexDirectStruct:
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
rValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
if (node->getQualifier().isWriteOnly()) {
const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
if (symNode != nullptr)
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
else if (binaryNode &&
(binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct ||
binaryNode->getAsOperator()->getOp() == EOpIndexDirect))
if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str());
else
error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str());
else
error(loc, "can't read from writeonly object: ", op, "");
} else {
if (binaryNode) {
switch (binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect:
case EOpIndexDirectStruct:
case EOpVectorSwizzle:
case EOpMatrixSwizzle:
rValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
}
}
return;
}
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode && symNode->getQualifier().isWriteOnly())
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
}
// Add 'symbol' to the list of deferred linkage symbols, which

View File

@ -2121,9 +2121,15 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
{
// Make sure the image types have the correct layout() format and correct argument types
const TType& imageType = arg0->getType();
if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint ||
imageType.getSampler().type == EbtInt64 || imageType.getSampler().type == EbtUint64) {
if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui &&
imageType.getQualifier().getFormat() != ElfR64i && imageType.getQualifier().getFormat() != ElfR64ui)
error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
if (callNode.getType().getBasicType() == EbtInt64 && imageType.getQualifier().getFormat() != ElfR64i)
error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), "");
else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui)
error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), "");
} else {
bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
(fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
@ -3368,7 +3374,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
//
void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
{
globalQualifierFixCheck(publicType.loc, publicType.qualifier);
globalQualifierFixCheck(publicType.loc, publicType.qualifier, true);
checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
if (publicType.qualifier.isNonUniform()) {
error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
@ -3379,7 +3385,7 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
//
// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
//
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier)
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck)
{
bool nonuniformOkay = false;
@ -3404,6 +3410,16 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
case EvqTemporary:
nonuniformOkay = true;
break;
case EvqUniform:
// According to GLSL spec: The std430 qualifier is supported only for shader storage blocks; a shader using
// the std430 qualifier on a uniform block will fail to compile.
// Only check the global declaration: layout(std430) uniform;
if (blockName == nullptr &&
qualifier.layoutPacking == ElpStd430)
{
error(loc, "it is invalid to declare std430 qualifier on uniform", "", "");
}
break;
default:
break;
}
@ -3411,7 +3427,9 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
if (!nonuniformOkay && qualifier.isNonUniform())
error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
invariantCheck(loc, qualifier);
// Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
if (!isMemberCheck || structNestingLevel > 0)
invariantCheck(loc, qualifier);
}
//
@ -4083,6 +4101,9 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType
if (isRuntimeLength(base))
return;
if (base.getType().getQualifier().builtIn == EbvSampleMask)
return;
// Check for last member of a bufferreference type, which is runtime sizeable
// but doesn't support runtime length
if (base.getType().getQualifier().storage == EvqBuffer) {
@ -4634,14 +4655,14 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
{
if (structNestingLevel > 0)
if (structNestingLevel > 0 || blockNestingLevel > 0)
error(loc, "cannot nest a block definition inside a structure or block", "", "");
++structNestingLevel;
++blockNestingLevel;
}
void TParseContext::nestedStructCheck(const TSourceLoc& loc)
{
if (structNestingLevel > 0)
if (structNestingLevel > 0 || blockNestingLevel > 0)
error(loc, "cannot nest a structure definition inside a structure or block", "", "");
++structNestingLevel;
}
@ -6537,13 +6558,15 @@ void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType
error(loc, "atomic_uint binding is too large", "binding", "");
return;
}
if(publicType.qualifier.hasOffset()) {
if (publicType.qualifier.hasOffset())
atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
}
return;
}
if (publicType.arraySizes) {
error(loc, "expect an array name", "", "");
}
if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference())
warn(loc, "useless application of layout qualifier", "layout", "");
#endif
@ -6634,6 +6657,22 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
if (type.getQualifier().storage == EvqShared && type.containsCoopMat())
error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
if (profile == EEsProfile) {
if (type.getQualifier().isPipeInput() && type.getBasicType() == EbtStruct) {
if (type.getQualifier().isArrayedIo(language)) {
TType perVertexType(type, 0);
if (perVertexType.containsArray() && perVertexType.containsBuiltIn() == false) {
error(loc, "A per vertex structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), "");
}
}
else if (type.containsArray() && type.containsBuiltIn() == false) {
error(loc, "A structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), "");
}
if (type.containsStructure())
error(loc, "A structure containing an struct is not allowed as input in ES", type.getTypeName().c_str(), "");
}
}
if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone)
@ -6956,6 +6995,15 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
return nullptr;
}
TBasicType destType = type.getBasicType();
for (int i = 0; i < type.getVectorSize(); ++i) {
TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType();
if (destType != initType && !intermediate.canImplicitlyPromote(initType, destType)) {
error(loc, "type mismatch in initializer list", "initializer list", type.getCompleteString().c_str());
return nullptr;
}
}
} else {
error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
return nullptr;
@ -7492,10 +7540,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
TType& memberType = *typeList[member].type;
TQualifier& memberQualifier = memberType.getQualifier();
const TSourceLoc& memberLoc = typeList[member].loc;
globalQualifierFixCheck(memberLoc, memberQualifier);
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
memberQualifier.storage = currentBlockQualifier.storage;
globalQualifierFixCheck(memberLoc, memberQualifier);
#ifndef GLSLANG_WEB
inheritMemoryQualifiers(currentBlockQualifier, memberQualifier);
if (currentBlockQualifier.perPrimitiveNV)
@ -8193,7 +8241,7 @@ void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qual
bool pipeOut = qualifier.isPipeOutput();
bool pipeIn = qualifier.isPipeInput();
if (version >= 300 || (!isEsProfile() && version >= 420)) {
if ((version >= 300 && isEsProfile()) || (!isEsProfile() && version >= 420)) {
if (! pipeOut)
error(loc, "can only apply to an output", "invariant", "");
} else {

View File

@ -83,7 +83,7 @@ public:
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
scopeMangler("::"),
symbolTable(symbolTable),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
currentFunctionType(nullptr),
postEntryPointReturn(false),
contextPragma(true, false),
@ -178,7 +178,8 @@ public:
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
int statementNestingLevel; // 0 if outside all flow control or compound statements
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
int structNestingLevel; // 0 if outside structures
int blockNestingLevel; // 0 if outside blocks
int controlFlowNestingLevel; // 0 if outside all flow control
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
@ -365,7 +366,7 @@ public:
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
void memberQualifierCheck(glslang::TPublicType&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);

View File

@ -471,6 +471,28 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY;
(*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY;
(*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY;
(*KeywordMap)["i64image1D"] = I64IMAGE1D;
(*KeywordMap)["u64image1D"] = U64IMAGE1D;
(*KeywordMap)["i64image2D"] = I64IMAGE2D;
(*KeywordMap)["u64image2D"] = U64IMAGE2D;
(*KeywordMap)["i64image3D"] = I64IMAGE3D;
(*KeywordMap)["u64image3D"] = U64IMAGE3D;
(*KeywordMap)["i64image2DRect"] = I64IMAGE2DRECT;
(*KeywordMap)["u64image2DRect"] = U64IMAGE2DRECT;
(*KeywordMap)["i64imageCube"] = I64IMAGECUBE;
(*KeywordMap)["u64imageCube"] = U64IMAGECUBE;
(*KeywordMap)["i64imageBuffer"] = I64IMAGEBUFFER;
(*KeywordMap)["u64imageBuffer"] = U64IMAGEBUFFER;
(*KeywordMap)["i64image1DArray"] = I64IMAGE1DARRAY;
(*KeywordMap)["u64image1DArray"] = U64IMAGE1DARRAY;
(*KeywordMap)["i64image2DArray"] = I64IMAGE2DARRAY;
(*KeywordMap)["u64image2DArray"] = U64IMAGE2DARRAY;
(*KeywordMap)["i64imageCubeArray"] = I64IMAGECUBEARRAY;
(*KeywordMap)["u64imageCubeArray"] = U64IMAGECUBEARRAY;
(*KeywordMap)["i64image2DMS"] = I64IMAGE2DMS;
(*KeywordMap)["u64image2DMS"] = U64IMAGE2DMS;
(*KeywordMap)["i64image2DMSArray"] = I64IMAGE2DMSARRAY;
(*KeywordMap)["u64image2DMSArray"] = U64IMAGE2DMSARRAY;
(*KeywordMap)["double"] = DOUBLE;
(*KeywordMap)["dvec2"] = DVEC2;
(*KeywordMap)["dvec3"] = DVEC3;
@ -982,7 +1004,7 @@ int TScanContext::tokenizeIdentifier()
return keyword;
case PACKED:
if ((parseContext.isEsProfile() && parseContext.version < 300) ||
(!parseContext.isEsProfile() && parseContext.version < 330))
(!parseContext.isEsProfile() && parseContext.version < 140))
return reservedWord();
return identifierOrType();
@ -1147,6 +1169,19 @@ int TScanContext::tokenizeIdentifier()
afterType = true;
return firstGenerationImage(false);
case I64IMAGE1D:
case U64IMAGE1D:
case I64IMAGE1DARRAY:
case U64IMAGE1DARRAY:
case I64IMAGE2DRECT:
case U64IMAGE2DRECT:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
return firstGenerationImage(false);
}
return identifierOrType();
case IMAGEBUFFER:
case IIMAGEBUFFER:
case UIMAGEBUFFER:
@ -1155,6 +1190,18 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
return keyword;
return firstGenerationImage(false);
case I64IMAGEBUFFER:
case U64IMAGEBUFFER:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
return keyword;
return firstGenerationImage(false);
}
return identifierOrType();
case IMAGE2D:
case IIMAGE2D:
@ -1171,6 +1218,20 @@ int TScanContext::tokenizeIdentifier()
afterType = true;
return firstGenerationImage(true);
case I64IMAGE2D:
case U64IMAGE2D:
case I64IMAGE3D:
case U64IMAGE3D:
case I64IMAGECUBE:
case U64IMAGECUBE:
case I64IMAGE2DARRAY:
case U64IMAGE2DARRAY:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64))
return firstGenerationImage(true);
return identifierOrType();
case IMAGECUBEARRAY:
case IIMAGECUBEARRAY:
case UIMAGECUBEARRAY:
@ -1179,6 +1240,18 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
return keyword;
return secondGenerationImage();
case I64IMAGECUBEARRAY:
case U64IMAGECUBEARRAY:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
return keyword;
return secondGenerationImage();
}
return identifierOrType();
case IMAGE2DMS:
case IIMAGE2DMS:
@ -1188,6 +1261,17 @@ int TScanContext::tokenizeIdentifier()
case UIMAGE2DMSARRAY:
afterType = true;
return secondGenerationImage();
case I64IMAGE2DMS:
case U64IMAGE2DMS:
case I64IMAGE2DMSARRAY:
case U64IMAGE2DMSARRAY:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
return secondGenerationImage();
}
return identifierOrType();
case DOUBLE:
case DVEC2:

View File

@ -85,6 +85,8 @@ void TType::buildMangledName(TString& mangledName) const
#endif
case EbtInt: mangledName += "i"; break;
case EbtUint: mangledName += "u"; break;
case EbtInt64: mangledName += "i64"; break;
case EbtUint64: mangledName += "u64"; break;
default: break; // some compilers want this
}
if (sampler.isImageClass())
@ -146,6 +148,8 @@ void TType::buildMangledName(TString& mangledName) const
if (typeName)
mangledName += *typeName;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->getBasicType() == EbtVoid)
continue;
mangledName += '-';
(*structure)[i].type->buildMangledName(mangledName);
}

View File

@ -613,20 +613,24 @@ public:
//
protected:
static const int globalLevel = 3;
bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
public:
bool isEmpty() { return table.size() == 0; }
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
static bool isBuiltInSymbol(int uniqueId) {
int level = uniqueId >> LevelFlagBitOffset;
return isBuiltInLevel(level);
}
void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
void setSeparateNameSpaces() { separateNameSpaces = true; }
void push()
{
table.push_back(new TSymbolTableLevel);
updateUniqueIdLevelFlag();
}
// Make a new symbol-table level to represent the scope introduced by a structure
@ -639,6 +643,7 @@ public:
{
assert(thisSymbol.getName().size() == 0);
table.push_back(new TSymbolTableLevel);
updateUniqueIdLevelFlag();
table.back()->setThisLevel();
insert(thisSymbol);
}
@ -648,6 +653,7 @@ public:
table[currentLevel()]->getPreviousDefaultPrecisions(p);
delete table.back();
table.pop_back();
updateUniqueIdLevelFlag();
}
//
@ -867,12 +873,20 @@ public:
table[level]->readOnly();
}
// Add current level in the high-bits of unique id
void updateUniqueIdLevelFlag() {
// clamp level to avoid overflow
uint32_t level = currentLevel() > 7 ? 7 : currentLevel();
uniqueId &= ((1 << LevelFlagBitOffset) - 1);
uniqueId |= (level << LevelFlagBitOffset);
}
protected:
TSymbolTable(TSymbolTable&);
TSymbolTable& operator=(TSymbolTableLevel&);
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
static const uint32_t LevelFlagBitOffset = 28;
std::vector<TSymbolTableLevel*> table;
int uniqueId; // for unique identification in code generation
bool noBuiltInRedeclarations;

View File

@ -328,6 +328,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable;
// OVR extensions
extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
@ -477,6 +478,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_KHR_shader_subgroup_clustered 1\n"
"#define GL_KHR_shader_subgroup_quad 1\n"
"#define GL_EXT_shader_image_int64 1\n"
"#define GL_EXT_shader_atomic_int64 1\n"
"#define GL_EXT_shader_realtime_clock 1\n"
"#define GL_EXT_ray_tracing 1\n"

View File

@ -200,6 +200,7 @@ const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate";
const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64";
// Arrays of extensions for the above viewportEXTs duplications

View File

@ -242,6 +242,18 @@ GLSLANG_WEB_EXCLUDE_ON
%token <lex> F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY
%token <lex> F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY
%token <lex> I64IMAGE1D U64IMAGE1D
%token <lex> I64IMAGE2D U64IMAGE2D
%token <lex> I64IMAGE3D U64IMAGE3D
%token <lex> I64IMAGE2DRECT U64IMAGE2DRECT
%token <lex> I64IMAGECUBE U64IMAGECUBE
%token <lex> I64IMAGEBUFFER U64IMAGEBUFFER
%token <lex> I64IMAGE1DARRAY U64IMAGE1DARRAY
%token <lex> I64IMAGE2DARRAY U64IMAGE2DARRAY
%token <lex> I64IMAGECUBEARRAY U64IMAGECUBEARRAY
%token <lex> I64IMAGE2DMS U64IMAGE2DMS
%token <lex> I64IMAGE2DMSARRAY U64IMAGE2DMSARRAY
// texture without sampler
%token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY
%token <lex> TEXTURE1D ITEXTURE1D UTEXTURE1D
@ -905,7 +917,7 @@ declaration
block_structure
: type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
--parseContext.structNestingLevel;
--parseContext.blockNestingLevel;
parseContext.blockName = $2.string;
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
@ -3203,6 +3215,116 @@ GLSLANG_WEB_EXCLUDE_ON
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint, Esd2D, true, false, true);
}
| I64IMAGE1D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd1D);
}
| U64IMAGE1D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd1D);
}
| I64IMAGE2D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D);
}
| U64IMAGE2D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D);
}
| I64IMAGE3D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd3D);
}
| U64IMAGE3D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd3D);
}
| I64IMAGE2DRECT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdRect);
}
| U64IMAGE2DRECT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdRect);
}
| I64IMAGECUBE {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdCube);
}
| U64IMAGECUBE {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdCube);
}
| I64IMAGEBUFFER {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdBuffer);
}
| U64IMAGEBUFFER {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdBuffer);
}
| I64IMAGE1DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd1D, true);
}
| U64IMAGE1DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd1D, true);
}
| I64IMAGE2DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D, true);
}
| U64IMAGE2DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D, true);
}
| I64IMAGECUBEARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdCube, true);
}
| U64IMAGECUBEARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdCube, true);
}
| I64IMAGE2DMS {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D, false, false, true);
}
| U64IMAGE2DMS {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D, false, false, true);
}
| I64IMAGE2DMSARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D, true, false, true);
}
| U64IMAGE2DMSARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D, true, false, true);
}
| SAMPLEREXTERNALOES { // GL_OES_EGL_image_external
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;

View File

@ -242,6 +242,18 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY
%token <lex> F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY
%token <lex> I64IMAGE1D U64IMAGE1D
%token <lex> I64IMAGE2D U64IMAGE2D
%token <lex> I64IMAGE3D U64IMAGE3D
%token <lex> I64IMAGE2DRECT U64IMAGE2DRECT
%token <lex> I64IMAGECUBE U64IMAGECUBE
%token <lex> I64IMAGEBUFFER U64IMAGEBUFFER
%token <lex> I64IMAGE1DARRAY U64IMAGE1DARRAY
%token <lex> I64IMAGE2DARRAY U64IMAGE2DARRAY
%token <lex> I64IMAGECUBEARRAY U64IMAGECUBEARRAY
%token <lex> I64IMAGE2DMS U64IMAGE2DMS
%token <lex> I64IMAGE2DMSARRAY U64IMAGE2DMSARRAY
// texture without sampler
%token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY
%token <lex> TEXTURE1D ITEXTURE1D UTEXTURE1D
@ -905,7 +917,7 @@ declaration
block_structure
: type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
--parseContext.structNestingLevel;
--parseContext.blockNestingLevel;
parseContext.blockName = $2.string;
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
@ -3203,6 +3215,116 @@ type_specifier_nonarray
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint, Esd2D, true, false, true);
}
| I64IMAGE1D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd1D);
}
| U64IMAGE1D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd1D);
}
| I64IMAGE2D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D);
}
| U64IMAGE2D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D);
}
| I64IMAGE3D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd3D);
}
| U64IMAGE3D {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd3D);
}
| I64IMAGE2DRECT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdRect);
}
| U64IMAGE2DRECT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdRect);
}
| I64IMAGECUBE {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdCube);
}
| U64IMAGECUBE {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdCube);
}
| I64IMAGEBUFFER {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdBuffer);
}
| U64IMAGEBUFFER {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdBuffer);
}
| I64IMAGE1DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd1D, true);
}
| U64IMAGE1DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd1D, true);
}
| I64IMAGE2DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D, true);
}
| U64IMAGE2DARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D, true);
}
| I64IMAGECUBEARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, EsdCube, true);
}
| U64IMAGECUBEARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, EsdCube, true);
}
| I64IMAGE2DMS {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D, false, false, true);
}
| U64IMAGE2DMS {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D, false, false, true);
}
| I64IMAGE2DMSARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtInt64, Esd2D, true, false, true);
}
| U64IMAGE2DMSARRAY {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint64, Esd2D, true, false, true);
}
| SAMPLEREXTERNALOES { // GL_OES_EGL_image_external
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;

File diff suppressed because it is too large Load Diff

View File

@ -297,171 +297,193 @@ extern int yydebug;
F16IMAGEBUFFER = 507,
F16IMAGE2DMS = 508,
F16IMAGE2DMSARRAY = 509,
TEXTURECUBEARRAY = 510,
ITEXTURECUBEARRAY = 511,
UTEXTURECUBEARRAY = 512,
TEXTURE1D = 513,
ITEXTURE1D = 514,
UTEXTURE1D = 515,
TEXTURE1DARRAY = 516,
ITEXTURE1DARRAY = 517,
UTEXTURE1DARRAY = 518,
TEXTURE2DRECT = 519,
ITEXTURE2DRECT = 520,
UTEXTURE2DRECT = 521,
TEXTUREBUFFER = 522,
ITEXTUREBUFFER = 523,
UTEXTUREBUFFER = 524,
TEXTURE2DMS = 525,
ITEXTURE2DMS = 526,
UTEXTURE2DMS = 527,
TEXTURE2DMSARRAY = 528,
ITEXTURE2DMSARRAY = 529,
UTEXTURE2DMSARRAY = 530,
F16TEXTURE1D = 531,
F16TEXTURE2D = 532,
F16TEXTURE3D = 533,
F16TEXTURE2DRECT = 534,
F16TEXTURECUBE = 535,
F16TEXTURE1DARRAY = 536,
F16TEXTURE2DARRAY = 537,
F16TEXTURECUBEARRAY = 538,
F16TEXTUREBUFFER = 539,
F16TEXTURE2DMS = 540,
F16TEXTURE2DMSARRAY = 541,
SUBPASSINPUT = 542,
SUBPASSINPUTMS = 543,
ISUBPASSINPUT = 544,
ISUBPASSINPUTMS = 545,
USUBPASSINPUT = 546,
USUBPASSINPUTMS = 547,
F16SUBPASSINPUT = 548,
F16SUBPASSINPUTMS = 549,
LEFT_OP = 550,
RIGHT_OP = 551,
INC_OP = 552,
DEC_OP = 553,
LE_OP = 554,
GE_OP = 555,
EQ_OP = 556,
NE_OP = 557,
AND_OP = 558,
OR_OP = 559,
XOR_OP = 560,
MUL_ASSIGN = 561,
DIV_ASSIGN = 562,
ADD_ASSIGN = 563,
MOD_ASSIGN = 564,
LEFT_ASSIGN = 565,
RIGHT_ASSIGN = 566,
AND_ASSIGN = 567,
XOR_ASSIGN = 568,
OR_ASSIGN = 569,
SUB_ASSIGN = 570,
STRING_LITERAL = 571,
LEFT_PAREN = 572,
RIGHT_PAREN = 573,
LEFT_BRACKET = 574,
RIGHT_BRACKET = 575,
LEFT_BRACE = 576,
RIGHT_BRACE = 577,
DOT = 578,
COMMA = 579,
COLON = 580,
EQUAL = 581,
SEMICOLON = 582,
BANG = 583,
DASH = 584,
TILDE = 585,
PLUS = 586,
STAR = 587,
SLASH = 588,
PERCENT = 589,
LEFT_ANGLE = 590,
RIGHT_ANGLE = 591,
VERTICAL_BAR = 592,
CARET = 593,
AMPERSAND = 594,
QUESTION = 595,
INVARIANT = 596,
HIGH_PRECISION = 597,
MEDIUM_PRECISION = 598,
LOW_PRECISION = 599,
PRECISION = 600,
PACKED = 601,
RESOURCE = 602,
SUPERP = 603,
FLOATCONSTANT = 604,
INTCONSTANT = 605,
UINTCONSTANT = 606,
BOOLCONSTANT = 607,
IDENTIFIER = 608,
TYPE_NAME = 609,
CENTROID = 610,
IN = 611,
OUT = 612,
INOUT = 613,
STRUCT = 614,
VOID = 615,
WHILE = 616,
BREAK = 617,
CONTINUE = 618,
DO = 619,
ELSE = 620,
FOR = 621,
IF = 622,
DISCARD = 623,
RETURN = 624,
SWITCH = 625,
CASE = 626,
DEFAULT = 627,
UNIFORM = 628,
SHARED = 629,
BUFFER = 630,
FLAT = 631,
SMOOTH = 632,
LAYOUT = 633,
DOUBLECONSTANT = 634,
INT16CONSTANT = 635,
UINT16CONSTANT = 636,
FLOAT16CONSTANT = 637,
INT32CONSTANT = 638,
UINT32CONSTANT = 639,
INT64CONSTANT = 640,
UINT64CONSTANT = 641,
SUBROUTINE = 642,
DEMOTE = 643,
PAYLOADNV = 644,
PAYLOADINNV = 645,
HITATTRNV = 646,
CALLDATANV = 647,
CALLDATAINNV = 648,
PAYLOADEXT = 649,
PAYLOADINEXT = 650,
HITATTREXT = 651,
CALLDATAEXT = 652,
CALLDATAINEXT = 653,
PATCH = 654,
SAMPLE = 655,
NONUNIFORM = 656,
COHERENT = 657,
VOLATILE = 658,
RESTRICT = 659,
READONLY = 660,
WRITEONLY = 661,
DEVICECOHERENT = 662,
QUEUEFAMILYCOHERENT = 663,
WORKGROUPCOHERENT = 664,
SUBGROUPCOHERENT = 665,
NONPRIVATE = 666,
SHADERCALLCOHERENT = 667,
NOPERSPECTIVE = 668,
EXPLICITINTERPAMD = 669,
PERVERTEXNV = 670,
PERPRIMITIVENV = 671,
PERVIEWNV = 672,
PERTASKNV = 673,
PRECISE = 674
I64IMAGE1D = 510,
U64IMAGE1D = 511,
I64IMAGE2D = 512,
U64IMAGE2D = 513,
I64IMAGE3D = 514,
U64IMAGE3D = 515,
I64IMAGE2DRECT = 516,
U64IMAGE2DRECT = 517,
I64IMAGECUBE = 518,
U64IMAGECUBE = 519,
I64IMAGEBUFFER = 520,
U64IMAGEBUFFER = 521,
I64IMAGE1DARRAY = 522,
U64IMAGE1DARRAY = 523,
I64IMAGE2DARRAY = 524,
U64IMAGE2DARRAY = 525,
I64IMAGECUBEARRAY = 526,
U64IMAGECUBEARRAY = 527,
I64IMAGE2DMS = 528,
U64IMAGE2DMS = 529,
I64IMAGE2DMSARRAY = 530,
U64IMAGE2DMSARRAY = 531,
TEXTURECUBEARRAY = 532,
ITEXTURECUBEARRAY = 533,
UTEXTURECUBEARRAY = 534,
TEXTURE1D = 535,
ITEXTURE1D = 536,
UTEXTURE1D = 537,
TEXTURE1DARRAY = 538,
ITEXTURE1DARRAY = 539,
UTEXTURE1DARRAY = 540,
TEXTURE2DRECT = 541,
ITEXTURE2DRECT = 542,
UTEXTURE2DRECT = 543,
TEXTUREBUFFER = 544,
ITEXTUREBUFFER = 545,
UTEXTUREBUFFER = 546,
TEXTURE2DMS = 547,
ITEXTURE2DMS = 548,
UTEXTURE2DMS = 549,
TEXTURE2DMSARRAY = 550,
ITEXTURE2DMSARRAY = 551,
UTEXTURE2DMSARRAY = 552,
F16TEXTURE1D = 553,
F16TEXTURE2D = 554,
F16TEXTURE3D = 555,
F16TEXTURE2DRECT = 556,
F16TEXTURECUBE = 557,
F16TEXTURE1DARRAY = 558,
F16TEXTURE2DARRAY = 559,
F16TEXTURECUBEARRAY = 560,
F16TEXTUREBUFFER = 561,
F16TEXTURE2DMS = 562,
F16TEXTURE2DMSARRAY = 563,
SUBPASSINPUT = 564,
SUBPASSINPUTMS = 565,
ISUBPASSINPUT = 566,
ISUBPASSINPUTMS = 567,
USUBPASSINPUT = 568,
USUBPASSINPUTMS = 569,
F16SUBPASSINPUT = 570,
F16SUBPASSINPUTMS = 571,
LEFT_OP = 572,
RIGHT_OP = 573,
INC_OP = 574,
DEC_OP = 575,
LE_OP = 576,
GE_OP = 577,
EQ_OP = 578,
NE_OP = 579,
AND_OP = 580,
OR_OP = 581,
XOR_OP = 582,
MUL_ASSIGN = 583,
DIV_ASSIGN = 584,
ADD_ASSIGN = 585,
MOD_ASSIGN = 586,
LEFT_ASSIGN = 587,
RIGHT_ASSIGN = 588,
AND_ASSIGN = 589,
XOR_ASSIGN = 590,
OR_ASSIGN = 591,
SUB_ASSIGN = 592,
STRING_LITERAL = 593,
LEFT_PAREN = 594,
RIGHT_PAREN = 595,
LEFT_BRACKET = 596,
RIGHT_BRACKET = 597,
LEFT_BRACE = 598,
RIGHT_BRACE = 599,
DOT = 600,
COMMA = 601,
COLON = 602,
EQUAL = 603,
SEMICOLON = 604,
BANG = 605,
DASH = 606,
TILDE = 607,
PLUS = 608,
STAR = 609,
SLASH = 610,
PERCENT = 611,
LEFT_ANGLE = 612,
RIGHT_ANGLE = 613,
VERTICAL_BAR = 614,
CARET = 615,
AMPERSAND = 616,
QUESTION = 617,
INVARIANT = 618,
HIGH_PRECISION = 619,
MEDIUM_PRECISION = 620,
LOW_PRECISION = 621,
PRECISION = 622,
PACKED = 623,
RESOURCE = 624,
SUPERP = 625,
FLOATCONSTANT = 626,
INTCONSTANT = 627,
UINTCONSTANT = 628,
BOOLCONSTANT = 629,
IDENTIFIER = 630,
TYPE_NAME = 631,
CENTROID = 632,
IN = 633,
OUT = 634,
INOUT = 635,
STRUCT = 636,
VOID = 637,
WHILE = 638,
BREAK = 639,
CONTINUE = 640,
DO = 641,
ELSE = 642,
FOR = 643,
IF = 644,
DISCARD = 645,
RETURN = 646,
SWITCH = 647,
CASE = 648,
DEFAULT = 649,
UNIFORM = 650,
SHARED = 651,
BUFFER = 652,
FLAT = 653,
SMOOTH = 654,
LAYOUT = 655,
DOUBLECONSTANT = 656,
INT16CONSTANT = 657,
UINT16CONSTANT = 658,
FLOAT16CONSTANT = 659,
INT32CONSTANT = 660,
UINT32CONSTANT = 661,
INT64CONSTANT = 662,
UINT64CONSTANT = 663,
SUBROUTINE = 664,
DEMOTE = 665,
PAYLOADNV = 666,
PAYLOADINNV = 667,
HITATTRNV = 668,
CALLDATANV = 669,
CALLDATAINNV = 670,
PAYLOADEXT = 671,
PAYLOADINEXT = 672,
HITATTREXT = 673,
CALLDATAEXT = 674,
CALLDATAINEXT = 675,
PATCH = 676,
SAMPLE = 677,
NONUNIFORM = 678,
COHERENT = 679,
VOLATILE = 680,
RESTRICT = 681,
READONLY = 682,
WRITEONLY = 683,
DEVICECOHERENT = 684,
QUEUEFAMILYCOHERENT = 685,
WORKGROUPCOHERENT = 686,
SUBGROUPCOHERENT = 687,
NONPRIVATE = 688,
SHADERCALLCOHERENT = 689,
NOPERSPECTIVE = 690,
EXPLICITINTERPAMD = 691,
PERVERTEXNV = 692,
PERPRIMITIVENV = 693,
PERVIEWNV = 694,
PERTASKNV = 695,
PRECISE = 696
};
#endif
@ -506,7 +528,7 @@ union YYSTYPE
glslang::TArraySizes* typeParameters;
} interm;
#line 510 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
#line 532 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;

View File

@ -37,9 +37,11 @@
#include "../Include/Common.h"
#include "../Include/InfoSink.h"
#include "../Include/Types.h"
#include "gl_types.h"
#include "iomapper.h"
#include "SymbolTable.h"
//
// Map IO bindings.
@ -82,17 +84,17 @@ public:
// If a global is being visited, then we should also traverse it incase it's evaluation
// ends up visiting inputs we want to tag as live
else if (base->getQualifier().storage == EvqGlobal)
addGlobalReference(base->getName());
addGlobalReference(base->getAccessName());
if (target) {
TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
ent.stage = intermediate.getStage();
TVarLiveMap::iterator at = target->find(
ent.symbol->getName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
ent.symbol->getAccessName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
if (at != target->end() && at->second.id == ent.id)
at->second.live = at->second.live || ! traverseAll; // update live state
else
(*target)[ent.symbol->getName()] = ent;
(*target)[ent.symbol->getAccessName()] = ent;
}
}
@ -125,7 +127,8 @@ public:
return;
TVarEntryInfo ent = { base->getId() };
TVarLiveMap::const_iterator at = source->find(base->getName());
// Fix a defect, when block has no instance name, we need to find its block name
TVarLiveMap::const_iterator at = source->find(base->getAccessName());
if (at == source->end())
return;
@ -181,7 +184,7 @@ struct TNotifyInOutAdaptor
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
{
resolver.notifyInOut(stage, entKey.second);
resolver.notifyInOut(entKey.second.stage, entKey.second);
}
private:
@ -189,12 +192,13 @@ private:
};
struct TResolverUniformAdaptor {
TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TVarLiveMap* uniform[EShLangCount], TInfoSink& i, bool& e)
: stage(s)
, resolver(r)
, infoSink(i)
, error(e)
{
memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
}
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
@ -206,9 +210,9 @@ struct TResolverUniformAdaptor {
ent.newIndex = -1;
const bool isValid = resolver.validateBinding(stage, ent);
if (isValid) {
resolver.resolveBinding(stage, ent);
resolver.resolveSet(stage, ent);
resolver.resolveUniformLocation(stage, ent);
resolver.resolveBinding(ent.stage, ent);
resolver.resolveSet(ent.stage, ent);
resolver.resolveUniformLocation(ent.stage, ent);
if (ent.newBinding != -1) {
if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
@ -217,6 +221,17 @@ struct TResolverUniformAdaptor {
infoSink.info.message(EPrefixInternalError, err.c_str());
error = true;
}
if (ent.symbol->getQualifier().hasBinding()) {
for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
if (idx == ent.stage || uniformVarMap[idx] == nullptr)
continue;
auto entKey2 = uniformVarMap[idx]->find(entKey.first);
if (entKey2 != uniformVarMap[idx]->end()) {
entKey2->second.newBinding = ent.newBinding;
}
}
}
}
if (ent.newSet != -1) {
if (ent.newSet >= int(TQualifier::layoutSetEnd)) {
@ -225,6 +240,16 @@ struct TResolverUniformAdaptor {
infoSink.info.message(EPrefixInternalError, err.c_str());
error = true;
}
if (ent.symbol->getQualifier().hasSet()) {
for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
if ((idx == stage) || (uniformVarMap[idx] == nullptr))
continue;
auto entKey2 = uniformVarMap[idx]->find(entKey.first);
if (entKey2 != uniformVarMap[idx]->end()) {
entKey2->second.newSet = ent.newSet;
}
}
}
}
} else {
TString errorMsg = "Invalid binding: " + entKey.first;
@ -239,7 +264,7 @@ struct TResolverUniformAdaptor {
TIoMapResolver& resolver;
TInfoSink& infoSink;
bool& error;
TVarLiveMap* uniformVarMap[EShLangCount];
private:
TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
};
@ -261,7 +286,7 @@ struct TResolverInOutAdaptor {
ent.newBinding = -1;
ent.newSet = -1;
ent.newIndex = -1;
const bool isValid = resolver.validateInOut(stage, ent);
const bool isValid = resolver.validateInOut(ent.stage, ent);
if (isValid) {
resolver.resolveInOutLocation(stage, ent);
resolver.resolveInOutComponent(stage, ent);
@ -296,17 +321,116 @@ private:
struct TSymbolValidater
{
TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
TVarLiveMap* uniform[EShLangCount], bool& hadError)
TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version)
: preStage(EShLangCount)
, currentStage(EShLangCount)
, nextStage(EShLangCount)
, resolver(r)
, infoSink(i)
, hadError(hadError)
, profile(profile)
, version(version)
{
memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*)));
memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*)));
memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
std::map<TString, TString> anonymousMemberMap;
std::vector<TRange> usedUniformLocation;
std::vector<TString> usedUniformName;
usedUniformLocation.clear();
usedUniformName.clear();
for (int i = 0; i < EShLangCount; i++) {
if (uniformVarMap[i]) {
for (auto uniformVar : *uniformVarMap[i])
{
TIntermSymbol* pSymbol = uniformVar.second.symbol;
TQualifier qualifier = uniformVar.second.symbol->getQualifier();
TString symbolName = pSymbol->getAccessName();
// All the uniform needs multi-stage location check (block/default)
int uniformLocation = qualifier.layoutLocation;
if (uniformLocation != TQualifier::layoutLocationEnd) {
// Total size of current uniform, could be block, struct or other types.
int size = TIntermediate::computeTypeUniformLocationSize(pSymbol->getType());
TRange locationRange(uniformLocation, uniformLocation + size - 1);
// Combine location and component ranges
int overlapLocation = -1;
bool diffLocation = false;
// Check for collisions, except for vertex inputs on desktop targeting OpenGL
overlapLocation = checkLocationOverlap(locationRange, usedUniformLocation, symbolName, usedUniformName, diffLocation);
// Overlap locations of uniforms, regardless of components (multi stages)
if (overlapLocation == -1) {
usedUniformLocation.push_back(locationRange);
usedUniformName.push_back(symbolName);
}
else if (overlapLocation >= 0) {
if (diffLocation == true) {
TString err = ("Uniform location should be equal for same uniforms: " +std::to_string(overlapLocation)).c_str();
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
break;
}
else {
TString err = ("Uniform location overlaps across stages: " + std::to_string(overlapLocation)).c_str();
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
break;
}
}
}
if ((uniformVar.second.symbol->getBasicType() == EbtBlock) &&
IsAnonymous(uniformVar.second.symbol->getName()))
{
auto blockType = uniformVar.second.symbol->getType().getStruct();
for (size_t memberIdx = 0; memberIdx < blockType->size(); ++memberIdx) {
auto memberName = (*blockType)[memberIdx].type->getFieldName();
if (anonymousMemberMap.find(memberName) != anonymousMemberMap.end())
{
if (anonymousMemberMap[memberName] != uniformVar.second.symbol->getType().getTypeName())
{
TString err = "Invalid block member name: " + memberName;
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
break;
}
}
else
{
anonymousMemberMap[memberName] = uniformVar.second.symbol->getType().getTypeName();
}
}
}
if (hadError)
break;
}
}
}
}
// In case we need to new an intermediate, which costs too much
int checkLocationOverlap(const TRange& locationRange, std::vector<TRange>& usedUniformLocation, const TString symbolName, std::vector<TString>& usedUniformName, bool& diffLocation)
{
for (size_t r = 0; r < usedUniformLocation.size(); ++r) {
if (usedUniformName[r] == symbolName) {
diffLocation = true;
return (usedUniformLocation[r].start == locationRange.start &&
usedUniformLocation[r].last == locationRange.last)
? -2 : std::max(locationRange.start, usedUniformLocation[r].start);
}
if (locationRange.overlap(usedUniformLocation[r])) {
// there is a collision; pick one
return std::max(locationRange.start, usedUniformLocation[r].start);
}
}
return -1; // no collision
}
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
@ -339,11 +463,24 @@ struct TSymbolValidater
// validate stage in;
if (preStage == EShLangCount)
return;
if (name == "gl_PerVertex")
if (TSymbolTable::isBuiltInSymbol(base->getId()))
return;
if (outVarMaps[preStage] != nullptr) {
auto ent2 = outVarMaps[preStage]->find(name);
uint32_t location = base->getType().getQualifier().layoutLocation;
if (ent2 == outVarMaps[preStage]->end() &&
location != glslang::TQualifier::layoutLocationEnd) {
for (auto var = outVarMaps[preStage]->begin(); var != ent2; var++) {
if (var->second.symbol->getType().getQualifier().layoutLocation == location) {
ent2 = var;
break;
}
}
}
if (ent2 != outVarMaps[preStage]->end()) {
auto& type1 = base->getType();
auto& type2 = ent2->second.symbol->getType();
hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
TType subType(ent2->second.symbol->getType(), 0);
subType.appendMangledName(mangleName2);
@ -351,23 +488,49 @@ struct TSymbolValidater
else {
ent2->second.symbol->getType().appendMangledName(mangleName2);
}
if (mangleName1 == mangleName2)
if (mangleName1 == mangleName2) {
// For ES 3.0 only, other versions have no such restrictions
// According to ES 3.0 spec: The type and presence of the interpolation qualifiers and
// storage qualifiers of variables with the same name declared in all linked shaders must
// match, otherwise the link command will fail.
if (profile == EEsProfile && version == 300) {
// Don't need to check smooth qualifier, as it uses the default interpolation mode
if (ent1.stage == EShLangFragment && type1.isBuiltIn() == false) {
if (type1.getQualifier().flat != type2.getQualifier().flat ||
type1.getQualifier().nopersp != type2.getQualifier().nopersp) {
TString err = "Interpolation qualifier mismatch : " + entKey.first;
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
}
}
}
return;
}
else {
TString err = "Invalid In/Out variable type : " + entKey.first;
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
}
}
else if (!base->getType().isBuiltIn()) {
// According to spec: A link error is generated if any statically referenced input variable
// or block does not have a matching output
if (profile == EEsProfile && ent1.live) {
hadError = true;
TString errorStr = name + ": not been declare as a output variable in pre shader stage.";
infoSink.info.message(EPrefixError, errorStr.c_str());
}
}
return;
}
} else if (base->getQualifier().storage == EvqVaryingOut) {
// validate stage out;
if (nextStage == EShLangCount)
return;
if (name == "gl_PerVertex")
if (TSymbolTable::isBuiltInSymbol(base->getId()))
return;
if (outVarMaps[nextStage] != nullptr) {
if (inVarMaps[nextStage] != nullptr) {
auto ent2 = inVarMaps[nextStage]->find(name);
if (ent2 != inVarMaps[nextStage]->end()) {
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
@ -400,11 +563,50 @@ struct TSymbolValidater
hadError = true;
}
mangleName2.clear();
// validate instance name of blocks
if (hadError == false &&
base->getType().getBasicType() == EbtBlock &&
IsAnonymous(base->getName()) != IsAnonymous(ent2->second.symbol->getName())) {
TString err = "Matched uniform block names must also either all be lacking "
"an instance name or all having an instance name: " + entKey.first;
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
}
// validate uniform block member qualifier and member names
auto& type1 = base->getType();
auto& type2 = ent2->second.symbol->getType();
if (hadError == false && base->getType().getBasicType() == EbtBlock) {
hadError = hadError || typeCheck(&type1, &type2, name.c_str(), true);
}
else {
hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
}
}
else if (base->getBasicType() == EbtBlock)
{
if (IsAnonymous(base->getName()))
{
// The name of anonymous block member can't same with default uniform variable.
auto blockType1 = base->getType().getStruct();
for (size_t memberIdx = 0; memberIdx < blockType1->size(); ++memberIdx) {
auto memberName = (*blockType1)[memberIdx].type->getFieldName();
if (uniformVarMap[i]->find(memberName) != uniformVarMap[i]->end())
{
TString err = "Invalid Uniform variable name : " + memberName;
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
break;
}
}
}
}
}
}
}
}
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
// Use for mark pre stage, to get more interface symbol information.
EShLanguage preStage, currentStage, nextStage;
@ -412,9 +614,118 @@ struct TSymbolValidater
TIoMapResolver& resolver;
TInfoSink& infoSink;
bool& hadError;
EProfile profile;
int version;
private:
TSymbolValidater& operator=(TSymbolValidater&) = delete;
bool qualifierCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
{
bool hasError = false;
const TQualifier& qualifier1 = type1->getQualifier();
const TQualifier& qualifier2 = type2->getQualifier();
if (((isBlock == false) &&
(type1->getQualifier().storage == EvqUniform && type2->getQualifier().storage == EvqUniform)) ||
(type1->getQualifier().storage == EvqGlobal && type2->getQualifier().storage == EvqGlobal)) {
if (qualifier1.precision != qualifier2.precision) {
hasError = true;
std::string errorStr = name + ": have precision conflict cross stage.";
infoSink.info.message(EPrefixError, errorStr.c_str());
}
if (qualifier1.hasFormat() && qualifier2.hasFormat()) {
if (qualifier1.layoutFormat != qualifier2.layoutFormat) {
hasError = true;
std::string errorStr = name + ": have layout format conflict cross stage.";
infoSink.info.message(EPrefixError, errorStr.c_str());
}
}
}
if (isBlock == true) {
if (qualifier1.layoutPacking != qualifier2.layoutPacking) {
hasError = true;
std::string errorStr = name + ": have layoutPacking conflict cross stage.";
infoSink.info.message(EPrefixError, errorStr.c_str());
}
if (qualifier1.layoutMatrix != qualifier2.layoutMatrix) {
hasError = true;
std::string errorStr = name + ": have layoutMatrix conflict cross stage.";
infoSink.info.message(EPrefixError, errorStr.c_str());
}
if (qualifier1.layoutOffset != qualifier2.layoutOffset) {
hasError = true;
std::string errorStr = name + ": have layoutOffset conflict cross stage.";
infoSink.info.message(EPrefixError, errorStr.c_str());
}
if (qualifier1.layoutAlign != qualifier2.layoutAlign) {
hasError = true;
std::string errorStr = name + ": have layoutAlign conflict cross stage.";
infoSink.info.message(EPrefixError, errorStr.c_str());
}
}
return hasError;
}
bool typeCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
{
bool hasError = false;
if (!(type1->isStruct() && type2->isStruct())) {
hasError = hasError || qualifierCheck(type1, type2, name, isBlock);
}
else {
if (type1->getBasicType() == EbtBlock && type2->getBasicType() == EbtBlock)
isBlock = true;
const TTypeList* typeList1 = type1->getStruct();
const TTypeList* typeList2 = type2->getStruct();
std::string newName = name;
size_t memberCount = typeList1->size();
size_t index2 = 0;
for (size_t index = 0; index < memberCount; index++, index2++) {
// Skip inactive member
if (typeList1->at(index).type->getBasicType() == EbtVoid)
continue;
while (index2 < typeList2->size() && typeList2->at(index2).type->getBasicType() == EbtVoid) {
++index2;
}
// TypeList1 has more members in list
if (index2 == typeList2->size()) {
std::string errorStr = name + ": struct mismatch.";
infoSink.info.message(EPrefixError, errorStr.c_str());
hasError = true;
break;
}
if (typeList1->at(index).type->getFieldName() != typeList2->at(index2).type->getFieldName()) {
std::string errorStr = name + ": member name mismatch.";
infoSink.info.message(EPrefixError, errorStr.c_str());
hasError = true;
}
else {
newName = typeList1->at(index).type->getFieldName().c_str();
}
hasError = hasError || typeCheck(typeList1->at(index).type, typeList2->at(index2).type, newName, isBlock);
}
while (index2 < typeList2->size())
{
// TypeList2 has more members
if (typeList2->at(index2).type->getBasicType() != EbtVoid) {
std::string errorStr = name + ": struct mismatch.";
infoSink.info.message(EPrefixError, errorStr.c_str());
hasError = true;
break;
}
++index2;
}
}
return hasError;
}
};
struct TSlotCollector {
@ -500,7 +811,7 @@ int TDefaultIoResolverBase::resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent
int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const char* name = ent.symbol->getName().c_str();
const char* name = ent.symbol->getAccessName().c_str();
// kick out of not doing this
if (! doAutoLocationMapping()) {
return ent.newLocation = -1;
@ -609,7 +920,7 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate
int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = getAccessName(ent.symbol);
const TString& name = ent.symbol->getAccessName();
if (currentStage != stage) {
preStage = currentStage;
currentStage = stage;
@ -693,7 +1004,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = getAccessName(ent.symbol);
const TString& name = ent.symbol->getAccessName();
// kick out of not doing this
if (! doAutoLocationMapping()) {
return ent.newLocation = -1;
@ -764,7 +1075,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = getAccessName(ent.symbol);
const TString& name = ent.symbol->getAccessName();
// On OpenGL arrays of opaque types take a separate binding for each element
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
TResourceType resource = getResourceType(type);
@ -839,7 +1150,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
const TType& type = ent.symbol->getType();
const TString& name = getAccessName(ent.symbol);
const TString& name = ent.symbol->getAccessName();
TStorageQualifier storage = type.getQualifier().storage;
EShLanguage stage(EShLangCount);
switch (storage) {
@ -899,7 +1210,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
const TType& type = ent.symbol->getType();
const TString& name = getAccessName(ent.symbol);
const TString& name = ent.symbol->getAccessName();
int resource = getResourceType(type);
if (type.getQualifier().hasBinding()) {
TVarSlotMap& varSlotMap = resourceSlotMap[resource];
@ -922,13 +1233,6 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
}
}
const TString& TDefaultGlslIoResolver::getAccessName(const TIntermSymbol* symbol)
{
return symbol->getBasicType() == EbtBlock ?
symbol->getType().getTypeName() :
symbol->getName();
}
//TDefaultGlslIoResolver end
/*
@ -1117,25 +1421,23 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
}
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
std::for_each(inVarMap.begin(), inVarMap.end(),
[&inVector](TVarLivePair p) { inVector.push_back(p); });
for (auto& var : inVarMap) { inVector.push_back(var); }
std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
});
std::for_each(outVarMap.begin(), outVarMap.end(),
[&outVector](TVarLivePair p) { outVector.push_back(p); });
for (auto& var : outVarMap) { outVector.push_back(var); }
std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
});
std::for_each(uniformVarMap.begin(), uniformVarMap.end(),
[&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
for (auto& var : uniformVarMap) { uniformVector.push_back(var); }
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
});
bool hadError = false;
TVarLiveMap* dummyUniformVarMap[EShLangCount] = {};
TNotifyInOutAdaptor inOutNotify(stage, *resolver);
TNotifyUniformAdaptor uniformNotify(stage, *resolver);
TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError);
TResolverUniformAdaptor uniformResolve(stage, *resolver, dummyUniformVarMap, infoSink, hadError);
TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError);
resolver->beginNotifications(stage);
std::for_each(inVector.begin(), inVector.end(), inOutNotify);
@ -1143,22 +1445,22 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify);
resolver->endNotifications(stage);
resolver->beginResolve(stage);
std::for_each(inVector.begin(), inVector.end(), inOutResolve);
for (auto& var : inVector) { inOutResolve(var); }
std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) {
auto at = inVarMap.find(p.second.symbol->getName());
if (at != inVarMap.end())
auto at = inVarMap.find(p.second.symbol->getAccessName());
if (at != inVarMap.end() && p.second.id == at->second.id)
at->second = p.second;
});
std::for_each(outVector.begin(), outVector.end(), inOutResolve);
for (auto& var : outVector) { inOutResolve(var); }
std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) {
auto at = outVarMap.find(p.second.symbol->getName());
if (at != outVarMap.end())
auto at = outVarMap.find(p.second.symbol->getAccessName());
if (at != outVarMap.end() && p.second.id == at->second.id)
at->second = p.second;
});
std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) {
auto at = uniformVarMap.find(p.second.symbol->getName());
if (at != uniformVarMap.end())
auto at = uniformVarMap.find(p.second.symbol->getAccessName());
if (at != uniformVarMap.end() && p.second.id == at->second.id)
at->second = p.second;
});
resolver->endResolve(stage);
@ -1174,9 +1476,14 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
//
// Returns false if the input is too malformed to do this.
bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
bool somethingToDo = !intermediate.getResourceSetBinding().empty() ||
intermediate.getAutoMapBindings() ||
intermediate.getAutoMapLocations();
// Profile and version are use for symbol validate.
profile = intermediate.getProfile();
version = intermediate.getVersion();
bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() ||
intermediate.getAutoMapLocations();
// Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
// unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
@ -1236,31 +1543,30 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
resolver->endResolve(EShLangCount);
if (!hadError) {
//Resolve uniform location, ubo/ssbo/opaque bindings across stages
TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, infoSink, hadError);
TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, uniformVarMap, infoSink, hadError);
TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps, outVarMaps, uniformVarMap, hadError);
TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps,
outVarMaps, uniformVarMap, hadError, profile, version);
TVarLiveVector uniformVector;
resolver->beginResolve(EShLangCount);
for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
if (inVarMaps[stage] != nullptr) {
inOutResolve.setStage(EShLanguage(stage));
std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), symbolValidater);
std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutResolve);
std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), symbolValidater);
std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutResolve);
for (auto& var : *(inVarMaps[stage])) { symbolValidater(var); }
for (auto& var : *(inVarMaps[stage])) { inOutResolve(var); }
for (auto& var : *(outVarMaps[stage])) { symbolValidater(var); }
for (auto& var : *(outVarMaps[stage])) { inOutResolve(var); }
}
if (uniformVarMap[stage] != nullptr) {
uniformResolve.setStage(EShLanguage(stage));
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(),
[&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
for (auto& var : *(uniformVarMap[stage])) { uniformVector.push_back(var); }
}
}
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
});
std::for_each(uniformVector.begin(), uniformVector.end(), symbolValidater);
std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
for (auto& var : uniformVector) { symbolValidater(var); }
for (auto& var : uniformVector) { uniformResolve(var); }
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
});
@ -1269,14 +1575,18 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
if (intermediates[stage] != nullptr) {
// traverse each stage, set new location to each input/output and unifom symbol, set new binding to
// ubo, ssbo and opaque symbols
TVarLiveMap** pUniformVarMap = uniformVarMap;
TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap;
std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) {
auto at = pUniformVarMap[stage]->find(p.second.symbol->getName());
if (at != pUniformVarMap[stage]->end())
auto at = pUniformVarMap[stage]->find(p.second.symbol->getAccessName());
if (at != pUniformVarMap[stage]->end() && at->second.id == p.second.id){
int resolvedBinding = at->second.newBinding;
at->second = p.second;
if (resolvedBinding > 0)
at->second.newBinding = resolvedBinding;
}
});
TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage],
*uniformVarMap[stage]);
*uniformResolve.uniformVarMap[stage]);
intermediates[stage]->getTreeRoot()->traverse(&iter_iomap);
}
}

View File

@ -203,7 +203,6 @@ public:
void endCollect(EShLanguage) override;
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
const TString& getAccessName(const TIntermSymbol*);
// in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
// We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
// if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
@ -263,10 +262,12 @@ public:
class TGlslIoMapper : public TIoMapper {
public:
TGlslIoMapper() {
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount);
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
profile = ENoProfile;
version = 0;
}
virtual ~TGlslIoMapper() {
for (size_t stage = 0; stage < EShLangCount; stage++) {
@ -293,6 +294,8 @@ public:
*uniformVarMap[EShLangCount];
TIntermediate* intermediates[EShLangCount];
bool hadError = false;
EProfile profile;
int version;
};
} // end namespace glslang

View File

@ -455,6 +455,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
token = scanToken(ppToken);
}
} else {
token = tokenPaste(token, *ppToken);
token = evalToToken(token, shortCircuit, res, err, ppToken);
return eval(token, precedence, shortCircuit, res, err, ppToken);
}

View File

@ -658,14 +658,17 @@ public:
blocks.back().numMembers = countAggregateMembers(type);
EShLanguageMask& stages = blocks.back().stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
if (updateStageMasks) {
EShLanguageMask& stages = blocks.back().stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
}
}
else {
blockIndex = it->second;
EShLanguageMask& stages = blocks[blockIndex].stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
if (updateStageMasks) {
EShLanguageMask& stages = blocks[blockIndex].stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
}
}
}