1// Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qcomputecommand.h"
5#include "qcomputecommand_p.h"
6
7QT_BEGIN_NAMESPACE
8
9namespace Qt3DRender {
10
11/*!
12 \class Qt3DRender::QComputeCommand
13 \since 5.7
14 \inmodule Qt3DRender
15 \brief QComponent to issue work for the compute shader on GPU.
16
17 A Qt3DRender::QComputeCommand is used to issue work for the compute shader.
18 The compute shader is specified in the QMaterial component of the same entity the
19 QComputeCommand is added to. The workGroupX, workGroupY and workGroupZ properties
20 specify the work group sizes for the compute shader invocation. Qt3DRender::QDispatchCompute
21 node needs to be present in the FrameGraph to actually issue the commands.
22
23 \note If the rendering policy is set to Qt3DRender::QRenderSettings::OnDemand and there are no
24 changes to the scene, the ComputeCommand will not be invoked repeatedly.
25 The Qt3DRender::QRenderSettings::Always render policy must be set for the ComputeCommand
26 to be repeatedly invoked if there are no other changes to the scene that triggers rendering a
27 new frame.
28 */
29
30/*!
31 \qmltype ComputeCommand
32 \since 5.7
33 \inqmlmodule Qt3D.Render
34 \inherits Component3D
35 \instantiates Qt3DRender::QComputeCommand
36 \brief Component to issue work for the compute shader on GPU.
37
38 A ComputeCommand is used to issue work for the compute shader.
39 The compute shader is specified in the Material component of the same entity the
40 ComputeCommand is added to. The workGroupX, workGroupY and workGroupZ properties
41 specify the work group sizes for the compute shader invocation. DispatchCompute
42 node needs to be present in the FrameGraph to actually issue the commands. The execution behavior
43 of the compute command can be controlled with the run type property.
44
45 \note If the rendering policy is set to RenderSettings.OnDemand, the run
46 type is set to Continuous and there are no changes to the scene, the
47 ComputeCommand will not be invoked repeatedly. The RenderSettings.Always
48 render policy must be set for the ComputeCommand to be repeatedly invoked
49 if there are no other changes to the scene that triggers rendering a new
50 frame.
51 */
52
53/*!
54 \qmlproperty int ComputeCommand::workGroupX
55 Specifies X workgroup size.
56 */
57
58/*!
59 \qmlproperty enumeration ComputeCommand::runType
60
61 Specifies whether the compute command should be performed every frame or
62 manually triggered.
63
64 \value ComputeCommand.Continuous Compute command is executed everyframe. This is the
65 default.
66
67 \value ComputeCommand.Manual CompouteCommand is executed for a given number of frames and
68 then the component disables itself.
69 */
70
71/*!
72 \qmlproperty int ComputeCommand::workGroupY
73 Specifies Y workgroup size.
74 */
75
76/*!
77 \qmlproperty int ComputeCommand::workGroupZ
78 Specifies Z workgroup size.
79 */
80
81/*!
82 \property QComputeCommand::workGroupX
83 Specifies X workgroup size.
84 */
85
86/*!
87 \property QComputeCommand::workGroupY
88 Specifies Y workgroup size.
89 */
90
91/*!
92 \property QComputeCommand::workGroupZ
93 Specifies Z workgroup size.
94 */
95
96/*!
97 \property QComputeCommand::runType
98
99 Specifies whether the compute command should be performed every frame or
100 manually triggered.
101
102 If set to Continuous, Compute command is executed everyframe. This is the
103 default.
104
105 If set to Manual CompouteCommand is executed for a given number of frames
106 and then the component disables itself.
107 */
108
109QComputeCommandPrivate::QComputeCommandPrivate()
110 : Qt3DCore::QComponentPrivate()
111 , m_workGroupX(1)
112 , m_workGroupY(1)
113 , m_workGroupZ(1)
114 , m_runType(QComputeCommand::Continuous)
115 , m_frameCount(0)
116{
117}
118
119void QComputeCommandPrivate::setFrameCount(int frameCount)
120{
121 m_frameCount = frameCount;
122 update();
123}
124
125/*!
126 The constructor creates a new Qt3DRender::QComputeCommand instance with the
127 specified \a parent.
128 */
129QComputeCommand::QComputeCommand(Qt3DCore::QNode *parent)
130 : Qt3DCore::QComponent(*new QComputeCommandPrivate, parent)
131{
132}
133
134/*! \internal */
135QComputeCommand::~QComputeCommand()
136{
137}
138
139int QComputeCommand::workGroupX() const
140{
141 Q_D(const QComputeCommand);
142 return d->m_workGroupX;
143}
144
145int QComputeCommand::workGroupY() const
146{
147 Q_D(const QComputeCommand);
148 return d->m_workGroupY;
149}
150
151int QComputeCommand::workGroupZ() const
152{
153 Q_D(const QComputeCommand);
154 return d->m_workGroupZ;
155}
156
157QComputeCommand::RunType QComputeCommand::runType() const
158{
159 Q_D(const QComputeCommand);
160 return d->m_runType;
161}
162
163/*!
164 Sets the workgroup for the first dimension to \a workGroupX.
165 */
166void QComputeCommand::setWorkGroupX(int workGroupX)
167{
168 Q_D(QComputeCommand);
169 if (d->m_workGroupX != workGroupX) {
170 d->m_workGroupX = workGroupX;
171 emit workGroupXChanged();
172 }
173}
174
175/*!
176 Sets the workgroup for the second dimension to \a workGroupY.
177 */
178void QComputeCommand::setWorkGroupY(int workGroupY)
179{
180 Q_D(QComputeCommand);
181 if (d->m_workGroupY != workGroupY) {
182 d->m_workGroupY = workGroupY;
183 emit workGroupYChanged();
184 }
185}
186
187/*!
188 Sets the workgroup for the third dimension to \a workGroupZ.
189 */
190void QComputeCommand::setWorkGroupZ(int workGroupZ)
191{
192 Q_D(QComputeCommand);
193 if (d->m_workGroupZ != workGroupZ) {
194 d->m_workGroupZ = workGroupZ;
195 emit workGroupZChanged();
196 }
197}
198
199void QComputeCommand::setRunType(QComputeCommand::RunType runType)
200{
201 Q_D(QComputeCommand);
202 if (d->m_runType != runType) {
203 d->m_runType = runType;
204 emit runTypeChanged();
205 }
206}
207
208/*!
209 When the run type is set to Manual, calling trigger will make the compute
210 command be executed for the next \a frameCount frames. Upon completion of
211 the execution, the enabled property will be set to false.
212 */
213void QComputeCommand::trigger(int frameCount)
214{
215 if (isEnabled())
216 qWarning() << Q_FUNC_INFO << "is triggered while it hasn't finished executing";
217
218 Q_D(QComputeCommand);
219 d->setFrameCount(frameCount);
220 setEnabled(true);
221}
222
223/*!
224 When the run type is set to Manual, calling trigger will make the compute
225 command be executed for the next \a frameCount frames. Upon completion of
226 the execution, the enabled property will be set to false. The size of the
227 workgroup previously set will be overridden with \a workGroupX, \a
228 workGroupY, \a workGroupZ.
229 */
230void QComputeCommand::trigger(int workGroupX, int workGroupY, int workGroupZ, int frameCount)
231{
232 if (isEnabled())
233 qWarning() << Q_FUNC_INFO << "is triggered while it hasn't finished executing";
234
235 setWorkGroupX(workGroupX);
236 setWorkGroupY(workGroupY);
237 setWorkGroupZ(workGroupZ);
238 Q_D(QComputeCommand);
239 d->setFrameCount(frameCount);
240 setEnabled(true);
241}
242
243} // Render
244
245QT_END_NAMESPACE
246
247#include "moc_qcomputecommand.cpp"
248

source code of qt3d/src/render/frontend/qcomputecommand.cpp