summaryrefslogtreecommitdiffstats
path: root/src/render/renderers/opengl/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/renderers/opengl/renderer')
-rw-r--r--src/render/renderers/opengl/renderer/rendercommand.cpp14
-rw-r--r--src/render/renderers/opengl/renderer/rendercommand_p.h17
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp103
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h4
-rw-r--r--src/render/renderers/opengl/renderer/renderercache_p.h2
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp526
-rw-r--r--src/render/renderers/opengl/renderer/renderview_p.h20
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder.cpp427
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder_p.h31
9 files changed, 679 insertions, 465 deletions
diff --git a/src/render/renderers/opengl/renderer/rendercommand.cpp b/src/render/renderers/opengl/renderer/rendercommand.cpp
index ee0bf0aec..072127391 100644
--- a/src/render/renderers/opengl/renderer/rendercommand.cpp
+++ b/src/render/renderers/opengl/renderer/rendercommand.cpp
@@ -71,6 +71,20 @@ RenderCommand::RenderCommand()
m_workGroups[2] = 0;
}
+bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept
+{
+ return (a.m_vao == b.m_vao && a.m_shader == b.m_shader && a.m_material == b.m_material &&
+ a.m_stateSet == b.m_stateSet && a.m_geometry == b.m_geometry && a.m_geometryRenderer == b.m_geometryRenderer &&
+ a.m_indirectDrawBuffer == b.m_indirectDrawBuffer && a.m_activeAttributes == b.m_activeAttributes &&
+ a.m_depth == b.m_depth && a.m_changeCost == b.m_changeCost && a.m_shaderDna == b.m_shaderDna &&
+ a.m_workGroups[0] == b.m_workGroups[0] && a.m_workGroups[1] == b.m_workGroups[1] && a.m_workGroups[2] == b.m_workGroups[2] &&
+ a.m_primitiveCount == b.m_primitiveCount && a.m_primitiveType == b.m_primitiveType && a.m_restartIndexValue == b.m_restartIndexValue &&
+ a.m_firstInstance == b.m_firstInstance && a.m_firstVertex == b.m_firstVertex && a.m_verticesPerPatch == b.m_verticesPerPatch &&
+ a.m_instanceCount == b.m_instanceCount && a.m_indexOffset == b.m_indexOffset && a.m_indexAttributeByteOffset == b.m_indexAttributeByteOffset &&
+ a.m_drawIndexed == b.m_drawIndexed && a.m_drawIndirect == b.m_drawIndirect && a.m_primitiveRestartEnabled == b.m_primitiveRestartEnabled &&
+ a.m_isValid == b.m_isValid && a.m_computeCommand == b.m_computeCommand);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/renderer/rendercommand_p.h b/src/render/renderers/opengl/renderer/rendercommand_p.h
index 61cc6d17d..58ab0cadd 100644
--- a/src/render/renderers/opengl/renderer/rendercommand_p.h
+++ b/src/render/renderers/opengl/renderer/rendercommand_p.h
@@ -55,6 +55,7 @@
#include <qglobal.h>
#include <Qt3DRender/private/shaderparameterpack_p.h>
#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/renderviewjobutils_p.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
@@ -69,6 +70,7 @@ namespace Qt3DRender {
namespace Render {
class RenderStateSet;
+using RenderStateSetPtr = QSharedPointer<RenderStateSet>;
class Q_AUTOTEST_EXPORT RenderCommand
{
@@ -80,12 +82,13 @@ public:
HMaterial m_material; // Purely used to ease sorting (minimize stage changes, binding changes ....)
ShaderParameterPack m_parameterPack; // Might need to be reworked so as to be able to destroy the
// Texture while submission is happening.
- RenderStateSet *m_stateSet;
+ RenderStateSetPtr m_stateSet;
HGeometry m_geometry;
HGeometryRenderer m_geometryRenderer;
HBuffer m_indirectDrawBuffer; // Reference to indirect draw buffer (valid only m_drawIndirect == true)
+ HComputeCommand m_computeCommand;
// A QAttribute pack might be interesting
// This is a temporary fix in the meantime, to remove the hacked methods in Technique
@@ -121,6 +124,18 @@ public:
bool m_isValid;
};
+Q_AUTOTEST_EXPORT bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept;
+
+inline bool operator!=(const RenderCommand &lhs, const RenderCommand &rhs) noexcept
+{ return !operator==(lhs, rhs); }
+
+struct EntityRenderCommandData
+{
+ Entity *entity;
+ RenderCommand command;
+ RenderPassParameterData passData;
+};
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 121a6aa8f..f17e66108 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -432,6 +432,9 @@ void Renderer::initialize()
m_waitForInitializationToBeCompleted.release(1);
// Allow the aspect manager to proceed
m_vsyncFrameAdvanceService->proceedToNextFrame();
+
+ // Force initial refresh
+ markDirty(AllDirty, nullptr);
}
/*!
@@ -860,13 +863,13 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
QHash<HVao, bool> updatedTable;
for (RenderView *rv: renderViews) {
- const QVector<RenderCommand *> commands = rv->commands();
- for (RenderCommand *command : commands) {
+ QVector<RenderCommand> &commands = rv->commands();
+ for (RenderCommand &command : commands) {
// Update/Create VAO
- if (command->m_type == RenderCommand::Draw) {
- Geometry *rGeometry = m_nodesManager->data<Geometry, GeometryManager>(command->m_geometry);
- GeometryRenderer *rGeometryRenderer = m_nodesManager->data<GeometryRenderer, GeometryRendererManager>(command->m_geometryRenderer);
- Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader);
+ if (command.m_type == RenderCommand::Draw) {
+ Geometry *rGeometry = m_nodesManager->data<Geometry, GeometryManager>(command.m_geometry);
+ GeometryRenderer *rGeometryRenderer = m_nodesManager->data<GeometryRenderer, GeometryRendererManager>(command.m_geometryRenderer);
+ Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command.m_shader);
// We should never have inserted a command for which these are null
// in the first place
@@ -879,15 +882,15 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
// Create VAO or return already created instance associated with command shader/geometry
// (VAO is emulated if not supported)
- createOrUpdateVAO(command, &vaoHandle, &vao);
- command->m_vao = vaoHandle;
+ createOrUpdateVAO(&command, &vaoHandle, &vao);
+ command.m_vao = vaoHandle;
// Avoids redoing the same thing for the same VAO
if (!updatedTable.contains(vaoHandle)) {
updatedTable.insert(vaoHandle, true);
// Do we have any attributes that are dirty ?
- const bool requiresPartialVAOUpdate = requiresVAOAttributeUpdate(rGeometry, command);
+ const bool requiresPartialVAOUpdate = requiresVAOAttributeUpdate(rGeometry, &command);
// If true, we need to reupload all attributes to set the VAO
// Otherwise only dirty attributes will be updates
@@ -898,7 +901,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
if (rGeometry->isDirty())
m_dirtyGeometry.push_back(rGeometry);
- if (!command->m_activeAttributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) {
+ if (!command.m_activeAttributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) {
Profiling::GLTimeRecorder recorder(Profiling::VAOUpload);
// Activate shader
m_submissionContext->activateShader(shader->dna());
@@ -906,7 +909,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
vao->bind();
// Update or set Attributes and Buffers for the given rGeometry and Command
// Note: this fills m_dirtyAttributes as well
- if (updateVAOWithAttributes(rGeometry, command, shader, requiresFullVAOUpdate))
+ if (updateVAOWithAttributes(rGeometry, &command, shader, requiresFullVAOUpdate))
vao->setSpecified(true);
}
}
@@ -918,11 +921,11 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
rGeometryRenderer->unsetDirty();
// Prepare the ShaderParameterPack based on the active uniforms of the shader
- shader->prepareUniforms(command->m_parameterPack);
+ shader->prepareUniforms(command.m_parameterPack);
{ // Scoped to show extent
- command->m_isValid = !command->m_activeAttributes.empty();
- if (!command->m_isValid)
+ command.m_isValid = !command.m_activeAttributes.empty();
+ if (!command.m_isValid)
continue;
// Update the draw command with what's going to be needed for the drawing
@@ -942,7 +945,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
indirectAttribute = attribute;
break;
case QAttribute::VertexAttribute: {
- if (command->m_activeAttributes.contains(attribute->nameId()))
+ if (command.m_activeAttributes.contains(attribute->nameId()))
estimatedCount = qMax(attribute->count(), estimatedCount);
break;
}
@@ -952,20 +955,20 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
}
}
- command->m_drawIndexed = (indexAttribute != nullptr);
- command->m_drawIndirect = (indirectAttribute != nullptr);
+ command.m_drawIndexed = (indexAttribute != nullptr);
+ command.m_drawIndirect = (indirectAttribute != nullptr);
// Update the draw command with all the information required for the drawing
- if (command->m_drawIndexed) {
- command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
- command->m_indexAttributeByteOffset = indexAttribute->byteOffset() + rGeometryRenderer->indexBufferByteOffset();
+ if (command.m_drawIndexed) {
+ command.m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
+ command.m_indexAttributeByteOffset = indexAttribute->byteOffset() + rGeometryRenderer->indexBufferByteOffset();
}
// Note: we only care about the primitiveCount when using direct draw calls
// For indirect draw calls it is assumed the buffer was properly set already
- if (command->m_drawIndirect) {
- command->m_indirectAttributeByteOffset = indirectAttribute->byteOffset();
- command->m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId());
+ if (command.m_drawIndirect) {
+ command.m_indirectAttributeByteOffset = indirectAttribute->byteOffset();
+ command.m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId());
} else {
// Use the count specified by the GeometryRender
// If not specify use the indexAttribute count if present
@@ -978,22 +981,22 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
}
}
- command->m_primitiveCount = primitiveCount;
- command->m_primitiveType = rGeometryRenderer->primitiveType();
- command->m_primitiveRestartEnabled = rGeometryRenderer->primitiveRestartEnabled();
- command->m_restartIndexValue = rGeometryRenderer->restartIndexValue();
- command->m_firstInstance = rGeometryRenderer->firstInstance();
- command->m_instanceCount = rGeometryRenderer->instanceCount();
- command->m_firstVertex = rGeometryRenderer->firstVertex();
- command->m_indexOffset = rGeometryRenderer->indexOffset();
- command->m_verticesPerPatch = rGeometryRenderer->verticesPerPatch();
+ command.m_primitiveCount = primitiveCount;
+ command.m_primitiveType = rGeometryRenderer->primitiveType();
+ command.m_primitiveRestartEnabled = rGeometryRenderer->primitiveRestartEnabled();
+ command.m_restartIndexValue = rGeometryRenderer->restartIndexValue();
+ command.m_firstInstance = rGeometryRenderer->firstInstance();
+ command.m_instanceCount = rGeometryRenderer->instanceCount();
+ command.m_firstVertex = rGeometryRenderer->firstVertex();
+ command.m_indexOffset = rGeometryRenderer->indexOffset();
+ command.m_verticesPerPatch = rGeometryRenderer->verticesPerPatch();
} // scope
- } else if (command->m_type == RenderCommand::Compute) {
- Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader);
+ } else if (command.m_type == RenderCommand::Compute) {
+ Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command.m_shader);
Q_ASSERT(shader);
// Prepare the ShaderParameterPack based on the active uniforms of the shader
- shader->prepareUniforms(command->m_parameterPack);
+ shader->prepareUniforms(command.m_parameterPack);
}
}
}
@@ -1834,6 +1837,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
const bool computeableDirty = dirtyBitsForFrame & AbstractRenderer::ComputeDirty;
const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty;
const bool materialCacheNeedsToBeRebuilt = shadersDirty || materialDirty || frameGraphDirty;
+ const bool renderCommandsDirty = materialCacheNeedsToBeRebuilt || renderableDirty || computeableDirty;
// Rebuild Entity Layers list if layers are dirty
if (layersDirty)
@@ -1873,6 +1877,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty);
builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt);
builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty);
+ builder.setRenderCommandCacheNeedsToBeRebuilt(renderCommandsDirty);
builder.prepareJobs();
renderBinJobs.append(builder.buildJobHierachy());
@@ -2075,7 +2080,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
bool allCommandsIssued = true;
// Render drawing commands
- const QVector<RenderCommand *> commands = rv->commands();
+ QVector<RenderCommand> commands = rv->commands();
// Use the graphicscontext to submit the commands to the underlying
// graphics API (OpenGL)
@@ -2084,18 +2089,18 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
RenderStateSet *globalState = m_submissionContext->currentStateSet();
OpenGLVertexArrayObject *vao = nullptr;
- for (RenderCommand *command : qAsConst(commands)) {
+ for (RenderCommand &command : commands) {
- if (command->m_type == RenderCommand::Compute) { // Compute Call
- performCompute(rv, command);
+ if (command.m_type == RenderCommand::Compute) { // Compute Call
+ performCompute(rv, &command);
} else { // Draw Command
// Check if we have a valid command that can be drawn
- if (!command->m_isValid) {
+ if (!command.m_isValid) {
allCommandsIssued = false;
continue;
}
- vao = m_nodesManager->vaoManager()->data(command->m_vao);
+ vao = m_nodesManager->vaoManager()->data(command.m_vao);
// something may have went wrong when initializing the VAO
if (!vao->isSpecified()) {
@@ -2106,7 +2111,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
{
Profiling::GLTimeRecorder recorder(Profiling::ShaderUpdate);
//// We activate the shader here
- if (!m_submissionContext->activateShader(command->m_shaderDna)) {
+ if (!m_submissionContext->activateShader(command.m_shaderDna)) {
allCommandsIssued = false;
continue;
}
@@ -2121,7 +2126,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
{
Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate);
//// Update program uniforms
- if (!m_submissionContext->setParameters(command->m_parameterPack)) {
+ if (!m_submissionContext->setParameters(command.m_parameterPack)) {
allCommandsIssued = false;
// If we have failed to set uniform (e.g unable to bind a texture)
// we won't perform the draw call which could show invalid content
@@ -2132,7 +2137,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
//// OpenGL State
// TO DO: Make states not dependendent on their backend node for this step
// Set state
- RenderStateSet *localState = command->m_stateSet;
+ RenderStateSet *localState = command.m_stateSet.data();
{
@@ -2140,8 +2145,8 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
// Merge the RenderCommand state with the globalState of the RenderView
// Or restore the globalState if no stateSet for the RenderCommand
if (localState != nullptr) {
- command->m_stateSet->merge(globalState);
- m_submissionContext->setCurrentStateSet(command->m_stateSet);
+ command.m_stateSet->merge(globalState);
+ m_submissionContext->setCurrentStateSet(localState);
} else {
m_submissionContext->setCurrentStateSet(globalState);
}
@@ -2151,7 +2156,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
// at that point
//// Draw Calls
- performDraw(command);
+ performDraw(&command);
}
} // end of RenderCommands loop
@@ -2167,7 +2172,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
}
bool Renderer::updateVAOWithAttributes(Geometry *geometry,
- RenderCommand *command,
+ const RenderCommand *command,
Shader *shader,
bool forceUpdate)
{
@@ -2227,7 +2232,7 @@ bool Renderer::updateVAOWithAttributes(Geometry *geometry,
}
bool Renderer::requiresVAOAttributeUpdate(Geometry *geometry,
- RenderCommand *command) const
+ const RenderCommand *command) const
{
const auto attributeIds = geometry->attributes();
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index b1cd4aac5..db63f31d0 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -254,12 +254,12 @@ public:
void prepareCommandsSubmission(const QVector<RenderView *> &renderViews);
bool executeCommandsSubmission(const RenderView *rv);
bool updateVAOWithAttributes(Geometry *geometry,
- RenderCommand *command,
+ const RenderCommand *command,
Shader *shader,
bool forceUpdate);
bool requiresVAOAttributeUpdate(Geometry *geometry,
- RenderCommand *command) const;
+ const RenderCommand *command) const;
void setOpenGLContext(QOpenGLContext *context) override;
const GraphicsApiFilterData *contextInfo() const;
diff --git a/src/render/renderers/opengl/renderer/renderercache_p.h b/src/render/renderers/opengl/renderer/renderercache_p.h
index 0e9c5d3cd..a1298f491 100644
--- a/src/render/renderers/opengl/renderer/renderercache_p.h
+++ b/src/render/renderers/opengl/renderer/renderercache_p.h
@@ -56,6 +56,7 @@
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/renderviewjobutils_p.h>
#include <Qt3DRender/private/lightsource_p.h>
+#include <Qt3DRender/private/rendercommand_p.h>
QT_BEGIN_NAMESPACE
@@ -73,6 +74,7 @@ struct RendererCache
QVector<Entity *> renderableEntities;
QVector<Entity *> computeEntities;
EnvironmentLight* environmentLight;
+ QVector<EntityRenderCommandData> renderCommandData;
};
QHash<FrameGraphNode *, LeafNodeData> leafNodeCache;
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index 48f622c07..c38ffae80 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -282,11 +282,6 @@ RenderView::RenderView()
RenderView::~RenderView()
{
- delete m_stateSet;
- for (RenderCommand *command : qAsConst(m_commands)) {
- delete command->m_stateSet;
- delete command;
- }
}
namespace {
@@ -294,7 +289,7 @@ namespace {
template<int SortType>
struct AdjacentSubRangeFinder
{
- static bool adjacentSubRange(RenderCommand *, RenderCommand *)
+ static bool adjacentSubRange(const RenderCommand &, const RenderCommand &)
{
Q_UNREACHABLE();
return false;
@@ -304,47 +299,47 @@ struct AdjacentSubRangeFinder
template<>
struct AdjacentSubRangeFinder<QSortPolicy::StateChangeCost>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_changeCost == b->m_changeCost;
+ return a.m_changeCost == b.m_changeCost;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::BackToFront>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_depth == b->m_depth;
+ return a.m_depth == b.m_depth;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::Material>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_shaderDna == b->m_shaderDna;
+ return a.m_shaderDna == b.m_shaderDna;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::FrontToBack>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_depth == b->m_depth;
+ return a.m_depth == b.m_depth;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::Texture>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
// Two renderCommands are adjacent if one contains all the other command's textures
- QVector<ShaderParameterPack::NamedResource> texturesA = a->m_parameterPack.textures();
- QVector<ShaderParameterPack::NamedResource> texturesB = b->m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures();
if (texturesB.size() > texturesA.size())
qSwap(texturesA, texturesB);
@@ -359,7 +354,7 @@ struct AdjacentSubRangeFinder<QSortPolicy::Texture>
};
template<typename Predicate>
-int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands,
+int advanceUntilNonAdjacent(const QVector<RenderCommand> &commands,
const int beg, const int end, Predicate pred)
{
int i = beg + 1;
@@ -372,7 +367,7 @@ int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands,
}
-using CommandIt = QVector<RenderCommand *>::iterator;
+using CommandIt = QVector<RenderCommand>::iterator;
template<int SortType>
struct SubRangeSorter
@@ -390,8 +385,8 @@ struct SubRangeSorter<QSortPolicy::StateChangeCost>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_changeCost > b->m_changeCost;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_changeCost > b.m_changeCost;
});
}
};
@@ -401,8 +396,8 @@ struct SubRangeSorter<QSortPolicy::BackToFront>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_depth > b->m_depth;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_depth > b.m_depth;
});
}
};
@@ -413,8 +408,8 @@ struct SubRangeSorter<QSortPolicy::Material>
static void sortSubRange(CommandIt begin, const CommandIt end)
{
// First we sort by shaderDNA
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_shaderDna > b->m_shaderDna;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_shaderDna > b.m_shaderDna;
});
}
};
@@ -424,8 +419,8 @@ struct SubRangeSorter<QSortPolicy::FrontToBack>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_depth < b->m_depth;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_depth < b.m_depth;
});
}
};
@@ -435,9 +430,9 @@ struct SubRangeSorter<QSortPolicy::Texture>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- QVector<ShaderParameterPack::NamedResource> texturesA = a->m_parameterPack.textures();
- QVector<ShaderParameterPack::NamedResource> texturesB = b->m_parameterPack.textures();
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures();
const int originalTextureASize = texturesA.size();
@@ -456,7 +451,7 @@ struct SubRangeSorter<QSortPolicy::Texture>
}
};
-int findSubRange(const QVector<RenderCommand *> &commands,
+int findSubRange(const QVector<RenderCommand> &commands,
const int begin, const int end,
const QSortPolicy::SortType sortType)
{
@@ -477,14 +472,14 @@ int findSubRange(const QVector<RenderCommand *> &commands,
}
}
-void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end)
+void sortByMaterial(QVector<RenderCommand> &commands, int begin, const int end)
{
// We try to arrange elements so that their rendering cost is minimized for a given shader
int rangeEnd = advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange);
while (begin != end) {
if (begin + 1 < rangeEnd) {
- std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (RenderCommand *a, RenderCommand *b){
- return a->m_material.handle() < b->m_material.handle();
+ std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (const RenderCommand &a, const RenderCommand &b){
+ return a.m_material.handle() < b.m_material.handle();
});
}
begin = rangeEnd;
@@ -492,7 +487,7 @@ void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end
}
}
-void sortCommandRange(QVector<RenderCommand *> &commands, int begin, const int end, const int level,
+void sortCommandRange(QVector<RenderCommand> &commands, int begin, const int end, const int level,
const QVector<Qt3DRender::QSortPolicy::SortType> &sortingTypes)
{
if (level >= sortingTypes.size())
@@ -542,20 +537,21 @@ void RenderView::sort()
// Minimize uniform changes
int i = 0;
- while (i < m_commands.size()) {
+ const int commandSize = m_commands.size();
+ while (i < commandSize) {
int j = i;
// Advance while commands share the same shader
- while (i < m_commands.size() && m_commands[j]->m_shaderDna == m_commands[i]->m_shaderDna)
+ while (i < commandSize && m_commands[j].m_shaderDna == m_commands[i].m_shaderDna)
++i;
if (i - j > 0) { // Several commands have the same shader, so we minimize uniform changes
- PackUniformHash cachedUniforms = m_commands[j++]->m_parameterPack.uniforms();
+ PackUniformHash cachedUniforms = m_commands[j++].m_parameterPack.uniforms();
while (j < i) {
// We need the reference here as we are modifying the original container
// not the copy
- PackUniformHash &uniforms = m_commands.at(j)->m_parameterPack.m_uniforms;
+ PackUniformHash &uniforms = m_commands[j].m_parameterPack.m_uniforms;
PackUniformHash::iterator it = uniforms.begin();
const PackUniformHash::iterator end = uniforms.end();
@@ -571,6 +567,9 @@ void RenderView::sort()
if (it.value() == refValue) {
it = uniforms.erase(it);
} else {
+ // Record updated value so that subsequent comparison
+ // for the next command will be made againts latest
+ // uniform value
cachedUniforms.insert(it.key(), it.value());
++it;
}
@@ -622,19 +621,12 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) {
}
// If we are there, we know that entity had a GeometryRenderer + Material
-QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
+QVector<EntityRenderCommandData> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
{
- // Note: since many threads can be building render commands
- // we need to ensure that the UniformBlockValueBuilder they are using
- // is only accessed from the same thread
- UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
- builder->shaderDataManager = m_manager->shaderDataManager();
- builder->textureManager = m_manager->textureManager();
- m_localData.setLocalData(builder);
-
- QVector<RenderCommand *> commands;
+ QVector<EntityRenderCommandData> commands;
commands.reserve(entities.size());
+
for (Entity *entity : entities) {
GeometryRenderer *geometryRenderer = nullptr;
HGeometryRenderer geometryRendererHandle = entity->componentHandle<GeometryRenderer>();
@@ -651,84 +643,47 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit
// 1 RenderCommand per RenderPass pass on an Entity with a Mesh
for (const RenderPassParameterData &passData : renderPassData) {
// Add the RenderPass Parameters
- RenderCommand *command = new RenderCommand();
- command->m_geometryRenderer = geometryRendererHandle;
- command->m_geometry = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId());
-
- // Project the camera-to-object-center vector onto the camera
- // view vector. This gives a depth value suitable as the key
- // for BackToFront sorting.
- command->m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir);
- command->m_material = materialHandle;
+ RenderCommand command = {};
+ command.m_geometryRenderer = geometryRendererHandle;
+ command.m_geometry = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId());
+
+ command.m_material = materialHandle;
// For RenderPass based states we use the globally set RenderState
// if no renderstates are defined as part of the pass. That means:
// RenderPass { renderStates: [] } will use the states defined by
// StateSet in the FrameGraph
RenderPass *pass = passData.pass;
if (pass->hasRenderStates()) {
- command->m_stateSet = new RenderStateSet();
- addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager());
+ command.m_stateSet = RenderStateSetPtr::create();
+ addStatesToRenderStateSet(command.m_stateSet.data(), pass->renderStates(), m_manager->renderStateManager());
if (m_stateSet != nullptr)
- command->m_stateSet->merge(m_stateSet);
- command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet);
+ command.m_stateSet->merge(m_stateSet);
+ command.m_changeCost = m_renderer->defaultRenderState()->changeCost(command.m_stateSet.data());
}
+ command.m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(pass->shaderProgram());
- // Pick which lights to take in to account.
- // For now decide based on the distance by taking the MAX_LIGHTS closest lights.
- // Replace with more sophisticated mechanisms later.
- // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command
- QVector<LightSource> lightSources = m_lightSources;
- if (lightSources.size() > 1) {
- const Vector3D entityCenter = entity->worldBoundingVolume()->center();
- std::sort(lightSources.begin(), lightSources.end(),
- [&] (const LightSource &a, const LightSource &b) {
- const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center());
- const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center());
- return distA < distB;
- });
- }
-
- ParameterInfoList globalParameters = passData.parameterInfo;
- // setShaderAndUniforms can initialize a localData
- // make sure this is cleared before we leave this function
- setShaderAndUniforms(command,
- pass,
- globalParameters,
- entity,
- lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS)),
- m_environmentLight);
-
- commands.append(command);
+ const EntityRenderCommandData commandData = { entity, command, passData };
+ commands.append(commandData);
}
}
}
- // We reset the local data once we are done with it
- m_localData.setLocalData(nullptr);
-
return commands;
}
-QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
+QVector<EntityRenderCommandData> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
{
- // Note: since many threads can be building render commands
- // we need to ensure that the UniformBlockValueBuilder they are using
- // is only accessed from the same thread
- UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
- builder->shaderDataManager = m_manager->shaderDataManager();
- builder->textureManager = m_manager->textureManager();
- m_localData.setLocalData(builder);
-
// If the RenderView contains only a ComputeDispatch then it cares about
// A ComputeDispatch is also implicitely a NoDraw operation
// enabled flag
// layer component
// material/effect/technique/parameters/filters/
- QVector<RenderCommand *> commands;
+ QVector<EntityRenderCommandData> commands;
commands.reserve(entities.size());
for (Entity *entity : entities) {
ComputeCommand *computeJob = nullptr;
- if ((computeJob = entity->renderComponent<ComputeCommand>()) != nullptr
+ HComputeCommand computeCommandHandle = entity->componentHandle<ComputeCommand>();
+ if ((computeJob = nodeManagers()->computeJobManager()->data(computeCommandHandle)) != nullptr
&& computeJob->isEnabled()) {
// Note: if frameCount has reached 0 in the previous frame, isEnabled
@@ -742,41 +697,96 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En
// 1 RenderCommand per RenderPass pass on an Entity with a Mesh
for (const RenderPassParameterData &passData : renderPassData) {
// Add the RenderPass Parameters
- RenderCommand *command = new RenderCommand();
+ RenderCommand command = {};
RenderPass *pass = passData.pass;
if (pass->hasRenderStates()) {
- command->m_stateSet = new RenderStateSet();
- addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager());
+ command.m_stateSet = RenderStateSetPtr::create();
+ addStatesToRenderStateSet(command.m_stateSet.data(), pass->renderStates(), m_manager->renderStateManager());
// Merge per pass stateset with global stateset
// so that the local stateset only overrides
if (m_stateSet != nullptr)
- command->m_stateSet->merge(m_stateSet);
- command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet);
+ command.m_stateSet->merge(m_stateSet);
+ command.m_changeCost = m_renderer->defaultRenderState()->changeCost(command.m_stateSet.data());
}
+ command.m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(pass->shaderProgram());
+ command.m_computeCommand = computeCommandHandle;
+ command.m_type = RenderCommand::Compute;
+ command.m_workGroups[0] = std::max(m_workGroups[0], computeJob->x());
+ command.m_workGroups[1] = std::max(m_workGroups[1], computeJob->y());
+ command.m_workGroups[2] = std::max(m_workGroups[2], computeJob->z());
+
+ const EntityRenderCommandData commandData = { entity, command, passData };
+ commands.append(commandData);
+ }
+ }
+ }
- command->m_type = RenderCommand::Compute;
- command->m_workGroups[0] = std::max(m_workGroups[0], computeJob->x());
- command->m_workGroups[1] = std::max(m_workGroups[1], computeJob->y());
- command->m_workGroups[2] = std::max(m_workGroups[2], computeJob->z());
-
- ParameterInfoList globalParameters = passData.parameterInfo;
- setShaderAndUniforms(command,
- pass,
- globalParameters,
- entity,
- QVector<LightSource>(),
- nullptr);
- commands.append(command);
+ return commands;
+}
+
+void RenderView::updateRenderCommand(QVector<EntityRenderCommandData *> &renderCommandData)
+{
+ // Note: since many threads can be building render commands
+ // we need to ensure that the UniformBlockValueBuilder they are using
+ // is only accessed from the same thread
+ UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
+ builder->shaderDataManager = m_manager->shaderDataManager();
+ builder->textureManager = m_manager->textureManager();
+ m_localData.setLocalData(builder);
+
+ for (EntityRenderCommandData *commandData : renderCommandData) {
+ Entity *entity = commandData->entity;
+ RenderPassParameterData passData = commandData->passData;
+ RenderCommand &command = commandData->command;
+
+ // Pick which lights to take in to account.
+ // For now decide based on the distance by taking the MAX_LIGHTS closest lights.
+ // Replace with more sophisticated mechanisms later.
+ // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command
+ QVector<LightSource> lightSources;
+ EnvironmentLight *environmentLight = nullptr;
+
+ if (command.m_type == RenderCommand::Draw) {
+ // Project the camera-to-object-center vector onto the camera
+ // view vector. This gives a depth value suitable as the key
+ // for BackToFront sorting.
+ command.m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir);
+
+ environmentLight = m_environmentLight;
+ lightSources = m_lightSources;
+
+ if (lightSources.size() > 1) {
+ const Vector3D entityCenter = entity->worldBoundingVolume()->center();
+ std::sort(lightSources.begin(), lightSources.end(),
+ [&] (const LightSource &a, const LightSource &b) {
+ const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center());
+ const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center());
+ return distA < distB;
+ });
}
+ lightSources = lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS));
+ } else { // Compute
+ // Note: if frameCount has reached 0 in the previous frame, isEnabled
+ // would be false
+ ComputeCommand *computeJob = m_manager->computeJobManager()->data(command.m_computeCommand);
+ if (computeJob->runType() == QComputeCommand::Manual)
+ computeJob->updateFrameCount();
}
+
+ ParameterInfoList globalParameters = passData.parameterInfo;
+ // setShaderAndUniforms can initialize a localData
+ // make sure this is cleared before we leave this function
+ setShaderAndUniforms(&command,
+ globalParameters,
+ entity,
+ lightSources,
+ environmentLight);
}
// We reset the local data once we are done with it
m_localData.setLocalData(nullptr);
-
- return commands;
}
void RenderView::updateMatrices()
@@ -911,7 +921,6 @@ void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &unif
}
void RenderView::setShaderAndUniforms(RenderCommand *command,
- RenderPass *rPass,
ParameterInfoList &parameters,
Entity *entity,
const QVector<LightSource> &activeLightSources,
@@ -927,163 +936,158 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
// For each ParameterBinder in the RenderPass -> create a QUniformPack
// Once that works, improve that to try and minimize QUniformPack updates
- if (rPass != nullptr) {
- // Index Shader by Shader UUID
- command->m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(rPass->shaderProgram());
- Shader *shader = m_manager->data<Shader, ShaderManager>(command->m_shader);
- if (shader != nullptr && shader->isLoaded()) {
- command->m_shaderDna = shader->dna();
-
- // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings
- // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name
- // equals to the parameter name
- const QVector<int> uniformNamesIds = shader->uniformsNamesIds();
- const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds();
- const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds();
- const QVector<int> attributeNamesIds = shader->attributeNamesIds();
-
- // Set fragData Name and index
- // Later on we might want to relink the shader if attachments have changed
- // But for now we set them once and for all
+ // Index Shader by Shader UUID
+ Shader *shader = m_manager->data<Shader, ShaderManager>(command->m_shader);
+ if (shader != nullptr && shader->isLoaded()) {
+ command->m_shaderDna = shader->dna();
+
+ // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings
+ // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name
+ // equals to the parameter name
+ const QVector<int> uniformNamesIds = shader->uniformsNamesIds();
+ const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds();
+ const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds();
+ const QVector<int> attributeNamesIds = shader->attributeNamesIds();
+
+ // Set fragData Name and index
+ // Later on we might want to relink the shader if attachments have changed
+ // But for now we set them once and for all
+ if (!m_renderTarget.isNull() && !shader->isLoaded()) {
QHash<QString, int> fragOutputs;
- if (!m_renderTarget.isNull() && !shader->isLoaded()) {
- const auto atts = m_attachmentPack.attachments();
- for (const Attachment &att : atts) {
- if (att.m_point <= QRenderTargetOutput::Color15)
- fragOutputs.insert(att.m_name, att.m_point);
- }
+ const auto atts = m_attachmentPack.attachments();
+ for (const Attachment &att : atts) {
+ if (att.m_point <= QRenderTargetOutput::Color15)
+ fragOutputs.insert(att.m_name, att.m_point);
}
+ // Set frag outputs in the shaders if hash not empty
+ if (!fragOutputs.isEmpty())
+ shader->setFragOutputs(fragOutputs);
+ }
- if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() ||
- !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) {
+ if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() ||
+ !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) {
- // Set default standard uniforms without bindings
- const Matrix4x4 worldTransform = *(entity->worldTransform());
- for (const int uniformNameId : uniformNamesIds) {
- if (ms_standardUniformSetters.contains(uniformNameId))
- setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform);
- }
+ // Set default standard uniforms without bindings
+ const Matrix4x4 worldTransform = *(entity->worldTransform());
- // Set default attributes
- for (const int attributeNameId : attributeNamesIds)
- command->m_activeAttributes.push_back(attributeNameId);
-
- // Parameters remaining could be
- // -> uniform scalar / vector
- // -> uniform struct / arrays
- // -> uniform block / array (4.3)
- // -> ssbo block / array (4.3)
-
- ParameterInfoList::const_iterator it = parameters.cbegin();
- const ParameterInfoList::const_iterator parametersEnd = parameters.cend();
-
- while (it != parametersEnd) {
- Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle);
- const UniformValue &uniformValue = param->uniformValue();
- if (uniformNamesIds.contains(it->nameId)) { // Parameter is a regular uniform
- setUniformValue(command->m_parameterPack, it->nameId, uniformValue);
- } else if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block
- setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue);
- } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO
- setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue);
- } else { // Parameter is a struct
- ShaderData *shaderData = nullptr;
- if (uniformValue.valueType() == UniformValue::NodeId &&
- (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) {
- // Try to check if we have a struct or array matching a QShaderData parameter
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId));
- }
- // Otherwise: param unused by current shader
+ for (const int uniformNameId : uniformNamesIds) {
+ if (ms_standardUniformSetters.contains(uniformNameId))
+ setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform);
+ }
+
+ // Set default attributes
+ command->m_activeAttributes = attributeNamesIds;
+
+ // Parameters remaining could be
+ // -> uniform scalar / vector
+ // -> uniform struct / arrays
+ // -> uniform block / array (4.3)
+ // -> ssbo block / array (4.3)
+
+ ParameterInfoList::const_iterator it = parameters.cbegin();
+ const ParameterInfoList::const_iterator parametersEnd = parameters.cend();
+
+ while (it != parametersEnd) {
+ Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle);
+ const UniformValue &uniformValue = param->uniformValue();
+ if (uniformNamesIds.contains(it->nameId)) { // Parameter is a regular uniform
+ setUniformValue(command->m_parameterPack, it->nameId, uniformValue);
+ } else if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block
+ setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue);
+ } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO
+ setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue);
+ } else { // Parameter is a struct
+ ShaderData *shaderData = nullptr;
+ if (uniformValue.valueType() == UniformValue::NodeId &&
+ (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) {
+ // Try to check if we have a struct or array matching a QShaderData parameter
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId));
}
- ++it;
+ // Otherwise: param unused by current shader
}
+ ++it;
+ }
+
+ // Lights
+
+ int lightIdx = 0;
+ for (const LightSource &lightSource : activeLightSources) {
+ if (lightIdx == MAX_LIGHTS)
+ break;
+ Entity *lightEntity = lightSource.entity;
+ const Vector3D worldPos = lightEntity->worldBoundingVolume()->center();
+ for (Light *light : lightSource.lights) {
+ if (!light->isEnabled())
+ continue;
- // Lights
+ ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData());
+ if (!shaderData)
+ continue;
- int lightIdx = 0;
- for (const LightSource &lightSource : activeLightSources) {
if (lightIdx == MAX_LIGHTS)
break;
- Entity *lightEntity = lightSource.entity;
- const Vector3D worldPos = lightEntity->worldBoundingVolume()->center();
- for (Light *light : lightSource.lights) {
- if (!light->isEnabled())
- continue;
-
- ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData());
- if (!shaderData)
- continue;
-
- if (lightIdx == MAX_LIGHTS)
- break;
-
- // Note: implicit conversion of values to UniformValue
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos);
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
-
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
-
- // There is no risk in doing that even if multithreaded
- // since we are sure that a shaderData is unique for a given light
- // and won't ever be referenced as a Component either
- Matrix4x4 *worldTransform = lightEntity->worldTransform();
- if (worldTransform)
- shaderData->updateWorldTransform(*worldTransform);
-
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
- ++lightIdx;
- }
- }
- if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID))
- setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 1), lightIdx)));
-
- // If no active light sources and no environment light, add a default light
- if (activeLightSources.isEmpty() && !environmentLight) {
// Note: implicit conversion of values to UniformValue
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
-
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
+
+
+ // There is no risk in doing that even if multithreaded
+ // since we are sure that a shaderData is unique for a given light
+ // and won't ever be referenced as a Component either
+ Matrix4x4 *worldTransform = lightEntity->worldTransform();
+ if (worldTransform)
+ shaderData->updateWorldTransform(*worldTransform);
+
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
+ ++lightIdx;
}
+ }
- // Environment Light
- int envLightCount = 0;
- if (environmentLight && environmentLight->isEnabled()) {
- ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData());
- if (shaderData) {
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight"));
- envLightCount = 1;
- }
- } else {
- // with some drivers, samplers (like the envbox sampler) need to be bound even though
- // they may not be actually used, otherwise draw calls can fail
- static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance"));
- static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular"));
- setUniformValue(command->m_parameterPack, irradianceId, m_renderer->submissionContext()->maxTextureUnitsCount());
- setUniformValue(command->m_parameterPack, specularId, m_renderer->submissionContext()->maxTextureUnitsCount());
+ if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID))
+ setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 1), lightIdx)));
+
+ // If no active light sources and no environment light, add a default light
+ if (activeLightSources.isEmpty() && !environmentLight) {
+ // Note: implicit conversion of values to UniformValue
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
+ }
+
+ // Environment Light
+ int envLightCount = 0;
+ if (environmentLight && environmentLight->isEnabled()) {
+ ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData());
+ if (shaderData) {
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight"));
+ envLightCount = 1;
}
- setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount);
+ } else {
+ // with some drivers, samplers (like the envbox sampler) need to be bound even though
+ // they may not be actually used, otherwise draw calls can fail
+ static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance"));
+ static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular"));
+ setUniformValue(command->m_parameterPack, irradianceId, m_renderer->submissionContext()->maxTextureUnitsCount());
+ setUniformValue(command->m_parameterPack, specularId, m_renderer->submissionContext()->maxTextureUnitsCount());
}
- // Set frag outputs in the shaders if hash not empty
- if (!fragOutputs.isEmpty())
- shader->setFragOutputs(fragOutputs);
+ setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount);
}
}
- else {
- qCWarning(Render::Backend) << Q_FUNC_INFO << "Using default effect as none was provided";
- }
}
bool RenderView::hasBlitFramebufferInfo() const
diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h
index 7ebcdb6bd..7d148118d 100644
--- a/src/render/renderers/opengl/renderer/renderview_p.h
+++ b/src/render/renderers/opengl/renderer/renderview_p.h
@@ -227,10 +227,16 @@ public:
RenderPassList passesAndParameters(ParameterInfoList *parameter, Entity *node, bool useDefaultMaterials = true);
- QVector<RenderCommand *> buildDrawRenderCommands(const QVector<Entity *> &entities) const;
- QVector<RenderCommand *> buildComputeRenderCommands(const QVector<Entity *> &entities) const;
- void setCommands(QVector<RenderCommand *> &commands) Q_DECL_NOTHROW { m_commands = commands; }
- QVector<RenderCommand *> commands() const Q_DECL_NOTHROW { return m_commands; }
+ QVector<EntityRenderCommandData> buildDrawRenderCommands(const QVector<Entity *> &entities) const;
+ QVector<EntityRenderCommandData> buildComputeRenderCommands(const QVector<Entity *> &entities) const;
+
+
+ void updateRenderCommand(QVector<EntityRenderCommandData *> &renderCommandData);
+
+
+ void setCommands(const QVector<RenderCommand> &commands) Q_DECL_NOTHROW { m_commands = commands; }
+ QVector<RenderCommand> &commands() { return m_commands; }
+ QVector<RenderCommand> commands() const { return m_commands; }
void setAttachmentPack(const AttachmentPack &pack) { m_attachmentPack = pack; }
const AttachmentPack &attachmentPack() const { return m_attachmentPack; }
@@ -291,7 +297,6 @@ public:
private:
void setShaderAndUniforms(RenderCommand *command,
- RenderPass *pass,
ParameterInfoList &parameters,
Entity *entity,
const QVector<LightSource> &activeLightSources,
@@ -331,10 +336,7 @@ private:
QVector<Qt3DCore::QNodeId> m_insertFenceIds;
QVector<QWaitFenceData> m_waitFences;
- // We do not use pointers to RenderNodes or Drawable's here so that the
- // render aspect is free to change the drawables on the next frame whilst
- // the render thread is submitting these commands.
- QVector<RenderCommand *> m_commands;
+ QVector<RenderCommand> m_commands;
mutable QVector<LightSource> m_lightSources;
EnvironmentLight *m_environmentLight;
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
index 83fab301a..3c6521263 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
@@ -54,14 +54,60 @@ const int RenderViewBuilder::m_optimalParallelJobCount = std::max(std::min(4, QT
namespace {
-class SyncRenderViewCommandBuilders
+class SyncPreCommandBuilding
{
public:
- explicit SyncRenderViewCommandBuilders(const RenderViewInitializerJobPtr &renderViewJob,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs,
- Renderer *renderer)
+ explicit SyncPreCommandBuilding(RenderViewInitializerJobPtr renderViewInitializerJob,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
+ Renderer *renderer,
+ FrameGraphNode *leafNode)
+ : m_renderViewInitializer(renderViewInitializerJob)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
+ , m_renderer(renderer)
+ , m_leafNode(leafNode)
+ {
+ }
+
+ void operator()()
+ {
+ // Split commands to build among jobs
+ QMutexLocker lock(m_renderer->cache()->mutex());
+ // Rebuild RenderCommands for all entities in RV (ignoring filtering)
+ const RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
+ RenderView *rv = m_renderViewInitializer->renderView();
+ const auto entities = !rv->isCompute() ? dataCacheForLeaf.renderableEntities : dataCacheForLeaf.computeEntities;
+
+ rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
+
+ lock.unlock();
+
+ // Split among the number of command builders
+ int i = 0;
+ const int m = RenderViewBuilder::optimalJobCount() - 1;
+ const int packetSize = entities.size() / RenderViewBuilder::optimalJobCount();
+ while (i < m) {
+ const RenderViewCommandBuilderJobPtr renderViewCommandBuilder = m_renderViewCommandBuilderJobs.at(i);
+ renderViewCommandBuilder->setEntities(entities.mid(i * packetSize, packetSize));
+ ++i;
+ }
+ m_renderViewCommandBuilderJobs.at(i)->setEntities(entities.mid(i * packetSize, packetSize + entities.size() % (m + 1)));
+ }
+
+private:
+ RenderViewInitializerJobPtr m_renderViewInitializer;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
+ Renderer *m_renderer;
+ FrameGraphNode *m_leafNode;
+};
+
+class SyncRenderViewPostCommandUpdate
+{
+public:
+ explicit SyncRenderViewPostCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdateJobs,
+ Renderer *renderer)
: m_renderViewJob(renderViewJob)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdateJobs)
, m_renderer(renderer)
{}
@@ -71,17 +117,19 @@ public:
RenderView *rv = m_renderViewJob->renderView();
int totalCommandCount = 0;
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs))
totalCommandCount += renderViewCommandBuilder->commands().size();
- QVector<RenderCommand *> commands;
+ QVector<RenderCommand> commands;
commands.reserve(totalCommandCount);
// Reduction
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs))
commands += std::move(renderViewCommandBuilder->commands());
+
rv->setCommands(commands);
+ // TO DO: Find way to store commands once or at least only when required
// Sort the commands
rv->sort();
@@ -91,15 +139,15 @@ public:
private:
RenderViewInitializerJobPtr m_renderViewJob;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
Renderer *m_renderer;
};
-class SyncFrustumCulling
+class SyncPreFrustumCulling
{
public:
- explicit SyncFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCulling)
+ explicit SyncPreFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCulling)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCulling)
{}
@@ -120,21 +168,23 @@ private:
FrustumCullingJobPtr m_frustumCullingJob;
};
-class SyncRenderViewInitialization
+class SyncRenderViewPostInitialization
{
public:
- explicit SyncRenderViewInitialization(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterLayerEntityJobPtr &filterEntityByLayerJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs)
+ explicit SyncRenderViewPostInitialization(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCullingJob,
+ const FilterLayerEntityJobPtr &filterEntityByLayerJob,
+ const FilterProximityDistanceJobPtr &filterProximityJob,
+ const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCullingJob)
, m_filterEntityByLayerJob(filterEntityByLayerJob)
, m_filterProximityJob(filterProximityJob)
, m_materialGathererJobs(materialGathererJobs)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
{}
void operator()()
@@ -154,8 +204,10 @@ public:
materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter()));
}
- // Command builders
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ // Command builders and updates
+ for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs))
+ renderViewCommandUpdater->setRenderView(rv);
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
renderViewCommandBuilder->setRenderView(rv);
// Set whether frustum culling is enabled or not
@@ -168,26 +220,31 @@ private:
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
};
-class SyncRenderCommandBuilding
+class SyncRenderViewPreCommandUpdate
{
public:
- explicit SyncRenderCommandBuilding(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs,
- Renderer *renderer,
- FrameGraphNode *leafNode)
+ explicit SyncRenderViewPreCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCullingJob,
+ const FilterProximityDistanceJobPtr &filterProximityJob,
+ const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
+ Renderer *renderer,
+ FrameGraphNode *leafNode,
+ bool fullCommandRebuild)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCullingJob)
, m_filterProximityJob(filterProximityJob)
, m_materialGathererJobs(materialGathererJobs)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
, m_renderer(renderer)
, m_leafNode(leafNode)
+ , m_fullRebuild(fullCommandRebuild)
{}
void operator()()
@@ -197,21 +254,45 @@ public:
RenderView *rv = m_renderViewJob->renderView();
if (!rv->noDraw()) {
- QVector<Entity *> renderableEntities;
- const bool isDraw = !rv->isCompute();
+ ///////// CACHE LOCKED ////////////
+ // Retrieve Data from Cache
QMutexLocker lock(m_renderer->cache()->mutex());
- const auto& cacheData = m_renderer->cache()->leafNodeCache.value(m_leafNode);
+ Q_ASSERT(m_renderer->cache()->leafNodeCache.contains(m_leafNode));
- if (isDraw)
- renderableEntities = cacheData.renderableEntities;
- else
- renderableEntities = cacheData.computeEntities;
+ const bool isDraw = !rv->isCompute();
+ const RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
+
+ // Rebuild RenderCommands if required
+ // This should happen fairly infrequently (FrameGraph Change, Geometry/Material change)
+ // and allow to skip that step most of the time
+ if (m_fullRebuild) {
+ // Clear previous cache
+ RendererCache::LeafNodeData &writableCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
+ writableCacheForLeaf.renderCommandData.clear();
+
+ QVector<EntityRenderCommandData> commandData;
+ // Reduction
+ {
+ int totalCommandCount = 0;
+ for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
+ totalCommandCount += renderViewCommandBuilder->commandData().size();
+ commandData.reserve(totalCommandCount);
+ for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
+ commandData += std::move(renderViewCommandBuilder->commandData());
+ }
+ // Store in cache
+ writableCacheForLeaf.renderCommandData = std::move(commandData);
+ }
+ const QVector<EntityRenderCommandData> commandData = dataCacheForLeaf.renderCommandData;
- const QVector<Entity *> filteredEntities = cacheData.filterEntitiesByLayer;
- QVector<LightSource> lightSources = cacheData.gatheredLights;
- rv->setEnvironmentLight(cacheData.environmentLight);
+ QVector<Entity *> renderableEntities = isDraw ? dataCacheForLeaf.renderableEntities : dataCacheForLeaf.computeEntities;
+ const QVector<Entity *> filteredEntities = dataCacheForLeaf.filterEntitiesByLayer;
+ QVector<LightSource> lightSources = dataCacheForLeaf.gatheredLights;
+ rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
+ rv->setEnvironmentLight(dataCacheForLeaf.environmentLight);
lock.unlock();
+ ///////// END OF CACHE LOCKED ////////////
// Filter out entities that weren't selected by the layer filters
// Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector
@@ -232,20 +313,43 @@ public:
renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_filterProximityJob->filteredEntities());
}
+ // Filter out Render commands for which the Entity wasn't selected because
+ // of frustum, proximity or layer filtering
+ QVector<EntityRenderCommandData *> filteredCommandData;
+ filteredCommandData.reserve(renderableEntities.size());
+ // Because dataCacheForLeaf.renderableEntities or computeEntities are sorted
+ // What we get out of EntityRenderCommandData is also sorted by Entity
+ auto eIt = std::cbegin(renderableEntities);
+ auto cIt = std::cbegin(commandData);
+ const auto eEnd = std::cend(renderableEntities);
+ const auto cEnd = std::cend(commandData);
+
+ while (eIt != eEnd) {
+ const Entity *targetEntity = *eIt;
+ // Advance until we have commands whose Entity has a lower address
+ // than the selected filtered entity
+ while (cIt->entity < targetEntity && cIt != cEnd)
+ ++cIt;
+
+ // Push pointers to command data for all commands that match the
+ // entity
+ while (cIt->entity == targetEntity && cIt != cEnd) {
+ filteredCommandData.push_back(const_cast<EntityRenderCommandData *>(&(*cIt)));
+ ++cIt;
+ }
+ ++eIt;
+ }
+
// Split among the number of command builders
int i = 0;
const int m = RenderViewBuilder::optimalJobCount() - 1;
- const int packetSize = renderableEntities.size() / RenderViewBuilder::optimalJobCount();
+ const int packetSize = filteredCommandData.size() / RenderViewBuilder::optimalJobCount();
while (i < m) {
- const RenderViewBuilderJobPtr renderViewCommandBuilder = m_renderViewBuilderJobs.at(i);
- renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize));
+ const RenderViewCommandUpdaterJobPtr renderViewCommandBuilder = m_renderViewCommandUpdaterJobs.at(i);
+ renderViewCommandBuilder->setRenderables(filteredCommandData.mid(i * packetSize, packetSize));
++i;
}
- m_renderViewBuilderJobs.at(i)->setRenderables(renderableEntities.mid(i * packetSize, packetSize + renderableEntities.size() % (m + 1)));
- {
- QMutexLocker rendererCacheLock(m_renderer->cache()->mutex());
- rv->setMaterialParameterTable(m_renderer->cache()->leafNodeCache.value(m_leafNode).materialParameterGatherer);
- }
+ m_renderViewCommandUpdaterJobs.at(i)->setRenderables(filteredCommandData.mid(i * packetSize, packetSize + filteredCommandData.size() % (m + 1)));
}
}
@@ -254,9 +358,11 @@ private:
FrustumCullingJobPtr m_frustumCullingJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
Renderer *m_renderer;
FrameGraphNode *m_leafNode;
+ bool m_fullRebuild;
};
class SetClearDrawBufferIndex
@@ -365,8 +471,8 @@ class SyncRenderableEntities
{
public:
explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
+ Renderer *renderer,
+ FrameGraphNode *leafNode)
: m_gatherJob(gatherJob)
, m_renderer(renderer)
, m_leafNode(leafNode)
@@ -375,10 +481,12 @@ public:
void operator()()
{
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
QMutexLocker lock(m_renderer->cache()->mutex());
RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.renderableEntities = m_gatherJob->filteredEntities();
- std::sort(dataCacheForLeaf.renderableEntities.begin(), dataCacheForLeaf.renderableEntities.end());
+ dataCacheForLeaf.renderableEntities = selectedEntities;
}
private:
@@ -391,8 +499,8 @@ class SyncComputableEntities
{
public:
explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
+ Renderer *renderer,
+ FrameGraphNode *leafNode)
: m_gatherJob(gatherJob)
, m_renderer(renderer)
, m_leafNode(leafNode)
@@ -401,10 +509,12 @@ public:
void operator()()
{
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
QMutexLocker lock(m_renderer->cache()->mutex());
RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.computeEntities = m_gatherJob->filteredEntities();
- std::sort(dataCacheForLeaf.computeEntities.begin(), dataCacheForLeaf.computeEntities.end());
+ dataCacheForLeaf.computeEntities = selectedEntities;
}
private:
@@ -424,10 +534,11 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende
, m_lightsCacheNeedsToBeRebuilt(false)
, m_renderableCacheNeedsToBeRebuilt(false)
, m_computableCacheNeedsToBeRebuilt(false)
+ , m_renderCommandCacheNeedsToBeRebuilt(false)
, m_renderViewJob(RenderViewInitializerJobPtr::create())
, m_filterEntityByLayerJob()
, m_frustumCullingJob(new Render::FrustumCullingJob())
- , m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
+ , m_syncPreFrustumCullingJob(SynchronizerJobPtr::create(SyncPreFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
, m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex))
, m_syncFilterEntityByLayerJob()
, m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create())
@@ -464,9 +575,14 @@ FrustumCullingJobPtr RenderViewBuilder::frustumCullingJob() const
return m_frustumCullingJob;
}
-QVector<RenderViewBuilderJobPtr> RenderViewBuilder::renderViewBuilderJobs() const
+QVector<RenderViewCommandUpdaterJobPtr> RenderViewBuilder::renderViewCommandUpdaterJobs() const
+{
+ return m_renderViewCommandUpdaterJobs;
+}
+
+QVector<RenderViewCommandBuilderJobPtr> RenderViewBuilder::renderViewCommandBuilderJobs() const
{
- return m_renderViewBuilderJobs;
+ return m_renderViewCommandBuilderJobs;
}
QVector<MaterialParameterGathererJobPtr> RenderViewBuilder::materialGathererJobs() const
@@ -474,24 +590,29 @@ QVector<MaterialParameterGathererJobPtr> RenderViewBuilder::materialGathererJobs
return m_materialGathererJobs;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderViewInitializationJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPostInitializationJob() const
+{
+ return m_syncRenderViewPostInitializationJob;
+}
+
+SynchronizerJobPtr RenderViewBuilder::syncPreFrustumCullingJob() const
{
- return m_syncRenderViewInitializationJob;
+ return m_syncPreFrustumCullingJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncFrustumCullingJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPreCommandBuildingJob() const
{
- return m_syncFrustumCullingJob;
+ return m_syncRenderViewPreCommandBuildingJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderCommandBuildingJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPreCommandUpdateJob() const
{
- return m_syncRenderCommandBuildingJob;
+ return m_syncRenderViewPreCommandUpdateJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderViewCommandBuildersJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPostCommandUpdateJob() const
{
- return m_syncRenderViewCommandBuildersJob;
+ return m_syncRenderViewPostCommandUpdateJob;
}
SynchronizerJobPtr RenderViewBuilder::setClearDrawBufferIndexJob() const
@@ -526,7 +647,7 @@ void RenderViewBuilder::prepareJobs()
m_lightGathererJob->setManager(entityManager);
m_cacheLightsJob = SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
+ JobTypes::EntityComponentTypeFiltering);
m_cacheLightsJob->addDependency(m_lightGathererJob);
}
@@ -535,8 +656,8 @@ void RenderViewBuilder::prepareJobs()
m_renderableEntityFilterJob->setManager(entityManager);
m_cacheRenderableEntitiesJob = SynchronizerJobPtr::create(
- SyncRenderableEntities(m_renderableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
+ SyncRenderableEntities(m_renderableEntityFilterJob, m_renderer, m_leafNode),
+ JobTypes::EntityComponentTypeFiltering);
m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob);
}
@@ -545,23 +666,36 @@ void RenderViewBuilder::prepareJobs()
m_computableEntityFilterJob->setManager(entityManager);
m_cacheComputableEntitiesJob = SynchronizerJobPtr::create(
- SyncComputableEntities(m_computableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
+ SyncComputableEntities(m_computableEntityFilterJob, m_renderer, m_leafNode),
+ JobTypes::EntityComponentTypeFiltering);
m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob);
}
+ if (m_renderCommandCacheNeedsToBeRebuilt) {
+
+ m_renderViewCommandBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
+ auto renderViewCommandBuilder = Render::RenderViewCommandBuilderJobPtr::create();
+ m_renderViewCommandBuilderJobs.push_back(renderViewCommandBuilder);
+ }
+ m_syncRenderViewPreCommandBuildingJob = SynchronizerJobPtr::create(SyncPreCommandBuilding(m_renderViewJob,
+ m_renderViewCommandBuilderJobs,
+ m_renderer,
+ m_leafNode),
+ JobTypes::SyncRenderViewPreCommandBuilding);
+ }
+
m_renderViewJob->setRenderer(m_renderer);
m_renderViewJob->setFrameGraphLeafNode(m_leafNode);
m_renderViewJob->setSubmitOrderIndex(m_renderViewIndex);
// RenderCommand building is the most consuming task -> split it
// Estimate the number of jobs to create based on the number of entities
- m_renderViewBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ m_renderViewCommandUpdaterJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
- auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create();
- renderViewCommandBuilder->setIndex(m_renderViewIndex);
- renderViewCommandBuilder->setRenderer(m_renderer);
- m_renderViewBuilderJobs.push_back(renderViewCommandBuilder);
+ auto renderViewCommandUpdater = Render::RenderViewCommandUpdaterJobPtr::create();
+ renderViewCommandUpdater->setRenderer(m_renderer);
+ m_renderViewCommandUpdaterJobs.push_back(renderViewCommandUpdater);
}
if (m_materialGathererCacheNeedsToBeRebuilt) {
@@ -582,7 +716,7 @@ void RenderViewBuilder::prepareJobs()
m_syncMaterialGathererJob = SynchronizerJobPtr::create(SyncMaterialParameterGatherer(m_materialGathererJobs,
m_renderer,
m_leafNode),
- JobTypes::SyncMaterialGatherer);
+ JobTypes::SyncMaterialGatherer);
}
if (m_layerCacheNeedsToBeRebuilt) {
@@ -594,34 +728,37 @@ void RenderViewBuilder::prepareJobs()
JobTypes::SyncFilterEntityByLayer);
}
- m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob,
- m_frustumCullingJob,
- m_filterProximityJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs,
- m_renderer,
- m_leafNode),
- JobTypes::SyncRenderViewCommandBuilding);
-
- m_syncRenderViewCommandBuildersJob = SynchronizerJobPtr::create(SyncRenderViewCommandBuilders(m_renderViewJob,
- m_renderViewBuilderJobs,
- m_renderer),
- JobTypes::SyncRenderViewCommandBuilder);
-
- m_syncRenderViewInitializationJob = SynchronizerJobPtr::create(SyncRenderViewInitialization(m_renderViewJob,
- m_frustumCullingJob,
- m_filterEntityByLayerJob,
- m_filterProximityJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs),
- JobTypes::SyncRenderViewInitialization);
+ m_syncRenderViewPreCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPreCommandUpdate(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterProximityJob,
+ m_materialGathererJobs,
+ m_renderViewCommandUpdaterJobs,
+ m_renderViewCommandBuilderJobs,
+ m_renderer,
+ m_leafNode,
+ m_renderCommandCacheNeedsToBeRebuilt),
+ JobTypes::SyncRenderViewPreCommandUpdate);
+
+ m_syncRenderViewPostCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPostCommandUpdate(m_renderViewJob,
+ m_renderViewCommandUpdaterJobs,
+ m_renderer),
+ JobTypes::SyncRenderViewPostCommandUpdate);
+
+ m_syncRenderViewPostInitializationJob = SynchronizerJobPtr::create(SyncRenderViewPostInitialization(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterEntityByLayerJob,
+ m_filterProximityJob,
+ m_materialGathererJobs,
+ m_renderViewCommandUpdaterJobs,
+ m_renderViewCommandBuilderJobs),
+ JobTypes::SyncRenderViewInitialization);
}
QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
{
QVector<Qt3DCore::QAspectJobPtr> jobs;
- jobs.reserve(m_materialGathererJobs.size() + m_renderViewBuilderJobs.size() + 11);
+ jobs.reserve(m_materialGathererJobs.size() + m_renderViewCommandUpdaterJobs.size() + 11);
// Set dependencies
@@ -629,36 +766,36 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
// TODO: Maybe only update skinning palettes for non-culled entities
m_renderViewJob->addDependency(m_renderer->updateSkinningPaletteJob());
- m_syncFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob());
- m_syncFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob());
- m_syncFrustumCullingJob->addDependency(m_syncRenderViewInitializationJob);
+ m_syncPreFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob());
+ m_syncPreFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob());
+ m_syncPreFrustumCullingJob->addDependency(m_syncRenderViewPostInitializationJob);
m_frustumCullingJob->addDependency(m_renderer->expandBoundingVolumeJob());
- m_frustumCullingJob->addDependency(m_syncFrustumCullingJob);
+ m_frustumCullingJob->addDependency(m_syncPreFrustumCullingJob);
- m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewInitializationJob);
+ m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewPostInitializationJob);
- m_syncRenderViewInitializationJob->addDependency(m_renderViewJob);
+ m_syncRenderViewPostInitializationJob->addDependency(m_renderViewJob);
m_filterProximityJob->addDependency(m_renderer->expandBoundingVolumeJob());
- m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob);
+ m_filterProximityJob->addDependency(m_syncRenderViewPostInitializationJob);
- m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob);
- m_syncRenderCommandBuildingJob->addDependency(m_filterProximityJob);
- m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncRenderViewPostInitializationJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_filterProximityJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_frustumCullingJob);
// Ensure the RenderThread won't be able to process dirtyResources
// before they have been completely gathered
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->introspectShadersJob());
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->bufferGathererJob());
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->textureGathererJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->introspectShadersJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->bufferGathererJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->textureGathererJob());
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) {
- renderViewCommandBuilder->addDependency(m_syncRenderCommandBuildingJob);
- m_syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder);
+ for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs)) {
+ renderViewCommandUpdater->addDependency(m_syncRenderViewPreCommandUpdateJob);
+ m_syncRenderViewPostCommandUpdateJob->addDependency(renderViewCommandUpdater);
}
- m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewCommandBuildersJob);
+ m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewPostCommandUpdateJob);
m_renderer->frameCleanupJob()->addDependency(m_setClearDrawBufferIndexJob);
// Add jobs
@@ -667,59 +804,75 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
if (m_lightsCacheNeedsToBeRebuilt) {
jobs.push_back(m_lightGathererJob); // Step 1
jobs.push_back(m_cacheLightsJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheLightsJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_cacheLightsJob);
}
if (m_renderableCacheNeedsToBeRebuilt) {
jobs.push_back(m_renderableEntityFilterJob); // Step 1
jobs.push_back(m_cacheRenderableEntitiesJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheRenderableEntitiesJob);
}
if (m_computableCacheNeedsToBeRebuilt) {
// Note: do it only if OpenGL 4.3+ available
jobs.push_back(m_computableEntityFilterJob); // Step 1
jobs.push_back(m_cacheComputableEntitiesJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheComputableEntitiesJob);
}
- jobs.push_back(m_syncRenderViewInitializationJob); // Step 2
+ jobs.push_back(m_syncRenderViewPostInitializationJob); // Step 2
+
+ if (m_renderCommandCacheNeedsToBeRebuilt) { // Step 3
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_cacheComputableEntitiesJob);
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_cacheRenderableEntitiesJob);
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncRenderViewPostInitializationJob);
+
+ if (m_materialGathererCacheNeedsToBeRebuilt)
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncMaterialGathererJob);
+
+ jobs.push_back(m_syncRenderViewPreCommandBuildingJob);
+
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs)) {
+ renderViewCommandBuilder->addDependency(m_syncRenderViewPreCommandBuildingJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(renderViewCommandBuilder);
+ jobs.push_back(renderViewCommandBuilder);
+ }
+ }
if (m_layerCacheNeedsToBeRebuilt) {
m_filterEntityByLayerJob->addDependency(m_renderer->updateEntityLayersJob());
- m_filterEntityByLayerJob->addDependency(m_syncRenderViewInitializationJob);
+ m_filterEntityByLayerJob->addDependency(m_syncRenderViewPostInitializationJob);
m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob());
m_syncFilterEntityByLayerJob->addDependency(m_filterEntityByLayerJob);
- m_syncRenderCommandBuildingJob->addDependency(m_syncFilterEntityByLayerJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncFilterEntityByLayerJob);
jobs.push_back(m_filterEntityByLayerJob); // Step 3
jobs.push_back(m_syncFilterEntityByLayerJob); // Step 4
}
- jobs.push_back(m_syncFrustumCullingJob); // Step 3
+ jobs.push_back(m_syncPreFrustumCullingJob); // Step 3
jobs.push_back(m_filterProximityJob); // Step 3
jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3
if (m_materialGathererCacheNeedsToBeRebuilt) {
for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
- materialGatherer->addDependency(m_syncRenderViewInitializationJob);
+ materialGatherer->addDependency(m_syncRenderViewPostInitializationJob);
materialGatherer->addDependency(m_renderer->introspectShadersJob());
materialGatherer->addDependency(m_renderer->filterCompatibleTechniqueJob());
jobs.push_back(materialGatherer); // Step3
m_syncMaterialGathererJob->addDependency(materialGatherer);
}
- m_syncRenderCommandBuildingJob->addDependency(m_syncMaterialGathererJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncMaterialGathererJob);
jobs.push_back(m_syncMaterialGathererJob); // Step 3
}
jobs.push_back(m_frustumCullingJob); // Step 4
- jobs.push_back(m_syncRenderCommandBuildingJob); // Step 5
+ jobs.push_back(m_syncRenderViewPreCommandUpdateJob); // Step 5
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 6
+ // Build RenderCommands or Update RenderCommand Uniforms
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs)) // Step 6
jobs.push_back(renderViewCommandBuilder);
- jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 7
+ jobs.push_back(m_syncRenderViewPostCommandUpdateJob); // Step 7
return jobs;
}
@@ -784,6 +937,16 @@ bool RenderViewBuilder::lightGathererCacheNeedsToBeRebuilt() const
return m_lightsCacheNeedsToBeRebuilt;
}
+void RenderViewBuilder::setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
+{
+ m_renderCommandCacheNeedsToBeRebuilt = needsToBeRebuilt;
+}
+
+bool RenderViewBuilder::renderCommandCacheNeedsToBeRebuilt() const
+{
+ return m_renderCommandCacheNeedsToBeRebuilt;
+}
+
int RenderViewBuilder::optimalJobCount()
{
return RenderViewBuilder::m_optimalParallelJobCount;
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
index e223a5f1e..66344da11 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
@@ -58,7 +58,8 @@
#include <Qt3DRender/private/genericlambdajob_p.h>
#include <Qt3DRender/private/materialparametergathererjob_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
-#include <Qt3DRender/private/renderviewbuilderjob_p.h>
+#include <Qt3DRender/private/renderviewcommandbuilderjob_p.h>
+#include <Qt3DRender/private/renderviewcommandupdaterjob_p.h>
#include <Qt3DRender/private/renderview_p.h>
#include <Qt3DRender/private/frustumcullingjob_p.h>
#include <Qt3DRender/private/lightgatherer_p.h>
@@ -87,12 +88,14 @@ public:
RenderableEntityFilterPtr renderableEntityFilterJob() const;
ComputableEntityFilterPtr computableEntityFilterJob() const;
FrustumCullingJobPtr frustumCullingJob() const;
- QVector<RenderViewBuilderJobPtr> renderViewBuilderJobs() const;
+ QVector<RenderViewCommandBuilderJobPtr> renderViewCommandBuilderJobs() const;
+ QVector<RenderViewCommandUpdaterJobPtr> renderViewCommandUpdaterJobs() const;
QVector<MaterialParameterGathererJobPtr> materialGathererJobs() const;
- SynchronizerJobPtr syncRenderViewInitializationJob() const;
- SynchronizerJobPtr syncFrustumCullingJob() const;
- SynchronizerJobPtr syncRenderCommandBuildingJob() const;
- SynchronizerJobPtr syncRenderViewCommandBuildersJob() const;
+ SynchronizerJobPtr syncRenderViewPostInitializationJob() const;
+ SynchronizerJobPtr syncPreFrustumCullingJob() const;
+ SynchronizerJobPtr syncRenderViewPreCommandBuildingJob() const;
+ SynchronizerJobPtr syncRenderViewPreCommandUpdateJob() const;
+ SynchronizerJobPtr syncRenderViewPostCommandUpdateJob() const;
SynchronizerJobPtr setClearDrawBufferIndexJob() const;
SynchronizerJobPtr syncFilterEntityByLayerJob() const;
FilterProximityDistanceJobPtr filterProximityJob() const;
@@ -118,6 +121,9 @@ public:
void setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
bool lightGathererCacheNeedsToBeRebuilt() const;
+ void setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
+ bool renderCommandCacheNeedsToBeRebuilt() const;
+
static int optimalJobCount();
static QVector<Entity *> entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset);
@@ -130,6 +136,7 @@ private:
bool m_lightsCacheNeedsToBeRebuilt;
bool m_renderableCacheNeedsToBeRebuilt;
bool m_computableCacheNeedsToBeRebuilt;
+ bool m_renderCommandCacheNeedsToBeRebuilt;
RenderViewInitializerJobPtr m_renderViewJob;
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
@@ -137,13 +144,15 @@ private:
RenderableEntityFilterPtr m_renderableEntityFilterJob;
ComputableEntityFilterPtr m_computableEntityFilterJob;
FrustumCullingJobPtr m_frustumCullingJob;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- SynchronizerJobPtr m_syncRenderViewInitializationJob;
- SynchronizerJobPtr m_syncFrustumCullingJob;
- SynchronizerJobPtr m_syncRenderCommandBuildingJob;
- SynchronizerJobPtr m_syncRenderViewCommandBuildersJob;
+ SynchronizerJobPtr m_syncRenderViewPostInitializationJob;
+ SynchronizerJobPtr m_syncPreFrustumCullingJob;
+ SynchronizerJobPtr m_syncRenderViewPreCommandBuildingJob;
+ SynchronizerJobPtr m_syncRenderViewPreCommandUpdateJob;
+ SynchronizerJobPtr m_syncRenderViewPostCommandUpdateJob;
SynchronizerJobPtr m_setClearDrawBufferIndexJob;
SynchronizerJobPtr m_syncFilterEntityByLayerJob;
SynchronizerJobPtr m_syncMaterialGathererJob;