1// Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB).
2// Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QT3DRENDER_RENDER_RHI_RENDERER_H
6#define QT3DRENDER_RENDER_RHI_RENDERER_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists for the convenience
13// of other Qt classes. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <Qt3DRender/qrenderaspect.h>
20#include <Qt3DRender/qtechnique.h>
21#include <Qt3DRender/private/handle_types_p.h>
22#include <Qt3DRender/private/abstractrenderer_p.h>
23#include <Qt3DCore/qaspectjob.h>
24#include <Qt3DRender/private/qt3drender_global_p.h>
25#include <Qt3DRender/private/rendersettings_p.h>
26#include <Qt3DRender/private/updateshaderdatatransformjob_p.h>
27#include <Qt3DRender/private/framecleanupjob_p.h>
28#include <Qt3DRender/private/sendbuffercapturejob_p.h>
29#include <Qt3DRender/private/genericlambdajob_p.h>
30#include <Qt3DRender/private/shaderbuilder_p.h>
31#include <Qt3DRender/private/lightgatherer_p.h>
32#include <Qt3DRender/private/texture_p.h>
33#include <Qt3DRender/private/attachmentpack_p.h>
34#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
35#include <Qt3DRender/private/filtercompatibletechniquejob_p.h>
36#include <Qt3DRender/private/renderqueue_p.h>
37#include <Qt3DRender/private/renderercache_p.h>
38#include <Qt3DRender/private/renderviewinitializerjob_p.h>
39
40#include <rhi/qrhi.h>
41
42#include <shaderparameterpack_p.h>
43#include <logging_p.h>
44#include <rhihandle_types_p.h>
45#include <renderview_p.h>
46
47#include <QHash>
48#include <QMatrix4x4>
49#include <QObject>
50
51#include <QOffscreenSurface>
52#include <QMutex>
53#include <QWaitCondition>
54#include <QAtomicInt>
55#include <QScopedPointer>
56#include <QSemaphore>
57
58#include <functional>
59
60#if defined(QT_BUILD_INTERNAL)
61class tst_Renderer;
62#endif
63
64QT_BEGIN_NAMESPACE
65
66class QSurface;
67class QMouseEvent;
68class QScreen;
69
70namespace Qt3DCore {
71class QEntity;
72}
73
74namespace Qt3DRender {
75
76class QCamera;
77class QMaterial;
78class QShaderProgram;
79class QMesh;
80class QRenderPass;
81class QAbstractShapeMesh;
82struct GraphicsApiFilterData;
83class QSceneImporter;
84
85namespace DebugRhi {
86class CommandExecuter;
87}
88
89namespace Render {
90
91class CameraLens;
92class FrameGraphNode;
93class Material;
94class Technique;
95class Shader;
96class Entity;
97class Effect;
98class RenderPass;
99class RenderStateSet;
100class VSyncFrameAdvanceService;
101class NodeManagers;
102class ResourceAccessor;
103
104using ComputableEntityFilter = FilterEntityByComponentJob<Render::ComputeCommand, Render::Material>;
105using ComputableEntityFilterPtr = QSharedPointer<ComputableEntityFilter>;
106using RenderableEntityFilter =
107 FilterEntityByComponentJob<Render::GeometryRenderer, Render::Material>;
108using RenderableEntityFilterPtr = QSharedPointer<RenderableEntityFilter>;
109
110using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
111using SynchronizerPostFramePtr =
112 GenericLambdaJobAndPostFramePtr<std::function<void()>,
113 std::function<void(Qt3DCore::QAspectManager *)>>;
114
115namespace Rhi {
116
117class CommandThread;
118class SubmissionContext;
119class RenderCommand;
120struct RHIRenderTarget;
121class RHIShader;
122class RHIResourceManagers;
123class RenderView;
124class RHIGraphicsPipeline;
125class RHIComputePipeline;
126class PipelineUBOSet;
127
128class Q_AUTOTEST_EXPORT Renderer : public AbstractRenderer
129{
130public:
131 explicit Renderer();
132 ~Renderer();
133
134 void dumpInfo() const override;
135 API api() const override;
136
137 void setRenderDriver(AbstractRenderer::RenderDriver driver) override;
138 AbstractRenderer::RenderDriver renderDriver() const override;
139
140 qint64 time() const override;
141 void setTime(qint64 time) override;
142 void setJobsInLastFrame(int jobsInLastFrame) override;
143
144 void setAspect(QRenderAspect *aspect) override;
145 void setNodeManagers(NodeManagers *managers) override;
146 void setServices(Qt3DCore::QServiceLocator *services) override;
147 void setSurfaceExposed(bool exposed) override;
148
149 QRenderAspect *aspect() const override;
150 NodeManagers *nodeManagers() const override;
151 Qt3DCore::QServiceLocator *services() const override { return m_services; }
152
153 void initialize() override;
154 void shutdown() override;
155 void releaseGraphicsResources() override;
156
157 void render(bool swapBuffers = true) override;
158 void cleanGraphicsResources() override;
159
160 bool isRunning() const override { return m_running.loadRelaxed(); }
161
162 void setSceneRoot(Entity *sgRoot) override;
163 Entity *sceneRoot() const override { return m_renderSceneRoot; }
164
165 FrameGraphNode *frameGraphRoot() const override;
166 RenderQueue<RenderView> *renderQueue() { return &m_renderQueue; }
167
168 void markDirty(BackendNodeDirtySet changes, BackendNode *node) override;
169 BackendNodeDirtySet dirtyBits() override;
170
171#if defined(QT_BUILD_INTERNAL)
172 void clearDirtyBits(BackendNodeDirtySet changes) override;
173#endif
174 bool shouldRender() const override;
175 void skipNextFrame() override;
176 void jobsDone(Qt3DCore::QAspectManager *manager) override;
177
178 bool processMouseEvent(QObject *object, QMouseEvent *event) override;
179 bool processKeyEvent(QObject *object, QKeyEvent *event) override;
180
181 std::vector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override;
182 std::vector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
183
184 inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; }
185 inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const
186 {
187 return m_updateShaderDataTransformJob;
188 }
189 inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const
190 {
191 return m_filterCompatibleTechniqueJob;
192 }
193 inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; }
194 inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
195 inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
196 inline LightGathererPtr lightGathererJob() const { return m_lightGathererJob; }
197 inline RenderableEntityFilterPtr renderableEntityFilterJob() const
198 {
199 return m_renderableEntityFilterJob;
200 }
201 inline ComputableEntityFilterPtr computableEntityFilterJob() const
202 {
203 return m_computableEntityFilterJob;
204 }
205
206 Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override;
207
208 void setSettings(RenderSettings *settings) override;
209 RenderSettings *settings() const override;
210 QOpenGLContext *shareContext() const override;
211
212 inline RHIResourceManagers *rhiResourceManagers() const { return m_RHIResourceManagers; }
213
214 void updateResources();
215 void updateTexture(Texture *texture);
216 void cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId);
217 void cleanupShader(const Shader *shader);
218 void downloadRHIBuffers();
219
220 struct RHIPassInfo
221 {
222 std::vector<RenderView *> rvs;
223 QSurface *surface = nullptr;
224 Qt3DCore::QNodeId renderTargetId;
225 };
226
227 std::vector<RHIPassInfo> prepareCommandsSubmission(const std::vector<RenderView *> &renderViews);
228 bool executeCommandsSubmission(const RHIPassInfo &passInfo);
229
230 // For Scene3D/Scene2D rendering
231 void setOpenGLContext(QOpenGLContext *context) override;
232 void setRHIContext(QRhi *ctx) override;
233 void setDefaultRHIRenderTarget(QRhiRenderTarget *defaultTarget) override;
234 void setRHICommandBuffer(QRhiCommandBuffer *commandBuffer) override;
235 bool accessOpenGLTexture(Qt3DCore::QNodeId nodeId, QOpenGLTexture **texture, QMutex **lock,
236 bool readonly) override;
237 QSharedPointer<RenderBackendResourceAccessor> resourceAccessor() const override;
238
239 const GraphicsApiFilterData *contextInfo() const override;
240 SubmissionContext *submissionContext() const;
241
242 inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; }
243
244 QList<QPair<QObject *, QMouseEvent>> pendingPickingEvents() const;
245 QList<QKeyEvent> pendingKeyEvents() const;
246
247 void enqueueRenderView(RenderView *renderView, int submitOrder);
248 bool waitUntilReadyToSubmit();
249
250 QVariant executeCommand(const QStringList &args) override;
251 void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *) override {};
252 QSurfaceFormat format() override;
253
254 struct ViewSubmissionResultData
255 {
256 ViewSubmissionResultData() : surface(nullptr) { }
257
258 QSurface *surface;
259 };
260
261 ViewSubmissionResultData submitRenderViews(const std::vector<RHIPassInfo> &rhiPassesInfo);
262
263 RendererCache<RenderCommand> *cache() { return &m_cache; }
264 void setScreen(QScreen *scr) override;
265 QScreen *screen() const override;
266
267 float *textureTransform() noexcept { return m_textureTransform; }
268 const float *textureTransform() const noexcept { return m_textureTransform; }
269#ifdef QT3D_RENDER_UNIT_TESTS
270public:
271#else
272
273private:
274#endif
275 Qt3DCore::QServiceLocator *m_services;
276 QRenderAspect *m_aspect;
277 NodeManagers *m_nodesManager;
278
279 // Frame graph root
280 Qt3DCore::QNodeId m_frameGraphRootUuid;
281
282 Entity *m_renderSceneRoot;
283
284 // Fail safe values that we can use if a RenderCommand
285 // is missing a shader
286 RenderStateSet *m_defaultRenderStateSet;
287 ShaderParameterPack m_defaultUniformPack;
288
289 QScopedPointer<SubmissionContext> m_submissionContext;
290
291 RenderQueue<RenderView> m_renderQueue;
292 QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService;
293
294 QSemaphore m_submitRenderViewsSemaphore;
295 QSemaphore m_waitForInitializationToBeCompleted;
296 QMutex m_hasBeenInitializedMutex;
297
298 QAtomicInt m_running;
299
300 std::vector<Attribute *> m_dirtyAttributes;
301 std::vector<Geometry *> m_dirtyGeometry;
302 QAtomicInt m_exposed;
303
304 struct DirtyBits
305 {
306 BackendNodeDirtySet marked; // marked dirty since last job build
307 BackendNodeDirtySet remaining; // remaining dirty after jobs have finished
308 };
309 DirtyBits m_dirtyBits;
310
311 QAtomicInt m_lastFrameCorrect;
312 QOpenGLContext *m_glContext;
313 QRhi *m_rhiContext;
314
315 qint64 m_time;
316
317 RenderSettings *m_settings;
318
319 UpdateShaderDataTransformJobPtr m_updateShaderDataTransformJob;
320 FrameCleanupJobPtr m_cleanupJob;
321 SendBufferCaptureJobPtr m_sendBufferCaptureJob;
322 FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob;
323 LightGathererPtr m_lightGathererJob;
324 RenderableEntityFilterPtr m_renderableEntityFilterJob;
325 ComputableEntityFilterPtr m_computableEntityFilterJob;
326
327 QMutex m_pendingRenderCaptureSendRequestsMutex;
328 std::vector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests;
329
330 SynchronizerJobPtr m_bufferGathererJob;
331 SynchronizerJobPtr m_textureGathererJob;
332 SynchronizerPostFramePtr m_introspectShaderJob;
333
334 void lookForDirtyBuffers();
335 void lookForDownloadableBuffers();
336 void lookForDirtyTextures();
337 void reloadDirtyShaders();
338 void sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager);
339 void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager);
340 void sendSetFenceHandlesToFrontend();
341 void sendDisablesToFrontend(Qt3DCore::QAspectManager *manager);
342
343 std::vector<HBuffer> m_dirtyBuffers;
344 std::vector<Qt3DCore::QNodeId> m_downloadableBuffers;
345 std::vector<HShader> m_dirtyShaders;
346 std::vector<HTexture> m_dirtyTextures;
347 std::vector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
348 std::vector<Qt3DCore::QNodeId> m_updatedDisableSubtreeEnablers;
349 Qt3DCore::QNodeIdVector m_textureIdsToCleanup;
350 std::vector<ShaderBuilderUpdate> m_shaderBuilderUpdates;
351
352 bool m_ownedContext;
353
354 RHIResourceManagers *m_RHIResourceManagers;
355 QMutex m_offscreenSurfaceMutex;
356
357 QScopedPointer<Qt3DRender::DebugRhi::CommandExecuter> m_commandExecuter;
358
359#ifdef QT_BUILD_INTERNAL
360 friend class ::tst_Renderer;
361#endif
362
363 QMetaObject::Connection m_contextConnection;
364 RendererCache<RenderCommand> m_cache;
365 bool m_shouldSwapBuffers;
366
367 std::vector<FrameGraphNode *> m_frameGraphLeaves;
368 QScreen *m_screen = nullptr;
369 QSharedPointer<ResourceAccessor> m_scene2DResourceAccessor;
370 QHash<RenderView *, std::vector<RHIGraphicsPipeline *>> m_rvToGraphicsPipelines;
371 QHash<RenderView *, std::vector<RHIComputePipeline *>> m_rvToComputePipelines;
372 RenderDriver m_driver = RenderDriver::Qt3D;
373
374 bool m_hasSwapChain = false;
375
376 int m_jobsInLastFrame = 0;
377
378 float m_textureTransform[4];
379
380 bool prepareGeometryInputBindings(const Geometry *geometry, const RHIShader *shader,
381 QVarLengthArray<QRhiVertexInputBinding, 8> &inputBindings,
382 QVarLengthArray<QRhiVertexInputAttribute, 8> &rhiAttributes,
383 QHash<int, int> &attributeNameToBinding);
384
385 void updateGraphicsPipeline(RenderCommand &command, RenderView *rv);
386 void updateComputePipeline(RenderCommand &cmd, RenderView *rv,
387 int renderViewIndex);
388
389 void buildGraphicsPipelines(RHIGraphicsPipeline *graphicsPipeline,
390 RenderView *rv,
391 const RenderCommand &command);
392
393 void buildComputePipelines(RHIComputePipeline *computePipeline,
394 RenderView *rv,
395 const RenderCommand &command);
396
397 void cleanupRenderTarget(const Qt3DCore::QNodeId &renderTarget);
398
399 void createRenderTarget(RenderTarget *);
400 bool setupRenderTarget(RenderView* rv, RHIGraphicsPipeline* graphicsPipeline, QRhiSwapChain* swapchain);
401
402 bool uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView *rv,
403 RenderCommand &command);
404
405 bool uploadBuffersForCommand(RHIComputePipeline* compute, RenderCommand &command);
406 bool uploadBuffersForCommand(RHIGraphicsPipeline* graphics, RenderCommand &command);
407 bool uploadUBOsForCommand(QRhiCommandBuffer *cb, const RenderView *rv,
408 const RenderCommand &command);
409 bool performCompute(QRhiCommandBuffer *cb, RenderCommand &command);
410 bool performDraw(QRhiCommandBuffer *cb, const QRhiViewport &vp, const QRhiScissor *scissor,
411 RenderCommand &command);
412 bool setBindingAndShaderResourcesForCommand(QRhiCommandBuffer *cb,
413 RenderCommand &command,
414 PipelineUBOSet *uboSet);
415};
416
417} // namespace Rhi
418} // namespace Render
419} // namespace Qt3DRender
420
421QT_END_NAMESPACE
422
423#endif // QT3DRENDER_RENDER_RHI_RENDERER_H
424

source code of qt3d/src/plugins/renderers/rhi/renderer/renderer_p.h