diff options
Diffstat (limited to 'src/plugins/renderers/rhi/renderer/renderer_p.h')
-rw-r--r-- | src/plugins/renderers/rhi/renderer/renderer_p.h | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/src/plugins/renderers/rhi/renderer/renderer_p.h b/src/plugins/renderers/rhi/renderer/renderer_p.h new file mode 100644 index 000000000..8cceca801 --- /dev/null +++ b/src/plugins/renderers/rhi/renderer/renderer_p.h @@ -0,0 +1,443 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** 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_RENDER_RHI_RENDERER_H +#define QT3DRENDER_RENDER_RHI_RENDERER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/qrenderaspect.h> +#include <Qt3DRender/qtechnique.h> +#include <Qt3DRender/private/handle_types_p.h> +#include <Qt3DRender/private/abstractrenderer_p.h> +#include <Qt3DCore/qaspectjob.h> +#include <Qt3DRender/private/qt3drender_global_p.h> +#include <Qt3DRender/private/rendersettings_p.h> +#include <Qt3DRender/private/updateshaderdatatransformjob_p.h> +#include <Qt3DRender/private/framecleanupjob_p.h> +#include <Qt3DRender/private/platformsurfacefilter_p.h> +#include <Qt3DRender/private/sendbuffercapturejob_p.h> +#include <Qt3DRender/private/genericlambdajob_p.h> +#include <Qt3DRender/private/shaderbuilder_p.h> +#include <Qt3DRender/private/lightgatherer_p.h> +#include <Qt3DRender/private/texture_p.h> +#include <Qt3DRender/private/attachmentpack_p.h> +#include <Qt3DRender/private/filterentitybycomponentjob_p.h> + +#include <QtGui/private/qrhi_p.h> + +#include <shaderparameterpack_p.h> +#include <renderviewinitializerjob_p.h> +#include <filtercompatibletechniquejob_p.h> +#include <renderercache_p.h> +#include <logging_p.h> +#include <rhihandle_types_p.h> +#include <renderercache_p.h> + +#include <QHash> +#include <QMatrix4x4> +#include <QObject> + +#include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> +#include <QOpenGLBuffer> +#include <QMutex> +#include <QWaitCondition> +#include <QAtomicInt> +#include <QScopedPointer> +#include <QSemaphore> + +#include <functional> + +#if defined(QT_BUILD_INTERNAL) +class tst_Renderer; +#endif + +QT_BEGIN_NAMESPACE + +class QSurface; +class QMouseEvent; +class QScreen; + +namespace Qt3DCore { +class QEntity; +class QFrameAllocator; +class QEventFilterService; +} + +namespace Qt3DRender { + +class QCamera; +class QMaterial; +class QShaderProgram; +class QMesh; +class QRenderPass; +class QAbstractShapeMesh; +struct GraphicsApiFilterData; +class QSceneImporter; + +namespace Debug { +class CommandExecuter; +} + +namespace Render { + +class CameraLens; +class FrameGraphNode; +class Material; +class Technique; +class Shader; +class Entity; +class Effect; +class RenderPass; +class RenderThread; +class RenderStateSet; +class VSyncFrameAdvanceService; +class NodeManagers; +class ResourceAccessor; + +using ComputableEntityFilter = FilterEntityByComponentJob<Render::ComputeCommand, Render::Material>; +using ComputableEntityFilterPtr = QSharedPointer<ComputableEntityFilter>; +using RenderableEntityFilter = + FilterEntityByComponentJob<Render::GeometryRenderer, Render::Material>; +using RenderableEntityFilterPtr = QSharedPointer<RenderableEntityFilter>; + +using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; +using SynchronizerPostFramePtr = + GenericLambdaJobAndPostFramePtr<std::function<void()>, + std::function<void(Qt3DCore::QAspectManager *)>>; + +namespace Rhi { + +class CommandThread; +class SubmissionContext; +class RenderCommand; +class RenderQueue; +class RenderView; +class RHIShader; +class RHIResourceManagers; + +class Q_AUTOTEST_EXPORT Renderer : public AbstractRenderer +{ +public: + explicit Renderer(QRenderAspect::RenderType type); + ~Renderer(); + + void dumpInfo() const override; + API api() const override; + + qint64 time() const override; + void setTime(qint64 time) override; + void setJobsInLastFrame(int jobsInLastFrame) override; + + void setAspect(QRenderAspect *aspect) override; + void setNodeManagers(NodeManagers *managers) override; + void setServices(Qt3DCore::QServiceLocator *services) override; + void setSurfaceExposed(bool exposed) override; + + QRenderAspect *aspect() const override; + NodeManagers *nodeManagers() const override; + Qt3DCore::QServiceLocator *services() const override { return m_services; } + + void initialize() override; + void shutdown() override; + void releaseGraphicsResources() override; + + void render() override; + void doRender(bool swapBuffers = true) override; + void cleanGraphicsResources() override; + + bool isRunning() const override { return m_running.loadRelaxed(); } + + void setSceneRoot(Entity *sgRoot) override; + Entity *sceneRoot() const override { return m_renderSceneRoot; } + + FrameGraphNode *frameGraphRoot() const override; + RenderQueue *renderQueue() const { return m_renderQueue; } + + void markDirty(BackendNodeDirtySet changes, BackendNode *node) override; + BackendNodeDirtySet dirtyBits() override; + +#if defined(QT_BUILD_INTERNAL) + void clearDirtyBits(BackendNodeDirtySet changes) override; +#endif + bool shouldRender() const override; + void skipNextFrame() override; + void jobsDone(Qt3DCore::QAspectManager *manager) override; + + void setPendingEvents(const QList<QPair<QObject *, QMouseEvent>> &mouseEvents, + const QList<QKeyEvent> &keyEvents) override; + + QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override; + QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override; + + inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; } + inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const + { + return m_updateShaderDataTransformJob; + } + inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const + { + return m_filterCompatibleTechniqueJob; + } + inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; } + inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; } + inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; } + inline LightGathererPtr lightGathererJob() const { return m_lightGathererJob; } + inline RenderableEntityFilterPtr renderableEntityFilterJob() const + { + return m_renderableEntityFilterJob; + } + inline ComputableEntityFilterPtr computableEntityFilterJob() const + { + return m_computableEntityFilterJob; + } + + Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override; + + void setSettings(RenderSettings *settings) override; + RenderSettings *settings() const override; + QOpenGLContext *shareContext() const override; + + inline RHIResourceManagers *rhiResourceManagers() const { return m_RHIResourceManagers; } + + // Executed in secondary GL thread + void loadShader(Shader *shader, Qt3DRender::Render::HShader shaderHandle) override; + + void updateResources(); + void updateTexture(Texture *texture); + void cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId); + void cleanupShader(const Shader *shader); + void downloadGLBuffers(); + void blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId, + Qt3DCore::QNodeId outputRenderTargetId, QRect inputRect, QRect outputRect, + GLuint defaultFramebuffer); + + struct RHIPassInfo + { + QVector<RenderView *> rvs; + QSurface *surface = nullptr; + Qt3DCore::QNodeId renderTargetId; + AttachmentPack attachmentPack; + }; + + QVector<RHIPassInfo> prepareCommandsSubmission(const QVector<RenderView *> &renderViews); + bool executeCommandsSubmission(const RHIPassInfo &passInfo); + + // For Scene2D rendering + void setOpenGLContext(QOpenGLContext *context) override; + bool accessOpenGLTexture(Qt3DCore::QNodeId nodeId, QOpenGLTexture **texture, QMutex **lock, + bool readonly) override; + QSharedPointer<RenderBackendResourceAccessor> resourceAccessor() const override; + + const GraphicsApiFilterData *contextInfo() const; + SubmissionContext *submissionContext() const; + + inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; } + + QList<QPair<QObject *, QMouseEvent>> pendingPickingEvents() const; + QList<QKeyEvent> pendingKeyEvents() const; + + void enqueueRenderView(RenderView *renderView, int submitOrder); + bool isReadyToSubmit(); + + QVariant executeCommand(const QStringList &args) override; + void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) override; + QSurfaceFormat format() override; + + struct ViewSubmissionResultData + { + ViewSubmissionResultData() : lastBoundFBOId(0), surface(nullptr) { } + + uint lastBoundFBOId; + QSurface *surface; + }; + + ViewSubmissionResultData submitRenderViews(const QVector<RHIPassInfo> &rhiPassesInfo); + + RendererCache *cache() { return &m_cache; } + void setScreen(QScreen *scr) override; + QScreen *screen() const override; + + float *textureTransform() noexcept { return m_textureTransform; } + const float *textureTransform() const noexcept { return m_textureTransform; } +#ifdef QT3D_RENDER_UNIT_TESTS +public: +#else + +private: +#endif + bool canRender() const; + + Qt3DCore::QServiceLocator *m_services; + QRenderAspect *m_aspect; + NodeManagers *m_nodesManager; + + // Frame graph root + Qt3DCore::QNodeId m_frameGraphRootUuid; + + Entity *m_renderSceneRoot; + + // Fail safe values that we can use if a RenderCommand + // is missing a shader + RenderStateSet *m_defaultRenderStateSet; + ShaderParameterPack m_defaultUniformPack; + + QScopedPointer<SubmissionContext> m_submissionContext; + + RenderQueue *m_renderQueue; + QScopedPointer<RenderThread> m_renderThread; + QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService; + + QSemaphore m_submitRenderViewsSemaphore; + QSemaphore m_waitForInitializationToBeCompleted; + QMutex m_hasBeenInitializedMutex; + + QAtomicInt m_running; + + QVector<Attribute *> m_dirtyAttributes; + QVector<Geometry *> m_dirtyGeometry; + QAtomicInt m_exposed; + + struct DirtyBits + { + BackendNodeDirtySet marked; // marked dirty since last job build + BackendNodeDirtySet remaining; // remaining dirty after jobs have finished + }; + DirtyBits m_dirtyBits; + + QAtomicInt m_lastFrameCorrect; + QOpenGLContext *m_glContext; + + qint64 m_time; + + RenderSettings *m_settings; + + UpdateShaderDataTransformJobPtr m_updateShaderDataTransformJob; + FrameCleanupJobPtr m_cleanupJob; + SendBufferCaptureJobPtr m_sendBufferCaptureJob; + FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob; + LightGathererPtr m_lightGathererJob; + RenderableEntityFilterPtr m_renderableEntityFilterJob; + ComputableEntityFilterPtr m_computableEntityFilterJob; + + QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests; + + void performDraw(RenderCommand *command); + void performCompute(const RenderView *rv, RenderCommand *command); + + SynchronizerJobPtr m_bufferGathererJob; + SynchronizerJobPtr m_textureGathererJob; + SynchronizerPostFramePtr m_introspectShaderJob; + + void lookForDirtyBuffers(); + void lookForDownloadableBuffers(); + void lookForDirtyTextures(); + void reloadDirtyShaders(); + void sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager); + void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager); + void sendSetFenceHandlesToFrontend(); + void sendDisablesToFrontend(Qt3DCore::QAspectManager *manager); + + QVector<HBuffer> m_dirtyBuffers; + QVector<Qt3DCore::QNodeId> m_downloadableBuffers; + QVector<HShader> m_dirtyShaders; + QVector<HTexture> m_dirtyTextures; + QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties; + QVector<Qt3DCore::QNodeId> m_updatedDisableSubtreeEnablers; + Qt3DCore::QNodeIdVector m_textureIdsToCleanup; + QVector<ShaderBuilderUpdate> m_shaderBuilderUpdates; + + bool m_ownedContext; + + OffscreenSurfaceHelper *m_offscreenHelper; + RHIResourceManagers *m_RHIResourceManagers; + QMutex m_offscreenSurfaceMutex; + + QScopedPointer<Qt3DRender::Debug::CommandExecuter> m_commandExecuter; + +#ifdef QT_BUILD_INTERNAL + friend class ::tst_Renderer; +#endif + + QMetaObject::Connection m_contextConnection; + RendererCache m_cache; + bool m_shouldSwapBuffers; + + QVector<FrameGraphNode *> m_frameGraphLeaves; + QScreen *m_screen = nullptr; + QSharedPointer<ResourceAccessor> m_scene2DResourceAccessor; + + QOffscreenSurface *m_fallbackSurface {}; + + bool m_hasSwapChain = false; + + QList<QPair<QObject *, QMouseEvent>> m_frameMouseEvents; + QList<QKeyEvent> m_frameKeyEvents; + QMutex m_frameEventsMutex; + int m_jobsInLastFrame = 0; + + float m_textureTransform[4]; + + void updateGraphicsPipeline(RenderCommand &command, RenderView *rv, int renderViewIndex); + bool uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView *rv, + RenderCommand &command); + bool uploadUBOsForCommand(QRhiCommandBuffer *cb, const RenderView *rv, + const RenderCommand &command); + bool performDraw(QRhiCommandBuffer *cb, const QRhiViewport &vp, const QRhiScissor *scissor, + const RenderCommand &command); +}; + +} // namespace Rhi +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_RHI_RENDERER_H |