1/****************************************************************************
2**
3** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcomputecommand.h"
41#include "qcomputecommand_p.h"
42
43QT_BEGIN_NAMESPACE
44
45namespace Qt3DRender {
46
47/*!
48 \class Qt3DRender::QComputeCommand
49 \since 5.7
50 \inmodule Qt3DRender
51 \brief QComponent to issue work for the compute shader on GPU.
52
53 A Qt3DRender::QComputeCommand is used to issue work for the compute shader.
54 The compute shader is specified in the QMaterial component of the same entity the
55 QComputeCommand is added to. The workGroupX, workGroupY and workGroupZ properties
56 specify the work group sizes for the compute shader invocation. Qt3DRender::QDispatchCompute
57 node needs to be present in the FrameGraph to actually issue the commands.
58
59 \note If the rendering policy is set to Qt3DRender::QRenderSettings::OnDemand and there are no
60 changes to the scene, the ComputeCommand will not be invoked repeatedly.
61 The Qt3DRender::QRenderSettings::Always render policy must be set for the ComputeCommand
62 to be repeatedly invoked if there are no other changes to the scene that triggers rendering a
63 new frame.
64 */
65
66/*!
67 \qmltype ComputeCommand
68 \since 5.7
69 \inqmlmodule Qt3D.Render
70 \inherits Component3D
71 \instantiates Qt3DRender::QComputeCommand
72 \brief Component to issue work for the compute shader on GPU.
73
74 A ComputeCommand is used to issue work for the compute shader.
75 The compute shader is specified in the Material component of the same entity the
76 ComputeCommand is added to. The workGroupX, workGroupY and workGroupZ properties
77 specify the work group sizes for the compute shader invocation. DispatchCompute
78 node needs to be present in the FrameGraph to actually issue the commands. The execution behavior
79 of the compute command can be controlled with the run type property.
80
81 \note If the rendering policy is set to RenderSettings.OnDemand, the run
82 type is set to Continuous and there are no changes to the scene, the
83 ComputeCommand will not be invoked repeatedly. The RenderSettings.Always
84 render policy must be set for the ComputeCommand to be repeatedly invoked
85 if there are no other changes to the scene that triggers rendering a new
86 frame.
87 */
88
89/*!
90 \qmlproperty int ComputeCommand::workGroupX
91 Specifies X workgroup size.
92 */
93
94/*!
95 \qmlproperty enumeration ComputeCommand::runType
96
97 Specifies whether the compute command should be performed every frame or
98 manually triggered.
99
100 \value ComputeCommand.Continuous Compute command is executed everyframe. This is the
101 default.
102
103 \value ComputeCommand.Manual CompouteCommand is executed for a given number of frames and
104 then the component disables itself.
105 */
106
107/*!
108 \qmlproperty int ComputeCommand::workGroupY
109 Specifies Y workgroup size.
110 */
111
112/*!
113 \qmlproperty int ComputeCommand::workGroupZ
114 Specifies Z workgroup size.
115 */
116
117/*!
118 \property QComputeCommand::workGroupX
119 Specifies X workgroup size.
120 */
121
122/*!
123 \property QComputeCommand::workGroupY
124 Specifies Y workgroup size.
125 */
126
127/*!
128 \property QComputeCommand::workGroupZ
129 Specifies Z workgroup size.
130 */
131
132/*!
133 \property QComputeCommand::runType
134
135 Specifies whether the compute command should be performed every frame or
136 manually triggered.
137
138 If set to Continuous, Compute command is executed everyframe. This is the
139 default.
140
141 If set to Manual CompouteCommand is executed for a given number of frames
142 and then the component disables itself.
143 */
144
145QComputeCommandPrivate::QComputeCommandPrivate()
146 : Qt3DCore::QComponentPrivate()
147 , m_workGroupX(1)
148 , m_workGroupY(1)
149 , m_workGroupZ(1)
150 , m_runType(QComputeCommand::Continuous)
151 , m_frameCount(0)
152{
153}
154
155void QComputeCommandPrivate::setFrameCount(int frameCount)
156{
157 m_frameCount = frameCount;
158 update();
159}
160
161/*!
162 The constructor creates a new Qt3DRender::QComputeCommand instance with the
163 specified \a parent.
164 */
165QComputeCommand::QComputeCommand(Qt3DCore::QNode *parent)
166 : Qt3DCore::QComponent(*new QComputeCommandPrivate, parent)
167{
168}
169
170/*! \internal */
171QComputeCommand::~QComputeCommand()
172{
173}
174
175int QComputeCommand::workGroupX() const
176{
177 Q_D(const QComputeCommand);
178 return d->m_workGroupX;
179}
180
181int QComputeCommand::workGroupY() const
182{
183 Q_D(const QComputeCommand);
184 return d->m_workGroupY;
185}
186
187int QComputeCommand::workGroupZ() const
188{
189 Q_D(const QComputeCommand);
190 return d->m_workGroupZ;
191}
192
193QComputeCommand::RunType QComputeCommand::runType() const
194{
195 Q_D(const QComputeCommand);
196 return d->m_runType;
197}
198
199/*!
200 Sets the workgroup for the first dimension to \a workGroupX.
201 */
202void QComputeCommand::setWorkGroupX(int workGroupX)
203{
204 Q_D(QComputeCommand);
205 if (d->m_workGroupX != workGroupX) {
206 d->m_workGroupX = workGroupX;
207 emit workGroupXChanged();
208 }
209}
210
211/*!
212 Sets the workgroup for the second dimension to \a workGroupY.
213 */
214void QComputeCommand::setWorkGroupY(int workGroupY)
215{
216 Q_D(QComputeCommand);
217 if (d->m_workGroupY != workGroupY) {
218 d->m_workGroupY = workGroupY;
219 emit workGroupYChanged();
220 }
221}
222
223/*!
224 Sets the workgroup for the third dimension to \a workGroupZ.
225 */
226void QComputeCommand::setWorkGroupZ(int workGroupZ)
227{
228 Q_D(QComputeCommand);
229 if (d->m_workGroupZ != workGroupZ) {
230 d->m_workGroupZ = workGroupZ;
231 emit workGroupZChanged();
232 }
233}
234
235void QComputeCommand::setRunType(QComputeCommand::RunType runType)
236{
237 Q_D(QComputeCommand);
238 if (d->m_runType != runType) {
239 d->m_runType = runType;
240 emit runTypeChanged();
241 }
242}
243
244/*!
245 When the run type is set to Manual, calling trigger will make the compute
246 command be executed for the next \a frameCount frames. Upon completion of
247 the execution, the enabled property will be set to false.
248 */
249void QComputeCommand::trigger(int frameCount)
250{
251 if (isEnabled())
252 qWarning() << Q_FUNC_INFO << "is triggered while it hasn't finished executing";
253
254 Q_D(QComputeCommand);
255 d->setFrameCount(frameCount);
256 setEnabled(true);
257}
258
259/*!
260 When the run type is set to Manual, calling trigger will make the compute
261 command be executed for the next \a frameCount frames. Upon completion of
262 the execution, the enabled property will be set to false. The size of the
263 workgroup previously set will be overridden with \a workGroupX, \a
264 workGroupY, \a workGroupZ.
265 */
266void QComputeCommand::trigger(int workGroupX, int workGroupY, int workGroupZ, int frameCount)
267{
268 if (isEnabled())
269 qWarning() << Q_FUNC_INFO << "is triggered while it hasn't finished executing";
270
271 setWorkGroupX(workGroupX);
272 setWorkGroupY(workGroupY);
273 setWorkGroupZ(workGroupZ);
274 Q_D(QComputeCommand);
275 d->setFrameCount(frameCount);
276 setEnabled(true);
277}
278
279Qt3DCore::QNodeCreatedChangeBasePtr QComputeCommand::createNodeCreationChange() const
280{
281 auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QComputeCommandData>::create(arguments: this);
282 auto &data = creationChange->data;
283 Q_D(const QComputeCommand);
284 data.workGroupX = d->m_workGroupX;
285 data.workGroupY = d->m_workGroupY;
286 data.workGroupZ = d->m_workGroupZ;
287 data.runType = d->m_runType;
288 data.frameCount = d->m_frameCount;
289 return creationChange;
290}
291
292} // Render
293
294QT_END_NAMESPACE
295

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