summaryrefslogtreecommitdiffstats
path: root/tests/auto/render/opengl/renderviews/tst_renderviews.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/render/opengl/renderviews/tst_renderviews.cpp')
-rw-r--r--tests/auto/render/opengl/renderviews/tst_renderviews.cpp556
1 files changed, 556 insertions, 0 deletions
diff --git a/tests/auto/render/opengl/renderviews/tst_renderviews.cpp b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp
new file mode 100644
index 000000000..6d01122d1
--- /dev/null
+++ b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <qbackendnodetester.h>
+#include <private/memorybarrier_p.h>
+#include <testpostmanarbiter.h>
+#include <testrenderer.h>
+#include <private/shader_p.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <renderview_p.h>
+#include <renderviewjobutils_p.h>
+#include <rendercommand_p.h>
+#include <renderer_p.h>
+#include <glresourcemanagers_p.h>
+#include <private/shader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace OpenGL {
+
+namespace {
+
+void compareShaderParameterPacks(const ShaderParameterPack &t1,
+ const ShaderParameterPack &t2)
+{
+ const PackUniformHash hash1 = t1.uniforms();
+ const PackUniformHash hash2 = t2.uniforms();
+
+ QCOMPARE(hash1.keys.size(), hash2.keys.size());
+
+ for (int i = 0, m = hash1.keys.size(); i < m; ++i) {
+ const int key = hash1.keys.at(i);
+ QCOMPARE(hash1.value(key), hash2.value(key));
+ }
+}
+
+} // anonymous
+
+class tst_RenderViews : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void checkRenderViewSizeFitsWithAllocator()
+ {
+ QSKIP("Allocated Disabled");
+ QVERIFY(sizeof(RenderView) <= 192);
+ QVERIFY(sizeof(RenderView::InnerData) <= 192);
+ }
+
+ void checkRenderViewInitialState()
+ {
+ // GIVEN
+ RenderView renderView;
+
+ // THEN
+ QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None);
+ }
+
+ void checkMemoryBarrierInitialization()
+ {
+ // GIVEN
+ RenderView renderView;
+
+ // THEN
+ QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None);
+
+ // WHEN
+ const QMemoryBarrier::Operations barriers(QMemoryBarrier::BufferUpdate|QMemoryBarrier::ShaderImageAccess);
+ renderView.setMemoryBarrier(barriers);
+
+ // THEN
+ QCOMPARE(renderView.memoryBarrier(), barriers);
+ }
+
+ void checkSetRenderViewConfig()
+ {
+ TestRenderer renderer;
+ {
+ // GIVEN
+ const QMemoryBarrier::Operations barriers(QMemoryBarrier::AtomicCounter|QMemoryBarrier::ShaderStorage);
+ Qt3DRender::QMemoryBarrier frontendBarrier;
+ FrameGraphManager frameGraphManager;
+ MemoryBarrier backendBarrier;
+ RenderView renderView;
+ // setRenderViewConfigFromFrameGraphLeafNode assumes node has a manager
+ backendBarrier.setFrameGraphManager(&frameGraphManager);
+ backendBarrier.setRenderer(&renderer);
+
+ // WHEN
+ frontendBarrier.setWaitOperations(barriers);
+ simulateInitializationSync(&frontendBarrier, &backendBarrier);
+
+ // THEN
+ QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None);
+ QCOMPARE(backendBarrier.waitOperations(), barriers);
+
+ // WHEN
+ Qt3DRender::Render::OpenGL::setRenderViewConfigFromFrameGraphLeafNode(&renderView, &backendBarrier);
+
+ // THEN
+ QCOMPARE(backendBarrier.waitOperations(), renderView.memoryBarrier());
+ }
+ // TO DO: Complete tests for other framegraph node types
+ }
+
+ void checkRenderCommandBackToFrontSorting()
+ {
+ // GIVEN
+ Qt3DRender::Render::NodeManagers nodeManagers;
+ Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ RenderView renderView;
+ QVector<RenderCommand> rawCommands;
+ QVector<QSortPolicy::SortType> sortTypes;
+
+ renderer.setNodeManagers(&nodeManagers);
+ renderView.setRenderer(&renderer);
+
+ sortTypes.push_back(QSortPolicy::BackToFront);
+
+ for (int i = 0; i < 200; ++i) {
+ RenderCommand c;
+ c.m_depth = float(i);
+ rawCommands.push_back(c);
+ }
+
+ // WHEN
+ renderView.addSortType(sortTypes);
+ renderView.setCommands(rawCommands);
+ 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);
+
+ // RenderCommands are deleted by RenderView dtor
+ renderer.shutdown();
+ }
+
+ void checkRenderCommandMaterialSorting()
+ {
+ // GIVEN
+ Qt3DRender::Render::NodeManagers nodeManagers;
+ Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ RenderView renderView;
+ QVector<RenderCommand> rawCommands;
+ QVector<QSortPolicy::SortType> sortTypes;
+
+ renderer.setNodeManagers(&nodeManagers);
+ renderView.setRenderer(&renderer);
+
+ sortTypes.push_back(QSortPolicy::Material);
+
+ GLShader *dnas[5] = {
+ reinterpret_cast<GLShader *>(0x250),
+ reinterpret_cast<GLShader *>(0x500),
+ reinterpret_cast<GLShader *>(0x1000),
+ reinterpret_cast<GLShader *>(0x1500),
+ reinterpret_cast<GLShader *>(0x2000)
+ };
+
+ for (int i = 0; i < 20; ++i) {
+ RenderCommand c;
+ c.m_glShader = dnas[i % 5];
+ rawCommands.push_back(c);
+ }
+
+ // WHEN
+ renderView.addSortType(sortTypes);
+ renderView.setCommands(rawCommands);
+ renderView.sort();
+
+ // THEN
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
+ QCOMPARE(rawCommands.size(), sortedCommands.size());
+ GLShader *targetShader;
+
+ for (int j = 0; j < sortedCommands.size(); ++j) {
+
+ if (j % 4 == 0) {
+ targetShader = sortedCommands.at(j).m_glShader;
+ if (j > 0)
+ QVERIFY(targetShader != sortedCommands.at(j - 1).m_glShader);
+ }
+ QCOMPARE(targetShader, sortedCommands.at(j).m_glShader);
+ }
+
+ // RenderCommands are deleted by RenderView dtor
+ renderer.shutdown();
+ }
+
+ void checkRenderViewUniformMinification_data()
+ {
+ QTest::addColumn<QVector<QShaderProgram*>>("shaders");
+ QTest::addColumn<QVector<ShaderParameterPack>>("rawParameters");
+ QTest::addColumn<QVector<ShaderParameterPack>>("expectedMinimizedParameters");
+
+ Qt3DCore::QNodeId fakeTextureNodeId = Qt3DCore::QNodeId::createId();
+
+ ShaderParameterPack pack1;
+ pack1.setUniform(1, UniformValue(883));
+ pack1.setUniform(2, UniformValue(1584.0f));
+ pack1.setTexture(3, 0, fakeTextureNodeId);
+
+ QShaderProgram *shader1 = new QShaderProgram();
+ QShaderProgram *shader2 = new QShaderProgram();
+
+ shader1->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("1"));
+ shader2->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("2"));
+
+ ShaderParameterPack minifiedPack1;
+
+ QTest::newRow("NoMinification")
+ << (QVector<QShaderProgram*>() << shader1 << shader2)
+ << (QVector<ShaderParameterPack>() << pack1 << pack1)
+ << (QVector<ShaderParameterPack>() << pack1 << pack1);
+
+ QTest::newRow("SingleShaderMinified")
+ << (QVector<QShaderProgram*>() << shader1 << shader1 << shader1)
+ << (QVector<ShaderParameterPack>() << pack1 << pack1 << pack1)
+ << (QVector<ShaderParameterPack>() << pack1 << minifiedPack1 << minifiedPack1);
+
+ QTest::newRow("MultipleShadersMinified")
+ << (QVector<QShaderProgram*>() << shader1 << shader1 << shader1 << shader2 << shader2 << shader2)
+ << (QVector<ShaderParameterPack>() << pack1 << pack1 << pack1 << pack1 << pack1 << pack1)
+ << (QVector<ShaderParameterPack>() << pack1 << minifiedPack1 << minifiedPack1 << pack1 << minifiedPack1 << minifiedPack1);
+ }
+
+ void checkRenderViewUniformMinification()
+ {
+ QFETCH(QVector<QShaderProgram*>, shaders);
+ QFETCH(QVector<ShaderParameterPack>, rawParameters);
+ QFETCH(QVector<ShaderParameterPack>, expectedMinimizedParameters);
+
+ Qt3DRender::Render::NodeManagers nodeManagers;
+ Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ renderer.setNodeManagers(&nodeManagers);
+
+ GLShaderManager *shaderManager = renderer.glResourceManagers()->glShaderManager();
+ for (int i = 0, m = shaders.size(); i < m; ++i) {
+ Shader* backend = new Shader();
+ backend->setRenderer(&renderer);
+ simulateInitializationSync(shaders.at(i), backend);
+ shaderManager->createOrAdoptExisting(backend);
+ }
+
+ RenderView renderView;
+ QVector<RenderCommand> rawCommands;
+ renderView.setRenderer(&renderer);
+
+ for (int i = 0, m = shaders.size(); i < m; ++i) {
+ RenderCommand c;
+ c.m_shaderId = shaders.at(i)->id();
+ c.m_glShader = shaderManager->lookupResource(c.m_shaderId);
+ c.m_parameterPack = rawParameters.at(i);
+ rawCommands.push_back(c);
+ }
+
+ // WHEN
+ renderView.setCommands(rawCommands);
+ renderView.addSortType((QVector<QSortPolicy::SortType>() << QSortPolicy::Uniform));
+ 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));
+ }
+
+ renderer.shutdown();
+ }
+
+
+ void checkRenderCommandFrontToBackSorting()
+ {
+ // GIVEN
+ Qt3DRender::Render::NodeManagers nodeManagers;
+ Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ RenderView renderView;
+ QVector<RenderCommand> rawCommands;
+ QVector<QSortPolicy::SortType> sortTypes;
+
+ renderer.setNodeManagers(&nodeManagers);
+ renderView.setRenderer(&renderer);
+
+ sortTypes.push_back(QSortPolicy::FrontToBack);
+
+ for (int i = 0; i < 200; ++i) {
+ RenderCommand c;
+ c.m_depth = float(i);
+ rawCommands.push_back(c);
+ }
+
+ // WHEN
+ renderView.addSortType(sortTypes);
+ renderView.setCommands(rawCommands);
+ 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);
+
+ // RenderCommands are deleted by RenderView dtor
+ renderer.shutdown();
+ }
+
+ void checkRenderCommandStateCostSorting()
+ {
+ // GIVEN
+ Qt3DRender::Render::NodeManagers nodeManagers;
+ Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ RenderView renderView;
+ QVector<RenderCommand> rawCommands;
+ QVector<QSortPolicy::SortType> sortTypes;
+
+ renderer.setNodeManagers(&nodeManagers);
+ renderView.setRenderer(&renderer);
+
+ sortTypes.push_back(QSortPolicy::StateChangeCost);
+
+ for (int i = 0; i < 200; ++i) {
+ RenderCommand c;
+ c.m_changeCost = i;
+ rawCommands.push_back(c);
+ }
+
+ // WHEN
+ renderView.addSortType(sortTypes);
+ renderView.setCommands(rawCommands);
+ 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);
+
+ // RenderCommands are deleted by RenderView dtor
+ renderer.shutdown();
+ }
+
+ void checkRenderCommandCombinedStateMaterialDepthSorting()
+ {
+ // GIVEN
+ Qt3DRender::Render::NodeManagers nodeManagers;
+ Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ RenderView renderView;
+ QVector<RenderCommand> rawCommands;
+ QVector<QSortPolicy::SortType> sortTypes;
+
+ renderer.setNodeManagers(&nodeManagers);
+ renderView.setRenderer(&renderer);
+
+ sortTypes.push_back(QSortPolicy::StateChangeCost);
+ sortTypes.push_back(QSortPolicy::Material);
+ sortTypes.push_back(QSortPolicy::BackToFront);
+
+ GLShader *dna[5] = {
+ reinterpret_cast<GLShader *>(0x250),
+ reinterpret_cast<GLShader *>(0x500),
+ reinterpret_cast<GLShader *>(0x1000),
+ reinterpret_cast<GLShader *>(0x1500),
+ reinterpret_cast<GLShader *>(0x2000)
+ };
+
+ float depth[3] = {
+ 10.0f,
+ 25.0f,
+ 30.0f
+ };
+
+ int stateChangeCost[2] = {
+ 100,
+ 200
+ };
+
+ auto buildRC = [] (GLShader *dna, float depth, int changeCost) {
+ RenderCommand c;
+ c.m_glShader = dna;
+ c.m_depth = depth;
+ c.m_changeCost = changeCost;
+ return c;
+ };
+
+ RenderCommand c5 = buildRC(dna[3], depth[1], stateChangeCost[1]);
+ RenderCommand c3 = buildRC(dna[3], depth[0], stateChangeCost[1]);
+ RenderCommand c4 = buildRC(dna[2], depth[1], stateChangeCost[1]);
+ RenderCommand c8 = buildRC(dna[1], depth[1], stateChangeCost[1]);
+ RenderCommand c0 = buildRC(dna[0], depth[2], stateChangeCost[1]);
+
+ RenderCommand c2 = buildRC(dna[2], depth[2], stateChangeCost[0]);
+ RenderCommand c9 = buildRC(dna[2], depth[0], stateChangeCost[0]);
+ RenderCommand c1 = buildRC(dna[1], depth[0], stateChangeCost[0]);
+ 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;
+
+ // WHEN
+ renderView.addSortType(sortTypes);
+ renderView.setCommands(rawCommands);
+ renderView.sort();
+
+ // THEN
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
+ 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));
+
+ // RenderCommands are deleted by RenderView dtor
+ renderer.shutdown();
+ }
+
+ void checkRenderCommandTextureSorting()
+ {
+ // GIVEN
+ RenderView renderView;
+ QVector<QSortPolicy::SortType> sortTypes;
+
+ sortTypes.push_back(QSortPolicy::Texture);
+
+
+ Qt3DCore::QNodeId tex1 = Qt3DCore::QNodeId::createId();
+ Qt3DCore::QNodeId tex2 = Qt3DCore::QNodeId::createId();
+ Qt3DCore::QNodeId tex3 = Qt3DCore::QNodeId::createId();
+ Qt3DCore::QNodeId tex4 = Qt3DCore::QNodeId::createId();
+
+ RenderCommand a;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(0, 0, tex1);
+ pack.setTexture(1, 0, tex3);
+ pack.setTexture(2, 0, tex4);
+ pack.setTexture(3, 0, tex2);
+ a.m_parameterPack = pack;
+ }
+ RenderCommand b;
+ RenderCommand c;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(0, 0, tex1);
+ pack.setTexture(3, 0, tex2);
+ c.m_parameterPack = pack;
+ }
+ RenderCommand d;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(1, 0, tex3);
+ pack.setTexture(2, 0, tex4);
+ d.m_parameterPack = pack;
+ }
+ RenderCommand e;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(3, 0, tex2);
+ e.m_parameterPack = pack;
+ }
+ RenderCommand f;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(3, 0, tex2);
+ f.m_parameterPack = pack;
+ }
+ RenderCommand g;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(0, 0, tex1);
+ pack.setTexture(1, 0, tex3);
+ pack.setTexture(2, 0, tex4);
+ pack.setTexture(3, 0, tex2);
+ g.m_parameterPack = pack;
+ }
+
+ // WHEN
+ QVector<RenderCommand> rawCommands = {a, b, c, d, e, f, g};
+ renderView.addSortType(sortTypes);
+ renderView.setCommands(rawCommands);
+ renderView.sort();
+
+ // THEN
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
+ 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);
+ // RenderCommands are deleted by RenderView dtor
+ }
+private:
+};
+
+} // OpenGL
+
+} // Render
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+//APPLESS_
+QTEST_MAIN(Qt3DRender::Render::OpenGL::tst_RenderViews)
+
+#include "tst_renderviews.moc"