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

source code of qt3d/src/render/materialsystem/qshaderprogrambuilder.cpp