From 7fc0b67b3473e88d2085bd77e0611b35a646a44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sat, 3 Jun 2017 11:11:11 -0700 Subject: [PATCH] Updated glslang. --- 3rdparty/glslang/SPIRV/GlslangToSpv.cpp | 55 +++- 3rdparty/glslang/SPIRV/GlslangToSpv.h | 11 +- 3rdparty/glslang/SPIRV/SpvBuilder.cpp | 84 ++++- 3rdparty/glslang/SPIRV/SpvBuilder.h | 24 +- 3rdparty/glslang/SPIRV/spvIR.h | 3 - 3rdparty/glslang/StandAlone/CMakeLists.txt | 3 +- .../glslang/StandAlone/DirStackFileIncluder.h | 125 ++++++++ 3rdparty/glslang/StandAlone/StandAlone.cpp | 18 +- 3rdparty/glslang/Test/bar.h | 1 + .../baseResults/hlsl.aliasOpaque.frag.out | 174 ++++++++++ .../baseResults/hlsl.flattenOpaque.frag.out | 297 +++++++++++++++++ .../Test/baseResults/hlsl.include.vert.out | 75 +++++ .../baseResults/hlsl.includeNegative.vert.out | 10 + .../glslang/Test/baseResults/include.vert.out | 69 ++++ .../Test/baseResults/spv.debugInfo.frag.out | 272 ++++++++++++++++ .../Test/baseResults/spv.ssboAlias.frag.out | 88 +++++ .../spv.texture.sampler.transform.frag.out | 38 +++ 3rdparty/glslang/Test/foo.h | 1 + 3rdparty/glslang/Test/hlsl.aliasOpaque.frag | 29 ++ 3rdparty/glslang/Test/hlsl.flattenOpaque.frag | 40 +++ 3rdparty/glslang/Test/hlsl.include.vert | 8 + .../glslang/Test/hlsl.includeNegative.vert | 8 + 3rdparty/glslang/Test/inc1/badInc.h | 1 + 3rdparty/glslang/Test/inc1/bar.h | 3 + 3rdparty/glslang/Test/inc1/foo.h | 3 + 3rdparty/glslang/Test/inc2/bar.h | 2 + 3rdparty/glslang/Test/inc2/foo.h | 1 + 3rdparty/glslang/Test/include.vert | 16 + 3rdparty/glslang/Test/parent.h | 1 + 3rdparty/glslang/Test/parentBad | 3 + 3rdparty/glslang/Test/runtests | 22 +- 3rdparty/glslang/Test/spv.debugInfo.frag | 52 +++ 3rdparty/glslang/Test/spv.ssboAlias.frag | 10 + .../Test/spv.texture.sampler.transform.frag | 13 + 3rdparty/glslang/glslang/Include/Types.h | 1 + .../MachineIndependent/Intermediate.cpp | 45 +++ .../MachineIndependent/ParseHelper.cpp | 11 + .../glslang/MachineIndependent/ShaderLang.cpp | 11 +- .../glslang/MachineIndependent/iomapper.cpp | 42 +-- .../MachineIndependent/localintermediate.h | 16 +- .../MachineIndependent/preprocessor/Pp.cpp | 10 +- 3rdparty/glslang/glslang/Public/ShaderLang.h | 29 +- 3rdparty/glslang/gtests/Hlsl.FromFile.cpp | 2 + 3rdparty/glslang/gtests/Spv.FromFile.cpp | 19 ++ 3rdparty/glslang/gtests/TestFixture.h | 29 +- 3rdparty/glslang/hlsl/hlslParseHelper.cpp | 302 ++++++++++++++---- 3rdparty/glslang/hlsl/hlslParseHelper.h | 9 +- 3rdparty/glslang/hlsl/hlslParseables.cpp | 2 +- tools/shaderc/shaderc_spirv.cpp | 9 +- 49 files changed, 1920 insertions(+), 177 deletions(-) create mode 100644 3rdparty/glslang/StandAlone/DirStackFileIncluder.h create mode 100644 3rdparty/glslang/Test/bar.h create mode 100755 3rdparty/glslang/Test/baseResults/hlsl.aliasOpaque.frag.out create mode 100755 3rdparty/glslang/Test/baseResults/hlsl.flattenOpaque.frag.out create mode 100755 3rdparty/glslang/Test/baseResults/hlsl.include.vert.out create mode 100755 3rdparty/glslang/Test/baseResults/hlsl.includeNegative.vert.out create mode 100644 3rdparty/glslang/Test/baseResults/include.vert.out create mode 100644 3rdparty/glslang/Test/baseResults/spv.debugInfo.frag.out create mode 100755 3rdparty/glslang/Test/baseResults/spv.ssboAlias.frag.out create mode 100644 3rdparty/glslang/Test/baseResults/spv.texture.sampler.transform.frag.out create mode 100644 3rdparty/glslang/Test/foo.h create mode 100644 3rdparty/glslang/Test/hlsl.aliasOpaque.frag create mode 100644 3rdparty/glslang/Test/hlsl.flattenOpaque.frag create mode 100644 3rdparty/glslang/Test/hlsl.include.vert create mode 100644 3rdparty/glslang/Test/hlsl.includeNegative.vert create mode 100644 3rdparty/glslang/Test/inc1/badInc.h create mode 100644 3rdparty/glslang/Test/inc1/bar.h create mode 100644 3rdparty/glslang/Test/inc1/foo.h create mode 100644 3rdparty/glslang/Test/inc2/bar.h create mode 100644 3rdparty/glslang/Test/inc2/foo.h create mode 100644 3rdparty/glslang/Test/include.vert create mode 100644 3rdparty/glslang/Test/parent.h create mode 100644 3rdparty/glslang/Test/parentBad create mode 100644 3rdparty/glslang/Test/spv.debugInfo.frag create mode 100644 3rdparty/glslang/Test/spv.ssboAlias.frag create mode 100644 3rdparty/glslang/Test/spv.texture.sampler.transform.frag diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp index 966acef49..e175bfc65 100755 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp +++ b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp @@ -101,7 +101,7 @@ private: // class TGlslangToSpvTraverser : public glslang::TIntermTraverser { public: - TGlslangToSpvTraverser(const glslang::TIntermediate*, spv::SpvBuildLogger* logger); + TGlslangToSpvTraverser(const glslang::TIntermediate*, spv::SpvBuildLogger* logger, glslang::SpvOptions& options); virtual ~TGlslangToSpvTraverser() { } bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*); @@ -179,6 +179,7 @@ protected: spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); spv::Id getExtBuiltins(const char* name); + glslang::SpvOptions& options; spv::Function* shaderEntry; spv::Function* currentFunction; spv::Instruction* entryPoint; @@ -851,8 +852,11 @@ bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifie // Implement the TGlslangToSpvTraverser class. // -TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate, spv::SpvBuildLogger* buildLogger) - : TIntermTraverser(true, false, true), shaderEntry(nullptr), currentFunction(nullptr), +TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate, + spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) + : TIntermTraverser(true, false, true), + options(options), + shaderEntry(nullptr), currentFunction(nullptr), sequenceDepth(0), logger(buildLogger), builder((glslang::GetKhronosToolId() << 16) | GeneratorVersion, logger), inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), @@ -862,6 +866,11 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls builder.clearAccessChain(); builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), glslangIntermediate->getVersion()); + if (options.generateDebugInfo) { + builder.setSourceFile(glslangIntermediate->getSourceFile()); + builder.setSourceText(glslangIntermediate->getSourceText()); + builder.setEmitOpLines(); + } stdBuiltins = builder.import("GLSL.std.450"); builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str()); @@ -1069,6 +1078,8 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) { + builder.setLine(node->getLoc().line); + SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); if (node->getType().getQualifier().isSpecConstant()) spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); @@ -1256,6 +1267,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) { + builder.setLine(node->getLoc().line); + SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); if (node->getType().getQualifier().isSpecConstant()) spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); @@ -1499,6 +1512,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt return false; case glslang::EOpFunctionCall: { + builder.setLine(node->getLoc().line); if (node->isUserDefined()) result = handleUserFunctionCall(node); // assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done @@ -1605,6 +1619,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpConstructStruct: case glslang::EOpConstructTextureSampler: { + builder.setLine(node->getLoc().line); std::vector arguments; translateArguments(*node, arguments); spv::Id constructed; @@ -1715,6 +1730,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt right->traverse(this); spv::Id rightId = accessChainLoad(right->getType()); + builder.setLine(node->getLoc().line); result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()), resultType(), leftId, rightId, left->getType().getBasicType(), reduceComparison); @@ -1787,10 +1803,13 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt glslangOperands[arg]->traverse(this); if (lvalue) operands.push_back(builder.accessChainGetLValue()); - else + else { + builder.setLine(node->getLoc().line); operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); + } } + builder.setLine(node->getLoc().line); if (atomic) { // Handle all atomics result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); @@ -1872,6 +1891,8 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang node->getFalseBlock()->traverse(this); spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); + builder.setLine(node->getLoc().line); + // smear condition to vector, if necessary (AST is always scalar) if (builder.isVector(trueValue)) condition = builder.smearScalar(spv::NoPrecision, condition, @@ -2014,6 +2035,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn // by a block-ending branch. But we don't want to put any other body/test // instructions in it, since the body/test may have arbitrary instructions, // including merges of its own. + builder.setLine(node->getLoc().line); builder.setBuildPoint(&blocks.head); builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control); if (node->testFirst() && node->getTest()) { @@ -2022,8 +2044,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn builder.setBuildPoint(&test); node->getTest()->traverse(this); - spv::Id condition = - accessChainLoad(node->getTest()->getType()); + spv::Id condition = accessChainLoad(node->getTest()->getType()); builder.createConditionalBranch(condition, &blocks.body, &blocks.merge); builder.setBuildPoint(&blocks.body); @@ -2038,6 +2059,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn node->getTerminal()->traverse(this); builder.createBranch(&blocks.head); } else { + builder.setLine(node->getLoc().line); builder.createBranch(&blocks.body); breakForLoop.push(true); @@ -2072,6 +2094,8 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T if (node->getExpression()) node->getExpression()->traverse(this); + builder.setLine(node->getLoc().line); + switch (node->getFlowOp()) { case glslang::EOpKill: builder.makeDiscard(); @@ -3049,9 +3073,11 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node) { - if (! node->isImage() && ! node->isTexture()) { + if (! node->isImage() && ! node->isTexture()) return spv::NoResult; - } + + builder.setLine(node->getLoc().line); + auto resultType = [&node,this]{ return convertGlslangToSpvType(node->getType()); }; // Process a GLSL texturing op (will be SPV image) @@ -5561,22 +5587,27 @@ void OutputSpvHex(const std::vector& spirv, const char* baseName, // // Set up the glslang traversal // -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv) +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, SpvOptions* options) { spv::SpvBuildLogger logger; - GlslangToSpv(intermediate, spirv, &logger); + GlslangToSpv(intermediate, spirv, &logger, options); } -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, spv::SpvBuildLogger* logger) +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options) { TIntermNode* root = intermediate.getTreeRoot(); if (root == 0) return; + glslang::SpvOptions defaultOptions; + if (options == nullptr) + options = &defaultOptions; + glslang::GetThreadPoolAllocator().push(); - TGlslangToSpvTraverser it(&intermediate, logger); + TGlslangToSpvTraverser it(&intermediate, logger, *options); root->traverse(&it); it.finishSpv(); it.dumpSpv(spirv); diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.h b/3rdparty/glslang/SPIRV/GlslangToSpv.h index aba48a383..0dad4d219 100644 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.h +++ b/3rdparty/glslang/SPIRV/GlslangToSpv.h @@ -47,9 +47,16 @@ namespace glslang { +struct SpvOptions { + SpvOptions() : generateDebugInfo(false) { } + bool generateDebugInfo; +}; + void GetSpirvVersion(std::string&); -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv); -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, spv::SpvBuildLogger* logger); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); void OutputSpvBin(const std::vector& spirv, const char* baseName); void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.cpp b/3rdparty/glslang/SPIRV/SpvBuilder.cpp index 0add1db40..ffd17af1b 100644 --- a/3rdparty/glslang/SPIRV/SpvBuilder.cpp +++ b/3rdparty/glslang/SPIRV/SpvBuilder.cpp @@ -59,6 +59,9 @@ namespace spv { Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) : source(SourceLanguageUnknown), sourceVersion(0), + sourceFileStringId(NoResult), + currentLine(0), + emitOpLines(false), addressModel(AddressingModelLogical), memoryModel(MemoryModelGLSL450), builderNumber(magicNumber), @@ -84,6 +87,26 @@ Id Builder::import(const char* name) return import->getResultId(); } +// Emit an OpLine if we've been asked to emit OpLines and the line number +// has changed since the last time, and is a valid line number. +void Builder::setLine(int lineNum) +{ + if (lineNum != 0 && lineNum != currentLine) { + currentLine = lineNum; + if (emitOpLines) + addLine(sourceFileStringId, currentLine, 0); + } +} + +void Builder::addLine(Id fileName, int lineNum, int column) +{ + Instruction* line = new Instruction(OpLine); + line->addIdOperand(fileName); + line->addImmediateOperand(lineNum); + line->addImmediateOperand(column); + buildPoint->addInstruction(std::unique_ptr(line)); +} + // For creating new groupedTypes (will return old type if the requested one was already made). Id Builder::makeVoidType() { @@ -928,17 +951,6 @@ void Builder::addMemberName(Id id, int memberNumber, const char* string) names.push_back(std::unique_ptr(name)); } -void Builder::addLine(Id target, Id fileName, int lineNum, int column) -{ - Instruction* line = new Instruction(OpLine); - line->addIdOperand(target); - line->addIdOperand(fileName); - line->addImmediateOperand(lineNum); - line->addImmediateOperand(column); - - lines.push_back(std::unique_ptr(line)); -} - void Builder::addDecoration(Id id, Decoration decoration, int num) { if (decoration == spv::DecorationMax) @@ -2411,12 +2423,8 @@ void Builder::dump(std::vector& out) const dumpInstructions(out, executionModes); // Debug instructions - if (source != SourceLanguageUnknown) { - Instruction sourceInst(0, 0, OpSource); - sourceInst.addImmediateOperand(source); - sourceInst.addImmediateOperand(sourceVersion); - sourceInst.dump(out); - } + dumpInstructions(out, strings); + dumpSourceInstructions(out); for (int e = 0; e < (int)sourceExtensions.size(); ++e) { Instruction sourceExtInst(0, 0, OpSourceExtension); sourceExtInst.addStringOperand(sourceExtensions[e]); @@ -2574,6 +2582,48 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els elseBlock->addPredecessor(buildPoint); } +// OpSource +// [OpSourceContinued] +// ... +void Builder::dumpSourceInstructions(std::vector& out) const +{ + const int maxWordCount = 0xFFFF; + const int opSourceWordCount = 4; + const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1; + + if (source != SourceLanguageUnknown) { + // OpSource Language Version File Source + Instruction sourceInst(NoResult, NoType, OpSource); + sourceInst.addImmediateOperand(source); + sourceInst.addImmediateOperand(sourceVersion); + // File operand + if (sourceFileStringId != NoResult) { + sourceInst.addIdOperand(sourceFileStringId); + // Source operand + if (sourceText.size() > 0) { + int nextByte = 0; + std::string subString; + while ((int)sourceText.size() - nextByte > 0) { + subString = sourceText.substr(nextByte, nonNullBytesPerInstruction); + if (nextByte == 0) { + // OpSource + sourceInst.addStringOperand(subString.c_str()); + sourceInst.dump(out); + } else { + // OpSourcContinued + Instruction sourceContinuedInst(OpSourceContinued); + sourceContinuedInst.addStringOperand(subString.c_str()); + sourceContinuedInst.dump(out); + } + nextByte += nonNullBytesPerInstruction; + } + } else + sourceInst.dump(out); + } else + sourceInst.dump(out); + } +} + void Builder::dumpInstructions(std::vector& out, const std::vector >& instructions) const { for (int i = 0; i < (int)instructions.size(); ++i) { diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.h b/3rdparty/glslang/SPIRV/SpvBuilder.h index d93174ed2..60d97e9c8 100755 --- a/3rdparty/glslang/SPIRV/SpvBuilder.h +++ b/3rdparty/glslang/SPIRV/SpvBuilder.h @@ -70,7 +70,16 @@ public: source = lang; sourceVersion = version; } + void setSourceFile(const std::string& file) + { + Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString); + fileString->addStringOperand(file.c_str()); + sourceFileStringId = fileString->getResultId(); + strings.push_back(std::unique_ptr(fileString)); + } + void setSourceText(const std::string& text) { sourceText = text; } void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void setEmitOpLines() { emitOpLines = true; } void addExtension(const char* ext) { extensions.insert(ext); } Id import(const char*); void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) @@ -92,6 +101,12 @@ public: return id; } + // Log the current line, and if different than the last one, + // issue a new OpLine, using the current file name. + void setLine(int line); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + // For creating new types (will return old type if the requested one was already made). Id makeVoidType(); Id makeBoolType(); @@ -213,7 +228,6 @@ public: void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); void addName(Id, const char* name); void addMemberName(Id, int member, const char* name); - void addLine(Id target, Id fileName, int line, int column); void addDecoration(Id, Decoration, int num = -1); void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); @@ -561,10 +575,15 @@ public: void simplifyAccessChainSwizzle(); void createAndSetNoPredecessorBlock(const char*); void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; void dumpInstructions(std::vector&, const std::vector >&) const; SourceLanguage source; int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + bool emitOpLines; std::set extensions; std::vector sourceExtensions; AddressingModel addressModel; @@ -579,6 +598,7 @@ public: AccessChain accessChain; // special blocks of instructions for output + std::vector > strings; std::vector > imports; std::vector > entryPoints; std::vector > executionModes; @@ -599,7 +619,7 @@ public: // Our loop stack. std::stack loops; - // The stream for outputing warnings and errors. + // The stream for outputting warnings and errors. SpvBuildLogger* logger; }; // end Builder class diff --git a/3rdparty/glslang/SPIRV/spvIR.h b/3rdparty/glslang/SPIRV/spvIR.h index ce8b4b8a0..087a53f26 100755 --- a/3rdparty/glslang/SPIRV/spvIR.h +++ b/3rdparty/glslang/SPIRV/spvIR.h @@ -87,7 +87,6 @@ public: void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); } void addStringOperand(const char* str) { - originalString = str; unsigned int word; char* wordString = (char*)&word; char* wordPtr = wordString; @@ -120,7 +119,6 @@ public: Id getTypeId() const { return typeId; } Id getIdOperand(int op) const { return operands[op]; } unsigned int getImmediateOperand(int op) const { return operands[op]; } - const char* getStringOperand() const { return originalString.c_str(); } // Write out the binary form. void dump(std::vector& out) const @@ -151,7 +149,6 @@ protected: Id typeId; Op opCode; std::vector operands; - std::string originalString; // could be optimized away; convenience for getting string operand Block* block; }; diff --git a/3rdparty/glslang/StandAlone/CMakeLists.txt b/3rdparty/glslang/StandAlone/CMakeLists.txt index f37fb0f9f..c61667cc0 100644 --- a/3rdparty/glslang/StandAlone/CMakeLists.txt +++ b/3rdparty/glslang/StandAlone/CMakeLists.txt @@ -6,7 +6,7 @@ target_include_directories(glslang-default-resource-limits PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${PROJECT_SOURCE_DIR}) -set(SOURCES StandAlone.cpp) +set(SOURCES StandAlone.cpp DirStackFileIncluder.h) set(REMAPPER_SOURCES spirv-remap.cpp) add_executable(glslangValidator ${SOURCES}) @@ -22,7 +22,6 @@ set(LIBRARIES SPVRemapper glslang-default-resource-limits) - if(WIN32) set(LIBRARIES ${LIBRARIES} psapi) elseif(UNIX) diff --git a/3rdparty/glslang/StandAlone/DirStackFileIncluder.h b/3rdparty/glslang/StandAlone/DirStackFileIncluder.h new file mode 100644 index 000000000..8f06f9ea8 --- /dev/null +++ b/3rdparty/glslang/StandAlone/DirStackFileIncluder.h @@ -0,0 +1,125 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2017 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +#include +#include +#include +#include + +#include "./../glslang/Public/ShaderLang.h" + +// Default include class for normal include convention of search backward +// through the stack of active include paths (for nested includes). +// Can be overridden to customize. +class DirStackFileIncluder : public glslang::TShader::Includer { +public: + virtual IncludeResult* includeLocal(const char* headerName, + const char* includerName, + size_t inclusionDepth) override + { + return readLocalPath(headerName, includerName, inclusionDepth); + } + + virtual IncludeResult* includeSystem(const char* headerName, + const char* /*includerName*/, + size_t /*inclusionDepth*/) override + { + return readSystemPath(headerName); + } + + virtual void releaseInclude(IncludeResult* result) override + { + if (result != nullptr) { + delete [] static_cast(result->userData); + delete result; + } + } + + virtual ~DirStackFileIncluder() override { } + +protected: + typedef char tUserDataElement; + std::vector directoryStack; + + // Search for a valid "local" path based on combining the stack of include + // directories and the nominal name of the header. + virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) + { + // Discard popped include directories, and if first level, initialize. + directoryStack.resize(depth); + if (depth == 1) + directoryStack.front() = getDirectory(includerName); + + // find a directory that works, reverse search of include stack + for (auto it = directoryStack.rbegin(); it != directoryStack.rend(); ++it) { + std::string path = *it + '/' + headerName; + std::replace(path.begin(), path.end(), '\\', '/'); + std::ifstream file(path, std::ios_base::binary | std::ios_base::ate); + if (file) { + directoryStack.push_back(getDirectory(path)); + return newIncludeResult(path, file, (int)file.tellg()); + } + } + + return nullptr; + } + + // Search for a valid path. + // Not implemented yet; returning nullptr signals failure to find. + virtual IncludeResult* readSystemPath(const char* /*headerName*/) const + { + return nullptr; + } + + // Do actual reading of the file, filling in a new include result. + virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const + { + char* content = new tUserDataElement [length]; + file.seekg(0, file.beg); + file.read(content, length); + return new IncludeResult(path, content, length, content); + } + + // If no path markers, return current working directory. + // Otherwise, strip file name and return path leading up to it. + virtual std::string getDirectory(const std::string path) const + { + size_t last = path.find_last_of("/\\"); + return last == std::string::npos ? "." : path.substr(0, last); + } +}; diff --git a/3rdparty/glslang/StandAlone/StandAlone.cpp b/3rdparty/glslang/StandAlone/StandAlone.cpp index 8a6b12dc4..40110e35d 100644 --- a/3rdparty/glslang/StandAlone/StandAlone.cpp +++ b/3rdparty/glslang/StandAlone/StandAlone.cpp @@ -41,6 +41,7 @@ #include "ResourceLimits.h" #include "Worklist.h" +#include "DirStackFileIncluder.h" #include "./../glslang/Include/ShHandle.h" #include "./../glslang/Include/revision.h" #include "./../glslang/Public/ShaderLang.h" @@ -48,6 +49,7 @@ #include "../SPIRV/GLSL.std.450.h" #include "../SPIRV/doc.h" #include "../SPIRV/disassemble.h" + #include #include #include @@ -91,6 +93,7 @@ enum TOptions { EOptionHlslOffsets = (1 << 23), EOptionHlslIoMapping = (1 << 24), EOptionAutoMapLocations = (1 << 25), + EOptionDebug = (1 << 26), }; // @@ -448,6 +451,9 @@ void ProcessArguments(std::vector>& workItem } else Error("no provided for -e"); break; + case 'g': + Options |= EOptionDebug; + break; case 'h': usage(); break; @@ -539,6 +545,8 @@ void SetMessageOptions(EShMessages& messages) messages = (EShMessages)(messages | EShMsgKeepUncalled); if (Options & EOptionHlslOffsets) messages = (EShMessages)(messages | EShMsgHlslOffsets); + if (Options & EOptionDebug) + messages = (EShMessages)(messages | EShMsgDebugInfo); } // @@ -659,9 +667,9 @@ void CompileAndLinkShaderUnits(std::vector compUnits) const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100; + DirStackFileIncluder includer; if (Options & EOptionOutputPreprocessed) { std::string str; - glslang::TShader::ForbidIncluder includer; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str, includer)) { PutsIfNonEmpty(str.c_str()); @@ -672,7 +680,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) StderrIfNonEmpty(shader->getInfoDebugLog()); continue; } - if (! shader->parse(&Resources, defaultVersion, false, messages)) + if (! shader->parse(&Resources, defaultVersion, false, messages, includer)) CompileFailed = true; program.addShader(shader); @@ -722,7 +730,10 @@ void CompileAndLinkShaderUnits(std::vector compUnits) std::vector spirv; std::string warningsErrors; spv::SpvBuildLogger logger; - glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger); + glslang::SpvOptions spvOptions; + if (Options & EOptionDebug) + spvOptions.generateDebugInfo = true; + glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger, &spvOptions); // Dump the spv to a file or stdout, etc., but only if not doing // memory/perf testing, as it's not internal to programmatic use. @@ -1031,6 +1042,7 @@ void usage() " (default is ES version 100)\n" " -D input is HLSL\n" " -e specify entry-point name\n" + " -g generate debug information\n" " -h print this usage message\n" " -i intermediate tree (glslang AST) is printed out\n" " -l link all input files together to form a single module\n" diff --git a/3rdparty/glslang/Test/bar.h b/3rdparty/glslang/Test/bar.h new file mode 100644 index 000000000..c206a325d --- /dev/null +++ b/3rdparty/glslang/Test/bar.h @@ -0,0 +1 @@ +float4 i1; diff --git a/3rdparty/glslang/Test/baseResults/hlsl.aliasOpaque.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.aliasOpaque.frag.out new file mode 100755 index 000000000..370dcb1aa --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.aliasOpaque.frag.out @@ -0,0 +1,174 @@ +hlsl.aliasOpaque.frag +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:12 Function Definition: osCall(struct-OS-p1-f1-t211; ( temp 4-component vector of float) +0:12 Function Parameters: +0:? 'ss' ( in sampler) +0:? 'a' ( in float) +0:? 'tex' ( in texture2D) +0:? Sequence +0:13 Branch: Return with expression +0:13 vector-scale ( temp 4-component vector of float) +0:? 'a' ( in float) +0:13 texture ( temp 4-component vector of float) +0:13 Construct combined texture-sampler ( temp sampler2D) +0:? 'tex' ( in texture2D) +0:? 'ss' ( in sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:17 Function Definition: @main( ( temp 4-component vector of float) +0:17 Function Parameters: +0:? Sequence +0:19 'gss2' ( uniform sampler) +0:20 'gss' ( uniform sampler) +0:21 'gtex' ( uniform texture2D) +0:22 move second child to first child ( temp float) +0:? 'a' ( temp float) +0:22 Constant: +0:22 3.000000 +0:28 Branch: Return with expression +0:28 Function Call: osCall(struct-OS-p1-f1-t211; ( temp 4-component vector of float) +0:? 'gss' ( uniform sampler) +0:? 'a' ( temp float) +0:? 'gtex' ( uniform texture2D) +0:17 Function Definition: main( ( temp void) +0:17 Function Parameters: +0:? Sequence +0:17 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:17 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'gss' ( uniform sampler) +0:? 'gss2' ( uniform sampler) +0:? 'gtex' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:12 Function Definition: osCall(struct-OS-p1-f1-t211; ( temp 4-component vector of float) +0:12 Function Parameters: +0:? 'ss' ( in sampler) +0:? 'a' ( in float) +0:? 'tex' ( in texture2D) +0:? Sequence +0:13 Branch: Return with expression +0:13 vector-scale ( temp 4-component vector of float) +0:? 'a' ( in float) +0:13 texture ( temp 4-component vector of float) +0:13 Construct combined texture-sampler ( temp sampler2D) +0:? 'tex' ( in texture2D) +0:? 'ss' ( in sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:17 Function Definition: @main( ( temp 4-component vector of float) +0:17 Function Parameters: +0:? Sequence +0:19 'gss2' ( uniform sampler) +0:20 'gss' ( uniform sampler) +0:21 'gtex' ( uniform texture2D) +0:22 move second child to first child ( temp float) +0:? 'a' ( temp float) +0:22 Constant: +0:22 3.000000 +0:28 Branch: Return with expression +0:28 Function Call: osCall(struct-OS-p1-f1-t211; ( temp 4-component vector of float) +0:? 'gss' ( uniform sampler) +0:? 'a' ( temp float) +0:? 'gtex' ( uniform texture2D) +0:17 Function Definition: main( ( temp void) +0:17 Function Parameters: +0:? Sequence +0:17 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:17 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'gss' ( uniform sampler) +0:? 'gss2' ( uniform sampler) +0:? 'gtex' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 48 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 46 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 17 "osCall(struct-OS-p1-f1-t211;" + Name 14 "ss" + Name 15 "a" + Name 16 "tex" + Name 20 "@main(" + Name 35 "gss2" + Name 36 "gss" + Name 37 "gtex" + Name 38 "a" + Name 40 "param" + Name 46 "@entryPointOutput" + Decorate 35(gss2) DescriptorSet 0 + Decorate 36(gss) DescriptorSet 0 + Decorate 37(gtex) DescriptorSet 0 + Decorate 46(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeSampler + 7: TypePointer UniformConstant 6 + 8: TypeFloat 32 + 9: TypePointer Function 8(float) + 10: TypeImage 8(float) 2D sampled format:Unknown + 11: TypePointer UniformConstant 10 + 12: TypeVector 8(float) 4 + 13: TypeFunction 12(fvec4) 7(ptr) 9(ptr) 11(ptr) + 19: TypeFunction 12(fvec4) + 25: TypeSampledImage 10 + 27: TypeVector 8(float) 2 + 28: 8(float) Constant 1045220557 + 29: 8(float) Constant 1050253722 + 30: 27(fvec2) ConstantComposite 28 29 + 35(gss2): 7(ptr) Variable UniformConstant + 36(gss): 7(ptr) Variable UniformConstant + 37(gtex): 11(ptr) Variable UniformConstant + 39: 8(float) Constant 1077936128 + 45: TypePointer Output 12(fvec4) +46(@entryPointOutput): 45(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 47: 12(fvec4) FunctionCall 20(@main() + Store 46(@entryPointOutput) 47 + Return + FunctionEnd +17(osCall(struct-OS-p1-f1-t211;): 12(fvec4) Function None 13 + 14(ss): 7(ptr) FunctionParameter + 15(a): 9(ptr) FunctionParameter + 16(tex): 11(ptr) FunctionParameter + 18: Label + 22: 8(float) Load 15(a) + 23: 10 Load 16(tex) + 24: 6 Load 14(ss) + 26: 25 SampledImage 23 24 + 31: 12(fvec4) ImageSampleImplicitLod 26 30 + 32: 12(fvec4) VectorTimesScalar 31 22 + ReturnValue 32 + FunctionEnd + 20(@main(): 12(fvec4) Function None 19 + 21: Label + 38(a): 9(ptr) Variable Function + 40(param): 9(ptr) Variable Function + Store 38(a) 39 + 41: 8(float) Load 38(a) + Store 40(param) 41 + 42: 12(fvec4) FunctionCall 17(osCall(struct-OS-p1-f1-t211;) 36(gss) 40(param) 37(gtex) + ReturnValue 42 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/hlsl.flattenOpaque.frag.out b/3rdparty/glslang/Test/baseResults/hlsl.flattenOpaque.frag.out new file mode 100755 index 000000000..392ff722a --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.flattenOpaque.frag.out @@ -0,0 +1,297 @@ +hlsl.flattenOpaque.frag +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:15 Function Definition: osCall1(struct-os-p11; ( temp 4-component vector of float) +0:15 Function Parameters: +0:? 's2D' ( in sampler) +0:? Sequence +0:16 Branch: Return with expression +0:16 texture ( temp 4-component vector of float) +0:16 Construct combined texture-sampler ( temp sampler2D) +0:16 'tex' ( uniform texture2D) +0:? 's2D' ( in sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:20 Function Definition: osCall2(struct-os-p11;vf2; ( temp 4-component vector of float) +0:20 Function Parameters: +0:? 's2D' ( in sampler) +0:20 'f2' ( in 2-component vector of float) +0:? Sequence +0:21 Branch: Return with expression +0:21 texture ( temp 4-component vector of float) +0:21 Construct combined texture-sampler ( temp sampler2D) +0:21 'tex' ( uniform texture2D) +0:? 's2D' ( in sampler) +0:21 'f2' ( in 2-component vector of float) +0:25 Function Definition: os2Call1(struct-os2-p1-t211; ( temp 4-component vector of float) +0:25 Function Parameters: +0:? 's2D' ( in sampler) +0:? 'tex' ( in texture2D) +0:? Sequence +0:26 Branch: Return with expression +0:26 texture ( temp 4-component vector of float) +0:26 Construct combined texture-sampler ( temp sampler2D) +0:? 'tex' ( in texture2D) +0:? 's2D' ( in sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:30 Function Definition: os2Call2(struct-os2-p1-t211;vf2; ( temp 4-component vector of float) +0:30 Function Parameters: +0:? 's2D' ( in sampler) +0:? 'tex' ( in texture2D) +0:30 'f2' ( in 2-component vector of float) +0:? Sequence +0:31 Branch: Return with expression +0:31 texture ( temp 4-component vector of float) +0:31 Construct combined texture-sampler ( temp sampler2D) +0:? 'tex' ( in texture2D) +0:? 's2D' ( in sampler) +0:31 'f2' ( in 2-component vector of float) +0:35 Function Definition: @main( ( temp 4-component vector of float) +0:35 Function Parameters: +0:? Sequence +0:39 Branch: Return with expression +0:38 add ( temp 4-component vector of float) +0:37 add ( temp 4-component vector of float) +0:36 add ( temp 4-component vector of float) +0:36 Function Call: osCall1(struct-os-p11; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:37 Function Call: osCall2(struct-os-p11;vf2; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:38 Function Call: os2Call1(struct-os2-p1-t211; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:? 'tex' ( uniform texture2D) +0:39 Function Call: os2Call2(struct-os2-p1-t211;vf2; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:? 'tex' ( uniform texture2D) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:35 Function Definition: main( ( temp void) +0:35 Function Parameters: +0:? Sequence +0:35 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:35 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'tex' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 500 +gl_FragCoord origin is upper left +0:? Sequence +0:15 Function Definition: osCall1(struct-os-p11; ( temp 4-component vector of float) +0:15 Function Parameters: +0:? 's2D' ( in sampler) +0:? Sequence +0:16 Branch: Return with expression +0:16 texture ( temp 4-component vector of float) +0:16 Construct combined texture-sampler ( temp sampler2D) +0:16 'tex' ( uniform texture2D) +0:? 's2D' ( in sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:20 Function Definition: osCall2(struct-os-p11;vf2; ( temp 4-component vector of float) +0:20 Function Parameters: +0:? 's2D' ( in sampler) +0:20 'f2' ( in 2-component vector of float) +0:? Sequence +0:21 Branch: Return with expression +0:21 texture ( temp 4-component vector of float) +0:21 Construct combined texture-sampler ( temp sampler2D) +0:21 'tex' ( uniform texture2D) +0:? 's2D' ( in sampler) +0:21 'f2' ( in 2-component vector of float) +0:25 Function Definition: os2Call1(struct-os2-p1-t211; ( temp 4-component vector of float) +0:25 Function Parameters: +0:? 's2D' ( in sampler) +0:? 'tex' ( in texture2D) +0:? Sequence +0:26 Branch: Return with expression +0:26 texture ( temp 4-component vector of float) +0:26 Construct combined texture-sampler ( temp sampler2D) +0:? 'tex' ( in texture2D) +0:? 's2D' ( in sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:30 Function Definition: os2Call2(struct-os2-p1-t211;vf2; ( temp 4-component vector of float) +0:30 Function Parameters: +0:? 's2D' ( in sampler) +0:? 'tex' ( in texture2D) +0:30 'f2' ( in 2-component vector of float) +0:? Sequence +0:31 Branch: Return with expression +0:31 texture ( temp 4-component vector of float) +0:31 Construct combined texture-sampler ( temp sampler2D) +0:? 'tex' ( in texture2D) +0:? 's2D' ( in sampler) +0:31 'f2' ( in 2-component vector of float) +0:35 Function Definition: @main( ( temp 4-component vector of float) +0:35 Function Parameters: +0:? Sequence +0:39 Branch: Return with expression +0:38 add ( temp 4-component vector of float) +0:37 add ( temp 4-component vector of float) +0:36 add ( temp 4-component vector of float) +0:36 Function Call: osCall1(struct-os-p11; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:37 Function Call: osCall2(struct-os-p11;vf2; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:38 Function Call: os2Call1(struct-os2-p1-t211; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:? 'tex' ( uniform texture2D) +0:39 Function Call: os2Call2(struct-os2-p1-t211;vf2; ( temp 4-component vector of float) +0:? 's2D' ( uniform sampler) +0:? 'tex' ( uniform texture2D) +0:? Constant: +0:? 0.200000 +0:? 0.300000 +0:35 Function Definition: main( ( temp void) +0:35 Function Parameters: +0:? Sequence +0:35 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) +0:35 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? 'tex' ( uniform texture2D) +0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 85 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 83 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 12 "osCall1(struct-os-p11;" + Name 11 "s2D" + Name 19 "osCall2(struct-os-p11;vf2;" + Name 17 "s2D" + Name 18 "f2" + Name 26 "os2Call1(struct-os2-p1-t211;" + Name 24 "s2D" + Name 25 "tex" + Name 32 "os2Call2(struct-os2-p1-t211;vf2;" + Name 29 "s2D" + Name 30 "tex" + Name 31 "f2" + Name 35 "@main(" + Name 37 "tex" + Name 68 "s2D" + Name 70 "param" + Name 73 "s2D" + Name 74 "tex" + Name 77 "param" + Name 83 "@entryPointOutput" + Decorate 37(tex) DescriptorSet 0 + Decorate 68(s2D) DescriptorSet 0 + Decorate 73(s2D) DescriptorSet 0 + Decorate 74(tex) DescriptorSet 0 + Decorate 83(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeSampler + 7: TypePointer UniformConstant 6 + 8: TypeFloat 32 + 9: TypeVector 8(float) 4 + 10: TypeFunction 9(fvec4) 7(ptr) + 14: TypeVector 8(float) 2 + 15: TypePointer Function 14(fvec2) + 16: TypeFunction 9(fvec4) 7(ptr) 15(ptr) + 21: TypeImage 8(float) 2D sampled format:Unknown + 22: TypePointer UniformConstant 21 + 23: TypeFunction 9(fvec4) 7(ptr) 22(ptr) + 28: TypeFunction 9(fvec4) 7(ptr) 22(ptr) 15(ptr) + 34: TypeFunction 9(fvec4) + 37(tex): 22(ptr) Variable UniformConstant + 40: TypeSampledImage 21 + 42: 8(float) Constant 1045220557 + 43: 8(float) Constant 1050253722 + 44: 14(fvec2) ConstantComposite 42 43 + 68(s2D): 7(ptr) Variable UniformConstant + 73(s2D): 7(ptr) Variable UniformConstant + 74(tex): 22(ptr) Variable UniformConstant + 82: TypePointer Output 9(fvec4) +83(@entryPointOutput): 82(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 84: 9(fvec4) FunctionCall 35(@main() + Store 83(@entryPointOutput) 84 + Return + FunctionEnd +12(osCall1(struct-os-p11;): 9(fvec4) Function None 10 + 11(s2D): 7(ptr) FunctionParameter + 13: Label + 38: 21 Load 37(tex) + 39: 6 Load 11(s2D) + 41: 40 SampledImage 38 39 + 45: 9(fvec4) ImageSampleImplicitLod 41 44 + ReturnValue 45 + FunctionEnd +19(osCall2(struct-os-p11;vf2;): 9(fvec4) Function None 16 + 17(s2D): 7(ptr) FunctionParameter + 18(f2): 15(ptr) FunctionParameter + 20: Label + 48: 21 Load 37(tex) + 49: 6 Load 17(s2D) + 50: 40 SampledImage 48 49 + 51: 14(fvec2) Load 18(f2) + 52: 9(fvec4) ImageSampleImplicitLod 50 51 + ReturnValue 52 + FunctionEnd +26(os2Call1(struct-os2-p1-t211;): 9(fvec4) Function None 23 + 24(s2D): 7(ptr) FunctionParameter + 25(tex): 22(ptr) FunctionParameter + 27: Label + 55: 21 Load 25(tex) + 56: 6 Load 24(s2D) + 57: 40 SampledImage 55 56 + 58: 9(fvec4) ImageSampleImplicitLod 57 44 + ReturnValue 58 + FunctionEnd +32(os2Call2(struct-os2-p1-t211;vf2;): 9(fvec4) Function None 28 + 29(s2D): 7(ptr) FunctionParameter + 30(tex): 22(ptr) FunctionParameter + 31(f2): 15(ptr) FunctionParameter + 33: Label + 61: 21 Load 30(tex) + 62: 6 Load 29(s2D) + 63: 40 SampledImage 61 62 + 64: 14(fvec2) Load 31(f2) + 65: 9(fvec4) ImageSampleImplicitLod 63 64 + ReturnValue 65 + FunctionEnd + 35(@main(): 9(fvec4) Function None 34 + 36: Label + 70(param): 15(ptr) Variable Function + 77(param): 15(ptr) Variable Function + 69: 9(fvec4) FunctionCall 12(osCall1(struct-os-p11;) 68(s2D) + Store 70(param) 44 + 71: 9(fvec4) FunctionCall 19(osCall2(struct-os-p11;vf2;) 68(s2D) 70(param) + 72: 9(fvec4) FAdd 69 71 + 75: 9(fvec4) FunctionCall 26(os2Call1(struct-os2-p1-t211;) 73(s2D) 74(tex) + 76: 9(fvec4) FAdd 72 75 + Store 77(param) 44 + 78: 9(fvec4) FunctionCall 32(os2Call2(struct-os2-p1-t211;vf2;) 73(s2D) 74(tex) 77(param) + 79: 9(fvec4) FAdd 76 78 + ReturnValue 79 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/hlsl.include.vert.out b/3rdparty/glslang/Test/baseResults/hlsl.include.vert.out new file mode 100755 index 000000000..8f31aa0f4 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.include.vert.out @@ -0,0 +1,75 @@ +../Test/hlsl.include.vert +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 44 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 42 + Source HLSL 500 + Name 4 "main" + Name 9 "@main(" + Name 11 "$Global" + MemberName 11($Global) 0 "i1" + MemberName 11($Global) 1 "i2" + MemberName 11($Global) 2 "i4" + MemberName 11($Global) 3 "i3" + MemberName 11($Global) 4 "i6" + MemberName 11($Global) 5 "i5" + Name 13 "" + Name 42 "@entryPointOutput" + MemberDecorate 11($Global) 0 Offset 0 + MemberDecorate 11($Global) 1 Offset 16 + MemberDecorate 11($Global) 2 Offset 32 + MemberDecorate 11($Global) 3 Offset 48 + MemberDecorate 11($Global) 4 Offset 64 + MemberDecorate 11($Global) 5 Offset 80 + Decorate 11($Global) Block + Decorate 13 DescriptorSet 0 + Decorate 42(@entryPointOutput) BuiltIn Position + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11($Global): TypeStruct 7(fvec4) 7(fvec4) 7(fvec4) 7(fvec4) 7(fvec4) 7(fvec4) + 12: TypePointer Uniform 11($Global) + 13: 12(ptr) Variable Uniform + 14: TypeInt 32 1 + 15: 14(int) Constant 0 + 16: TypePointer Uniform 7(fvec4) + 19: 14(int) Constant 1 + 23: 14(int) Constant 3 + 27: 14(int) Constant 2 + 31: 14(int) Constant 5 + 35: 14(int) Constant 4 + 41: TypePointer Output 7(fvec4) +42(@entryPointOutput): 41(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 43: 7(fvec4) FunctionCall 9(@main() + Store 42(@entryPointOutput) 43 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label + 17: 16(ptr) AccessChain 13 15 + 18: 7(fvec4) Load 17 + 20: 16(ptr) AccessChain 13 19 + 21: 7(fvec4) Load 20 + 22: 7(fvec4) FAdd 18 21 + 24: 16(ptr) AccessChain 13 23 + 25: 7(fvec4) Load 24 + 26: 7(fvec4) FAdd 22 25 + 28: 16(ptr) AccessChain 13 27 + 29: 7(fvec4) Load 28 + 30: 7(fvec4) FAdd 26 29 + 32: 16(ptr) AccessChain 13 31 + 33: 7(fvec4) Load 32 + 34: 7(fvec4) FAdd 30 33 + 36: 16(ptr) AccessChain 13 35 + 37: 7(fvec4) Load 36 + 38: 7(fvec4) FAdd 34 37 + ReturnValue 38 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/hlsl.includeNegative.vert.out b/3rdparty/glslang/Test/baseResults/hlsl.includeNegative.vert.out new file mode 100755 index 000000000..5faa383fe --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/hlsl.includeNegative.vert.out @@ -0,0 +1,10 @@ +hlsl.includeNegative.vert +ERROR: ./foo.h:1: '#error' : should not be included +ERROR: ./inc2/../foo.h:1: '#error' : should not be included +ERROR: ./parentBad:3: '#error' : bad parent +ERROR: hlsl.includeNegative.vert:7: '#error' : in main +hlsl.includeNegative.vert(8): error at column 0, HLSL parsing failed. +ERROR: 5 compilation errors. No code generated. + + +SPIR-V is not generated for failed compile or link diff --git a/3rdparty/glslang/Test/baseResults/include.vert.out b/3rdparty/glslang/Test/baseResults/include.vert.out new file mode 100644 index 000000000..c94ffcb08 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/include.vert.out @@ -0,0 +1,69 @@ +include.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + +Shader version: 450 +Requested GL_GOOGLE_cpp_style_line_directive +Requested GL_GOOGLE_include_directive +0:? Sequence +0:13 Function Definition: main( ( global void) +0:13 Function Parameters: +0:15 Sequence +0:15 move second child to first child ( temp 4-component vector of float) +0:15 'color' ( smooth out 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 'i1' ( global 4-component vector of float) +0:15 'i2' ( global 4-component vector of float) +0:15 'i3' ( global 4-component vector of float) +0:15 'i4' ( global 4-component vector of float) +0:15 'i5' ( global 4-component vector of float) +0:15 'i6' ( global 4-component vector of float) +0:? Linker Objects +0:? 'i1' ( global 4-component vector of float) +0:? 'i2' ( global 4-component vector of float) +0:? 'i4' ( global 4-component vector of float) +0:? 'i3' ( global 4-component vector of float) +0:? 'i6' ( global 4-component vector of float) +0:? 'i5' ( global 4-component vector of float) +0:? 'color' ( smooth out 4-component vector of float) +0:? 'gl_VertexID' ( gl_VertexId int VertexId) +0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId) + + +Linked vertex stage: + + +Shader version: 450 +Requested GL_GOOGLE_cpp_style_line_directive +Requested GL_GOOGLE_include_directive +0:? Sequence +0:13 Function Definition: main( ( global void) +0:13 Function Parameters: +0:15 Sequence +0:15 move second child to first child ( temp 4-component vector of float) +0:15 'color' ( smooth out 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 add ( temp 4-component vector of float) +0:15 'i1' ( global 4-component vector of float) +0:15 'i2' ( global 4-component vector of float) +0:15 'i3' ( global 4-component vector of float) +0:15 'i4' ( global 4-component vector of float) +0:15 'i5' ( global 4-component vector of float) +0:15 'i6' ( global 4-component vector of float) +0:? Linker Objects +0:? 'i1' ( global 4-component vector of float) +0:? 'i2' ( global 4-component vector of float) +0:? 'i4' ( global 4-component vector of float) +0:? 'i3' ( global 4-component vector of float) +0:? 'i6' ( global 4-component vector of float) +0:? 'i5' ( global 4-component vector of float) +0:? 'color' ( smooth out 4-component vector of float) +0:? 'gl_VertexID' ( gl_VertexId int VertexId) +0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId) + diff --git a/3rdparty/glslang/Test/baseResults/spv.debugInfo.frag.out b/3rdparty/glslang/Test/baseResults/spv.debugInfo.frag.out new file mode 100644 index 000000000..16f605bfa --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/spv.debugInfo.frag.out @@ -0,0 +1,272 @@ +spv.debugInfo.frag +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 126 + + Capability Shader + 2: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 5 "main" 24 52 + ExecutionMode 5 OriginUpperLeft + 1: String "spv.debugInfo.frag" + Source GLSL 450 1 "#version 450 + +struct S { + int a; +}; + +uniform ubuf { + S s; +}; + +uniform sampler2D s2d; + +layout(location = 0) in vec4 inv; +layout(location = 0) out vec4 outv; + +vec4 foo(S s) +{ + vec4 r = s.a * inv; + ++r; + if (r.x > 3.0) + --r; + else + r *= 2; + + return r; +} + +void main() +{ + outv = foo(s); + outv += texture(s2d, vec2(0.5)); + + switch (s.a) { + case 10: + ++outv; + break; + case 20: + outv = 2 * outv; + ++outv; + break; + default: + --outv; + break; + } + + for (int i = 0; i < 10; ++i) + outv *= 3.0; + + outv.x < 10.0 ? + outv = sin(outv) : + outv = cos(outv); +}" + Name 5 "main" + Name 8 "S" + MemberName 8(S) 0 "a" + Name 14 "foo(struct-S-i11;" + Name 13 "s" + Name 17 "r" + Name 24 "inv" + Name 52 "outv" + Name 53 "S" + MemberName 53(S) 0 "a" + Name 54 "ubuf" + MemberName 54(ubuf) 0 "s" + Name 56 "" + Name 57 "S" + MemberName 57(S) 0 "a" + Name 59 "param" + Name 69 "s2d" + Name 99 "i" + Decorate 24(inv) Location 0 + Decorate 52(outv) Location 0 + MemberDecorate 53(S) 0 Offset 0 + MemberDecorate 54(ubuf) 0 Offset 0 + Decorate 54(ubuf) Block + Decorate 56 DescriptorSet 0 + Decorate 69(s2d) DescriptorSet 0 + 3: TypeVoid + 4: TypeFunction 3 + 7: TypeInt 32 1 + 8(S): TypeStruct 7(int) + 9: TypePointer Function 8(S) + 10: TypeFloat 32 + 11: TypeVector 10(float) 4 + 12: TypeFunction 11(fvec4) 9(ptr) + 16: TypePointer Function 11(fvec4) + 18: 7(int) Constant 0 + 19: TypePointer Function 7(int) + 23: TypePointer Input 11(fvec4) + 24(inv): 23(ptr) Variable Input + 28: 10(float) Constant 1065353216 + 31: TypeInt 32 0 + 32: 31(int) Constant 0 + 33: TypePointer Function 10(float) + 36: 10(float) Constant 1077936128 + 37: TypeBool + 45: 10(float) Constant 1073741824 + 51: TypePointer Output 11(fvec4) + 52(outv): 51(ptr) Variable Output + 53(S): TypeStruct 7(int) + 54(ubuf): TypeStruct 53(S) + 55: TypePointer Uniform 54(ubuf) + 56: 55(ptr) Variable Uniform + 57(S): TypeStruct 7(int) + 58: TypePointer Function 57(S) + 60: TypePointer Uniform 53(S) + 66: TypeImage 10(float) 2D sampled format:Unknown + 67: TypeSampledImage 66 + 68: TypePointer UniformConstant 67 + 69(s2d): 68(ptr) Variable UniformConstant + 71: TypeVector 10(float) 2 + 72: 10(float) Constant 1056964608 + 73: 71(fvec2) ConstantComposite 72 72 + 77: TypePointer Uniform 7(int) + 106: 7(int) Constant 10 + 111: 7(int) Constant 1 + 114: TypePointer Output 10(float) + 117: 10(float) Constant 1092616192 + 5(main): 3 Function None 4 + 6: Label + 59(param): 58(ptr) Variable Function + 99(i): 19(ptr) Variable Function + 113: 16(ptr) Variable Function + Line 1 30 0 + 61: 60(ptr) AccessChain 56 18 + 62: 53(S) Load 61 + 63: 7(int) CompositeExtract 62 0 + 64: 19(ptr) AccessChain 59(param) 18 + Store 64 63 + 65: 11(fvec4) FunctionCall 14(foo(struct-S-i11;) 59(param) + Store 52(outv) 65 + Line 1 31 0 + 70: 67 Load 69(s2d) + 74: 11(fvec4) ImageSampleImplicitLod 70 73 + 75: 11(fvec4) Load 52(outv) + 76: 11(fvec4) FAdd 75 74 + Store 52(outv) 76 + Line 1 33 0 + 78: 77(ptr) AccessChain 56 18 18 + 79: 7(int) Load 78 + SelectionMerge 83 None + Switch 79 82 + case 10: 80 + case 20: 81 + 82: Label + Line 1 42 0 + 94: 11(fvec4) Load 52(outv) + 95: 11(fvec4) CompositeConstruct 28 28 28 28 + 96: 11(fvec4) FSub 94 95 + Store 52(outv) 96 + Line 1 43 0 + Branch 83 + 80: Label + Line 1 35 0 + 84: 11(fvec4) Load 52(outv) + 85: 11(fvec4) CompositeConstruct 28 28 28 28 + 86: 11(fvec4) FAdd 84 85 + Store 52(outv) 86 + Line 1 36 0 + Branch 83 + 81: Label + Line 1 38 0 + 88: 11(fvec4) Load 52(outv) + 89: 11(fvec4) VectorTimesScalar 88 45 + Store 52(outv) 89 + Line 1 39 0 + 90: 11(fvec4) Load 52(outv) + 91: 11(fvec4) CompositeConstruct 28 28 28 28 + 92: 11(fvec4) FAdd 90 91 + Store 52(outv) 92 + Line 1 40 0 + Branch 83 + 83: Label + Line 1 46 0 + Store 99(i) 18 + Branch 100 + 100: Label + LoopMerge 102 103 None + Branch 104 + 104: Label + 105: 7(int) Load 99(i) + 107: 37(bool) SLessThan 105 106 + BranchConditional 107 101 102 + 101: Label + Line 1 47 0 + 108: 11(fvec4) Load 52(outv) + 109: 11(fvec4) VectorTimesScalar 108 36 + Store 52(outv) 109 + Branch 103 + 103: Label + Line 1 46 0 + 110: 7(int) Load 99(i) + 112: 7(int) IAdd 110 111 + Store 99(i) 112 + Branch 100 + 102: Label + Line 1 49 0 + 115: 114(ptr) AccessChain 52(outv) 32 + 116: 10(float) Load 115 + 118: 37(bool) FOrdLessThan 116 117 + SelectionMerge 120 None + BranchConditional 118 119 123 + 119: Label + Line 1 50 0 + 121: 11(fvec4) Load 52(outv) + 122: 11(fvec4) ExtInst 2(GLSL.std.450) 13(Sin) 121 + Store 52(outv) 122 + Store 113 122 + Branch 120 + 123: Label + Line 1 51 0 + 124: 11(fvec4) Load 52(outv) + 125: 11(fvec4) ExtInst 2(GLSL.std.450) 14(Cos) 124 + Store 52(outv) 125 + Store 113 125 + Branch 120 + 120: Label + Return + FunctionEnd +14(foo(struct-S-i11;): 11(fvec4) Function None 12 + 13(s): 9(ptr) FunctionParameter + 15: Label + 17(r): 16(ptr) Variable Function + Line 1 18 0 + 20: 19(ptr) AccessChain 13(s) 18 + 21: 7(int) Load 20 + 22: 10(float) ConvertSToF 21 + 25: 11(fvec4) Load 24(inv) + 26: 11(fvec4) VectorTimesScalar 25 22 + Store 17(r) 26 + Line 1 19 0 + 27: 11(fvec4) Load 17(r) + 29: 11(fvec4) CompositeConstruct 28 28 28 28 + 30: 11(fvec4) FAdd 27 29 + Store 17(r) 30 + Line 1 20 0 + 34: 33(ptr) AccessChain 17(r) 32 + 35: 10(float) Load 34 + 38: 37(bool) FOrdGreaterThan 35 36 + SelectionMerge 40 None + BranchConditional 38 39 44 + 39: Label + Line 1 21 0 + 41: 11(fvec4) Load 17(r) + 42: 11(fvec4) CompositeConstruct 28 28 28 28 + 43: 11(fvec4) FSub 41 42 + Store 17(r) 43 + Branch 40 + 44: Label + Line 1 23 0 + 46: 11(fvec4) Load 17(r) + 47: 11(fvec4) VectorTimesScalar 46 45 + Store 17(r) 47 + Branch 40 + 40: Label + Line 1 25 0 + 48: 11(fvec4) Load 17(r) + ReturnValue 48 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/spv.ssboAlias.frag.out b/3rdparty/glslang/Test/baseResults/spv.ssboAlias.frag.out new file mode 100755 index 000000000..22915d736 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/spv.ssboAlias.frag.out @@ -0,0 +1,88 @@ +spv.ssboAlias.frag +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 46 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 43 + ExecutionMode 4 OriginUpperLeft + Source HLSL 500 + Name 4 "main" + Name 9 "@main(" + Name 13 "Buf1" + MemberName 13(Buf1) 0 "@data" + Name 15 "Buf1" + Name 18 "Buf1@count" + MemberName 18(Buf1@count) 0 "@count" + Name 20 "Buf1@count" + Name 30 "Buf2" + Name 31 "Buf2@count" + Name 43 "@entryPointOutput" + Name 45 "Buf3" + Decorate 12 ArrayStride 4 + MemberDecorate 13(Buf1) 0 Offset 0 + Decorate 13(Buf1) BufferBlock + Decorate 15(Buf1) DescriptorSet 0 + Decorate 15(Buf1) Binding 84 + MemberDecorate 18(Buf1@count) 0 Offset 0 + Decorate 18(Buf1@count) BufferBlock + Decorate 20(Buf1@count) DescriptorSet 0 + Decorate 20(Buf1@count) Binding 83 + Decorate 30(Buf2) DescriptorSet 0 + Decorate 30(Buf2) Binding 85 + Decorate 31(Buf2@count) DescriptorSet 0 + Decorate 31(Buf2@count) Binding 86 + Decorate 43(@entryPointOutput) Location 0 + Decorate 45(Buf3) DescriptorSet 0 + Decorate 45(Buf3) Binding 84 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11: TypeInt 32 0 + 12: TypeRuntimeArray 11(int) + 13(Buf1): TypeStruct 12 + 14: TypePointer Uniform 13(Buf1) + 15(Buf1): 14(ptr) Variable Uniform + 16: TypeInt 32 1 + 17: 16(int) Constant 0 + 18(Buf1@count): TypeStruct 16(int) + 19: TypePointer Uniform 18(Buf1@count) + 20(Buf1@count): 19(ptr) Variable Uniform + 21: TypePointer Uniform 16(int) + 23: 16(int) Constant 1 + 24: 11(int) Constant 1 + 25: 11(int) Constant 0 + 27: 11(int) Constant 10 + 28: TypePointer Uniform 11(int) + 30(Buf2): 14(ptr) Variable Uniform + 31(Buf2@count): 19(ptr) Variable Uniform + 34: 11(int) Constant 20 + 36: 6(float) Constant 1065353216 + 37: 6(float) Constant 1077936128 + 38: 6(float) Constant 1084227584 + 39: 7(fvec4) ConstantComposite 36 37 38 36 + 42: TypePointer Output 7(fvec4) +43(@entryPointOutput): 42(ptr) Variable Output + 45(Buf3): 14(ptr) Variable Uniform + 4(main): 2 Function None 3 + 5: Label + 44: 7(fvec4) FunctionCall 9(@main() + Store 43(@entryPointOutput) 44 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label + 22: 21(ptr) AccessChain 20(Buf1@count) 17 + 26: 11(int) AtomicIAdd 22 24 25 23 + 29: 28(ptr) AccessChain 15(Buf1) 17 26 + Store 29 27 + 32: 21(ptr) AccessChain 31(Buf2@count) 17 + 33: 11(int) AtomicIAdd 32 24 25 23 + 35: 28(ptr) AccessChain 30(Buf2) 17 33 + Store 35 34 + ReturnValue 39 + FunctionEnd diff --git a/3rdparty/glslang/Test/baseResults/spv.texture.sampler.transform.frag.out b/3rdparty/glslang/Test/baseResults/spv.texture.sampler.transform.frag.out new file mode 100644 index 000000000..198c48196 --- /dev/null +++ b/3rdparty/glslang/Test/baseResults/spv.texture.sampler.transform.frag.out @@ -0,0 +1,38 @@ +spv.texture.sampler.transform.frag +Warning, version 440 is not yet complete; most version-specific features are present, but some are missing. + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 19 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 9 16 + ExecutionMode 4 OriginUpperLeft + Source GLSL 440 + Name 4 "main" + Name 9 "color" + Name 12 "tex" + Name 16 "coord" + Decorate 12(tex) DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypePointer Output 7(fvec4) + 9(color): 8(ptr) Variable Output + 10: TypeImage 6(float) 2D sampled format:Unknown + 11: TypePointer UniformConstant 10 + 12(tex): 11(ptr) Variable UniformConstant + 14: TypeVector 6(float) 2 + 15: TypePointer Input 14(fvec2) + 16(coord): 15(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + 13: 10 Load 12(tex) + 17: 14(fvec2) Load 16(coord) + 18: 7(fvec4) ImageSampleImplicitLod 13 17 + Store 9(color) 18 + Return + FunctionEnd diff --git a/3rdparty/glslang/Test/foo.h b/3rdparty/glslang/Test/foo.h new file mode 100644 index 000000000..7f79340b6 --- /dev/null +++ b/3rdparty/glslang/Test/foo.h @@ -0,0 +1 @@ +#error should not be included \ No newline at end of file diff --git a/3rdparty/glslang/Test/hlsl.aliasOpaque.frag b/3rdparty/glslang/Test/hlsl.aliasOpaque.frag new file mode 100644 index 000000000..8b1cceff9 --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.aliasOpaque.frag @@ -0,0 +1,29 @@ +struct OS { + SamplerState ss; + float a; + Texture2D tex; +}; + +SamplerState gss; +SamplerState gss2; +Texture2D gtex; + +float4 osCall(OS s) +{ + return s.a * s.tex.Sample(s.ss, float2(0.2, 0.3)); +} + +float4 main() : SV_TARGET0 +{ + OS os; + os.ss = gss2; + os.ss = gss; + os.tex = gtex; + os.a = 3.0; + + // this should give an error + //SamplerState localss; + //localss = gss2; + + return osCall(os); +} diff --git a/3rdparty/glslang/Test/hlsl.flattenOpaque.frag b/3rdparty/glslang/Test/hlsl.flattenOpaque.frag new file mode 100644 index 000000000..279be8a0b --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.flattenOpaque.frag @@ -0,0 +1,40 @@ +struct os { + sampler2D s2D; +}; + +struct os2 { + sampler2D s2D; + Texture2D tex; +}; + +Texture2D tex; +os s; +os2 s2; + +float4 osCall1(os s) +{ + return tex.Sample(s.s2D, float2(0.2, 0.3)); +} + +float4 osCall2(os s, float2 f2) +{ + return tex.Sample(s.s2D, f2); +} + +float4 os2Call1(os2 s) +{ + return s.tex.Sample(s.s2D, float2(0.2, 0.3)); +} + +float4 os2Call2(os2 s, float2 f2) +{ + return s.tex.Sample(s.s2D, f2); +} + +float4 main() : SV_TARGET0 +{ + return osCall1(s) + + osCall2(s, float2(0.2, 0.3)) + + os2Call1(s2) + + os2Call2(s2, float2(0.2, 0.3)); +} diff --git a/3rdparty/glslang/Test/hlsl.include.vert b/3rdparty/glslang/Test/hlsl.include.vert new file mode 100644 index 000000000..683398e52 --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.include.vert @@ -0,0 +1,8 @@ +#include "bar.h" +#include "./inc1/bar.h" +#include "inc2\bar.h" + +float4 main() : SV_Position +{ + return i1 + i2 + i3 + i4 + i5 + i6; +} diff --git a/3rdparty/glslang/Test/hlsl.includeNegative.vert b/3rdparty/glslang/Test/hlsl.includeNegative.vert new file mode 100644 index 000000000..64d31fab9 --- /dev/null +++ b/3rdparty/glslang/Test/hlsl.includeNegative.vert @@ -0,0 +1,8 @@ +#include "foo.h" +#include "inc2/../foo.h" +#include "inc1/badInc.h" + +float4 main() : SV_Position +{ +#error in main +} diff --git a/3rdparty/glslang/Test/inc1/badInc.h b/3rdparty/glslang/Test/inc1/badInc.h new file mode 100644 index 000000000..a77135538 --- /dev/null +++ b/3rdparty/glslang/Test/inc1/badInc.h @@ -0,0 +1 @@ +#include "parentBad" diff --git a/3rdparty/glslang/Test/inc1/bar.h b/3rdparty/glslang/Test/inc1/bar.h new file mode 100644 index 000000000..1a650fb6a --- /dev/null +++ b/3rdparty/glslang/Test/inc1/bar.h @@ -0,0 +1,3 @@ +float4 i2; + +#include "foo.h" diff --git a/3rdparty/glslang/Test/inc1/foo.h b/3rdparty/glslang/Test/inc1/foo.h new file mode 100644 index 000000000..1819034d5 --- /dev/null +++ b/3rdparty/glslang/Test/inc1/foo.h @@ -0,0 +1,3 @@ +#include "parent.h" + +float4 i3; diff --git a/3rdparty/glslang/Test/inc2/bar.h b/3rdparty/glslang/Test/inc2/bar.h new file mode 100644 index 000000000..901c058e7 --- /dev/null +++ b/3rdparty/glslang/Test/inc2/bar.h @@ -0,0 +1,2 @@ +#include "foo.h" +float4 i5; diff --git a/3rdparty/glslang/Test/inc2/foo.h b/3rdparty/glslang/Test/inc2/foo.h new file mode 100644 index 000000000..fd09e808c --- /dev/null +++ b/3rdparty/glslang/Test/inc2/foo.h @@ -0,0 +1 @@ +float4 i6; \ No newline at end of file diff --git a/3rdparty/glslang/Test/include.vert b/3rdparty/glslang/Test/include.vert new file mode 100644 index 000000000..192a4891a --- /dev/null +++ b/3rdparty/glslang/Test/include.vert @@ -0,0 +1,16 @@ +#version 450 + +#extension GL_GOOGLE_include_directive : enable + +#define float4 vec4 + +#include "bar.h" +#include "./inc1/bar.h" +#include "inc2\bar.h" + +out vec4 color; + +void main() +{ + color = i1 + i2 + i3 + i4 + i5 + i6; +} diff --git a/3rdparty/glslang/Test/parent.h b/3rdparty/glslang/Test/parent.h new file mode 100644 index 000000000..9ef68e0b8 --- /dev/null +++ b/3rdparty/glslang/Test/parent.h @@ -0,0 +1 @@ +float4 i4; diff --git a/3rdparty/glslang/Test/parentBad b/3rdparty/glslang/Test/parentBad new file mode 100644 index 000000000..e54c10d05 --- /dev/null +++ b/3rdparty/glslang/Test/parentBad @@ -0,0 +1,3 @@ +int a; + +#error bad parent diff --git a/3rdparty/glslang/Test/runtests b/3rdparty/glslang/Test/runtests index a3c89e045..c3a049b14 100755 --- a/3rdparty/glslang/Test/runtests +++ b/3rdparty/glslang/Test/runtests @@ -90,14 +90,32 @@ diff -b $BASEDIR/hlsl.hlslOffset.vert.out $TARGETDIR/hlsl.hlslOffset.vert.out || # echo Configuring HLSL descriptor set and binding number manually $EXE -V -D -e main -H hlsl.multiDescriptorSet.frag --rsb frag t0 0 0 t1 1 0 s0 0 1 s1 1 1 b0 2 0 b1 2 1 b2 2 2 > $TARGETDIR/hlsl.multiDescriptorSet.frag.out -diff -b $BASEDIR/hlsl.multiDescriptorSet.frag.out $TARGETDIR/hlsl.multiDescriptorSet.frag.out +diff -b $BASEDIR/hlsl.multiDescriptorSet.frag.out $TARGETDIR/hlsl.multiDescriptorSet.frag.out || HASERROR=1 # # Testing location error # echo Testing SPV no location $EXE -V -C spv.noLocation.vert > $TARGETDIR/spv.noLocation.vert.out -diff -b $BASEDIR/spv.noLocation.vert.out $TARGETDIR/spv.noLocation.vert.out +diff -b $BASEDIR/spv.noLocation.vert.out $TARGETDIR/spv.noLocation.vert.out || HASERROR=1 + +# +# Testing debug information +# +echo Testing SPV Debug Information +$EXE -g -H spv.debugInfo.frag > $TARGETDIR/spv.debugInfo.frag.out +diff -b $BASEDIR/spv.debugInfo.frag.out $TARGETDIR/spv.debugInfo.frag.out || HASERROR=1 + +# +# Testing Includer +# +echo Testing Includer +$EXE -D -e main -H ../Test/hlsl.include.vert > $TARGETDIR/hlsl.include.vert.out +diff -b $BASEDIR/hlsl.include.vert.out $TARGETDIR/hlsl.include.vert.out || HASERROR=1 +$EXE -D -e main -H hlsl.includeNegative.vert > $TARGETDIR/hlsl.includeNegative.vert.out +diff -b $BASEDIR/hlsl.includeNegative.vert.out $TARGETDIR/hlsl.includeNegative.vert.out || HASERROR=1 +$EXE -l -i include.vert > $TARGETDIR/include.vert.out +diff -b $BASEDIR/include.vert.out $TARGETDIR/include.vert.out || HASERROR=1 # # Final checking diff --git a/3rdparty/glslang/Test/spv.debugInfo.frag b/3rdparty/glslang/Test/spv.debugInfo.frag new file mode 100644 index 000000000..3b6cd27fe --- /dev/null +++ b/3rdparty/glslang/Test/spv.debugInfo.frag @@ -0,0 +1,52 @@ +#version 450 + +struct S { + int a; +}; + +uniform ubuf { + S s; +}; + +uniform sampler2D s2d; + +layout(location = 0) in vec4 inv; +layout(location = 0) out vec4 outv; + +vec4 foo(S s) +{ + vec4 r = s.a * inv; + ++r; + if (r.x > 3.0) + --r; + else + r *= 2; + + return r; +} + +void main() +{ + outv = foo(s); + outv += texture(s2d, vec2(0.5)); + + switch (s.a) { + case 10: + ++outv; + break; + case 20: + outv = 2 * outv; + ++outv; + break; + default: + --outv; + break; + } + + for (int i = 0; i < 10; ++i) + outv *= 3.0; + + outv.x < 10.0 ? + outv = sin(outv) : + outv = cos(outv); +} \ No newline at end of file diff --git a/3rdparty/glslang/Test/spv.ssboAlias.frag b/3rdparty/glslang/Test/spv.ssboAlias.frag new file mode 100644 index 000000000..ed3d3e793 --- /dev/null +++ b/3rdparty/glslang/Test/spv.ssboAlias.frag @@ -0,0 +1,10 @@ +AppendStructuredBuffer Buf1 : register(u1); +AppendStructuredBuffer Buf2 : register(u2); +AppendStructuredBuffer Buf3 : register(u1); + +float4 main() : SV_Target +{ + Buf1.Append(10u); + Buf2.Append(20u); + return float4(1.0, 3.0, 5.0, 1.0); +} \ No newline at end of file diff --git a/3rdparty/glslang/Test/spv.texture.sampler.transform.frag b/3rdparty/glslang/Test/spv.texture.sampler.transform.frag new file mode 100644 index 000000000..872d9b04d --- /dev/null +++ b/3rdparty/glslang/Test/spv.texture.sampler.transform.frag @@ -0,0 +1,13 @@ +#version 440 + +uniform sampler smp; +uniform texture2D tex; + +in vec2 coord; + +out vec4 color; + +void main() +{ + color = texture(sampler2D(tex, smp), coord); +} diff --git a/3rdparty/glslang/glslang/Include/Types.h b/3rdparty/glslang/glslang/Include/Types.h index 6bcbe4088..5eac73e0d 100644 --- a/3rdparty/glslang/glslang/Include/Types.h +++ b/3rdparty/glslang/glslang/Include/Types.h @@ -1310,6 +1310,7 @@ public: virtual TBasicType getBasicType() const { return basicType; } virtual const TSampler& getSampler() const { return sampler; } + virtual TSampler& getSampler() { return sampler; } virtual TQualifier& getQualifier() { return qualifier; } virtual const TQualifier& getQualifier() const { return qualifier; } diff --git a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp b/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp index 663e30c66..ad9720c09 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp @@ -1776,6 +1776,14 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/) // Propagate 'noContraction' label in backward from 'precise' variables. glslang::PropagateNoContraction(*this); + switch (textureSamplerTransformMode) { + case EShTexSampTransKeep: + break; + case EShTexSampTransUpgradeTextureRemoveSampler: + performTextureUpgradeAndSamplerRemovalTransformation(root); + break; + } + return true; } @@ -2943,4 +2951,41 @@ bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TInt (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant()); } +struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser { + bool visitAggregate(TVisit, TIntermAggregate* ag) override { + using namespace std; + TIntermSequence& seq = ag->getSequence(); + // remove pure sampler variables + TIntermSequence::iterator newEnd = remove_if(seq.begin(), seq.end(), [](TIntermNode* node) { + TIntermSymbol* symbol = node->getAsSymbolNode(); + if (!symbol) + return false; + + return (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()); + }); + seq.erase(newEnd, seq.end()); + // replace constructors with sampler/textures + // update textures into sampled textures + for_each(seq.begin(), seq.end(), [](TIntermNode*& node) { + TIntermSymbol* symbol = node->getAsSymbolNode(); + if (!symbol) { + TIntermAggregate *constructor = node->getAsAggregate(); + if (constructor && constructor->getOp() == EOpConstructTextureSampler) { + if (!constructor->getSequence().empty()) + node = constructor->getSequence()[0]; + } + } else if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) { + symbol->getWritableType().getSampler().combined = true; + } + }); + return true; + } +}; + +void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root) +{ + TextureUpgradeAndSamplerRemovalTransform transform; + root->traverse(&transform); +} + } // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp index af6eef8aa..91b14adff 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp @@ -2102,6 +2102,17 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T case EOpConstructDMat4x2: case EOpConstructDMat4x3: case EOpConstructDMat4x4: +#ifdef AMD_EXTENSIONS + case EOpConstructF16Mat2x2: + case EOpConstructF16Mat2x3: + case EOpConstructF16Mat2x4: + case EOpConstructF16Mat3x2: + case EOpConstructF16Mat3x3: + case EOpConstructF16Mat3x4: + case EOpConstructF16Mat4x2: + case EOpConstructF16Mat4x3: + case EOpConstructF16Mat4x4: +#endif constructingMatrix = true; break; default: diff --git a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp b/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp index 1f7c005f3..b7485ec19 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp @@ -728,6 +728,11 @@ bool ProcessDeferred( intermediate.setOriginUpperLeft(); if ((messages & EShMsgHlslOffsets) || (messages & EShMsgReadHlsl)) intermediate.setHlslOffsets(); + if (messages & EShMsgDebugInfo) { + intermediate.setSourceFile(names[numPre]); + for (int s = 0; s < numStrings; ++s) + intermediate.addSourceText(strings[numPre]); + } SetupBuiltinSymbolTable(version, profile, spvVersion, source); TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)] @@ -1578,6 +1583,7 @@ void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslI void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } void TShader::setResourceSetBinding(const std::vector& base) { intermediate->setResourceSetBinding(base); } +void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); } // // Turn the shader strings into a parse tree in the TIntermediate. @@ -1601,11 +1607,6 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion forwardCompatible, messages, *intermediate, includer, sourceEntryPointName); } -bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) -{ - return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); -} - // Fill in a string with the result of preprocessing ShaderStrings // Returns true if all extensions, pragmas and version strings were valid. bool TShader::preprocess(const TBuiltInResource* builtInResources, diff --git a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp index 26772ddc4..e5991ffb1 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp @@ -374,7 +374,12 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver int reserveSlot(int set, int slot) { TSlotSet::iterator at = findSlot(set, slot); - slots[set].insert(at, slot); + + // tolerate aliasing, by not double-recording aliases + // (policy about appropriateness of the alias is higher up) + if (at == slots[set].end() || *at != slot) + slots[set].insert(at, slot); + return slot; } @@ -468,24 +473,6 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase { bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override { - if (type.getQualifier().hasBinding()) { - const int set = getLayoutSet(type); - - if (isImageType(type)) - return checkEmpty(set, baseImageBinding + type.getQualifier().layoutBinding); - - if (isTextureType(type)) - return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding); - - if (isSsboType(type)) - return checkEmpty(set, baseSsboBinding + type.getQualifier().layoutBinding); - - if (isSamplerType(type)) - return checkEmpty(set, baseSamplerBinding + type.getQualifier().layoutBinding); - - if (isUboType(type)) - return checkEmpty(set, baseUboBinding + type.getQualifier().layoutBinding); - } return true; } @@ -496,7 +483,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase if (type.getQualifier().hasBinding()) { if (isImageType(type)) return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding); - + if (isTextureType(type)) return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding); @@ -588,21 +575,6 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase { bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override { - if (type.getQualifier().hasBinding()) { - const int set = getLayoutSet(type); - - if (isUavType(type)) - return checkEmpty(set, baseUavBinding + type.getQualifier().layoutBinding); - - if (isSrvType(type)) - return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding); - - if (isSamplerType(type)) - return checkEmpty(set, baseSamplerBinding + type.getQualifier().layoutBinding); - - if (isUboType(type)) - return checkEmpty(set, baseUboBinding + type.getQualifier().layoutBinding); - } return true; } diff --git a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h index 444d341d5..56319dc69 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h +++ b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h @@ -182,7 +182,8 @@ public: useUnknownFormat(false), hlslOffsets(false), useStorageBuffer(false), - hlslIoMapping(false) + hlslIoMapping(false), + textureSamplerTransformMode(EShTexSampTransKeep) { localSize[0] = 1; localSize[1] = 1; @@ -233,6 +234,7 @@ public: bool usingStorageBuffer() const { return useStorageBuffer; } void setHlslIoMapping(bool b) { hlslIoMapping = b; } bool usingHlslIoMapping() { return hlslIoMapping; } + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } void setVersion(int v) { version = v; } int getVersion() const { return version; } @@ -449,6 +451,11 @@ public: return semanticNameSet.insert(name).first->c_str(); } + void setSourceFile(const char* file) { sourceFile = file; } + const std::string& getSourceFile() const { return sourceFile; } + void addSourceText(const char* text) { sourceText = sourceText + text; } + const std::string& getSourceText() const { return sourceText; } + const char* const implicitThisName = "@this"; protected: @@ -472,6 +479,7 @@ protected: void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); + void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); const EShLanguage language; // stage, known at construction time EShSource source; // source language, known a bit later @@ -536,6 +544,12 @@ protected: std::unordered_set usedConstantId; // specialization constant ids used std::set semanticNameSet; + EShTextureSamplerTransformMode textureSamplerTransformMode; + + // source code of shader, useful as part of debug information + std::string sourceFile; + std::string sourceText; + private: void operator=(TIntermediate&); // prevent assignments }; diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp index 293ada6ce..da432bd54 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -613,14 +613,14 @@ int TPpContext::CPPinclude(TPpToken* ppToken) TShader::Includer::IncludeResult* res = nullptr; if (startWithLocalSearch) res = includer.includeLocal(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); - if (! res || res->headerName.empty()) { + if (res == nullptr || res->headerName.empty()) { includer.releaseInclude(res); res = includer.includeSystem(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); } // Process the results - if (res && !res->headerName.empty()) { - if (res->headerData && res->headerLength) { + if (res != nullptr && !res->headerName.empty()) { + if (res->headerData != nullptr && res->headerLength > 0) { // path for processing one or more tokens from an included header, hand off 'res' const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); std::ostringstream prologue; @@ -638,8 +638,8 @@ int TPpContext::CPPinclude(TPpToken* ppToken) } else { // error path, clean up std::string message = - res ? std::string(res->headerData, res->headerLength) - : std::string("Could not process include directive"); + res != nullptr ? std::string(res->headerData, res->headerLength) + : std::string("Could not process include directive"); parseContext.ppError(directiveLoc, message.c_str(), "#include", "for header name: %s", filename.c_str()); includer.releaseInclude(res); } diff --git a/3rdparty/glslang/glslang/Public/ShaderLang.h b/3rdparty/glslang/glslang/Public/ShaderLang.h index 3be66d43e..b2a4deacd 100644 --- a/3rdparty/glslang/glslang/Public/ShaderLang.h +++ b/3rdparty/glslang/glslang/Public/ShaderLang.h @@ -134,6 +134,14 @@ typedef enum { EShOptFull, // Optimizations that will take more time } EShOptimizationLevel; +// +// Texture and Sampler transformation mode. +// +typedef enum { + EShTexSampTransKeep, // keep textures and samplers as is (default) + EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers +} EShTextureSamplerTransformMode; + // // Message choices for what errors and warnings are given. // @@ -149,6 +157,7 @@ enum EShMessages { EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules + EShMsgDebugInfo = (1 << 10), // save debug information }; // @@ -313,6 +322,7 @@ public: void setHlslIoMapping(bool hlslIoMap); void setFlattenUniformArrays(bool flatten); void setNoStorageFormat(bool useUnknownFormat); + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); // Interface to #include handlers. // @@ -397,6 +407,9 @@ public: virtual void releaseInclude(IncludeResult*) override { } }; + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages, Includer&); + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages messages) { @@ -404,12 +417,18 @@ public: return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); } - bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages, Includer&); - // Equivalent to parse() without a default profile and without forcing defaults. - // Provided for backwards compatibility. - bool parse(const TBuiltInResource*, int defaultVersion, bool forwardCompatible, EShMessages); + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); + } + + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, + Includer& includer) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); + } + bool preprocess(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages message, std::string* outputString, diff --git a/3rdparty/glslang/gtests/Hlsl.FromFile.cpp b/3rdparty/glslang/gtests/Hlsl.FromFile.cpp index 87c830251..9edc51af7 100644 --- a/3rdparty/glslang/gtests/Hlsl.FromFile.cpp +++ b/3rdparty/glslang/gtests/Hlsl.FromFile.cpp @@ -81,6 +81,7 @@ INSTANTIATE_TEST_CASE_P( ToSpirv, HlslCompileTest, ::testing::ValuesIn(std::vector{ {"hlsl.amend.frag", "f1"}, + {"hlsl.aliasOpaque.frag", "main"}, {"hlsl.array.frag", "PixelShaderFunction"}, {"hlsl.array.implicit-size.frag", "PixelShaderFunction"}, {"hlsl.array.multidim.frag", "main"}, @@ -114,6 +115,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.float1.frag", "PixelShaderFunction"}, {"hlsl.float4.frag", "PixelShaderFunction"}, {"hlsl.flatten.return.frag", "main"}, + {"hlsl.flattenOpaque.frag", "main"}, {"hlsl.forLoop.frag", "PixelShaderFunction"}, {"hlsl.gather.array.dx10.frag", "main"}, {"hlsl.gather.basic.dx10.frag", "main"}, diff --git a/3rdparty/glslang/gtests/Spv.FromFile.cpp b/3rdparty/glslang/gtests/Spv.FromFile.cpp index fd9c585c7..1552b9523 100644 --- a/3rdparty/glslang/gtests/Spv.FromFile.cpp +++ b/3rdparty/glslang/gtests/Spv.FromFile.cpp @@ -75,6 +75,7 @@ using CompileVulkanToSpirvTestAMD = GlslangTest<::testing::TestWithParam>; #endif +using CompileUpgradeTextureToSampledTextureAndDropSamplersTest = GlslangTest<::testing::TestWithParam>; // Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully // generate SPIR-V. @@ -172,6 +173,15 @@ TEST_P(CompileVulkanToSpirvTestNV, FromFile) } #endif +TEST_P(CompileUpgradeTextureToSampledTextureAndDropSamplersTest, FromFile) +{ + loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(GlobalTestSettings.testRoot, + GetParam(), + Source::GLSL, + Semantics::Vulkan, + Target::Spv); +} + // clang-format off INSTANTIATE_TEST_CASE_P( Glsl, CompileVulkanToSpirvTest, @@ -320,6 +330,7 @@ INSTANTIATE_TEST_CASE_P( { "spv.register.autoassign-2.frag", "main", 5, 10, 0, 15, 30, true, true }, { "spv.buffer.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true }, { "spv.ssbo.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true }, + { "spv.ssboAlias.frag", "main", 0, 0, 0, 0, 83, true, false }, { "spv.rw.autoassign.frag", "main", 5, 10, 20, 15, 30, true, true }, { "spv.register.autoassign.rangetest.frag", "main", glslang::TQualifier::layoutBindingEnd-2, @@ -407,6 +418,14 @@ INSTANTIATE_TEST_CASE_P( FileNameAsCustomTestSuffix ); #endif + +INSTANTIATE_TEST_CASE_P( + Glsl, CompileUpgradeTextureToSampledTextureAndDropSamplersTest, + ::testing::ValuesIn(std::vector({ + "spv.texture.sampler.transform.frag", + })), + FileNameAsCustomTestSuffix +); // clang-format on } // anonymous namespace diff --git a/3rdparty/glslang/gtests/TestFixture.h b/3rdparty/glslang/gtests/TestFixture.h index c00645bed..a503b5fb2 100644 --- a/3rdparty/glslang/gtests/TestFixture.h +++ b/3rdparty/glslang/gtests/TestFixture.h @@ -197,12 +197,14 @@ public: GlslangResult compileAndLink( const std::string shaderName, const std::string& code, const std::string& entryPointName, EShMessages controls, - bool flattenUniformArrays = false) + bool flattenUniformArrays = false, + EShTextureSamplerTransformMode texSampTransMode = EShTexSampTransKeep) { const EShLanguage kind = GetShaderStage(GetSuffix(shaderName)); glslang::TShader shader(kind); shader.setAutoMapLocations(true); + shader.setTextureSamplerTransformMode(texSampTransMode); shader.setFlattenUniformArrays(flattenUniformArrays); bool success = compile(&shader, code, entryPointName, controls); @@ -570,6 +572,31 @@ public: expectedErrorFname); } + void loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(const std::string& testDir, + const std::string& testName, + Source source, + Semantics semantics, + Target target, + const std::string& entryPointName = "") + { + const std::string inputFname = testDir + "/" + testName; + const std::string expectedOutputFname = testDir + "/baseResults/" + testName + ".out"; + std::string input, expectedOutput; + + tryLoadFile(inputFname, "input", &input); + tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); + + const EShMessages controls = DeriveOptions(source, semantics, target); + GlslangResult result = compileAndLink(testName, input, entryPointName, controls, false, EShTexSampTransUpgradeTextureRemoveSampler); + + // Generate the hybrid output in the way of glslangValidator. + std::ostringstream stream; + outputResultToStream(&stream, result, controls); + + checkEqAndUpdateIfRequested(expectedOutput, stream.str(), + expectedOutputFname); + } + private: const int defaultVersion; const EProfile defaultProfile; diff --git a/3rdparty/glslang/hlsl/hlslParseHelper.cpp b/3rdparty/glslang/hlsl/hlslParseHelper.cpp index a105b84dc..ff0c7771e 100755 --- a/3rdparty/glslang/hlsl/hlslParseHelper.cpp +++ b/3rdparty/glslang/hlsl/hlslParseHelper.cpp @@ -147,7 +147,7 @@ bool HlslParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& // bool HlslParseContext::shouldConvertLValue(const TIntermNode* node) const { - if (node == nullptr) + if (node == nullptr || node->getAsTyped() == nullptr) return false; const TIntermAggregate* lhsAsAggregate = node->getAsAggregate(); @@ -157,10 +157,14 @@ bool HlslParseContext::shouldConvertLValue(const TIntermNode* node) const if (lhsAsBinary != nullptr && (lhsAsBinary->getOp() == EOpVectorSwizzle || lhsAsBinary->getOp() == EOpIndexDirect)) lhsAsAggregate = lhsAsBinary->getLeft()->getAsAggregate(); - if (lhsAsAggregate != nullptr && lhsAsAggregate->getOp() == EOpImageLoad) return true; + // If it's a syntactic write to a sampler, we will use that to establish + // a compile-time alias. + if (node->getAsTyped()->getBasicType() == EbtSampler) + return true; + return false; } @@ -233,7 +237,7 @@ bool HlslParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, T // // Most things are passed through unmodified, except for error checking. // -TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char* op, TIntermTyped* node) +TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char* op, TIntermTyped*& node) { if (node == nullptr) return nullptr; @@ -256,6 +260,10 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char* // *** If we get here, we're going to apply some conversion to an l-value. + // Spin off sampler aliasing + if (node->getAsTyped()->getBasicType() == EbtSampler) + return handleSamplerLvalue(loc, op, node); + // Helper to create a load. const auto makeLoad = [&](TIntermSymbol* rhsTmp, TIntermTyped* object, TIntermTyped* coord, const TType& derefType) { TIntermAggregate* loadOp = new TIntermAggregate(EOpImageLoad); @@ -500,6 +508,42 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char* return node; } +// Deal with sampler aliasing: turning assignments into aliases +TIntermTyped* HlslParseContext::handleSamplerLvalue(const TSourceLoc& loc, const char* op, TIntermTyped*& node) +{ + // Can only alias an assignment: "s1 = s2" + TIntermBinary* binary = node->getAsBinaryNode(); + if (binary == nullptr || node->getAsOperator()->getOp() != EOpAssign || + binary->getLeft() ->getAsSymbolNode() == nullptr || + binary->getRight()->getAsSymbolNode() == nullptr) { + error(loc, "can't modify sampler", op, ""); + return node; + } + + // Best is if we are aliasing a flattened struct member "S.s1 = s2", + // in which case we want to update the flattening information with the alias, + // making everything else work seamlessly. + TIntermSymbol* left = binary->getLeft()->getAsSymbolNode(); + TIntermSymbol* right = binary->getRight()->getAsSymbolNode(); + for (auto fit = flattenMap.begin(); fit != flattenMap.end(); ++fit) { + for (auto mit = fit->second.members.begin(); mit != fit->second.members.end(); ++mit) { + if ((*mit)->getUniqueId() == left->getId()) { + // found it: update with alias to the existing variable, and don't emit any code + (*mit) = new TVariable(&right->getName(), right->getType()); + (*mit)->setUniqueId(right->getId()); + // replace node (rest of compiler expects either an error or code to generate) + // with pointless access + node = binary->getRight(); + return node; + } + } + } + + warn(loc, "could not create alias for sampler", op, ""); + + return node; +} + void HlslParseContext::handlePragma(const TSourceLoc& loc, const TVector& tokens) { if (pragmaCallback) @@ -774,7 +818,7 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc, else { // at least one of base and index is variable... - if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlattenUniform(base->getType()))) { + if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlatten(base->getType()))) { if (index->getQualifier().storage != EvqConst) error(loc, "Invalid variable index to flattened array", base->getAsSymbolNode()->getName().c_str(), ""); @@ -981,7 +1025,7 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt } } if (fieldFound) { - if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlattenUniform(base->getType()))) { + if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlatten(base->getType()))) { result = flattenAccess(base, member); } else { // Update the base and member to access if this was a split structure. @@ -1115,14 +1159,13 @@ TType& HlslParseContext::split(TType& type, TString name, const TType* outerStru return type; } -// Is this a uniform array which should be flattened? -bool HlslParseContext::shouldFlattenUniform(const TType& type) const +// Is this a uniform array or structure which should be flattened? +bool HlslParseContext::shouldFlatten(const TType& type) const { const TStorageQualifier qualifier = type.getQualifier().storage; - return qualifier == EvqUniform && - ((type.isArray() && intermediate.getFlattenUniformArrays()) || type.isStruct()) && - type.containsOpaque(); + return (qualifier == EvqUniform && type.isArray() && intermediate.getFlattenUniformArrays()) || + type.isStruct() && type.containsOpaque(); } // Top level variable flattening: construct data @@ -1285,16 +1328,22 @@ bool HlslParseContext::wasSplit(const TIntermTyped* node) const // Turn an access into an aggregate that was flattened to instead be // an access to the individual variable the member was flattened to. // Assumes shouldFlatten() or equivalent was called first. +// Also assumes that initFlattening() and finalizeFlattening() bracket the usage. TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member) { const TType dereferencedType(base->getType(), member); // dereferenced type - const TIntermSymbol& symbolNode = *base->getAsSymbolNode(); - const auto flattenData = flattenMap.find(symbolNode.getId()); + TIntermTyped* flattened = flattenAccess(symbolNode.getId(), member, dereferencedType); + + return flattened ? flattened : base; +} +TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, const TType& dereferencedType) +{ + const auto flattenData = flattenMap.find(uniqueId); if (flattenData == flattenMap.end()) - return base; + return nullptr; // Calculate new cumulative offset from the packed tree flattenOffset.back() = flattenData->second.offsets[flattenOffset.back() + member]; @@ -1307,7 +1356,7 @@ TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member) } else { // If this is not the final flattening, accumulate the position and return // an object of the partially dereferenced type. - return new TIntermSymbol(symbolNode.getId(), "flattenShadow", dereferencedType); + return new TIntermSymbol(uniqueId, "flattenShadow", dereferencedType); } } @@ -1663,15 +1712,32 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l symbolTable.makeInternalVariable(*variable); pushImplicitThis(variable); } + // Insert the parameters with name in the symbol table. if (! symbolTable.insert(*variable)) error(loc, "redefinition", variable->getName().c_str(), ""); - // Add the parameter to the AST - paramNodes = intermediate.growAggregate(paramNodes, - intermediate.addSymbol(*variable, loc), - loc); - // Add hidden parameter for struct buffer counters, if needed. + // Add parameters to the AST list. + if (shouldFlatten(variable->getType())) { + // Expand the AST parameter nodes (but not the name mangling or symbol table view) + // for structures that need to be flattened. + flatten(loc, *variable); + const TTypeList* structure = variable->getType().getStruct(); + for (int mem = 0; mem < (int)structure->size(); ++mem) { + initFlattening(); + paramNodes = intermediate.growAggregate(paramNodes, + flattenAccess(variable->getUniqueId(), mem, *(*structure)[mem].type), + loc); + finalizeFlattening(); + } + } else { + // Add the parameter to the AST + paramNodes = intermediate.growAggregate(paramNodes, + intermediate.addSymbol(*variable, loc), + loc); + } + + // Add hidden AST parameter for struct buffer counters, if needed. addStructBufferHiddenCounterParam(loc, param, paramNodes); } else paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); @@ -2265,7 +2331,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op const bool flattened = isLeft ? isFlattenLeft : isFlattenRight; const bool split = isLeft ? isSplitLeft : isSplitRight; const TIntermTyped* outer = isLeft ? outerLeft : outerRight; - const TVector& flatVariables = isLeft ? *leftVariables : *rightVariables; + const TVector& flatVariables = isLeft ? *leftVariables : *rightVariables; // Index operator if it's an aggregate, else EOpNull const TOperator op = node->getType().isArray() ? EOpIndexDirect : @@ -2320,7 +2386,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op const int elementsToCopy = std::min(elementsL, elementsR); // array case - for (int element=0; element < elementsToCopy; ++element) { + for (int element = 0; element < elementsToCopy; ++element) { arrayElement.push_back(element); // Add a new AST symbol node if we have a temp variable holding a complex RHS. @@ -2511,7 +2577,7 @@ bool HlslParseContext::hasStructBuffCounter(const TType& type) const case EbvRWStructuredBuffer: // ... return true; default: - return false; // the other structuredbfufer types do not have a counter. + return false; // the other structuredbuffer types do not have a counter. } } @@ -4419,14 +4485,18 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct pushFrontArguments(intermediate.addSymbol(*getImplicitThis(thisDepth)), arguments); } - // Convert 'in' arguments + // Convert 'in' arguments, so that types match. + // However, skip those that need expansion, that is covered next. if (arguments) addInputArgumentConversions(*fnCandidate, arguments); - // If any argument is a pass-by-reference struct buffer with an associated counter - // buffer, we have to add another hidden parameter for that counter. - if (aggregate && !builtIn) - addStructBuffArguments(loc, aggregate); + // Expand arguments. Some arguments must physically expand to a different set + // than what the shader declared and passes. + if (arguments && !builtIn) + expandArguments(loc, *fnCandidate, arguments); + + // Expansion may have changed the form of arguments + aggregate = arguments ? arguments->getAsAggregate() : nullptr; op = fnCandidate->getBuiltInOp(); if (builtIn && op != EOpNull) { @@ -4464,24 +4534,35 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct decomposeSampleMethods(loc, result, arguments); // HLSL->AST sample method decompositions decomposeGeometryMethods(loc, result, arguments); // HLSL->AST geometry method decompositions + // Create the qualifier list, carried in the AST for the call. + // Because some arguments expand to multiple arguments, the qualifier list will + // be longer than the formal parameter list. + if (result == fnNode && result->getAsAggregate()) { + TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); + for (int i = 0; i < fnCandidate->getParamCount(); ++i) { + TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; + if (hasStructBuffCounter(*(*fnCandidate)[i].type)) { + // add buffer and counter buffer argument qualifier + qualifierList.push_back(qual); + qualifierList.push_back(qual); + } else if (shouldFlatten(*(*fnCandidate)[i].type)) { + // add structure member expansion + for (int memb = 0; memb < (int)(*fnCandidate)[i].type->getStruct()->size(); ++memb) + qualifierList.push_back(qual); + } else { + // Normal 1:1 case + qualifierList.push_back(qual); + } + } + } + // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. // Also, build the qualifier list for user function calls, which are always called with an aggregate. // We don't do this is if there has been a decomposition, which will have added its own conversions // for output parameters. - if (result == fnNode && result->getAsAggregate()) { - TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; - qualifierList.push_back(qual); - - // add counter buffer argument qualifier - if (hasStructBuffCounter(*(*fnCandidate)[i].type)) - qualifierList.push_back(qual); - } - + if (result == fnNode && result->getAsAggregate()) result = addOutputArgumentConversions(*fnCandidate, *result->getAsOperator()); - } } } @@ -4512,20 +4593,22 @@ void HlslParseContext::pushFrontArguments(TIntermTyped* front, TIntermTyped*& ar void HlslParseContext::addInputArgumentConversions(const TFunction& function, TIntermTyped*& arguments) { TIntermAggregate* aggregate = arguments->getAsAggregate(); - const auto setArg = [&](int argNum, TIntermTyped* arg) { + + // Replace a single argument with a single argument. + const auto setArg = [&](int paramNum, TIntermTyped* arg) { if (function.getParamCount() == 1) arguments = arg; else { - if (aggregate) - aggregate->getSequence()[argNum] = arg; - else + if (aggregate == nullptr) arguments = arg; + else + aggregate->getSequence()[paramNum] = arg; } }; // Process each argument's conversion - for (int i = 0; i < function.getParamCount(); ++i) { - if (! function[i].type->getQualifier().isParamInput()) + for (int param = 0; param < function.getParamCount(); ++param) { + if (! function[param].type->getQualifier().isParamInput()) continue; // At this early point there is a slight ambiguity between whether an aggregate 'arguments' @@ -4533,42 +4616,121 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI // means take 'arguments' itself as the one argument. TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() - : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped()); - if (*function[i].type != arg->getType()) { + : (aggregate ? + aggregate->getSequence()[param]->getAsTyped() : + arguments->getAsTyped()); + if (*function[param].type != arg->getType()) { // In-qualified arguments just need an extra node added above the argument to // convert to the correct type. - TIntermTyped* convArg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg); + TIntermTyped* convArg = intermediate.addConversion(EOpFunctionCall, *function[param].type, arg); if (convArg != nullptr) - convArg = intermediate.addUniShapeConversion(EOpFunctionCall, *function[i].type, convArg); + convArg = intermediate.addUniShapeConversion(EOpFunctionCall, *function[param].type, convArg); if (convArg != nullptr) - setArg(i, convArg); + setArg(param, convArg); else - error(arg->getLoc(), "cannot convert input argument, argument", "", "%d", i); + error(arg->getLoc(), "cannot convert input argument, argument", "", "%d", param); } else { if (wasFlattened(arg) || wasSplit(arg)) { - // Will make a two-level subtree. - // The deepest will copy member-by-member to build the structure to pass. - // The level above that will be a two-operand EOpComma sequence that follows the copy by the - // object itself. - TVariable* internalAggregate = makeInternalVariable("aggShadow", *function[i].type); - internalAggregate->getWritableType().getQualifier().makeTemporary(); - TIntermSymbol* internalSymbolNode = new TIntermSymbol(internalAggregate->getUniqueId(), - internalAggregate->getName(), - internalAggregate->getType()); - internalSymbolNode->setLoc(arg->getLoc()); - // This makes the deepest level, the member-wise copy - TIntermAggregate* assignAgg = handleAssign(arg->getLoc(), EOpAssign, internalSymbolNode, arg)->getAsAggregate(); + // If both formal and calling arg are to be flattened, leave that to argument + // expansion, not conversion. + if (!shouldFlatten(*function[param].type)) { + // Will make a two-level subtree. + // The deepest will copy member-by-member to build the structure to pass. + // The level above that will be a two-operand EOpComma sequence that follows the copy by the + // object itself. + TVariable* internalAggregate = makeInternalVariable("aggShadow", *function[param].type); + internalAggregate->getWritableType().getQualifier().makeTemporary(); + TIntermSymbol* internalSymbolNode = new TIntermSymbol(internalAggregate->getUniqueId(), + internalAggregate->getName(), + internalAggregate->getType()); + internalSymbolNode->setLoc(arg->getLoc()); + // This makes the deepest level, the member-wise copy + TIntermAggregate* assignAgg = handleAssign(arg->getLoc(), EOpAssign, internalSymbolNode, arg)->getAsAggregate(); - // Now, pair that with the resulting aggregate. - assignAgg = intermediate.growAggregate(assignAgg, internalSymbolNode, arg->getLoc()); - assignAgg->setOperator(EOpComma); - assignAgg->setType(internalAggregate->getType()); - setArg(i, assignAgg); + // Now, pair that with the resulting aggregate. + assignAgg = intermediate.growAggregate(assignAgg, internalSymbolNode, arg->getLoc()); + assignAgg->setOperator(EOpComma); + assignAgg->setType(internalAggregate->getType()); + setArg(param, assignAgg); + } } } } } +// +// Add any needed implicit expansion of calling arguments from what the shader listed to what's +// internally needed for the AST (given the constraints downstream). +// +void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& function, TIntermTyped*& arguments) +{ + TIntermAggregate* aggregate = arguments->getAsAggregate(); + int functionParamNumberOffset = 0; + + // Replace a single argument with a single argument. + const auto setArg = [&](int paramNum, TIntermTyped* arg) { + if (function.getParamCount() + functionParamNumberOffset == 1) + arguments = arg; + else { + if (aggregate == nullptr) + arguments = arg; + else + aggregate->getSequence()[paramNum] = arg; + } + }; + + // Replace a single argument with a list of arguments + const auto setArgList = [&](int paramNum, const TVector& args) { + if (args.size() == 1) + setArg(paramNum, args.front()); + else { + if (function.getParamCount() + functionParamNumberOffset == 1) { + arguments = intermediate.makeAggregate(args.front()); + std::for_each(args.begin() + 1, args.end(), + [&](TIntermTyped* arg) { + arguments = intermediate.growAggregate(arguments, arg); + }); + } else { + auto it = aggregate->getSequence().erase(aggregate->getSequence().begin() + paramNum); + aggregate->getSequence().insert(it, args.begin(), args.end()); + } + } + functionParamNumberOffset += (args.size() - 1); + }; + + // Process each argument's conversion + for (int param = 0; param < function.getParamCount(); ++param) { + // At this early point there is a slight ambiguity between whether an aggregate 'arguments' + // is the single argument itself or its children are the arguments. Only one argument + // means take 'arguments' itself as the one argument. + TIntermTyped* arg = function.getParamCount() == 1 + ? arguments->getAsTyped() + : (aggregate ? + aggregate->getSequence()[param + functionParamNumberOffset]->getAsTyped() : + arguments->getAsTyped()); + + if (wasFlattened(arg) && shouldFlatten(*function[param].type)) { + // Need to pass the structure members instead of the structure. + TVector memberArgs; + for (int memb = 0; memb < (int)arg->getType().getStruct()->size(); ++memb) { + initFlattening(); + memberArgs.push_back(flattenAccess(arg, memb)); + finalizeFlattening(); + } + setArgList(param + functionParamNumberOffset, memberArgs); + } + } + + // TODO: if we need both hidden counter args (below) and struct expansion (above) + // the two algorithms need to be merged: Each assumes the list starts out 1:1 between + // parameters and arguments. + + // If any argument is a pass-by-reference struct buffer with an associated counter + // buffer, we have to add another hidden parameter for that counter. + if (aggregate) + addStructBuffArguments(loc, aggregate); +} + // // Add any needed implicit output conversions for function-call arguments. This // can require a new tree topology, complicated further by whether the function @@ -4682,7 +4844,7 @@ void HlslParseContext::addStructBuffArguments(const TSourceLoc& loc, TIntermAggr TIntermSequence argsWithCounterBuffers; - for (int param=0; paramgetSequence().size()); ++param) { + for (int param = 0; param < int(aggregate->getSequence().size()); ++param) { argsWithCounterBuffers.push_back(aggregate->getSequence()[param]); if (hasStructBuffCounter(aggregate->getSequence()[param]->getAsTyped()->getType())) { @@ -6769,7 +6931,7 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, const TStr inheritGlobalDefaults(type.getQualifier()); - const bool flattenVar = shouldFlattenUniform(type); + const bool flattenVar = shouldFlatten(type); // correct IO in the type switch (type.getQualifier().storage) { diff --git a/3rdparty/glslang/hlsl/hlslParseHelper.h b/3rdparty/glslang/hlsl/hlslParseHelper.h index f7b293abb..9a9896423 100755 --- a/3rdparty/glslang/hlsl/hlslParseHelper.h +++ b/3rdparty/glslang/hlsl/hlslParseHelper.h @@ -96,6 +96,7 @@ public: void decomposeGeometryMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments); void addInputArgumentConversions(const TFunction&, TIntermTyped*&); + void expandArguments(const TSourceLoc&, const TFunction&, TIntermTyped*&); TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&); void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); TFunction* makeConstructorCall(const TSourceLoc&, const TType&); @@ -186,7 +187,8 @@ public: virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override; // Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore. - TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped* node); + TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node); + TIntermTyped* handleSamplerLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node); bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&); @@ -236,13 +238,14 @@ protected: // Array and struct flattening TIntermTyped* flattenAccess(TIntermTyped* base, int member); - bool shouldFlattenUniform(const TType&) const; + TIntermTyped* flattenAccess(int uniqueId, int member, const TType&); + bool shouldFlatten(const TType&) const; bool wasFlattened(const TIntermTyped* node) const; bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); } int addFlattenedMember(const TSourceLoc& loc, const TVariable&, const TType&, TFlattenData&, const TString& name, bool track); bool isFinalFlattening(const TType& type) const { return !(type.isStruct() || type.isArray()); } - // Structure splitting (splits interstage builtin types into its own struct) + // Structure splitting (splits interstage built-in types into its own struct) TIntermTyped* splitAccessStruct(const TSourceLoc& loc, TIntermTyped*& base, int& member); void splitAccessArray(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index); TType& split(TType& type, TString name, const TType* outerStructType = nullptr); diff --git a/3rdparty/glslang/hlsl/hlslParseables.cpp b/3rdparty/glslang/hlsl/hlslParseables.cpp index e094aef9d..db67c39df 100755 --- a/3rdparty/glslang/hlsl/hlslParseables.cpp +++ b/3rdparty/glslang/hlsl/hlslParseables.cpp @@ -502,7 +502,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c static const EShLanguageMask EShLangAll = EShLanguageMask(EShLangCount - 1); // These are the actual stage masks defined in the documentation, in case they are - // needed for furture validation. For now, they are commented out, and set below + // needed for future validation. For now, they are commented out, and set below // to EShLangAll, to allow any intrinsic to be used in any shader, which is legal // if it is not called. // diff --git a/tools/shaderc/shaderc_spirv.cpp b/tools/shaderc/shaderc_spirv.cpp index e788db476..6848fa1d4 100644 --- a/tools/shaderc/shaderc_spirv.cpp +++ b/tools/shaderc/shaderc_spirv.cpp @@ -12,8 +12,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u #include #include #include -//#include -//#include +#include BX_PRAGMA_DIAGNOSTIC_POP() namespace bgfx @@ -50,12 +49,6 @@ namespace stl = tinystl; #include "../../src/shader_spirv.h" -namespace glslang -{ - void GlslangToSpv(const glslang::TIntermediate& _intermediate, std::vector& _spirv); - -} // namespace glslang - namespace bgfx { namespace spirv { const TBuiltInResource resourceLimits =