From fee0f43522483415b4af1475caaca21658f3e24a Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 17 Oct 2019 10:03:01 +0200 Subject: Convert EntityRenderCommandData to struct of vectors Change-Id: Ib290491476b083e6aa4cff5c112a802c4e198987 Reviewed-by: Sean Harmer --- .../opengl/jobs/renderviewcommandbuilderjob_p.h | 4 +- .../opengl/jobs/renderviewcommandupdaterjob.cpp | 6 +-- .../opengl/jobs/renderviewcommandupdaterjob_p.h | 4 +- .../renderers/opengl/renderer/rendercommand_p.h | 53 ++++++++++++++++++++-- .../renderers/opengl/renderer/renderercache_p.h | 2 +- .../renderers/opengl/renderer/renderview.cpp | 32 +++++++------ .../renderers/opengl/renderer/renderview_p.h | 6 +-- .../opengl/renderer/renderviewbuilder.cpp | 26 +++++------ 8 files changed, 90 insertions(+), 43 deletions(-) diff --git a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h index 725f83b62..9f45a8005 100644 --- a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h +++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h @@ -68,14 +68,14 @@ public: inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; } inline void setEntities(const QVector &entities) { m_entities = entities; } - inline QVector &commandData() { return m_commandData; } + inline EntityRenderCommandData &commandData() { return m_commandData; } void run() final; private: RenderView *m_renderView; QVector m_entities; - QVector m_commandData; + EntityRenderCommandData m_commandData; }; typedef QSharedPointer RenderViewCommandBuilderJobPtr; diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp index d58b288e6..af1d545ed 100644 --- a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp +++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp @@ -70,11 +70,7 @@ void RenderViewCommandUpdaterJob::run() // Copy commands out of cached -> ensures we can submit them for rendering // while cache is rebuilt or modified for next frame - QVector commands; - commands.reserve(m_renderables.size()); - for (const EntityRenderCommandData *data : m_renderables) - commands.push_back(data->command); - m_commands = commands; + m_commands = m_renderables.commands; } } diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h index 3fff5f1a0..72caef6cf 100644 --- a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h +++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h @@ -71,7 +71,7 @@ public: inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; } inline void setRenderer(Renderer *renderer) Q_DECL_NOTHROW { m_renderer = renderer; } - inline void setRenderables(const QVector &renderables) Q_DECL_NOTHROW { m_renderables = renderables; } + inline void setRenderables(const EntityRenderCommandData &renderables) Q_DECL_NOTHROW { m_renderables = renderables; } QVector &commands() Q_DECL_NOTHROW { return m_commands; } @@ -80,7 +80,7 @@ public: private: RenderView *m_renderView; Renderer *m_renderer; - QVector m_renderables; + EntityRenderCommandData m_renderables; QVector m_commands; }; diff --git a/src/render/renderers/opengl/renderer/rendercommand_p.h b/src/render/renderers/opengl/renderer/rendercommand_p.h index 58ab0cadd..0180d6996 100644 --- a/src/render/renderers/opengl/renderer/rendercommand_p.h +++ b/src/render/renderers/opengl/renderer/rendercommand_p.h @@ -131,11 +131,58 @@ inline bool operator!=(const RenderCommand &lhs, const RenderCommand &rhs) noexc struct EntityRenderCommandData { - Entity *entity; - RenderCommand command; - RenderPassParameterData passData; + QVector entities; + QVector commands; + QVector passesData; + + void reserve(int size) + { + entities.reserve(size); + commands.reserve(size); + passesData.reserve(size); + } + + inline int size() const { return entities.size(); } + + inline void push_back(Entity *e, const RenderCommand &c, const RenderPassParameterData &p) + { + entities.push_back(e); + commands.push_back(c); + passesData.push_back(p); + } + + inline void push_back(Entity *e, RenderCommand &&c, RenderPassParameterData &&p) + { + entities.push_back(e); + commands.push_back(std::move(c)); + passesData.push_back(std::move(p)); + } + + EntityRenderCommandData &operator+=(const EntityRenderCommandData &t) + { + entities += t.entities; + commands += t.commands; + passesData += t.passesData; + return *this; + } + + EntityRenderCommandData &operator+=(EntityRenderCommandData &&t) + { + entities += std::move(t.entities); + commands += std::move(t.commands); + passesData += std::move(t.passesData); + return *this; + } + + EntityRenderCommandData mid(int idx, int len) const + { + return { entities.mid(idx, len), commands.mid(idx, len), passesData.mid(idx, len) }; + } + + }; + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/renderers/opengl/renderer/renderercache_p.h b/src/render/renderers/opengl/renderer/renderercache_p.h index 984004993..02fe4ff41 100644 --- a/src/render/renderers/opengl/renderer/renderercache_p.h +++ b/src/render/renderers/opengl/renderer/renderercache_p.h @@ -70,7 +70,7 @@ struct RendererCache { QVector filterEntitiesByLayer; MaterialParameterGathererData materialParameterGatherer; - QVector renderCommandData; + EntityRenderCommandData renderCommandData; }; // Shared amongst all RV cache diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp index b102de9de..97d494370 100644 --- a/src/render/renderers/opengl/renderer/renderview.cpp +++ b/src/render/renderers/opengl/renderer/renderview.cpp @@ -621,11 +621,11 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) { } // If we are there, we know that entity had a GeometryRenderer + Material -QVector RenderView::buildDrawRenderCommands(const QVector &entities) const +EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector &entities) const { - QVector commands; - commands.reserve(entities.size()); + EntityRenderCommandData commands; + commands.reserve(entities.size()); for (Entity *entity : entities) { GeometryRenderer *geometryRenderer = nullptr; @@ -662,8 +662,9 @@ QVector RenderView::buildDrawRenderCommands(const QVect } command.m_shader = m_manager->lookupHandle(pass->shaderProgram()); - const EntityRenderCommandData commandData = { entity, command, passData }; - commands.append(commandData); + commands.push_back(entity, + std::move(command), + std::move(passData)); } } } @@ -671,15 +672,17 @@ QVector RenderView::buildDrawRenderCommands(const QVect return commands; } -QVector RenderView::buildComputeRenderCommands(const QVector &entities) const +EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector &entities) const { // If the RenderView contains only a ComputeDispatch then it cares about // A ComputeDispatch is also implicitely a NoDraw operation // enabled flag // layer component // material/effect/technique/parameters/filters/ - QVector commands; + EntityRenderCommandData commands; + commands.reserve(entities.size()); + for (Entity *entity : entities) { ComputeCommand *computeJob = nullptr; HComputeCommand computeCommandHandle = entity->componentHandle(); @@ -712,8 +715,9 @@ QVector RenderView::buildComputeRenderCommands(const QV command.m_workGroups[1] = std::max(m_workGroups[1], computeJob->y()); command.m_workGroups[2] = std::max(m_workGroups[2], computeJob->z()); - const EntityRenderCommandData commandData = { entity, command, passData }; - commands.append(commandData); + commands.push_back(entity, + std::move(command), + std::move(passData)); } } } @@ -721,7 +725,7 @@ QVector RenderView::buildComputeRenderCommands(const QV return commands; } -void RenderView::updateRenderCommand(QVector &renderCommandData) +void RenderView::updateRenderCommand(EntityRenderCommandData &renderCommandData) { // Note: since many threads can be building render commands // we need to ensure that the UniformBlockValueBuilder they are using @@ -731,10 +735,10 @@ void RenderView::updateRenderCommand(QVector &renderC builder->textureManager = m_manager->textureManager(); m_localData.setLocalData(builder); - for (EntityRenderCommandData *commandData : renderCommandData) { - Entity *entity = commandData->entity; - RenderPassParameterData passData = commandData->passData; - RenderCommand &command = commandData->command; + for (int i = 0, m = renderCommandData.size(); i < m; ++i) { + Entity *entity = renderCommandData.entities.at(i); + const RenderPassParameterData passData = renderCommandData.passesData.at(i); + RenderCommand &command = renderCommandData.commands[i]; // Pick which lights to take in to account. // For now decide based on the distance by taking the MAX_LIGHTS closest lights. diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h index 7d148118d..1221e7a59 100644 --- a/src/render/renderers/opengl/renderer/renderview_p.h +++ b/src/render/renderers/opengl/renderer/renderview_p.h @@ -227,11 +227,11 @@ public: RenderPassList passesAndParameters(ParameterInfoList *parameter, Entity *node, bool useDefaultMaterials = true); - QVector buildDrawRenderCommands(const QVector &entities) const; - QVector buildComputeRenderCommands(const QVector &entities) const; + EntityRenderCommandData buildDrawRenderCommands(const QVector &entities) const; + EntityRenderCommandData buildComputeRenderCommands(const QVector &entities) const; - void updateRenderCommand(QVector &renderCommandData); + void updateRenderCommand(EntityRenderCommandData &renderCommandData); void setCommands(const QVector &commands) Q_DECL_NOTHROW { m_commands = commands; } diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp index ead29ec03..40179fbd6 100644 --- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp +++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp @@ -268,11 +268,7 @@ public: // This should happen fairly infrequently (FrameGraph Change, Geometry/Material change) // and allow to skip that step most of the time if (m_fullRebuild) { - // Clear previous cache - RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode]; - writableCacheForLeaf.renderCommandData.clear(); - - QVector commandData; + EntityRenderCommandData commandData; // Reduction { int totalCommandCount = 0; @@ -282,10 +278,12 @@ public: for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs)) commandData += std::move(renderViewCommandBuilder->commandData()); } - // Store in cache + + // Store new cache + RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode]; writableCacheForLeaf.renderCommandData = std::move(commandData); } - const QVector commandData = dataCacheForLeaf.renderCommandData; + const EntityRenderCommandData commandData = dataCacheForLeaf.renderCommandData; const QVector filteredEntities = dataCacheForLeaf.filterEntitiesByLayer; QVector renderableEntities = isDraw ? cache->renderableEntities : cache->computeEntities; @@ -317,26 +315,28 @@ public: // Filter out Render commands for which the Entity wasn't selected because // of frustum, proximity or layer filtering - QVector filteredCommandData; + EntityRenderCommandData filteredCommandData; filteredCommandData.reserve(renderableEntities.size()); // Because dataCacheForLeaf.renderableEntities or computeEntities are sorted // What we get out of EntityRenderCommandData is also sorted by Entity auto eIt = std::cbegin(renderableEntities); - auto cIt = std::cbegin(commandData); const auto eEnd = std::cend(renderableEntities); - const auto cEnd = std::cend(commandData); + int cIt = 0; + const int cEnd = commandData.size(); while (eIt != eEnd) { const Entity *targetEntity = *eIt; // Advance until we have commands whose Entity has a lower address // than the selected filtered entity - while (cIt->entity < targetEntity && cIt != cEnd) + while (cIt != cEnd && commandData.entities.at(cIt) < targetEntity) ++cIt; // Push pointers to command data for all commands that match the // entity - while (cIt->entity == targetEntity && cIt != cEnd) { - filteredCommandData.push_back(const_cast(&(*cIt))); + while (cIt != cEnd && commandData.entities.at(cIt) == targetEntity) { + filteredCommandData.push_back(commandData.entities.at(cIt), + commandData.commands.at(cIt), + commandData.passesData.at(cIt)); ++cIt; } ++eIt; -- cgit v1.2.3