diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2019-02-28 11:54:59 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2019-03-06 14:12:15 +0000 |
commit | f875e7156fa4a2772a6622949877db66aebdacca (patch) | |
tree | b837afa3c36de0a1d94db0bbebfd3a4aa654d517 /src/render/renderers/opengl | |
parent | a356d132b2a426ecd7edb7858245266433b3e855 (diff) |
QSortPolicy: add sorting by Texture
It can be more efficient to render a scene by sorting drawing commands based on
the textures they are requiring. In conjunction with Material sorting, this can
reduce the amount of GL calls being sent to the driver.
[ChangeLog][Qt3DRender] QSortPolicy can now sort by Texture
Change-Id: Ibc013e9d506ea3061b19a56c548e8184f2b981cc
Reviewed-by: Mike Krus <mike.krus@kdab.com>
Diffstat (limited to 'src/render/renderers/opengl')
-rw-r--r-- | src/render/renderers/opengl/renderer/renderview.cpp | 53 | ||||
-rw-r--r-- | src/render/renderers/opengl/renderer/shaderparameterpack_p.h | 12 |
2 files changed, 65 insertions, 0 deletions
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp index 3aa45c836..ff43e74f4 100644 --- a/src/render/renderers/opengl/renderer/renderview.cpp +++ b/src/render/renderers/opengl/renderer/renderview.cpp @@ -321,6 +321,27 @@ struct AdjacentSubRangeFinder<QSortPolicy::FrontToBack> } }; +template<> +struct AdjacentSubRangeFinder<QSortPolicy::Texture> +{ + static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) + { + // Two renderCommands are adjacent if one contains all the other command's textures + QVector<ShaderParameterPack::NamedTexture> texturesA = a->m_parameterPack.textures(); + QVector<ShaderParameterPack::NamedTexture> texturesB = b->m_parameterPack.textures(); + + if (texturesB.size() > texturesA.size()) + qSwap(texturesA, texturesB); + + // textureB.size() is always <= textureA.size() + for (const ShaderParameterPack::NamedTexture &texB : qAsConst(texturesB)) { + if (!texturesA.contains(texB)) + return false; + } + return true; + } +}; + template<typename Predicate> int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands, const int beg, const int end, Predicate pred) @@ -393,6 +414,33 @@ struct SubRangeSorter<QSortPolicy::FrontToBack> } }; +template<> +struct SubRangeSorter<QSortPolicy::Texture> +{ + static void sortSubRange(CommandIt begin, const CommandIt end) + { + std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { + QVector<ShaderParameterPack::NamedTexture> texturesA = a->m_parameterPack.textures(); + QVector<ShaderParameterPack::NamedTexture> texturesB = b->m_parameterPack.textures(); + + const int originalTextureASize = texturesA.size(); + const bool isSuperior = originalTextureASize > texturesB.size(); + + if (texturesB.size() > texturesA.size()) + qSwap(texturesA, texturesB); + + int identicalTextureCount = 0; + + for (const ShaderParameterPack::NamedTexture &texB : qAsConst(texturesB)) { + if (texturesA.contains(texB)) + ++identicalTextureCount; + } + + return identicalTextureCount < originalTextureASize; + }); + } +}; + int findSubRange(const QVector<RenderCommand *> &commands, const int begin, const int end, const QSortPolicy::SortType sortType) @@ -406,6 +454,8 @@ int findSubRange(const QVector<RenderCommand *> &commands, return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange); case QSortPolicy::FrontToBack: return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::FrontToBack>::adjacentSubRange); + case QSortPolicy::Texture: + return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Texture>::adjacentSubRange); default: Q_UNREACHABLE(); return end; @@ -449,6 +499,9 @@ void sortCommandRange(QVector<RenderCommand *> &commands, int begin, const int e case QSortPolicy::FrontToBack: SubRangeSorter<QSortPolicy::FrontToBack>::sortSubRange(commands.begin() + begin, commands.begin() + end); break; + case QSortPolicy::Texture: + SubRangeSorter<QSortPolicy::Texture>::sortSubRange(commands.begin() + begin, commands.begin() + end); + break; default: Q_UNREACHABLE(); } diff --git a/src/render/renderers/opengl/renderer/shaderparameterpack_p.h b/src/render/renderers/opengl/renderer/shaderparameterpack_p.h index fe9ab3995..d1fbe936f 100644 --- a/src/render/renderers/opengl/renderer/shaderparameterpack_p.h +++ b/src/render/renderers/opengl/renderer/shaderparameterpack_p.h @@ -118,6 +118,18 @@ public: int glslNameId; Qt3DCore::QNodeId texId; int uniformArrayIndex; + + bool operator==(const NamedTexture &other) const + { + return glslNameId == other.glslNameId && + texId == other.texId && + uniformArrayIndex == other.uniformArrayIndex; + } + + bool operator!=(const NamedTexture &other) const + { + return !(*this == other); + } }; inline QVector<NamedTexture> textures() const { return m_textures; } |