1 | // Copyright (C) 2019 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #ifndef QSSGSCENERENDERER_H |
5 | #define QSSGSCENERENDERER_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <ssg/qssgrendercontextcore.h> |
19 | |
20 | #include <qsgtextureprovider.h> |
21 | #include <qsgrendernode.h> |
22 | #include <QSGSimpleTextureNode> |
23 | |
24 | #include <QtQuick3D/private/qquick3dviewport_p.h> |
25 | #include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h> |
26 | #include <QtQuick3DRuntimeRender/private/qssgrhieffectsystem_p.h> |
27 | #include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h> |
28 | |
29 | #include <QtCore/qpointer.h> |
30 | |
31 | #include <optional> |
32 | |
33 | #include "qquick3dsceneenvironment_p.h" |
34 | |
35 | QT_BEGIN_NAMESPACE |
36 | |
37 | |
38 | class QQuick3DSceneManager; |
39 | class QQuick3DViewport; |
40 | struct QSSGRenderLayer; |
41 | |
42 | class QQuick3DSceneRenderer |
43 | { |
44 | using PickResultList = QVarLengthArray<QSSGRenderPickResult, 20>; |
45 | public: |
46 | explicit QQuick3DSceneRenderer(const std::shared_ptr<QSSGRenderContextInterface> &rci); |
47 | ~QQuick3DSceneRenderer(); |
48 | |
49 | static QSSGRenderLayer::TonemapMode getTonemapMode(const QQuick3DSceneEnvironment &environment) |
50 | { |
51 | if (environment.useBuiltinTonemapper()) |
52 | return QSSGRenderLayer::TonemapMode(environment.tonemapMode()); |
53 | |
54 | // Special case for the extend scene environment... |
55 | return (environment.tonemapMode() != QQuick3DSceneEnvironment::QQuick3DEnvironmentTonemapModes::TonemapModeNone) ? QSSGRenderLayer::TonemapMode::Custom |
56 | : QSSGRenderLayer::TonemapMode::None; |
57 | } |
58 | |
59 | protected: |
60 | QRhiTexture *renderToRhiTexture(QQuickWindow *qw); |
61 | void beginFrame(); |
62 | void endFrame(); |
63 | void rhiPrepare(const QRect &viewport, qreal displayPixelRatio); |
64 | void rhiRender(); |
65 | void synchronize(QQuick3DViewport *view3D, const QSize &size, float dpr); |
66 | void invalidateFramebufferObject(); |
67 | QSize surfaceSize() const { return m_surfaceSize; } |
68 | void releaseCachedResources(); |
69 | |
70 | std::optional<QSSGRenderRay> getRayFromViewportPos(const QPointF &pos); |
71 | PickResultList syncPick(const QSSGRenderRay &ray); |
72 | PickResultList syncPickOne(const QSSGRenderRay &ray, QSSGRenderNode *node); |
73 | PickResultList syncPickSubset(const QSSGRenderRay &ray, QVarLengthArray<QSSGRenderNode *> subset); |
74 | PickResultList syncPickAll(const QSSGRenderRay &ray); |
75 | |
76 | void setGlobalPickingEnabled(bool isEnabled); |
77 | |
78 | QQuick3DRenderStats *renderStats(); |
79 | |
80 | private: |
81 | void releaseAaDependentRhiResources(); |
82 | void updateLayerNode(QQuick3DViewport *view3D, const QList<QSSGRenderGraphObject *> &resourceLoaders); |
83 | void addNodeToLayer(QSSGRenderNode *node); |
84 | void removeNodeFromLayer(QSSGRenderNode *node); |
85 | std::shared_ptr<QSSGRenderContextInterface> m_sgContext; |
86 | QSSGRenderLayer *m_layer = nullptr; |
87 | QPointer<QQuick3DWindowAttachment> winAttacment; |
88 | QSize m_surfaceSize; |
89 | SGFramebufferObjectNode *fboNode = nullptr; |
90 | bool m_aaIsDirty = true; |
91 | |
92 | // RHI |
93 | QRhiTexture *m_texture = nullptr; |
94 | // the rt is set up to output into m_texture or m_ssaaTexture or m_msaaRenderBuffer(+resolve into m_texture) |
95 | QRhiTextureRenderTarget *m_textureRenderTarget = nullptr; |
96 | QRhiRenderPassDescriptor *m_textureRenderPassDescriptor = nullptr; |
97 | // used by the draw quad that does m_ssaaTexture -> m_texture |
98 | QRhiTextureRenderTarget *m_ssaaTextureToTextureRenderTarget = nullptr; |
99 | QRhiRenderPassDescriptor *m_ssaaTextureToTextureRenderPassDescriptor = nullptr; |
100 | QRhiRenderBuffer *m_msaaRenderBuffer = nullptr; |
101 | QRhiTexture *m_msaaMultiViewRenderBuffer = nullptr; |
102 | QRhiTexture *m_ssaaTexture = nullptr; |
103 | QRhiTexture *m_temporalAATexture = nullptr; |
104 | QRhiTexture *m_prevTempAATexture = nullptr; |
105 | QRhiTextureRenderTarget *m_temporalAARenderTarget = nullptr; |
106 | QRhiRenderPassDescriptor *m_temporalAARenderPassDescriptor = nullptr; |
107 | QRhiRenderBuffer *m_depthStencilBuffer = nullptr; |
108 | QRhiTexture *m_multiViewDepthStencilBuffer = nullptr; |
109 | bool m_textureNeedsFlip = true; |
110 | QSSGRenderLayer::Background m_backgroundMode; |
111 | QColor m_userBackgroundColor = Qt::black; |
112 | QColor m_linearBackgroundColor = Qt::black; |
113 | QColor m_tonemappedBackgroundColor = Qt::black; |
114 | int m_samples = 1; |
115 | QSSGRhiEffectSystem *m_effectSystem = nullptr; |
116 | |
117 | QPointer<QQuick3DRenderStats> m_renderStats; |
118 | |
119 | QSSGRenderNode *m_sceneRootNode = nullptr; |
120 | QSSGRenderNode *m_importRootNode = nullptr; |
121 | |
122 | float m_ssaaMultiplier = 1.5f; |
123 | |
124 | bool m_prepared = false; |
125 | |
126 | int requestedFramesCount = 0; |
127 | bool m_postProcessingStack = false; |
128 | Q_QUICK3D_PROFILE_ID |
129 | |
130 | friend class SGFramebufferObjectNode; |
131 | friend class QQuick3DSGRenderNode; |
132 | friend class QQuick3DSGDirectRenderer; |
133 | friend class QQuick3DViewport; |
134 | friend struct ViewportTransformHelper; |
135 | }; |
136 | |
137 | class Q_QUICK3D_EXPORT QQuick3DRenderLayerHelpers |
138 | { |
139 | public: |
140 | static void updateLayerNodeHelper(const QQuick3DViewport &view3D, QSSGRenderLayer &layerNode, bool &aaIsDirty, bool &temporalIsDirty, float &ssaaMultiplier); |
141 | }; |
142 | |
143 | class SGFramebufferObjectNode final : public QSGTextureProvider, public QSGSimpleTextureNode |
144 | { |
145 | Q_OBJECT |
146 | |
147 | public: |
148 | SGFramebufferObjectNode(); |
149 | ~SGFramebufferObjectNode() override; |
150 | |
151 | void scheduleRender(); |
152 | |
153 | QSGTexture *texture() const override; |
154 | |
155 | void preprocess() override; |
156 | |
157 | public Q_SLOTS: |
158 | void render(); |
159 | |
160 | void handleScreenChange(); |
161 | |
162 | public: |
163 | QQuickWindow *window; |
164 | QQuick3DSceneRenderer *renderer; |
165 | QQuick3DViewport *quickFbo; |
166 | |
167 | bool renderPending; |
168 | bool invalidatePending; |
169 | |
170 | qreal devicePixelRatio; |
171 | }; |
172 | |
173 | class QQuick3DSGRenderNode final : public QSGRenderNode |
174 | { |
175 | public: |
176 | ~QQuick3DSGRenderNode(); |
177 | void prepare() override; |
178 | StateFlags changedStates() const override; |
179 | void render(const RenderState *state) override; |
180 | void releaseResources() override; |
181 | RenderingFlags flags() const override; |
182 | public: |
183 | QQuickWindow *window = nullptr; |
184 | QQuick3DSceneRenderer *renderer = nullptr; |
185 | }; |
186 | |
187 | class QQuick3DSGDirectRenderer : public QObject |
188 | { |
189 | Q_OBJECT |
190 | public: |
191 | enum QQuick3DSGDirectRendererMode { |
192 | Underlay, |
193 | Overlay |
194 | }; |
195 | QQuick3DSGDirectRenderer(QQuick3DSceneRenderer *renderer, QQuickWindow *window, QQuick3DSGDirectRendererMode mode = Underlay); |
196 | ~QQuick3DSGDirectRenderer(); |
197 | |
198 | QQuick3DSceneRenderer *renderer() { return m_renderer; } |
199 | void setViewport(const QRectF &viewport); |
200 | |
201 | void requestRender(); |
202 | void setVisibility(bool visible); |
203 | |
204 | void preSynchronize(); |
205 | |
206 | private Q_SLOTS: |
207 | void prepare(); |
208 | void render(); |
209 | |
210 | private: |
211 | QQuick3DSceneRenderer *m_renderer = nullptr; |
212 | QQuickWindow *m_window = nullptr; |
213 | QRectF m_viewport; |
214 | bool m_isVisible = true; |
215 | QRhiTexture *m_rhiTexture = nullptr; |
216 | bool renderPending = false; |
217 | }; |
218 | |
219 | QT_END_NAMESPACE |
220 | |
221 | #endif // QSSGSCENERENDERER_H |
222 | |