diff --git a/.gitignore b/.gitignore index d93c2022..66cbff97 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build/ Test/localResults/ Test/multiThread.out Test/singleThread.out +External/googletest diff --git a/CMakeLists.txt b/CMakeLists.txt index c7bda517..1027e7e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 2.8) +enable_testing() + set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "prefix") project(glslang) @@ -11,7 +13,7 @@ elseif(UNIX) add_definitions(-fPIC) add_definitions(-DGLSLANG_OSINCLUDE_UNIX) else(WIN32) - message("unkown platform") + message("unknown platform") endif(WIN32) if(CMAKE_COMPILER_IS_GNUCXX) @@ -20,8 +22,12 @@ elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") add_definitions(-std=c++11) endif() +# We depend on these for later projects, so they should come first. +add_subdirectory(External) + add_subdirectory(glslang) add_subdirectory(OGLCompilersDLL) add_subdirectory(StandAlone) add_subdirectory(SPIRV) add_subdirectory(hlsl) +add_subdirectory(gtests) diff --git a/External/CMakeLists.txt b/External/CMakeLists.txt new file mode 100644 index 00000000..d43cf9d0 --- /dev/null +++ b/External/CMakeLists.txt @@ -0,0 +1,16 @@ +# Suppress all warnings from external projects. +set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w) + +if (TARGET gmock) + message(STATUS "Google Mock already configured - use it") +elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest) + # We need to make sure Google Test does not mess up with the + # global CRT settings on Windows. + if(WIN32) + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + endif(WIN32) + add_subdirectory(googletest) +else() + message(STATUS + "Google Mock was not found - tests based on that will not build") +endif() diff --git a/README.md b/README.md index 7a60e280..56bdeec9 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,12 @@ bison --defines=MachineIndependent/glslang_tab.cpp.h -o MachineIndependent/glslang_tab.cpp ``` +Glslang is adding the ability to test with +[Google Test](https://github.com/google/googletest) framework. If you want to +build and run those tests, please make sure you have a copy of Google Tests +checked out in the `External/` directory: +`git clone https://github.com/google/googletest.git`. + Programmatic Interfaces ----------------------- @@ -97,7 +103,7 @@ class TProgram See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more details. -### C Functional Interface (orginal) +### C Functional Interface (orignal) This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to as the `Sh*()` interface, as all the entry points start `Sh`. @@ -112,13 +118,17 @@ ShCompile(shader, compiler) -> compiler(AST) -> ``` In practice, `ShCompile()` takes shader strings, default version, and -warning/error and other options for controling compilation. +warning/error and other options for controlling compilation. Testing ------- Test results should always be included with a pull request that modifies -functionality. There is a simple process for doing this, described here: +functionality. And since glslang is adding the ability to test with +[Google Test](https://github.com/google/googletest) framework, +please write your new tests using Google Test. + +The old (deprecated) testing process is: `Test` is an active test directory that contains test input and a subdirectory `baseResults` that contains the expected results of the diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 1c6abec9..df8a1e1f 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -128,8 +128,9 @@ protected: void addDecoration(spv::Id id, spv::Decoration dec, unsigned value); void addMemberDecoration(spv::Id id, int member, spv::Decoration dec); void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); - spv::Id createSpvSpecConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); + spv::Id createSpvConstant(const glslang::TIntermTyped&); + spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); + spv::Id createSpvConstantFromConstSubTree(glslang::TIntermTyped* subTree); bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); @@ -1527,7 +1528,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node) { int nextConst = 0; - spv::Id constant = createSpvConstant(node->getType(), node->getConstArray(), nextConst, false); + spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false); builder.clearAccessChain(); builder.setAccessChainRValue(constant); @@ -1636,8 +1637,8 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* // First, steer off constants, which are not SPIR-V variables, but // can still have a mapping to a SPIR-V Id. // This includes specialization constants. - if (node->getQualifier().storage == glslang::EvqConst) { - return createSpvSpecConstant(*node); + if (node->getQualifier().isConstant()) { + return createSpvConstant(*node); } // Now, handle actual variables @@ -3444,11 +3445,12 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: builder.promoteScalar(precision, operands.front(), operands[2]); break; case glslang::EOpMix: - if (isFloat) + if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) { + assert(isFloat); libCall = spv::GLSLstd450FMix; - else { + } else { opCode = spv::OpSelect; - spv::MissingFunctionality("translating integer mix to OpSelect"); + std::swap(operands.front(), operands.back()); } builder.promoteScalar(precision, operands.front(), operands.back()); break; @@ -3738,15 +3740,15 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De // recursively walks. So, this function walks the "top" of the tree: // - emit specialization constant-building instructions for specConstant // - when running into a non-spec-constant, switch to createSpvConstant() -spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermTyped& node) +spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node) { - assert(node.getQualifier().storage == glslang::EvqConst); + assert(node.getQualifier().isConstant()); if (! node.getQualifier().specConstant) { // hand off to the non-spec-constant path assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); int nextConst = 0; - return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), + return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), nextConst, false); } @@ -3755,7 +3757,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) { // this is a direct literal assigned to a layout(constant_id=) declaration int nextConst = 0; - return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), + return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), nextConst, true); } else { // gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants, @@ -3769,8 +3771,11 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim)); } return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); + } else if (auto* sn = node.getAsSymbolNode()){ + return createSpvConstantFromConstSubTree(sn->getConstSubtree()); } else { - spv::MissingFunctionality("specialization-constant expression trees"); + spv::MissingFunctionality("Neither a front-end constant nor a spec constant."); + exit(1); return spv::NoResult; } } @@ -3782,7 +3787,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType // If there are not enough elements present in 'consts', 0 will be substituted; // an empty 'consts' can be used to create a fully zeroed SPIR-V constant. // -spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) +spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) { // vector of constants for SPIR-V std::vector spvConsts; @@ -3793,15 +3798,15 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT if (glslangType.isArray()) { glslang::TType elementType(glslangType, 0); for (int i = 0; i < glslangType.getOuterArraySize(); ++i) - spvConsts.push_back(createSpvConstant(elementType, consts, nextConst, false)); + spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false)); } else if (glslangType.isMatrix()) { glslang::TType vectorType(glslangType, 0); for (int col = 0; col < glslangType.getMatrixCols(); ++col) - spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst, false)); + spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false)); } else if (glslangType.getStruct()) { glslang::TVector::const_iterator iter; for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) - spvConsts.push_back(createSpvConstant(*iter->type, consts, nextConst, false)); + spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); } else if (glslangType.isVector()) { for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { bool zero = nextConst >= consts.size(); @@ -3858,6 +3863,97 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT return builder.makeCompositeConstant(typeId, spvConsts); } +namespace { +class SpecConstantOpModeGuard { +public: + SpecConstantOpModeGuard(spv::Builder* builder) + : builder_(builder) { + previous_flag_ = builder->isInSpecConstCodeGenMode(); + builder->setToSpecConstCodeGenMode(); + } + ~SpecConstantOpModeGuard() { + previous_flag_ ? builder_->setToSpecConstCodeGenMode() + : builder_->setToNormalCodeGenMode(); + } + +private: + spv::Builder* builder_; + bool previous_flag_; +}; +} + +// Create constant ID from const initializer sub tree. +spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( + glslang::TIntermTyped* subTree) +{ + const glslang::TType& glslangType = subTree->getType(); + spv::Id typeId = convertGlslangToSpvType(glslangType); + bool is_spec_const = subTree->getType().getQualifier().isSpecConstant(); + if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) { + // Aggregate node, we should generate OpConstantComposite or + // OpSpecConstantComposite instruction. + + std::vector const_constituents; + for (auto NI = an->getSequence().begin(); NI != an->getSequence().end(); + NI++) { + const_constituents.push_back( + createSpvConstantFromConstSubTree((*NI)->getAsTyped())); + } + // Note that constructors are aggregate nodes, so expressions like: + // float x = float(y) will become an aggregate node. If 'x' is declared + // as a constant, the aggregate node representing 'float(y)' will be + // processed here. + if (builder.isVectorType(typeId) || builder.isMatrixType(typeId) || + builder.isAggregateType(typeId)) { + return builder.makeCompositeConstant(typeId, const_constituents, is_spec_const); + } else { + assert(builder.isScalarType(typeId) && const_constituents.size() == 1); + return const_constituents.front(); + } + + } else if (glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) { + // Binary operation node, we should generate OpSpecConstantOp + // This case should only happen when Specialization Constants are involved. + + // Spec constants defined with binary operations and other constants requires + // OpSpecConstantOp instruction. + SpecConstantOpModeGuard set_to_spec_const_mode(&builder); + + bn->traverse(this); + return accessChainLoad(bn->getType()); + + } else if (glslang::TIntermUnary* un = subTree->getAsUnaryNode()) { + // Unary operation node, similar to binary operation node, should only + // happen when specialization constants are involved. + + // Spec constants defined with unary operations and other constants requires + // OpSpecConstantOp instruction. + SpecConstantOpModeGuard set_to_spec_const_mode(&builder); + + un->traverse(this); + return accessChainLoad(un->getType()); + + } else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) { + // ConstantUnion node, should redirect to + // createSpvConstantFromConstUnionArray + int nextConst = 0; + return createSpvConstantFromConstUnionArray( + glslangType, cn->getConstArray(), nextConst, is_spec_const); + + } else if (const glslang::TIntermSymbol* sn = subTree->getAsSymbolNode()) { + // Symbol node. Call getSymbolId(). This should cover both cases 1) the + // symbol has already been assigned an ID, 2) need a new ID for this + // symbol. + return getSymbolId(sn); + + } else { + spv::MissingFunctionality( + "createSpvConstantFromConstSubTree() not covered TIntermTyped* const " + "initializer subtree."); + return spv::NoResult; + } +} + // Return true if the node is a constant or symbol whose reading has no // non-trivial observable cost or effect. bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) diff --git a/SPIRV/SPVRemapper.cpp b/SPIRV/SPVRemapper.cpp index 965867ef..35dda17b 100755 --- a/SPIRV/SPVRemapper.cpp +++ b/SPIRV/SPVRemapper.cpp @@ -573,7 +573,7 @@ namespace spv { op_fn_nop); // Window size for context-sensitive canonicalization values - // Emperical best size from a single data set. TODO: Would be a good tunable. + // Empirical best size from a single data set. TODO: Would be a good tunable. // We essentially perform a little convolution around each instruction, // to capture the flavor of nearby code, to hopefully match to similar // code in other modules. diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 06d7a02a..f69e7feb 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -64,7 +64,8 @@ Builder::Builder(unsigned int magicNumber) : builderNumber(magicNumber), buildPoint(0), uniqueId(0), - mainFunction(0) + mainFunction(0), + generatingOpCodeForSpecConst(false) { clearAccessChain(); } @@ -1063,6 +1064,11 @@ Id Builder::createArrayLength(Id base, unsigned int member) Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), std::vector(1, index)); + } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); extract->addImmediateOperand(index); @@ -1073,6 +1079,11 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector& indexes) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), indexes); + } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); for (int i = 0; i < (int)indexes.size(); ++i) @@ -1170,6 +1181,11 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant // An opcode that has one operands, a result id, and a type Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + return createSpecConstantOp(opCode, typeId, std::vector(1, operand), std::vector()); + } Instruction* op = new Instruction(getUniqueId(), typeId, opCode); op->addIdOperand(operand); buildPoint->addInstruction(std::unique_ptr(op)); @@ -1179,6 +1195,13 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) { + // Generate code for spec constants if in spec constant operation + // generation mode. + if (generatingOpCodeForSpecConst) { + std::vector operands(2); + operands[0] = left; operands[1] = right; + return createSpecConstantOp(opCode, typeId, operands, std::vector()); + } Instruction* op = new Instruction(getUniqueId(), typeId, opCode); op->addIdOperand(left); op->addIdOperand(right); @@ -1208,6 +1231,20 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) return op->getResultId(); } +Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) +{ + Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); + op->addImmediateOperand((unsigned) opCode); + for (auto it = operands.cbegin(); it != operands.cend(); ++it) + op->addIdOperand(*it); + for (auto it = literals.cbegin(); it != literals.cend(); ++it) + op->addImmediateOperand(*it); + module.mapInstruction(op); + constantsTypesGlobals.push_back(std::unique_ptr(op)); + + return op->getResultId(); +} + Id Builder::createFunctionCall(spv::Function* function, std::vector& args) { Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); @@ -1225,6 +1262,11 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, std: if (channels.size() == 1) return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); + if (generatingOpCodeForSpecConst) { + std::vector operands(2); + operands[0] = operands[1] = source; + return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision); + } Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); assert(isVector(source)); swizzle->addIdOperand(source); @@ -1290,10 +1332,23 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) if (numComponents == 1) return scalar; - Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); - for (int c = 0; c < numComponents; ++c) - smear->addIdOperand(scalar); - buildPoint->addInstruction(std::unique_ptr(smear)); + Instruction* smear = nullptr; + if (generatingOpCodeForSpecConst) { + auto members = std::vector(numComponents, scalar); + // 'scalar' can not be spec constant here. All spec constant involved + // promotion is done in createSpvConstantFromConstUnionArray(). This + // 'if' branch is only accessed when 'scalar' is used in the def-chain + // of other vector type spec constants. In such cases, all the + // instructions needed to promote 'scalar' to a vector type constants + // should be added at module level. + auto result_id = makeCompositeConstant(vectorType, members, false); + smear = module.getInstruction(result_id); + } else { + smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); + for (int c = 0; c < numComponents; ++c) + smear->addIdOperand(scalar); + buildPoint->addInstruction(std::unique_ptr(smear)); + } return setPrecision(smear->getResultId(), precision); } @@ -2158,7 +2213,7 @@ void Builder::eliminateDeadDecorations() { } } decorations.erase(std::remove_if(decorations.begin(), decorations.end(), - [&unreachable_definitions](std::unique_ptr& I) { + [&unreachable_definitions](std::unique_ptr& I) -> bool { Instruction* inst = I.get(); Id decoration_id = inst->getIdOperand(0); return unreachable_definitions.count(decoration_id) != 0; @@ -2268,7 +2323,7 @@ void Builder::simplifyAccessChainSwizzle() // To the extent any swizzling can become part of the chain // of accesses instead of a post operation, make it so. -// If 'dynamic' is true, include transfering a non-static component index, +// If 'dynamic' is true, include transferring a non-static component index, // otherwise, only transfer static indexes. // // Also, Boolean vectors are likely to be special. While diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index 162e79ef..62f6775e 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -262,6 +262,7 @@ public: Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); Id createOp(Op, Id typeId, const std::vector& operands); Id createFunctionCall(spv::Function*, std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); // Take an rvalue (source) and a set of channels to extract from it to // make a new rvalue, which is returned. @@ -521,6 +522,13 @@ public: void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control); + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + protected: Id makeIntConstant(Id typeId, unsigned value, bool specConstant); Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const; @@ -544,6 +552,7 @@ public: Block* buildPoint; Id uniqueId; Function* mainFunction; + bool generatingOpCodeForSpecConst; AccessChain accessChain; // special blocks of instructions for output diff --git a/StandAlone/CMakeLists.txt b/StandAlone/CMakeLists.txt index 48fa5029..e9d72110 100644 --- a/StandAlone/CMakeLists.txt +++ b/StandAlone/CMakeLists.txt @@ -1,5 +1,13 @@ cmake_minimum_required(VERSION 2.8) +add_library(glslang-default-resource-limits + ${CMAKE_CURRENT_SOURCE_DIR}/DefaultResourceLimits.cpp +) +target_include_directories(glslang-default-resource-limits + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC ${PROJECT_SOURCE_DIR} +) + set(SOURCES StandAlone.cpp) set(REMAPPER_SOURCES spirv-remap.cpp) @@ -11,7 +19,8 @@ set(LIBRARIES OGLCompiler OSDependent HLSL - SPIRV) + SPIRV + glslang-default-resource-limits) if(WIN32) set(LIBRARIES ${LIBRARIES} psapi) diff --git a/StandAlone/DefaultResourceLimits.cpp b/StandAlone/DefaultResourceLimits.cpp new file mode 100644 index 00000000..66032de1 --- /dev/null +++ b/StandAlone/DefaultResourceLimits.cpp @@ -0,0 +1,239 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "DefaultResourceLimits.h" + +namespace glslang { + +const TBuiltInResource DefaultTBuiltInResource = { + /* .MaxLights = */ 32, + /* .MaxClipPlanes = */ 6, + /* .MaxTextureUnits = */ 32, + /* .MaxTextureCoords = */ 32, + /* .MaxVertexAttribs = */ 64, + /* .MaxVertexUniformComponents = */ 4096, + /* .MaxVaryingFloats = */ 64, + /* .MaxVertexTextureImageUnits = */ 32, + /* .MaxCombinedTextureImageUnits = */ 80, + /* .MaxTextureImageUnits = */ 32, + /* .MaxFragmentUniformComponents = */ 4096, + /* .MaxDrawBuffers = */ 32, + /* .MaxVertexUniformVectors = */ 128, + /* .MaxVaryingVectors = */ 8, + /* .MaxFragmentUniformVectors = */ 16, + /* .MaxVertexOutputVectors = */ 16, + /* .MaxFragmentInputVectors = */ 15, + /* .MinProgramTexelOffset = */ -8, + /* .MaxProgramTexelOffset = */ 7, + /* .MaxClipDistances = */ 8, + /* .MaxComputeWorkGroupCountX = */ 65535, + /* .MaxComputeWorkGroupCountY = */ 65535, + /* .MaxComputeWorkGroupCountZ = */ 65535, + /* .MaxComputeWorkGroupSizeX = */ 1024, + /* .MaxComputeWorkGroupSizeY = */ 1024, + /* .MaxComputeWorkGroupSizeZ = */ 64, + /* .MaxComputeUniformComponents = */ 1024, + /* .MaxComputeTextureImageUnits = */ 16, + /* .MaxComputeImageUniforms = */ 8, + /* .MaxComputeAtomicCounters = */ 8, + /* .MaxComputeAtomicCounterBuffers = */ 1, + /* .MaxVaryingComponents = */ 60, + /* .MaxVertexOutputComponents = */ 64, + /* .MaxGeometryInputComponents = */ 64, + /* .MaxGeometryOutputComponents = */ 128, + /* .MaxFragmentInputComponents = */ 128, + /* .MaxImageUnits = */ 8, + /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, + /* .MaxCombinedShaderOutputResources = */ 8, + /* .MaxImageSamples = */ 0, + /* .MaxVertexImageUniforms = */ 0, + /* .MaxTessControlImageUniforms = */ 0, + /* .MaxTessEvaluationImageUniforms = */ 0, + /* .MaxGeometryImageUniforms = */ 0, + /* .MaxFragmentImageUniforms = */ 8, + /* .MaxCombinedImageUniforms = */ 8, + /* .MaxGeometryTextureImageUnits = */ 16, + /* .MaxGeometryOutputVertices = */ 256, + /* .MaxGeometryTotalOutputComponents = */ 1024, + /* .MaxGeometryUniformComponents = */ 1024, + /* .MaxGeometryVaryingComponents = */ 64, + /* .MaxTessControlInputComponents = */ 128, + /* .MaxTessControlOutputComponents = */ 128, + /* .MaxTessControlTextureImageUnits = */ 16, + /* .MaxTessControlUniformComponents = */ 1024, + /* .MaxTessControlTotalOutputComponents = */ 4096, + /* .MaxTessEvaluationInputComponents = */ 128, + /* .MaxTessEvaluationOutputComponents = */ 128, + /* .MaxTessEvaluationTextureImageUnits = */ 16, + /* .MaxTessEvaluationUniformComponents = */ 1024, + /* .MaxTessPatchComponents = */ 120, + /* .MaxPatchVertices = */ 32, + /* .MaxTessGenLevel = */ 64, + /* .MaxViewports = */ 16, + /* .MaxVertexAtomicCounters = */ 0, + /* .MaxTessControlAtomicCounters = */ 0, + /* .MaxTessEvaluationAtomicCounters = */ 0, + /* .MaxGeometryAtomicCounters = */ 0, + /* .MaxFragmentAtomicCounters = */ 8, + /* .MaxCombinedAtomicCounters = */ 8, + /* .MaxAtomicCounterBindings = */ 1, + /* .MaxVertexAtomicCounterBuffers = */ 0, + /* .MaxTessControlAtomicCounterBuffers = */ 0, + /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, + /* .MaxGeometryAtomicCounterBuffers = */ 0, + /* .MaxFragmentAtomicCounterBuffers = */ 1, + /* .MaxCombinedAtomicCounterBuffers = */ 1, + /* .MaxAtomicCounterBufferSize = */ 16384, + /* .MaxTransformFeedbackBuffers = */ 4, + /* .MaxTransformFeedbackInterleavedComponents = */ 64, + /* .MaxCullDistances = */ 8, + /* .MaxCombinedClipAndCullDistances = */ 8, + /* .MaxSamples = */ 4, + /* .limits = */ { + /* .nonInductiveForLoops = */ 1, + /* .whileLoops = */ 1, + /* .doWhileLoops = */ 1, + /* .generalUniformIndexing = */ 1, + /* .generalAttributeMatrixVectorIndexing = */ 1, + /* .generalVaryingIndexing = */ 1, + /* .generalSamplerIndexing = */ 1, + /* .generalVariableIndexing = */ 1, + /* .generalConstantMatrixVectorIndexing = */ 1, + }}; + +std::string GetDefaultTBuiltInResourceString() +{ + std::ostringstream ostream; + + ostream << "MaxLights " << DefaultTBuiltInResource.maxLights << "\n" + << "MaxClipPlanes " << DefaultTBuiltInResource.maxClipPlanes << "\n" + << "MaxTextureUnits " << DefaultTBuiltInResource.maxTextureUnits << "\n" + << "MaxTextureCoords " << DefaultTBuiltInResource.maxTextureCoords << "\n" + << "MaxVertexAttribs " << DefaultTBuiltInResource.maxVertexAttribs << "\n" + << "MaxVertexUniformComponents " << DefaultTBuiltInResource.maxVertexUniformComponents << "\n" + << "MaxVaryingFloats " << DefaultTBuiltInResource.maxVaryingFloats << "\n" + << "MaxVertexTextureImageUnits " << DefaultTBuiltInResource.maxVertexTextureImageUnits << "\n" + << "MaxCombinedTextureImageUnits " << DefaultTBuiltInResource.maxCombinedTextureImageUnits << "\n" + << "MaxTextureImageUnits " << DefaultTBuiltInResource.maxTextureImageUnits << "\n" + << "MaxFragmentUniformComponents " << DefaultTBuiltInResource.maxFragmentUniformComponents << "\n" + << "MaxDrawBuffers " << DefaultTBuiltInResource.maxDrawBuffers << "\n" + << "MaxVertexUniformVectors " << DefaultTBuiltInResource.maxVertexUniformVectors << "\n" + << "MaxVaryingVectors " << DefaultTBuiltInResource.maxVaryingVectors << "\n" + << "MaxFragmentUniformVectors " << DefaultTBuiltInResource.maxFragmentUniformVectors << "\n" + << "MaxVertexOutputVectors " << DefaultTBuiltInResource.maxVertexOutputVectors << "\n" + << "MaxFragmentInputVectors " << DefaultTBuiltInResource.maxFragmentInputVectors << "\n" + << "MinProgramTexelOffset " << DefaultTBuiltInResource.minProgramTexelOffset << "\n" + << "MaxProgramTexelOffset " << DefaultTBuiltInResource.maxProgramTexelOffset << "\n" + << "MaxClipDistances " << DefaultTBuiltInResource.maxClipDistances << "\n" + << "MaxComputeWorkGroupCountX " << DefaultTBuiltInResource.maxComputeWorkGroupCountX << "\n" + << "MaxComputeWorkGroupCountY " << DefaultTBuiltInResource.maxComputeWorkGroupCountY << "\n" + << "MaxComputeWorkGroupCountZ " << DefaultTBuiltInResource.maxComputeWorkGroupCountZ << "\n" + << "MaxComputeWorkGroupSizeX " << DefaultTBuiltInResource.maxComputeWorkGroupSizeX << "\n" + << "MaxComputeWorkGroupSizeY " << DefaultTBuiltInResource.maxComputeWorkGroupSizeY << "\n" + << "MaxComputeWorkGroupSizeZ " << DefaultTBuiltInResource.maxComputeWorkGroupSizeZ << "\n" + << "MaxComputeUniformComponents " << DefaultTBuiltInResource.maxComputeUniformComponents << "\n" + << "MaxComputeTextureImageUnits " << DefaultTBuiltInResource.maxComputeTextureImageUnits << "\n" + << "MaxComputeImageUniforms " << DefaultTBuiltInResource.maxComputeImageUniforms << "\n" + << "MaxComputeAtomicCounters " << DefaultTBuiltInResource.maxComputeAtomicCounters << "\n" + << "MaxComputeAtomicCounterBuffers " << DefaultTBuiltInResource.maxComputeAtomicCounterBuffers << "\n" + << "MaxVaryingComponents " << DefaultTBuiltInResource.maxVaryingComponents << "\n" + << "MaxVertexOutputComponents " << DefaultTBuiltInResource.maxVertexOutputComponents << "\n" + << "MaxGeometryInputComponents " << DefaultTBuiltInResource.maxGeometryInputComponents << "\n" + << "MaxGeometryOutputComponents " << DefaultTBuiltInResource.maxGeometryOutputComponents << "\n" + << "MaxFragmentInputComponents " << DefaultTBuiltInResource.maxFragmentInputComponents << "\n" + << "MaxImageUnits " << DefaultTBuiltInResource.maxImageUnits << "\n" + << "MaxCombinedImageUnitsAndFragmentOutputs " << DefaultTBuiltInResource.maxCombinedImageUnitsAndFragmentOutputs << "\n" + << "MaxCombinedShaderOutputResources " << DefaultTBuiltInResource.maxCombinedShaderOutputResources << "\n" + << "MaxImageSamples " << DefaultTBuiltInResource.maxImageSamples << "\n" + << "MaxVertexImageUniforms " << DefaultTBuiltInResource.maxVertexImageUniforms << "\n" + << "MaxTessControlImageUniforms " << DefaultTBuiltInResource.maxTessControlImageUniforms << "\n" + << "MaxTessEvaluationImageUniforms " << DefaultTBuiltInResource.maxTessEvaluationImageUniforms << "\n" + << "MaxGeometryImageUniforms " << DefaultTBuiltInResource.maxGeometryImageUniforms << "\n" + << "MaxFragmentImageUniforms " << DefaultTBuiltInResource.maxFragmentImageUniforms << "\n" + << "MaxCombinedImageUniforms " << DefaultTBuiltInResource.maxCombinedImageUniforms << "\n" + << "MaxGeometryTextureImageUnits " << DefaultTBuiltInResource.maxGeometryTextureImageUnits << "\n" + << "MaxGeometryOutputVertices " << DefaultTBuiltInResource.maxGeometryOutputVertices << "\n" + << "MaxGeometryTotalOutputComponents " << DefaultTBuiltInResource.maxGeometryTotalOutputComponents << "\n" + << "MaxGeometryUniformComponents " << DefaultTBuiltInResource.maxGeometryUniformComponents << "\n" + << "MaxGeometryVaryingComponents " << DefaultTBuiltInResource.maxGeometryVaryingComponents << "\n" + << "MaxTessControlInputComponents " << DefaultTBuiltInResource.maxTessControlInputComponents << "\n" + << "MaxTessControlOutputComponents " << DefaultTBuiltInResource.maxTessControlOutputComponents << "\n" + << "MaxTessControlTextureImageUnits " << DefaultTBuiltInResource.maxTessControlTextureImageUnits << "\n" + << "MaxTessControlUniformComponents " << DefaultTBuiltInResource.maxTessControlUniformComponents << "\n" + << "MaxTessControlTotalOutputComponents " << DefaultTBuiltInResource.maxTessControlTotalOutputComponents << "\n" + << "MaxTessEvaluationInputComponents " << DefaultTBuiltInResource.maxTessEvaluationInputComponents << "\n" + << "MaxTessEvaluationOutputComponents " << DefaultTBuiltInResource.maxTessEvaluationOutputComponents << "\n" + << "MaxTessEvaluationTextureImageUnits " << DefaultTBuiltInResource.maxTessEvaluationTextureImageUnits << "\n" + << "MaxTessEvaluationUniformComponents " << DefaultTBuiltInResource.maxTessEvaluationUniformComponents << "\n" + << "MaxTessPatchComponents " << DefaultTBuiltInResource.maxTessPatchComponents << "\n" + << "MaxPatchVertices " << DefaultTBuiltInResource.maxPatchVertices << "\n" + << "MaxTessGenLevel " << DefaultTBuiltInResource.maxTessGenLevel << "\n" + << "MaxViewports " << DefaultTBuiltInResource.maxViewports << "\n" + << "MaxVertexAtomicCounters " << DefaultTBuiltInResource.maxVertexAtomicCounters << "\n" + << "MaxTessControlAtomicCounters " << DefaultTBuiltInResource.maxTessControlAtomicCounters << "\n" + << "MaxTessEvaluationAtomicCounters " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounters << "\n" + << "MaxGeometryAtomicCounters " << DefaultTBuiltInResource.maxGeometryAtomicCounters << "\n" + << "MaxFragmentAtomicCounters " << DefaultTBuiltInResource.maxFragmentAtomicCounters << "\n" + << "MaxCombinedAtomicCounters " << DefaultTBuiltInResource.maxCombinedAtomicCounters << "\n" + << "MaxAtomicCounterBindings " << DefaultTBuiltInResource.maxAtomicCounterBindings << "\n" + << "MaxVertexAtomicCounterBuffers " << DefaultTBuiltInResource.maxVertexAtomicCounterBuffers << "\n" + << "MaxTessControlAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessControlAtomicCounterBuffers << "\n" + << "MaxTessEvaluationAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounterBuffers << "\n" + << "MaxGeometryAtomicCounterBuffers " << DefaultTBuiltInResource.maxGeometryAtomicCounterBuffers << "\n" + << "MaxFragmentAtomicCounterBuffers " << DefaultTBuiltInResource.maxFragmentAtomicCounterBuffers << "\n" + << "MaxCombinedAtomicCounterBuffers " << DefaultTBuiltInResource.maxCombinedAtomicCounterBuffers << "\n" + << "MaxAtomicCounterBufferSize " << DefaultTBuiltInResource.maxAtomicCounterBufferSize << "\n" + << "MaxTransformFeedbackBuffers " << DefaultTBuiltInResource.maxTransformFeedbackBuffers << "\n" + << "MaxTransformFeedbackInterleavedComponents " << DefaultTBuiltInResource.maxTransformFeedbackInterleavedComponents << "\n" + << "MaxCullDistances " << DefaultTBuiltInResource.maxCullDistances << "\n" + << "MaxCombinedClipAndCullDistances " << DefaultTBuiltInResource.maxCombinedClipAndCullDistances << "\n" + << "MaxSamples " << DefaultTBuiltInResource.maxSamples << "\n" + + << "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n" + << "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n" + << "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n" + << "generalUniformIndexing " << DefaultTBuiltInResource.limits.generalUniformIndexing << "\n" + << "generalAttributeMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalAttributeMatrixVectorIndexing << "\n" + << "generalVaryingIndexing " << DefaultTBuiltInResource.limits.generalVaryingIndexing << "\n" + << "generalSamplerIndexing " << DefaultTBuiltInResource.limits.generalSamplerIndexing << "\n" + << "generalVariableIndexing " << DefaultTBuiltInResource.limits.generalVariableIndexing << "\n" + << "generalConstantMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalConstantMatrixVectorIndexing << "\n" + ; + + return ostream.str(); +} + +} // end namespace glslang diff --git a/StandAlone/DefaultResourceLimits.h b/StandAlone/DefaultResourceLimits.h new file mode 100644 index 00000000..fa52a2a7 --- /dev/null +++ b/StandAlone/DefaultResourceLimits.h @@ -0,0 +1,54 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef _DEFAULT_RESOURCE_LIMITS_INCLUDED_ +#define _DEFAULT_RESOURCE_LIMITS_INCLUDED_ + +#include + +#include "glslang/Include/ResourceLimits.h" + +namespace glslang { + +// These are the default resources for TBuiltInResources, used for both +// - parsing this string for the case where the user didn't supply one, +// - dumping out a template for user construction of a config file. +extern const TBuiltInResource DefaultTBuiltInResource; + +// Returns the DefaultTBuiltInResource as a human-readable string. +std::string GetDefaultTBuiltInResourceString(); + +} // end namespace glslang + +#endif // _DEFAULT_RESOURCE_LIMITS_INCLUDED_ diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 2e0db6d4..2f5a7180 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -37,6 +37,7 @@ // this only applies to the standalone wrapper, not the front end in general #define _CRT_SECURE_NO_WARNINGS +#include "DefaultResourceLimits.h" #include "Worklist.h" #include "./../glslang/Include/ShHandle.h" #include "./../glslang/Include/revision.h" @@ -112,108 +113,7 @@ TBuiltInResource Resources; std::string ConfigFile; // -// These are the default resources for TBuiltInResources, used for both -// - parsing this string for the case where the user didn't supply one -// - dumping out a template for user construction of a config file -// -const char* DefaultConfig = - "MaxLights 32\n" - "MaxClipPlanes 6\n" - "MaxTextureUnits 32\n" - "MaxTextureCoords 32\n" - "MaxVertexAttribs 64\n" - "MaxVertexUniformComponents 4096\n" - "MaxVaryingFloats 64\n" - "MaxVertexTextureImageUnits 32\n" - "MaxCombinedTextureImageUnits 80\n" - "MaxTextureImageUnits 32\n" - "MaxFragmentUniformComponents 4096\n" - "MaxDrawBuffers 32\n" - "MaxVertexUniformVectors 128\n" - "MaxVaryingVectors 8\n" - "MaxFragmentUniformVectors 16\n" - "MaxVertexOutputVectors 16\n" - "MaxFragmentInputVectors 15\n" - "MinProgramTexelOffset -8\n" - "MaxProgramTexelOffset 7\n" - "MaxClipDistances 8\n" - "MaxComputeWorkGroupCountX 65535\n" - "MaxComputeWorkGroupCountY 65535\n" - "MaxComputeWorkGroupCountZ 65535\n" - "MaxComputeWorkGroupSizeX 1024\n" - "MaxComputeWorkGroupSizeY 1024\n" - "MaxComputeWorkGroupSizeZ 64\n" - "MaxComputeUniformComponents 1024\n" - "MaxComputeTextureImageUnits 16\n" - "MaxComputeImageUniforms 8\n" - "MaxComputeAtomicCounters 8\n" - "MaxComputeAtomicCounterBuffers 1\n" - "MaxVaryingComponents 60\n" - "MaxVertexOutputComponents 64\n" - "MaxGeometryInputComponents 64\n" - "MaxGeometryOutputComponents 128\n" - "MaxFragmentInputComponents 128\n" - "MaxImageUnits 8\n" - "MaxCombinedImageUnitsAndFragmentOutputs 8\n" - "MaxCombinedShaderOutputResources 8\n" - "MaxImageSamples 0\n" - "MaxVertexImageUniforms 0\n" - "MaxTessControlImageUniforms 0\n" - "MaxTessEvaluationImageUniforms 0\n" - "MaxGeometryImageUniforms 0\n" - "MaxFragmentImageUniforms 8\n" - "MaxCombinedImageUniforms 8\n" - "MaxGeometryTextureImageUnits 16\n" - "MaxGeometryOutputVertices 256\n" - "MaxGeometryTotalOutputComponents 1024\n" - "MaxGeometryUniformComponents 1024\n" - "MaxGeometryVaryingComponents 64\n" - "MaxTessControlInputComponents 128\n" - "MaxTessControlOutputComponents 128\n" - "MaxTessControlTextureImageUnits 16\n" - "MaxTessControlUniformComponents 1024\n" - "MaxTessControlTotalOutputComponents 4096\n" - "MaxTessEvaluationInputComponents 128\n" - "MaxTessEvaluationOutputComponents 128\n" - "MaxTessEvaluationTextureImageUnits 16\n" - "MaxTessEvaluationUniformComponents 1024\n" - "MaxTessPatchComponents 120\n" - "MaxPatchVertices 32\n" - "MaxTessGenLevel 64\n" - "MaxViewports 16\n" - "MaxVertexAtomicCounters 0\n" - "MaxTessControlAtomicCounters 0\n" - "MaxTessEvaluationAtomicCounters 0\n" - "MaxGeometryAtomicCounters 0\n" - "MaxFragmentAtomicCounters 8\n" - "MaxCombinedAtomicCounters 8\n" - "MaxAtomicCounterBindings 1\n" - "MaxVertexAtomicCounterBuffers 0\n" - "MaxTessControlAtomicCounterBuffers 0\n" - "MaxTessEvaluationAtomicCounterBuffers 0\n" - "MaxGeometryAtomicCounterBuffers 0\n" - "MaxFragmentAtomicCounterBuffers 1\n" - "MaxCombinedAtomicCounterBuffers 1\n" - "MaxAtomicCounterBufferSize 16384\n" - "MaxTransformFeedbackBuffers 4\n" - "MaxTransformFeedbackInterleavedComponents 64\n" - "MaxCullDistances 8\n" - "MaxCombinedClipAndCullDistances 8\n" - "MaxSamples 4\n" - - "nonInductiveForLoops 1\n" - "whileLoops 1\n" - "doWhileLoops 1\n" - "generalUniformIndexing 1\n" - "generalAttributeMatrixVectorIndexing 1\n" - "generalVaryingIndexing 1\n" - "generalSamplerIndexing 1\n" - "generalVariableIndexing 1\n" - "generalConstantMatrixVectorIndexing 1\n" - ; - -// -// Parse either a .conf file provided by the user or the default string above. +// Parse either a .conf file provided by the user or the default from glslang::DefaultTBuiltInResource // void ProcessConfigFile() { @@ -230,8 +130,8 @@ void ProcessConfigFile() } if (config == 0) { - config = new char[strlen(DefaultConfig) + 1]; - strcpy(config, DefaultConfig); + Resources = glslang::DefaultTBuiltInResource; + return; } const char* delims = " \t\n\r"; @@ -718,8 +618,9 @@ void CompileAndLinkShaderUnits(std::vector compUnits) if (Options & EOptionOutputPreprocessed) { std::string str; + glslang::TShader::ForbidInclude includer; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, - messages, &str, glslang::TShader::ForbidInclude())) { + messages, &str, includer)) { PutsIfNonEmpty(str.c_str()); } else { CompileFailed = true; @@ -854,7 +755,7 @@ int C_DECL main(int argc, char* argv[]) ProcessArguments(argc, argv); if (Options & EOptionDumpConfig) { - printf("%s", DefaultConfig); + printf("%s", glslang::GetDefaultTBuiltInResourceString().c_str()); if (Worklist.empty()) return ESuccess; } diff --git a/Test/baseResults/150.geom.out b/Test/baseResults/150.geom.out index aa00868d..48b7925f 100644 --- a/Test/baseResults/150.geom.out +++ b/Test/baseResults/150.geom.out @@ -215,9 +215,9 @@ ERROR: node is still EOpNull! 0:33 Constant: 0:33 3 (const int) 0:33 direct index (temp float ClipDistance) -0:33 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:33 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:33 Constant: 0:33 1 (const int) 0:33 Constant: @@ -230,8 +230,8 @@ ERROR: node is still EOpNull! 0:34 Constant: 0:34 0 (const uint) 0:34 gl_Position: direct index for structure (in 4-component vector of float Position) -0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:34 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:34 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:34 Constant: 0:34 0 (const int) 0:34 Constant: @@ -242,8 +242,8 @@ ERROR: node is still EOpNull! 0:35 Constant: 0:35 1 (const uint) 0:35 gl_PointSize: direct index for structure (in float PointSize) -0:35 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:35 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:35 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:35 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:35 Constant: 0:35 3 (const int) 0:35 Constant: @@ -293,7 +293,7 @@ ERROR: node is still EOpNull! 0:? 'toF' (layout(stream=0 ) out block{layout(stream=0 ) out 3-component vector of float color}) 0:? 'anon@0' (layout(stream=0 ) out block{layout(stream=0 ) out 3-component vector of float color}) 0:? 'anon@1' (layout(stream=0 ) out block{layout(stream=0 ) gl_Position 4-component vector of float Position gl_Position, layout(stream=0 ) gl_PointSize float PointSize gl_PointSize, layout(stream=0 ) out 4-element array of float ClipDistance gl_ClipDistance}) -0:? 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_in' (in 4-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:? 'ov0' (layout(stream=0 ) out 4-component vector of float) 0:? 'ov4' (layout(stream=4 ) out 4-component vector of float) 0:? 'o1v0' (layout(stream=0 ) out 4-component vector of float) diff --git a/Test/baseResults/150.tesc.out b/Test/baseResults/150.tesc.out index a5289c93..8b7ab7dc 100644 --- a/Test/baseResults/150.tesc.out +++ b/Test/baseResults/150.tesc.out @@ -932,8 +932,8 @@ vertices = 4 0:20 move second child to first child (temp 4-component vector of float) 0:20 'p' (temp 4-component vector of float) 0:20 gl_Position: direct index for structure (in 4-component vector of float Position) -0:20 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:20 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:20 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:20 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:20 Constant: 0:20 1 (const int) 0:20 Constant: @@ -942,8 +942,8 @@ vertices = 4 0:21 move second child to first child (temp float) 0:21 'ps' (temp float) 0:21 gl_PointSize: direct index for structure (in float PointSize) -0:21 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:21 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:21 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:21 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:21 Constant: 0:21 1 (const int) 0:21 Constant: @@ -952,9 +952,9 @@ vertices = 4 0:22 move second child to first child (temp float) 0:22 'cd' (temp float) 0:22 direct index (temp float ClipDistance) -0:22 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:22 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:22 Constant: 0:22 1 (const int) 0:22 Constant: @@ -975,25 +975,25 @@ vertices = 4 0:26 'gl_InvocationID' (in int InvocationID) 0:28 move second child to first child (temp 4-component vector of float) 0:28 gl_Position: direct index for structure (out 4-component vector of float Position) -0:28 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:28 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:28 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:28 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:28 'gl_InvocationID' (in int InvocationID) 0:28 Constant: 0:28 0 (const int) 0:28 'p' (temp 4-component vector of float) 0:29 move second child to first child (temp float) 0:29 gl_PointSize: direct index for structure (out float PointSize) -0:29 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:29 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:29 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:29 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:29 'gl_InvocationID' (in int InvocationID) 0:29 Constant: 0:29 1 (const int) 0:29 'ps' (temp float) 0:30 move second child to first child (temp float) 0:30 direct index (temp float ClipDistance) -0:30 gl_ClipDistance: direct index for structure (out 1-element array of float ClipDistance) -0:30 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:30 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:30 gl_ClipDistance: direct index for structure (out 2-element array of float ClipDistance) +0:30 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:30 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:30 'gl_InvocationID' (in int InvocationID) 0:30 Constant: 0:30 2 (const int) @@ -1027,8 +1027,8 @@ vertices = 4 0:23 move second child to first child (temp 4-component vector of float) 0:23 'p' (temp 4-component vector of float) 0:23 gl_Position: direct index for structure (in 4-component vector of float Position) -0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:23 Constant: 0:23 1 (const int) 0:23 Constant: @@ -1037,8 +1037,8 @@ vertices = 4 0:24 move second child to first child (temp float) 0:24 'ps' (temp float) 0:24 gl_PointSize: direct index for structure (in float PointSize) -0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:24 Constant: 0:24 1 (const int) 0:24 Constant: @@ -1047,9 +1047,9 @@ vertices = 4 0:25 move second child to first child (temp float) 0:25 'cd' (temp float) 0:25 direct index (temp float ClipDistance) -0:25 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:25 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:25 Constant: 0:25 1 (const int) 0:25 Constant: @@ -1070,25 +1070,25 @@ vertices = 4 0:29 'gl_InvocationID' (in int InvocationID) 0:31 move second child to first child (temp 4-component vector of float) 0:31 gl_Position: direct index for structure (out 4-component vector of float Position) -0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:31 'gl_InvocationID' (in int InvocationID) 0:31 Constant: 0:31 0 (const int) 0:31 'p' (temp 4-component vector of float) 0:32 move second child to first child (temp float) 0:32 gl_PointSize: direct index for structure (out float PointSize) -0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:32 'gl_InvocationID' (in int InvocationID) 0:32 Constant: 0:32 1 (const int) 0:32 'ps' (temp float) 0:33 move second child to first child (temp float) 0:33 direct index (temp float ClipDistance) -0:33 gl_ClipDistance: direct index for structure (out 1-element array of float ClipDistance) -0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:33 gl_ClipDistance: direct index for structure (out 2-element array of float ClipDistance) +0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:33 'gl_InvocationID' (in int InvocationID) 0:33 Constant: 0:33 2 (const int) @@ -1158,8 +1158,8 @@ vertices = 4 0:67 Function Parameters: 0:69 Sequence 0:69 gl_PointSize: direct index for structure (out float PointSize) -0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:69 Constant: 0:69 4 (const int) 0:69 Constant: @@ -1192,8 +1192,8 @@ vertices = 4 0:17 move second child to first child (temp 4-component vector of float) 0:17 'p' (temp 4-component vector of float) 0:17 gl_Position: direct index for structure (in 4-component vector of float Position) -0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:17 Constant: 0:17 1 (const int) 0:17 Constant: @@ -1202,8 +1202,8 @@ vertices = 4 0:18 move second child to first child (temp float) 0:18 'ps' (temp float) 0:18 gl_PointSize: direct index for structure (in float PointSize) -0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:18 Constant: 0:18 1 (const int) 0:18 Constant: @@ -1212,9 +1212,9 @@ vertices = 4 0:19 move second child to first child (temp float) 0:19 'cd' (temp float) 0:19 direct index (temp float ClipDistance) -0:19 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:19 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:19 Constant: 0:19 1 (const int) 0:19 Constant: @@ -1280,7 +1280,7 @@ vertices = 4 0:37 0 (const int) 0:36 true case is null 0:? Linker Objects -0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:? 'outa' (global 4-element array of int) 0:? 'patchOut' (patch out 4-component vector of float) 0:? 'patchIn' (patch in 4-component vector of float) @@ -1324,8 +1324,8 @@ ERROR: node is still EOpNull! 0:22 move second child to first child (temp 4-component vector of float) 0:22 'p' (temp 4-component vector of float) 0:22 gl_Position: direct index for structure (in 4-component vector of float Position) -0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:22 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:22 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:22 Constant: 0:22 1 (const int) 0:22 Constant: @@ -1334,8 +1334,8 @@ ERROR: node is still EOpNull! 0:23 move second child to first child (temp float) 0:23 'ps' (temp float) 0:23 gl_PointSize: direct index for structure (in float PointSize) -0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:23 Constant: 0:23 1 (const int) 0:23 Constant: @@ -1344,9 +1344,9 @@ ERROR: node is still EOpNull! 0:24 move second child to first child (temp float) 0:24 'cd' (temp float) 0:24 direct index (temp float ClipDistance) -0:24 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:24 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:24 Constant: 0:24 1 (const int) 0:24 Constant: @@ -1414,8 +1414,8 @@ ERROR: node is still EOpNull! 0:32 move second child to first child (temp 4-component vector of float) 0:32 'p' (temp 4-component vector of float) 0:32 gl_Position: direct index for structure (in 4-component vector of float Position) -0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:32 Constant: 0:32 1 (const int) 0:32 Constant: @@ -1424,8 +1424,8 @@ ERROR: node is still EOpNull! 0:33 move second child to first child (temp float) 0:33 'ps' (temp float) 0:33 gl_PointSize: direct index for structure (in float PointSize) -0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:33 Constant: 0:33 1 (const int) 0:33 Constant: @@ -1434,9 +1434,9 @@ ERROR: node is still EOpNull! 0:34 move second child to first child (temp float) 0:34 'cd' (temp float) 0:34 direct index (temp float ClipDistance) -0:34 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:34 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:34 Constant: 0:34 1 (const int) 0:34 Constant: @@ -1572,7 +1572,7 @@ ERROR: node is still EOpNull! 0:? 'badp2' (flat patch in 4-component vector of float) 0:? 'badp3' (noperspective patch in 4-component vector of float) 0:? 'badp4' (patch sample in 3-component vector of float) -0:? 'gl_in' (in 32-element array of block{in 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float ClipDistance gl_ClipDistance}) 0:? 'ina' (in 2-component vector of float) 0:? 'inb' (in 32-element array of 2-component vector of float) 0:? 'inc' (in 32-element array of 2-component vector of float) diff --git a/Test/baseResults/310.comp.out b/Test/baseResults/310.comp.out index ff438e3a..d6b03322 100644 --- a/Test/baseResults/310.comp.out +++ b/Test/baseResults/310.comp.out @@ -337,7 +337,7 @@ ERROR: node is still EOpNull! 0:201 1 (const int) 0:201 Constant: 0:201 2 (const int) -0:202 Test condition and select (layout(column_major shared ) temp highp float) +0:202 Test condition and select (temp highp float) 0:202 Condition 0:202 'b' (temp bool) 0:202 true case @@ -764,7 +764,7 @@ ERROR: node is still EOpNull! 0:201 1 (const int) 0:201 Constant: 0:201 2 (const int) -0:202 Test condition and select (layout(column_major shared ) temp highp float) +0:202 Test condition and select (temp highp float) 0:202 Condition 0:202 'b' (temp bool) 0:202 true case diff --git a/Test/baseResults/400.tesc.out b/Test/baseResults/400.tesc.out index 6a0b895a..99867ca5 100644 --- a/Test/baseResults/400.tesc.out +++ b/Test/baseResults/400.tesc.out @@ -233,8 +233,8 @@ ERROR: node is still EOpNull! 0:23 move second child to first child (temp 4-component vector of float) 0:23 'p' (temp 4-component vector of float) 0:23 gl_Position: direct index for structure (in 4-component vector of float Position) -0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:23 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:23 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:23 Constant: 0:23 1 (const int) 0:23 Constant: @@ -243,8 +243,8 @@ ERROR: node is still EOpNull! 0:24 move second child to first child (temp float) 0:24 'ps' (temp float) 0:24 gl_PointSize: direct index for structure (in float PointSize) -0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:24 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:24 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:24 Constant: 0:24 1 (const int) 0:24 Constant: @@ -253,9 +253,9 @@ ERROR: node is still EOpNull! 0:25 move second child to first child (temp float) 0:25 'cd' (temp float) 0:25 direct index (temp float ClipDistance) -0:25 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:25 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:25 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:25 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:25 Constant: 0:25 1 (const int) 0:25 Constant: @@ -276,25 +276,25 @@ ERROR: node is still EOpNull! 0:29 'gl_InvocationID' (in int InvocationID) 0:31 move second child to first child (temp 4-component vector of float) 0:31 gl_Position: direct index for structure (out 4-component vector of float Position) -0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:31 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:31 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:31 'gl_InvocationID' (in int InvocationID) 0:31 Constant: 0:31 0 (const int) 0:31 'p' (temp 4-component vector of float) 0:32 move second child to first child (temp float) 0:32 gl_PointSize: direct index for structure (out float PointSize) -0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:32 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:32 'gl_InvocationID' (in int InvocationID) 0:32 Constant: 0:32 1 (const int) 0:32 'ps' (temp float) 0:33 move second child to first child (temp float) 0:33 direct index (temp float ClipDistance) -0:33 gl_ClipDistance: direct index for structure (out 1-element array of float ClipDistance) -0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:33 gl_ClipDistance: direct index for structure (out 2-element array of float ClipDistance) +0:33 indirect index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:33 'gl_InvocationID' (in int InvocationID) 0:33 Constant: 0:33 2 (const int) @@ -364,8 +364,8 @@ ERROR: node is still EOpNull! 0:67 Function Parameters: 0:69 Sequence 0:69 gl_PointSize: direct index for structure (out float PointSize) -0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) -0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:69 direct index (temp block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) +0:69 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:69 Constant: 0:69 4 (const int) 0:69 Constant: @@ -390,7 +390,7 @@ ERROR: node is still EOpNull! 0:97 'd' (temp double) 0:97 'd' (temp double) 0:? Linker Objects -0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_out' (out 4-element array of block{out 4-component vector of float Position gl_Position, out float PointSize gl_PointSize, out 2-element array of float ClipDistance gl_ClipDistance}) 0:? 'outa' (global 4-element array of int) 0:? 'patchIn' (patch in 4-component vector of float) 0:? 'patchOut' (patch out 4-component vector of float) diff --git a/Test/baseResults/400.tese.out b/Test/baseResults/400.tese.out index 55670f87..76883aa7 100644 --- a/Test/baseResults/400.tese.out +++ b/Test/baseResults/400.tese.out @@ -179,8 +179,8 @@ ERROR: node is still EOpNull! 0:32 move second child to first child (temp 4-component vector of float) 0:32 'p' (temp 4-component vector of float) 0:32 gl_Position: direct index for structure (in 4-component vector of float Position) -0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:32 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:32 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:32 Constant: 0:32 1 (const int) 0:32 Constant: @@ -189,8 +189,8 @@ ERROR: node is still EOpNull! 0:33 move second child to first child (temp float) 0:33 'ps' (temp float) 0:33 gl_PointSize: direct index for structure (in float PointSize) -0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:33 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:33 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:33 Constant: 0:33 1 (const int) 0:33 Constant: @@ -199,9 +199,9 @@ ERROR: node is still EOpNull! 0:34 move second child to first child (temp float) 0:34 'cd' (temp float) 0:34 direct index (temp float ClipDistance) -0:34 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:34 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:34 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:34 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:34 Constant: 0:34 1 (const int) 0:34 Constant: @@ -263,7 +263,7 @@ ERROR: node is still EOpNull! 0:? 'badp2' (flat patch in 4-component vector of float) 0:? 'badp3' (noperspective patch in 4-component vector of float) 0:? 'badp4' (patch sample in 3-component vector of float) -0:? 'gl_in' (in 32-element array of block{in 1-element array of float ClipDistance gl_ClipDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float ClipDistance gl_ClipDistance}) 0:? 'ina' (in 2-component vector of float) 0:? 'inb' (in 32-element array of 2-component vector of float) 0:? 'inc' (in 32-element array of 2-component vector of float) diff --git a/Test/baseResults/420.tesc.out b/Test/baseResults/420.tesc.out index db65fd99..594e1302 100644 --- a/Test/baseResults/420.tesc.out +++ b/Test/baseResults/420.tesc.out @@ -132,8 +132,8 @@ ERROR: node is still EOpNull! 0:17 move second child to first child (temp 4-component vector of float) 0:17 'p' (temp 4-component vector of float) 0:17 gl_Position: direct index for structure (in 4-component vector of float Position) -0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:17 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:17 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:17 Constant: 0:17 1 (const int) 0:17 Constant: @@ -142,8 +142,8 @@ ERROR: node is still EOpNull! 0:18 move second child to first child (temp float) 0:18 'ps' (temp float) 0:18 gl_PointSize: direct index for structure (in float PointSize) -0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:18 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:18 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:18 Constant: 0:18 1 (const int) 0:18 Constant: @@ -152,9 +152,9 @@ ERROR: node is still EOpNull! 0:19 move second child to first child (temp float) 0:19 'cd' (temp float) 0:19 direct index (temp float ClipDistance) -0:19 gl_ClipDistance: direct index for structure (in 1-element array of float ClipDistance) -0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) -0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 1-element array of float ClipDistance gl_ClipDistance}) +0:19 gl_ClipDistance: direct index for structure (in 3-element array of float ClipDistance) +0:19 direct index (temp block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) +0:19 'gl_in' (in 32-element array of block{in 4-component vector of float Position gl_Position, in float PointSize gl_PointSize, in 3-element array of float ClipDistance gl_ClipDistance}) 0:19 Constant: 0:19 1 (const int) 0:19 Constant: diff --git a/Test/baseResults/450.geom.out b/Test/baseResults/450.geom.out index fd98d088..1579e18d 100644 --- a/Test/baseResults/450.geom.out +++ b/Test/baseResults/450.geom.out @@ -57,9 +57,9 @@ output primitive = none 0:13 Constant: 0:13 2 (const int) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (in 1-element array of float CullDistance) -0:13 direct index (temp block{in 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_in' (in 2-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (in 3-element array of float CullDistance) +0:13 direct index (temp block{in 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_in' (in 2-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:13 Constant: 0:13 1 (const int) 0:13 Constant: @@ -67,6 +67,6 @@ output primitive = none 0:13 Constant: 0:13 2 (const int) 0:? Linker Objects -0:? 'gl_in' (in 2-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:? 'gl_in' (in 2-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:? 'anon@0' (layout(stream=0 ) out block{layout(stream=0 ) out 3-element array of float CullDistance gl_CullDistance}) diff --git a/Test/baseResults/450.tesc.out b/Test/baseResults/450.tesc.out index 8a8e9fbf..66cd5c26 100644 --- a/Test/baseResults/450.tesc.out +++ b/Test/baseResults/450.tesc.out @@ -44,18 +44,18 @@ vertices = -1 0:13 Sequence 0:13 move second child to first child (temp float) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (out 1-element array of float CullDistance) -0:13 indirect index (temp block{out 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_out' (out 4-element array of block{out 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (out 3-element array of float CullDistance) +0:13 indirect index (temp block{out 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_out' (out 4-element array of block{out 3-element array of float CullDistance gl_CullDistance}) 0:13 'gl_InvocationID' (in int InvocationID) 0:13 Constant: 0:13 0 (const int) 0:13 Constant: 0:13 2 (const int) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (in 1-element array of float CullDistance) -0:13 direct index (temp block{in 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (in 3-element array of float CullDistance) +0:13 direct index (temp block{in 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:13 Constant: 0:13 1 (const int) 0:13 Constant: @@ -63,6 +63,6 @@ vertices = -1 0:13 Constant: 0:13 2 (const int) 0:? Linker Objects -0:? 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) -0:? 'gl_out' (out 4-element array of block{out 1-element array of float CullDistance gl_CullDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) +0:? 'gl_out' (out 4-element array of block{out 3-element array of float CullDistance gl_CullDistance}) diff --git a/Test/baseResults/450.tese.out b/Test/baseResults/450.tese.out index c6e97b8d..a1116b40 100644 --- a/Test/baseResults/450.tese.out +++ b/Test/baseResults/450.tese.out @@ -53,9 +53,9 @@ triangle order = ccw 0:13 Constant: 0:13 2 (const int) 0:13 direct index (temp float CullDistance) -0:13 gl_CullDistance: direct index for structure (in 1-element array of float CullDistance) -0:13 direct index (temp block{in 1-element array of float CullDistance gl_CullDistance}) -0:13 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:13 gl_CullDistance: direct index for structure (in 3-element array of float CullDistance) +0:13 direct index (temp block{in 3-element array of float CullDistance gl_CullDistance}) +0:13 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:13 Constant: 0:13 1 (const int) 0:13 Constant: @@ -63,6 +63,6 @@ triangle order = ccw 0:13 Constant: 0:13 2 (const int) 0:? Linker Objects -0:? 'gl_in' (in 32-element array of block{in 1-element array of float CullDistance gl_CullDistance}) +0:? 'gl_in' (in 32-element array of block{in 3-element array of float CullDistance gl_CullDistance}) 0:? 'anon@0' (out block{out 3-element array of float CullDistance gl_CullDistance}) diff --git a/Test/baseResults/spv.330.geom.out b/Test/baseResults/spv.330.geom.out old mode 100755 new mode 100644 diff --git a/Test/baseResults/spv.400.frag.out b/Test/baseResults/spv.400.frag.out index a851500c..651d67de 100644 --- a/Test/baseResults/spv.400.frag.out +++ b/Test/baseResults/spv.400.frag.out @@ -7,7 +7,7 @@ Linked fragment stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 1104 +// Id's are bound by 1112 Capability Shader Capability Float64 @@ -15,7 +15,7 @@ Linked fragment stage: Capability SampledRect 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Fragment 4 "main" 13 1025 1031 1036 1048 1074 1095 1097 + EntryPoint Fragment 4 "main" 13 1025 1031 1036 1048 1074 1095 1097 1103 1105 ExecutionMode 4 OriginUpperLeft Source GLSL 400 SourceExtension "GL_ARB_separate_shader_objects" @@ -52,6 +52,8 @@ Linked fragment stage: Name 1078 "isamp2DA" Name 1095 "gl_FragCoord" Name 1097 "vl2" + Name 1103 "uo" + Name 1105 "u" Decorate 17(u2drs) DescriptorSet 0 Decorate 1023(arrayedSampler) DescriptorSet 0 Decorate 1025(i) Flat @@ -60,6 +62,7 @@ Linked fragment stage: Decorate 1078(isamp2DA) DescriptorSet 0 Decorate 1095(gl_FragCoord) BuiltIn FragCoord Decorate 1097(vl2) Location 6 + Decorate 1105(u) Flat 2: TypeVoid 3: TypeFunction 2 10: TypeFloat 32 @@ -177,6 +180,10 @@ Linked fragment stage: 1094: TypePointer Input 11(fvec4) 1095(gl_FragCoord): 1094(ptr) Variable Input 1097(vl2): 1094(ptr) Variable Input + 1102: TypePointer Output 30(int) + 1103(uo): 1102(ptr) Variable Output + 1104: TypePointer Input 30(int) + 1105(u): 1104(ptr) Variable Input 4(main): 2 Function None 3 5: Label 1017(v): 1016(ptr) Variable Function @@ -227,8 +234,13 @@ Linked fragment stage: 1100: 11(fvec4) Load 13(outp) 1101: 11(fvec4) FAdd 1100 1099 Store 13(outp) 1101 - 1102: 2 FunctionCall 6(foo23() - 1103: 2 FunctionCall 8(doubles() + 1106: 30(int) Load 1105(u) + 1107: 23(int) Load 1025(i) + 1108: 30(int) Bitcast 1107 + 1109: 30(int) UMod 1106 1108 + Store 1103(uo) 1109 + 1110: 2 FunctionCall 6(foo23() + 1111: 2 FunctionCall 8(doubles() Return FunctionEnd 6(foo23(): 2 Function None 3 @@ -719,28 +731,28 @@ Linked fragment stage: 424: 37(float) Load 39(doublev) 425: 37(float) Load 39(doublev) 429: 426(bool) Load 428(boolv) - 430: 37(float) ExtInst 1(GLSL.std.450) 46(FMix) 424 425 429 + 430: 37(float) Select 429 425 424 431: 37(float) Load 39(doublev) 432: 37(float) FAdd 431 430 Store 39(doublev) 432 433: 41(fvec2) Load 43(dvec2v) 434: 41(fvec2) Load 43(dvec2v) 438: 435(bvec2) Load 437(bvec2v) - 439: 41(fvec2) ExtInst 1(GLSL.std.450) 46(FMix) 433 434 438 + 439: 41(fvec2) Select 438 434 433 440: 41(fvec2) Load 43(dvec2v) 441: 41(fvec2) FAdd 440 439 Store 43(dvec2v) 441 442: 46(fvec3) Load 48(dvec3v) 443: 46(fvec3) Load 48(dvec3v) 447: 444(bvec3) Load 446(bvec3v) - 448: 46(fvec3) ExtInst 1(GLSL.std.450) 46(FMix) 442 443 447 + 448: 46(fvec3) Select 447 443 442 449: 46(fvec3) Load 48(dvec3v) 450: 46(fvec3) FAdd 449 448 Store 48(dvec3v) 450 451: 51(fvec4) Load 53(dvec4v) 452: 51(fvec4) Load 53(dvec4v) 456: 453(bvec4) Load 455(bvec4v) - 457: 51(fvec4) ExtInst 1(GLSL.std.450) 46(FMix) 451 452 456 + 457: 51(fvec4) Select 456 452 451 458: 51(fvec4) Load 53(dvec4v) 459: 51(fvec4) FAdd 458 457 Store 53(dvec4v) 459 diff --git a/Test/baseResults/spv.400.tesc.out b/Test/baseResults/spv.400.tesc.out index eea07ce7..290a19cd 100755 --- a/Test/baseResults/spv.400.tesc.out +++ b/Test/baseResults/spv.400.tesc.out @@ -7,68 +7,68 @@ Linked tessellation control stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 93 +// Id's are bound by 94 Capability Tessellation Capability TessellationPointSize Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint TessellationControl 4 "main" 23 40 43 46 52 66 73 79 83 84 87 88 91 92 + EntryPoint TessellationControl 4 "main" 24 41 44 47 55 69 74 80 84 85 88 89 92 93 ExecutionMode 4 OutputVertices 4 Source GLSL 400 SourceExtension "GL_ARB_separate_shader_objects" Name 4 "main" Name 12 "a" Name 17 "p" - Name 19 "gl_PerVertex" - MemberName 19(gl_PerVertex) 0 "gl_Position" - MemberName 19(gl_PerVertex) 1 "gl_PointSize" - MemberName 19(gl_PerVertex) 2 "gl_ClipDistance" - Name 23 "gl_in" - Name 30 "ps" - Name 34 "cd" - Name 38 "pvi" - Name 40 "gl_PatchVerticesIn" - Name 42 "pid" - Name 43 "gl_PrimitiveID" - Name 45 "iid" - Name 46 "gl_InvocationID" - Name 48 "gl_PerVertex" - MemberName 48(gl_PerVertex) 0 "gl_Position" - MemberName 48(gl_PerVertex) 1 "gl_PointSize" - MemberName 48(gl_PerVertex) 2 "gl_ClipDistance" - Name 52 "gl_out" - Name 66 "gl_TessLevelOuter" - Name 73 "gl_TessLevelInner" - Name 78 "outa" - Name 79 "patchOut" - Name 83 "inb" - Name 84 "ind" - Name 87 "ivla" - Name 88 "ivlb" - Name 91 "ovla" - Name 92 "ovlb" - MemberDecorate 19(gl_PerVertex) 0 BuiltIn Position - MemberDecorate 19(gl_PerVertex) 1 BuiltIn PointSize - MemberDecorate 19(gl_PerVertex) 2 BuiltIn ClipDistance - Decorate 19(gl_PerVertex) Block - Decorate 40(gl_PatchVerticesIn) BuiltIn PatchVertices - Decorate 43(gl_PrimitiveID) BuiltIn PrimitiveId - Decorate 46(gl_InvocationID) BuiltIn InvocationId - MemberDecorate 48(gl_PerVertex) 0 BuiltIn Position - MemberDecorate 48(gl_PerVertex) 1 BuiltIn PointSize - MemberDecorate 48(gl_PerVertex) 2 BuiltIn ClipDistance - Decorate 48(gl_PerVertex) Block - Decorate 66(gl_TessLevelOuter) Patch - Decorate 66(gl_TessLevelOuter) BuiltIn TessLevelOuter - Decorate 73(gl_TessLevelInner) Patch - Decorate 73(gl_TessLevelInner) BuiltIn TessLevelInner - Decorate 79(patchOut) Patch - Decorate 87(ivla) Location 3 - Decorate 88(ivlb) Location 4 - Decorate 91(ovla) Location 3 - Decorate 92(ovlb) Location 4 + Name 20 "gl_PerVertex" + MemberName 20(gl_PerVertex) 0 "gl_Position" + MemberName 20(gl_PerVertex) 1 "gl_PointSize" + MemberName 20(gl_PerVertex) 2 "gl_ClipDistance" + Name 24 "gl_in" + Name 31 "ps" + Name 35 "cd" + Name 39 "pvi" + Name 41 "gl_PatchVerticesIn" + Name 43 "pid" + Name 44 "gl_PrimitiveID" + Name 46 "iid" + Name 47 "gl_InvocationID" + Name 51 "gl_PerVertex" + MemberName 51(gl_PerVertex) 0 "gl_Position" + MemberName 51(gl_PerVertex) 1 "gl_PointSize" + MemberName 51(gl_PerVertex) 2 "gl_ClipDistance" + Name 55 "gl_out" + Name 69 "gl_TessLevelOuter" + Name 74 "gl_TessLevelInner" + Name 79 "outa" + Name 80 "patchOut" + Name 84 "inb" + Name 85 "ind" + Name 88 "ivla" + Name 89 "ivlb" + Name 92 "ovla" + Name 93 "ovlb" + MemberDecorate 20(gl_PerVertex) 0 BuiltIn Position + MemberDecorate 20(gl_PerVertex) 1 BuiltIn PointSize + MemberDecorate 20(gl_PerVertex) 2 BuiltIn ClipDistance + Decorate 20(gl_PerVertex) Block + Decorate 41(gl_PatchVerticesIn) BuiltIn PatchVertices + Decorate 44(gl_PrimitiveID) BuiltIn PrimitiveId + Decorate 47(gl_InvocationID) BuiltIn InvocationId + MemberDecorate 51(gl_PerVertex) 0 BuiltIn Position + MemberDecorate 51(gl_PerVertex) 1 BuiltIn PointSize + MemberDecorate 51(gl_PerVertex) 2 BuiltIn ClipDistance + Decorate 51(gl_PerVertex) Block + Decorate 69(gl_TessLevelOuter) Patch + Decorate 69(gl_TessLevelOuter) BuiltIn TessLevelOuter + Decorate 74(gl_TessLevelInner) Patch + Decorate 74(gl_TessLevelInner) BuiltIn TessLevelInner + Decorate 80(patchOut) Patch + Decorate 88(ivla) Location 3 + Decorate 89(ivlb) Location 4 + Decorate 92(ovla) Location 3 + Decorate 93(ovlb) Location 4 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 0 @@ -81,98 +81,99 @@ Linked tessellation control stage: 14: TypeFloat 32 15: TypeVector 14(float) 4 16: TypePointer Function 15(fvec4) - 18: TypeArray 14(float) 7 -19(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 18 - 20: 6(int) Constant 32 - 21: TypeArray 19(gl_PerVertex) 20 - 22: TypePointer Input 21 - 23(gl_in): 22(ptr) Variable Input - 24: 10(int) Constant 1 - 25: 10(int) Constant 0 - 26: TypePointer Input 15(fvec4) - 29: TypePointer Function 14(float) - 31: TypePointer Input 14(float) - 35: 10(int) Constant 2 - 39: TypePointer Input 10(int) -40(gl_PatchVerticesIn): 39(ptr) Variable Input -43(gl_PrimitiveID): 39(ptr) Variable Input -46(gl_InvocationID): 39(ptr) Variable Input -48(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 18 - 49: 6(int) Constant 4 - 50: TypeArray 48(gl_PerVertex) 49 - 51: TypePointer Output 50 - 52(gl_out): 51(ptr) Variable Output - 55: TypePointer Output 15(fvec4) - 59: TypePointer Output 14(float) - 64: TypeArray 14(float) 49 - 65: TypePointer Output 64 -66(gl_TessLevelOuter): 65(ptr) Variable Output - 67: 10(int) Constant 3 - 68: 14(float) Constant 1078774989 - 70: 6(int) Constant 2 - 71: TypeArray 14(float) 70 - 72: TypePointer Output 71 -73(gl_TessLevelInner): 72(ptr) Variable Output - 74: 14(float) Constant 1067869798 - 76: TypeArray 10(int) 49 - 77: TypePointer Private 76 - 78(outa): 77(ptr) Variable Private - 79(patchOut): 55(ptr) Variable Output - 80: TypeVector 14(float) 2 - 81: TypeArray 80(fvec2) 20 - 82: TypePointer Input 81 - 83(inb): 82(ptr) Variable Input - 84(ind): 82(ptr) Variable Input - 85: TypeArray 15(fvec4) 20 - 86: TypePointer Input 85 - 87(ivla): 86(ptr) Variable Input - 88(ivlb): 86(ptr) Variable Input - 89: TypeArray 15(fvec4) 49 - 90: TypePointer Output 89 - 91(ovla): 90(ptr) Variable Output - 92(ovlb): 90(ptr) Variable Output + 18: 6(int) Constant 3 + 19: TypeArray 14(float) 18 +20(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 19 + 21: 6(int) Constant 32 + 22: TypeArray 20(gl_PerVertex) 21 + 23: TypePointer Input 22 + 24(gl_in): 23(ptr) Variable Input + 25: 10(int) Constant 1 + 26: 10(int) Constant 0 + 27: TypePointer Input 15(fvec4) + 30: TypePointer Function 14(float) + 32: TypePointer Input 14(float) + 36: 10(int) Constant 2 + 40: TypePointer Input 10(int) +41(gl_PatchVerticesIn): 40(ptr) Variable Input +44(gl_PrimitiveID): 40(ptr) Variable Input +47(gl_InvocationID): 40(ptr) Variable Input + 49: 6(int) Constant 2 + 50: TypeArray 14(float) 49 +51(gl_PerVertex): TypeStruct 15(fvec4) 14(float) 50 + 52: 6(int) Constant 4 + 53: TypeArray 51(gl_PerVertex) 52 + 54: TypePointer Output 53 + 55(gl_out): 54(ptr) Variable Output + 58: TypePointer Output 15(fvec4) + 62: TypePointer Output 14(float) + 67: TypeArray 14(float) 52 + 68: TypePointer Output 67 +69(gl_TessLevelOuter): 68(ptr) Variable Output + 70: 10(int) Constant 3 + 71: 14(float) Constant 1078774989 + 73: TypePointer Output 50 +74(gl_TessLevelInner): 73(ptr) Variable Output + 75: 14(float) Constant 1067869798 + 77: TypeArray 10(int) 52 + 78: TypePointer Private 77 + 79(outa): 78(ptr) Variable Private + 80(patchOut): 58(ptr) Variable Output + 81: TypeVector 14(float) 2 + 82: TypeArray 81(fvec2) 21 + 83: TypePointer Input 82 + 84(inb): 83(ptr) Variable Input + 85(ind): 83(ptr) Variable Input + 86: TypeArray 15(fvec4) 21 + 87: TypePointer Input 86 + 88(ivla): 87(ptr) Variable Input + 89(ivlb): 87(ptr) Variable Input + 90: TypeArray 15(fvec4) 52 + 91: TypePointer Output 90 + 92(ovla): 91(ptr) Variable Output + 93(ovlb): 91(ptr) Variable Output 4(main): 2 Function None 3 5: Label 12(a): 11(ptr) Variable Function 17(p): 16(ptr) Variable Function - 30(ps): 29(ptr) Variable Function - 34(cd): 29(ptr) Variable Function - 38(pvi): 11(ptr) Variable Function - 42(pid): 11(ptr) Variable Function - 45(iid): 11(ptr) Variable Function + 31(ps): 30(ptr) Variable Function + 35(cd): 30(ptr) Variable Function + 39(pvi): 11(ptr) Variable Function + 43(pid): 11(ptr) Variable Function + 46(iid): 11(ptr) Variable Function MemoryBarrier 7 8 ControlBarrier 7 7 9 Store 12(a) 13 - 27: 26(ptr) AccessChain 23(gl_in) 24 25 - 28: 15(fvec4) Load 27 - Store 17(p) 28 - 32: 31(ptr) AccessChain 23(gl_in) 24 24 - 33: 14(float) Load 32 - Store 30(ps) 33 - 36: 31(ptr) AccessChain 23(gl_in) 24 35 35 - 37: 14(float) Load 36 - Store 34(cd) 37 - 41: 10(int) Load 40(gl_PatchVerticesIn) - Store 38(pvi) 41 - 44: 10(int) Load 43(gl_PrimitiveID) - Store 42(pid) 44 - 47: 10(int) Load 46(gl_InvocationID) - Store 45(iid) 47 - 53: 10(int) Load 46(gl_InvocationID) - 54: 15(fvec4) Load 17(p) - 56: 55(ptr) AccessChain 52(gl_out) 53 25 - Store 56 54 - 57: 10(int) Load 46(gl_InvocationID) - 58: 14(float) Load 30(ps) - 60: 59(ptr) AccessChain 52(gl_out) 57 24 - Store 60 58 - 61: 10(int) Load 46(gl_InvocationID) - 62: 14(float) Load 34(cd) - 63: 59(ptr) AccessChain 52(gl_out) 61 35 24 - Store 63 62 - 69: 59(ptr) AccessChain 66(gl_TessLevelOuter) 67 - Store 69 68 - 75: 59(ptr) AccessChain 73(gl_TessLevelInner) 24 - Store 75 74 + 28: 27(ptr) AccessChain 24(gl_in) 25 26 + 29: 15(fvec4) Load 28 + Store 17(p) 29 + 33: 32(ptr) AccessChain 24(gl_in) 25 25 + 34: 14(float) Load 33 + Store 31(ps) 34 + 37: 32(ptr) AccessChain 24(gl_in) 25 36 36 + 38: 14(float) Load 37 + Store 35(cd) 38 + 42: 10(int) Load 41(gl_PatchVerticesIn) + Store 39(pvi) 42 + 45: 10(int) Load 44(gl_PrimitiveID) + Store 43(pid) 45 + 48: 10(int) Load 47(gl_InvocationID) + Store 46(iid) 48 + 56: 10(int) Load 47(gl_InvocationID) + 57: 15(fvec4) Load 17(p) + 59: 58(ptr) AccessChain 55(gl_out) 56 26 + Store 59 57 + 60: 10(int) Load 47(gl_InvocationID) + 61: 14(float) Load 31(ps) + 63: 62(ptr) AccessChain 55(gl_out) 60 25 + Store 63 61 + 64: 10(int) Load 47(gl_InvocationID) + 65: 14(float) Load 35(cd) + 66: 62(ptr) AccessChain 55(gl_out) 64 36 25 + Store 66 65 + 72: 62(ptr) AccessChain 69(gl_TessLevelOuter) 70 + Store 72 71 + 76: 62(ptr) AccessChain 74(gl_TessLevelInner) 25 + Store 76 75 Return FunctionEnd diff --git a/Test/baseResults/spv.400.tese.out b/Test/baseResults/spv.400.tese.out index 03e181ce..51534b12 100755 --- a/Test/baseResults/spv.400.tese.out +++ b/Test/baseResults/spv.400.tese.out @@ -7,14 +7,14 @@ Linked tessellation evaluation stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 98 +// Id's are bound by 96 Capability Tessellation Capability TessellationPointSize Capability ClipDistance 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint TessellationEvaluation 4 "main" 21 38 41 47 53 61 68 77 81 82 86 90 93 94 97 + EntryPoint TessellationEvaluation 4 "main" 21 38 41 47 53 61 66 75 79 80 84 88 91 92 95 ExecutionMode 4 Triangles ExecutionMode 4 SpacingFractionalOdd ExecutionMode 4 VertexOrderCcw @@ -41,23 +41,23 @@ Linked tessellation evaluation stage: Name 53 "gl_TessLevelOuter" Name 57 "tli" Name 61 "gl_TessLevelInner" - Name 66 "gl_PerVertex" - MemberName 66(gl_PerVertex) 0 "gl_Position" - MemberName 66(gl_PerVertex) 1 "gl_PointSize" - MemberName 66(gl_PerVertex) 2 "gl_ClipDistance" - Name 68 "" - Name 77 "patchIn" - Name 81 "inb" - Name 82 "ind" - Name 83 "testblb" - MemberName 83(testblb) 0 "f" - Name 86 "blb" - Name 87 "testbld" - MemberName 87(testbld) 0 "f" - Name 90 "bld" - Name 93 "ivla" - Name 94 "ivlb" - Name 97 "ovla" + Name 64 "gl_PerVertex" + MemberName 64(gl_PerVertex) 0 "gl_Position" + MemberName 64(gl_PerVertex) 1 "gl_PointSize" + MemberName 64(gl_PerVertex) 2 "gl_ClipDistance" + Name 66 "" + Name 75 "patchIn" + Name 79 "inb" + Name 80 "ind" + Name 81 "testblb" + MemberName 81(testblb) 0 "f" + Name 84 "blb" + Name 85 "testbld" + MemberName 85(testbld) 0 "f" + Name 88 "bld" + Name 91 "ivla" + Name 92 "ivlb" + Name 95 "ovla" MemberDecorate 17(gl_PerVertex) 0 BuiltIn Position MemberDecorate 17(gl_PerVertex) 1 BuiltIn PointSize MemberDecorate 17(gl_PerVertex) 2 BuiltIn ClipDistance @@ -69,16 +69,16 @@ Linked tessellation evaluation stage: Decorate 53(gl_TessLevelOuter) BuiltIn TessLevelOuter Decorate 61(gl_TessLevelInner) Patch Decorate 61(gl_TessLevelInner) BuiltIn TessLevelInner - MemberDecorate 66(gl_PerVertex) 0 BuiltIn Position - MemberDecorate 66(gl_PerVertex) 1 BuiltIn PointSize - MemberDecorate 66(gl_PerVertex) 2 BuiltIn ClipDistance - Decorate 66(gl_PerVertex) Block - Decorate 77(patchIn) Patch - Decorate 83(testblb) Block - Decorate 87(testbld) Block - Decorate 93(ivla) Location 23 - Decorate 94(ivlb) Location 24 - Decorate 97(ovla) Location 23 + MemberDecorate 64(gl_PerVertex) 0 BuiltIn Position + MemberDecorate 64(gl_PerVertex) 1 BuiltIn PointSize + MemberDecorate 64(gl_PerVertex) 2 BuiltIn ClipDistance + Decorate 64(gl_PerVertex) Block + Decorate 75(patchIn) Patch + Decorate 81(testblb) Block + Decorate 85(testbld) Block + Decorate 91(ivla) Location 23 + Decorate 92(ivlb) Location 24 + Decorate 95(ovla) Location 23 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 1 @@ -88,7 +88,7 @@ Linked tessellation evaluation stage: 11: TypeVector 10(float) 4 12: TypePointer Function 11(fvec4) 14: TypeInt 32 0 - 15: 14(int) Constant 1 + 15: 14(int) Constant 3 16: TypeArray 10(float) 15 17(gl_PerVertex): TypeStruct 11(fvec4) 10(float) 16 18: 14(int) Constant 32 @@ -117,34 +117,32 @@ Linked tessellation evaluation stage: 59: TypeArray 10(float) 58 60: TypePointer Input 59 61(gl_TessLevelInner): 60(ptr) Variable Input - 64: 14(int) Constant 3 - 65: TypeArray 10(float) 64 -66(gl_PerVertex): TypeStruct 11(fvec4) 10(float) 65 - 67: TypePointer Output 66(gl_PerVertex) - 68: 67(ptr) Variable Output - 70: TypePointer Output 11(fvec4) - 73: TypePointer Output 10(float) - 77(patchIn): 24(ptr) Variable Input - 78: TypeVector 10(float) 2 - 79: TypeArray 78(fvec2) 18 - 80: TypePointer Input 79 - 81(inb): 80(ptr) Variable Input - 82(ind): 80(ptr) Variable Input - 83(testblb): TypeStruct 6(int) - 84: TypeArray 83(testblb) 18 - 85: TypePointer Input 84 - 86(blb): 85(ptr) Variable Input - 87(testbld): TypeStruct 6(int) - 88: TypeArray 87(testbld) 18 - 89: TypePointer Input 88 - 90(bld): 89(ptr) Variable Input - 91: TypeArray 11(fvec4) 18 - 92: TypePointer Input 91 - 93(ivla): 92(ptr) Variable Input - 94(ivlb): 92(ptr) Variable Input - 95: TypeArray 11(fvec4) 58 - 96: TypePointer Output 95 - 97(ovla): 96(ptr) Variable Output +64(gl_PerVertex): TypeStruct 11(fvec4) 10(float) 16 + 65: TypePointer Output 64(gl_PerVertex) + 66: 65(ptr) Variable Output + 68: TypePointer Output 11(fvec4) + 71: TypePointer Output 10(float) + 75(patchIn): 24(ptr) Variable Input + 76: TypeVector 10(float) 2 + 77: TypeArray 76(fvec2) 18 + 78: TypePointer Input 77 + 79(inb): 78(ptr) Variable Input + 80(ind): 78(ptr) Variable Input + 81(testblb): TypeStruct 6(int) + 82: TypeArray 81(testblb) 18 + 83: TypePointer Input 82 + 84(blb): 83(ptr) Variable Input + 85(testbld): TypeStruct 6(int) + 86: TypeArray 85(testbld) 18 + 87: TypePointer Input 86 + 88(bld): 87(ptr) Variable Input + 89: TypeArray 11(fvec4) 18 + 90: TypePointer Input 89 + 91(ivla): 90(ptr) Variable Input + 92(ivlb): 90(ptr) Variable Input + 93: TypeArray 11(fvec4) 58 + 94: TypePointer Output 93 + 95(ovla): 94(ptr) Variable Output 4(main): 2 Function None 3 5: Label 8(a): 7(ptr) Variable Function @@ -178,14 +176,14 @@ Linked tessellation evaluation stage: 62: 29(ptr) AccessChain 61(gl_TessLevelInner) 22 63: 10(float) Load 62 Store 57(tli) 63 - 69: 11(fvec4) Load 13(p) - 71: 70(ptr) AccessChain 68 23 - Store 71 69 - 72: 10(float) Load 28(ps) - 74: 73(ptr) AccessChain 68 22 - Store 74 72 - 75: 10(float) Load 32(cd) - 76: 73(ptr) AccessChain 68 33 33 - Store 76 75 + 67: 11(fvec4) Load 13(p) + 69: 68(ptr) AccessChain 66 23 + Store 69 67 + 70: 10(float) Load 28(ps) + 72: 71(ptr) AccessChain 66 22 + Store 72 70 + 73: 10(float) Load 32(cd) + 74: 71(ptr) AccessChain 66 33 33 + Store 74 73 Return FunctionEnd diff --git a/Test/baseResults/spv.Operations.frag.out b/Test/baseResults/spv.Operations.frag.out index b3a6d283..a5863729 100755 --- a/Test/baseResults/spv.Operations.frag.out +++ b/Test/baseResults/spv.Operations.frag.out @@ -281,7 +281,7 @@ Linked fragment stage: 176: 7(fvec4) Load 9(v) 177: 7(fvec4) Load 9(v) 182: 179(bvec4) Load 181(ub41) - 183: 7(fvec4) ExtInst 1(GLSL.std.450) 46(FMix) 176 177 182 + 183: 7(fvec4) Select 182 177 176 184: 7(fvec4) Load 9(v) 185: 7(fvec4) FAdd 184 183 Store 9(v) 185 diff --git a/Test/baseResults/spv.specConstantComposite.vert.out b/Test/baseResults/spv.specConstantComposite.vert.out new file mode 100644 index 00000000..5e2dfa4a --- /dev/null +++ b/Test/baseResults/spv.specConstantComposite.vert.out @@ -0,0 +1,172 @@ +spv.specConstantComposite.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + + +Linked vertex stage: + + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 106 + + Capability Shader + Capability Float64 + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 27 105 + Source GLSL 450 + Name 4 "main" + Name 6 "refer_primary_spec_const(" + Name 8 "refer_composite_spec_const(" + Name 10 "refer_copmosite_dot_dereference(" + Name 12 "refer_composite_bracket_dereference(" + Name 16 "refer_spec_const_array_length(" + Name 18 "declare_spec_const_in_func(" + Name 27 "color" + Name 41 "flat_struct" + MemberName 41(flat_struct) 0 "i" + MemberName 41(flat_struct) 1 "f" + MemberName 41(flat_struct) 2 "d" + MemberName 41(flat_struct) 3 "b" + Name 42 "nesting_struct" + MemberName 42(nesting_struct) 0 "nested" + MemberName 42(nesting_struct) 1 "v" + MemberName 42(nesting_struct) 2 "i" + Name 72 "indexable" + Name 76 "indexable" + Name 83 "len" + Name 105 "global_vec4_array_with_spec_length" + Decorate 21 SpecId 203 + Decorate 28 SpecId 200 + Decorate 32 SpecId 201 + Decorate 43 SpecId 202 + 2: TypeVoid + 3: TypeFunction 2 + 14: TypeInt 32 1 + 15: TypeFunction 14(int) + 20: TypeBool + 21: 20(bool) SpecConstantTrue + 24: TypeFloat 32 + 25: TypeVector 24(float) 4 + 26: TypePointer Output 25(fvec4) + 27(color): 26(ptr) Variable Output + 28: 14(int) SpecConstant 3 + 32: 24(float) SpecConstant 1078523331 + 33: 25(fvec4) SpecConstantComposite 32 32 32 32 + 36: 24(float) Constant 1133908460 + 37: 25(fvec4) SpecConstantComposite 32 32 36 36 + 40: TypeFloat 64 + 41(flat_struct): TypeStruct 14(int) 24(float) 40(float) 20(bool) +42(nesting_struct): TypeStruct 41(flat_struct) 25(fvec4) 14(int) + 43: 40(float) SpecConstant 1413754136 1074340347 + 44:41(flat_struct) SpecConstantComposite 28 32 43 21 + 45:42(nesting_struct) SpecConstantComposite 44 33 28 + 46: 14(int) Constant 2 + 51: TypeInt 32 0 + 52: 51(int) Constant 0 + 57: 51(int) Constant 5 + 58: TypeArray 24(float) 57 + 59: 24(float) Constant 1065353216 + 60: 24(float) Constant 1073741824 + 61: 24(float) Constant 1077936128 + 62: 58 SpecConstantComposite 32 32 59 60 61 + 63: 14(int) Constant 1 + 68: TypeArray 14(int) 57 + 69: 14(int) Constant 30 + 70: 68 SpecConstantComposite 28 28 63 46 69 + 71: TypePointer Function 68 + 73: TypePointer Function 14(int) + 87: 24(float) Constant 1106321080 + 88:41(flat_struct) SpecConstantComposite 69 87 43 21 + 89: 14(int) Constant 10 + 90:42(nesting_struct) SpecConstantComposite 88 37 89 + 96: 20(bool) ConstantFalse + 97:41(flat_struct) SpecConstantComposite 28 32 43 96 + 98: 24(float) Constant 1036831949 + 99: 25(fvec4) ConstantComposite 98 98 98 98 + 100:42(nesting_struct) SpecConstantComposite 97 99 28 + 101: 14(int) Constant 3000 + 102:42(nesting_struct) SpecConstantComposite 88 37 101 + 103: TypeArray 25(fvec4) 28 + 104: TypePointer Input 103 +105(global_vec4_array_with_spec_length): 104(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd +6(refer_primary_spec_const(): 2 Function None 3 + 7: Label + SelectionMerge 23 None + BranchConditional 21 22 23 + 22: Label + 29: 24(float) ConvertSToF 28 + 30: 25(fvec4) Load 27(color) + 31: 25(fvec4) VectorTimesScalar 30 29 + Store 27(color) 31 + Branch 23 + 23: Label + Return + FunctionEnd +8(refer_composite_spec_const(): 2 Function None 3 + 9: Label + 34: 25(fvec4) Load 27(color) + 35: 25(fvec4) FAdd 34 33 + Store 27(color) 35 + 38: 25(fvec4) Load 27(color) + 39: 25(fvec4) FSub 38 37 + Store 27(color) 39 + Return + FunctionEnd +10(refer_copmosite_dot_dereference(): 2 Function None 3 + 11: Label + 47: 14(int) CompositeExtract 45 2 + 48: 24(float) ConvertSToF 47 + 49: 25(fvec4) Load 27(color) + 50: 25(fvec4) VectorTimesScalar 49 48 + Store 27(color) 50 + 53: 24(float) CompositeExtract 33 0 + 54: 25(fvec4) Load 27(color) + 55: 25(fvec4) CompositeConstruct 53 53 53 53 + 56: 25(fvec4) FAdd 54 55 + Store 27(color) 56 + Return + FunctionEnd +12(refer_composite_bracket_dereference(): 2 Function None 3 + 13: Label + 72(indexable): 71(ptr) Variable Function + 76(indexable): 71(ptr) Variable Function + 64: 24(float) CompositeExtract 62 1 + 65: 25(fvec4) Load 27(color) + 66: 25(fvec4) CompositeConstruct 64 64 64 64 + 67: 25(fvec4) FSub 65 66 + Store 27(color) 67 + Store 72(indexable) 70 + 74: 73(ptr) AccessChain 72(indexable) 28 + 75: 14(int) Load 74 + Store 76(indexable) 70 + 77: 73(ptr) AccessChain 76(indexable) 75 + 78: 14(int) Load 77 + 79: 24(float) ConvertSToF 78 + 80: 25(fvec4) Load 27(color) + 81: 25(fvec4) CompositeConstruct 79 79 79 79 + 82: 25(fvec4) FDiv 80 81 + Store 27(color) 82 + Return + FunctionEnd +16(refer_spec_const_array_length(): 14(int) Function None 15 + 17: Label + 83(len): 73(ptr) Variable Function + Store 83(len) 28 + 84: 14(int) Load 83(len) + ReturnValue 84 + FunctionEnd +18(declare_spec_const_in_func(): 2 Function None 3 + 19: Label + 91: 14(int) CompositeExtract 90 2 + 92: 24(float) ConvertSToF 91 + 93: 25(fvec4) Load 27(color) + 94: 25(fvec4) CompositeConstruct 92 92 92 92 + 95: 25(fvec4) FDiv 93 94 + Store 27(color) 95 + Return + FunctionEnd diff --git a/Test/baseResults/spv.specConstantOperations.vert.out b/Test/baseResults/spv.specConstantOperations.vert.out new file mode 100644 index 00000000..476efc90 --- /dev/null +++ b/Test/baseResults/spv.specConstantOperations.vert.out @@ -0,0 +1,116 @@ +spv.specConstantOperations.vert +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + + +Linked vertex stage: + + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 94 + + Capability Shader + Capability Float64 + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" + Source GLSL 450 + Name 4 "main" + Decorate 7 SpecId 200 + Decorate 9 SpecId 201 + Decorate 11 SpecId 202 + Decorate 12 SpecId 203 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: 6(float) SpecConstant 1078530010 + 8: TypeInt 32 1 + 9: 8(int) SpecConstant 10 + 10: TypeInt 32 0 + 11: 10(int) SpecConstant 100 + 12: 8(int) SpecConstant 4294967286 + 13: TypeFloat 64 + 14: 13(float) SpecConstantOp 115 7 + 15: 6(float) SpecConstantOp 115 14 + 16: 8(int) SpecConstantOp 126 9 + 17: 8(int) SpecConstantOp 200 9 + 18: 8(int) Constant 2 + 19: 8(int) SpecConstantOp 128 9 18 + 20: 8(int) SpecConstantOp 128 9 18 + 21: 8(int) Constant 3 + 22: 8(int) SpecConstantOp 130 20 21 + 23: 8(int) Constant 4 + 24: 8(int) SpecConstantOp 130 19 23 + 25: 8(int) SpecConstantOp 132 12 18 + 26: 10(int) Constant 2 + 27: 10(int) SpecConstantOp 132 11 26 + 28: 8(int) Constant 5 + 29: 8(int) SpecConstantOp 135 25 28 + 30: 10(int) Constant 5 + 31: 10(int) SpecConstantOp 134 27 30 + 32: 8(int) SpecConstantOp 139 12 23 + 33: 10(int) Constant 4 + 34: 10(int) SpecConstantOp 137 11 33 + 35: 8(int) SpecConstantOp 132 12 21 + 36: 8(int) SpecConstantOp 135 35 28 + 37: 8(int) Constant 10 + 38: 8(int) SpecConstantOp 195 12 37 + 39: 8(int) Constant 20 + 40: 10(int) SpecConstantOp 194 11 39 + 41: 8(int) Constant 1 + 42: 8(int) SpecConstantOp 196 12 41 + 43: 10(int) SpecConstantOp 196 11 18 + 44: 8(int) Constant 256 + 45: 8(int) SpecConstantOp 197 12 44 + 46: 10(int) Constant 512 + 47: 10(int) SpecConstantOp 198 11 46 + 48: TypeBool + 49: 48(bool) SpecConstantOp 177 9 12 + 50: 48(bool) SpecConstantOp 170 11 11 + 51: 48(bool) SpecConstantOp 173 9 12 + 52: TypeVector 8(int) 4 + 53: 8(int) Constant 30 + 54: 52(ivec4) SpecConstantComposite 39 53 9 9 + 55: TypeVector 10(int) 4 + 56: 10(int) Constant 4294967295 + 57: 10(int) Constant 4294967294 + 58: 55(ivec4) SpecConstantComposite 11 11 56 57 + 59: TypeVector 6(float) 4 + 60: 6(float) Constant 1067450368 + 61: 59(fvec4) SpecConstantComposite 7 60 7 60 + 62: TypeVector 13(float) 4 + 63: 62(fvec4) SpecConstantOp 115 61 + 64: 59(fvec4) SpecConstantOp 115 63 + 65: 52(ivec4) SpecConstantOp 200 54 + 66: 52(ivec4) SpecConstantOp 126 54 + 67: 52(ivec4) ConstantComposite 18 18 18 18 + 68: 52(ivec4) SpecConstantOp 128 54 67 + 69: 52(ivec4) SpecConstantOp 128 54 67 + 70: 52(ivec4) ConstantComposite 21 21 21 21 + 71: 52(ivec4) SpecConstantOp 130 69 70 + 72: 52(ivec4) ConstantComposite 23 23 23 23 + 73: 52(ivec4) SpecConstantOp 130 71 72 + 74: 52(ivec4) SpecConstantOp 132 54 67 + 75: 52(ivec4) ConstantComposite 28 28 28 28 + 76: 52(ivec4) SpecConstantOp 135 74 75 + 77: 52(ivec4) SpecConstantOp 139 54 72 + 78: 52(ivec4) ConstantComposite 37 37 37 37 + 79: 52(ivec4) SpecConstantOp 195 54 78 + 80: 52(ivec4) SpecConstantOp 196 54 67 + 81: 8(int) Constant 1024 + 82: 52(ivec4) ConstantComposite 81 81 81 81 + 83: 52(ivec4) SpecConstantOp 197 54 82 + 84: 10(int) Constant 2048 + 85: 55(ivec4) ConstantComposite 84 84 84 84 + 86: 55(ivec4) SpecConstantOp 198 58 85 + 87: 10(int) Constant 0 + 88: 8(int) SpecConstantOp 81 54 0 + 89: TypeVector 8(int) 2 + 90: 89(ivec2) SpecConstantOp 79 54 54 1(GLSL.std.450) 0 + 91: TypeVector 8(int) 3 + 92: 91(ivec3) SpecConstantOp 79 54 54 2 1(GLSL.std.450) 0 + 93: 52(ivec4) SpecConstantOp 79 54 54 1(GLSL.std.450) 2 0 3 + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd diff --git a/Test/baseResults/spv.test.frag.out b/Test/baseResults/spv.test.frag.out old mode 100755 new mode 100644 diff --git a/Test/baseResults/spv.test.vert.out b/Test/baseResults/spv.test.vert.out old mode 100755 new mode 100644 diff --git a/Test/spv.400.frag b/Test/spv.400.frag index 2014b5b0..05b4370b 100644 --- a/Test/spv.400.frag +++ b/Test/spv.400.frag @@ -2,6 +2,8 @@ in vec2 c2D; flat in int i; +flat in uint u; +out uint uo; out vec4 outp; out ivec4 ioutp; out uvec4 uoutp; @@ -254,6 +256,7 @@ void main() ioutp += textureGatherOffset(isamp2DA, vec3(0.1), ivec2(i)); outp += gl_FragCoord + vl2; + uo = u % i; foo23(); doubles(); } diff --git a/Test/spv.specConstantComposite.vert b/Test/spv.specConstantComposite.vert new file mode 100644 index 00000000..4450ddd6 --- /dev/null +++ b/Test/spv.specConstantComposite.vert @@ -0,0 +1,93 @@ +#version 450 + +// constant_id specified scalar spec constants +layout(constant_id = 200) const int spec_int = 3; +layout(constant_id = 201) const float spec_float = 3.14; +layout(constant_id = 202) const + double spec_double = 3.1415926535897932384626433832795; +layout(constant_id = 203) const bool spec_bool = true; + +const float cast_spec_float = float(spec_float); + +// Flat struct +struct flat_struct { + int i; + float f; + double d; + bool b; +}; + +// Nesting struct +struct nesting_struct { + flat_struct nested; + vec4 v; + int i; +}; + +// Expect OpSpecConstantComposite +// Flat struct initializer +const flat_struct spec_flat_struct_all_spec = {spec_int, spec_float, + spec_double, spec_bool}; +const flat_struct spec_flat_struct_partial_spec = {30, 30.14, spec_double, + spec_bool}; + +// Nesting struct initializer +const nesting_struct nesting_struct_ctor = { + {spec_int, spec_float, spec_double, false}, + vec4(0.1, 0.1, 0.1, 0.1), + spec_int}; + +// Vector constructor +const vec4 spec_vec4_all_spec = + vec4(spec_float, spec_float, spec_float, spec_float); +const vec4 spec_vec4_partial_spec = + vec4(spec_float, spec_float, 300.14, 300.14); + +// Struct nesting constructor +const nesting_struct spec_nesting_struct_all_spec = { + spec_flat_struct_all_spec, spec_vec4_all_spec, spec_int}; +const nesting_struct spec_nesting_struct_partial_spec = { + spec_flat_struct_partial_spec, spec_vec4_partial_spec, 3000}; + +const float spec_float_array[5] = {spec_float, spec_float, 1.0, 2.0, 3.0}; +const int spec_int_array[5] = {spec_int, spec_int, 1, 2, 30}; + +// global_vec4_array_with_spec_length is not a spec constant, but its array +// size is. When calling global_vec4_array_with_spec_length.length(), A +// TIntermSymbol Node shoule be returned, instead of a TIntermConstantUnion +// node which represents a known constant value. +in vec4 global_vec4_array_with_spec_length[spec_int]; + +out vec4 color; + +void refer_primary_spec_const() { + if (spec_bool) color *= spec_int; +} + +void refer_composite_spec_const() { + color += spec_vec4_all_spec; + color -= spec_vec4_partial_spec; +} + +void refer_copmosite_dot_dereference() { + color *= spec_nesting_struct_all_spec.i; + color += spec_vec4_all_spec.x; +} + +void refer_composite_bracket_dereference() { + color -= spec_float_array[1]; + color /= spec_int_array[spec_int_array[spec_int]]; +} + +int refer_spec_const_array_length() { + int len = global_vec4_array_with_spec_length.length(); + return len; +} + +void declare_spec_const_in_func() { + const nesting_struct spec_const_declared_in_func = { + spec_flat_struct_partial_spec, spec_vec4_partial_spec, 10}; + color /= spec_const_declared_in_func.i; +} + +void main() {} diff --git a/Test/spv.specConstantOperations.vert b/Test/spv.specConstantOperations.vert new file mode 100644 index 00000000..9de96aee --- /dev/null +++ b/Test/spv.specConstantOperations.vert @@ -0,0 +1,90 @@ +#version 450 + +layout(constant_id = 200) const float sp_float = 3.1415926; +layout(constant_id = 201) const int sp_int = 10; +layout(constant_id = 202) const uint sp_uint = 100; +layout(constant_id = 203) const int sp_sint = -10; + + +// +// Scalars +// + +// Size convert +const double float_to_double = double(sp_float); +const float double_to_float = float(float_to_double); + +// Negate and Not +const int negate_int = -sp_int; +const int not_int = ~sp_int; + +// Add and Subtract +const int sp_int_add_two = sp_int + 2; +const int sp_int_add_two_sub_three = sp_int + 2 - 3; +const int sp_int_add_two_sub_four = sp_int_add_two - 4; + +// Mul, Div and Rem +const int sp_sint_mul_two = sp_sint * 2; +const uint sp_uint_mul_two = sp_uint * 2; +const int sp_sint_mul_two_div_five = sp_sint_mul_two / 5; +const uint sp_uint_mul_two_div_five = sp_uint_mul_two / 5; +const int sp_sint_rem_four = sp_sint % 4; +const uint sp_uint_rem_four = sp_uint % 4; +const int sp_sint_mul_three_div_five = sp_sint * 3 / 5; + +// Shift +const int sp_sint_shift_right_arithmetic = sp_sint >> 10; +const uint sp_uint_shift_right_arithmetic = sp_uint >> 20; +const int sp_sint_shift_left = sp_sint << 1; +const uint sp_uint_shift_left = sp_uint << 2; + +// Bitwise And, Or, Xor +const int sp_sint_or_256 = sp_sint | 0x100; +const uint sp_uint_xor_512 = sp_uint ^ 0x200; + +/* // Scalar comparison */ +const bool sp_int_lt_sp_sint = sp_int < sp_sint; +const bool sp_uint_equal_sp_uint = sp_uint == sp_uint; +const bool sp_int_gt_sp_sint = sp_int > sp_sint; + +// +// Vectors +// +const ivec4 iv = ivec4(20, 30, sp_int, sp_int); +const uvec4 uv = uvec4(sp_uint, sp_uint, -1, -2); +const vec4 fv = vec4(sp_float, 1.25, sp_float, 1.25); + +// Size convert +const dvec4 fv_to_dv = dvec4(fv); +const vec4 dv_to_fv = vec4(fv_to_dv); + +// Negate and Not +const ivec4 not_iv = ~iv; +const ivec4 negate_iv = -iv; + +// Add and Subtract +const ivec4 iv_add_two = iv + 2; +const ivec4 iv_add_two_sub_three = iv + 2 - 3; +const ivec4 iv_add_two_sub_four = iv_add_two_sub_three - 4; + +// Mul, Div and Rem +const ivec4 iv_mul_two = iv * 2; +const ivec4 iv_mul_two_div_five = iv_mul_two / 5; +const ivec4 iv_rem_four = iv % 4; + +// Shift +const ivec4 iv_shift_right_arithmetic = iv >> 10; +const ivec4 iv_shift_left = iv << 2; + +// Bitwise And, Or, Xor +const ivec4 iv_or_1024 = iv | 0x400; +const uvec4 uv_xor_2048 = uv ^ 0x800; + +// Swizzles +const int iv_x = iv.x; +const ivec2 iv_yx = iv.yx; +const ivec3 iv_zyx = iv.zyx; +const ivec4 iv_yzxw = iv.yzxw; + +void main() {} + diff --git a/Test/test-spirv-list b/Test/test-spirv-list index 0e223674..b7dfd537 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -102,6 +102,8 @@ spv.pushConstant.vert spv.subpass.frag spv.specConstant.vert spv.specConstant.comp +spv.specConstantComposite.vert +spv.specConstantOperations.vert # GLSL-level semantics vulkan.frag vulkan.vert diff --git a/glslang/Include/InfoSink.h b/glslang/Include/InfoSink.h index a321ebcc..5862e5d8 100644 --- a/glslang/Include/InfoSink.h +++ b/glslang/Include/InfoSink.h @@ -92,7 +92,7 @@ public: case EPrefixInternalError: append("INTERNAL ERROR: "); break; case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; case EPrefixNote: append("NOTE: "); break; - default: append("UNKOWN ERROR: "); break; + default: append("UNKNOWN ERROR: "); break; } } void location(const TSourceLoc& loc) { diff --git a/glslang/Include/PoolAlloc.h b/glslang/Include/PoolAlloc.h index de41053f..c3bebc63 100644 --- a/glslang/Include/PoolAlloc.h +++ b/glslang/Include/PoolAlloc.h @@ -95,7 +95,7 @@ public: void checkAllocList() const; - // Return total size needed to accomodate user buffer of 'size', + // Return total size needed to accommodate user buffer of 'size', // plus our tracking data. inline static size_t allocationSize(size_t size) { return size + 2 * guardBlockSize + headerSize(); @@ -241,8 +241,8 @@ protected: int numCalls; // just an interesting statistic size_t totalBytes; // just an interesting statistic private: - TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator - TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor + TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator + TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor }; diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index c88bca67..bff7e9a9 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -411,6 +411,19 @@ public: clearLayout(); } + // Drop just the storage qualification, which perhaps should + // never be done, as it is fundamentally inconsistent, but need to + // explore what downstream consumers need. + // E.g., in a deference, it is an inconsistency between: + // A) partially dereferenced resource is still in the storage class it started in + // B) partially dereferenced resource is a new temporary object + // If A, then nothing should change, if B, then everything should change, but this is half way. + void makePartialTemporary() + { + storage = EvqTemporary; + specConstant = false; + } + TStorageQualifier storage : 6; TBuiltInVariable builtIn : 8; TPrecisionQualifier precision : 3; @@ -727,6 +740,7 @@ public: } void makeSpecConstant() { + storage = EvqConst; specConstant = true; } static const char* getLayoutPackingString(TLayoutPacking packing) @@ -1209,6 +1223,7 @@ public: virtual int getMatrixCols() const { return matrixCols; } virtual int getMatrixRows() const { return matrixRows; } virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } + virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index ce5fb775..ab177011 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -612,25 +612,29 @@ public: // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from // per process threadPoolAllocator, then it causes increased memory usage per compile // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int i, const TString& n, const TType& t) : - TIntermTyped(t), id(i) { name = n;} + TIntermSymbol(int i, const TString& n, const TType& t) + : TIntermTyped(t), id(i), constSubtree(nullptr) + { name = n; } virtual int getId() const { return id; } virtual const TString& getName() const { return name; } virtual void traverse(TIntermTraverser*); virtual TIntermSymbol* getAsSymbolNode() { return this; } virtual const TIntermSymbol* getAsSymbolNode() const { return this; } - void setConstArray(const TConstUnionArray& c) { unionArray = c; } - const TConstUnionArray& getConstArray() const { return unionArray; } + void setConstArray(const TConstUnionArray& c) { constArray = c; } + const TConstUnionArray& getConstArray() const { return constArray; } + void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + TIntermTyped* getConstSubtree() const { return constSubtree; } protected: int id; // the unique id of the symbol this node represents TString name; // the name of the symbol this node represents - TConstUnionArray unionArray; // if the symbol is a front-end compile-time constant, this is its value + TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value + TIntermTyped* constSubtree; }; class TIntermConstantUnion : public TIntermTyped { public: - TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua), literal(false) { } - const TConstUnionArray& getConstArray() const { return unionArray; } + TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } + const TConstUnionArray& getConstArray() const { return constArray; } virtual TIntermConstantUnion* getAsConstantUnion() { return this; } virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } virtual void traverse(TIntermTraverser*); @@ -640,7 +644,7 @@ public: void setExpression() { literal = false; } bool isLiteral() const { return literal; } protected: - const TConstUnionArray unionArray; + const TConstUnionArray constArray; bool literal; // true if node represents a literal in the source code }; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index bafcb917..777de2d6 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -61,25 +61,35 @@ namespace glslang { // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& loc) +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, + TIntermTyped* constSubtree, const TSourceLoc& loc) { TIntermSymbol* node = new TIntermSymbol(id, name, type); node->setLoc(loc); + node->setConstArray(constArray); + node->setConstSubtree(constSubtree); return node; } -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, const TSourceLoc& loc) +TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable) { - TIntermSymbol* node = addSymbol(id, name, type, loc); - node->setConstArray(constArray); + glslang::TSourceLoc loc; // just a null location + loc.init(); - return node; + return addSymbol(variable, loc); } TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc) { - return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), loc); + return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc); +} + +TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc) +{ + TConstUnionArray unionArray; // just a null constant + + return addSymbol(0, "", type, unionArray, nullptr, loc); } // @@ -252,6 +262,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo // // For constructors, we are now done, it was all in the conversion. + // TODO: but, did this bypass constant folding? // switch (op) { case EOpConstructInt: @@ -281,7 +292,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo if (child->getAsConstantUnion()) return child->getAsConstantUnion()->fold(op, node->getType()); - // If it's a specialiation constant, the result is too. + // If it's a specialization constant, the result is too. if (child->getType().getQualifier().isSpecConstant()) node->getWritableType().getQualifier().makeSpecConstant(); @@ -474,6 +485,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EOpSub: case EOpMul: case EOpDiv: + case EOpMod: case EOpVectorTimesScalar: case EOpVectorTimesMatrix: @@ -605,6 +617,12 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt newNode->setLoc(node->getLoc()); newNode->setOperand(node); + // TODO: it seems that some unary folding operations should occur here, but are not + + // Propagate specialization-constant-ness. + if (node->getType().getQualifier().isSpecConstant()) + newNode->getWritableType().getQualifier().makeSpecConstant(); + return newNode; } @@ -813,7 +831,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // Make a selection node. // TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); - node->getQualifier().storage = EvqTemporary; + node->getQualifier().makeTemporary(); node->setLoc(loc); node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision); @@ -872,7 +890,6 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseT TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& loc) { - TIntermAggregate* node = new TIntermAggregate(EOpSequence); node->setLoc(loc); @@ -1017,8 +1034,7 @@ void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymb const TAnonMember* anon = symbol.getAsAnonMember(); variable = &anon->getAnonContainer(); } - TIntermSymbol* node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType()); - node->setConstArray(variable->getConstArray()); + TIntermSymbol* node = addSymbol(*variable); linkage = growAggregate(linkage, node); } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index f005da4e..d47a0ed4 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -484,7 +484,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn TIntermTyped* result = nullptr; int indexValue = 0; - if (index->getQualifier().storage == EvqConst) { + if (index->getQualifier().isFrontEndConstant()) { indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); checkIndex(loc, base->getType(), indexValue); } @@ -495,7 +495,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); else error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) + } else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) return intermediate.foldDereference(base, indexValue, loc); else { // at least one of base and index is variable... @@ -503,7 +503,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) handleIoResizeArrayAccess(loc, base); - if (index->getQualifier().storage == EvqConst) { + if (index->getQualifier().isFrontEndConstant()) { if (base->getType().isImplicitlySizedArray()) updateImplicitArraySize(loc, base, indexValue); result = intermediate.addIndex(EOpIndexDirect, base, index, loc); @@ -541,10 +541,15 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn } else { // Insert valid dereferenced result TType newType(base->getType(), 0); // dereferenced type - if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) + if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) { newType.getQualifier().storage = EvqConst; - else - newType.getQualifier().storage = EvqTemporary; + // If base or index is a specialization constant, the result should also be a specialization constant. + if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) { + newType.getQualifier().makeSpecConstant(); + } + } else { + newType.getQualifier().makePartialTemporary(); + } result->setType(newType); if (anyIndexLimits) @@ -587,7 +592,7 @@ void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* b (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() && ! base->getType().getQualifier().isPipeInput() && ! base->getType().getQualifier().isPipeOutput() && - base->getType().getQualifier().storage != EvqConst) || + ! base->getType().getQualifier().isConstant()) || (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || base->getType().getQualifier().isPipeOutput()))) { // it's too early to know what the inductive variables are, save it for post processing @@ -820,6 +825,9 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm return result; else { TType type(base->getBasicType(), EvqTemporary, fields.num); + // Swizzle operations propagate specialization-constantness + if (base->getQualifier().isSpecConstant()) + type.getQualifier().makeSpecConstant(); return addConstructor(loc, base, type, mapTypeToConstructorOp(type)); } } @@ -837,6 +845,9 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, (int) vectorString.size())); } + // Swizzle operations propagate specialization-constantness + if (base->getType().getQualifier().isSpecConstant()) + result->getWritableType().getQualifier().makeSpecConstant(); } } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { const TTypeList* fields = base->getType().getStruct(); @@ -849,7 +860,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm } } if (fieldFound) { - if (base->getType().getQualifier().storage == EvqConst) + if (base->getType().getQualifier().isFrontEndConstant()) result = intermediate.foldDereference(base, member, loc); else { blockMemberExtensionCheck(loc, base, field); @@ -1017,7 +1028,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, loc); } } else - paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(0, "", *param.type, loc), loc); + paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); } intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); loopNestingLevel = 0; @@ -1220,6 +1231,11 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction else error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); } + } else if (type.getOuterArrayNode()) { + // If the array's outer size is specified by an intermediate node, it means the array's length + // was specified by a specialization constant. In such a case, we should return the node of the + // specialization constants to represent the length. + return type.getOuterArrayNode(); } else length = type.getOuterArraySize(); } else if (type.isMatrix()) @@ -2039,7 +2055,7 @@ void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TInt // void TParseContext::constantValueCheck(TIntermTyped* node, const char* token) { - if (node->getQualifier().storage != EvqConst) + if (! node->getQualifier().isConstant()) error(node->getLoc(), "constant expression required", token, ""); } @@ -2204,6 +2220,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T int size = 0; bool constType = true; + bool specConstType = false; // value is only valid if constType is true bool full = false; bool overFull = false; bool matrixInMatrix = false; @@ -2232,12 +2249,18 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) full = true; - if (function[arg].type->getQualifier().storage != EvqConst) + if (! function[arg].type->getQualifier().isConstant()) constType = false; + if (function[arg].type->getQualifier().isSpecConstant()) + specConstType = true; } - if (constType) - type.getQualifier().storage = EvqConst; + if (constType) { + if (specConstType) + type.getQualifier().makeSpecConstant(); + else + type.getQualifier().storage = EvqConst; + } if (type.isArray()) { if (function.getParamCount() == 0) { @@ -3099,16 +3122,27 @@ void TParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode * // This has to be the result of a block dereference, unless it's bad shader code // If it's a uniform block, then an error will be issued elsewhere, but // return early now to avoid crashing later in this function. - if (! deref->getLeft()->getAsSymbolNode() || deref->getLeft()->getBasicType() != EbtBlock || + if (deref->getLeft()->getBasicType() != EbtBlock || deref->getLeft()->getType().getQualifier().storage == EvqUniform || deref->getRight()->getAsConstantUnion() == nullptr) return; - blockIndex = deref->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); + const TIntermTyped* left = deref->getLeft(); + const TIntermTyped* right = deref->getRight(); - lookupName = &deref->getLeft()->getAsSymbolNode()->getName(); + if (left->getAsBinaryNode()) { + left = left->getAsBinaryNode()->getLeft(); // Block array access + assert(left->isArray()); + } + + if (! left->getAsSymbolNode()) + return; + + blockIndex = right->getAsConstantUnion()->getConstArray()[0].getIConst(); + + lookupName = &left->getAsSymbolNode()->getName(); if (IsAnonymous(*lookupName)) - lookupName = &(*deref->getLeft()->getType().getStruct())[blockIndex].type->getFieldName(); + lookupName = &(*left->getType().getStruct())[blockIndex].type->getFieldName(); } // Lookup the symbol, should only fail if shader code is incorrect @@ -3121,7 +3155,10 @@ void TParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode * return; } - symbol->getWritableType().setImplicitArraySize(index + 1); + if (symbol->getType().isStruct() && blockIndex != -1) + (*symbol->getWritableType().getStruct())[blockIndex].type->setImplicitArraySize(index + 1); + else + symbol->getWritableType().setImplicitArraySize(index + 1); } // Returns true if the first argument to the #line directive is the line number for the next line. @@ -3148,7 +3185,7 @@ void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier // if (type.getQualifier().storage == EvqConst || type.getQualifier().storage == EvqConstReadOnly) { - type.getQualifier().storage = EvqTemporary; + type.getQualifier().makeTemporary(); error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); } } @@ -4849,7 +4886,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp if (! initializer) { // error recovery; don't leave const without constant values if (qualifier == EvqConst) - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } @@ -4869,21 +4906,22 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp } } - // Uniform and global consts require a constant initializer - if (qualifier == EvqUniform && initializer->getType().getQualifier().storage != EvqConst) { + // Uniforms require a compile-time constant initializer + if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } - if (qualifier == EvqConst && symbolTable.atGlobalLevel() && initializer->getType().getQualifier().storage != EvqConst) { + // Global consts require a constant initializer (specialization constant is okay) + if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } // Const variables require a constant initializer, depending on version if (qualifier == EvqConst) { - if (initializer->getType().getQualifier().storage != EvqConst) { + if (! initializer->getType().getQualifier().isConstant()) { const char* initFeature = "non-constant initializer"; requireProfile(loc, ~EEsProfile, initFeature); profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); @@ -4895,7 +4933,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp // // "In declarations of global variables with no storage qualifier or with a const // qualifier any initializer must be a constant expression." - if (symbolTable.atGlobalLevel() && initializer->getType().getQualifier().storage != EvqConst) { + if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { const char* initFeature = "non-constant global initializer"; if (relaxedErrors()) warn(loc, "not allowed in this version", initFeature, ""); @@ -4908,14 +4946,27 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp // Compile-time tagging of the variable with its constant value... initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); - if (! initializer || ! initializer->getAsConstantUnion() || variable->getType() != initializer->getType()) { + if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) { error(loc, "non-matching or non-convertible constant type for const initializer", variable->getType().getStorageQualifierString(), ""); - variable->getWritableType().getQualifier().storage = EvqTemporary; + variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } - variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); + // We either have a folded constant in getAsConstantUnion, or we have to use + // the initializer's subtree in the AST to represent the computation of a + // specialization constant. + assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant()); + if (initializer->getAsConstantUnion()) + variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); + else { + // It's a specialization constant. + variable->getWritableType().getQualifier().makeSpecConstant(); + + // Keep the subtree that computes the specialization constant with the variable. + // Later, a symbol node will adopt the subtree from the variable. + variable->setConstSubtree(initializer); + } } else { // normal assigning of a value to a variable... specializationCheck(loc, initializer->getType(), "initializer"); @@ -5076,12 +5127,17 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* // if the structure constructor contains more than one parameter, then construct // each parameter - int paramCount = 0; // keeps a track of the constructor parameter number being checked + int paramCount = 0; // keeps track of the constructor parameter number being checked // for each parameter to the constructor call, check to see if the right type is passed or convert them // to the right type if possible (and allowed). // for structure constructors, just check if the right type is passed, no conversion is allowed. + // We don't know "top down" whether type is a specialization constant, + // but a const becomes a specialization constant if any of its children are. + bool hasSpecConst = false; + bool isConstConstrutor = true; + for (TIntermSequence::iterator p = sequenceVector.begin(); p != sequenceVector.end(); p++, paramCount++) { if (type.isArray()) @@ -5091,13 +5147,19 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* else newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); - if (newNode) + if (newNode) { *p = newNode; - else + if (! newNode->getType().getQualifier().isConstant()) + isConstConstrutor = false; + if (newNode->getType().getQualifier().isSpecConstant()) + hasSpecConst = true; + } else return nullptr; } TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc); + if (isConstConstrutor && hasSpecConst) + constructor->getWritableType().getQualifier().makeSpecConstant(); return constructor; } diff --git a/glslang/MachineIndependent/PoolAlloc.cpp b/glslang/MachineIndependent/PoolAlloc.cpp index a41cadf1..d56979b4 100644 --- a/glslang/MachineIndependent/PoolAlloc.cpp +++ b/glslang/MachineIndependent/PoolAlloc.cpp @@ -32,8 +32,8 @@ //POSSIBILITY OF SUCH DAMAGE. // -#include "../Include/PoolAlloc.h" #include "../Include/Common.h" +#include "../Include/PoolAlloc.h" #include "../Include/InitializeGlobals.h" #include "../OSDependent/osinclude.h" diff --git a/glslang/MachineIndependent/Scan.h b/glslang/MachineIndependent/Scan.h index 936b99f1..219049be 100644 --- a/glslang/MachineIndependent/Scan.h +++ b/glslang/MachineIndependent/Scan.h @@ -51,10 +51,10 @@ const int EndOfInput = -1; // class TInputScanner { public: - TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0) : + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0, bool single = false) : numSources(n), sources(reinterpret_cast(s)), // up to this point, common usage is "char*", but now we need positive 8-bit characters - lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f) + lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single) { loc = new TSourceLoc[numSources]; for (int i = 0; i < numSources; ++i) { @@ -67,6 +67,10 @@ public: loc[currentSource].string = -stringBias; loc[currentSource].line = 1; loc[currentSource].column = 0; + logicalSourceLoc.string = 0; + logicalSourceLoc.line = 1; + logicalSourceLoc.column = 0; + logicalSourceLoc.name = loc[0].name; } virtual ~TInputScanner() @@ -82,8 +86,11 @@ public: int ret = peek(); ++loc[currentSource].column; + ++logicalSourceLoc.column; if (ret == '\n') { ++loc[currentSource].line; + ++logicalSourceLoc.line; + logicalSourceLoc.column = 0; loc[currentSource].column = 0; } advance(); @@ -118,6 +125,7 @@ public: if (currentChar > 0) { --currentChar; --loc[currentSource].column; + --logicalSourceLoc.column; if (loc[currentSource].column < 0) { // We've moved back past a new line. Find the // previous newline (or start of the file) to compute @@ -129,6 +137,7 @@ public: } --chIndex; } + logicalSourceLoc.column = (int)(currentChar - chIndex); loc[currentSource].column = (int)(currentChar - chIndex); } } else { @@ -141,23 +150,57 @@ public: } else currentChar = lengths[currentSource] - 1; } - if (peek() == '\n') + if (peek() == '\n') { --loc[currentSource].line; + --logicalSourceLoc.line; + } } // for #line override - void setLine(int newLine) { loc[getLastValidSourceIndex()].line = newLine; } - void setFile(const char* filename) { loc[getLastValidSourceIndex()].name = filename; } + void setLine(int newLine) + { + logicalSourceLoc.line = newLine; + loc[getLastValidSourceIndex()].line = newLine; + } + + // for #line override in filename based parsing + void setFile(const char* filename) + { + logicalSourceLoc.name = filename; + loc[getLastValidSourceIndex()].name = filename; + } + + void setFile(const char* filename, size_t i) + { + if (i == getLastValidSourceIndex()) { + logicalSourceLoc.name = filename; + } + loc[i].name = filename; + } + void setString(int newString) { + logicalSourceLoc.string = newString; loc[getLastValidSourceIndex()].string = newString; + logicalSourceLoc.name = nullptr; loc[getLastValidSourceIndex()].name = nullptr; } // for #include content indentation - void setColumn(int col) { loc[getLastValidSourceIndex()].column = col; } + void setColumn(int col) + { + logicalSourceLoc.column = col; + loc[getLastValidSourceIndex()].column = col; + } - const TSourceLoc& getSourceLoc() const { return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; } + const TSourceLoc& getSourceLoc() const + { + if (singleLogical) { + return logicalSourceLoc; + } else { + return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; + } + } // Returns the index (starting from 0) of the most recent valid source string we are reading from. int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } @@ -204,6 +247,10 @@ protected: int stringBias; // the first string that is the user's string number 0 int finale; // number of internal strings after user's last string + + TSourceLoc logicalSourceLoc; + bool singleLogical; // treats the strings as a single logical string. + // locations will be reported from the first string. }; } // end namespace glslang diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 80f84a46..6034f1ab 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -132,7 +132,8 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil TIntermediate intermediate(language, version, profile); TParseContext parseContext(symbolTable, intermediate, true, version, profile, spv, vulkan, language, infoSink); - TPpContext ppContext(parseContext, TShader::ForbidInclude()); + TShader::ForbidInclude includer; + TPpContext ppContext(parseContext, "", includer); TScanContext scanContext(parseContext); parseContext.setScanContext(&scanContext); parseContext.setPpContext(&ppContext); @@ -491,7 +492,7 @@ bool ProcessDeferred( TIntermediate& intermediate, // returned tree, etc. ProcessingContext& processingContext, bool requireNonempty, - const TShader::Includer& includer + TShader::Includer& includer ) { if (! InitThread()) @@ -559,7 +560,6 @@ bool ProcessDeferred( version = defaultVersion; profile = defaultProfile; } - int spv = (messages & EShMsgSpvRules) ? 100 : 0; // TODO find path to get real version number here, for now non-0 is what matters EShSource source = (messages & EShMsgReadHlsl) ? EShSourceHlsl : EShSourceGlsl; bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, source, version, profile, spv); @@ -609,7 +609,7 @@ bool ProcessDeferred( parseContext = new TParseContext(symbolTable, intermediate, false, version, profile, spv, vulkan, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages); } - TPpContext ppContext(*parseContext, includer); + TPpContext ppContext(*parseContext, names[numPre]? names[numPre]: "", includer); // only GLSL (bison triggered, really) needs an externally set scan context glslang::TScanContext scanContext(*parseContext); @@ -886,7 +886,7 @@ bool PreprocessDeferred( bool forceDefaultVersionAndProfile, bool forwardCompatible, // give errors for use of deprecated features EShMessages messages, // warnings/errors/AST; things to print out - const TShader::Includer& includer, + TShader::Includer& includer, TIntermediate& intermediate, // returned tree, etc. std::string* outputString) { @@ -925,7 +925,7 @@ bool CompileDeferred( bool forwardCompatible, // give errors for use of deprecated features EShMessages messages, // warnings/errors/AST; things to print out TIntermediate& intermediate,// returned tree, etc. - const TShader::Includer& includer) + TShader::Includer& includer) { DoFullParse parser; return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, @@ -1074,9 +1074,10 @@ int ShCompile( compiler->infoSink.debug.erase(); TIntermediate intermediate(compiler->getLanguage()); + TShader::ForbidInclude includer; bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, "", optLevel, resources, defaultVersion, ENoProfile, false, - forwardCompatible, messages, intermediate, TShader::ForbidInclude()); + forwardCompatible, messages, intermediate, includer); // // Call the machine dependent compiler @@ -1389,7 +1390,7 @@ void TShader::setEntryPoint(const char* entryPoint) // Returns true for success. // bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages messages, const Includer& includer) + bool forwardCompatible, EShMessages messages, Includer& includer) { if (! InitThread()) return false; @@ -1417,7 +1418,7 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages message, std::string* output_string, - const TShader::Includer& includer) + Includer& includer) { if (! InitThread()) return false; diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index 9794a5d2..75f50402 100644 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -252,11 +252,14 @@ TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf) if (copyOf.numExtensions != 0) setExtensions(copyOf.numExtensions, copyOf.extensions); - if (! copyOf.unionArray.empty()) { + if (! copyOf.constArray.empty()) { assert(! copyOf.type.isStruct()); - TConstUnionArray newArray(copyOf.unionArray, 0, copyOf.unionArray.size()); - unionArray = newArray; + TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size()); + constArray = newArray; } + + // don't support specialization-constant subtrees in cloned tables + constSubtree = nullptr; } TVariable* TVariable::clone() const diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index ad73b3b5..9877ab7f 100644 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -135,7 +135,7 @@ protected: // // Variable class, meaning a symbol that's not a function. // -// There could be a separate class heirarchy for Constant variables; +// There could be a separate class hierarchy for Constant variables; // Only one of int, bool, or float, (or none) is correct for // any particular use, but it's easy to do this way, and doesn't // seem worth having separate classes, and "getConst" can't simply return @@ -144,7 +144,10 @@ protected: // class TVariable : public TSymbol { public: - TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), userType(uT) { type.shallowCopy(t); } + TVariable(const TString *name, const TType& t, bool uT = false ) + : TSymbol(name), + userType(uT), + constSubtree(nullptr) { type.shallowCopy(t); } virtual TVariable* clone() const; virtual ~TVariable() { } @@ -153,9 +156,11 @@ public: virtual const TType& getType() const { return type; } virtual TType& getWritableType() { assert(writable); return type; } virtual bool isUserType() const { return userType; } - virtual const TConstUnionArray& getConstArray() const { return unionArray; } - virtual TConstUnionArray& getWritableConstArray() { assert(writable); return unionArray; } - virtual void setConstArray(const TConstUnionArray& constArray) { unionArray = constArray; } + virtual const TConstUnionArray& getConstArray() const { return constArray; } + virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } + virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } + virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + virtual TIntermTyped* getConstSubtree() const { return constSubtree; } virtual void dump(TInfoSink &infoSink) const; @@ -167,7 +172,12 @@ protected: bool userType; // we are assuming that Pool Allocator will free the memory allocated to unionArray // when this object is destroyed - TConstUnionArray unionArray; + + // TODO: these two should be a union + // A variable could be a compile-time constant, or a specialization + // constant, or neither, but never both. + TConstUnionArray constArray; // for compile-time constant value + TIntermTyped* constSubtree; // for specialization constant computation }; // diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index b52551ff..eb6c30cd 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -48,7 +48,7 @@ namespace { bool is_positive_infinity(double x) { #ifdef _MSC_VER return _fpclass(x) == _FPCLASS_PINF; -#elif defined __ANDROID__ || defined __linux__ +#elif defined __ANDROID__ || defined __linux__ || __MINGW32__ || __MINGW64__ return std::isinf(x) && (x >= 0); #else return isinf(x) && (x >= 0); @@ -605,6 +605,11 @@ void TOutputTraverser::visitSymbol(TIntermSymbol* node) if (! node->getConstArray().empty()) OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1); + else if (node->getConstSubtree()) { + incrementDepth(node); + node->getConstSubtree()->traverse(this); + decrementDepth(); + } } bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node) diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index efffb716..42be8b90 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -167,10 +167,10 @@ public: int getNumErrors() const { return numErrors; } void addPushConstantCount() { ++numPushConstants; } bool isRecursive() const { return recursive; } - - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, const TSourceLoc&); - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); + + TIntermSymbol* addSymbol(const TVariable&); TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const; TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); @@ -331,6 +331,7 @@ public: static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor); protected: + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); void error(TInfoSink& infoSink, const char*); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index da709421..b9d00c8e 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -611,24 +611,28 @@ int TPpContext::CPPinclude(TPpToken* ppToken) if (token != '\n' && token != EndOfInput) { parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", ""); } else { - auto include = includer.include(filename.c_str()); - std::string sourceName = include.first; - std::string replacement = include.second; - if (!sourceName.empty()) { - if (!replacement.empty()) { + TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), TShader::Includer::EIncludeRelative, currentSourceFile.c_str(), includeStack.size() + 1); + if (res && !res->file_name.empty()) { + if (res->file_data && res->file_length) { const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); - std::ostringstream content; - content << "#line " << forNextLine << " " << "\"" << sourceName << "\"\n"; - content << replacement << (replacement.back() == '\n' ? "" : "\n"); - content << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; - pushInput(new TokenizableString(directiveLoc, content.str(), this)); + std::ostringstream prologue; + std::ostringstream epilogue; + prologue << "#line " << forNextLine << " " << "\"" << res->file_name << "\"\n"; + epilogue << (res->file_data[res->file_length - 1] == '\n'? "" : "\n") << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; + pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this)); } // At EOF, there's no "current" location anymore. if (token != EndOfInput) parseContext.setCurrentColumn(0); // Don't accidentally return EndOfInput, which will end all preprocessing. return '\n'; } else { - parseContext.ppError(directiveLoc, replacement.c_str(), "#include", ""); + std::string message = + res ? std::string(res->file_data, res->file_length) + : std::string("Could not process include directive"); + parseContext.ppError(directiveLoc, message.c_str(), "#include", ""); + if (res) { + includer.releaseInclude(res); + } } } } diff --git a/glslang/MachineIndependent/preprocessor/PpContext.cpp b/glslang/MachineIndependent/preprocessor/PpContext.cpp index b18ba4f6..6f0b8a9a 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.cpp +++ b/glslang/MachineIndependent/preprocessor/PpContext.cpp @@ -83,8 +83,10 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace glslang { -TPpContext::TPpContext(TParseContextBase& pc, const TShader::Includer& inclr) : - preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false) +TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) : + preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false), + rootFileName(rootFileName), + currentSourceFile(rootFileName) { InitAtomTable(); InitScanner(); diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index 6716c7e1..f65eb603 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -78,6 +78,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef PPCONTEXT_H #define PPCONTEXT_H +#include #include #include "../ParseHelper.h" @@ -121,7 +122,7 @@ class TInputScanner; // Don't expect too much in terms of OO design. class TPpContext { public: - TPpContext(TParseContextBase&, const TShader::Includer&); + TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); virtual ~TPpContext(); void setPreamble(const char* preamble, size_t length); @@ -290,7 +291,7 @@ protected: // // Used to obtain #include content. - const TShader::Includer& includer; + TShader::Includer& includer; int InitCPP(); int CPPdefine(TPpToken * ppToken); @@ -430,21 +431,40 @@ protected: TInputScanner* input; }; - // Holds a string that can be tokenized via the tInput interface. - class TokenizableString : public tInput { + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { public: - // Copies str, which must be non-empty. - TokenizableString(const TSourceLoc& startLoc, const std::string& str, TPpContext* pp) + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) : tInput(pp), - str_(str), - strings(str_.data()), - length(str_.size()), - scanner(1, &strings, &length), + prologue_(prologue), + includedFile_(includedFile), + epilogue_(epilogue), + scanner(3, strings, lengths, names, 0, 0, true), prevScanner(nullptr), - stringInput(pp, scanner) { - scanner.setLine(startLoc.line); - scanner.setString(startLoc.string); - scanner.setFile(startLoc.name); + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->file_data; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->file_length; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.name, 0); + scanner.setFile(startLoc.name, 1); + scanner.setFile(startLoc.name, 2); } // tInput methods: @@ -456,16 +476,34 @@ protected: { prevScanner = pp->parseContext.getScanner(); pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); } - void notifyDeleted() override { pp->parseContext.setScanner(prevScanner); } private: - // Stores the titular string. - const std::string str_; - // Will point to str_[0] and be passed to scanner constructor. - const char* const strings; + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->file_data and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; // Length of str_, passed to scanner constructor. - size_t length; + size_t lengths[3]; + // String names + const char* names[3]; // Scans over str_. TInputScanner scanner; // The previous effective scanner before the scanner in this instance @@ -480,6 +518,24 @@ protected: void missingEndifCheck(); int lFloatConst(int len, int ch, TPpToken* ppToken); + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->file_name; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->file_name; + } + } + bool inComment; // @@ -487,8 +543,12 @@ protected: // typedef TUnorderedMap TAtomMap; typedef TVector TStringMap; + TAtomMap atomMap; TStringMap stringMap; + std::stack includeStack; + std::string currentSourceFile; + std::string rootFileName; int nextAtom; void InitAtomTable(); void AddAtomFixed(const char* s, int atom); diff --git a/glslang/OSDependent/Unix/ossource.cpp b/glslang/OSDependent/Unix/ossource.cpp index 5ce882ab..3bd725ea 100644 --- a/glslang/OSDependent/Unix/ossource.cpp +++ b/glslang/OSDependent/Unix/ossource.cpp @@ -61,7 +61,7 @@ static void DetachThreadLinux(void *) // -// Registers cleanup handler, sets cancel type and state, and excecutes the thread specific +// Registers cleanup handler, sets cancel type and state, and executes the thread specific // cleanup handler. This function will be called in the Standalone.cpp for regression // testing. When OpenGL applications are run with the driver code, Linux OS does the // thread cleanup. diff --git a/glslang/OSDependent/Windows/CMakeLists.txt b/glslang/OSDependent/Windows/CMakeLists.txt index ff0b99e9..9bc73a37 100644 --- a/glslang/OSDependent/Windows/CMakeLists.txt +++ b/glslang/OSDependent/Windows/CMakeLists.txt @@ -4,6 +4,12 @@ set(SOURCES ossource.cpp ../osinclude.h) add_library(OSDependent STATIC ${SOURCES}) +# MinGW GCC complains about function pointer casts to void*. +# Turn that off with -fpermissive. +if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") + target_compile_options(OSDependent PRIVATE -fpermissive) +endif() + if(WIN32) source_group("Source" FILES ${SOURCES}) endif(WIN32) diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index e676211a..856af262 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -300,25 +300,90 @@ public: void setEntryPoint(const char* entryPoint); // Interface to #include handlers. + // + // To support #include, a client of Glslang does the following: + // 1. Call setStringsWithNames to set the source strings and associated + // names. For example, the names could be the names of the files + // containing the shader sources. + // 2. Call parse with an Includer. + // + // When the Glslang parser encounters an #include directive, it calls + // the Includer's include method with the the requested include name + // together with the current string name. The returned IncludeResult + // contains the fully resolved name of the included source, together + // with the source text that should replace the #include directive + // in the source stream. After parsing that source, Glslang will + // release the IncludeResult object. class Includer { public: - // On success, returns the full path and content of the file with the given - // filename that replaces "#include filename". On failure, returns an empty - // string and an error message. - virtual std::pair include(const char* filename) const = 0; + typedef enum { + EIncludeRelative, // For #include "something" + EIncludeStandard // Reserved. For #include + } IncludeType; + + // An IncludeResult contains the resolved name and content of a source + // inclusion. + struct IncludeResult { + // For a successful inclusion, the fully resolved name of the requested + // include. For example, in a filesystem-based includer, full resolution + // should convert a relative path name into an absolute path name. + // For a failed inclusion, this is an empty string. + std::string file_name; + // The content and byte length of the requested inclusion. The + // Includer producing this IncludeResult retains ownership of the + // storage. + // For a failed inclusion, the file_data + // field points to a string containing error details. + const char* file_data; + const size_t file_length; + // Include resolver's context. + void* user_data; + }; + + // Resolves an inclusion request by name, type, current source name, + // and include depth. + // On success, returns an IncludeResult containing the resolved name + // and content of the include. On failure, returns an IncludeResult + // with an empty string for the file_name and error details in the + // file_data field. The Includer retains ownership of the contents + // of the returned IncludeResult value, and those contents must + // remain valid until the releaseInclude method is called on that + // IncludeResult object. + virtual IncludeResult* include(const char* requested_source, + IncludeType type, + const char* requesting_source, + size_t inclusion_depth) = 0; + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult* result) = 0; }; // Returns an error message for any #include directive. class ForbidInclude : public Includer { public: - std::pair include(const char* /*filename*/) const override + IncludeResult* include(const char*, IncludeType, const char*, size_t) override { - return std::make_pair("", "unexpected include directive"); + static const char unexpected_include[] = + "unexpected include directive"; + static const IncludeResult unexpectedIncludeResult = + {"", unexpected_include, sizeof(unexpected_include) - 1, nullptr}; + return new IncludeResult(unexpectedIncludeResult); + } + virtual void releaseInclude(IncludeResult* result) override + { + delete result; } }; + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages messages) + { + TShader::ForbidInclude includer; + return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); + } + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages, const Includer& = ForbidInclude()); + bool forwardCompatible, EShMessages, Includer&); // Equivalent to parse() without a default profile and without forcing defaults. // Provided for backwards compatibility. @@ -326,7 +391,7 @@ public: bool preprocess(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages message, std::string* outputString, - const TShader::Includer& includer); + Includer& includer); const char* getInfoLog(); const char* getInfoDebugLog(); diff --git a/gtests/AST.FromFile.cpp b/gtests/AST.FromFile.cpp new file mode 100644 index 00000000..5e0b31e9 --- /dev/null +++ b/gtests/AST.FromFile.cpp @@ -0,0 +1,191 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using CompileToAstTest = GlslangTest<::testing::TestWithParam>; + +TEST_P(CompileToAstTest, FromFile) +{ + loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), + Semantics::OpenGL, Target::AST); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + Glsl, CompileToAstTest, + ::testing::ValuesIn(std::vector({ + "sample.frag", + "sample.vert", + "decls.frag", + "specExamples.frag", + "specExamples.vert", + "versionsClean.frag", + "versionsClean.vert", + "versionsErrors.frag", + "versionsErrors.vert", + "100.frag", + "120.vert", + "120.frag", + "130.vert", + "130.frag", + "140.vert", + "140.frag", + "150.vert", + "150.geom", + "150.frag", + "precision.frag", + "precision.vert", + "nonSquare.vert", + "matrixError.vert", + "cppSimple.vert", + "cppIndent.vert", + "cppNest.vert", + "cppComplexExpr.vert", + "badChars.frag", + "pointCoord.frag", + "array.frag", + "array100.frag", + "comment.frag", + "300.vert", + "300.frag", + "300BuiltIns.frag", + "300layout.vert", + "300layout.frag", + "300operations.frag", + "300block.frag", + "310.comp", + "310.vert", + "310.geom", + "310.frag", + "310.tesc", + "310.tese", + "310implicitSizeArrayError.vert", + "310AofA.vert", + "330.frag", + "330comp.frag", + "constErrors.frag", + "constFold.frag", + "errors.frag", + "forwardRef.frag", + "uint.frag", + "switch.frag", + "tokenLength.vert", + "100Limits.vert", + "100scope.vert", + "110scope.vert", + "300scope.vert", + "400.frag", + "420.frag", + "420.vert", + "420.geom", + "420_size_gl_in.geom", + "430scope.vert", + "lineContinuation100.vert", + "lineContinuation.vert", + "numeral.frag", + "400.geom", + "400.tesc", + "400.tese", + "410.tesc", + "420.tesc", + "420.tese", + "410.geom", + "430.vert", + "430.comp", + "430AofA.frag", + "440.vert", + "440.frag", + "450.vert", + "450.geom", + "450.tesc", + "450.tese", + "450.frag", + "450.comp", + "dce.frag", + "atomic_uint.frag", + "aggOps.frag", + "always-discard.frag", + "always-discard2.frag", + "conditionalDiscard.frag", + "conversion.frag", + "dataOut.frag", + "dataOutIndirect.frag", + "deepRvalue.frag", + "depthOut.frag", + "discard-dce.frag", + "doWhileLoop.frag", + "earlyReturnDiscard.frag", + "flowControl.frag", + "forLoop.frag", + "functionCall.frag", + "functionSemantics.frag", + "length.frag", + "localAggregates.frag", + "loops.frag", + "loopsArtificial.frag", + "matrix.frag", + "matrix2.frag", + "newTexture.frag", + "Operations.frag", + "prepost.frag", + "simpleFunctionCall.frag", + "structAssignment.frag", + "structDeref.frag", + "structure.frag", + "swizzle.frag", + "syntaxError.frag", + "test.frag", + "texture.frag", + "types.frag", + "uniformArray.frag", + "variableArrayIndex.frag", + "varyingArray.frag", + "varyingArrayIndirect.frag", + "voidFunction.frag", + "whileLoop.frag", + "nonVulkan.frag", + "spv.atomic.comp", + })), + FileNameAsCustomTestName +); +// clang-format on + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/BuiltInResource.FromFile.cpp b/gtests/BuiltInResource.FromFile.cpp new file mode 100644 index 00000000..c2d2b8b6 --- /dev/null +++ b/gtests/BuiltInResource.FromFile.cpp @@ -0,0 +1,57 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include "StandAlone/DefaultResourceLimits.h" +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using DefaultResourceTest = GlslangTest<::testing::Test>; + +TEST_F(DefaultResourceTest, FromFile) +{ + const std::string path = GLSLANG_TEST_DIRECTORY "/baseResults/test.conf"; + std::string expectedConfig; + tryLoadFile(path, "expected resource limit", &expectedConfig); + const std::string realConfig = glslang::GetDefaultTBuiltInResourceString(); + ASSERT_EQ(expectedConfig, realConfig); +} + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/CMakeLists.txt b/gtests/CMakeLists.txt new file mode 100644 index 00000000..57378cea --- /dev/null +++ b/gtests/CMakeLists.txt @@ -0,0 +1,32 @@ +if (TARGET gmock) + message(STATUS "Google Mock found - building tests") + + set(TEST_SOURCES + # Framework related source files + ${CMAKE_CURRENT_SOURCE_DIR}/Initializer.h + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Settings.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Settings.h + ${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.h + + # Test related source files + ${CMAKE_CURRENT_SOURCE_DIR}/AST.FromFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BuiltInResource.FromFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Pp.FromFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Spv.FromFile.cpp + ) + + add_executable(glslangtests ${TEST_SOURCES}) + target_compile_definitions(glslangtests + PRIVATE GLSLANG_TEST_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/../Test") + target_include_directories(glslangtests PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${gmock_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/include) + target_link_libraries(glslangtests PRIVATE + glslang OSDependent OGLCompiler glslang + SPIRV glslang-default-resource-limits gmock) + add_test(NAME glslang-gtests COMMAND glslangtests) +endif() diff --git a/gtests/Initializer.h b/gtests/Initializer.h new file mode 100644 index 00000000..e8fa30d1 --- /dev/null +++ b/gtests/Initializer.h @@ -0,0 +1,119 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_GTESTS_INITIALIZER_H +#define GLSLANG_GTESTS_INITIALIZER_H + +#include + +#include "glslang/Public/ShaderLang.h" + +namespace glslangtest { + +// Initializes glslang on creation, and destroys it on completion. +// And provides .Acquire() as a way to reinitialize glslang if semantics change. +// This object is expected to be a singleton, so that internal glslang state +// can be correctly handled. +// +// TODO(antiagainst): It's a known bug that some of the internal states need to +// be reset if semantics change: +// https://github.com/KhronosGroup/glslang/issues/166 +// Therefore, the following mechanism is needed. Remove this once the above bug +// gets fixed. +class GlslangInitializer { +public: + GlslangInitializer() : lastMessages(EShMsgDefault) + { + glslang::InitializeProcess(); + } + + ~GlslangInitializer() { glslang::FinalizeProcess(); } + + // A token indicates that the glslang is reinitialized (if necessary) to the + // required semantics. And that won't change until the token is destroyed. + class InitializationToken { + public: + InitializationToken() : initializer(nullptr) {} + ~InitializationToken() + { + if (initializer) { + initializer->release(); + } + } + + InitializationToken(InitializationToken&& other) + : initializer(other.initializer) + { + other.initializer = nullptr; + } + + InitializationToken(const InitializationToken&) = delete; + + private: + InitializationToken(GlslangInitializer* initializer) + : initializer(initializer) {} + + friend class GlslangInitializer; + GlslangInitializer* initializer; + }; + + // Obtains exclusive access to the glslang state. The state remains + // exclusive until the Initialization Token has been destroyed. + // Re-initializes glsl state iff the previous messages and the current + // messages are incompatible. + InitializationToken acquire(EShMessages new_messages) + { + stateLock.lock(); + + if ((lastMessages ^ new_messages) & + (EShMsgVulkanRules | EShMsgSpvRules)) { + glslang::FinalizeProcess(); + glslang::InitializeProcess(); + } + lastMessages = new_messages; + return InitializationToken(this); + } + +private: + void release() { stateLock.unlock(); } + + friend class InitializationToken; + + EShMessages lastMessages; + std::mutex stateLock; +}; + +} // namespace glslangtest + +#endif // GLSLANG_GTESTS_INITIALIZER_H diff --git a/gtests/Pp.FromFile.cpp b/gtests/Pp.FromFile.cpp new file mode 100644 index 00000000..cfd987ba --- /dev/null +++ b/gtests/Pp.FromFile.cpp @@ -0,0 +1,74 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using PreprocessingTest = GlslangTest<::testing::TestWithParam>; + +TEST_P(PreprocessingTest, FromFile) +{ + loadFilePreprocessAndCheck(GLSLANG_TEST_DIRECTORY, GetParam()); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + Glsl, PreprocessingTest, + ::testing::ValuesIn(std::vector({ + "preprocessor.cpp_style_line_directive.vert", + "preprocessor.cpp_style___FILE__.vert", + "preprocessor.edge_cases.vert", + "preprocessor.errors.vert", + "preprocessor.extensions.vert", + "preprocessor.function_macro.vert", + "preprocessor.include.enabled.vert", + "preprocessor.include.disabled.vert", + "preprocessor.line.vert", + "preprocessor.line.frag", + "preprocessor.pragma.vert", + "preprocessor.simple.vert", + "preprocessor.success_if_parse_would_fail.vert", + "preprocessor.defined.vert", + "preprocessor.many.endif.vert", + })), + FileNameAsCustomTestName +); +// clang-format on + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/README.md b/gtests/README.md new file mode 100644 index 00000000..c8261cc4 --- /dev/null +++ b/gtests/README.md @@ -0,0 +1,26 @@ +Glslang Tests based on the Google Test Framework +================================================ + +This directory contains [Google Test][gtest] based test fixture and test +cases for glslang. + +Apart from typical unit tests, necessary utility methods are added into +the [`GlslangTests`](TestFixture.h) fixture to provide the ability to do +file-based integration tests. Various `*.FromFile.cpp` files lists names +of files containing input shader code in the `Test/` directory. Utility +methods will load the input shader source, compile them, and compare with +the corresponding expected output in the `Test/baseResults/` directory. + +How to run the tests +-------------------- + +Please make sure you have a copy of [Google Test][gtest] checked out under +the `External` directory before building. After building, just run the +`ctest` command or the `gtests/glslangtests` binary in your build directory. + +The `gtests/glslangtests` binary also provides an `--update-mode` command +line option, which, if supplied, will overwrite the golden files under +the `Test/baseResults/` directory with real output from that invocation. +This serves as an easy way to update golden files. + +[gtest]: https://github.com/google/googletest diff --git a/gtests/Settings.cpp b/gtests/Settings.cpp new file mode 100644 index 00000000..4ba7989b --- /dev/null +++ b/gtests/Settings.cpp @@ -0,0 +1,41 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "Settings.h" + +namespace glslangtest { + +GTestSettings GlobalTestSettings = {nullptr, false}; + +} // namespace glslangtest diff --git a/gtests/Settings.h b/gtests/Settings.h new file mode 100644 index 00000000..30056a7b --- /dev/null +++ b/gtests/Settings.h @@ -0,0 +1,54 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_GTESTS_SETTINGS_H +#define GLSLANG_GTESTS_SETTINGS_H + +namespace glslangtest { + +class GlslangInitializer; + +struct GTestSettings { + // A handle to GlslangInitializer instance. + GlslangInitializer* initializer; + // An indicator of whether GTest should write real output to the file for + // the expected output. + bool updateMode; +}; + +extern GTestSettings GlobalTestSettings; + +} // namespace glslangtest + +#endif // GLSLANG_GTESTS_SETTINGS_H diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp new file mode 100644 index 00000000..9cd0787a --- /dev/null +++ b/gtests/Spv.FromFile.cpp @@ -0,0 +1,188 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include "TestFixture.h" + +namespace glslangtest { +namespace { + +using CompileToSpirvTest = GlslangTest<::testing::TestWithParam>; +using VulkanSemantics = GlslangTest<::testing::TestWithParam>; + +// Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully +// generate SPIR-V. +TEST_P(CompileToSpirvTest, FromFile) +{ + loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), + Semantics::Vulkan, Target::Spirv); +} + +// GLSL-level Vulkan semantics test. Expected to error out before generating +// SPIR-V. +TEST_P(VulkanSemantics, FromFile) +{ + loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), + Semantics::Vulkan, Target::Spirv); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + Glsl, CompileToSpirvTest, + ::testing::ValuesIn(std::vector({ + // Test looping constructs. + // No tests yet for making sure break and continue from a nested loop + // goes to the innermost target. + "spv.do-simple.vert", + "spv.do-while-continue-break.vert", + "spv.for-complex-condition.vert", + "spv.for-continue-break.vert", + "spv.for-simple.vert", + "spv.for-notest.vert", + "spv.for-nobody.vert", + "spv.while-continue-break.vert", + "spv.while-simple.vert", + // vulkan-specific tests + "spv.set.vert", + "spv.double.comp", + "spv.100ops.frag", + "spv.130.frag", + "spv.140.frag", + "spv.150.geom", + "spv.150.vert", + "spv.300BuiltIns.vert", + "spv.300layout.frag", + "spv.300layout.vert", + "spv.300layoutp.vert", + "spv.310.comp", + "spv.330.geom", + "spv.400.frag", + "spv.400.tesc", + "spv.400.tese", + "spv.420.geom", + "spv.430.vert", + "spv.accessChain.frag", + "spv.aggOps.frag", + "spv.always-discard.frag", + "spv.always-discard2.frag", + "spv.bitCast.frag", + "spv.bool.vert", + "spv.boolInBlock.frag", + "spv.branch-return.vert", + "spv.conditionalDiscard.frag", + "spv.conversion.frag", + "spv.dataOut.frag", + "spv.dataOutIndirect.frag", + "spv.dataOutIndirect.vert", + "spv.deepRvalue.frag", + "spv.depthOut.frag", + "spv.discard-dce.frag", + "spv.doWhileLoop.frag", + "spv.earlyReturnDiscard.frag", + "spv.flowControl.frag", + "spv.forLoop.frag", + "spv.forwardFun.frag", + "spv.functionCall.frag", + "spv.functionSemantics.frag", + "spv.interpOps.frag", + "spv.layoutNested.vert", + "spv.length.frag", + "spv.localAggregates.frag", + "spv.loops.frag", + "spv.loopsArtificial.frag", + "spv.matFun.vert", + "spv.matrix.frag", + "spv.matrix2.frag", + "spv.memoryQualifier.frag", + "spv.merge-unreachable.frag", + "spv.newTexture.frag", + "spv.noDeadDecorations.vert", + "spv.nonSquare.vert", + "spv.Operations.frag", + "spv.intOps.vert", + "spv.precision.frag", + "spv.prepost.frag", + "spv.qualifiers.vert", + "spv.shiftOps.frag", + "spv.simpleFunctionCall.frag", + "spv.simpleMat.vert", + "spv.sparseTexture.frag", + "spv.sparseTextureClamp.frag", + "spv.structAssignment.frag", + "spv.structDeref.frag", + "spv.structure.frag", + "spv.switch.frag", + "spv.swizzle.frag", + "spv.test.frag", + "spv.test.vert", + "spv.texture.frag", + "spv.texture.vert", + "spv.image.frag", + "spv.types.frag", + "spv.uint.frag", + "spv.uniformArray.frag", + "spv.variableArrayIndex.frag", + "spv.varyingArray.frag", + "spv.varyingArrayIndirect.frag", + "spv.voidFunction.frag", + "spv.whileLoop.frag", + "spv.AofA.frag", + "spv.queryL.frag", + "spv.separate.frag", + "spv.shortCircuit.frag", + "spv.pushConstant.vert", + "spv.subpass.frag", + "spv.specConstant.vert", + "spv.specConstant.comp", + "spv.specConstantComposite.vert", + })), + FileNameAsCustomTestName +); + +INSTANTIATE_TEST_CASE_P( + Glsl, VulkanSemantics, + ::testing::ValuesIn(std::vector({ + "vulkan.frag", + "vulkan.vert", + "vulkan.comp", + })), + FileNameAsCustomTestName +); +// clang-format on + +} // anonymous namespace +} // namespace glslangtest diff --git a/gtests/TestFixture.cpp b/gtests/TestFixture.cpp new file mode 100644 index 00000000..744fa558 --- /dev/null +++ b/gtests/TestFixture.cpp @@ -0,0 +1,124 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "TestFixture.h" + +namespace glslangtest { + +std::string FileNameAsCustomTestName( + const ::testing::TestParamInfo& info) +{ + std::string name = info.param; + // A valid test case suffix cannot have '.' and '-' inside. + std::replace(name.begin(), name.end(), '.', '_'); + std::replace(name.begin(), name.end(), '-', '_'); + return name; +} + +EShLanguage GetGlslLanguageForStage(const std::string& stage) +{ + if (stage == "vert") { + return EShLangVertex; + } else if (stage == "tesc") { + return EShLangTessControl; + } else if (stage == "tese") { + return EShLangTessEvaluation; + } else if (stage == "geom") { + return EShLangGeometry; + } else if (stage == "frag") { + return EShLangFragment; + } else if (stage == "comp") { + return EShLangCompute; + } else { + assert(0 && "Unknown shader stage"); + return EShLangCount; + } +} + +EShMessages GetSpirvMessageOptionsForSemanticsAndTarget(Semantics semantics, + Target target) +{ + EShMessages result = EShMsgDefault; + + switch (target) { + case Target::AST: + result = EShMsgAST; + break; + case Target::Spirv: + result = EShMsgSpvRules; + break; + }; + + switch (semantics) { + case Semantics::OpenGL: + break; + case Semantics::Vulkan: + result = static_cast(result | EShMsgVulkanRules); + break; + } + + return result; +} + +std::pair ReadFile(const std::string& path) +{ + std::ifstream fstream(path, std::ios::in); + if (fstream) { + std::string contents; + fstream.seekg(0, std::ios::end); + contents.reserve(fstream.tellg()); + fstream.seekg(0, std::ios::beg); + contents.assign((std::istreambuf_iterator(fstream)), + std::istreambuf_iterator()); + return std::make_pair(true, contents); + } + return std::make_pair(false, ""); +} + +bool WriteFile(const std::string& path, const std::string& contents) +{ + std::ofstream fstream(path, std::ios::out); + if (!fstream) return false; + fstream << contents; + fstream.flush(); + return true; +} + +std::string GetSuffix(const std::string& name) +{ + const size_t pos = name.rfind('.'); + return (pos == std::string::npos) ? "" : name.substr(name.rfind('.') + 1); +} + +} // namespace glslangtest diff --git a/gtests/TestFixture.h b/gtests/TestFixture.h new file mode 100644 index 00000000..87a365b5 --- /dev/null +++ b/gtests/TestFixture.h @@ -0,0 +1,307 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_GTESTS_TEST_FIXTURE_H +#define GLSLANG_GTESTS_TEST_FIXTURE_H + +#include +#include +#include +#include +#include + +#include + +#include "SPIRV/GlslangToSpv.h" +#include "SPIRV/disassemble.h" +#include "SPIRV/doc.h" +#include "StandAlone/DefaultResourceLimits.h" +#include "glslang/Public/ShaderLang.h" + +#include "Initializer.h" +#include "Settings.h" + +// We need CMake to provide us the absolute path to the directory containing +// test files, so we are certain to find those files no matter where the test +// harness binary is generated. This provides out-of-source build capability. +#ifndef GLSLANG_TEST_DIRECTORY +#error \ + "GLSLANG_TEST_DIRECTORY needs to be defined for gtest to locate test files." +#endif + +namespace glslangtest { + +// This function is used to provide custom test name suffixes based on the +// shader source file names. Otherwise, the test name suffixes will just be +// numbers, which are not quite obvious. +std::string FileNameAsCustomTestName( + const ::testing::TestParamInfo& info); + +// Enum for shader compilation semantics. +enum class Semantics { + OpenGL, + Vulkan, +}; + +// Enum for compilation target. +enum class Target { + AST, + Spirv, +}; + +EShLanguage GetGlslLanguageForStage(const std::string& stage); + +EShMessages GetSpirvMessageOptionsForSemanticsAndTarget(Semantics semantics, + Target target); + +// Reads the content of the file at the given |path|. On success, returns true +// and the contents; otherwise, returns false and an empty string. +std::pair ReadFile(const std::string& path); + +// Writes the given |contents| into the file at the given |path|. Returns true +// on successful output. +bool WriteFile(const std::string& path, const std::string& contents); + +// Returns the suffix of the given |name|. +std::string GetSuffix(const std::string& name); + +// Base class for glslang integration tests. It contains many handy utility-like +// methods such as reading shader source files, compiling into AST/SPIR-V, and +// comparing with expected outputs. +// +// To write value-Parameterized tests: +// using ValueParamTest = GlslangTest<::testing::TestWithParam>; +// To use as normal fixture: +// using FixtureTest = GlslangTest<::testing::Test>; +template +class GlslangTest : public GT { +public: + GlslangTest() + : defaultVersion(100), + defaultProfile(ENoProfile), + forceVersionProfile(false), + isForwardCompatible(false) {} + + // Tries to load the contents from the file at the given |path|. On success, + // writes the contents into |contents|. On failure, errors out. + void tryLoadFile(const std::string& path, const std::string& tag, + std::string* contents) + { + bool fileReadOk; + std::tie(fileReadOk, *contents) = ReadFile(path); + ASSERT_TRUE(fileReadOk) << "Cannot open " << tag << " file: " << path; + } + + // Checks the equality of |expected| and |real|. If they are not equal, + // write + // |real| to the given file named as |fname| if update mode is on. + void checkEqAndUpdateIfRequested(const std::string& expected, + const std::string& real, + const std::string& fname) + { + // In order to output the message we want under proper circumstances, we + // need the following operator<< stuff. + EXPECT_EQ(expected, real) + << (GlobalTestSettings.updateMode + ? ("Mismatch found and update mode turned on - " + "flushing expected result output.") + : ""); + + // Update the expected output file if requested. + // It looks weird to duplicate the comparison between expected_output + // and + // stream.str(). However, if creating a variable for the comparison + // result, + // we cannot have pretty print of the string diff in the above. + if (GlobalTestSettings.updateMode && expected != real) { + EXPECT_TRUE(WriteFile(fname, real)) << "Flushing failed"; + } + } + + // A struct for holding all the information returned by glslang compilation + // and linking. + struct GlslangResult { + const std::string compilationOutput; + const std::string compilationError; + const std::string linkingOutput; + const std::string linkingError; + const std::string spirv; // Optional SPIR-V disassembly text. + }; + + // Compiles and linkes the given GLSL |source| code of the given shader + // |stage| into the given |target| under the given |semantics|. Returns + // a GlslangResult instance containing all the information generated + // during the process. If |target| is Target::Spirv, also disassembles + // the result and returns disassembly text. + GlslangResult compileGlsl(const std::string& source, + const std::string& stage, Semantics semantics, + Target target) + { + const char* shaderStrings = source.data(); + const int shaderLengths = static_cast(source.size()); + const EShLanguage language = GetGlslLanguageForStage(stage); + + glslang::TShader shader(language); + shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1); + const EShMessages messages = + GetSpirvMessageOptionsForSemanticsAndTarget(semantics, target); + // Reinitialize glslang if the semantics change. + GlslangInitializer::InitializationToken token = + GlobalTestSettings.initializer->acquire(messages); + bool success = + shader.parse(&glslang::DefaultTBuiltInResource, defaultVersion, + isForwardCompatible, messages); + + glslang::TProgram program; + program.addShader(&shader); + success &= program.link(messages); + + if (success && target == Target::Spirv) { + std::vector spirv_binary; + glslang::GlslangToSpv(*program.getIntermediate(language), + spirv_binary); + + std::ostringstream disassembly_stream; + spv::Parameterize(); + spv::Disassemble(disassembly_stream, spirv_binary); + return {shader.getInfoLog(), shader.getInfoDebugLog(), + program.getInfoLog(), program.getInfoDebugLog(), + disassembly_stream.str()}; + } else { + return {shader.getInfoLog(), shader.getInfoDebugLog(), + program.getInfoLog(), program.getInfoDebugLog(), ""}; + } + } + + void loadFileCompileAndCheck(const std::string& testDir, + const std::string& testName, + Semantics semantics, Target target) + { + 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); + + GlslangResult result = + compileGlsl(input, GetSuffix(testName), semantics, target); + + // Generate the hybrid output in the way of glslangValidator. + std::ostringstream stream; + + const auto outputIfNotEmpty = [&stream](const std::string& str) { + if (!str.empty()) stream << str << "\n"; + }; + + stream << testName << "\n"; + outputIfNotEmpty(result.compilationOutput); + outputIfNotEmpty(result.compilationError); + outputIfNotEmpty(result.linkingOutput); + outputIfNotEmpty(result.linkingError); + if (target == Target::Spirv) { + stream + << (result.spirv.empty() + ? "SPIR-V is not generated for failed compile or link\n" + : result.spirv); + } + + checkEqAndUpdateIfRequested(expectedOutput, stream.str(), + expectedOutputFname); + } + + // Preprocesses the given GLSL |source| code. On success, returns true, the + // preprocessed shader, and warning messages. Otherwise, returns false, an + // empty string, and error messages. + std::tuple preprocessGlsl( + const std::string& source) + { + const char* shaderStrings = source.data(); + const int shaderLengths = static_cast(source.size()); + + glslang::TShader shader(EShLangVertex); + shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1); + std::string ppShader; + glslang::TShader::ForbidInclude includer; + const bool success = shader.preprocess( + &glslang::DefaultTBuiltInResource, defaultVersion, defaultProfile, + forceVersionProfile, isForwardCompatible, EShMsgOnlyPreprocessor, + &ppShader, includer); + + std::string log = shader.getInfoLog(); + log += shader.getInfoDebugLog(); + if (success) { + return std::make_tuple(true, ppShader, log); + } else { + return std::make_tuple(false, "", log); + } + } + + void loadFilePreprocessAndCheck(const std::string& testDir, + const std::string& testName) + { + const std::string inputFname = testDir + "/" + testName; + const std::string expectedOutputFname = + testDir + "/baseResults/" + testName + ".out"; + const std::string expectedErrorFname = + testDir + "/baseResults/" + testName + ".err"; + std::string input, expectedOutput, expectedError; + + tryLoadFile(inputFname, "input", &input); + tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); + tryLoadFile(expectedErrorFname, "expected error", &expectedError); + + bool ppOk; + std::string output, error; + std::tie(ppOk, output, error) = preprocessGlsl(input); + if (!output.empty()) output += '\n'; + if (!error.empty()) error += '\n'; + + checkEqAndUpdateIfRequested(expectedOutput, output, + expectedOutputFname); + checkEqAndUpdateIfRequested(expectedError, error, + expectedErrorFname); + } + +private: + const int defaultVersion; + const EProfile defaultProfile; + const bool forceVersionProfile; + const bool isForwardCompatible; +}; + +} // namespace glslangtest + +#endif // GLSLANG_GTESTS_TEST_FIXTURE_H diff --git a/gtests/main.cpp b/gtests/main.cpp new file mode 100644 index 00000000..b9806aa2 --- /dev/null +++ b/gtests/main.cpp @@ -0,0 +1,63 @@ +// +// Copyright (C) 2016 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 Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include "Initializer.h" +#include "Settings.h" + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + + std::unique_ptr initializer( + new glslangtest::GlslangInitializer); + + glslangtest::GlobalTestSettings.initializer = initializer.get(); + + for (int i = 1; i < argc; ++i) { + if (!strncmp("--update-mode", argv[i], 13)) { + glslangtest::GlobalTestSettings.updateMode = true; + break; + } + } + + const int result = RUN_ALL_TESTS(); + + glslangtest::GlobalTestSettings.initializer = nullptr; + + return result; +} diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 95a266fd..534174d0 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -743,7 +743,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l loc); } } else - paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(0, "", *param.type, loc), loc); + paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); } intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); loopNestingLevel = 0;