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
qsgmaterialshader.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qsgmaterial.h"
8#include <QtCore/QFile>
9
11
12/*!
13 \class QSGMaterialShader
14 \brief The QSGMaterialShader class represents a graphics API independent shader program.
15 \inmodule QtQuick
16 \ingroup qtquick-scenegraph-materials
17 \since 5.14
18
19 QSGMaterialShader represents a combination of vertex and fragment shaders,
20 data that define the graphics pipeline state changes, and logic that
21 updates graphics resources, such as uniform buffers and textures.
22
23 \note All classes with QSG prefix should be used solely on the scene graph's
24 rendering thread. See \l {Scene Graph and Rendering} for more information.
25
26 The QSGMaterial and QSGMaterialShader form a tight relationship. For one
27 scene graph (including nested graphs), there is one unique
28 QSGMaterialShader instance that encapsulates the shaders and other data
29 the scene graph uses to render an object with that material. Each
30 QSGGeometryNode can have a unique QSGMaterial that defines how the graphics
31 pipeline must be configured while drawing the node. An instance of
32 QSGMaterialShader is never created explicitly by the user, it will be
33 created on demand by the scene graph through QSGMaterial::createShader().
34 The scene graph creates an instance of QSGMaterialShader by calling the
35 QSGMaterial::createShader() method, ensuring that there is only one
36 instance of each shader implementation.
37
38 In Qt 5, QSGMaterialShader was tied to OpenGL. It was built directly on
39 QOpenGLShaderProgram and had functions like \c updateState() that could
40 issue arbitrary OpenGL commands. This is no longer the case in Qt 6.
41 QSGMaterialShader is not strictly data-oriented, meaning it provides data
42 (shaders and the desired pipeline state changes) together with logic that
43 updates data in a uniform buffer. Graphics API access is not provided. This
44 means that a QSGMaterialShader cannot make OpenGL, Vulkan, Metal, or Direct
45 3D calls on its own. Together with the unified shader management, this
46 allows a QSGMaterialShader to be written once, and be functional with any of
47 the supported graphics APIs at run time.
48
49 The shaders set by calling the protected setShaderFileName() function
50 control what material does with the vertex data from the geometry, and how
51 the fragments are shaded. A QSGMaterialShader will typically set a vertex
52 and a fragment shader during construction. Changing the shaders afterwards
53 may not lead to the desired effect and must be avoided.
54
55 In Qt 6, the default approach is to ship \c{.qsb} files with the application,
56 typically embedded via the resource system, and referenced when calling
57 setShaderFileName(). The \c{.qsb} files are generated offline, or at latest
58 at application build time, from Vulkan-style GLSL source code using the \c
59 qsb tool from the Qt Shader Tools module.
60
61 There are three virtuals that can be overridden. These provide the data, or
62 the logic to generate the data, for uniform buffers, textures, and pipeline
63 state changes.
64
65 updateUniformData() is the function that is most commonly reimplemented in
66 subclasses. This function is expected to update the contents of a
67 QByteArray that will then be exposed to the shaders as a uniform buffer.
68 Any QSGMaterialShader that has a uniform block in its vertex or fragment
69 shader must reimplement updateUniformData().
70
71 updateSampledImage() is relevant when the shader code samples textures. The
72 function will be invoked for each sampler (or combined image sampler, in
73 APIs where relevant), giving it the option to specify which QSGTexture
74 should be exposed to the shader.
75
76 The shader pipeline state changes are less often used. One use case is
77 materials that wish to use a specific blend mode. The relevant function is
78 updateGraphicsPipelineState(). This function is not called unless the
79 QSGMaterialShader has opted in by setting the flag
80 UpdatesGraphicsPipelineState. The task of the function is to update the
81 GraphicsPipelineState struct instance that is passed to it with the
82 desired changes. Currently only blending and culling-related features are
83 available, other states cannot be controlled by materials.
84
85 A minimal example, that also includes texture support, could be the
86 following. Here we assume that Material is the QSGMaterial that creates an
87 instance of Shader in its \l{QSGMaterial::createShader()}{createShader()},
88 and that it holds a QSGTexture we want to sample in the fragment shader. The
89 vertex shader relies only on the modelview-projection matrix.
90
91 \code
92 class Shader : public QSGMaterialShader
93 {
94 public:
95 Shader()
96 {
97 setShaderFileName(VertexStage, QLatin1String(":/materialshader.vert.qsb"));
98 setShaderFileName(FragmentStage, QLatin1String(":/materialshader.frag.qsb"));
99 }
100
101 bool updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *)
102 {
103 bool changed = false;
104 QByteArray *buf = state.uniformData();
105 if (state.isMatrixDirty()) {
106 const QMatrix4x4 m = state.combinedMatrix();
107 memcpy(buf->data(), m.constData(), 64);
108 changed = true;
109 }
110 return changed;
111 }
112
113 void updateSampledImage(RenderState &, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *)
114 {
115 Material *mat = static_cast<Material *>(newMaterial);
116 if (binding == 1)
117 *texture = mat->texture();
118 }
119 };
120 \endcode
121
122 The Vulkan-style GLSL source code for the shaders could look like the
123 following. These are expected to be preprocessed offline using the \c qsb
124 tool, which generates the \c{.qsb} files referenced in the Shader()
125 constructor.
126
127 \badcode
128 #version 440
129 layout(location = 0) in vec4 aVertex;
130 layout(location = 1) in vec2 aTexCoord;
131 layout(location = 0) out vec2 vTexCoord;
132 layout(std140, binding = 0) uniform buf {
133 mat4 qt_Matrix;
134 } ubuf;
135 out gl_PerVertex { vec4 gl_Position; };
136 void main() {
137 gl_Position = ubuf.qt_Matrix * aVertex;
138 vTexCoord = aTexCoord;
139 }
140 \endcode
141
142 \badcode
143 #version 440
144 layout(location = 0) in vec2 vTexCoord;
145 layout(location = 0) out vec4 fragColor;
146 layout(binding = 1) uniform sampler2D srcTex;
147 void main() {
148 vec4 c = texture(srcTex, vTexCoord);
149 fragColor = vec4(c.rgb * 0.5, 1.0);
150 }
151 \endcode
152
153 \note All classes with QSG prefix should be used solely on the scene graph's
154 rendering thread. See \l {Scene Graph and Rendering} for more information.
155
156 \sa QSGMaterial, {Scene Graph - Custom Material}, {Scene Graph - Two Texture Providers}, {Scene Graph - Graph}
157 */
158
159/*!
160 \enum QSGMaterialShader::Flag
161 Flag values to indicate special material properties.
162
163 \value UpdatesGraphicsPipelineState Setting this flag enables calling
164 updateGraphicsPipelineState().
165 */
166
167QShader QSGMaterialShaderPrivate::loadShader(const QString &filename)
168{
169 QFile f(filename);
170 if (!f.open(QIODevice::ReadOnly)) {
171 qWarning() << "Failed to find shader" << filename;
172 return QShader();
173 }
174 return QShader::fromSerialized(f.readAll());
175}
176
177void QSGMaterialShaderPrivate::clearCachedRendererData()
178{
179 for (int i = 0; i < MAX_SHADER_RESOURCE_BINDINGS; ++i)
180 textureBindingTable[i].clear();
181 for (int i = 0; i < MAX_SHADER_RESOURCE_BINDINGS; ++i)
182 samplerBindingTable[i].clear();
183}
184
185static inline QRhiShaderResourceBinding::StageFlags toSrbStage(QShader::Stage stage)
186{
187 switch (stage) {
188 case QShader::VertexStage:
189 return QRhiShaderResourceBinding::VertexStage;
190 case QShader::FragmentStage:
191 return QRhiShaderResourceBinding::FragmentStage;
192 default:
193 Q_UNREACHABLE();
194 break;
195 }
196 return { };
197}
198
199void QSGMaterialShaderPrivate::prepare(QShader::Variant vertexShaderVariant)
200{
201 ubufBinding = -1;
202 ubufSize = 0;
203 ubufStages = { };
204 memset(static_cast<void *>(combinedImageSamplerBindings), 0, sizeof(combinedImageSamplerBindings));
205 memset(static_cast<void *>(combinedImageSamplerCount), 0, sizeof(combinedImageSamplerCount));
206 vertexShader = fragmentShader = nullptr;
207 masterUniformData.clear();
208
209 clearCachedRendererData();
210
211 for (QShader::Stage stage : { QShader::VertexStage, QShader::FragmentStage }) {
212 auto it = shaderFileNames.constFind(stage);
213 if (it != shaderFileNames.cend()) {
214 const QShader s = loadShader(*it);
215 if (!s.isValid())
216 continue;
217 shaders[stage] = ShaderStageData(s);
218 // load only once, subsequent prepare() calls will have it all in shaders already
219 shaderFileNames.erase(it);
220 }
221 }
222
223 auto vsIt = shaders.find(QShader::VertexStage);
224 if (vsIt != shaders.end()) {
225 vsIt->shaderVariant = vertexShaderVariant;
226 vsIt->vertexInputLocations.clear();
227 vsIt->qt_order_attrib_location = -1;
228
229 const QShaderDescription desc = vsIt->shader.description();
230 const QList<QShaderDescription::InOutVariable> vertexInputs = desc.inputVariables();
231 for (const QShaderDescription::InOutVariable &v : vertexInputs) {
232 if (vertexShaderVariant == QShader::BatchableVertexShader
233 && v.name == QByteArrayLiteral("_qt_order")) {
234 vsIt->qt_order_attrib_location = v.location;
235 } else {
236 vsIt->vertexInputLocations.append(v.location);
237 }
238 }
239
240 if (vsIt->vertexInputLocations.contains(vsIt->qt_order_attrib_location)) {
241 qWarning("Vertex input clash in rewritten (batchable) vertex shader at input location %d. "
242 "Vertex shaders must avoid using this location.", vsIt->qt_order_attrib_location);
243 }
244 }
245
246 for (auto it = shaders.begin(); it != shaders.end(); ++it) {
247 const QShaderDescription desc = it->shader.description();
248
249 const QList<QShaderDescription::UniformBlock> ubufs = desc.uniformBlocks();
250 const int ubufCount = ubufs.size();
251 if (ubufCount > 1) {
252 qWarning("Multiple uniform blocks found in shader. "
253 "This should be avoided as Qt Quick supports only one.");
254 }
255 for (int i = 0; i < ubufCount; ++i) {
256 const QShaderDescription::UniformBlock &ubuf(ubufs[i]);
257 if (ubuf.size <= 0) {
258 // QByteArray::fill() would treat a negative size as "keep the current
259 // size", leaving a buffer that every member offset then writes past.
260 qWarning("Uniform block %s has an invalid size (%d); ignored",
261 ubuf.blockName.constData(), ubuf.size);
262 continue;
263 }
264 if (ubufBinding == -1 && ubuf.binding >= 0) {
265 ubufBinding = ubuf.binding;
266 ubufSize = ubuf.size;
267 ubufStages |= toSrbStage(it->shader.stage());
268 masterUniformData.fill('\0', ubufSize);
269 } else if (ubufBinding == ubuf.binding && ubuf.binding >= 0) {
270 if (ubuf.size > ubufSize) {
271 ubufSize = ubuf.size;
272 masterUniformData.fill('\0', ubufSize);
273 }
274 ubufStages |= toSrbStage(it->shader.stage());
275 } else {
276 qWarning("Uniform block %s (binding %d) ignored", ubuf.blockName.constData(),
277 ubuf.binding);
278 }
279 }
280
281 const QList<QShaderDescription::InOutVariable> imageSamplers = desc.combinedImageSamplers();
282 const int imageSamplersCount = imageSamplers.size();
283 for (int i = 0; i < imageSamplersCount; ++i) {
284 const QShaderDescription::InOutVariable &var(imageSamplers[i]);
285
286 if (var.binding < 0)
287 continue;
288
289 if (var.binding < MAX_SHADER_RESOURCE_BINDINGS) {
290 combinedImageSamplerBindings[var.binding] |= toSrbStage(it->shader.stage());
291
292 int count = 1;
293 for (int dim : var.arrayDims)
294 count *= dim;
295
296 combinedImageSamplerCount[var.binding] = count;
297 } else {
298 qWarning("Encountered invalid combined image sampler (%s) binding %d",
299 var.name.constData(), var.binding);
300 }
301 }
302
303 if (it.key() == QShader::VertexStage)
304 vertexShader = &it.value();
305 else if (it.key() == QShader::FragmentStage)
306 fragmentShader = &it.value();
307 }
308
309 if (vertexShader && vertexShaderVariant == QShader::BatchableVertexShader && vertexShader->qt_order_attrib_location == -1)
310 qWarning("No rewriter-inserted attribute found, this should not happen.");
311}
312
313/*!
314 Constructs a new QSGMaterialShader.
315 */
316QSGMaterialShader::QSGMaterialShader()
317 : d_ptr(new QSGMaterialShaderPrivate(this))
318{
319}
320
321/*!
322 \internal
323 */
324QSGMaterialShader::QSGMaterialShader(QSGMaterialShaderPrivate &dd)
325 : d_ptr(&dd)
326{
327}
328
329/*!
330 \internal
331 */
332QSGMaterialShader::~QSGMaterialShader()
333{
334}
335
336// We have our own enum as QShader is not initially public. Internally
337// everything works with QShader::Stage however. So convert.
338static inline QShader::Stage toShaderStage(QSGMaterialShader::Stage stage)
339{
340 switch (stage) {
341 case QSGMaterialShader::VertexStage:
342 return QShader::VertexStage;
343 case QSGMaterialShader::FragmentStage:
344 return QShader::FragmentStage;
345 default:
346 Q_UNREACHABLE_RETURN(QShader::VertexStage);
347 }
348}
349
350/*!
351 Sets the \a shader for the specified \a stage.
352 */
353void QSGMaterialShader::setShader(Stage stage, const QShader &shader)
354{
355 Q_D(QSGMaterialShader);
356 d->shaders[toShaderStage(stage)] = QSGMaterialShaderPrivate::ShaderStageData(shader);
357}
358
359/*!
360 Sets the \a filename for the shader for the specified \a stage.
361
362 The file is expected to contain a serialized QShader.
363
364 \warning Shaders, including \c{.qsb} files, are assumed to be trusted
365 content. Application developers are advised to carefully consider the
366 potential implications before allowing the loading of user-provided content
367 that is not part of the application.
368 */
369void QSGMaterialShader::setShaderFileName(Stage stage, const QString &filename)
370{
371 Q_D(QSGMaterialShader);
372 d->shaderFileNames[toShaderStage(stage)] = filename;
373}
374
375/*!
376 Sets the \a filename for the shader for the specified \a stage.
377
378 The file is expected to contain a serialized QShader.
379
380 This overload is used when enabling \l{QSGMaterial::viewCount()}{multiview}
381 rendering, in particular when the \l{qt_add_shaders}
382 {build system's MULTIVIEW convenience option} is used.
383
384 \a viewCount should be 2, 3, or 4. The \a filename is adjusted automatically
385 based on this.
386
387 \warning Shaders, including \c{.qsb} files, are assumed to be trusted
388 content. Application developers are advised to carefully consider the
389 potential implications before allowing the loading of user-provided content
390 that is not part of the application.
391
392 \since 6.8
393 */
394void QSGMaterialShader::setShaderFileName(Stage stage, const QString &filename, int viewCount)
395{
396 Q_D(QSGMaterialShader);
397 if (viewCount == 2)
398 d->shaderFileNames[toShaderStage(stage)] = filename + QStringLiteral(".mv2qsb");
399 else if (viewCount == 3)
400 d->shaderFileNames[toShaderStage(stage)] = filename + QStringLiteral(".mv3qsb");
401 else if (viewCount == 4)
402 d->shaderFileNames[toShaderStage(stage)] = filename + QStringLiteral(".mv4qsb");
403 else
404 d->shaderFileNames[toShaderStage(stage)] = filename;
405}
406
407/*!
408 \return the currently set flags for this material shader.
409 */
410QSGMaterialShader::Flags QSGMaterialShader::flags() const
411{
412 Q_D(const QSGMaterialShader);
413 return d->flags;
414}
415
416/*!
417 Sets the \a flags on this material shader if \a on is true;
418 otherwise clears the specified flags.
419*/
420void QSGMaterialShader::setFlag(Flags flags, bool on)
421{
422 Q_D(QSGMaterialShader);
423 if (on)
424 d->flags |= flags;
425 else
426 d->flags &= ~flags;
427}
428
429/*!
430 Sets the \a flags for this material shader.
431 */
432void QSGMaterialShader::setFlags(Flags flags)
433{
434 Q_D(QSGMaterialShader);
435 d->flags = flags;
436}
437
438/*!
439 Returns the number of elements in the combined image sampler variable at \a
440 binding. This value is introspected from the shader code. The variable may
441 be an array, and may have more than one dimension.
442
443 The count reflects the total number of combined image sampler items in the
444 variable. In the following example, the count for \c{srcA} is 1, \c{srcB}
445 is 4, and \c{srcC} is 6.
446
447 \badcode
448 layout (binding = 0) uniform sampler2D srcA;
449 layout (binding = 1) uniform sampler2D srcB[4];
450 layout (binding = 2) uniform sampler2D srcC[2][3];
451 \endcode
452
453 This count is the number of QSGTexture pointers in the texture parameter
454 of \l{QSGMaterialShader::updateSampledImage}.
455
456 \sa QSGMaterialShader::updateSampledImage
457 \since 6.4
458 */
459int QSGMaterialShader::combinedImageSamplerCount(int binding) const
460{
461 Q_D(const QSGMaterialShader);
462
463 if (binding >= 0 && binding < d->MAX_SHADER_RESOURCE_BINDINGS)
464 return d->combinedImageSamplerCount[binding];
465
466 return 0;
467}
468
469/*!
470 This function is called by the scene graph to get the contents of the
471 shader program's uniform buffer updated. The implementation is not expected
472 to perform any real graphics operations, it is merely responsible for
473 copying data to the QByteArray returned from RenderState::uniformData().
474 The scene graph takes care of making that buffer visible in the shaders.
475
476 The current rendering \a state is passed from the scene graph. If the state
477 indicates that any relevant state is dirty, the implementation must update
478 the appropriate region in the buffer data that is accessible via
479 RenderState::uniformData(). When a state, such as, matrix or opacity, is
480 not dirty, there is no need to touch the corresponding region since the
481 data is persistent.
482
483 The return value must be \c true whenever any change was made to the uniform data.
484
485 The subclass specific state, such as the color of a flat color material,
486 should be extracted from \a newMaterial to update the relevant regions in
487 the buffer accordingly.
488
489 \a oldMaterial can be used to minimize buffer changes (which are typically
490 memcpy calls) when updating material states. When \a oldMaterial is null,
491 this shader was just activated.
492 */
493bool QSGMaterialShader::updateUniformData(RenderState &state,
494 QSGMaterial *newMaterial,
495 QSGMaterial *oldMaterial)
496{
497 Q_UNUSED(state);
498 Q_UNUSED(newMaterial);
499 Q_UNUSED(oldMaterial);
500 return false;
501}
502
503/*!
504 This function is called by the scene graph to prepare use of sampled images
505 in the shader, typically in the form of combined image samplers.
506
507 \a binding is the binding number of the sampler. The function is called for
508 each combined image sampler variable in the shader code associated with the
509 QSGMaterialShader.
510
511 \a{texture} is an array of QSGTexture pointers. The number of elements in
512 the array matches the number of elements in the image sampler variable
513 specified in the shader code. This variable may be an array, and may have
514 more than one dimension. The number of elements in the array may be
515 found via \l{QSGMaterialShader::combinedImageSamplerCount}
516
517 When an element in \a{texture} is null, it must be set to a valid
518 QSGTexture pointer before returning. When non-null, it is up to the
519 material to decide if a new \c{QSGTexture *} is stored to it, or if it
520 updates some parameters on the already known QSGTexture. The ownership of
521 the QSGTexture is not transferred.
522
523 The current rendering \a state is passed from the scene graph. Where
524 relevant, it is up to the material to trigger enqueuing texture data
525 uploads via QSGTexture::commitTextureOperations().
526
527 The subclass specific state can be extracted from \a newMaterial.
528
529 \a oldMaterial can be used to minimize changes. When \a oldMaterial is null,
530 this shader was just activated.
531
532 \sa QSGMaterialShader::combinedImageSamplerCount
533 */
534void QSGMaterialShader::updateSampledImage(RenderState &state,
535 int binding,
536 QSGTexture **texture,
537 QSGMaterial *newMaterial,
538 QSGMaterial *oldMaterial)
539{
540 Q_UNUSED(state);
541 Q_UNUSED(binding);
542 Q_UNUSED(texture);
543 Q_UNUSED(newMaterial);
544 Q_UNUSED(oldMaterial);
545}
546
547/*!
548 This function is called by the scene graph to enable the material to
549 provide a custom set of graphics state. The set of states that are
550 customizable by material is limited to blending and related settings.
551
552 \note This function is only called when the UpdatesGraphicsPipelineState
553 flag was enabled via setFlags(). By default it is not set, and so this
554 function is never called.
555
556 The return value must be \c true whenever a change was made to any of the
557 members in \a ps.
558
559 \note The contents of \a ps is not persistent between invocations of this
560 function.
561
562 The current rendering \a state is passed from the scene graph.
563
564 The subclass specific state can be extracted from \a newMaterial. When \a
565 oldMaterial is null, this shader was just activated.
566 */
567bool QSGMaterialShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
568 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
569{
570 Q_UNUSED(state);
571 Q_UNUSED(ps);
572 Q_UNUSED(newMaterial);
573 Q_UNUSED(oldMaterial);
574 return false;
575}
576
577/*!
578 \class QSGMaterialShader::RenderState
579
580 \brief Encapsulates the current rendering state during a call to
581 QSGMaterialShader::updateUniformData() and the other \c update type of
582 functions.
583
584 \inmodule QtQuick
585 \since 5.14
586
587 The render state contains a number of accessors that the shader needs to
588 respect in order to conform to the current state of the scene graph.
589 */
590
591/*!
592 \enum QSGMaterialShader::RenderState::DirtyState
593
594 \value DirtyMatrix Used to indicate that the matrix has changed and must be
595 updated.
596
597 \value DirtyOpacity Used to indicate that the opacity has changed and must
598 be updated.
599
600 \value DirtyCachedMaterialData Used to indicate that the cached material
601 state has changed and must be updated.
602
603 \value DirtyAll Used to indicate that everything needs to be updated.
604 */
605
606/*!
607 \fn bool QSGMaterialShader::RenderState::isMatrixDirty() const
608
609 Returns \c true if the dirtyStates() contain the dirty matrix state,
610 otherwise returns \c false.
611 */
612
613/*!
614 \fn bool QSGMaterialShader::RenderState::isOpacityDirty() const
615
616 Returns \c true if the dirtyStates() contains the dirty opacity state,
617 otherwise returns \c false.
618 */
619
620/*!
621 \fn QSGMaterialShader::RenderState::DirtyStates QSGMaterialShader::RenderState::dirtyStates() const
622
623 Returns which rendering states that have changed and needs to be updated
624 for geometry rendered with this material to conform to the current
625 rendering state.
626 */
627
628/*!
629 \class QSGMaterialShader::GraphicsPipelineState
630
631 \brief Describes state changes that the material wants to apply to the
632 currently active graphics pipeline state.
633
634 \inmodule QtQuick
635 \since 5.14
636
637 Unlike QSGMaterialShader, directly issuing state change commands with the
638 underlying graphics API is not possible with QSGMaterialShader. This is
639 mainly because the concept of individually changeable states is considered
640 deprecated and not supported with modern graphics APIs.
641
642 Therefore, it is up to QSGMaterialShader to expose a data structure with
643 the set of supported states, which the material can change in its
644 updatePipelineState() implementation, if there is one. The scenegraph will
645 then internally apply these changes to the active graphics pipeline state,
646 then rolling them back as appropriate.
647
648 When updateGraphicsPipelineState() is called, the struct has all members
649 set to a valid value to reflect the renderer's current state. Not changing
650 any values (or not reimplementing the function) indicates that the material
651 is fine with the defaults (which are dynamic however, depending on
652 QSGMaterial flags, for example).
653 */
654
655/*!
656 \enum QSGMaterialShader::GraphicsPipelineState::BlendFactor
657 \since 5.14
658
659 \value Zero
660 \value One
661 \value SrcColor
662 \value OneMinusSrcColor
663 \value DstColor
664 \value OneMinusDstColor
665 \value SrcAlpha
666 \value OneMinusSrcAlpha
667 \value DstAlpha
668 \value OneMinusDstAlpha
669 \value ConstantColor
670 \value OneMinusConstantColor
671 \value ConstantAlpha
672 \value OneMinusConstantAlpha
673 \value SrcAlphaSaturate
674 \value Src1Color
675 \value OneMinusSrc1Color
676 \value Src1Alpha
677 \value OneMinusSrc1Alpha
678 */
679
680/*!
681 \enum QSGMaterialShader::GraphicsPipelineState::BlendOp
682 \since 6.8
683
684 \value Add
685 \value Subtract
686 \value ReverseSubtract
687 \value Min
688 \value Max
689 */
690
691/*!
692 \enum QSGMaterialShader::GraphicsPipelineState::ColorMaskComponent
693 \since 5.14
694
695 \value R
696 \value G
697 \value B
698 \value A
699 */
700
701/*!
702 \enum QSGMaterialShader::GraphicsPipelineState::CullMode
703 \since 5.14
704
705 \value CullNone
706 \value CullFront
707 \value CullBack
708 */
709
710/*!
711 \enum QSGMaterialShader::GraphicsPipelineState::PolygonMode
712 \since 6.4
713 \brief Specifies the polygon rasterization mode
714
715 Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
716 the fill mode used when rasterizing polygons. Polygons may be drawn as
717 solids (Fill), or as a wire mesh (Line).
718
719 \warning OpenGL ES does not support the \c{Line} polygon mode. OpenGL ES
720 will rasterize all polygons as filled no matter what polygon mode is set.
721 Using \c{Line} will make your application non-portable.
722
723 \value Fill The interior of the polygon is filled (default)
724 \value Line Boundary edges of the polygon are drawn as line segments.
725 */
726
727/*!
728 \variable QSGMaterialShader::GraphicsPipelineState::blendEnable
729 \since 5.14
730 \brief Enables blending.
731
732 \note Changing this flag should be done with care, and is best avoided.
733 Rather, materials should always use the QSGMaterial::Blend flag to indicate
734 that they wish to use blending. Changing this value from false to true for
735 a material that did not declare QSGMaterial::Blend can lead to unexpected
736 visual results.
737 */
738
739/*!
740 \variable QSGMaterialShader::GraphicsPipelineState::srcColor
741 \since 5.14
742 \brief Source blending factor, either RGB or RGBA depending on separateBlendFactors.
743 */
744
745/*!
746 \variable QSGMaterialShader::GraphicsPipelineState::dstColor
747 \since 5.14
748 \brief Destination blending factor, either RGB or RGBA depending on separateBlendFactors.
749 */
750
751/*!
752 \variable QSGMaterialShader::GraphicsPipelineState::colorWrite
753 \since 5.14
754 \brief Color write mask.
755 */
756
757/*!
758 \variable QSGMaterialShader::GraphicsPipelineState::blendConstant
759 \since 5.14
760 \brief Blend constant applicable when a blending factor is set to use a constant value.
761 */
762
763/*!
764 \variable QSGMaterialShader::GraphicsPipelineState::cullMode
765 \since 5.14
766 \brief Cull mode.
767 */
768
769/*!
770 \variable QSGMaterialShader::GraphicsPipelineState::polygonMode
771 \since 6.4
772 \brief Polygon rasterization mode.
773 */
774
775/*!
776 \variable QSGMaterialShader::GraphicsPipelineState::separateBlendFactors
777 \since 6.5
778 \brief Indicates that alpha blending factors are specified separately.
779
780 False by default, meaning both RGB and alpha blending factors are defined
781 by srcColor and dstColor. When set to true, the alpha blending factors are
782 taken from srcAlpha and dstAlpha instead, and srcColor and dstColor applies
783 only to RGB.
784 */
785
786/*!
787 \variable QSGMaterialShader::GraphicsPipelineState::srcAlpha
788 \since 6.5
789 \brief Source alpha blending factor.
790
791 Applies only when separateBlendFactors is set to true.
792 */
793
794/*!
795 \variable QSGMaterialShader::GraphicsPipelineState::dstAlpha
796 \since 6.5
797 \brief Destination alpha blending factor.
798
799 Applies only when separateBlendFactors is set to true.
800 */
801
802/*!
803 \variable QSGMaterialShader::GraphicsPipelineState::opColor
804 \since 6.8
805 \brief RGB blending operation.
806 */
807
808/*!
809 \variable QSGMaterialShader::GraphicsPipelineState::opAlpha
810 \since 6.8
811 \brief Alpha blending operation.
812 */
813
814/*!
815 Returns the accumulated opacity to be used for rendering.
816 */
817float QSGMaterialShader::RenderState::opacity() const
818{
819 Q_ASSERT(m_data);
820 return float(static_cast<const QSGRenderer *>(m_data)->currentOpacity());
821}
822
823/*!
824 Returns the modelview determinant to be used for rendering.
825 */
826float QSGMaterialShader::RenderState::determinant() const
827{
828 Q_ASSERT(m_data);
829 return float(static_cast<const QSGRenderer *>(m_data)->determinant());
830}
831
832/*!
833 Returns the matrix combined of modelview matrix and project matrix.
834 */
835QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const
836{
837 Q_ASSERT(m_data);
838 return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix(0);
839}
840
841/*!
842 \internal
843 */
844QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix(qsizetype index) const
845{
846 Q_ASSERT(m_data);
847 return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix(index);
848}
849
850/*!
851 Returns the ratio between physical pixels and device-independent pixels
852 to be used for rendering.
853*/
854float QSGMaterialShader::RenderState::devicePixelRatio() const
855{
856 Q_ASSERT(m_data);
857 return float(static_cast<const QSGRenderer *>(m_data)->devicePixelRatio());
858}
859
860/*!
861 Returns the model view matrix.
862
863 If the material has the RequiresFullMatrix flag set, this is guaranteed to
864 be the complete transform matrix calculated from the scenegraph.
865
866 However, if this flag is not set, the renderer may choose to alter this
867 matrix. For example, it may pre-transform vertices on the CPU and set this
868 matrix to identity.
869
870 In a situation such as the above, it is still possible to retrieve the
871 actual matrix determinant by setting the RequiresDeterminant flag in the
872 material and calling the determinant() accessor.
873 */
874QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const
875{
876 Q_ASSERT(m_data);
877 return static_cast<const QSGRenderer *>(m_data)->currentModelViewMatrix();
878}
879
880/*!
881 Returns the projection matrix.
882 */
883QMatrix4x4 QSGMaterialShader::RenderState::projectionMatrix() const
884{
885 Q_ASSERT(m_data);
886 return static_cast<const QSGRenderer *>(m_data)->currentProjectionMatrix(0);
887}
888
889/*!
890 \internal
891 */
892QMatrix4x4 QSGMaterialShader::RenderState::projectionMatrix(qsizetype index) const
893{
894 Q_ASSERT(m_data);
895 return static_cast<const QSGRenderer *>(m_data)->currentProjectionMatrix(index);
896}
897
898/*!
899 \internal
900 */
901qsizetype QSGMaterialShader::RenderState::projectionMatrixCount() const
902{
903 Q_ASSERT(m_data);
904 return static_cast<const QSGRenderer *>(m_data)->projectionMatrixCount();
905}
906
907/*!
908 Returns the viewport rect of the surface being rendered to.
909 */
910QRect QSGMaterialShader::RenderState::viewportRect() const
911{
912 Q_ASSERT(m_data);
913 return static_cast<const QSGRenderer *>(m_data)->viewportRect();
914}
915
916/*!
917 Returns the device rect of the surface being rendered to
918 */
919QRect QSGMaterialShader::RenderState::deviceRect() const
920{
921 Q_ASSERT(m_data);
922 return static_cast<const QSGRenderer *>(m_data)->deviceRect();
923}
924
925/*!
926 Returns a pointer to the data for the uniform (constant) buffer in the
927 shader. Uniform data must only be updated from
928 QSGMaterialShader::updateUniformData(). The return value is null in the
929 other reimplementable functions, such as,
930 QSGMaterialShader::updateSampledImage().
931
932 \note It is strongly recommended to declare the uniform block with \c
933 std140 in the shader, and to carefully study the standard uniform block
934 layout as described in section 7.6.2.2 of the OpenGL specification. It is
935 up to the QSGMaterialShader implementation to ensure data gets placed
936 at the right location in this QByteArray, taking alignment requirements
937 into account. Shader code translated to other shading languages is expected
938 to use the same offsets for block members, even when the target language
939 uses different packing rules by default.
940
941 \note Avoid copying from C++ POD types, such as, structs, in order to
942 update multiple members at once, unless it has been verified that the
943 layouts of the C++ struct and the GLSL uniform block match.
944 */
945QByteArray *QSGMaterialShader::RenderState::uniformData()
946{
947 Q_ASSERT(m_data);
948 return static_cast<const QSGRenderer *>(m_data)->currentUniformData();
949}
950
951/*!
952 Returns a resource update batch to which upload and copy operatoins can be
953 queued. This is typically used by
954 QSGMaterialShader::updateSampledImage() to enqueue texture image
955 content updates.
956 */
957QRhiResourceUpdateBatch *QSGMaterialShader::RenderState::resourceUpdateBatch()
958{
959 Q_ASSERT(m_data);
960 return static_cast<const QSGRenderer *>(m_data)->currentResourceUpdateBatch();
961}
962
963/*!
964 Returns the current QRhi.
965 */
966QRhi *QSGMaterialShader::RenderState::rhi()
967{
968 Q_ASSERT(m_data);
969 return static_cast<const QSGRenderer *>(m_data)->currentRhi();
970}
971
972QT_END_NAMESPACE
Combined button and popup list for selecting options.
static QShader::Stage toShaderStage(QSGMaterialShader::Stage stage)
static QRhiShaderResourceBinding::StageFlags toSrbStage(QShader::Stage stage)