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) |
61 | class tst_Renderer; |
62 | #endif |
63 | |
64 | QT_BEGIN_NAMESPACE |
65 | |
66 | class QSurface; |
67 | class QMouseEvent; |
68 | class QScreen; |
69 | |
70 | namespace Qt3DCore { |
71 | class QEntity; |
72 | } |
73 | |
74 | namespace Qt3DRender { |
75 | |
76 | class QCamera; |
77 | class QMaterial; |
78 | class QShaderProgram; |
79 | class QMesh; |
80 | class QRenderPass; |
81 | class QAbstractShapeMesh; |
82 | struct GraphicsApiFilterData; |
83 | class QSceneImporter; |
84 | |
85 | namespace DebugRhi { |
86 | class CommandExecuter; |
87 | } |
88 | |
89 | namespace Render { |
90 | |
91 | class CameraLens; |
92 | class FrameGraphNode; |
93 | class Material; |
94 | class Technique; |
95 | class Shader; |
96 | class Entity; |
97 | class Effect; |
98 | class RenderPass; |
99 | class RenderStateSet; |
100 | class VSyncFrameAdvanceService; |
101 | class NodeManagers; |
102 | class ResourceAccessor; |
103 | |
104 | using ComputableEntityFilter = FilterEntityByComponentJob<Render::ComputeCommand, Render::Material>; |
105 | using ComputableEntityFilterPtr = QSharedPointer<ComputableEntityFilter>; |
106 | using RenderableEntityFilter = |
107 | FilterEntityByComponentJob<Render::GeometryRenderer, Render::Material>; |
108 | using RenderableEntityFilterPtr = QSharedPointer<RenderableEntityFilter>; |
109 | |
110 | using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; |
111 | using SynchronizerPostFramePtr = |
112 | GenericLambdaJobAndPostFramePtr<std::function<void()>, |
113 | std::function<void(Qt3DCore::QAspectManager *)>>; |
114 | |
115 | namespace Rhi { |
116 | |
117 | class CommandThread; |
118 | class SubmissionContext; |
119 | class RenderCommand; |
120 | struct RHIRenderTarget; |
121 | class RHIShader; |
122 | class RHIResourceManagers; |
123 | class RenderView; |
124 | class RHIGraphicsPipeline; |
125 | class RHIComputePipeline; |
126 | class PipelineUBOSet; |
127 | |
128 | class Q_AUTOTEST_EXPORT Renderer : public AbstractRenderer |
129 | { |
130 | public: |
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 |
270 | public: |
271 | #else |
272 | |
273 | private: |
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 | |
421 | QT_END_NAMESPACE |
422 | |
423 | #endif // QT3DRENDER_RENDER_RHI_RENDERER_H |
424 | |