/**************************************************************************** ** ** 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 #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { 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::setRenderViewConfigFromFrameGraphLeafNode(&renderView, &backendBarrier); // THEN QCOMPARE(backendBarrier.waitOperations(), renderView.memoryBarrier()); } // TO DO: Complete tests for other framegraph node types } void checkRenderCommandBackToFrontSorting() { // GIVEN RenderView renderView; QVector rawCommands; QVector sortTypes; 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 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 } void checkRenderCommandMaterialSorting() { // GIVEN RenderView renderView; QVector rawCommands; QVector sortTypes; sortTypes.push_back(QSortPolicy::Material); ProgramDNA dnas[5] = { ProgramDNA(250), ProgramDNA(500), ProgramDNA(1000), ProgramDNA(1500), ProgramDNA(2000), }; for (int i = 0; i < 20; ++i) { RenderCommand c; c.m_shaderDna = dnas[i % 5]; rawCommands.push_back(c); } // WHEN renderView.addSortType(sortTypes); renderView.setCommands(rawCommands); renderView.sort(); // THEN const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); ProgramDNA targetDNA; for (int j = 0; j < sortedCommands.size(); ++j) { if (j % 4 == 0) { targetDNA = sortedCommands.at(j).m_shaderDna; if (j > 0) QVERIFY(targetDNA != sortedCommands.at(j - 1).m_shaderDna); } QCOMPARE(targetDNA, sortedCommands.at(j).m_shaderDna); } // RenderCommands are deleted by RenderView dtor } void checkRenderViewUniformMinification_data() { QTest::addColumn>("programDNAs"); QTest::addColumn>("rawParameters"); QTest::addColumn>("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); ShaderParameterPack minifiedPack1; QTest::newRow("NoMinification") << (QVector() << ProgramDNA(883) << ProgramDNA(1584)) << (QVector() << pack1 << pack1) << (QVector() << pack1 << pack1); QTest::newRow("SingleShaderMinified") << (QVector() << ProgramDNA(883) << ProgramDNA(883) << ProgramDNA(883)) << (QVector() << pack1 << pack1 << pack1) << (QVector() << pack1 << minifiedPack1 << minifiedPack1); QTest::newRow("MultipleShadersMinified") << (QVector() << ProgramDNA(883) << ProgramDNA(883) << ProgramDNA(883) << ProgramDNA(1584) << ProgramDNA(1584) << ProgramDNA(1584)) << (QVector() << pack1 << pack1 << pack1 << pack1 << pack1 << pack1) << (QVector() << pack1 << minifiedPack1 << minifiedPack1 << pack1 << minifiedPack1 << minifiedPack1); } void checkRenderViewUniformMinification() { QFETCH(QVector, programDNAs); QFETCH(QVector, rawParameters); QFETCH(QVector, expectedMinimizedParameters); RenderView renderView; QVector rawCommands; for (int i = 0, m = programDNAs.size(); i < m; ++i) { RenderCommand c; c.m_shaderDna = programDNAs.at(i); c.m_parameterPack = rawParameters.at(i); rawCommands.push_back(c); } // WHEN renderView.setCommands(rawCommands); renderView.addSortType((QVector() << QSortPolicy::Uniform)); renderView.sort(); // THEN const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands, sortedCommands); for (int i = 0, m = programDNAs.size(); i < m; ++i) { const RenderCommand c = sortedCommands.at(i); QCOMPARE(c.m_shaderDna, programDNAs.at(i)); compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i)); } } void checkRenderCommandFrontToBackSorting() { // GIVEN RenderView renderView; QVector rawCommands; QVector sortTypes; 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 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 } void checkRenderCommandStateCostSorting() { // GIVEN RenderView renderView; QVector rawCommands; QVector sortTypes; 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 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 } void checkRenderCommandCombinedStateMaterialDepthSorting() { // GIVEN RenderView renderView; QVector rawCommands; QVector sortTypes; sortTypes.push_back(QSortPolicy::StateChangeCost); sortTypes.push_back(QSortPolicy::Material); sortTypes.push_back(QSortPolicy::BackToFront); ProgramDNA dna[4] = { ProgramDNA(250), ProgramDNA(500), ProgramDNA(1000), ProgramDNA(1500) }; float depth[3] = { 10.0f, 25.0f, 30.0f }; int stateChangeCost[2] = { 100, 200 }; auto buildRC = [] (ProgramDNA dna, float depth, int changeCost) { RenderCommand c; c.m_shaderDna = 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 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 } void checkRenderCommandTextureSorting() { // GIVEN RenderView renderView; QVector 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 rawCommands = {a, b, c, d, e, f, g}; renderView.addSortType(sortTypes); renderView.setCommands(rawCommands); renderView.sort(); // THEN const QVector 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: }; } // Render } // Qt3DRender QT_END_NAMESPACE //APPLESS_ QTEST_MAIN(Qt3DRender::Render::tst_RenderViews) #include "tst_renderviews.moc"