summaryrefslogtreecommitdiffstats
path: root/src/render/renderers/opengl/renderer/renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/renderers/opengl/renderer/renderer.cpp')
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp162
1 files changed, 136 insertions, 26 deletions
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index aeb3e513d..b4a19c641 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>
@@ -197,6 +198,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_ownedContext(false)
@@ -294,6 +296,8 @@ void Renderer::setNodeManagers(NodeManagers *managers)
m_updateShaderDataTransformJob->setManagers(m_nodesManager);
m_cleanupJob->setManagers(m_nodesManager);
m_calculateBoundingVolumeJob->setManagers(m_nodesManager);
+ m_expandBoundingVolumeJob->setManagers(m_nodesManager);
+ m_worldTransformJob->setManagers(m_nodesManager);
m_pickBoundingVolumeJob->setManagers(m_nodesManager);
m_rayCastingJob->setManagers(m_nodesManager);
m_updateWorldBoundingVolumeJob->setManager(m_nodesManager->renderNodesManager());
@@ -303,6 +307,7 @@ void Renderer::setNodeManagers(NodeManagers *managers)
m_updateMeshTriangleListJob->setManagers(m_nodesManager);
m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager());
m_updateEntityLayersJob->setManager(m_nodesManager);
+ m_updateTreeEnabledJob->setManagers(m_nodesManager);
m_updateEntityHierarchyJob->setManager(m_nodesManager);
}
@@ -393,6 +398,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 +1105,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 +1191,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 +1210,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 +1239,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 +1323,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 +1351,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 +1412,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 +1448,7 @@ void Renderer::cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId)
glTextureManager->abandon(glTexture, cleanedUpTextureId);
}
+// Called by SubmitRenderView
void Renderer::downloadGLBuffers()
{
lookForDownloadableBuffers();
@@ -1478,6 +1533,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 +1736,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 +1824,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