/**************************************************************************** ** ** Copyright (C) 2017 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 class tst_Renderer : public QObject { Q_OBJECT public : tst_Renderer() {} ~tst_Renderer() {} private Q_SLOTS: void checkPreRenderBinJobs() { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); Qt3DRender::Render::RenderSettings settings; // owned by FG manager Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); settings.setActiveFrameGraphId(fgRootId); renderer.setNodeManagers(&nodeManagers); renderer.setSettings(&settings); renderer.setOffscreenSurfaceHelper(&offscreenHelper); renderer.initialize(); // Ensure invoke calls are performed QCoreApplication::processEvents(); // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) QVector jobs = renderer.preRenderingJobs(); // THEN QCOMPARE(jobs.size(), 1 + // PickBoundingVolumeJob 1); // RayCastingJob // WHEN renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}}); jobs = renderer.preRenderingJobs(); // THEN QCOMPARE(jobs.size(), 1 + // PickBoundingVolumeJob 1 + // RayCastingJob 1); // SendBufferCaptureJob // Note: pending render buffer captures are only cleared when the job is run // WHEN renderer.m_updatedSetFences.push_back({Qt3DCore::QNodeId(), nullptr}); jobs = renderer.preRenderingJobs(); // THEN QCOMPARE(jobs.size(), 1 + // PickBoundingVolumeJob 1 + // RayCastingJob 1 + // SendBufferCaptureJob 1); // SendSetFenceHandlesJob // Note: pending set fence handles are only cleared when the job is run // Properly shutdown command thread renderer.shutdown(); } void checkRenderBinJobs() { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); Qt3DRender::Render::RenderQueue *renderQueue = renderer.renderQueue(); Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); Qt3DRender::Render::RenderSettings settings; // owned by FG manager Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); settings.setActiveFrameGraphId(fgRootId); renderer.setNodeManagers(&nodeManagers); renderer.setSettings(&settings); renderer.setOffscreenSurfaceHelper(&offscreenHelper); renderer.initialize(); // Ensure invoke calls are performed QCoreApplication::processEvents(); // NOTE: FilterCompatibleTechniqueJob and ShaderGathererJob cannot run because the context // is not initialized in this test const int renderViewBuilderMaterialCacheJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); // syncMaterialGathererJob // n * materialGathererJob const int layerCacheJobCount = 2; // filterEntityByLayerJob, // syncFilterEntityByLayerJob const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); // RenderViewBuilder renderViewJob, // syncRenderViewInitializationJob, // syncFrustumCullingJob, // filterProximityJob, // setClearDrawBufferIndexJob, // frustumCullingJob, // syncRenderCommandUpdateJob, // syncRenderViewCommandPostUpdateJob // n * (RenderViewCommandBuildJobs) // WHEN QVector jobs = renderer.renderBinJobs(); // THEN -> AllDirty // (Renderer is not initialized so FilterCompatibleTechniqueJob // and ShaderGathererJob are not added here) QCOMPARE(jobs.size(), 1 + // EntityEnabledDirty 1 + // WorldTransformJob 1 + // UpdateWorldBoundingVolume 1 + // UpdateShaderDataTransform 1 + // ExpandBoundingVolumeJob 1 + // CalculateBoundingVolumeJob 1 + // UpdateMeshTriangleListJob 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // BufferGathererJob 1 + // TexturesGathererJob 1 + // UpdateEntityLayersJob 1 + // LightGathererJob 1 + // CacheLightJob 1 + // RenderableEntityFilterJob 1 + // CacheRenderableEntitiesJob 1 + // ComputableEntityFilterJob 1 + // CacheComputableEntitiesJob singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + layerCacheJobCount + renderViewBuilderMaterialCacheJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (Nothing in cache) renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + layerCacheJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (RV leaf in cache) renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); renderer.cache()->leafNodeCache[renderer.m_frameGraphLeaves.first()] = {}; jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + layerCacheJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityEnabledDirty, nullptr); jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs 1 + // EntityEnabledDirty singleRenderViewJobCount + layerCacheJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TransformDirty, nullptr); jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // WorldTransformJob 1 + // UpdateWorldBoundingVolume 1 + // UpdateShaderDataTransform 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs 1 + // ExpandBoundingVolumeJob singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::MaterialDirty, nullptr); jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::GeometryDirty, nullptr); jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // CalculateBoundingVolumeJob 1 + // UpdateMeshTriangleListJob 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs 1 + // ExpandBoundingVolumeJob 1 + // RenderableEntityFilterPtr 1 + // SyncRenderableEntities singleRenderViewCommandRebuildJobCount + singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::BuffersDirty, nullptr); jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs 1 + // CalculateBoundingVolumeJob 1 + // UpdateMeshTriangleListJob 1 + // BufferGathererJob singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TexturesDirty, nullptr); jobs = renderer.renderBinJobs(); // THEN (level QCOMPARE(jobs.size(), 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // TexturesGathererJob 1 + // updateSkinningPaletteJob 1 + // SyncTexturesGathererJob singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); // Properly shutdown command thread renderer.shutdown(); } }; QTEST_MAIN(tst_Renderer) #include "tst_renderer.moc"