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/renderer.cpp159
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h17
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp5
-rw-r--r--src/render/renderers/opengl/renderer/renderview_p.h10
4 files changed, 163 insertions, 28 deletions
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index e9c582458..e7fa4615c 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -91,6 +91,7 @@
#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/private/commandthread_p.h>
#include <Qt3DRender/private/glcommands_p.h>
+#include <Qt3DRender/private/setfence_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
@@ -196,6 +197,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
, m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
, m_sendTextureChangesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendTextureChangesToFrontend(); }, JobTypes::SendTextureChangesToFrontend))
+ , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
, m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering))
, m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading))
, m_updateEntityHierarchyJob(Render::UpdateEntityHierarchyJobPtr::create())
@@ -393,6 +395,9 @@ void Renderer::initialize()
[this] { releaseGraphicsResources(); });
}
+ qCDebug(Backend) << "Qt3D shared context:" << ctx->shareContext();
+ qCDebug(Backend) << "Qt global shared context:" << qt_gl_global_share_context();
+
if (!ctx->shareContext()) {
m_shareContext = new QOpenGLContext;
m_shareContext->setFormat(ctx->format());
@@ -1097,7 +1102,7 @@ void Renderer::lookForDirtyTextures()
}
// Dirty meaning that something has changed on the texture
- // either properties, parameters, generator or a texture image
+ // either properties, parameters, shared texture id, generator or a texture image
if (texture->dirtyFlags() != Texture::NotDirty)
m_dirtyTextures.push_back(handle);
// Note: texture dirty flags are reset when actually updating the
@@ -1183,7 +1188,7 @@ void Renderer::reloadDirtyShaders()
// Executed in a job
void Renderer::sendTextureChangesToFrontend()
{
- const QVector<QPair<TextureProperties, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties);
+ const QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties);
for (const auto &pair : updateTextureProperties) {
// Prepare change notification
@@ -1202,6 +1207,22 @@ void Renderer::sendTextureChangesToFrontend()
}
}
+// Executed in a job
+void Renderer::sendSetFenceHandlesToFrontend()
+{
+ const QVector<QPair<Qt3DCore::QNodeId, GLFence>> updatedSetFence = std::move(m_updatedSetFences);
+ FrameGraphManager *fgManager = m_nodesManager->frameGraphManager();
+ for (const auto &pair : updatedSetFence) {
+ FrameGraphNode *fgNode = fgManager->lookupNode(pair.first);
+ if (fgNode != nullptr) { // Node could have been deleted before we got a chance to notify it
+ Q_ASSERT(fgNode->nodeType() == FrameGraphNode::SetFence);
+ SetFence *setFenceNode = static_cast<SetFence *>(fgNode);
+ setFenceNode->setHandleType(QSetFence::OpenGLFenceId);
+ setFenceNode->setHandle(QVariant::fromValue(pair.second));
+ }
+ }
+}
+
// Render Thread (or QtQuick RenderThread when using Scene3D)
// Scene3D: When using Scene3D rendering, we can't assume that when
// updateGLResources is called, the resource handles points to still existing
@@ -1215,6 +1236,25 @@ void Renderer::sendTextureChangesToFrontend()
void Renderer::updateGLResources()
{
{
+ // Update active fence objects:
+ // - Destroy fences that have reached their signaled state
+ GLFenceManager *fenceManager = m_nodesManager->glFenceManager();
+ const auto end = fenceManager->end();
+ auto it = fenceManager->begin();
+ while (it != end) {
+ const GLFence fence = it.value();
+ if (m_submissionContext->wasSyncSignaled(fence)) {
+ // Fence was signaled, we delete it
+ // before removing the entry from the manager
+ m_submissionContext->deleteSync(fence);
+ it = fenceManager->erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+
+ {
Profiling::GLTimeRecorder recorder(Profiling::BufferUpload);
const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers);
for (const HBuffer &handle: dirtyBufferHandles) {
@@ -1280,8 +1320,13 @@ void Renderer::updateGLResources()
// Gather these information and store them to be distributed by a change next frame
const QNodeIdVector referenceTextureIds = glTextureManager->referencedTextureIds(glTexture);
// Store properties and referenceTextureIds
- if (info.wasUpdated)
- m_updatedTextureProperties.push_back({info.properties, referenceTextureIds});
+ if (info.wasUpdated) {
+ Texture::TextureUpdateInfo updateInfo;
+ updateInfo.properties = info.properties;
+ updateInfo.handleType = QAbstractTexture::OpenGLTextureId;
+ updateInfo.handle = info.texture ? QVariant(info.texture->textureId()) : QVariant();
+ m_updatedTextureProperties.push_back({updateInfo, referenceTextureIds});
+ }
}
}
}
@@ -1303,18 +1348,21 @@ void Renderer::updateTexture(Texture *texture)
return;
// For implementing unique, non-shared, non-cached textures.
- // for now, every texture is shared by default
+ // for now, every texture is shared by default except if:
+ // - texture is reference by a render attachment
+ // - texture is referencing a shared texture id
+ bool isUnique = texture->sharedTextureId() > 0;
- bool isUnique = false;
-
- // TO DO: Update the vector once per frame (or in a job)
- const QVector<HAttachment> activeRenderTargetOutputs = m_nodesManager->attachmentManager()->activeHandles();
- // A texture is unique if it's being reference by a render target output
- for (const HAttachment &attachmentHandle : activeRenderTargetOutputs) {
- RenderTargetOutput *attachment = m_nodesManager->attachmentManager()->data(attachmentHandle);
- if (attachment->textureUuid() == texture->peerId()) {
- isUnique = true;
- break;
+ if (!isUnique) {
+ // TO DO: Update the vector once per frame (or in a job)
+ const QVector<HAttachment> activeRenderTargetOutputs = m_nodesManager->attachmentManager()->activeHandles();
+ // A texture is unique if it's being reference by a render target output
+ for (const HAttachment &attachmentHandle : activeRenderTargetOutputs) {
+ RenderTargetOutput *attachment = m_nodesManager->attachmentManager()->data(attachmentHandle);
+ if (attachment->textureUuid() == texture->peerId()) {
+ isUnique = true;
+ break;
+ }
}
}
@@ -1361,6 +1409,9 @@ void Renderer::updateTexture(Texture *texture)
// we hold a reference to a unique or exclusive access to a shared texture
// we can thus modify the texture directly.
const Texture::DirtyFlags dirtyFlags = texture->dirtyFlags();
+ if (dirtyFlags.testFlag(Texture::DirtySharedTextureId) &&
+ !glTextureManager->setSharedTextureId(glTexture, texture->sharedTextureId()))
+ qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setSharedTextureId failed, should be non-shared";
if (dirtyFlags.testFlag(Texture::DirtyProperties) &&
!glTextureManager->setProperties(glTexture, texture->properties()))
@@ -1394,6 +1445,7 @@ void Renderer::cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId)
glTextureManager->abandon(glTexture, cleanedUpTextureId);
}
+// Called by SubmitRenderView
void Renderer::downloadGLBuffers()
{
lookForDownloadableBuffers();
@@ -1478,6 +1530,45 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
if (renderView->memoryBarrier() != QMemoryBarrier::None)
m_submissionContext->memoryBarrier(renderView->memoryBarrier());
+
+ // Insert Fence into command stream if needed
+ const Qt3DCore::QNodeIdVector insertFenceIds = renderView->insertFenceIds();
+ GLFenceManager *fenceManager = m_nodesManager->glFenceManager();
+ for (const Qt3DCore::QNodeId insertFenceId : insertFenceIds) {
+ // If the fence is not in the manager, then it hasn't been inserted
+ // into the command stream yet.
+ if (fenceManager->find(insertFenceId) == fenceManager->end()) {
+ // Insert fence into command stream
+ GLFence glFence = m_submissionContext->fenceSync();
+ // Record glFence
+ fenceManager->insert(insertFenceId, glFence);
+ // Add entry for notification changes to be sent
+ m_updatedSetFences.push_back({insertFenceId, glFence});
+ }
+ // If it is in the manager, then it hasn't been signaled yet,
+ // nothing we can do but try at the next frame
+ }
+
+ // Wait for fences if needed
+ const QVector<QWaitFenceData> waitFences = renderView->waitFences();
+ for (const QWaitFenceData &waitFence : waitFences) {
+ // TO DO
+ if (waitFence.handleType != QWaitFence::OpenGLFenceId) {
+ qWarning() << "WaitFence handleType should be OpenGLFenceId when using the Qt 3D OpenGL renderer";
+ continue;
+ }
+ GLFence fence = reinterpret_cast<GLFence>(waitFence.handle.value<qintptr>());
+ if (fence == nullptr)
+ continue;
+
+ if (waitFence.waitOnCPU) {
+ m_submissionContext->clientWaitSync(fence,
+ waitFence.timeout);
+ } else {
+ m_submissionContext->waitSync(fence);
+ }
+ }
+
// Note: the RenderStateSet is allocated once per RV if needed
// and it contains a list of StateVariant value types
RenderStateSet *renderViewStateSet = renderView->stateSet();
@@ -1642,6 +1733,33 @@ void Renderer::skipNextFrame()
m_submitRenderViewsSemaphore.release(1);
}
+// Jobs we may have to run even if no rendering will happen
+QVector<QAspectJobPtr> Renderer::preRenderingJobs()
+{
+ QVector<QAspectJobPtr> jobs;
+
+ // Do we need to notify any texture about property changes?
+ if (m_updatedTextureProperties.size() > 0)
+ jobs.push_back(m_sendTextureChangesToFrontendJob);
+
+ // Do we need to notify frontend about fence change?
+ if (m_updatedSetFences.size() > 0)
+ jobs.push_back(m_sendSetFenceHandlesToFrontendJob);
+
+ const QVector<Qt3DCore::QNodeId> pendingCaptureIds = takePendingRenderCaptureSendRequests();
+ if (pendingCaptureIds.size() > 0) {
+ m_sendRenderCaptureJob->setPendingCaptureRequests(pendingCaptureIds);
+ jobs.push_back(m_sendRenderCaptureJob);
+ }
+ if (m_sendBufferCaptureJob->hasRequests())
+ jobs.push_back(m_sendBufferCaptureJob);
+
+ jobs.append(pickBoundingVolumeJob());
+ jobs.append(rayCastingJob());
+
+ return jobs;
+}
+
// Waits to be told to create jobs for the next frame
// Called by QRenderAspect jobsToExecute context of QAspectThread
// Returns all the jobs (and with proper dependency chain) required
@@ -1703,17 +1821,6 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
renderBinJobs.push_back(m_updateLevelOfDetailJob);
renderBinJobs.push_back(m_cleanupJob);
- const QVector<Qt3DCore::QNodeId> pendingCaptureIds = takePendingRenderCaptureSendRequests();
- if (pendingCaptureIds.size() > 0) {
- m_sendRenderCaptureJob->setPendingCaptureRequests(pendingCaptureIds);
- renderBinJobs.push_back(m_sendRenderCaptureJob);
- }
-
- // Do we need to notify any texture about property changes?
- if (m_updatedTextureProperties.size() > 0)
- renderBinJobs.push_back(m_sendTextureChangesToFrontendJob);
-
- renderBinJobs.push_back(m_sendBufferCaptureJob);
renderBinJobs.append(bufferJobs);
// Jobs to prepare GL Resource upload
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index 6443215a4..5b5f5c4f4 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -81,6 +81,7 @@
#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/private/renderercache_p.h>
#include <Qt3DRender/private/texture_p.h>
+#include <Qt3DRender/private/glfence_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -97,6 +98,10 @@
#include <functional>
+#if defined(QT_BUILD_INTERNAL)
+class tst_Renderer;
+#endif
+
QT_BEGIN_NAMESPACE
class QSurface;
@@ -153,7 +158,7 @@ typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-class QT3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
+class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
{
public:
explicit Renderer(QRenderAspect::RenderType type);
@@ -197,6 +202,7 @@ public:
bool shouldRender() override;
void skipNextFrame() override;
+ QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override;
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override;
Qt3DCore::QAspectJobPtr rayCastingJob() override;
@@ -376,6 +382,7 @@ private:
GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
GenericLambdaJobPtr<std::function<void ()>> m_sendTextureChangesToFrontendJob;
+ GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob;
IntrospectShadersJobPtr m_introspectShaderJob;
SynchronizerJobPtr m_syncTextureLoadingJob;
@@ -386,6 +393,7 @@ private:
void lookForDirtyTextures();
void reloadDirtyShaders();
void sendTextureChangesToFrontend();
+ void sendSetFenceHandlesToFrontend();
QMutex m_abandonedVaosMutex;
QVector<HVao> m_abandonedVaos;
@@ -394,7 +402,8 @@ private:
QVector<HBuffer> m_downloadableBuffers;
QVector<HShader> m_dirtyShaders;
QVector<HTexture> m_dirtyTextures;
- QVector<QPair<TextureProperties, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
+ QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
+ QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
bool m_ownedContext;
@@ -406,6 +415,10 @@ private:
friend class Qt3DRender::Debug::CommandExecuter;
#endif
+#ifdef QT_BUILD_INTERNAL
+ friend class ::tst_Renderer;
+#endif
+
QMetaObject::Connection m_contextConnection;
RendererCache m_cache;
};
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index 47e6a8fb1..de25f55d1 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -715,6 +715,11 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En
if ((computeJob = entity->renderComponent<ComputeCommand>()) != nullptr
&& computeJob->isEnabled()) {
+ // Note: if frameCount has reached 0 in the previous frame, isEnabled
+ // would be false
+ if (computeJob->runType() == QComputeCommand::Manual)
+ computeJob->updateFrameCount();
+
const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>();
const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId);
diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h
index cb3c74917..7ebcdb6bd 100644
--- a/src/render/renderers/opengl/renderer/renderview_p.h
+++ b/src/render/renderers/opengl/renderer/renderview_p.h
@@ -65,6 +65,7 @@
#include <Qt3DRender/private/qmemorybarrier_p.h>
#include <Qt3DRender/private/qrendercapture_p.h>
#include <Qt3DRender/private/qblitframebuffer_p.h>
+#include <Qt3DRender/private/qwaitfence_p.h>
#include <Qt3DCore/private/qframeallocator_p.h>
#include <Qt3DRender/private/aligned_malloc_p.h>
@@ -174,6 +175,13 @@ public:
inline void appendProximityFilterId(const Qt3DCore::QNodeId proximityFilterId) { m_data.m_proximityFilterIds.push_back(proximityFilterId); }
inline Qt3DCore::QNodeIdVector proximityFilterIds() const { return m_data.m_proximityFilterIds; }
+ inline void appendInsertFenceId(const Qt3DCore::QNodeId setFenceId) { m_insertFenceIds.push_back(setFenceId); }
+ // We prefix with get to avoid confusion when it is called
+ inline Qt3DCore::QNodeIdVector insertFenceIds() const { return m_insertFenceIds; }
+
+ inline void appendWaitFence(const QWaitFenceData &data) { m_waitFences.push_back(data); }
+ inline QVector<QWaitFenceData> waitFences() const { return m_waitFences; }
+
inline void setRenderPassFilter(const RenderPassFilter *rpFilter) Q_DECL_NOTHROW { m_data.m_passFilter = rpFilter; }
inline const RenderPassFilter *renderPassFilter() const Q_DECL_NOTHROW { return m_data.m_passFilter; }
@@ -320,6 +328,8 @@ private:
bool m_frustumCulling:1;
int m_workGroups[3];
QMemoryBarrier::Operations m_memoryBarrier;
+ 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