diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2016-07-12 15:16:14 +0200 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2016-10-09 10:22:11 +0000 |
commit | be1311b2de430fdafe898358c62c568717395f25 (patch) | |
tree | c20710fa85e7192335c5ce05b47bd5182042b6c4 | |
parent | cf1321a0ecc5e488da3734b200034b453410a8f2 (diff) |
Renderer: use jobs to find dirty GL resources
Change-Id: Id86e972e932d76b5dcfeacbeb5032d89b0702395
Reviewed-by: Kevin Ottens <kevin.ottens@kdab.com>
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r-- | src/render/backend/renderer.cpp | 110 | ||||
-rw-r--r-- | src/render/backend/renderer_p.h | 15 | ||||
-rw-r--r-- | src/render/jobs/job_common_p.h | 3 |
3 files changed, 90 insertions, 38 deletions
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 7f53d3c99..c8d85eff7 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -160,6 +160,9 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_calculateBoundingVolumeJob(Render::CalculateBoundingVolumeJobPtr::create()) , m_updateWorldBoundingVolumeJob(Render::UpdateWorldBoundingVolumeJobPtr::create()) , m_sendRenderCaptureJob(Render::SendRenderCaptureJobPtr::create(this)) + , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) + , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) + , m_shaderGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyShaders(); }, JobTypes::DirtyShaderGathering)) #ifdef QT3D_JOBS_RUN_STATS , m_commandExecuter(new Qt3DRender::Debug::CommandExecuter(this)) #endif @@ -750,48 +753,66 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView m_dirtyGeometry.clear(); } -void Renderer::updateGLResources() +// Executed in a job +void Renderer::lookForDirtyBuffers() { - // TO DO: The loops could be performed in a job so that we only - // have the actual dirty elements - const QVector<HBuffer> activeBufferHandles = m_nodesManager->bufferManager()->activeHandles(); for (HBuffer handle: activeBufferHandles) { Buffer *buffer = m_nodesManager->bufferManager()->data(handle); + if (buffer->isDirty()) + m_dirtyBuffers.push_back(handle); + } +} + +// Executed in a job +void Renderer::lookForDirtyTextures() +{ + const QVector<HTexture> activeTextureHandles = m_nodesManager->textureManager()->activeHandles(); + for (HTexture handle: activeTextureHandles) { + Texture *texture = m_nodesManager->textureManager()->data(handle); + if (texture->isDirty()) + m_dirtyTextures.push_back(handle); + } +} + +// Executed in a job +void Renderer::lookForDirtyShaders() +{ + const QVector<HShader> activeShaderHandles = m_nodesManager->shaderManager()->activeHandles(); + for (HShader handle: activeShaderHandles) { + Shader *shader = m_nodesManager->shaderManager()->data(handle); + // TO DO: Perform additional check for Graphics API compatibility + if (!shader->isLoaded()) + m_dirtyShaders.push_back(handle); + } +} + +void Renderer::updateGLResources() +{ + const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers); + for (HBuffer handle: dirtyBufferHandles) { + Buffer *buffer = m_nodesManager->bufferManager()->data(handle); // Perform data upload - if (buffer->isDirty()) { - // Forces creation if it doesn't exit - if (!m_graphicsContext->hasGLBufferForBuffer(buffer)) - m_graphicsContext->glBufferForRenderBuffer(buffer); - else // Otherwise update the glBuffer - m_graphicsContext->updateBuffer(buffer); - buffer->unsetDirty(); - } + // Forces creation if it doesn't exit + if (!m_graphicsContext->hasGLBufferForBuffer(buffer)) + m_graphicsContext->glBufferForRenderBuffer(buffer); + else // Otherwise update the glBuffer + m_graphicsContext->updateBuffer(buffer); + buffer->unsetDirty(); } - const QVector<HTechnique> activeTechniques = m_nodesManager->techniqueManager()->activeHandles(); - for (HTechnique techniqueHandle : activeTechniques) { - Technique *technique = m_nodesManager->techniqueManager()->data(techniqueHandle); - // If api of the renderer matches the one from the technique - if (*contextInfo() == *technique->graphicsApiFilter()) { - const auto passIds = technique->renderPasses(); - for (const QNodeId passId : passIds) { - RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId); - HShader shaderHandle = m_nodesManager->shaderManager()->lookupHandle(renderPass->shaderProgram()); - Shader *shader = m_nodesManager->shaderManager()->data(shaderHandle); - if (shader != nullptr && !shader->isLoaded()) - m_graphicsContext->loadShader(shader); - } - } + const QVector<HShader> dirtyShaderHandles = std::move(m_dirtyShaders); + for (HShader handle: dirtyShaderHandles) { + Shader *shader = m_nodesManager->shaderManager()->data(handle); + // Compile shader + m_graphicsContext->loadShader(shader); } - const QVector<HTexture> activeTextureHandles = m_nodesManager->textureManager()->activeHandles(); + const QVector<HTexture> activeTextureHandles = std::move(m_dirtyTextures); for (HTexture handle: activeTextureHandles) { Texture *texture = m_nodesManager->textureManager()->data(handle); - if (texture->isDirty()) { - // Upload/Update texture - texture->getOrCreateGLTexture(); - } + // Upload/Update texture + texture->getOrCreateGLTexture(); } } @@ -1000,6 +1021,22 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() for (const QAspectJobPtr &bufferJob : bufferJobs) m_calculateBoundingVolumeJob->addDependency(bufferJob); + + // Traverse the current framegraph. For each leaf node create a + // RenderView and set its configuration then create a job to + // populate the RenderView with a set of RenderCommands that get + // their details from the RenderNodes that are visible to the + // Camera selected by the framegraph configuration + FrameGraphVisitor visitor(this, m_nodesManager->frameGraphManager()); + visitor.traverse(frameGraphRoot(), &renderBinJobs); + + // Set dependencies of resource gatherer + for (const QAspectJobPtr &jobPtr : renderBinJobs) { + jobPtr->addDependency(m_bufferGathererJob); + jobPtr->addDependency(m_textureGathererJob); + jobPtr->addDependency(m_shaderGathererJob); + } + // Add jobs renderBinJobs.push_back(m_framePreparationJob); renderBinJobs.push_back(m_expandBoundingVolumeJob); @@ -1010,13 +1047,10 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() renderBinJobs.push_back(m_sendRenderCaptureJob); renderBinJobs.append(bufferJobs); - // Traverse the current framegraph. For each leaf node create a - // RenderView and set its configuration then create a job to - // populate the RenderView with a set of RenderCommands that get - // their details from the RenderNodes that are visible to the - // Camera selected by the framegraph configuration - FrameGraphVisitor visitor(this, m_nodesManager->frameGraphManager()); - visitor.traverse(frameGraphRoot(), &renderBinJobs); + // Jobs to prepare GL Resource upload + renderBinJobs.push_back(m_bufferGathererJob); + renderBinJobs.push_back(m_textureGathererJob); + renderBinJobs.push_back(m_shaderGathererJob); // Set target number of RenderViews m_renderQueue->setTargetRenderViewCount(visitor.leafNodeCount()); diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index ffc60273a..cc6646fdc 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -70,6 +70,7 @@ #include <Qt3DRender/private/updateworldboundingvolumejob_p.h> #include <Qt3DRender/private/platformsurfacefilter_p.h> #include <Qt3DRender/private/sendrendercapturejob_p.h> +#include <Qt3DRender/private/genericlambdajob_p.h> #include <QHash> #include <QMatrix4x4> @@ -84,6 +85,8 @@ #include <QScopedPointer> #include <QSemaphore> +#include <functional> + QT_BEGIN_NAMESPACE class QSurface; @@ -297,6 +300,18 @@ private: HVao *previousVAOHandle, OpenGLVertexArrayObject **vao); + GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob; + GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob; + GenericLambdaJobPtr<std::function<void ()>> m_shaderGathererJob; + + void lookForDirtyBuffers(); + void lookForDirtyTextures(); + void lookForDirtyShaders(); + + QVector<HBuffer> m_dirtyBuffers; + QVector<HShader> m_dirtyShaders; + QVector<HTexture> m_dirtyTextures; + #ifdef QT3D_JOBS_RUN_STATS QScopedPointer<Qt3DRender::Debug::CommandExecuter> m_commandExecuter; friend class Qt3DRender::Debug::CommandExecuter; diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h index 4eece1cc7..a5a8bb8e2 100644 --- a/src/render/jobs/job_common_p.h +++ b/src/render/jobs/job_common_p.h @@ -84,6 +84,9 @@ namespace JobTypes { LightGathering, UpdateWorldBoundingVolume, FrameSubmissionPart2, + DirtyBufferGathering, + DirtyTextureGathering, + DirtyShaderGathering, SendRenderCapture, SyncRenderViewCommandBuilding, SyncRenderViewInitialization, |