From c5215791f5fbfb16030e3d3ae2a426490c073618 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Tue, 27 Feb 2018 13:23:08 -0700 Subject: [PATCH] IO mapper: Fix #1261: Supply location mapper with size computer. This factored computeTypeLocationSize() out of needing the TIntermediate contents, and uses it to show how to know how many locations an object needs. However, it still does not do cross stage, or mixed location/no-location analysis. --- SPIRV/GlslangToSpv.cpp | 3 ++- glslang/MachineIndependent/ParseHelper.cpp | 3 ++- glslang/MachineIndependent/iomapper.cpp | 25 +++++++++++-------- glslang/MachineIndependent/linkValidate.cpp | 16 ++++++------ .../MachineIndependent/localintermediate.h | 2 +- hlsl/hlslParseHelper.cpp | 8 +++--- 6 files changed, 32 insertions(+), 25 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 7c69242e1..420c38ecf 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 5382f437a..434ba198f 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 a7d9d91d1..a0b5a7fba 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 59284bc6d..87f08e3b6 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 b0ef5fd03..26c753228 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 e56480f45..2395dafe9 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); } } }