diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 7c69242e..420c38ec 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -2668,7 +2668,8 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation); if (qualifier.hasLocation()) // track for upcoming inheritance - locationOffset += glslangIntermediate->computeTypeLocationSize(glslangMember); + locationOffset += glslangIntermediate->computeTypeLocationSize( + glslangMember, glslangIntermediate->getStage()); // component, XFB, others if (glslangMember.getQualifier().hasComponent()) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 5382f437..434ba198 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -6083,7 +6083,8 @@ void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifi memberQualifier.layoutLocation = nextLocation; memberQualifier.layoutComponent = TQualifier::layoutComponentEnd; } - nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(*typeList[member].type); + nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize( + *typeList[member].type, language); } } } diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp index a7d9d91d..a0b5a7fb 100644 --- a/glslang/MachineIndependent/iomapper.cpp +++ b/glslang/MachineIndependent/iomapper.cpp @@ -353,7 +353,9 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver { TDefaultIoResolverBase(const TIntermediate &intermediate) : intermediate(intermediate), - nextUniformLocation(0) + nextUniformLocation(0), + nextInputLocation(0), + nextOutputLocation(0) { } int getBaseBinding(TResourceType res, unsigned int set) const { @@ -446,7 +448,7 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver { return true; } - int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override + int resolveInOutLocation(EShLanguage stage, const char* /*name*/, const TType& type, bool /*is_live*/) override { // kick out of not doing this if (!doAutoLocationMapping()) @@ -464,14 +466,15 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver return -1; } - // Placeholder. - // TODO: It would be nice to flesh this out using - // intermediate->computeTypeLocationSize(type), or functions that call it like - // intermediate->addUsedLocation() - // These in turn would want the intermediate, which is not available here, but - // is available in many places, and a lot of copying from it could be saved if - // it were just available. - return 0; + // point to the right input or output location counter + int& nextLocation = type.getQualifier().isPipeInput() ? nextInputLocation : nextOutputLocation; + + // Placeholder. This does not do proper cross-stage lining up, nor + // work with mixed location/no-location declarations. + int location = nextLocation; + nextLocation += TIntermediate::computeTypeLocationSize(type, stage); + + return location; } int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override { @@ -492,6 +495,8 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver protected: const TIntermediate &intermediate; int nextUniformLocation; + int nextInputLocation; + int nextOutputLocation; // Return descriptor set specific base if there is one, and the generic base otherwise. int selectBaseBinding(int base, int descriptorSetBase) const { diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 59284bc6..87f08e3b 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -773,9 +773,9 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ // Strip off the outer array dimension for those having an extra one. if (type.isArray() && qualifier.isArrayedIo(language)) { TType elementType(type, 0); - size = computeTypeLocationSize(elementType); + size = computeTypeLocationSize(elementType, language); } else - size = computeTypeLocationSize(type); + size = computeTypeLocationSize(type, language); } // Locations, and components within locations. @@ -907,7 +907,7 @@ bool TIntermediate::addUsedConstantId(int id) // Recursively figure out how many locations are used up by an input or output type. // Return the size of type, as measured by "locations". -int TIntermediate::computeTypeLocationSize(const TType& type) const +int TIntermediate::computeTypeLocationSize(const TType& type, EShLanguage stage) { // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n // consecutive locations..." @@ -916,9 +916,9 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const TType elementType(type, 0); if (type.isImplicitlySizedArray()) { // TODO: are there valid cases of having an implicitly-sized array with a location? If so, running this code too early. - return computeTypeLocationSize(elementType); + return computeTypeLocationSize(elementType, stage); } else - return type.getOuterArraySize() * computeTypeLocationSize(elementType); + return type.getOuterArraySize() * computeTypeLocationSize(elementType, stage); } // "The locations consumed by block and structure members are determined by applying the rules above @@ -927,7 +927,7 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const int size = 0; for (int member = 0; member < (int)type.getStruct()->size(); ++member) { TType memberType(type, member); - size += computeTypeLocationSize(memberType); + size += computeTypeLocationSize(memberType, stage); } return size; } @@ -941,7 +941,7 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const if (type.isScalar()) return 1; if (type.isVector()) { - if (language == EShLangVertex && type.getQualifier().isPipeInput()) + if (stage == EShLangVertex && type.getQualifier().isPipeInput()) return 1; if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2) return 2; @@ -954,7 +954,7 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const // for an n-element array of m-component vectors..." if (type.isMatrix()) { TType columnType(type, 0); - return type.getMatrixCols() * computeTypeLocationSize(columnType); + return type.getMatrixCols() * computeTypeLocationSize(columnType, stage); } assert(0); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index b0ef5fd0..26c75322 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -575,7 +575,7 @@ public: int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); int addUsedOffsets(int binding, int offset, int numOffsets); bool addUsedConstantId(int id); - int computeTypeLocationSize(const TType&) const; + static int computeTypeLocationSize(const TType&, EShLanguage); bool setXfbBufferStride(int buffer, unsigned stride) { diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index e56480f4..2395dafe 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -1256,7 +1256,7 @@ int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType& // inherited locations must be auto bumped, not replicated if (flattenData.nextLocation != TQualifier::layoutLocationEnd) { memberVariable->getWritableType().getQualifier().layoutLocation = flattenData.nextLocation; - flattenData.nextLocation += intermediate.computeTypeLocationSize(memberVariable->getType()); + flattenData.nextLocation += intermediate.computeTypeLocationSize(memberVariable->getType(), language); nextOutLocation = std::max(nextOutLocation, flattenData.nextLocation); } } @@ -1536,9 +1536,9 @@ void HlslParseContext::assignToInterface(TVariable& variable) int size; if (type.isArray() && qualifier.isArrayedIo(language)) { TType elementType(type, 0); - size = intermediate.computeTypeLocationSize(elementType); + size = intermediate.computeTypeLocationSize(elementType, language); } else - size = intermediate.computeTypeLocationSize(type); + size = intermediate.computeTypeLocationSize(type, language); if (qualifier.storage == EvqVaryingIn) { variable.getWritableType().getQualifier().layoutLocation = nextInLocation; @@ -8633,7 +8633,7 @@ void HlslParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qual memberQualifier.layoutComponent = 0; } nextLocation = memberQualifier.layoutLocation + - intermediate.computeTypeLocationSize(*typeList[member].type); + intermediate.computeTypeLocationSize(*typeList[member].type, language); } } }