summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/backend/platformsurfacefilter.cpp4
-rw-r--r--src/render/backend/renderer.cpp150
-rw-r--r--src/render/backend/renderer_p.h4
-rw-r--r--src/render/backend/renderqueue.cpp6
-rw-r--r--src/render/backend/renderqueue_p.h4
-rw-r--r--src/render/backend/renderviewbuilder.cpp28
-rw-r--r--src/render/framegraph/framegraphvisitor.cpp26
-rw-r--r--src/render/framegraph/framegraphvisitor_p.h14
-rw-r--r--src/render/framegraph/qsortcriterion.cpp82
-rw-r--r--src/render/framegraph/qsortcriterion.h85
-rw-r--r--src/render/framegraph/rendercapture.cpp2
-rw-r--r--src/render/framegraph/viewportnode.cpp2
-rw-r--r--src/render/frontend/qabstractfunctor.h8
-rw-r--r--src/render/frontend/qlevelofdetail.cpp33
-rw-r--r--src/render/frontend/qlevelofdetailswitch.cpp8
-rw-r--r--src/render/frontend/qrenderaspect.cpp4
-rw-r--r--src/render/geometry/attribute.cpp2
-rw-r--r--src/render/geometry/buffer.cpp25
-rw-r--r--src/render/geometry/buffer_p.h1
-rw-r--r--src/render/geometry/geometryrenderer.cpp2
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp50
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp6
-rw-r--r--src/render/materialsystem/qeffect.cpp60
-rw-r--r--src/render/materialsystem/qmaterial.cpp102
-rw-r--r--src/render/materialsystem/qparameter.cpp127
-rw-r--r--src/render/materialsystem/qrenderpass.cpp89
-rw-r--r--src/render/materialsystem/qtechnique.cpp128
-rw-r--r--src/render/materialsystem/shader.cpp12
-rw-r--r--src/render/raycasting/qabstractcollisionqueryservice_p.h1
-rw-r--r--src/render/texture/apitexturemanager_p.h2
-rw-r--r--src/render/texture/gltexture.cpp12
-rw-r--r--src/render/texture/texture.cpp10
-rw-r--r--src/render/texture/texture_p.h1
33 files changed, 702 insertions, 388 deletions
diff --git a/src/render/backend/platformsurfacefilter.cpp b/src/render/backend/platformsurfacefilter.cpp
index 891e30c44..7458f607d 100644
--- a/src/render/backend/platformsurfacefilter.cpp
+++ b/src/render/backend/platformsurfacefilter.cpp
@@ -107,6 +107,10 @@ bool PlatformSurfaceFilter::eventFilter(QObject *obj, QEvent *e)
// If we remove it, the call to isSurfaceValid will
// implicitely return false
PlatformSurfaceFilter::m_surfacesValidity.remove(m_surface);
+ if (m_obj) {
+ m_obj->removeEventFilter(this);
+ m_obj = nullptr;
+ }
break;
}
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index 0fda6e5b4..bd8687d5e 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -86,6 +86,7 @@
#include <Qt3DRender/private/updatelevelofdetailjob_p.h>
#include <Qt3DRender/private/buffercapture_p.h>
#include <Qt3DRender/private/offscreensurfacehelper_p.h>
+#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/qt3dcore-config.h>
@@ -535,17 +536,26 @@ void Renderer::render()
void Renderer::doRender()
{
- bool submissionSucceeded = false;
- bool hasCleanedQueueAndProceeded = false;
Renderer::ViewSubmissionResultData submissionData;
+ bool hasCleanedQueueAndProceeded = false;
bool preprocessingComplete = false;
-
- if (isReadyToSubmit()) {
-
- // Lock the mutex to protect access to m_surface and check if we are still set
- // to the running state and that we have a valid surface on which to draw
- // TO DO: Is that still needed given the surface changes
- QMutexLocker locker(&m_mutex);
+ bool beganDrawing = false;
+ const bool canSubmit = isReadyToSubmit();
+
+ // Lock the mutex to protect access to the renderQueue while we look for its state
+ QMutexLocker locker(&m_renderQueueMutex);
+ const bool queueIsComplete = m_renderQueue->isFrameQueueComplete();
+ const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0;
+
+ // When using synchronous rendering (QtQuick)
+ // We are not sure that the frame queue is actually complete
+ // Since a call to render may not be synched with the completions
+ // of the RenderViewJobs
+ // In such a case we return early, waiting for a next call with
+ // the frame queue complete at this point
+
+ // RenderQueue is complete (but that means it may be of size 0)
+ if (canSubmit && (queueIsComplete && !queueIsEmpty)) {
const QVector<Render::RenderView *> renderViews = m_renderQueue->nextFrameQueue();
#ifdef QT3D_JOBS_RUN_STATS
@@ -560,8 +570,7 @@ void Renderer::doRender()
submissionStatsPart2.jobId.typeAndInstance[1] = 0;
submissionStatsPart2.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
#endif
-
- if (canRender() && (submissionSucceeded = renderViews.size() > 0) == true) {
+ if (canRender()) {
// Clear all dirty flags but Compute so that
// we still render every frame when a compute shader is used in a scene
BackendNodeDirtySet changesToUnset = m_changeSet;
@@ -583,7 +592,8 @@ void Renderer::doRender()
// Reset state for each draw if we don't have complete control of the context
if (!m_ownedContext)
m_graphicsContext->setCurrentStateSet(nullptr);
- if (m_graphicsContext->beginDrawing(surface)) {
+ beganDrawing = m_graphicsContext->beginDrawing(surface);
+ if (beganDrawing) {
// 1) Execute commands for buffer uploads, texture updates, shader loading first
updateGLResources();
// 2) Update VAO and copy data into commands to allow concurrent submission
@@ -594,6 +604,7 @@ void Renderer::doRender()
}
// 2) Proceed to next frame and start preparing frame n + 1
m_renderQueue->reset();
+ locker.unlock(); // Done protecting RenderQueue
m_vsyncFrameAdvanceService->proceedToNextFrame();
hasCleanedQueueAndProceeded = true;
@@ -637,61 +648,57 @@ void Renderer::doRender()
#endif
}
- // Note: submissionSucceeded is false when
- // * we cannot render because a shutdown has been scheduled
- // * the renderqueue is incomplete (only when rendering with a Scene3D)
- // Otherwise returns true even for cases like
- // * No render view
- // * No surface set
- // * OpenGLContext failed to be set current
- // This behavior is important as we need to
- // call proceedToNextFrame despite rendering errors that aren't fatal
-
// Only reset renderQueue and proceed to next frame if the submission
- // succeeded or it we are using a render thread and that is wasn't performed
+ // succeeded or if we are using a render thread and that is wasn't performed
// already
- // If submissionSucceeded isn't true this implies that something went wrong
+ // If hasCleanedQueueAndProceeded isn't true this implies that something went wrong
// with the rendering and/or the renderqueue is incomplete from some reason
// (in the case of scene3d the render jobs may be taking too long ....)
- if (m_renderThread || submissionSucceeded) {
-
- if (!hasCleanedQueueAndProceeded) {
- // Reset the m_renderQueue so that we won't try to render
- // with a queue used by a previous frame with corrupted content
- // if the current queue was correctly submitted
- m_renderQueue->reset();
-
- // We allow the RenderTickClock service to proceed to the next frame
- // In turn this will allow the aspect manager to request a new set of jobs
- // to be performed for each aspect
- m_vsyncFrameAdvanceService->proceedToNextFrame();
- }
+ // or alternatively it could be complete but empty (RenderQueue of size 0)
+ if (!hasCleanedQueueAndProceeded &&
+ (m_renderThread || queueIsComplete || queueIsEmpty)) {
+ // RenderQueue was full but something bad happened when
+ // trying to render it and therefore proceedToNextFrame was not called
+ // Note: in this case the renderQueue mutex is still locked
+
+ // Reset the m_renderQueue so that we won't try to render
+ // with a queue used by a previous frame with corrupted content
+ // if the current queue was correctly submitted
+ m_renderQueue->reset();
+
+ // We allow the RenderTickClock service to proceed to the next frame
+ // In turn this will allow the aspect manager to request a new set of jobs
+ // to be performed for each aspect
+ m_vsyncFrameAdvanceService->proceedToNextFrame();
+ }
- // Perform the last swapBuffers calls after the proceedToNextFrame
- // as this allows us to gain a bit of time for the preparation of the
- // next frame
+ // Perform the last swapBuffers calls after the proceedToNextFrame
+ // as this allows us to gain a bit of time for the preparation of the
+ // next frame
+ // Finish up with last surface used in the list of RenderViews
+ if (beganDrawing) {
+ SurfaceLocker surfaceLock(submissionData.surface);
// Finish up with last surface used in the list of RenderViews
- if (submissionSucceeded) {
- SurfaceLocker surfaceLock(submissionData.surface);
- // Finish up with last surface used in the list of RenderViews
- m_graphicsContext->endDrawing(submissionData.lastBoundFBOId == m_graphicsContext->defaultFBO() && surfaceLock.isSurfaceValid());
- }
+ m_graphicsContext->endDrawing(submissionData.lastBoundFBOId == m_graphicsContext->defaultFBO() && surfaceLock.isSurfaceValid());
}
}
// Called by RenderViewJobs
+// When the frameQueue is complete and we are using a renderThread
+// we allow the render thread to proceed
void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder)
{
- QMutexLocker locker(&m_mutex); // Prevent out of order execution
+ QMutexLocker locker(&m_renderQueueMutex); // Prevent out of order execution
// We cannot use a lock free primitive here because:
// - QVector is not thread safe
// - Even if the insert is made correctly, the isFrameComplete call
// could be invalid since depending on the order of execution
// the counter could be complete but the renderview not yet added to the
// buffer depending on whichever order the cpu decides to process this
-
- if (m_renderQueue->queueRenderView(renderView, submitOrder)) {
+ const bool isQueueComplete = m_renderQueue->queueRenderView(renderView, submitOrder);
+ locker.unlock(); // We're done protecting the queue at this point
+ if (isQueueComplete) {
if (m_renderThread && m_running.load())
Q_ASSERT(m_submitRenderViewsSemaphore.available() == 0);
m_submitRenderViewsSemaphore.release(1);
@@ -730,16 +737,6 @@ bool Renderer::isReadyToSubmit()
// something to render
// The case of shutdown should have been handled just before
Q_ASSERT(m_renderQueue->isFrameQueueComplete());
- } else {
- // When using synchronous rendering (QtQuick)
- // We are not sure that the frame queue is actually complete
- // Since a call to render may not be synched with the completions
- // of the RenderViewJobs
- // In such a case we return early, waiting for a next call with
- // the frame queue complete at this point
- QMutexLocker locker(&m_mutex);
- if (!m_renderQueue->isFrameQueueComplete())
- return false;
}
return true;
}
@@ -1016,12 +1013,11 @@ 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
// Forces creation if it doesn't exit
if (!m_graphicsContext->hasGLBufferForBuffer(buffer))
m_graphicsContext->glBufferForRenderBuffer(buffer);
- else if (buffer->isDirty()) // Otherwise update the glBuffer
- m_graphicsContext->updateBuffer(buffer);
+ // Update the glBuffer data
+ m_graphicsContext->updateBuffer(buffer);
buffer->unsetDirty();
}
}
@@ -1061,6 +1057,11 @@ void Renderer::updateGLResources()
// Render Thread
void Renderer::updateTexture(Texture *texture)
{
+ // Check that the current texture images are still in place, if not, do not update
+ const bool isValid = texture->isValid();
+ if (!isValid)
+ return;
+
// For implementing unique, non-shared, non-cached textures.
// for now, every texture is shared by default
@@ -1425,16 +1426,25 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
renderBinJobs.push_back(m_textureGathererJob);
renderBinJobs.push_back(m_shaderGathererJob);
- // 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);
+ QMutexLocker lock(&m_renderQueueMutex);
+ if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case)
+ // 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(m_nodesManager->frameGraphManager());
+ const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot());
+
+ const int fgBranchCount = fgLeaves.size();
+ for (int i = 0; i < fgBranchCount; ++i) {
+ RenderViewBuilder builder(fgLeaves.at(i), i, this);
+ renderBinJobs.append(builder.buildJobHierachy());
+ }
- // Set target number of RenderViews
- m_renderQueue->setTargetRenderViewCount(visitor.leafNodeCount());
+ // Set target number of RenderViews
+ m_renderQueue->setTargetRenderViewCount(fgBranchCount);
+ }
return renderBinJobs;
}
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index 9df24ef2c..af10108e9 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -259,7 +259,7 @@ public:
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
- QMutex* mutex() { return &m_mutex; }
+ QMutex* mutex() { return &m_renderQueueMutex; }
#ifdef QT3D_RENDER_UNIT_TESTS
@@ -290,7 +290,7 @@ private:
QScopedPointer<RenderThread> m_renderThread;
QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService;
- QMutex m_mutex;
+ QMutex m_renderQueueMutex;
QSemaphore m_submitRenderViewsSemaphore;
QSemaphore m_waitForInitializationToBeCompleted;
diff --git a/src/render/backend/renderqueue.cpp b/src/render/backend/renderqueue.cpp
index 6ec7da464..2fa1cb7d2 100644
--- a/src/render/backend/renderqueue.cpp
+++ b/src/render/backend/renderqueue.cpp
@@ -49,6 +49,7 @@ namespace Render {
RenderQueue::RenderQueue()
: m_noRender(false)
+ , m_wasReset(true)
, m_targetRenderViewCount(0)
, m_currentRenderViewCount(0)
, m_currentWorkQueue(1)
@@ -70,6 +71,7 @@ void RenderQueue::reset()
m_targetRenderViewCount = 0;
m_currentWorkQueue.clear();
m_noRender = false;
+ m_wasReset = true;
}
void RenderQueue::setNoRender()
@@ -88,6 +90,7 @@ bool RenderQueue::queueRenderView(RenderView *renderView, uint submissionOrderIn
Q_ASSERT(!m_noRender);
m_currentWorkQueue[submissionOrderIndex] = renderView;
++m_currentRenderViewCount;
+ Q_ASSERT(m_currentRenderViewCount <= m_targetRenderViewCount);
return isFrameQueueComplete();
}
@@ -109,6 +112,7 @@ void RenderQueue::setTargetRenderViewCount(int targetRenderViewCount)
Q_ASSERT(!m_noRender);
m_targetRenderViewCount = targetRenderViewCount;
m_currentWorkQueue.resize(targetRenderViewCount);
+ m_wasReset = false;
}
/*!
@@ -119,7 +123,7 @@ void RenderQueue::setTargetRenderViewCount(int targetRenderViewCount)
bool RenderQueue::isFrameQueueComplete() const
{
return (m_noRender
- || (m_targetRenderViewCount && m_targetRenderViewCount == currentRenderViewCount()));
+ || (m_targetRenderViewCount > 0 && m_targetRenderViewCount == m_currentRenderViewCount));
}
} // namespace Render
diff --git a/src/render/backend/renderqueue_p.h b/src/render/backend/renderqueue_p.h
index 49316049b..611f5849a 100644
--- a/src/render/backend/renderqueue_p.h
+++ b/src/render/backend/renderqueue_p.h
@@ -77,9 +77,13 @@ public:
void reset();
void setNoRender();
+ inline bool isNoRender() const { return m_noRender; }
+
+ inline bool wasReset() const { return m_wasReset; }
private:
bool m_noRender;
+ bool m_wasReset;
int m_targetRenderViewCount;
int m_currentRenderViewCount;
QVector<RenderView *> m_currentWorkQueue;
diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp
index f1355d27e..f47c6f419 100644
--- a/src/render/backend/renderviewbuilder.cpp
+++ b/src/render/backend/renderviewbuilder.cpp
@@ -66,14 +66,14 @@ public:
RenderView *rv = m_renderViewJob->renderView();
int totalCommandCount = 0;
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
totalCommandCount += renderViewCommandBuilder->commands().size();
QVector<RenderCommand *> commands;
commands.reserve(totalCommandCount);
// Reduction
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
commands += std::move(renderViewCommandBuilder->commands());
rv->setCommands(commands);
@@ -139,13 +139,13 @@ public:
m_filterEntityByLayerJob->setLayers(rv->layerFilter());
// Material Parameter building
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs)) {
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
materialGatherer->setRenderPassFilter(const_cast<RenderPassFilter *>(rv->renderPassFilter()));
materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter()));
}
// Command builders
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
renderViewCommandBuilder->setRenderView(rv);
// Set whether frustum culling is enabled or not
@@ -188,8 +188,6 @@ public:
RenderView *rv = m_renderViewJob->renderView();
if (!rv->noDraw()) {
- // Set the light sources
- rv->setLightSources(std::move(m_lightGathererJob->lights()));
rv->setEnvironmentLight(m_lightGathererJob->takeEnvironmentLight());
// We sort the vector so that the removal can then be performed linearly
@@ -208,6 +206,14 @@ public:
QVector<Entity *> filteredEntities = m_filterEntityByLayerJob->filteredEntities();
RenderViewBuilder::removeEntitiesNotInSubset(renderableEntities, filteredEntities);
+ // Set the light sources, with layer filters applied.
+ QVector<LightSource> lightSources = m_lightGathererJob->lights();
+ for (int i = 0; i < lightSources.count(); ++i) {
+ if (!filteredEntities.contains(lightSources[i].entity))
+ lightSources.removeAt(i--);
+ }
+ rv->setLightSources(lightSources);
+
// Filter out frustum culled entity for drawable entities
if (isDraw && rv->frustumCulling())
RenderViewBuilder::removeEntitiesNotInSubset(renderableEntities, m_frustumCullingJob->visibleEntities());
@@ -225,7 +231,7 @@ public:
// Reduction
QHash<Qt3DCore::QNodeId, QVector<RenderPassParameterData>> params;
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs))
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs))
params.unite(materialGatherer->materialToPassAndParameter());
// Set all required data on the RenderView for final processing
rv->setMaterialParameterTable(std::move(params));
@@ -425,7 +431,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob());
m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob);
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs)) {
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
materialGatherer->addDependency(m_syncRenderViewInitializationJob);
materialGatherer->addDependency(m_renderer->filterCompatibleTechniqueJob());
m_syncRenderCommandBuildingJob->addDependency(materialGatherer);
@@ -436,7 +442,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
m_syncRenderCommandBuildingJob->addDependency(m_lightGathererJob);
m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob);
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) {
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) {
renderViewCommandBuilder->addDependency(m_syncRenderCommandBuildingJob);
m_syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder);
}
@@ -458,13 +464,13 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
jobs.push_back(m_filterEntityByLayerJob); // Step 3
jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs)) // Step3
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) // Step3
jobs.push_back(materialGatherer);
jobs.push_back(m_frustumCullingJob); // Step 4
jobs.push_back(m_syncRenderCommandBuildingJob); // Step 4
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 5
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 5
jobs.push_back(renderViewCommandBuilder);
jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 6
diff --git a/src/render/framegraph/framegraphvisitor.cpp b/src/render/framegraph/framegraphvisitor.cpp
index d31e9cddd..cd8b08219 100644
--- a/src/render/framegraph/framegraphvisitor.cpp
+++ b/src/render/framegraph/framegraphvisitor.cpp
@@ -43,7 +43,6 @@
#include "framegraphnode_p.h"
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <QThreadPool>
QT_BEGIN_NAMESPACE
@@ -53,24 +52,16 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
-FrameGraphVisitor::FrameGraphVisitor(Renderer *renderer,
- const FrameGraphManager *manager)
- : m_renderer(renderer)
- , m_manager(manager)
- , m_jobs(nullptr)
- , m_renderviewIndex(0)
-
+FrameGraphVisitor::FrameGraphVisitor(const FrameGraphManager *manager)
+ : m_manager(manager)
{
+ m_leaves.reserve(8);
}
-void FrameGraphVisitor::traverse(FrameGraphNode *root,
- QVector<Qt3DCore::QAspectJobPtr> *jobs)
+QVector<FrameGraphNode *> FrameGraphVisitor::traverse(FrameGraphNode *root)
{
- m_jobs = jobs;
- m_renderviewIndex = 0;
+ m_leaves.clear();
- Q_ASSERT(m_renderer);
- Q_ASSERT(m_jobs);
Q_ASSERT_X(root, Q_FUNC_INFO, "The FrameGraphRoot is null");
// Kick off the traversal
@@ -78,6 +69,7 @@ void FrameGraphVisitor::traverse(FrameGraphNode *root,
if (node == nullptr)
qCritical() << Q_FUNC_INFO << "FrameGraph is null";
visit(node);
+ return m_leaves;
}
void FrameGraphVisitor::visit(Render::FrameGraphNode *node)
@@ -97,10 +89,8 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node)
// Leaf node - create a RenderView ready to be populated
// TODO: Pass in only framegraph config that has changed from previous
// index RenderViewJob.
- if (fgChildIds.empty()) {
- RenderViewBuilder builder(node, m_renderviewIndex++, m_renderer);
- m_jobs->append(builder.buildJobHierachy());
- }
+ if (fgChildIds.empty())
+ m_leaves.push_back(node);
}
} // namespace Render
diff --git a/src/render/framegraph/framegraphvisitor_p.h b/src/render/framegraph/framegraphvisitor_p.h
index af8f4caab..f4c0d7796 100644
--- a/src/render/framegraph/framegraphvisitor_p.h
+++ b/src/render/framegraph/framegraphvisitor_p.h
@@ -66,24 +66,18 @@ class FrameGraphNode;
class Renderer;
class FrameGraphManager;
-class FrameGraphVisitor
+class Q_AUTOTEST_EXPORT FrameGraphVisitor
{
public:
- explicit FrameGraphVisitor(Renderer *renderer,
- const FrameGraphManager *nodeManager);
+ explicit FrameGraphVisitor(const FrameGraphManager *nodeManager);
- void traverse(FrameGraphNode *root,
- QVector<Qt3DCore::QAspectJobPtr> *jobs);
-
- inline int leafNodeCount() Q_DECL_NOTHROW { return m_renderviewIndex; }
+ QVector<FrameGraphNode *> traverse(FrameGraphNode *root);
private:
void visit(Render::FrameGraphNode *node);
- Renderer *m_renderer;
const FrameGraphManager *m_manager;
- QVector<Qt3DCore::QAspectJobPtr> *m_jobs;
- int m_renderviewIndex;
+ QVector<FrameGraphNode *> m_leaves;
};
} // namespace Render
diff --git a/src/render/framegraph/qsortcriterion.cpp b/src/render/framegraph/qsortcriterion.cpp
deleted file mode 100644
index f5252b1f7..000000000
--- a/src/render/framegraph/qsortcriterion.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsortcriterion.h"
-#include "qsortcriterion_p.h"
-#include <Qt3DCore/qnodepropertychange.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-
-QSortCriterionPrivate::QSortCriterionPrivate()
- : QNodePrivate()
- , m_sort(QSortCriterion::StateChangeCost)
-{
-}
-
-QSortCriterion::QSortCriterion(QNode *parent)
- : QNode(*new QSortCriterionPrivate, parent)
-{
-}
-
-QSortCriterion::SortType QSortCriterion::sort() const
-{
- Q_D(const QSortCriterion);
- return d->m_sort;
-}
-
-void QSortCriterion::setSort(QSortCriterion::SortType sort)
-{
- Q_D(QSortCriterion);
- if (d->m_sort != sort) {
- d->m_sort = sort;
- emit sortChanged(sort);
- }
-}
-
-/*! \internal */
-QSortCriterion::QSortCriterion(QSortCriterionPrivate &dd, QNode *parent)
- : QNode(dd, parent)
-{
-}
-
-} // namespace Qt3DRender
-
-QT_END_NAMESPACE
diff --git a/src/render/framegraph/qsortcriterion.h b/src/render/framegraph/qsortcriterion.h
deleted file mode 100644
index 230f111f9..000000000
--- a/src/render/framegraph/qsortcriterion.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QT3DRENDER_QSORTCRITERION_H
-#define QT3DRENDER_QSORTCRITERION_H
-
-#include <Qt3DCore/qnode.h>
-#include <Qt3DRender/qt3drender_global.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-
-class QSortCriterionPrivate;
-
-class QT3DRENDERSHARED_EXPORT QSortCriterion : public Qt3DCore::QNode
-{
- Q_OBJECT
- Q_PROPERTY(Qt3DRender::QSortCriterion::SortType sort READ sort WRITE setSort NOTIFY sortChanged)
-public:
- explicit QSortCriterion(Qt3DCore::QNode *parent = Q_NULLPTR);
-
- enum SortType {
- StateChangeCost = (1 << 0),
- BackToFront = (1 << 1),
- Material = (1 << 2)
- };
- Q_ENUM(SortType) // LCOV_EXCL_LINE
-
- SortType sort() const;
-
-public Q_SLOTS:
- void setSort(SortType sort);
-
-Q_SIGNALS:
- void sortChanged(SortType sort);
-
-protected:
- QSortCriterion(QSortCriterionPrivate &dd, Qt3DCore::QNode *parent = Q_NULLPTR);
-
-private:
- Q_DECLARE_PRIVATE(QSortCriterion)
-};
-
-} // namespace Qt3DRender
-
-QT_END_NAMESPACE
-
-#endif // QSORTCRITERION_H
diff --git a/src/render/framegraph/rendercapture.cpp b/src/render/framegraph/rendercapture.cpp
index 1d3117c0d..dea1cf565 100644
--- a/src/render/framegraph/rendercapture.cpp
+++ b/src/render/framegraph/rendercapture.cpp
@@ -92,7 +92,7 @@ void RenderCapture::sendRenderCaptures()
{
QMutexLocker lock(&m_mutex);
- for (const RenderCaptureDataPtr data : qAsConst(m_renderCaptureData)) {
+ for (const RenderCaptureDataPtr &data : qAsConst(m_renderCaptureData)) {
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("renderCaptureData");
diff --git a/src/render/framegraph/viewportnode.cpp b/src/render/framegraph/viewportnode.cpp
index c16a660b0..b68f7b55b 100644
--- a/src/render/framegraph/viewportnode.cpp
+++ b/src/render/framegraph/viewportnode.cpp
@@ -123,7 +123,7 @@ void ViewportNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
if (e->type() == PropertyUpdated) {
QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
if (propertyChange->propertyName() == QByteArrayLiteral("normalizedRect")) {
- QRectF normalizedRect = propertyChange->value().value<QRectF>();
+ QRectF normalizedRect = propertyChange->value().toRectF();
setXMin(normalizedRect.x());
setYMin(normalizedRect.y());
setXMax(normalizedRect.width());
diff --git a/src/render/frontend/qabstractfunctor.h b/src/render/frontend/qabstractfunctor.h
index c05c04743..95f6aee51 100644
--- a/src/render/frontend/qabstractfunctor.h
+++ b/src/render/frontend/qabstractfunctor.h
@@ -80,6 +80,14 @@ public:
virtual ~QAbstractFunctor();
virtual qintptr id() const = 0;
+ // TODO: Remove when moving a copy of this to Qt3DCore
+ template<class T>
+ const T *functor_cast(const QAbstractFunctor *other) const
+ {
+ if (other->id() == functorTypeId<T>())
+ return static_cast<const T *>(other);
+ return nullptr;
+ }
private:
Q_DISABLE_COPY(QAbstractFunctor)
};
diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp
index df169876e..03df4e6a8 100644
--- a/src/render/frontend/qlevelofdetail.cpp
+++ b/src/render/frontend/qlevelofdetail.cpp
@@ -77,7 +77,7 @@ QLevelOfDetailPrivate::QLevelOfDetailPrivate()
The currentIndex property can then be used, for example, to enable or
disable entities, change material, etc.
- The LevelOfDetail component is not shareable between multiple Entity's.
+ The LevelOfDetail component is not shareable between multiple \l [QML]{Entity}{entities}.
\code
#include <Qt3DCore/QEntity>
@@ -185,35 +185,6 @@ QLevelOfDetailPrivate::QLevelOfDetailPrivate()
* \sa Qt3DRender::QLevelOfDetail::ThresholdType
*/
-
-/*!
- * \enum Qt3DRender::QLevelOfDetail::SizeProxyMode
- *
- * Specifies what is used as a proxy for the entity when computing distance
- * or size.
- *
- * \value LevelOfDetailBoundingSphere use the bounding sphere specified by the center
- * and radius properties.
- * \value Children LevelOfDetailBoundingSphere use the bounding sphere of the entity the
- * component is attached to.
- */
-
-/*!
- * \qmlproperty enumeration LevelOfDetail::SizeProxyMode
- *
- * Specifies what is used as a proxy for the entity when computing distance
- * or size.
- *
- * \list
- * \li LevelOfDetailBoundingSphere use the bounding sphere specified by the center
- * and radius properties.
- * \li Children LevelOfDetailBoundingSphere use the bounding sphere of the entity the
- * component is attached to.
- * \endlist
- * \sa Qt3DRender::QLevelOfDetail::SizeProxyMode
- */
-
-
/*!
* \qmlproperty Camera LevelOfDetail::camera
*
@@ -442,7 +413,7 @@ void QLevelOfDetail::setThresholds(const QVector<qreal> &thresholds)
Q_D(QLevelOfDetail);
if (d->m_thresholds != thresholds) {
d->m_thresholds = thresholds;
- thresholdsChanged(d->m_thresholds);
+ emit thresholdsChanged(d->m_thresholds);
}
}
diff --git a/src/render/frontend/qlevelofdetailswitch.cpp b/src/render/frontend/qlevelofdetailswitch.cpp
index a6d2b1530..845fdd5a6 100644
--- a/src/render/frontend/qlevelofdetailswitch.cpp
+++ b/src/render/frontend/qlevelofdetailswitch.cpp
@@ -69,11 +69,17 @@ namespace Qt3DRender {
This component is assigned to an entity. When the entity changes distance relative
to the camera, the LevelOfDetailSwitch will disable all the child entities except
- the one matching index \l LevelOfDetailSwitch::currentIndex.
+ the one matching index \l currentIndex.
\sa LevelOfDetail
*/
+/*!
+ \qmlproperty int LevelOfDetailSwitch::currentIndex
+
+ The index of the presently selected child entity.
+*/
+
/*! \fn Qt3DRender::QLevelOfDetailSwitch::QLevelOfDetailSwitch(Qt3DCore::QNode *parent)
Constructs a new QLevelOfDetailSwitch with the specified \a parent.
*/
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index e962f3700..11c03e7db 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -267,7 +267,7 @@ void QRenderAspectPrivate::registerBackendTypes()
q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer));
// Plugins
- for (QString plugin : m_pluginConfig)
+ for (const QString &plugin : m_pluginConfig)
loadRenderPlugin(plugin);
}
@@ -608,7 +608,7 @@ void QRenderAspectPrivate::configurePlugin(const QString &plugin)
if (!m_pluginConfig.contains(plugin)) {
m_pluginConfig.append(plugin);
- for (QRenderAspectPrivate *instance : m_instances)
+ for (QRenderAspectPrivate *instance : qAsConst(m_instances))
instance->loadRenderPlugin(plugin);
}
}
diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp
index 7e1ea79dd..6c8c0113a 100644
--- a/src/render/geometry/attribute.cpp
+++ b/src/render/geometry/attribute.cpp
@@ -108,7 +108,7 @@ void Attribute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
QByteArray propertyName = propertyChange->propertyName();
if (propertyName == QByteArrayLiteral("name")) {
- m_name = propertyChange->value().value<QString>();
+ m_name = propertyChange->value().toString();
m_nameId = StringToInt::lookupId(m_name);
m_attributeDirty = true;
} else if (propertyName == QByteArrayLiteral("vertexBaseType")) {
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index 1133b8e5e..55c86910f 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -88,6 +88,9 @@ void Buffer::executeFunctor()
{
Q_ASSERT(m_functor);
m_data = (*m_functor)();
+ // Request data to be loaded
+ forceDataUpload();
+
if (m_syncData) {
// Send data back to the frontend
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
@@ -101,6 +104,8 @@ void Buffer::executeFunctor()
//Called from th sendBufferJob
void Buffer::updateDataFromGPUToCPU(QByteArray data)
{
+ // Note: when this is called, data is what's currently in GPU memory
+ // so m_data shouldn't be reuploaded
m_data = data;
// Send data back to the frontend
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
@@ -121,21 +126,37 @@ void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang
m_access = data.access;
m_bufferDirty = true;
+ if (!m_data.isEmpty())
+ forceDataUpload();
+
m_functor = data.functor;
Q_ASSERT(m_manager);
if (m_functor)
m_manager->addDirtyBuffer(peerId());
}
+void Buffer::forceDataUpload()
+{
+ // We push back an update with offset = -1
+ // As this is the way to force data to be loaded
+ QBufferUpdate updateNewData;
+ updateNewData.offset = -1;
+ m_bufferUpdates.clear(); //previous updates are pointless
+ m_bufferUpdates.push_back(updateNewData);
+}
+
void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == PropertyUpdated) {
QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
QByteArray propertyName = propertyChange->propertyName();
if (propertyName == QByteArrayLiteral("data")) {
- QByteArray newData = propertyChange->value().value<QByteArray>();
- m_bufferDirty |= m_data != newData;
+ QByteArray newData = propertyChange->value().toByteArray();
+ bool dirty = m_data != newData;
+ m_bufferDirty |= dirty;
m_data = newData;
+ if (dirty)
+ forceDataUpload();
} else if (propertyName == QByteArrayLiteral("updateData")) {
Qt3DRender::QBufferUpdate updateData = propertyChange->value().value<Qt3DRender::QBufferUpdate>();
m_bufferUpdates.push_back(updateData);
diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h
index 9d9606eb0..691d6cc60 100644
--- a/src/render/geometry/buffer_p.h
+++ b/src/render/geometry/buffer_p.h
@@ -90,6 +90,7 @@ public:
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+ void forceDataUpload();
QBuffer::BufferType m_type;
QBuffer::UsageType m_usage;
diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp
index 54fe61831..4f5432e1d 100644
--- a/src/render/geometry/geometryrenderer.cpp
+++ b/src/render/geometry/geometryrenderer.cpp
@@ -153,7 +153,7 @@ void GeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
m_verticesPerPatch = propertyChange->value().value<int>();
m_dirty = true;
} else if (propertyName == QByteArrayLiteral("primitiveRestartEnabled")) {
- m_primitiveRestartEnabled = propertyChange->value().value<bool>();
+ m_primitiveRestartEnabled = propertyChange->value().toBool();
m_dirty = true;
} else if (propertyName == QByteArrayLiteral("primitiveType")) {
m_primitiveType = static_cast<QGeometryRenderer::PrimitiveType>(propertyChange->value().value<int>());
diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp
index 6fa081552..80e8267da 100644
--- a/src/render/graphicshelpers/graphicscontext.cpp
+++ b/src/render/graphicshelpers/graphicscontext.cpp
@@ -1320,16 +1320,16 @@ void GraphicsContext::applyUniform(const ShaderUniform &description, const Unifo
break;
case UniformType::UInt:
- applyUniformHelper<UniformType::Int>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UInt>(description.m_location, description.m_size, v);
break;
case UniformType::UIVec2:
- applyUniformHelper<UniformType::IVec2>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UIVec2>(description.m_location, description.m_size, v);
break;
case UniformType::UIVec3:
- applyUniformHelper<UniformType::IVec3>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UIVec3>(description.m_location, description.m_size, v);
break;
case UniformType::UIVec4:
- applyUniformHelper<UniformType::IVec4>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UIVec4>(description.m_location, description.m_size, v);
break;
case UniformType::Bool:
@@ -1501,8 +1501,6 @@ HGLBuffer GraphicsContext::createGLBufferFor(Buffer *buffer)
if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type())))
qCWarning(Render::Io) << Q_FUNC_INFO << "buffer binding failed";
- // TO DO: Handle usage pattern
- b->allocate(this, buffer->data().constData(), buffer->data().size(), false);
return m_renderer->nodeManagers()->glBufferManager()->lookupHandle(buffer->peerId());
}
@@ -1528,21 +1526,39 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel
// * setData was called changing the whole data or functor (or the usage pattern)
// * partial buffer updates where received
- // Note: we assume the case where both setData/functor and updates are called to be a misuse
- // with unexpected behavior
- const QVector<Qt3DRender::QBufferUpdate> updates = std::move(buffer->pendingBufferUpdates());
- if (!updates.empty()) {
- for (const Qt3DRender::QBufferUpdate &update : updates) {
+ // TO DO: Handle usage pattern
+ QVector<Qt3DRender::QBufferUpdate> updates = std::move(buffer->pendingBufferUpdates());
+ for (auto it = updates.begin(); it != updates.end(); ++it) {
+ auto update = it;
+ // We have a partial update
+ if (update->offset >= 0) {
+ //accumulate sequential updates as single one
+ int bufferSize = update->data.size();
+ auto it2 = it + 1;
+ while ((it2 != updates.end())
+ && (it2->offset - update->offset == bufferSize)) {
+ bufferSize += it2->data.size();
+ ++it2;
+ }
+ update->data.resize(bufferSize);
+ while (it + 1 != it2) {
+ ++it;
+ update->data.replace(it->offset - update->offset, it->data.size(), it->data);
+ it->data.clear();
+ }
// TO DO: based on the number of updates .., it might make sense to
// sometime use glMapBuffer rather than glBufferSubData
- b->update(this, update.data.constData(), update.data.size(), update.offset);
+ b->update(this, update->data.constData(), update->data.size(), update->offset);
+ } else {
+ // We have an update that was done by calling QBuffer::setData
+ // which is used to resize or entirely clear the buffer
+ // Note: we use the buffer data directly in that case
+ const int bufferSize = buffer->data().size();
+ b->allocate(this, bufferSize, false); // orphan the buffer
+ b->allocate(this, buffer->data().constData(), bufferSize, false);
}
- } else {
- const int bufferSize = buffer->data().size();
- // TO DO: Handle usage pattern
- b->allocate(this, bufferSize, false); // orphan the buffer
- b->allocate(this, buffer->data().constData(), bufferSize, false);
}
+
if (releaseBuffer) {
b->release(this);
if (bufferTypeToGLBufferType(buffer->type()) == GLBuffer::ArrayBuffer)
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index 7bd45587c..f9c7a390c 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -371,14 +371,14 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
}
break;
}
-
+#if QT_CONFIG(gestures)
case Qt::TapGesture: {
objectPicker->onClicked(pickEvent);
break;
}
-
+#endif
case QEvent::MouseMove: {
- if (objectPicker->isPressed() && objectPicker->isDragEnabled()) {
+ if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) {
objectPicker->onMoved(pickEvent);
}
// fallthrough
diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp
index 7778b5621..b611657c4 100644
--- a/src/render/materialsystem/qeffect.cpp
+++ b/src/render/materialsystem/qeffect.cpp
@@ -67,6 +67,35 @@ QEffectPrivate::QEffectPrivate()
The QEffect class combines a set of techniques and parameters used by those techniques to
produce a rendering effect for a material.
+ An QEffect instance should be shared among several QMaterial instances when possible.
+
+ \code
+ QEffect *effect = new QEffect();
+
+ // Create technique, render pass and shader
+ QTechnique *gl3Technique = new QTechnique();
+ QRenderPass *gl3Pass = new QRenderPass();
+ QShaderProgram *glShader = new QShaderProgram();
+
+ // Set the shader on the render pass
+ gl3Pass->setShaderProgram(glShader);
+
+ // Add the pass to the technique
+ gl3Technique->addRenderPass(gl3Pass);
+
+ // Set the targeted GL version for the technique
+ gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ // Add the technique to the effect
+ effect->addTechnique(gl3Technique);
+ \endcode
+
+ A QParameter defined on an Effect is overridden by a QParameter (of the same
+ name) defined in a QMaterial, QTechniqueFilter, QRenderPassFilter.
+
\sa QMaterial, QTechnique, QParameter
*/
@@ -81,6 +110,37 @@ QEffectPrivate::QEffectPrivate()
The Effect type combines a set of techniques and parameters used by those techniques to
produce a rendering effect for a material.
+ An Effect instance should be shared among several Material instances when possible.
+
+ A Parameter defined on an Effect is overridden by a QParameter (of the same
+ name) defined in a Material, TechniqueFilter, RenderPassFilter.
+
+ \code
+ Effect {
+ id: effect
+
+ technique: [
+ Technique {
+ id: gl3Technique
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 3
+ minorVersion: 1
+ }
+ renderPasses: [
+ RenderPass {
+ id: gl3Pass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ }
+ ]
+ }
+ ]
+ }
+ \endcode
+
\sa Material, Technique, Parameter
*/
diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp
index ca0f86463..c6913441e 100644
--- a/src/render/materialsystem/qmaterial.cpp
+++ b/src/render/materialsystem/qmaterial.cpp
@@ -60,7 +60,58 @@
sound should reflect off an element, the temperature of a surface,
and so on.
- \sa Effect
+ In itself, a Material doesn't do anything. It's only when it references an
+ Effect node that a Material becomes useful.
+
+ In practice, it often happens that a single Effect is being referenced by
+ several Material components. This allows to only create the effect,
+ techniques, passes and shaders once while allowing to specify the material
+ by adding Parameter instances.
+
+ A Parameter defined on a Material is overridden by a Parameter (of the same
+ name) defined in a TechniqueFilter or a RenderPassFilter.
+
+ \code
+ Effect {
+ id: effect
+
+ technique: [
+ Technique {
+ id: gl3Technique
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 3
+ minorVersion: 1
+ }
+ renderPasses: [
+ RenderPass {
+ id: gl3Pass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ }
+ ]
+ }
+ ]
+ }
+
+ Material {
+ id: material1
+ parameters: [
+ Parameter { name: "color"; value: "green" }
+ ]
+ }
+
+ Material {
+ id: material2
+ parameters: [
+ Parameter { name: "color"; value: "white" }
+ ]
+ }
+ \endcode
+
+ \sa Effect, Technique, Parameter
*/
/*!
@@ -77,7 +128,54 @@
sound should reflect off an element, the temperature of a surface,
and so on.
- \sa QEffect
+ In itself, a QMaterial doesn't do anything. It's only when it references a
+ QEffect node that a QMaterial becomes useful.
+
+ In practice, it often happens that a single QEffect is being referenced by
+ several QMaterial components. This allows to only create the effect,
+ techniques, passes and shaders once while allowing to specify the material
+ by adding QParameter instances.
+
+ A QParameter defined on a QMaterial is overridden by a QParameter (of the same
+ name) defined in a QTechniqueFilter or a QRenderPassFilter.
+
+ \code
+ QMaterial *material1 = new QMaterial();
+ QMaterial *material2 = new QMaterial();
+
+ // Create effect, technique, render pass and shader
+ QEffect *effect = new QEffect();
+ QTechnique *gl3Technique = new QTechnique();
+ QRenderPass *gl3Pass = new QRenderPass();
+ QShaderProgram *glShader = new QShaderProgram();
+
+ // Set the shader on the render pass
+ gl3Pass->setShaderProgram(glShader);
+
+ // Add the pass to the technique
+ gl3Technique->addRenderPass(gl3Pass);
+
+ // Set the targeted GL version for the technique
+ gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ // Add the technique to the effect
+ effect->addTechnique(gl3Technique);
+
+ // Set the effect on the materials
+ material1->setEffect(effect);
+ material2->setEffect(effect);
+
+ // Set different parameters on the materials
+ const QString parameterName = QStringLiteral("color");
+ material1->addParameter(new QParameter(parameterName, QColor::fromRgbF(0.0f, 1.0f, 0.0f, 1.0f);
+ material2->addParameter(new QParameter(parameterName, QColor::fromRgbF(1.0f, 1.0f, 1.0f, 1.0f);
+
+ \endcode
+
+ \sa QEffect, QTechnique, QParameter
*/
QT_BEGIN_NAMESPACE
diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp
index 8f83fd02e..2ca7d176b 100644
--- a/src/render/materialsystem/qparameter.cpp
+++ b/src/render/materialsystem/qparameter.cpp
@@ -45,18 +45,127 @@
/*!
- * \qmltype Parameter
- * \instantiates Qt3DRender::QParameter
- * \inqmlmodule Qt3D.Render
- * \brief Provides storage for a name and value pair.
+ \qmltype Parameter
+ \instantiates Qt3DRender::QParameter
+ \inqmlmodule Qt3D.Render
+ \brief Provides storage for a name and value pair. This maps to a shader uniform.
+
+ A Parameter can be referenced by a RenderPass, Technique, Effect, Material,
+ TechniqueFilter, RenderPassFilter. At runtime, depending on which shader is
+ selected for a given step of the rendering, the value contained in a
+ Parameter will be converted and uploaded if the shader contains a uniform
+ with a name matching that of the Parameter.
+
+ \code
+ Parameter {
+ name: "diffuseColor"
+ value: "blue"
+ }
+
+ // Works with the following GLSL uniform shader declarations
+ // uniform vec4 diffuseColor;
+ // uniform vec3 diffuseColor;
+ // uniform vec2 diffuseColor;
+ // uniform float diffuseColor;
+ \endcode
+
+ \note some care must be taken to ensure the value wrapped by a Parameter
+ can actually be converted to what the real uniform expect. Giving a value
+ stored as an int where the actual shader uniform is of type float could
+ result in undefined behaviors.
+
+ \note when the targeted uniform is an array, the name should be the name
+ of the uniform with [0] appended to it.
+
+ \code
+ Parameter {
+ name: "diffuseValues[0]"
+ value: [0.0, 1.0. 2.0, 3.0, 4.0, 883.0, 1340.0, 1584.0]
+ }
+
+ // Matching GLSL shader uniform declaration
+ // uniform float diffuseValues[8];
+ \endcode
+
+ When it comes to texture support, the Parameter value should be set to the
+ appropriate Texture subclass that matches the sampler type of the shader
+ uniform.
+
+ \code
+ Parameter {
+ name: "diffuseTexture"
+ value: Texture2D { ... }
+ }
+
+ // Works with the following GLSL uniform shader declaration
+ // uniform sampler2D diffuseTexture
+ \endcode
+
+ \sa Texture
*/
/*!
- * \class Qt3DRender::QParameter
- * \inheaderfile Qt3DRender/QParameter
- * \inmodule Qt3DRender
- *
- * \brief Provides storage for a name and value pair.
+ \class Qt3DRender::QParameter
+ \inheaderfile Qt3DRender/QParameter
+ \inmodule Qt3DRender
+ \brief Provides storage for a name and value pair. This maps to a shader uniform.
+
+ A QParameter can be referenced by a QRenderPass, QTechnique, QEffect, QMaterial,
+ QTechniqueFilter, QRenderPassFilter. At runtime, depending on which shader is
+ selected for a given step of the rendering, the value contained in a
+ QParameter will be converted and uploaded if the shader contains a uniform
+ with a name matching that of the QParameter.
+
+ \code
+ QParameter *param = new QParameter();
+ param->setName(QStringLiteral("diffuseColor"));
+ param->setValue(QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Alternatively you can create and set a QParameter this way
+ QParameter *param2 = new QParameter(QStringLiteral("diffuseColor"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Such QParameters will work with the following GLSL uniform shader declarations
+ // uniform vec4 diffuseColor;
+ // uniform vec3 diffuseColor;
+ // uniform vec2 diffuseColor;
+ // uniform float diffuseColor;
+ \endcode
+
+ \note some care must be taken to ensure the value wrapped by a QParameter
+ can actually be converted to what the real uniform expect. Giving a value
+ stored as an int where the actual shader uniform is of type float could
+ result in undefined behaviors.
+
+ \note when the targeted uniform is an array, the name should be the name
+ of the uniform with [0] appended to it.
+
+ \code
+ QParameter *param = new QParameter();
+ QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
+
+ param->setName(QStringLiteral("diffuseValues[0]"));
+ param->setValue(values);
+
+ // Matching GLSL shader uniform declaration
+ // uniform float diffuseValues[8];
+ \endcode
+
+ When it comes to texture support, the QParameter value should be set to the
+ appropriate QAbstractTexture subclass that matches the sampler type of the shader
+ uniform.
+
+ \code
+ QTexture2D *texture = new QTexture2D();
+ ...
+ QParameter *param = new QParameter();
+ param->setName(QStringLiteral("diffuseTexture"));
+ param->setValue(QVariant::fromValue(texture));
+
+ // Works with the following GLSL uniform shader declaration
+ // uniform sampler2D diffuseTexture
+ \endcode
+
+ \sa QAbstractTexture
*/
QT_BEGIN_NAMESPACE
diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp
index 6f5949781..61f844be3 100644
--- a/src/render/materialsystem/qrenderpass.cpp
+++ b/src/render/materialsystem/qrenderpass.cpp
@@ -72,9 +72,40 @@ QRenderPassPrivate::QRenderPassPrivate()
a list of FilterKey objects, a list of RenderState objects and a list
of \l Parameter objects.
- RenderPass executes the ShaderProgram using the given render states and parameters
- when its filter keys match the filter keys in RenderPassFilter or when no filter
- keys are specified and no RenderPassFilter is present in the FrameGraph.
+ RenderPass executes the ShaderProgram using the given RenderState and
+ Parameter nodes when at least one of FilterKey nodes being referenced
+ matches any of the FilterKey nodes in RenderPassFilter or when no FilterKey
+ nodes are specified and no RenderPassFilter is present in the FrameGraph.
+
+ If the RenderPass defines a Parameter, it will be overridden by a Parameter
+ with the same name if it exists in any of the Technique, Effect, Material,
+ TechniqueFilter, RenderPassFilter associated with the pass at runtime. This
+ still can be useful to define sane default values.
+
+ At render time, for each leaf node of the FrameGraph a base render state is
+ recorded by accumulating states defined by all RenderStateSet nodes in the
+ FrameGraph branch. Each RenderPass can overload this base render state by
+ specifying its own RenderState nodes.
+
+ \code
+ RenderPass {
+ id: pass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ parameters: [
+ Parameters { name: "color"; value: "red" }
+ ]
+ filterKeys: [
+ FilterKey { name: "name"; value: "zFillPass" }
+ ]
+ renderStates: [
+ DepthTest { }
+ ]
+ }
+ \endcode
+
+ \sa RenderPassFilter, FilterKey, Parameter, RenderState, Effect, Technique
*/
/*!
@@ -88,10 +119,54 @@ QRenderPassPrivate::QRenderPassPrivate()
of a Qt3DRender::QShaderProgram and a list of Qt3DRender::QFilterKey objects,
a list of Qt3DRender::QRenderState objects and a list of Qt3DRender::QParameter objects.
- QRenderPass executes the QShaderProgram using the given render states and parameters
- when its filter keys match the filter keys in Qt3DRender::QRenderPassFilter or
- when no filter keys are specified and no QRenderPassFilter is present
- in the FrameGraph.
+ QRenderPass executes the QShaderProgram using the given QRenderState and
+ QParameter nodes when at least one of QFilterKey nodes being referenced
+ matches any of the QFilterKey nodes in QRenderPassFilter or when no
+ QFilterKey nodes are specified and no QRenderPassFilter is present in the
+ FrameGraph.
+
+ If the QRenderPass defines a QParameter, it will be overridden by a
+ QParameter with the same name if it exists in any of the QTechnique,
+ QEffect, QMaterial, QTechniqueFilter, QRenderPassFilter associated with the
+ pass at runtime. This still can be useful to define sane default values.
+
+ At render time, for each leaf node of the FrameGraph a base render state is
+ recorded by accumulating states defined by all QRenderStateSet nodes in the
+ FrameGraph branch. Each QRenderPass can overload this base render state by
+ specifying its own QRenderState nodes.
+
+ \code
+ // Create the render passes
+ QRenderPass *pass = new QRenderPass();
+
+ // Create shader program
+ QShaderProgram *glShader = new QShaderProgram();
+
+ // Set the shader on the render pass
+ pass->setShaderProgram(glShader);
+
+ // Create a FilterKey
+ QFilterKey *filterKey = new QFilterKey();
+ filterKey->setName(QStringLiteral("name"));
+ fitlerKey->setValue(QStringLiteral("zFillPass"));
+
+ // Add the FilterKey to the pass
+ pass->addFilterKey(filterKey);
+
+ // Create a QParameter
+ QParameter *colorParameter = new QParameter(QStringLiteral("color"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Add parameter to pass
+ pass->addParameter(colorParameter);
+
+ // Create a QRenderState
+ QDepthTest *depthTest = new QDepthTest();
+
+ // Add the render state to the pass
+ pass->addRenderState(depthTest);
+ \endcode
+
+ \sa QRenderPassFilter, QFilterKey, QParameter, QRenderState, QEffect, QTechnique
*/
/*!
\typedef ParameterList
diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp
index 74505bfbd..df142cdee 100644
--- a/src/render/materialsystem/qtechnique.cpp
+++ b/src/render/materialsystem/qtechnique.cpp
@@ -68,14 +68,61 @@ QTechniquePrivate::~QTechniquePrivate()
\since 5.7
\brief Encapsulates a Technique.
- A Technique specifies a set of RenderPass objects, FilterKey objects, Parameter objects
- and a GraphicsApiFilter, which together define a rendering technique the given
- graphics API can render. The filter keys are used by TechniqueFilter
- to select specific techinques at specific parts of the FrameGraph.
- If the same parameter is specified both in Technique and RenderPass, the one
- in Technique overrides the one used in the RenderPass.
-
- \sa Qt3D.Render::Effect
+ A Technique specifies a set of RenderPass objects, FilterKey objects,
+ Parameter objects and a GraphicsApiFilter, which together define a
+ rendering technique the given graphics API can render. The filter keys are
+ used by TechniqueFilter to select specific techniques at specific parts of
+ the FrameGraph. If two Parameter instances with the same name are specified
+ in a Technique and a RenderPass, the one in Technique overrides the one
+ used in the RenderPass.
+
+ When creating an Effect that targets several versions of a graphics API, it
+ is useful to create several Technique nodes each with a graphicsApiFilter
+ set to match one of the targeted versions. At runtime, the Qt3D renderer
+ will select the most appropriate Technique based on which graphics API
+ versions are supported and (if specified) the FilterKey nodes that satisfy
+ a given TechniqueFilter in the FrameGraph.
+
+ \note When using OpenGL as the graphics API for rendering, Qt3D relies on
+ the QSurfaceFormat returned by QSurfaceFormat::defaultFormat() at runtime
+ to decide what is the most appropriate GL version available. If you need to
+ customize the QSurfaceFormat, do not forget to apply it with
+ QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
+ will likely have no effect on Qt3D related rendering.
+
+ \code
+ Technique {
+ id: gl3Technique
+ parameters: [
+ Parameter { name: "color"; value: "orange" }
+ ]
+ filterKeys: [
+ FilterKey { name: "name"; value: "zFillTechnique" }
+ ]
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 3
+ minorVersion: 1
+ }
+ renderPasses: [
+ RenderPass {
+ id: firstPass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ },
+ RenderPass {
+ id: secondPass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ }
+ ]
+ }
+ \endcode
+
+ \sa Effect, RenderPass, TechniqueFilter
*/
/*!
@@ -85,15 +132,62 @@ QTechniquePrivate::~QTechniquePrivate()
\since 5.7
\brief Encapsulates a Technique.
- A Qt3DRender::QTechnique specifies a set of Qt3DRender::QRenderPass objects,
- Qt3DRender::QFilterKey objects, Qt3DRender::QParameter objects and
- a Qt3DRender::QGraphicsApiFilter, which together define a rendering technique the given
- graphics API can render. The filter keys are used by Qt3DRender::QTechniqueFilter
- to select specific techinques at specific parts of the FrameGraph.
- If the same parameter is specified both in QTechnique and QRenderPass, the one
- in QTechnique overrides the one used in the QRenderPass.
-
- \sa Qt3DRender::QEffect
+ A Qt3DRender::QTechnique specifies a set of Qt3DRender::QRenderPass
+ objects, Qt3DRender::QFilterKey objects, Qt3DRender::QParameter objects and
+ a Qt3DRender::QGraphicsApiFilter, which together define a rendering
+ technique the given graphics API can render. The filter keys are used by
+ Qt3DRender::QTechniqueFilter to select specific techniques at specific
+ parts of the FrameGraph. If two QParameter instances with the same name are
+ specified in a QTechnique and a QRenderPass, the one in Technique overrides
+ the one used in the QRenderPass.
+
+ When creating an QEffect that targets several versions of a graphics API,
+ it is useful to create several QTechnique nodes each with a
+ graphicsApiFilter set to match one of the targeted GL versions. At runtime,
+ the Qt3D renderer will select the most appropriate QTechnique based on
+ which graphics API versions are supported and (if specified) the QFilterKey
+ nodes that satisfy a given QTechniqueFilter in the FrameGraph.
+
+ \note When using OpenGL as the graphics API for rendering, Qt3D relies on
+ the QSurfaceFormat returned by QSurfaceFormat::defaultFormat() at runtime
+ to decide what is the most appropriate GL version available. If you need to
+ customize the QSurfaceFormat, do not forget to apply it with
+ QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
+ will likely have no effect on Qt3D related rendering.
+
+ \code
+ QTechnique *gl3Technique = new QTechnique();
+
+ // Create the render passes
+ QRenderPass *firstPass = new QRenderPass();
+ QRenderPass *secondPass = new QRenderPass();
+
+ // Add the passes to the technique
+ gl3Technique->addRenderPass(firstPass);
+ gl3Technique->addRenderPass(secondPass);
+
+ // Set the targeted GL version for the technique
+ gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ // Create a FilterKey
+ QFilterKey *filterKey = new QFilterKey();
+ filterKey->setName(QStringLiteral("name"));
+ fitlerKey->setValue(QStringLiteral("zFillPass"));
+
+ // Add the FilterKey to the Technique
+ gl3Technique->addFilterKey(filterKey);
+
+ // Create a QParameter
+ QParameter *colorParameter = new QParameter(QStringLiteral("color"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Add parameter to technique
+ gl3Technique->addParameter(colorParameter);
+ \endcode
+
+ \sa QEffect, QRenderPass, QTechniqueFilter
*/
/*!
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index 3ee00739d..915ca1d54 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -311,8 +311,8 @@ void Shader::updateDNA()
QMutexLocker locker(&m_mutex);
uint attachmentHash = 0;
- QHash<QString, int>::const_iterator it = m_fragOutputs.begin();
- QHash<QString, int>::const_iterator end = m_fragOutputs.end();
+ QHash<QString, int>::const_iterator it = m_fragOutputs.cbegin();
+ QHash<QString, int>::const_iterator end = m_fragOutputs.cend();
while (it != end) {
attachmentHash += ::qHash(it.value()) + ::qHash(it.key());
++it;
@@ -373,11 +373,11 @@ void Shader::initializeUniformBlocks(const QVector<ShaderUniformBlock> &uniformB
qCDebug(Shaders) << "Initializing Uniform Block {" << m_uniformBlockNames[i] << "}";
// Find all active uniforms for the shader block
- QVector<ShaderUniform>::const_iterator uniformsIt = m_uniforms.begin();
- const QVector<ShaderUniform>::const_iterator uniformsEnd = m_uniforms.end();
+ QVector<ShaderUniform>::const_iterator uniformsIt = m_uniforms.cbegin();
+ const QVector<ShaderUniform>::const_iterator uniformsEnd = m_uniforms.cend();
- QVector<QString>::const_iterator uniformNamesIt = m_uniformsNames.begin();
- const QVector<QString>::const_iterator uniformNamesEnd = m_attributesNames.end();
+ QVector<QString>::const_iterator uniformNamesIt = m_uniformsNames.cbegin();
+ const QVector<QString>::const_iterator uniformNamesEnd = m_attributesNames.cend();
QHash<QString, ShaderUniform> activeUniformsInBlock;
diff --git a/src/render/raycasting/qabstractcollisionqueryservice_p.h b/src/render/raycasting/qabstractcollisionqueryservice_p.h
index 806c33d5b..1c1261937 100644
--- a/src/render/raycasting/qabstractcollisionqueryservice_p.h
+++ b/src/render/raycasting/qabstractcollisionqueryservice_p.h
@@ -79,6 +79,7 @@ public:
class QT3DRENDERSHARED_EXPORT QAbstractCollisionQueryService : public Qt3DCore::QAbstractServiceProvider
{
+ Q_OBJECT
public:
enum QueryMode {
FirstHit,
diff --git a/src/render/texture/apitexturemanager_p.h b/src/render/texture/apitexturemanager_p.h
index c062f0971..91747b3bc 100644
--- a/src/render/texture/apitexturemanager_p.h
+++ b/src/render/texture/apitexturemanager_p.h
@@ -273,7 +273,7 @@ public:
if (impl->isUnique())
return false;
- auto it = m_sharedTextures.find(impl);
+ auto it = m_sharedTextures.constFind(impl);
if (it == m_sharedTextures.cend())
return false;
diff --git a/src/render/texture/gltexture.cpp b/src/render/texture/gltexture.cpp
index bc2a1d464..854789e94 100644
--- a/src/render/texture/gltexture.cpp
+++ b/src/render/texture/gltexture.cpp
@@ -188,13 +188,11 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture()
if (!m_gl) {
m_gl = buildGLTexture();
- if (m_gl) {
- m_gl->allocateStorage();
- if (!m_gl->isStorageAllocated()) {
- qWarning() << Q_FUNC_INFO << "texture storage allocation failed";
- return nullptr;
- }
- } else {
+ if (!m_gl)
+ return nullptr;
+ m_gl->allocateStorage();
+ if (!m_gl->isStorageAllocated()) {
+ qWarning() << Q_FUNC_INFO << "texture storage allocation failed";
return nullptr;
}
}
diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp
index a1f0d0f98..21f29d0b6 100644
--- a/src/render/texture/texture.cpp
+++ b/src/render/texture/texture.cpp
@@ -254,6 +254,16 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
BackendNode::sceneChangeEvent(e);
}
+bool Texture::isValid() const
+{
+ for (const auto handle : m_textureImages) {
+ TextureImage *img = m_textureImageManager->data(handle);
+ if (img == nullptr)
+ return false;
+ }
+ return true;
+}
+
void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractTextureData>>(change);
diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h
index 18f650686..1f3ba729c 100644
--- a/src/render/texture/texture_p.h
+++ b/src/render/texture/texture_p.h
@@ -157,6 +157,7 @@ public:
inline const QVector<HTextureImage>& textureImages() const { return m_textureImages; }
inline const QTextureGeneratorPtr& dataGenerator() const { return m_dataFunctor; }
+ bool isValid() const;
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;