Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgrenderextensions.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
7#include "private/qssgassert_p.h"
8#include "private/qssglayerrenderdata_p.h"
10
12
13/*!
14 \class QSSGFrameData
15 \inmodule QtQuick3D
16 \since 6.7
17
18 \brief Storage class containing data collected for a frame.
19*/
20
21/*!
22 \return The renderable texture result from \a id. \nullptr if no matching \a id was found.
23
24 \note Even if the function returns a non-null result, the returned QSSGRhiRenderableTexture
25 might not be ready unless the pass rendering to the texture has been executed.
26
27 \note The returned value is only valid within the current frame. On each new frame
28 the renderable will be reset and should therefore be queried again.
29*/
30QSSGFrameData::Result QSSGFrameData::getRenderResult(RenderResult id) const
31{
32 const QSSGRhiRenderableTexture *res = nullptr;
33 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
34 const auto resultKey = QSSGRenderResult::toInternalRenderResultKey(id);
35 if (QSSG_GUARD(data && (std::size(data->renderResults) > size_t(resultKey))))
36 res = data->getRenderResult(resultKey);
37
38 return res ? Result{ res->texture, res->depthStencil } : Result{};
39}
40
41/*!
42 Schedule the given \a results to be made available for this frame.
43
44 This function should only be called during the prepare phase in \l QSSGRenderExtension::prepareData().
45
46 \note The requested results might not be available if the underlying layer does not support
47 them or if the layer does not contain any data that would make it necessary to produce the
48 requested results, in which case \l getRenderResult() will return a empty result.
49
50 \sa getRenderResult()
51*/
52
53void QSSGFrameData::scheduleRenderResults(RenderResults results) const
54{
55 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
56 QSSG_ASSERT(data, return);
57
58 auto &prepResult = data->layerPrepResult;
59
60 if (prepResult.getState() != QSSGLayerRenderPreparationResult::State::DataPrep) {
61 qWarning("QSSGFrameData::requestRenderResults: "
62 "Requesting render results should only be done during the prepare phase in prepareData().");
63 return;
64 }
65
66 if (results.testFlag(QSSGFrameData::RenderResult::DepthTexture))
67 prepResult.flags.setRequiresDepthTexture(true);
68 if (results.testFlag(QSSGFrameData::RenderResult::ScreenTexture))
69 prepResult.flags.setRequiresScreenTexture(true);
70 if (results.testFlag(RenderResult::AoTexture)) {
71 // NOTE: AO depends on the depth texture
72 prepResult.flags.setRequiresSsaoPass(true);
73 prepResult.flags.setRequiresDepthTexture(true);
74 }
75 if (results.testFlag(RenderResult::NormalTexture))
76 prepResult.flags.setRequiresNormalTexture(true);
77}
78
79qsizetype QSSGFrameData::getAttachmentCount(QSSGResourceId userPassId) const
80{
81 QSSGRenderUserPass *userPassNode = QSSGRenderGraphObjectUtils::getResource<QSSGRenderUserPass>(userPassId);
82 QSSG_ASSERT(userPassNode && userPassNode->type == QSSGRenderGraphObject::Type::RenderPass, return 0);
83
84 QSSGRhiRenderableTextureV2Ptr res;
85 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
86 if (QSSG_GUARD(data))
87 res = data->requestUserRenderPassManager()->getUserPassTexureResult(*userPassNode);
88
89 return res->colorAttachmentCount();
90}
91
92/*!
93 \return The renderable texture result from a user defined render pass with the given \a userPassId.
94 If no matching user pass could be found, or if the user pass did not produce any renderable textures,
95 an invalid Result is returned.
96
97 \note Even if the function returns a non-null result, the returned QSSGRhiRenderableTexture
98 might not be ready unless the pass rendering to the texture has been executed.
99
100 \note The returned value is only valid within the current frame. On each new frame
101 the renderable will be reset and should therefore be queried again.
102*/
103QSSGFrameData::Result QSSGFrameData::getRenderResult(QSSGResourceId userPassId, AttachmentSelector attachment) const
104{
105 QSSGRenderUserPass *userPassNode = QSSGRenderGraphObjectUtils::getResource<QSSGRenderUserPass>(userPassId);
106 QSSG_ASSERT(userPassNode && userPassNode->type == QSSGRenderGraphObject::Type::RenderPass, return Result{});
107
108 QSSGRhiRenderableTextureV2Ptr res;
109 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
110 if (QSSG_GUARD(data))
111 res = data->requestUserRenderPassManager()->getUserPassTexureResult(*userPassNode);
112
113 Result result;
114
115 const quint32 attachmentSelector = static_cast<quint32>(attachment);
116
117 if (res && res->isValid()) {
118 if (const qsizetype attachmentCount = res->colorAttachmentCount(); attachmentCount > qsizetype(attachmentSelector)) {
119 // Get the selected attachment
120 result = { res->getColorTexture(attachmentSelector)->texture().get(), res->getDepthStencil().get() };
121 } else {
122 qWarning() << "Requested attachment" << attachmentSelector << "but user pass only has" << attachmentCount << "attachments.";
123 }
124 }
125
126 return result;
127}
128
129/*!
130 \internal
131*/
132void QSSGFrameData::scheduleRenderResults(QSSGResourceId userPassId) const
133{
134 QSSGRenderUserPass *userPassNode = QSSGRenderGraphObjectUtils::getResource<QSSGRenderUserPass>(userPassId);
135 QSSG_ASSERT(userPassNode && userPassNode->type == QSSGRenderGraphObject::Type::RenderPass, return);
136
137 QSSGLayerRenderData *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
138 if (QSSG_GUARD(data))
139 data->requestUserRenderPassManager()->scheduleUserPass(userPassNode);
140}
141
142/*!
143 \return Base pipeline state for this frame
144 */
145QSSGRhiGraphicsPipelineState QSSGFrameData::getPipelineState() const
146{
147 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
148 QSSG_ASSERT(data, return {});
149 return data->getPipelineState();
150}
151
152/*!
153 \return The active camera for the scene, or null if non could be found.
154*/
155QSSGCameraId QSSGFrameData::activeCamera() const
156{
157 QSSGCameraId ret { QSSGCameraId::Invalid };
158 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
159 QSSG_ASSERT(data, return ret);
160 if (auto *ac = data->activeCamera())
161 ret = QSSGRenderGraphObjectUtils::getCameraId(*ac);
162
163 return ret;
164}
165
166QSSGRenderContextInterface *QSSGFrameData::contextInterface() const
167{
168 return m_ctx;
169}
170
171/*!
172 \return A list of layer nodes that match the \a layerMask and \a typeMask.
173 */
174QSSGNodeIdList QSSGFrameData::getLayerNodes(quint32 layerMask, TypeMask typeMask) const
175{
176 QSSG_ASSERT(m_ctx, return {});
177
178 auto *layer = getCurrent();
179 QSSG_ASSERT_X(layer, "No active layer for renderer!", return {});
180 const auto &layerNodes = layer->layerNodes;
181
182 return QSSGLayerRenderData::filter(layerNodes, layerMask, typeMask);;
183}
184
185/*!
186 \return A list of layer nodes for the given \a cameraId that match the \a typeMask.
187 If the camera does not have a layer mask, an empty list is returned.
188*/
189QSSGNodeIdList QSSGFrameData::getLayerNodes(QSSGCameraId cameraId, TypeMask typeMask) const
190{
191 auto *camera = QSSGRenderGraphObjectUtils::getNode<QSSGRenderCamera>(QSSGNodeId(cameraId));
192 const quint32 layerMask = camera ? camera->tag.value() : 0 /* LayerNone */;
193
194 return (layerMask != 0) ? getLayerNodes(layerMask, typeMask) : QSSGNodeIdList{};
195}
196
197void QSSGFrameData::clear()
198{
199
200}
201
202QSSGLayerRenderData *QSSGFrameData::getCurrent() const
203{
204 return QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
205}
206
207QSSGFrameData::QSSGFrameData(QSSGRenderContextInterface *ctx)
208 : m_ctx(ctx)
209{
210
211}
212
213/*!
214 \class QSSGRenderExtension
215 \inmodule QtQuick3D
216 \since 6.7
217
218 \brief Base class for extension backend node implementations.
219
220 \sa QQuick3DRenderExtension
221*/
222
223/*!
224 Constructor that allows users to specifying a user-type and flags for an extension.
225
226 \note For user-defined extensions the type must be a combination of \l QSSGRenderGraphObject::BaseType::User
227 and a value between 0 and 4095.
228
229 \note The \l QSSGRenderGraphObject::BaseType::Extension type is automatically added to the given \a inType.
230
231 \note The \a inFlags must include \l Flags::HasGraphicsResources if the extension
232 allocates graphics resources.
233
234 */
235QSSGRenderExtension::QSSGRenderExtension(Type inType, FlagT inFlags)
236 : QSSGRenderGraphObject(static_cast<Type>(TypeT(inType) | TypeT(QSSGRenderGraphObject::BaseType::Extension)), inFlags)
237{
238 Q_ASSERT_X((QSSGRenderGraphObjectUtils::getBaseType(type) == QSSGRenderGraphObject::BaseType::Extension) ||
239 (QSSGRenderGraphObjectUtils::getBaseType(type) == (QSSGRenderGraphObject::BaseType::Extension | QSSGRenderGraphObject::BaseType::User)),
240 "QSSGRenderExtension()",
241 "The type must be a combination of QSSGRenderGraphObject::BaseType::Extension "
242 "and optionally QSSGRenderGraphObject::BaseType::User.");
243}
244
245QSSGRenderExtension::QSSGRenderExtension()
246 : QSSGRenderGraphObject(QSSGRenderGraphObject::Type::RenderExtension, FlagT(Flags::HasGraphicsResources))
247{
248
249}
250
251QSSGRenderExtension::~QSSGRenderExtension()
252{
253
254}
255
256/*!
257 \enum QSSGRenderExtension::RenderMode
258
259 Specifies the render extension mode.
260
261 \value Standalone The rendering code is recorded in full during the render prepare phase.
262 This will usually imply that there are some output crated for a preceding render extension(s).
263 When this mode is used the \l prepareRender() and \l render() functions are both called during
264 the frame's prepare phase.
265
266 \value Main The rendering code is recorded within the main render pass. In this mode the
267 \l prepareRender() is called in the frame's prepare phase while \l render() is called the frame's render phase.
268
269*/
270
271/*!
272 \enum QSSGRenderExtension::RenderStage
273
274 Specifies the order the extension will be called.
275
276 \value PreColor The rendering code is recorded and executed before the main (color) pass.
277 \value PostColor The rendering code is recorded and executed after the main (color) pass.
278
279 \note The \l RenderStage is only relevant when the \l RenderMode is set to \l {RenderMode::Main}{Main}.
280*/
281
282
283/*!
284 Called after scene \a data is collected, but before any render data or rendering in the current
285 frame has been done.
286
287 \return Dirty state. Return \c true if the there are dirty data
288 that needs to be rendered.
289
290 \note Much of the data created/collected from the engine during the prepare and render phases
291 is per-frame and should be released or assumed released at the start of the next frame
292
293 \sa QSSGFrameData
294*/
295bool QSSGRenderExtension::prepareData(QSSGFrameData &data)
296{
297 Q_UNUSED(data);
298 return false;
299}
300
301/*!
302 Prepare data for rendering. Build and collect \a data needed for rendering. Any render extension
303 scheduled before this one has been processed. In addition; any render extension of
304 mode \l RenderMode::Standalone will, if successful, have been completed in full.
305
306 \note Much of the data created/collected from the engine during the prepare and render phases
307 is per-frame and should be released or assumed released at the start of the next frame
308
309 \sa QSSGFrameData
310*/
311void QSSGRenderExtension::prepareRender(QSSGFrameData &data)
312{
313 Q_UNUSED(data);
314}
315
316/*!
317 Record the render pass. Depending on the extensions \l {RenderMode}{mode} this function will be called
318 during the frame's prepare or render phase.
319
320 Use \a data to gain access to the render context from which the active QRhi object can be queried.
321
322 \sa QSSGRenderExtension::RenderMode
323*/
324void QSSGRenderExtension::render(QSSGFrameData &data)
325{
326 Q_UNUSED(data);
327}
328
329/*!
330 Called each time a new frame starts. Any data from the previous frame should be cleared at
331 this point.
332*/
333void QSSGRenderExtension::resetForFrame()
334{
335
336}
337
338/*!
339 \return The render mode used for this extension.
340 */
341QSSGRenderExtension::RenderMode QSSGRenderExtension::mode() const
342{
343 return RenderMode::Main;
344}
345
346/*!
347 \return The stage in which this render extension will be used.
348*/
349QSSGRenderExtension::RenderStage QSSGRenderExtension::stage() const
350{
351 return RenderStage::PostColor;
352}
353
354/*!
355 \class QSSGRenderTextureProviderExtension
356 \inmodule QtQuick3D
357 \since 6.11
358
359 \brief Base class for texture providers backend node implementations.
360
361 \note This class is meant to be used together with \l QQuick3DTextureProviderExtension.
362 and the \l mode and \l stage is always \c Standalone and \c PostColor respectively.
363
364 \sa QQuick3DTextureProviderExtension
365*/
366
367QSSGRenderTextureProviderExtension::QSSGRenderTextureProviderExtension()
368 : QSSGRenderExtension(QSSGRenderGraphObject::Type::TextureProvider, FlagT(Flags::HasGraphicsResources) | FlagT(QSSGRenderGraphObjectUtils::InternalFlags::AutoRegisterExtension))
369{
370
371}
372
373QSSGRenderTextureProviderExtension::~QSSGRenderTextureProviderExtension()
374{
375
376}
377
378QSSGRenderExtension::RenderStage QSSGRenderTextureProviderExtension::stage() const { return QSSGRenderExtension::RenderStage::PreColor; }
379
380QSSGRenderExtension::RenderMode QSSGRenderTextureProviderExtension::mode() const { return QSSGRenderExtension::RenderMode::Standalone; }
381
382QT_END_NAMESPACE
Combined button and popup list for selecting options.