diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2020-04-30 16:09:46 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2020-06-04 14:02:33 +0200 |
commit | 80e73b0a8537c794be187e8847f84d376c30bd66 (patch) | |
tree | a28c70f7985678880f16982a7da1260beebc0c06 /tests/auto | |
parent | 0c9c4e163458f99ac350aef4979754cbe147dac3 (diff) |
Leverage RV cache to reuse render commands when possible
- Only perform render command filtering when needed (when camera has moved usually)
- Keep RenderCommand around so that we only update them if needed:
-> We keep a double set of commands we per RV and switch in between every frame
- Introduce EntityRenderCommandDataView as a wrapper around RenderCommands
-> Use std::vector for RenderCommand storage (avoids hidden detachments)
-> Filter and sort indices into the RenderCommand vector rather than the commands
directly
- Cleanup RenderView
-> Remove InnerData field
-> Hide direct RenderCommand access
- Next steps
-> Only update uniforms that need to be updated
-> Most likely lights/standard uniforms won't all change every frame
-> Only update light sources for entity when needed
Change-Id: I153822a16c0989a8ac5b83d756385056c96572aa
Reviewed-by: Mike Krus <mike.krus@kdab.com>
(cherry picked from commit 59345bc1a733ee035b342feecadc923e062a850c)
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/render/opengl/renderviews/tst_renderviews.cpp | 223 |
1 files changed, 159 insertions, 64 deletions
diff --git a/tests/auto/render/opengl/renderviews/tst_renderviews.cpp b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp index 0b1e22909..aec13071a 100644 --- a/tests/auto/render/opengl/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp @@ -78,7 +78,6 @@ private Q_SLOTS: { QSKIP("Allocated Disabled"); QVERIFY(sizeof(RenderView) <= 192); - QVERIFY(sizeof(RenderView::InnerData) <= 192); } void checkRenderViewInitialState() @@ -137,13 +136,40 @@ private Q_SLOTS: // TO DO: Complete tests for other framegraph node types } + void checkDoesntCrashWhenNoCommandsToSort() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + RenderView renderView; + + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + + QVector<QSortPolicy::SortType> sortTypes; + sortTypes.push_back(QSortPolicy::BackToFront); + + // WHEN + renderView.addSortType(sortTypes); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + renderView.setRenderCommandDataView(view); + + // THEN -> shouldn't crash + renderView.sort(); + + // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); + } + void checkRenderCommandBackToFrontSorting() { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; - QVector<RenderCommand> rawCommands; + std::vector<RenderCommand> rawCommands; + QVector<QSortPolicy::SortType> sortTypes; renderer.setNodeManagers(&nodeManagers); @@ -159,14 +185,25 @@ private Q_SLOTS: // WHEN renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + view->data.commands = rawCommands; + view->indices.resize(rawCommands.size()); + std::iota(view->indices.begin(), view->indices.end(), 0); + + renderView.setRenderCommandDataView(view); + renderView.sort(); // THEN - const QVector<RenderCommand> sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1).m_depth > sortedCommands.at(j).m_depth); + int j = 0; + RenderCommand previousRC; + renderView.forEachCommand([&] (const RenderCommand &command) { + if (j > 0) + QVERIFY(previousRC.m_depth > command.m_depth); + previousRC = command; + ++j; + }); // RenderCommands are deleted by RenderView dtor renderer.shutdown(); @@ -178,7 +215,8 @@ private Q_SLOTS: Qt3DRender::Render::NodeManagers nodeManagers; Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; - QVector<RenderCommand> rawCommands; + std::vector<RenderCommand> rawCommands; + QVector<QSortPolicy::SortType> sortTypes; renderer.setNodeManagers(&nodeManagers); @@ -202,23 +240,31 @@ private Q_SLOTS: // WHEN renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + view->data.commands = rawCommands; + view->indices.resize(rawCommands.size()); + std::iota(view->indices.begin(), view->indices.end(), 0); + + renderView.setRenderCommandDataView(view); + renderView.sort(); // THEN - const QVector<RenderCommand> sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); + int j = 0; GLShader *targetShader; + RenderCommand previousRC; - for (int j = 0; j < sortedCommands.size(); ++j) { - + renderView.forEachCommand([&] (const RenderCommand &command) { if (j % 4 == 0) { - targetShader = sortedCommands.at(j).m_glShader; + targetShader = command.m_glShader; if (j > 0) - QVERIFY(targetShader != sortedCommands.at(j - 1).m_glShader); + QVERIFY(targetShader != previousRC.m_glShader); } - QCOMPARE(targetShader, sortedCommands.at(j).m_glShader); - } + QCOMPARE(targetShader, command.m_glShader); + previousRC = command; + ++j; + }); // RenderCommands are deleted by RenderView dtor renderer.shutdown(); @@ -280,7 +326,8 @@ private Q_SLOTS: } RenderView renderView; - QVector<RenderCommand> rawCommands; + std::vector<RenderCommand> rawCommands; + renderView.setRenderer(&renderer); for (int i = 0, m = shaders.size(); i < m; ++i) { @@ -292,19 +339,24 @@ private Q_SLOTS: } // WHEN - renderView.setCommands(rawCommands); renderView.addSortType((QVector<QSortPolicy::SortType>() << QSortPolicy::Uniform)); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + view->data.commands = rawCommands; + view->indices.resize(rawCommands.size()); + std::iota(view->indices.begin(), view->indices.end(), 0); + + renderView.setRenderCommandDataView(view); + renderView.sort(); // THEN - const QVector<RenderCommand> sortedCommands = renderView.commands(); - QCOMPARE(rawCommands, sortedCommands); - - for (int i = 0, m = shaders.size(); i < m; ++i) { - const RenderCommand c = sortedCommands.at(i); - QCOMPARE(c.m_shaderId, shaders.at(i)->id()); - compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i)); - } + int j = 0; + renderView.forEachCommand([&] (const RenderCommand &command) { + QCOMPARE(command.m_shaderId, shaders.at(j)->id()); + compareShaderParameterPacks(command.m_parameterPack, expectedMinimizedParameters.at(j)); + ++j; + }); renderer.shutdown(); } @@ -316,7 +368,8 @@ private Q_SLOTS: Qt3DRender::Render::NodeManagers nodeManagers; Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; - QVector<RenderCommand> rawCommands; + std::vector<RenderCommand> rawCommands; + QVector<QSortPolicy::SortType> sortTypes; renderer.setNodeManagers(&nodeManagers); @@ -332,14 +385,25 @@ private Q_SLOTS: // WHEN renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + view->data.commands = rawCommands; + view->indices.resize(rawCommands.size()); + std::iota(view->indices.begin(), view->indices.end(), 0); + + renderView.setRenderCommandDataView(view); + renderView.sort(); // THEN - const QVector<RenderCommand> sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1).m_depth < sortedCommands.at(j).m_depth); + int j = 0; + RenderCommand previousRC; + renderView.forEachCommand([&] (const RenderCommand &command) { + if (j > 0) + QVERIFY(previousRC.m_depth < command.m_depth); + previousRC = command; + ++j; + }); // RenderCommands are deleted by RenderView dtor renderer.shutdown(); @@ -351,7 +415,8 @@ private Q_SLOTS: Qt3DRender::Render::NodeManagers nodeManagers; Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; - QVector<RenderCommand> rawCommands; + std::vector<RenderCommand> rawCommands; + QVector<QSortPolicy::SortType> sortTypes; renderer.setNodeManagers(&nodeManagers); @@ -367,14 +432,26 @@ private Q_SLOTS: // WHEN renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + view->data.commands = rawCommands; + view->indices.resize(rawCommands.size()); + std::iota(view->indices.begin(), view->indices.end(), 0); + + renderView.setRenderCommandDataView(view); + renderView.sort(); // THEN - const QVector<RenderCommand> sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1).m_changeCost > sortedCommands.at(j).m_changeCost); + int j = 0; + RenderCommand previousRC; + renderView.forEachCommand([&] (const RenderCommand &command) { + if (j > 0) + QVERIFY(previousRC.m_changeCost > command.m_changeCost); + previousRC = command; + ++j; + }); + // RenderCommands are deleted by RenderView dtor renderer.shutdown(); @@ -386,7 +463,8 @@ private Q_SLOTS: Qt3DRender::Render::NodeManagers nodeManagers; Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; - QVector<RenderCommand> rawCommands; + std::vector<RenderCommand> rawCommands; + QVector<QSortPolicy::SortType> sortTypes; renderer.setNodeManagers(&nodeManagers); @@ -435,29 +513,38 @@ private Q_SLOTS: RenderCommand c7 = buildRC(dna[0], depth[2], stateChangeCost[0]); RenderCommand c6 = buildRC(dna[0], depth[1], stateChangeCost[0]); - rawCommands << c0 << c1 << c2 << c3 << c4 << c5 << c6 << c7 << c8 << c9; + rawCommands = { c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 }; // WHEN renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + view->data.commands = rawCommands; + view->indices.resize(rawCommands.size()); + std::iota(view->indices.begin(), view->indices.end(), 0); + + renderView.setRenderCommandDataView(view); + + renderView.sort(); // THEN - const QVector<RenderCommand> sortedCommands = renderView.commands(); + const std::vector<RenderCommand> &sortedCommands = view->data.commands; + const std::vector<size_t> &sortedCommandIndices = view->indices; QCOMPARE(rawCommands.size(), sortedCommands.size()); // Ordered by higher state, higher shaderDNA and higher depth - QCOMPARE(c0, sortedCommands.at(4)); - QCOMPARE(c3, sortedCommands.at(1)); - QCOMPARE(c4, sortedCommands.at(2)); - QCOMPARE(c5, sortedCommands.at(0)); - QCOMPARE(c8, sortedCommands.at(3)); - - QCOMPARE(c1, sortedCommands.at(7)); - QCOMPARE(c2, sortedCommands.at(5)); - QCOMPARE(c6, sortedCommands.at(9)); - QCOMPARE(c7, sortedCommands.at(8)); - QCOMPARE(c9, sortedCommands.at(6)); + QCOMPARE(c0, sortedCommands.at(sortedCommandIndices[4])); + QCOMPARE(c3, sortedCommands.at(sortedCommandIndices[1])); + QCOMPARE(c4, sortedCommands.at(sortedCommandIndices[2])); + QCOMPARE(c5, sortedCommands.at(sortedCommandIndices[0])); + QCOMPARE(c8, sortedCommands.at(sortedCommandIndices[3])); + + QCOMPARE(c1, sortedCommands.at(sortedCommandIndices[7])); + QCOMPARE(c2, sortedCommands.at(sortedCommandIndices[5])); + QCOMPARE(c6, sortedCommands.at(sortedCommandIndices[9])); + QCOMPARE(c7, sortedCommands.at(sortedCommandIndices[8])); + QCOMPARE(c9, sortedCommands.at(sortedCommandIndices[6])); // RenderCommands are deleted by RenderView dtor renderer.shutdown(); @@ -524,21 +611,29 @@ private Q_SLOTS: } // WHEN - QVector<RenderCommand> rawCommands = {a, b, c, d, e, f, g}; + std::vector<RenderCommand> rawCommands = {a, b, c, d, e, f, g}; renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); + + EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); + view->data.commands = rawCommands; + view->indices.resize(rawCommands.size()); + std::iota(view->indices.begin(), view->indices.end(), 0); + + renderView.setRenderCommandDataView(view); + renderView.sort(); // THEN - const QVector<RenderCommand> sortedCommands = renderView.commands(); + const std::vector<RenderCommand> &sortedCommands = view->data.commands; + const std::vector<size_t> &sortedCommandIndices = view->indices; QCOMPARE(rawCommands.size(), sortedCommands.size()); - QCOMPARE(sortedCommands.at(0), a); - QCOMPARE(sortedCommands.at(1), g); - QCOMPARE(sortedCommands.at(2), d); - QCOMPARE(sortedCommands.at(3), c); - QCOMPARE(sortedCommands.at(4), e); - QCOMPARE(sortedCommands.at(5), f); - QCOMPARE(sortedCommands.at(6), b); + QCOMPARE(sortedCommands.at(sortedCommandIndices[0]), a); + QCOMPARE(sortedCommands.at(sortedCommandIndices[1]), g); + QCOMPARE(sortedCommands.at(sortedCommandIndices[2]), d); + QCOMPARE(sortedCommands.at(sortedCommandIndices[3]), c); + QCOMPARE(sortedCommands.at(sortedCommandIndices[4]), e); + QCOMPARE(sortedCommands.at(sortedCommandIndices[5]), f); + QCOMPARE(sortedCommands.at(sortedCommandIndices[6]), b); // RenderCommands are deleted by RenderView dtor } private: |