From 0c8292f2af5839d01da8a72201097470f131cd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Mon, 27 Nov 2023 22:27:59 -0800 Subject: [PATCH] Updated glslang. --- 3rdparty/glslang/SPIRV/GlslangToSpv.cpp | 141 +++++++++--------- 3rdparty/glslang/SPIRV/GlslangToSpv.h | 20 ++- 3rdparty/glslang/SPIRV/SPVRemapper.h | 2 +- 3rdparty/glslang/SPIRV/SpvBuilder.cpp | 58 ++++--- 3rdparty/glslang/SPIRV/SpvBuilder.h | 9 +- 3rdparty/glslang/SPIRV/SpvTools.h | 13 +- 3rdparty/glslang/StandAlone/StandAlone.cpp | 1 + .../glslang/glslang/HLSL/hlslParseHelper.cpp | 2 + .../glslang/glslang/HLSL/hlslScanContext.cpp | 1 + 3rdparty/glslang/glslang/Include/Common.h | 28 ---- 3rdparty/glslang/glslang/Include/Types.h | 4 +- .../glslang/MachineIndependent/Constant.cpp | 4 +- .../glslang/MachineIndependent/Initialize.cpp | 22 +-- .../MachineIndependent/Intermediate.cpp | 40 ++++- .../MachineIndependent/ParseContextBase.cpp | 4 +- .../MachineIndependent/ParseHelper.cpp | 72 ++++++--- .../glslang/MachineIndependent/intermOut.cpp | 4 +- .../glslang/MachineIndependent/iomapper.cpp | 4 +- .../MachineIndependent/localintermediate.h | 10 +- tools/shaderc/shaderc_metal.cpp | 7 +- tools/shaderc/shaderc_spirv.cpp | 5 +- 21 files changed, 248 insertions(+), 203 deletions(-) diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp index daa855cac..671f3db36 100755 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp +++ b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp @@ -43,6 +43,7 @@ #include "spirv.hpp" #include "GlslangToSpv.h" #include "SpvBuilder.h" +#include "SpvTools.h" namespace spv { #include "GLSL.std.450.h" #include "GLSL.ext.KHR.h" @@ -66,6 +67,7 @@ namespace spv { #include #include #include +#include #include #include #include @@ -164,6 +166,7 @@ protected: spv::Id convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly = false); spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&, bool lastBufferBlockMember, bool forwardReferenceOnly = false); + void applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional member); bool filterMember(const glslang::TType& member); spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, const glslang::TQualifier&); @@ -4705,6 +4708,64 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty return spvType; } +// Apply SPIR-V decorations to the SPIR-V object (provided by SPIR-V ID). If member index is provided, the +// decorations are applied to this member. +void TGlslangToSpvTraverser::applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional member) +{ + assert(type.getQualifier().hasSpirvDecorate()); + + const glslang::TSpirvDecorate& spirvDecorate = type.getQualifier().getSpirvDecorate(); + + // Add spirv_decorate + for (auto& decorate : spirvDecorate.decorates) { + if (!decorate.second.empty()) { + std::vector literals; + TranslateLiterals(decorate.second, literals); + if (member.has_value()) + builder.addMemberDecoration(id, *member, static_cast(decorate.first), literals); + else + builder.addDecoration(id, static_cast(decorate.first), literals); + } else { + if (member.has_value()) + builder.addMemberDecoration(id, *member, static_cast(decorate.first)); + else + builder.addDecoration(id, static_cast(decorate.first)); + } + } + + // Add spirv_decorate_id + if (member.has_value()) { + // spirv_decorate_id not applied to members + assert(spirvDecorate.decorateIds.empty()); + } else { + for (auto& decorateId : spirvDecorate.decorateIds) { + std::vector operandIds; + assert(!decorateId.second.empty()); + for (auto extraOperand : decorateId.second) { + if (extraOperand->getQualifier().isFrontEndConstant()) + operandIds.push_back(createSpvConstant(*extraOperand)); + else + operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode())); + } + builder.addDecorationId(id, static_cast(decorateId.first), operandIds); + } + } + + // Add spirv_decorate_string + for (auto& decorateString : spirvDecorate.decorateStrings) { + std::vector strings; + assert(!decorateString.second.empty()); + for (auto extraOperand : decorateString.second) { + const char* string = extraOperand->getConstArray()[0].getSConst()->c_str(); + strings.push_back(string); + } + if (member.has_value()) + builder.addMemberDecoration(id, *member, static_cast(decorateString.first), strings); + else + builder.addDecoration(id, static_cast(decorateString.first), strings); + } +} + // TODO: this functionality should exist at a higher level, in creating the AST // // Identify interface members that don't have their required extension turned on. @@ -4943,37 +5004,9 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); } - // - // Add SPIR-V decorations for members (GL_EXT_spirv_intrinsics) - // - if (glslangMember.getQualifier().hasSprivDecorate()) { - const glslang::TSpirvDecorate& spirvDecorate = glslangMember.getQualifier().getSpirvDecorate(); - - // Add spirv_decorate - for (auto& decorate : spirvDecorate.decorates) { - if (!decorate.second.empty()) { - std::vector literals; - TranslateLiterals(decorate.second, literals); - builder.addMemberDecoration(spvType, member, static_cast(decorate.first), literals); - } - else - builder.addMemberDecoration(spvType, member, static_cast(decorate.first)); - } - - // spirv_decorate_id not applied to members - assert(spirvDecorate.decorateIds.empty()); - - // Add spirv_decorate_string - for (auto& decorateString : spirvDecorate.decorateStrings) { - std::vector strings; - assert(!decorateString.second.empty()); - for (auto extraOperand : decorateString.second) { - const char* string = extraOperand->getConstArray()[0].getSConst()->c_str(); - strings.push_back(string); - } - builder.addDecoration(spvType, static_cast(decorateString.first), strings); - } - } + // Add SPIR-V decorations (GL_EXT_spirv_intrinsics) + if (glslangMember.getQualifier().hasSpirvDecorate()) + applySpirvDecorate(glslangMember, spvType, member); } // Decorate the structure @@ -5462,7 +5495,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF spv::Function* function = builder.makeFunctionEntry( TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()), glslFunction->getName().c_str(), convertGlslangLinkageToSpv(glslFunction->getLinkType()), paramTypes, - paramNames, paramDecorations, &functionBlock); + paramDecorations, &functionBlock); builder.setupDebugFunctionEntry(function, glslFunction->getName().c_str(), glslFunction->getLoc().line, paramTypes, paramNames); if (implicitThis) @@ -9598,47 +9631,9 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); } - // - // Add SPIR-V decorations for structure (GL_EXT_spirv_intrinsics) - // - if (symbol->getType().getQualifier().hasSprivDecorate()) { - const glslang::TSpirvDecorate& spirvDecorate = symbol->getType().getQualifier().getSpirvDecorate(); - - // Add spirv_decorate - for (auto& decorate : spirvDecorate.decorates) { - if (!decorate.second.empty()) { - std::vector literals; - TranslateLiterals(decorate.second, literals); - builder.addDecoration(id, static_cast(decorate.first), literals); - } - else - builder.addDecoration(id, static_cast(decorate.first)); - } - - // Add spirv_decorate_id - for (auto& decorateId : spirvDecorate.decorateIds) { - std::vector operandIds; - assert(!decorateId.second.empty()); - for (auto extraOperand : decorateId.second) { - if (extraOperand->getQualifier().isFrontEndConstant()) - operandIds.push_back(createSpvConstant(*extraOperand)); - else - operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode())); - } - builder.addDecorationId(id, static_cast(decorateId.first), operandIds); - } - - // Add spirv_decorate_string - for (auto& decorateString : spirvDecorate.decorateStrings) { - std::vector strings; - assert(!decorateString.second.empty()); - for (auto extraOperand : decorateString.second) { - const char* string = extraOperand->getConstArray()[0].getSConst()->c_str(); - strings.push_back(string); - } - builder.addDecoration(id, static_cast(decorateString.first), strings); - } - } + // Add SPIR-V decorations (GL_EXT_spirv_intrinsics) + if (symbol->getType().getQualifier().hasSpirvDecorate()) + applySpirvDecorate(symbol->getType(), id, {}); return id; } diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.h b/3rdparty/glslang/SPIRV/GlslangToSpv.h index b9736d7c9..1b9ef3c51 100644 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.h +++ b/3rdparty/glslang/SPIRV/GlslangToSpv.h @@ -35,19 +35,25 @@ #pragma once -#if defined(_MSC_VER) && _MSC_VER >= 1900 - #pragma warning(disable : 4464) // relative include path contains '..' -#endif - -#include "SpvTools.h" -#include "glslang/Include/intermediate.h" - #include #include #include "Logger.h" namespace glslang { +class TIntermediate; + +struct SpvOptions { + bool generateDebugInfo {false}; + bool stripDebugInfo {false}; + bool disableOptimizer {true}; + bool optimizeSize {false}; + bool disassemble {false}; + bool validate {false}; + bool emitNonSemanticShaderDebugInfo {false}; + bool emitNonSemanticShaderDebugSource{ false }; + bool compileOnly{false}; +}; void GetSpirvVersion(std::string&); int GetSpirvGeneratorVersion(); diff --git a/3rdparty/glslang/SPIRV/SPVRemapper.h b/3rdparty/glslang/SPIRV/SPVRemapper.h index 42b01686e..33efe331e 100644 --- a/3rdparty/glslang/SPIRV/SPVRemapper.h +++ b/3rdparty/glslang/SPIRV/SPVRemapper.h @@ -77,9 +77,9 @@ public: #include #include "spirv.hpp" -#include "spvIR.h" namespace spv { +const Id NoResult = 0; // class to hold SPIR-V binary data for remapping, DCE, and debug stripping class spirvbin_t : public spirvbin_base_t diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.cpp b/3rdparty/glslang/SPIRV/SpvBuilder.cpp index 7586ecf59..f898b7541 100644 --- a/3rdparty/glslang/SPIRV/SpvBuilder.cpp +++ b/3rdparty/glslang/SPIRV/SpvBuilder.cpp @@ -1182,13 +1182,26 @@ Id Builder::makeDebugExpression() return debugExpression; } -Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const localVariable) +Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const pointer) { Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); inst->addIdOperand(nonSemanticShaderDebugInfo); inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugDeclare); inst->addIdOperand(debugLocalVariable); // debug local variable id - inst->addIdOperand(localVariable); // local variable id + inst->addIdOperand(pointer); // pointer to local variable id + inst->addIdOperand(makeDebugExpression()); // expression id + buildPoint->addInstruction(std::unique_ptr(inst)); + + return inst->getResultId(); +} + +Id Builder::makeDebugValue(Id const debugLocalVariable, Id const value) +{ + Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); + inst->addIdOperand(nonSemanticShaderDebugInfo); + inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugValue); + inst->addIdOperand(debugLocalVariable); // debug local variable id + inst->addIdOperand(value); // value of local variable id inst->addIdOperand(makeDebugExpression()); // expression id buildPoint->addInstruction(std::unique_ptr(inst)); @@ -2061,11 +2074,6 @@ Function* Builder::makeEntryPoint(const char* entryPoint) { assert(! entryPointFunction); - Block* entry; - std::vector paramsTypes; - std::vector paramNames; - std::vector> decorations; - auto const returnType = makeVoidType(); restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo; @@ -2073,7 +2081,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint) emitNonSemanticShaderDebugInfo = false; } - entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, LinkageTypeMax, paramsTypes, paramNames, decorations, &entry); + Block* entry = nullptr; + entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, LinkageTypeMax, {}, {}, &entry); emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; @@ -2082,8 +2091,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint) // Comments in header Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, - const std::vector& paramTypes, const std::vector& paramNames, - const std::vector>& decorations, Block **entry) + const std::vector& paramTypes, + const std::vector>& decorations, Block** entry) { // Make the function and initial instructions in it Id typeId = makeFunctionType(returnType, paramTypes); @@ -2148,20 +2157,25 @@ void Builder::setupDebugFunctionEntry(Function* function, const char* name, int Id firstParamId = function->getParamId(0); for (size_t p = 0; p < paramTypes.size(); ++p) { - auto getParamTypeId = [this](Id const& typeId) { - if (isPointerType(typeId) || isArrayType(typeId)) { - return getContainedTypeId(typeId); - } else { - return typeId; - } - }; + bool passByRef = false; + Id paramTypeId = paramTypes[p]; + + // For pointer-typed parameters, they are actually passed by reference and we need unwrap the pointer to get the actual parameter type. + if (isPointerType(paramTypeId) || isArrayType(paramTypeId)) { + passByRef = true; + paramTypeId = getContainedTypeId(paramTypeId); + } + auto const& paramName = paramNames[p]; - auto const debugLocalVariableId = - createDebugLocalVariable(debugId[getParamTypeId(paramTypes[p])], paramName, p + 1); + auto const debugLocalVariableId = createDebugLocalVariable(debugId[paramTypeId], paramName, p + 1); + auto const paramId = static_cast(firstParamId + p); + debugId[paramId] = debugLocalVariableId; - debugId[firstParamId + p] = debugLocalVariableId; - - makeDebugDeclare(debugLocalVariableId, firstParamId + p); + if (passByRef) { + makeDebugDeclare(debugLocalVariableId, paramId); + } else { + makeDebugValue(debugLocalVariableId, paramId); + } } } diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.h b/3rdparty/glslang/SPIRV/SpvBuilder.h index 1a85b1d67..eae8d4f56 100644 --- a/3rdparty/glslang/SPIRV/SpvBuilder.h +++ b/3rdparty/glslang/SPIRV/SpvBuilder.h @@ -231,7 +231,7 @@ public: Id createDebugGlobalVariable(Id const type, char const*const name, Id const variable); Id createDebugLocalVariable(Id type, char const*const name, size_t const argNumber = 0); Id makeDebugExpression(); - Id makeDebugDeclare(Id const debugLocalVariable, Id const localVariable); + Id makeDebugDeclare(Id const debugLocalVariable, Id const pointer); Id makeDebugValue(Id const debugLocalVariable, Id const value); Id makeDebugFunctionType(Id returnType, const std::vector& paramTypes); Id makeDebugFunction(Function* function, Id nameId, Id funcTypeId); @@ -420,10 +420,9 @@ public: // Make a shader-style function, and create its entry block if entry is non-zero. // Return the function, pass back the entry. // The returned pointer is only valid for the lifetime of this builder. - Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, - LinkageType linkType, const std::vector& paramTypes, - const std::vector& paramNames, - const std::vector>& precisions, Block **entry = nullptr); + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, + const std::vector& paramTypes, + const std::vector>& precisions, Block** entry = nullptr); // Create a return. An 'implicit' return is one not appearing in the source // code. In the case of an implicit return, no post-return block is inserted. diff --git a/3rdparty/glslang/SPIRV/SpvTools.h b/3rdparty/glslang/SPIRV/SpvTools.h index a4ce11b88..eabde4666 100644 --- a/3rdparty/glslang/SPIRV/SpvTools.h +++ b/3rdparty/glslang/SPIRV/SpvTools.h @@ -48,22 +48,11 @@ #endif #include "glslang/MachineIndependent/localintermediate.h" +#include "GlslangToSpv.h" #include "Logger.h" namespace glslang { -struct SpvOptions { - bool generateDebugInfo {false}; - bool stripDebugInfo {false}; - bool disableOptimizer {true}; - bool optimizeSize {false}; - bool disassemble {false}; - bool validate {false}; - bool emitNonSemanticShaderDebugInfo {false}; - bool emitNonSemanticShaderDebugSource{ false }; - bool compileOnly{false}; -}; - #if ENABLE_OPT // Translate glslang's view of target versioning to what SPIRV-Tools uses. diff --git a/3rdparty/glslang/StandAlone/StandAlone.cpp b/3rdparty/glslang/StandAlone/StandAlone.cpp index 28565365b..ed3deccd0 100644 --- a/3rdparty/glslang/StandAlone/StandAlone.cpp +++ b/3rdparty/glslang/StandAlone/StandAlone.cpp @@ -46,6 +46,7 @@ #include "DirStackFileIncluder.h" #include "./../glslang/Include/ShHandle.h" #include "./../glslang/Public/ShaderLang.h" +#include "../glslang/MachineIndependent/localintermediate.h" #include "../SPIRV/GlslangToSpv.h" #include "../SPIRV/GLSL.std.450.h" #include "../SPIRV/doc.h" diff --git a/3rdparty/glslang/glslang/HLSL/hlslParseHelper.cpp b/3rdparty/glslang/glslang/HLSL/hlslParseHelper.cpp index ac0dee50c..b0fb5f466 100644 --- a/3rdparty/glslang/glslang/HLSL/hlslParseHelper.cpp +++ b/3rdparty/glslang/glslang/HLSL/hlslParseHelper.cpp @@ -9551,6 +9551,8 @@ bool HlslParseContext::isInputBuiltIn(const TQualifier& qualifier) const return language == EShLangTessEvaluation; case EbvTessCoord: return language == EShLangTessEvaluation; + case EbvViewIndex: + return language != EShLangCompute; default: return false; } diff --git a/3rdparty/glslang/glslang/HLSL/hlslScanContext.cpp b/3rdparty/glslang/glslang/HLSL/hlslScanContext.cpp index 823b17aa3..e9edb6197 100644 --- a/3rdparty/glslang/glslang/HLSL/hlslScanContext.cpp +++ b/3rdparty/glslang/glslang/HLSL/hlslScanContext.cpp @@ -512,6 +512,7 @@ void HlslScanContext::fillInKeywordMap() (*SemanticMap)["SV_PRIMITIVEID"] = EbvPrimitiveId; (*SemanticMap)["SV_OUTPUTCONTROLPOINTID"] = EbvInvocationId; (*SemanticMap)["SV_ISFRONTFACE"] = EbvFace; + (*SemanticMap)["SV_VIEWID"] = EbvViewIndex; (*SemanticMap)["SV_INSTANCEID"] = EbvInstanceIndex; (*SemanticMap)["SV_INSIDETESSFACTOR"] = EbvTessLevelInner; (*SemanticMap)["SV_GSINSTANCEID"] = EbvInvocationId; diff --git a/3rdparty/glslang/glslang/Include/Common.h b/3rdparty/glslang/glslang/Include/Common.h index abfe84469..64dc1cdd5 100644 --- a/3rdparty/glslang/glslang/Include/Common.h +++ b/3rdparty/glslang/glslang/Include/Common.h @@ -294,34 +294,6 @@ template int IntLog2(T n) return result; } -inline bool IsInfinity(double x) { -#ifdef _MSC_VER - switch (_fpclass(x)) { - case _FPCLASS_NINF: - case _FPCLASS_PINF: - return true; - default: - return false; - } -#else - return std::isinf(x); -#endif -} - -inline bool IsNan(double x) { -#ifdef _MSC_VER - switch (_fpclass(x)) { - case _FPCLASS_SNAN: - case _FPCLASS_QNAN: - return true; - default: - return false; - } -#else - return std::isnan(x); -#endif -} - } // end namespace glslang #endif // _COMMON_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/Types.h b/3rdparty/glslang/glslang/Include/Types.h index 26aba9bbf..0a1aff8d2 100644 --- a/3rdparty/glslang/glslang/Include/Types.h +++ b/3rdparty/glslang/glslang/Include/Types.h @@ -1075,7 +1075,7 @@ public: } // GL_EXT_spirv_intrinsics - bool hasSprivDecorate() const { return spirvDecorate != nullptr; } + bool hasSpirvDecorate() const { return spirvDecorate != nullptr; } void setSpirvDecorate(int decoration, const TIntermAggregate* args = nullptr); void setSpirvDecorateId(int decoration, const TIntermAggregate* args); void setSpirvDecorateString(int decoration, const TIntermAggregate* args); @@ -2096,7 +2096,7 @@ public: const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; if (getQualifiers) { - if (qualifier.hasSprivDecorate()) + if (qualifier.hasSpirvDecorate()) appendStr(qualifier.getSpirvDecorateQualifierString().c_str()); if (qualifier.hasLayout()) { diff --git a/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp b/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp index 8acf9e552..4f706cad8 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp @@ -628,12 +628,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) case EOpIsNan: { - newConstArray[i].setBConst(IsNan(unionArray[i].getDConst())); + newConstArray[i].setBConst(std::isnan(unionArray[i].getDConst())); break; } case EOpIsInf: { - newConstArray[i].setBConst(IsInfinity(unionArray[i].getDConst())); + newConstArray[i].setBConst(std::isinf(unionArray[i].getDConst())); break; } diff --git a/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp b/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp index 8d5ce9af8..9feb261a5 100755 --- a/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp @@ -144,10 +144,10 @@ EProfile EDesktopProfile = static_cast(ENoProfile | ECoreProfile | ECo { EBadProfile } }; const Versioning* Es300Desktop130 = &Es300Desktop130Version[0]; - const Versioning Es310Desktop420Version[] = { { EEsProfile, 0, 310, 0, nullptr }, - { EDesktopProfile, 0, 420, 0, nullptr }, + const Versioning Es310Desktop400Version[] = { { EEsProfile, 0, 310, 0, nullptr }, + { EDesktopProfile, 0, 400, 0, nullptr }, { EBadProfile } }; - const Versioning* Es310Desktop420 = &Es310Desktop420Version[0]; + const Versioning* Es310Desktop400 = &Es310Desktop400Version[0]; const Versioning Es310Desktop450Version[] = { { EEsProfile, 0, 310, 0, nullptr }, { EDesktopProfile, 0, 450, 0, nullptr }, @@ -246,14 +246,14 @@ const BuiltInFunction BaseFunctions[] = { { EOpGreaterThanEqual, "greaterThanEqual", 2, TypeU, ClassBNS, Es300Desktop130 }, { EOpVectorEqual, "equal", 2, TypeU, ClassBNS, Es300Desktop130 }, { EOpVectorNotEqual, "notEqual", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpAtomicAdd, "atomicAdd", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, - { EOpAtomicMin, "atomicMin", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, - { EOpAtomicMax, "atomicMax", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, - { EOpAtomicAnd, "atomicAnd", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, - { EOpAtomicOr, "atomicOr", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, - { EOpAtomicXor, "atomicXor", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, - { EOpAtomicExchange, "atomicExchange", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, - { EOpAtomicCompSwap, "atomicCompSwap", 3, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicAdd, "atomicAdd", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, + { EOpAtomicMin, "atomicMin", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, + { EOpAtomicMax, "atomicMax", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, + { EOpAtomicAnd, "atomicAnd", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, + { EOpAtomicOr, "atomicOr", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, + { EOpAtomicXor, "atomicXor", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, + { EOpAtomicExchange, "atomicExchange", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, + { EOpAtomicCompSwap, "atomicCompSwap", 3, TypeIU, ClassV1FIOCV, Es310Desktop400 }, { EOpMix, "mix", 3, TypeB, ClassRegular, Es310Desktop450 }, { EOpMix, "mix", 3, TypeIU, ClassLB, Es310Desktop450 }, diff --git a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp b/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp index a8e3b38bf..5d3fc8afe 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp @@ -2590,6 +2590,18 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseT { assert(baseType == EbtFloat || baseType == EbtDouble || baseType == EbtFloat16); + if (isEsProfile() && (baseType == EbtFloat || baseType == EbtFloat16)) { + int exponent = 0; + frexp(d, &exponent); + int minExp = baseType == EbtFloat ? -126 : -14; + int maxExp = baseType == EbtFloat ? 127 : 15; + if (exponent > maxExp) { //overflow, d = inf + d = std::numeric_limits::infinity(); + } else if (exponent < minExp) { //underflow, d = 0.0; + d = 0.0; + } + } + TConstUnionArray unionArray(1); unionArray[0].setDConst(d); @@ -2647,28 +2659,42 @@ TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selecto // 'swizzleOkay' says whether or not it is okay to consider a swizzle // a valid part of the dereference chain. // -// 'BufferReferenceOk' says if type is buffer_reference, the routine stop to find the most left node. +// 'bufferReferenceOk' says if type is buffer_reference, the routine will stop to find the most left node. // +// 'proc' is an optional function to run on each node that is processed during the traversal. 'proc' must +// return true to continue the traversal, or false to end the traversal early. // -const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay , bool bufferReferenceOk) +const TIntermTyped* TIntermediate::traverseLValueBase(const TIntermTyped* node, bool swizzleOkay, + bool bufferReferenceOk, + std::function proc) { do { const TIntermBinary* binary = node->getAsBinaryNode(); - if (binary == nullptr) + if (binary == nullptr) { + if (proc) { + proc(*node); + } return node; + } TOperator op = binary->getOp(); - if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle && op != EOpMatrixSwizzle) + if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle && + op != EOpMatrixSwizzle) return nullptr; - if (! swizzleOkay) { + if (!swizzleOkay) { if (op == EOpVectorSwizzle || op == EOpMatrixSwizzle) return nullptr; if ((op == EOpIndexDirect || op == EOpIndexIndirect) && (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) && - ! binary->getLeft()->getType().isArray()) + !binary->getLeft()->getType().isArray()) return nullptr; } - node = node->getAsBinaryNode()->getLeft(); + if (proc) { + if (!proc(*node)) { + return node; + } + } + node = binary->getLeft(); if (bufferReferenceOk && node->isReference()) return node; } while (true); diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp index e8e32d926..9b1196727 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp @@ -208,7 +208,7 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, // // If we get here, we have an error and a message. // - const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true); + const TIntermTyped* leftMostTypeNode = TIntermediate::traverseLValueBase(node, true); if (symNode) error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); @@ -234,7 +234,7 @@ void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, const TIntermSymbol* symNode = node->getAsSymbolNode(); if (node->getQualifier().isWriteOnly()) { - const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true); + const TIntermTyped* leftMostTypeNode = TIntermediate::traverseLValueBase(node, true); if (symNode != nullptr) error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp index 592e9aa8a..0dad047d7 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp @@ -2571,7 +2571,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); } - const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true , true); + const TIntermTyped* base = TIntermediate::traverseLValueBase(arg0, true, true); const char* errMsg = "Only l-values corresponding to shader block storage or shared variables can be used with " "atomic memory functions."; if (base) { @@ -2591,20 +2591,57 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan case EOpInterpolateAtCentroid: case EOpInterpolateAtSample: case EOpInterpolateAtOffset: - case EOpInterpolateAtVertex: - // Make sure the first argument is an interpolant, or an array element of an interpolant + case EOpInterpolateAtVertex: { if (arg0->getType().getQualifier().storage != EvqVaryingIn) { - // It might still be an array element. + // Traverse down the left branch of arg0 to ensure this argument is a valid interpolant. // - // We could check more, but the semantics of the first argument are already met; the - // only way to turn an array into a float/vec* is array dereference and swizzle. + // For desktop GL >4.3 we effectively only need to ensure that arg0 represents an l-value from an + // input declaration. // - // ES and desktop 4.3 and earlier: swizzles may not be used - // desktop 4.4 and later: swizzles may be used - bool swizzleOkay = (!isEsProfile()) && (version >= 440); - const TIntermTyped* base = TIntermediate::findLValueBase(arg0, swizzleOkay); - if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn) - error(loc, "first argument must be an interpolant, or interpolant-array element", fnCandidate.getName().c_str(), ""); + // For desktop GL <= 4.3 and ES, we must also ensure that swizzling is not used + // + // For ES, we must also ensure that a field selection operator (i.e., '.') is not used on a named + // struct. + + const bool esProfile = isEsProfile(); + const bool swizzleOkay = !esProfile && (version >= 440); + + std::string interpolantErrorMsg = "first argument must be an interpolant, or interpolant-array element"; + bool isValid = true; // Assume that the interpolant is valid until we find a condition making it invalid + bool isIn = false; // Checks whether or not the interpolant is a shader input + bool structAccessOp = false; // Whether or not the previous node in the chain is a struct accessor + TIntermediate::traverseLValueBase( + arg0, swizzleOkay, false, + [&isValid, &isIn, &interpolantErrorMsg, esProfile, &structAccessOp](const TIntermNode& n) -> bool { + auto* type = n.getAsTyped(); + if (type) { + if (type->getType().getQualifier().storage == EvqVaryingIn) { + isIn = true; + } + // If a field accessor was used, it can only be used to access a field with an input block, not a struct. + if (structAccessOp && (type->getType().getBasicType() != EbtBlock)) { + interpolantErrorMsg += + ". Using the field of a named struct as an interpolant argument is not " + "allowed (ES-only)."; + isValid = false; + } + } + + // ES has different requirements for interpolants than GL + if (esProfile) { + // Swizzling will be taken care of by the 'swizzleOkay' argument passsed to traverseLValueBase, + // so we only ned to check whether or not a field accessor has been used with a named struct. + auto* binary = n.getAsBinaryNode(); + if (binary && (binary->getOp() == EOpIndexDirectStruct)) { + structAccessOp = true; + } + } + // Don't continue traversing if we know we have an invalid interpolant at this point. + return isValid; + }); + if (!isIn || !isValid) { + error(loc, interpolantErrorMsg.c_str(), fnCandidate.getName().c_str(), ""); + } } if (callNode.getOp() == EOpInterpolateAtVertex) { @@ -2620,7 +2657,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } } } - break; + } break; case EOpEmitStreamVertex: case EOpEndStreamPrimitive: @@ -4191,8 +4228,8 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons dst.spirvStorageClass = src.spirvStorageClass; // SPIR-V decorate qualifiers (GL_EXT_spirv_intrinsics) - if (src.hasSprivDecorate()) { - if (dst.hasSprivDecorate()) { + if (src.hasSpirvDecorate()) { + if (dst.hasSpirvDecorate()) { const TSpirvDecorate& srcSpirvDecorate = src.getSpirvDecorate(); TSpirvDecorate& dstSpirvDecorate = dst.getSpirvDecorate(); for (auto& decorate : srcSpirvDecorate.decorates) { @@ -6326,8 +6363,7 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb switch (qualifier.storage) { case EvqVaryingIn: case EvqVaryingOut: - if (!type.getQualifier().isTaskMemory() && - !type.getQualifier().hasSprivDecorate() && + if (!type.getQualifier().isTaskMemory() && !type.getQualifier().hasSpirvDecorate() && (type.getBasicType() != EbtBlock || (!(*type.getStruct())[0].type->getQualifier().hasLocation() && (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))) @@ -8540,7 +8576,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con memberQualifier.storage = EvqtaskPayloadSharedEXT; if (memberQualifier.storage == EvqSpirvStorageClass) error(memberLoc, "member cannot have a spirv_storage_class qualifier", memberType.getFieldName().c_str(), ""); - if (memberQualifier.hasSprivDecorate() && !memberQualifier.getSpirvDecorate().decorateIds.empty()) + if (memberQualifier.hasSpirvDecorate() && !memberQualifier.getSpirvDecorate().decorateIds.empty()) error(memberLoc, "member cannot have a spirv_decorate_id qualifier", memberType.getFieldName().c_str(), ""); if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())) error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), ""); diff --git a/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp b/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp index 32c3c573f..5b1414c94 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp @@ -1208,12 +1208,12 @@ bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node // - shows all digits, no premature rounding static void OutputDouble(TInfoSink& out, double value, TOutputTraverser::EExtraOutput extra) { - if (IsInfinity(value)) { + if (std::isinf(value)) { if (value < 0) out.debug << "-1.#INF"; else out.debug << "+1.#INF"; - } else if (IsNan(value)) + } else if (std::isnan(value)) out.debug << "1.#IND"; else { const int maxSize = 340; diff --git a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp index 63dedf76c..ed853256b 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp @@ -866,7 +866,7 @@ int TDefaultIoResolverBase::resolveInOutLocation(EShLanguage stage, TVarEntryInf } // no locations added if already present, a built-in variable, or a variable with SPIR-V decorate - if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getQualifier().hasSprivDecorate()) { + if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getQualifier().hasSpirvDecorate()) { return ent.newLocation = -1; } @@ -953,7 +953,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf return ent.newLocation = type.getQualifier().layoutLocation; } // no locations added if already present, a built-in variable, or a variable with SPIR-V decorate - if (type.isBuiltIn() || type.getQualifier().hasSprivDecorate()) { + if (type.isBuiltIn() || type.getQualifier().hasSpirvDecorate()) { return ent.newLocation = -1; } // no locations on blocks of built-in variables diff --git a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h index 2f0e65ce3..a7d4e18a4 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h +++ b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h @@ -43,11 +43,12 @@ #include "../Public/ShaderLang.h" #include "Versions.h" +#include +#include +#include +#include #include #include -#include -#include -#include class TInfoSink; @@ -572,7 +573,8 @@ public: TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); // Tree ops - static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false); + static const TIntermTyped* traverseLValueBase(const TIntermTyped*, bool swizzleOkay, bool bufferReferenceOk = false, + std::function proc = {}); // Linkage related void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); diff --git a/tools/shaderc/shaderc_metal.cpp b/tools/shaderc/shaderc_metal.cpp index 1b7cc8480..3c243ff9e 100644 --- a/tools/shaderc/shaderc_metal.cpp +++ b/tools/shaderc/shaderc_metal.cpp @@ -5,6 +5,8 @@ #include "shaderc.h" +#include // std::cout + BX_PRAGMA_DIAGNOSTIC_PUSH() BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // error C4100: 'inclusionDepth' : unreferenced formal parameter BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4265) // error C4265: 'spv::spirvbin_t': class has virtual functions, but destructor is not virtual @@ -15,8 +17,9 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u #define ENABLE_OPT 1 #include #include -#include #include +#include +#include #define SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS #include #include @@ -489,8 +492,6 @@ namespace bgfx { namespace metal program->dumpReflection(); } - BX_UNUSED(spv::MemorySemanticsAllMemory); - glslang::TIntermediate* intermediate = program->getIntermediate(stage); std::vector spirv; diff --git a/tools/shaderc/shaderc_spirv.cpp b/tools/shaderc/shaderc_spirv.cpp index 07b410ad4..f12f1668b 100644 --- a/tools/shaderc/shaderc_spirv.cpp +++ b/tools/shaderc/shaderc_spirv.cpp @@ -5,6 +5,8 @@ #include "shaderc.h" +#include // std::cout + BX_PRAGMA_DIAGNOSTIC_PUSH() BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // error C4100: 'inclusionDepth' : unreferenced formal parameter BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4265) // error C4265: 'spv::spirvbin_t': class has virtual functions, but destructor is not virtual @@ -17,6 +19,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u #include #include #include +#include #define SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS #include #include @@ -698,8 +701,6 @@ namespace bgfx { namespace spirv program->dumpReflection(); } - BX_UNUSED(spv::MemorySemanticsAllMemory); - glslang::TIntermediate* intermediate = program->getIntermediate(stage); std::vector spirv;