1/****************************************************************************
2**
3** Copyright (C) 2017 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 "qshaderprogrambuilder.h"
41#include "qshaderprogrambuilder_p.h"
42#include "qshaderprogram.h"
43#include <Qt3DCore/qpropertyupdatedchange.h>
44#include <Qt3DRender/private/qurlhelper_p.h>
45#include <QDebug>
46#include <QFile>
47#include <QFileInfo>
48#include <QUrl>
49
50/*!
51 \class Qt3DRender::QShaderProgramBuilder
52 \inmodule Qt3DRender
53 \brief Generates a Shader Program content from loaded graphs.
54 \inherits Qt3DCore::QNode
55 \since 5.10
56
57 A shader program builder consists of several different shader graphs
58 used to generate shader code.
59*/
60
61/*!
62 \qmltype ShaderProgramBuilder
63 \instantiates Qt3DRender::QShaderProgramBuilder
64 \inqmlmodule Qt3D.Render
65 \brief Generates a Shader Program content from loaded graphs.
66 \since 5.10
67
68 A shader program builder consists of several different shader graphs
69 used to generate shader code.
70*/
71
72QT_BEGIN_NAMESPACE
73
74namespace Qt3DRender {
75
76QShaderProgramBuilderPrivate::QShaderProgramBuilderPrivate()
77 : QNodePrivate(),
78 m_shaderProgram(nullptr)
79{
80}
81
82QShaderProgramBuilder::QShaderProgramBuilder(QNode *parent)
83 : QNode(*new QShaderProgramBuilderPrivate, parent)
84{
85}
86
87QShaderProgramBuilder::~QShaderProgramBuilder()
88{
89}
90
91/*! \internal */
92QShaderProgramBuilder::QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, QNode *parent)
93 : QNode(dd, parent)
94{
95}
96
97void QShaderProgramBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
98{
99 Q_D(QShaderProgramBuilder);
100 if (change->type() == Qt3DCore::PropertyUpdated) {
101 const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
102 if (e->propertyName() == QByteArrayLiteral("generatedShaderCode")) {
103 const bool blocked = blockNotifications(true);
104 const QPair<int, QByteArray> data = e->value().value<QPair<int, QByteArray>>();
105
106 switch (data.first) {
107 case QShaderProgram::Vertex: {
108 d->m_vertexShaderCode = data.second;
109 emit vertexShaderCodeChanged(d->m_vertexShaderCode);
110 break;
111 }
112 case QShaderProgram::Fragment:{
113 d->m_fragmentShaderCode = data.second;
114 emit fragmentShaderCodeChanged(d->m_fragmentShaderCode);
115 break;
116 }
117 case QShaderProgram::Geometry: {
118 d->m_geometryShaderCode = data.second;
119 emit geometryShaderCodeChanged(d->m_geometryShaderCode);
120 break;
121 }
122 case QShaderProgram::Compute: {
123 d->m_computeShaderCode = data.second;
124 emit computeShaderCodeChanged(d->m_computeShaderCode);
125 break;
126 }
127 case QShaderProgram::TessellationControl: {
128 d->m_tessControlShaderCode = data.second;
129 emit tessellationControlShaderCodeChanged(d->m_tessControlShaderCode);
130 break;
131 }
132 case QShaderProgram::TessellationEvaluation: {
133 d->m_tessEvalShaderCode = data.second;
134 emit tessellationEvaluationShaderCodeChanged(d->m_tessEvalShaderCode);
135 break;
136 }
137 }
138
139 blockNotifications(blocked);
140 }
141 }
142}
143
144/*!
145 \qmlproperty string ShaderProgramBuilder::shaderProgram
146
147 Holds the shader program on which this builder generates code.
148*/
149/*!
150 \property QShaderProgramBuilder::shaderProgram
151
152 Holds the shader program on which this builder generates code.
153*/
154void QShaderProgramBuilder::setShaderProgram(QShaderProgram *program)
155{
156 Q_D(QShaderProgramBuilder);
157 if (program != d->m_shaderProgram) {
158
159 if (d->m_shaderProgram)
160 d->unregisterDestructionHelper(d->m_shaderProgram);
161
162 // We need to add it as a child of the current node if it has been declared inline
163 // Or not previously added as a child of the current node so that
164 // 1) The backend gets notified about it's creation
165 // 2) When the current node is destroyed, it gets destroyed as well
166 if (program && !program->parent())
167 program->setParent(this);
168 d->m_shaderProgram = program;
169
170 // Ensures proper bookkeeping
171 if (d->m_shaderProgram)
172 d->registerDestructionHelper(d->m_shaderProgram, &QShaderProgramBuilder::setShaderProgram, d->m_shaderProgram);
173
174 emit shaderProgramChanged(program);
175 }
176}
177
178QShaderProgram *QShaderProgramBuilder::shaderProgram() const
179{
180 Q_D(const QShaderProgramBuilder);
181 return d->m_shaderProgram;
182}
183
184/*!
185 \qmlproperty stringlist ShaderProgramBuilder::enabledLayers
186
187 Holds the list of layers this builder will activate on the shader graphs
188 during code generation.
189*/
190/*!
191 \property QShaderProgramBuilder::enabledLayers
192
193 Holds the list of layers this builder will activate on the shader graphs
194 during code generation.
195*/
196void QShaderProgramBuilder::setEnabledLayers(const QStringList &layers)
197{
198 Q_D(QShaderProgramBuilder);
199 if (layers != d->m_enabledLayers) {
200 d->m_enabledLayers = layers;
201 emit enabledLayersChanged(layers);
202 }
203}
204
205QStringList QShaderProgramBuilder::enabledLayers() const
206{
207 Q_D(const QShaderProgramBuilder);
208 return d->m_enabledLayers;
209}
210
211/*!
212 \qmlproperty string ShaderProgram::vertexShaderGraph
213
214 Holds the URL to the vertex shader graph used by this shader program builder.
215*/
216/*!
217 \property QShaderProgramBuilder::vertexShaderGraph
218
219 Holds the URL to the vertex shader graph used by this shader program builder.
220*/
221void QShaderProgramBuilder::setVertexShaderGraph(const QUrl &vertexShaderGraph)
222{
223 Q_D(QShaderProgramBuilder);
224 if (vertexShaderGraph != d->m_vertexShaderGraph) {
225 d->m_vertexShaderGraph = vertexShaderGraph;
226 emit vertexShaderGraphChanged(vertexShaderGraph);
227 }
228}
229
230QUrl QShaderProgramBuilder::vertexShaderGraph() const
231{
232 Q_D(const QShaderProgramBuilder);
233 return d->m_vertexShaderGraph;
234}
235
236/*!
237 \qmlproperty string ShaderProgram::tessellationControlShaderGraph
238
239 Holds the URL to the tesselation control shader graph used by this shader program builder.
240*/
241/*!
242 \property QShaderProgramBuilder::tessellationControlShaderGraph
243
244 Holds the URL to the tesselation control shader graph used by this shader program builder.
245*/
246void QShaderProgramBuilder::setTessellationControlShaderGraph(const QUrl &tessellationControlShaderGraph)
247{
248 Q_D(QShaderProgramBuilder);
249 if (tessellationControlShaderGraph != d->m_tessControlShaderGraph) {
250 d->m_tessControlShaderGraph = tessellationControlShaderGraph;
251 emit tessellationControlShaderGraphChanged(tessellationControlShaderGraph);
252 }
253}
254
255QUrl QShaderProgramBuilder::tessellationControlShaderGraph() const
256{
257 Q_D(const QShaderProgramBuilder);
258 return d->m_tessControlShaderGraph;
259}
260
261/*!
262 \qmlproperty string ShaderProgram::tessellationEvaluationShaderGraph
263
264 Holds the URL to the tesselation evaluation shader graph used by this shader program builder.
265*/
266/*!
267 \property QShaderProgramBuilder::tessellationEvaluationShaderGraph
268
269 Holds the URL to the tesselation evaluation shader graph used by this shader program builder.
270*/
271void QShaderProgramBuilder::setTessellationEvaluationShaderGraph(const QUrl &tessellationEvaluationShaderGraph)
272{
273 Q_D(QShaderProgramBuilder);
274 if (tessellationEvaluationShaderGraph != d->m_tessEvalShaderGraph) {
275 d->m_tessEvalShaderGraph = tessellationEvaluationShaderGraph;
276 emit tessellationEvaluationShaderGraphChanged(tessellationEvaluationShaderGraph);
277 }
278}
279
280QUrl QShaderProgramBuilder::tessellationEvaluationShaderGraph() const
281{
282 Q_D(const QShaderProgramBuilder);
283 return d->m_tessEvalShaderGraph;
284}
285
286/*!
287 \qmlproperty string ShaderProgram::geometryShaderGraph
288
289 Holds the URL to the geometry shader graph used by this shader program builder.
290*/
291/*!
292 \property QShaderProgramBuilder::geometryShaderGraph
293
294 Holds the URL to the geometry shader graph used by this shader program builder.
295*/
296void QShaderProgramBuilder::setGeometryShaderGraph(const QUrl &geometryShaderGraph)
297{
298 Q_D(QShaderProgramBuilder);
299 if (geometryShaderGraph != d->m_geometryShaderGraph) {
300 d->m_geometryShaderGraph = geometryShaderGraph;
301 emit geometryShaderGraphChanged(geometryShaderGraph);
302 }
303}
304
305QUrl QShaderProgramBuilder::geometryShaderGraph() const
306{
307 Q_D(const QShaderProgramBuilder);
308 return d->m_geometryShaderGraph;
309}
310
311/*!
312 \qmlproperty string ShaderProgram::fragmentShaderGraph
313
314 Holds the URL to the fragment shader graph used by this shader program builder.
315*/
316/*!
317 \property QShaderProgramBuilder::fragmentShaderGraph
318
319 Holds the URL to the fragment shader graph used by this shader program builder.
320*/
321void QShaderProgramBuilder::setFragmentShaderGraph(const QUrl &fragmentShaderGraph)
322{
323 Q_D(QShaderProgramBuilder);
324 if (fragmentShaderGraph != d->m_fragmentShaderGraph) {
325 d->m_fragmentShaderGraph = fragmentShaderGraph;
326 emit fragmentShaderGraphChanged(fragmentShaderGraph);
327 }
328}
329
330QUrl QShaderProgramBuilder::fragmentShaderGraph() const
331{
332 Q_D(const QShaderProgramBuilder);
333 return d->m_fragmentShaderGraph;
334}
335
336/*!
337 \qmlproperty string ShaderProgram::computeShaderGraph
338
339 Holds the URL to the compute shader graph used by this shader program builder.
340*/
341/*!
342 \property QShaderProgramBuilder::computeShaderGraph
343
344 Holds the URL to the compute shader graph used by this shader program builder.
345*/
346void QShaderProgramBuilder::setComputeShaderGraph(const QUrl &computeShaderGraph)
347{
348 Q_D(QShaderProgramBuilder);
349 if (computeShaderGraph != d->m_computeShaderGraph) {
350 d->m_computeShaderGraph = computeShaderGraph;
351 emit computeShaderGraphChanged(computeShaderGraph);
352 }
353}
354
355QUrl QShaderProgramBuilder::computeShaderGraph() const
356{
357 Q_D(const QShaderProgramBuilder);
358 return d->m_computeShaderGraph;
359}
360
361/*!
362 \qmlproperty string ShaderProgramBuilder:vertexShaderCode
363
364 Holds the generated vertex shader code
365 \since 2.13
366*/
367/*!
368 \property QShaderProgram:Builder:vertexShaderCode
369
370 Holds the generate vertex shader code.
371 \since 5.13
372*/
373QByteArray QShaderProgramBuilder::vertexShaderCode() const
374{
375 Q_D(const QShaderProgramBuilder);
376 return d->m_vertexShaderCode;
377}
378
379/*!
380 \qmlproperty string ShaderProgramBuilder:tessellationControlShaderCode
381
382 Holds the generated tessellation control shader code
383 \since 2.13
384*/
385/*!
386 \property QShaderProgram:Builder:tessellationControlShaderCode
387
388 Holds the generate tessellation control shader code.
389 \since 5.13
390*/
391QByteArray QShaderProgramBuilder::tessellationControlShaderCode() const
392{
393 Q_D(const QShaderProgramBuilder);
394 return d->m_tessControlShaderCode;
395}
396
397/*!
398 \qmlproperty string ShaderProgramBuilder:tessellationEvaluationShaderCode
399
400 Holds the generated tessellation evaluation shader code
401 \since 2.13
402*/
403/*!
404 \property QShaderProgram:Builder:tessellationEvaluationShaderCode
405
406 Holds the generate tessellation evaluation shader code.
407 \since 5.13
408*/
409QByteArray QShaderProgramBuilder::tessellationEvaluationShaderCode() const
410{
411 Q_D(const QShaderProgramBuilder);
412 return d->m_tessEvalShaderCode;
413}
414
415/*!
416 \qmlproperty string ShaderProgramBuilder:geometryShaderCode
417
418 Holds the generated geometry shader code
419 \since 2.13
420*/
421/*!
422 \property QShaderProgram:Builder:geometryShaderCode
423
424 Holds the generate geometry shader code.
425 \since 5.13
426*/
427QByteArray QShaderProgramBuilder::geometryShaderCode() const
428{
429 Q_D(const QShaderProgramBuilder);
430 return d->m_geometryShaderCode;
431}
432
433/*!
434 \qmlproperty string ShaderProgramBuilder::fragmentShaderCode
435
436 Holds the generated fragment shader code
437 \since 2.13
438*/
439/*!
440 \property QShaderProgram:Builder:fragmentShaderCode
441
442 Holds the generate fragment shader code.
443 \since 5.13
444*/
445QByteArray QShaderProgramBuilder::fragmentShaderCode() const
446{
447 Q_D(const QShaderProgramBuilder);
448 return d->m_fragmentShaderCode;
449}
450
451/*!
452 \qmlproperty string ShaderProgramBuilder::computeShaderCode
453
454 Holds the generated compute shader code
455 \since 2.13
456*/
457/*!
458 \property QShaderProgram:Builder:computeShaderCode
459
460 Holds the generate compute shader code.
461 \since 5.13
462*/
463QByteArray QShaderProgramBuilder::computeShaderCode() const
464{
465 Q_D(const QShaderProgramBuilder);
466 return d->m_computeShaderCode;
467}
468
469Qt3DCore::QNodeCreatedChangeBasePtr QShaderProgramBuilder::createNodeCreationChange() const
470{
471 auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QShaderProgramBuilderData>::create(this);
472 auto &data = creationChange->data;
473 Q_D(const QShaderProgramBuilder);
474 data.shaderProgramId = d->m_shaderProgram ? d->m_shaderProgram->id() : Qt3DCore::QNodeId();
475 data.enabledLayers = d->m_enabledLayers;
476 data.vertexShaderGraph = d->m_vertexShaderGraph;
477 data.tessellationControlShaderGraph = d->m_tessControlShaderGraph;
478 data.tessellationEvaluationShaderGraph = d->m_tessEvalShaderGraph;
479 data.geometryShaderGraph = d->m_geometryShaderGraph;
480 data.fragmentShaderGraph = d->m_fragmentShaderGraph;
481 data.computeShaderGraph = d->m_computeShaderGraph;
482 return creationChange;
483}
484
485} // of namespace Qt3DRender
486
487QT_END_NAMESPACE
488