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 QSSGRenderExtension::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 \fn QSSGFrameData::Result QSSGFrameData::getRenderResult(QSSGResourceId userPassId, AttachmentSelector attachment) const
94
95 \return The renderable texture result from a user defined render pass with the given \a userPassId.
96 If no matching user pass could be found, or if the user pass did not produce any renderable textures,
97 an invalid Result is returned.
98
99 \note Even if the function returns a non-null result, the returned QSSGRhiRenderableTexture
100 might not be ready unless the pass rendering to the texture has been executed.
101
102 \note The returned value is only valid within the current frame. On each new frame
103 the renderable will be reset and should therefore be queried again.
104*/
105QSSGFrameData::Result QSSGFrameData::getRenderResult(QSSGResourceId userPassId, AttachmentSelector attachment) const
106{
107 QSSGRenderUserPass *userPassNode = QSSGRenderGraphObjectUtils::getResource<QSSGRenderUserPass>(userPassId);
108 QSSG_ASSERT(userPassNode && userPassNode->type == QSSGRenderGraphObject::Type::RenderPass, return Result{});
109
110 QSSGRhiRenderableTextureV2Ptr res;
111 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
112 if (QSSG_GUARD(data))
113 res = data->requestUserRenderPassManager()->getUserPassTexureResult(*userPassNode);
114
115 Result result;
116
117 const quint32 attachmentSelector = static_cast<quint32>(attachment);
118
119 if (res && res->isValid()) {
120 if (const qsizetype attachmentCount = res->colorAttachmentCount(); attachmentCount > qsizetype(attachmentSelector)) {
121 // Get the selected attachment
122 result = { res->getColorTexture(attachmentSelector)->texture().get(), res->getDepthStencil().get() };
123 } else {
124 qWarning() << "Requested attachment" << attachmentSelector << "but user pass only has" << attachmentCount << "attachments.";
125 }
126 }
127
128 return result;
129}
130
131/*!
132 \internal
133*/
134void QSSGFrameData::scheduleRenderResults(QSSGResourceId userPassId) const
135{
136 QSSGRenderUserPass *userPassNode = QSSGRenderGraphObjectUtils::getResource<QSSGRenderUserPass>(userPassId);
137 QSSG_ASSERT(userPassNode && userPassNode->type == QSSGRenderGraphObject::Type::RenderPass, return);
138
139 QSSGLayerRenderData *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
140 if (QSSG_GUARD(data))
141 data->requestUserRenderPassManager()->scheduleUserPass(userPassNode);
142}
143
144/*!
145 \return Base pipeline state for this frame
146 */
147QSSGRhiGraphicsPipelineState QSSGFrameData::getPipelineState() const
148{
149 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
150 QSSG_ASSERT(data, return {});
151 return data->getPipelineState();
152}
153
154/*!
155 \return The active camera for the scene, or null if non could be found.
156*/
157QSSGCameraId QSSGFrameData::activeCamera() const
158{
159 QSSGCameraId ret { QSSGCameraId::Invalid };
160 auto *data = QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
161 QSSG_ASSERT(data, return ret);
162 if (auto *ac = data->activeCamera())
163 ret = QSSGRenderGraphObjectUtils::getCameraId(*ac);
164
165 return ret;
166}
167
168QSSGRenderContextInterface *QSSGFrameData::contextInterface() const
169{
170 return m_ctx;
171}
172
173/*!
174 \return A list of layer nodes that match the \a layerMask and \a typeMask.
175 */
176QSSGNodeIdList QSSGFrameData::getLayerNodes(quint32 layerMask, TypeMask typeMask) const
177{
178 QSSG_ASSERT(m_ctx, return {});
179
180 auto *layer = getCurrent();
181 QSSG_ASSERT_X(layer, "No active layer for renderer!", return {});
182 const auto &layerNodes = layer->layerNodes;
183
184 return QSSGLayerRenderData::filter(layerNodes, layerMask, typeMask);;
185}
186
187/*!
188 \return A list of layer nodes for the given \a cameraId that match the \a typeMask.
189 If the camera does not have a layer mask, an empty list is returned.
190*/
191QSSGNodeIdList QSSGFrameData::getLayerNodes(QSSGCameraId cameraId, TypeMask typeMask) const
192{
193 auto *camera = QSSGRenderGraphObjectUtils::getNode<QSSGRenderCamera>(QSSGNodeId(cameraId));
194 const quint32 layerMask = camera ? camera->tag.value() : 0 /* LayerNone */;
195
196 return (layerMask != 0) ? getLayerNodes(layerMask, typeMask) : QSSGNodeIdList{};
197}
198
199void QSSGFrameData::clear()
200{
201
202}
203
204QSSGLayerRenderData *QSSGFrameData::getCurrent() const
205{
206 return QSSGLayerRenderData::getCurrent(*m_ctx->renderer());
207}
208
209QSSGFrameData::QSSGFrameData(QSSGRenderContextInterface *ctx)
210 : m_ctx(ctx)
211{
212
213}
214
215/*!
216 \class QSSGRenderExtension
217 \inmodule QtQuick3D
218 \since 6.7
219
220 \brief Base class for extension backend node implementations.
221
222 \sa QQuick3DRenderExtension
223*/
224
225/*!
226 Constructor that allows users to specifying a user-type and flags for an extension.
227
228 \note For user-defined extensions the type must be a combination of \l QSSGRenderGraphObject::BaseType::User
229 and a value between 0 and 4095.
230
231 \note The \l QSSGRenderGraphObject::BaseType::Extension type is automatically added to the given \a inType.
232
233 \note The \a inFlags must include \l Flags::HasGraphicsResources if the extension
234 allocates graphics resources.
235
236 */
237QSSGRenderExtension::QSSGRenderExtension(Type inType, FlagT inFlags)
238 : QSSGRenderGraphObject(static_cast<Type>(TypeT(inType) | TypeT(QSSGRenderGraphObject::BaseType::Extension)), inFlags)
239{
240 Q_ASSERT_X((QSSGRenderGraphObjectUtils::getBaseType(type) == QSSGRenderGraphObject::BaseType::Extension) ||
241 (QSSGRenderGraphObjectUtils::getBaseType(type) == (QSSGRenderGraphObject::BaseType::Extension | QSSGRenderGraphObject::BaseType::User)),
242 "QSSGRenderExtension()",
243 "The type must be a combination of QSSGRenderGraphObject::BaseType::Extension "
244 "and optionally QSSGRenderGraphObject::BaseType::User.");
245}
246
247QSSGRenderExtension::QSSGRenderExtension()
248 : QSSGRenderGraphObject(QSSGRenderGraphObject::Type::RenderExtension, FlagT(Flags::HasGraphicsResources))
249{
250
251}
252
253QSSGRenderExtension::~QSSGRenderExtension()
254{
255
256}
257
258/*!
259 \enum QSSGRenderExtension::RenderMode
260
261 Specifies the render extension mode.
262
263 \value Standalone The rendering code is recorded in full during the render prepare phase.
264 This will usually imply that there are some output crated for a preceding render extension(s).
265 When this mode is used the \l prepareRender() and \l render() functions are both called during
266 the frame's prepare phase.
267
268 \value Main The rendering code is recorded within the main render pass. In this mode the
269 \l prepareRender() is called in the frame's prepare phase while \l render() is called the frame's render phase.
270
271*/
272
273/*!
274 \enum QSSGRenderExtension::RenderStage
275
276 Specifies the order the extension will be called.
277
278 \value PreColor The rendering code is recorded and executed before the main (color) pass.
279 \value PostColor The rendering code is recorded and executed after the main (color) pass.
280
281 \note The \l RenderStage is only relevant when the \l RenderMode is set to \l {RenderMode::Main}{Main}.
282*/
283
284
285/*!
286 Called after scene \a data is collected, but before any render data or rendering in the current
287 frame has been done.
288
289 \return Dirty state. Return \c true if the there are dirty data
290 that needs to be rendered.
291
292 \note Much of the data created/collected from the engine during the prepare and render phases
293 is per-frame and should be released or assumed released at the start of the next frame
294
295 \sa QSSGFrameData
296*/
297bool QSSGRenderExtension::prepareData(QSSGFrameData &data)
298{
299 Q_UNUSED(data);
300 return false;
301}
302
303/*!
304 Prepare data for rendering. Build and collect \a data needed for rendering. Any render extension
305 scheduled before this one has been processed. In addition; any render extension of
306 mode \l RenderMode::Standalone will, if successful, have been completed in full.
307
308 \note Much of the data created/collected from the engine during the prepare and render phases
309 is per-frame and should be released or assumed released at the start of the next frame
310
311 \sa QSSGFrameData
312*/
313void QSSGRenderExtension::prepareRender(QSSGFrameData &data)
314{
315 Q_UNUSED(data);
316}
317
318/*!
319 Record the render pass. Depending on the extensions \l {RenderMode}{mode} this function will be called
320 during the frame's prepare or render phase.
321
322 Use \a data to gain access to the render context from which the active QRhi object can be queried.
323
324 \sa QSSGRenderExtension::RenderMode
325*/
326void QSSGRenderExtension::render(QSSGFrameData &data)
327{
328 Q_UNUSED(data);
329}
330
331/*!
332 Called each time a new frame starts. Any data from the previous frame should be cleared at
333 this point.
334*/
335void QSSGRenderExtension::resetForFrame()
336{
337
338}
339
340/*!
341 \return The render mode used for this extension.
342 */
343QSSGRenderExtension::RenderMode QSSGRenderExtension::mode() const
344{
345 return RenderMode::Main;
346}
347
348/*!
349 \return The stage in which this render extension will be used.
350*/
351QSSGRenderExtension::RenderStage QSSGRenderExtension::stage() const
352{
353 return RenderStage::PostColor;
354}
355
356/*!
357 \class QSSGRenderTextureProviderExtension
358 \inmodule QtQuick3D
359 \since 6.11
360
361 \brief Base class for texture providers backend node implementations.
362
363 \note This class is meant to be used together with \l QQuick3DTextureProviderExtension.
364 and the \l mode and \l stage is always \c Standalone and \c PostColor respectively.
365
366 \sa QQuick3DTextureProviderExtension
367*/
368
369QSSGRenderTextureProviderExtension::QSSGRenderTextureProviderExtension()
370 : QSSGRenderExtension(QSSGRenderGraphObject::Type::TextureProvider, FlagT(Flags::HasGraphicsResources) | FlagT(QSSGRenderGraphObjectUtils::InternalFlags::AutoRegisterExtension))
371{
372
373}
374
375QSSGRenderTextureProviderExtension::~QSSGRenderTextureProviderExtension()
376{
377
378}
379
380QSSGRenderExtension::RenderStage QSSGRenderTextureProviderExtension::stage() const { return QSSGRenderExtension::RenderStage::PreColor; }
381
382QSSGRenderExtension::RenderMode QSSGRenderTextureProviderExtension::mode() const { return QSSGRenderExtension::RenderMode::Standalone; }
383
384QT_END_NAMESPACE
Combined button and popup list for selecting options.