1/****************************************************************************
2**
3** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the Qt3D module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#ifndef QT3DRENDER_RENDER_RENDERER_H
42#define QT3DRENDER_RENDER_RENDERER_H
43
44//
45// W A R N I N G
46// -------------
47//
48// This file is not part of the Qt API. It exists for the convenience
49// of other Qt classes. This header file may change from version to
50// version without notice, or even be removed.
51//
52// We mean it.
53//
54
55#include <Qt3DRender/qrenderaspect.h>
56#include <Qt3DRender/qtechnique.h>
57#include <Qt3DRender/private/shaderparameterpack_p.h>
58#include <Qt3DRender/private/handle_types_p.h>
59#include <Qt3DRender/private/abstractrenderer_p.h>
60#include <Qt3DCore/qaspectjob.h>
61#include <Qt3DRender/private/qt3drender_global_p.h>
62#include <Qt3DRender/private/pickboundingvolumejob_p.h>
63#include <Qt3DRender/private/raycastingjob_p.h>
64#include <Qt3DRender/private/rendersettings_p.h>
65#include <Qt3DRender/private/renderviewinitializerjob_p.h>
66#include <Qt3DRender/private/expandboundingvolumejob_p.h>
67#include <Qt3DRender/private/updateworldtransformjob_p.h>
68#include <Qt3DRender/private/calcboundingvolumejob_p.h>
69#include <Qt3DRender/private/updateshaderdatatransformjob_p.h>
70#include <Qt3DRender/private/framecleanupjob_p.h>
71#include <Qt3DRender/private/updateworldboundingvolumejob_p.h>
72#include <Qt3DRender/private/updatetreeenabledjob_p.h>
73#include <Qt3DRender/private/platformsurfacefilter_p.h>
74#include <Qt3DRender/private/sendrendercapturejob_p.h>
75#include <Qt3DRender/private/sendbuffercapturejob_p.h>
76#include <Qt3DRender/private/genericlambdajob_p.h>
77#include <Qt3DRender/private/updatemeshtrianglelistjob_p.h>
78#include <Qt3DRender/private/filtercompatibletechniquejob_p.h>
79#include <Qt3DRender/private/updateskinningpalettejob_p.h>
80#include <Qt3DRender/private/updateentitylayersjob_p.h>
81#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
82#include <Qt3DRender/private/renderercache_p.h>
83#include <Qt3DRender/private/texture_p.h>
84#include <Qt3DRender/private/glfence_p.h>
85
86#include <QHash>
87#include <QMatrix4x4>
88#include <QObject>
89
90#include <QOpenGLShaderProgram>
91#include <QOpenGLVertexArrayObject>
92#include <QOpenGLBuffer>
93#include <QMutex>
94#include <QWaitCondition>
95#include <QAtomicInt>
96#include <QScopedPointer>
97#include <QSemaphore>
98
99#include <functional>
100
101#if defined(QT_BUILD_INTERNAL)
102class tst_Renderer;
103#endif
104
105QT_BEGIN_NAMESPACE
106
107class QSurface;
108class QMouseEvent;
109
110namespace Qt3DCore {
111class QEntity;
112class QFrameAllocator;
113class QEventFilterService;
114}
115
116namespace Qt3DRender {
117
118class QCamera;
119class QMaterial;
120class QShaderProgram;
121class QMesh;
122class QRenderPass;
123class QAbstractShapeMesh;
124struct GraphicsApiFilterData;
125class QSceneImporter;
126
127#if QT_CONFIG(qt3d_profile_jobs)
128namespace Debug {
129class CommandExecuter;
130}
131#endif
132
133namespace Render {
134
135class CameraLens;
136class SubmissionContext;
137class FrameGraphNode;
138class Material;
139class Technique;
140class Shader;
141class Entity;
142class RenderCommand;
143class RenderQueue;
144class RenderView;
145class Effect;
146class RenderPass;
147class RenderThread;
148class CommandThread;
149class RenderStateSet;
150class VSyncFrameAdvanceService;
151class PickEventFilter;
152class NodeManagers;
153class ShaderCache;
154
155class UpdateLevelOfDetailJob;
156typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
157
158using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
159using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>;
160
161class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
162{
163public:
164 explicit Renderer(QRenderAspect::RenderType type);
165 ~Renderer();
166
167 void dumpInfo() const override;
168 API api() const override { return AbstractRenderer::OpenGL; }
169
170 qint64 time() const override;
171 void setTime(qint64 time) override;
172
173 void setNodeManagers(NodeManagers *managers) override;
174 void setServices(Qt3DCore::QServiceLocator *services) override;
175 void setSurfaceExposed(bool exposed) override;
176
177 NodeManagers *nodeManagers() const override;
178 Qt3DCore::QServiceLocator *services() const override { return m_services; }
179
180 void initialize() override;
181 void shutdown() override;
182 void releaseGraphicsResources() override;
183
184 void render() override;
185 void doRender(bool scene3dBlocking = false) override;
186 void cleanGraphicsResources() override;
187
188 bool isRunning() const override { return m_running.load(); }
189
190 void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *sgRoot) override;
191 Entity *sceneRoot() const override { return m_renderSceneRoot; }
192
193 FrameGraphNode *frameGraphRoot() const override;
194 RenderQueue *renderQueue() const { return m_renderQueue; }
195
196 void markDirty(BackendNodeDirtySet changes, BackendNode *node) override;
197 BackendNodeDirtySet dirtyBits() override;
198
199#if defined(QT_BUILD_INTERNAL)
200 void clearDirtyBits(BackendNodeDirtySet changes) override;
201#endif
202 bool shouldRender() override;
203 void skipNextFrame() override;
204
205 QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override;
206 QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
207 Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override;
208 Qt3DCore::QAspectJobPtr rayCastingJob() override;
209 Qt3DCore::QAspectJobPtr syncLoadingJobs() override;
210 Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override;
211
212 QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const;
213
214 inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; }
215 inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const { return m_updateShaderDataTransformJob; }
216 inline CalculateBoundingVolumeJobPtr calculateBoundingVolumeJob() const { return m_calculateBoundingVolumeJob; }
217 inline UpdateTreeEnabledJobPtr updateTreeEnabledJob() const { return m_updateTreeEnabledJob; }
218 inline UpdateWorldTransformJobPtr updateWorldTransformJob() const { return m_worldTransformJob; }
219 inline UpdateWorldBoundingVolumeJobPtr updateWorldBoundingVolumeJob() const { return m_updateWorldBoundingVolumeJob; }
220 inline UpdateLevelOfDetailJobPtr updateLevelOfDetailJob() const { return m_updateLevelOfDetailJob; }
221 inline UpdateMeshTriangleListJobPtr updateMeshTriangleListJob() const { return m_updateMeshTriangleListJob; }
222 inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; }
223 inline SynchronizerJobPtr syncLoadingJobs() const { return m_syncLoadingJobs; }
224 inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; }
225 inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; }
226 inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
227 inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
228 inline Qt3DCore::QAspectJobPtr sendTextureChangesToFrontendJob() const { return m_sendTextureChangesToFrontendJob; }
229 inline UpdateEntityLayersJobPtr updateEntityLayersJob() const { return m_updateEntityLayersJob; }
230
231 Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override;
232
233 void registerEventFilter(Qt3DCore::QEventFilterService *service) override;
234
235 void setSettings(RenderSettings *settings) override;
236 RenderSettings *settings() const override;
237 QOpenGLContext *shareContext() const override;
238
239
240 // Executed in secondary GL thread
241 void loadShader(Shader *shader, Qt3DRender::Render::HShader shaderHandle) override;
242
243
244 void updateGLResources();
245 void updateTexture(Texture *texture);
246 void cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId);
247 void downloadGLBuffers();
248 void blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId,
249 Qt3DCore::QNodeId outputRenderTargetId,
250 QRect inputRect,
251 QRect outputRect,
252 GLuint defaultFramebuffer);
253
254 void prepareCommandsSubmission(const QVector<RenderView *> &renderViews);
255 bool executeCommandsSubmission(const RenderView *rv);
256 bool updateVAOWithAttributes(Geometry *geometry,
257 RenderCommand *command,
258 Shader *shader,
259 bool forceUpdate);
260
261 bool requiresVAOAttributeUpdate(Geometry *geometry,
262 RenderCommand *command) const;
263
264 void setOpenGLContext(QOpenGLContext *context) override;
265 const GraphicsApiFilterData *contextInfo() const;
266 SubmissionContext *submissionContext() const;
267
268 inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; }
269
270 QList<QPair<QObject*, QMouseEvent>> pendingPickingEvents() const;
271 QList<QKeyEvent> pendingKeyEvents() const;
272
273 void addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId);
274 const QVector<Qt3DCore::QNodeId> takePendingRenderCaptureSendRequests();
275
276 void enqueueRenderView(RenderView *renderView, int submitOrder);
277 bool isReadyToSubmit();
278
279 QVariant executeCommand(const QStringList &args) override;
280 void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) override;
281 QSurfaceFormat format() override;
282
283 struct ViewSubmissionResultData
284 {
285 ViewSubmissionResultData()
286 : lastBoundFBOId(0)
287 , surface(nullptr)
288 {}
289
290 uint lastBoundFBOId;
291 QSurface *surface;
292 };
293
294 ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
295
296 RendererCache *cache() { return &m_cache; }
297
298#ifdef QT3D_RENDER_UNIT_TESTS
299public:
300#else
301
302private:
303#endif
304 bool canRender() const;
305
306 Qt3DCore::QServiceLocator *m_services;
307 NodeManagers *m_nodesManager;
308
309 // Frame graph root
310 Qt3DCore::QNodeId m_frameGraphRootUuid;
311
312 Entity *m_renderSceneRoot;
313
314 // Fail safe values that we can use if a RenderCommand
315 // is missing a shader
316 RenderStateSet *m_defaultRenderStateSet;
317 ShaderParameterPack m_defaultUniformPack;
318
319 QScopedPointer<SubmissionContext> m_submissionContext;
320 QSurfaceFormat m_format;
321
322 RenderQueue *m_renderQueue;
323 QScopedPointer<RenderThread> m_renderThread;
324 QScopedPointer<CommandThread> m_commandThread;
325 QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService;
326
327 QSemaphore m_submitRenderViewsSemaphore;
328 QSemaphore m_waitForInitializationToBeCompleted;
329 QMutex m_hasBeenInitializedMutex;
330
331 QAtomicInt m_running;
332
333 QScopedPointer<PickEventFilter> m_pickEventFilter;
334
335 QVector<Attribute *> m_dirtyAttributes;
336 QVector<Geometry *> m_dirtyGeometry;
337 QAtomicInt m_exposed;
338
339 struct DirtyBits {
340 BackendNodeDirtySet marked = 0; // marked dirty since last job build
341 BackendNodeDirtySet remaining = 0; // remaining dirty after jobs have finished
342 };
343 DirtyBits m_dirtyBits;
344
345 QAtomicInt m_lastFrameCorrect;
346 QOpenGLContext *m_glContext;
347 QOpenGLContext *m_shareContext;
348 mutable QMutex m_shareContextMutex;
349 ShaderCache *m_shaderCache;
350 PickBoundingVolumeJobPtr m_pickBoundingVolumeJob;
351 RayCastingJobPtr m_rayCastingJob;
352
353 qint64 m_time;
354
355 RenderSettings *m_settings;
356
357 UpdateShaderDataTransformJobPtr m_updateShaderDataTransformJob;
358 FrameCleanupJobPtr m_cleanupJob;
359 UpdateWorldTransformJobPtr m_worldTransformJob;
360 ExpandBoundingVolumeJobPtr m_expandBoundingVolumeJob;
361 CalculateBoundingVolumeJobPtr m_calculateBoundingVolumeJob;
362 UpdateWorldBoundingVolumeJobPtr m_updateWorldBoundingVolumeJob;
363 UpdateTreeEnabledJobPtr m_updateTreeEnabledJob;
364 SendRenderCaptureJobPtr m_sendRenderCaptureJob;
365 SendBufferCaptureJobPtr m_sendBufferCaptureJob;
366 UpdateSkinningPaletteJobPtr m_updateSkinningPaletteJob;
367 UpdateLevelOfDetailJobPtr m_updateLevelOfDetailJob;
368 UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob;
369 FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob;
370 UpdateEntityLayersJobPtr m_updateEntityLayersJob;
371 UpdateEntityHierarchyJobPtr m_updateEntityHierarchyJob;
372
373 QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests;
374
375 void performDraw(RenderCommand *command);
376 void performCompute(const RenderView *rv, RenderCommand *command);
377 void createOrUpdateVAO(RenderCommand *command,
378 HVao *previousVAOHandle,
379 OpenGLVertexArrayObject **vao);
380
381 GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob;
382 GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
383 GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
384 GenericLambdaJobPtr<std::function<void ()>> m_sendTextureChangesToFrontendJob;
385 GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob;
386 IntrospectShadersJobPtr m_introspectShaderJob;
387
388 SynchronizerJobPtr m_syncLoadingJobs;
389
390 void lookForAbandonedVaos();
391 void lookForDirtyBuffers();
392 void lookForDownloadableBuffers();
393 void lookForDirtyTextures();
394 void reloadDirtyShaders();
395 void sendTextureChangesToFrontend();
396 void sendSetFenceHandlesToFrontend();
397
398 QMutex m_abandonedVaosMutex;
399 QVector<HVao> m_abandonedVaos;
400
401 QVector<HBuffer> m_dirtyBuffers;
402 QVector<HBuffer> m_downloadableBuffers;
403 QVector<HShader> m_dirtyShaders;
404 QVector<HTexture> m_dirtyTextures;
405 QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
406 QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
407 Qt3DCore::QNodeIdVector m_textureIdsToCleanup;
408
409 bool m_ownedContext;
410
411 OffscreenSurfaceHelper *m_offscreenHelper;
412 QMutex m_offscreenSurfaceMutex;
413
414#if QT_CONFIG(qt3d_profile_jobs)
415 QScopedPointer<Qt3DRender::Debug::CommandExecuter> m_commandExecuter;
416 friend class Qt3DRender::Debug::CommandExecuter;
417#endif
418
419#ifdef QT_BUILD_INTERNAL
420 friend class ::tst_Renderer;
421#endif
422
423 QMetaObject::Connection m_contextConnection;
424 RendererCache m_cache;
425};
426
427} // namespace Render
428} // namespace Qt3DRender
429
430QT_END_NAMESPACE
431
432#endif // QT3DRENDER_RENDER_RENDERER_H
433