Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qssgrhicontext.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qssgrhicontext_p.h"
5#include <QtQuick3DUtils/private/qssgmesh_p.h>
6#include <QtQuick3DUtils/private/qssgassert_p.h>
7#include <QtQuick3DRuntimeRender/private/qssgrenderableimage_p.h>
8#include <QtQuick3DRuntimeRender/private/qssgrendermesh_p.h>
9#include <QtQuick3DUtils/private/qssgutils_p.h>
10#include <QtQuick3DUtils/private/qssgassert_p.h>
11#include <QtCore/QVariant>
12#include <qtquick3d_tracepoints_p.h>
13
15
16Q_TRACE_POINT(qtquick3d, QSSG_renderPass_entry, const QString &renderPass);
17Q_TRACE_POINT(qtquick3d, QSSG_renderPass_exit);
18Q_TRACE_POINT(qtquick3d, QSSG_drawIndexed, int indexCount, int instanceCount);
19Q_TRACE_POINT(qtquick3d, QSSG_draw, int vertexCount, int instanceCount);
20
23 QRhiBuffer::UsageFlags usageMask,
27 : m_context(context),
28 m_stride(stride),
29 m_indexFormat(indexFormat)
30{
31 QSSG_ASSERT(size >= 0, size = 0);
32 m_buffer = m_context.rhi()->newBuffer(type, usageMask, quint32(size));
33 if (!m_buffer->create())
34 qWarning("Failed to build QRhiBuffer with size %d", m_buffer->size());
35}
36
38{
39 delete m_buffer;
40}
41
43{
44 if (compType == QSSGRenderComponentType::Float32) {
45 switch (numComps) {
46 case 1:
48 case 2:
50 case 3:
52 case 4:
54 default:
55 break;
56 }
57 } else if (compType == QSSGRenderComponentType::UnsignedInt32) {
58 switch (numComps) {
59 case 1:
61 case 2:
63 case 3:
65 case 4:
67 default:
68 break;
69 }
70 } else if (compType == QSSGRenderComponentType::Int32) {
71 switch (numComps) {
72 case 1:
74 case 2:
76 case 3:
78 case 4:
80 default:
81 break;
82 }
83 }
84 Q_ASSERT(false);
86}
87
89{
90 switch (drawMode) {
104 QSSG_ASSERT_X(false, "LineLoop draw mode is not supported", return QRhiGraphicsPipeline::Triangles);
105 }
106
107 Q_UNREACHABLE_RETURN(QRhiGraphicsPipeline::Triangles);
108}
109
111{
112 if (!shaders.vertexStage())
113 return;
114
115 const auto &vertexInputs = shaders.vertexInputs();
116
118 int inputIndex = 0;
119 for (auto it = inputLayout.cbeginAttributes(), itEnd = inputLayout.cendAttributes(); it != itEnd; ++it) {
120 const QSSGRhiInputAssemblerState::InputSemantic sem = inputs.at(inputIndex); // avoid detaching - submeshes share the same name list
121 auto vertexInputVar = vertexInputs.constFind(sem);
122 if (vertexInputVar != vertexInputs.constEnd()) {
123 attrs.append(*it);
124 attrs.last().setLocation(vertexInputVar->location);
125 } // else the mesh has an input attribute that is not declared and used in the vertex shader - that's fine
126
127 ++inputIndex;
128 }
129
130 // Add instance buffer input if necessary
131 if (instanceBufferBinding > 0) {
132 auto instanceBufferLocations = shaders.instanceBufferLocations();
133 // transform0
134 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
135 instanceBufferLocations.transform0,
137 0));
138 // transform1
139 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
140 instanceBufferLocations.transform1,
142 sizeof(float) * 4));
143 // transform2
144 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
145 instanceBufferLocations.transform2,
147 sizeof(float) * 4 * 2));
148 // color
149 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
150 instanceBufferLocations.color,
152 sizeof(float) * 4 * 3));
153 // data
154 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
155 instanceBufferLocations.data,
157 sizeof(float) * 4 * 4));
158 }
159
160 inputLayout.setAttributes(attrs.cbegin(), attrs.cend());
161}
162
164{
165 switch (cullFaceMode) {
173 qWarning("FrontAndBack cull mode not supported");
177 }
178
179 Q_UNREACHABLE_RETURN(QRhiGraphicsPipeline::None);
180}
181
183{
184 m_stages.append(stage);
185
186 // Copy all member infos for the uniform block with binding 0 into m_ub0
187 // for faster lookup.
188 if (stage.type() == QRhiShaderStage::Vertex) {
189 // Optimize by doing it only for the vertex shader. This code path is
190 // only hit for pipelines with vertex+fragment stages and an in shaders
191 // from materials an identical uniform block is present in both
192 // shaders, so go through only one of them.
194 for (const QShaderDescription::UniformBlock &blk : uniformBlocks) {
195 if (blk.binding == 0) {
196 m_ub0Size = blk.size;
197 m_ub0NextUBufOffset = m_context.rhi()->ubufAligned(m_ub0Size);
198 for (const QShaderDescription::BlockVariable &var : blk.members)
199 m_ub0[var.name] = var;
200 break;
201 }
202 }
203 // Now the same for vertex inputs.
204 if (!flags.testFlag(UsedWithoutIa)) {
206 for (const QShaderDescription::InOutVariable &var : inputs) {
209 } else if (var.name == QSSGMesh::MeshInternal::getNormalAttrName()) {
211 } else if (var.name == QSSGMesh::MeshInternal::getUV0AttrName()) {
213 } else if (var.name == QSSGMesh::MeshInternal::getUV1AttrName()) {
217 } else if (var.name == QSSGMesh::MeshInternal::getTexTanAttrName()) {
221 } else if (var.name == QSSGMesh::MeshInternal::getColorAttrName()) {
223 } else if (var.name == QSSGMesh::MeshInternal::getJointAttrName()) {
225 } else if (var.name == QSSGMesh::MeshInternal::getWeightAttrName()) {
227 } else if (var.name == "qt_instanceTransform0") {
229 } else if (var.name == "qt_instanceTransform1") {
231 } else if (var.name == "qt_instanceTransform2") {
233 } else if (var.name == "qt_instanceColor") {
234 instanceLocations.color = var.location;
235 } else if (var.name == "qt_instanceData") {
236 instanceLocations.data = var.location;
237 } else {
238 qWarning("Ignoring vertex input %s in shader", var.name.constData());
239 }
240 }
241 }
242 }
243
245 for (const QShaderDescription::InOutVariable &var : combinedImageSamplers)
246 m_combinedImageSamplers[var.name] = var;
247
248 std::fill(m_materialImageSamplerBindings,
249 m_materialImageSamplerBindings + size_t(QSSGRhiSamplerBindingHints::BindingMapSize),
250 -1);
251}
252
253void QSSGRhiShaderPipeline::setUniformValue(char *ubufData, const char *name, const QVariant &inValue, QSSGRenderShaderDataType inType)
254{
255 switch (inType) {
257 {
258 const qint32 v = inValue.toInt();
259 setUniform(ubufData, name, &v, sizeof(qint32));
260 }
261 break;
263 {
264 const qint32_2 v = inValue.value<qint32_2>();
265 setUniform(ubufData, name, &v, 2 * sizeof(qint32));
266 }
267 break;
269 {
270 const qint32_3 v = inValue.value<qint32_3>();
271 setUniform(ubufData, name, &v, 3 * sizeof(qint32));
272 }
273 break;
275 {
276 const qint32_4 v = inValue.value<qint32_4>();
277 setUniform(ubufData, name, &v, 4 * sizeof(qint32));
278 }
279 break;
281 {
282 // whatever bool is does not matter, what matters is that the GLSL bool is 4 bytes
283 const qint32 v = inValue.value<bool>();
284 setUniform(ubufData, name, &v, sizeof(qint32));
285 }
286 break;
288 {
289 const bool_2 b = inValue.value<bool_2>();
290 const qint32_2 v(b.x, b.y);
291 setUniform(ubufData, name, &v, 2 * sizeof(qint32));
292 }
293 break;
295 {
296 const bool_3 b = inValue.value<bool_3>();
297 const qint32_3 v(b.x, b.y, b.z);
298 setUniform(ubufData, name, &v, 3 * sizeof(qint32));
299 }
300 break;
302 {
303 const bool_4 b = inValue.value<bool_4>();
304 const qint32_4 v(b.x, b.y, b.z, b.w);
305 setUniform(ubufData, name, &v, 4 * sizeof(qint32));
306 }
307 break;
309 {
310 const float v = inValue.value<float>();
311 setUniform(ubufData, name, &v, sizeof(float));
312 }
313 break;
315 {
316 const QVector2D v = inValue.value<QVector2D>();
317 setUniform(ubufData, name, &v, 2 * sizeof(float));
318 }
319 break;
321 {
322 const QVector3D v = inValue.value<QVector3D>();
323 setUniform(ubufData, name, &v, 3 * sizeof(float));
324 }
325 break;
327 {
328 const QVector4D v = inValue.value<QVector4D>();
329 setUniform(ubufData, name, &v, 4 * sizeof(float));
330 }
331 break;
333 {
334 const QVector4D v = color::sRGBToLinear(inValue.value<QColor>());
335 setUniform(ubufData, name, &v, 4 * sizeof(float));
336 }
337 break;
339 {
340 const quint32 v = inValue.value<quint32>();
341 setUniform(ubufData, name, &v, sizeof(quint32));
342 }
343 break;
345 {
346 const quint32_2 v = inValue.value<quint32_2>();
347 setUniform(ubufData, name, &v, 2 * sizeof(quint32));
348 }
349 break;
351 {
352 const quint32_3 v = inValue.value<quint32_3>();
353 setUniform(ubufData, name, &v, 3 * sizeof(quint32));
354 }
355 break;
357 {
358 const quint32_4 v = inValue.value<quint32_4>();
359 setUniform(ubufData, name, &v, 4 * sizeof(quint32));
360 }
361 break;
363 {
364 const QMatrix3x3 m = inValue.value<QMatrix3x3>();
365 setUniform(ubufData, name, m.constData(), 12 * sizeof(float), nullptr, QSSGRhiShaderPipeline::UniformFlag::Mat3);
366 }
367 break;
369 {
370 const QMatrix4x4 v = inValue.value<QMatrix4x4>();
371 setUniform(ubufData, name, v.constData(), 16 * sizeof(float));
372 }
373 break;
375 {
376 const QSize s = inValue.value<QSize>();
377 float v[2] = { float(s.width()), float(s.height()) };
378 setUniform(ubufData, name, v, 2 * sizeof(float));
379 }
380 break;
382 {
383 const QSizeF s = inValue.value<QSizeF>();
384 float v[2] = { float(s.width()), float(s.height()) };
385 setUniform(ubufData, name, v, 2 * sizeof(float));
386 }
387 break;
389 {
390 const QPoint p = inValue.value<QPoint>();
391 float v[2] = { float(p.x()), float(p.y()) };
392 setUniform(ubufData, name, v, 2 * sizeof(float));
393 }
394 break;
396 {
397 const QPointF p = inValue.value<QPointF>();
398 float v[2] = { float(p.x()), float(p.y()) };
399 setUniform(ubufData, name, v, 2 * sizeof(float));
400 }
401 break;
403 {
404 const QRect r = inValue.value<QRect>();
405 float v[4] = { float(r.x()), float(r.y()), float(r.width()), float(r.height()) };
406 setUniform(ubufData, name, v, 4 * sizeof(float));
407 }
408 break;
410 {
411 const QRectF r = inValue.value<QRectF>();
412 float v[4] = { float(r.x()), float(r.y()), float(r.width()), float(r.height()) };
413 setUniform(ubufData, name, v, 4 * sizeof(float));
414 }
415 break;
417 {
418 const QQuaternion q = inValue.value<QQuaternion>();
419 float v[4] = { float(q.x()), float(q.y()), float(q.z()), float(q.scalar()) };
420 setUniform(ubufData, name, v, 4 * sizeof(float));
421 }
422 break;
423 default:
424 qWarning("Attempted to set uniform %s value with unsupported data type %i",
425 name, int(inType));
426 break;
427 }
428}
429
431{
432 auto iter = m_ub0.constFind(name);
433 if (iter != m_ub0.cend())
434 return iter->offset;
435 return -1;
436}
437
438void QSSGRhiShaderPipeline::setUniform(char *ubufData, const char *name, const void *data, size_t size, int *storeIndex, UniformFlags flags)
439{
440 int index = -1;
441 if (!storeIndex || *storeIndex == -1) {
443 auto it = m_uniformIndex.constFind(ba);
444 if (it != m_uniformIndex.cend()) {
445 index = int(*it);
446 } else if (ba.size() < qsizetype(sizeof(QSSGRhiShaderUniform::name))) {
448 memcpy(u.name, name, ba.size() + 1);
449 u.size = size;
450
451 const int new_idx = m_uniforms.size();
452 m_uniformIndex[name] = new_idx; // key is name, not ba, this has to be a deep copy QByteArray
453 m_uniforms.push_back(u);
454 index = new_idx;
455 } else {
456 qWarning("Attempted to set uniform with too long name: %s", name);
457 return;
458 }
459 if (storeIndex)
460 *storeIndex = index;
461 } else {
462 index = *storeIndex;
463 }
464
465 Q_ASSERT(index >= 0);
466 QSSGRhiShaderUniform &u = m_uniforms[index];
467 if (size <= u.size) {
468 if (u.offset == SIZE_MAX && u.maybeExists) {
469 auto it = m_ub0.constFind(QByteArray::fromRawData(u.name, strlen(u.name)));
470 if (it != m_ub0.constEnd()) {
471 u.offset = it->offset;
472#ifdef QT_DEBUG
473 if (int(u.size) != it->size) {
474 qWarning("Uniform block member '%s' got %d bytes whereas the true size is %d",
475 it->name.constData(),
476 int(u.size),
477 it->size);
478 return;
479 }
480#endif
481 }
482 }
483 if (u.offset == SIZE_MAX) {
484 // must silently ignore uniforms that are not in the actual shader
485 u.maybeExists = false; // but do not try again
486 return;
487 }
488
489 char *dst = ubufData + u.offset;
490 if (flags.testFlag(UniformFlag::Mat3)) {
491 // mat3 is still 4 floats per column in the uniform buffer (but there
492 // is no 4th column), so 48 bytes altogether, not 36 or 64.
493 const float *src = static_cast<const float *>(data);
494 memcpy(dst, src, 3 * sizeof(float));
495 memcpy(dst + 4 * sizeof(float), src + 3, 3 * sizeof(float));
496 memcpy(dst + 8 * sizeof(float), src + 6, 3 * sizeof(float));
497 } else {
498 memcpy(dst, data, size);
499 }
500 } else {
501 qWarning("Attempted to set %u bytes to uniform %s with size %u", uint(size), name, uint(u.size));
502 }
503}
504
505// Quick3D uniform buffer is std140 type and all array data should be stored in this rule.
506// You can check it in glspec45.core.pdf's 7.6.2.2.(4)
507// https://www.khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf
508void QSSGRhiShaderPipeline::setUniformArray(char *ubufData, const char *name, const void *data, size_t itemCount, QSSGRenderShaderDataType type, int *storeIndex)
509{
510 QSSGRhiShaderUniformArray *ua = nullptr;
511 constexpr size_t std140BaseTypeSize = 4 * sizeof(float);
512
513 if (!storeIndex || *storeIndex == -1) {
514 int index = -1;
516 auto it = m_uniformIndex.constFind(ba);
517 if (it != m_uniformIndex.cend()) {
518 index = int(*it);
519 ua = &m_uniformArrays[index];
520 } else if (ba.size() < qsizetype(sizeof(QSSGRhiShaderUniformArray::name))) {
521 index = m_uniformArrays.size();
522 m_uniformArrays.push_back(QSSGRhiShaderUniformArray());
523 m_uniformIndex[name] = index; // key needs deep copy
524 ua = &m_uniformArrays.last();
525 memcpy(ua->name, name, ba.size() + 1);
526 } else {
527 qWarning("Attempted to set uniform array with too long name: %s", name);
528 return;
529 }
530 if (storeIndex)
531 *storeIndex = index;
532 } else {
533 ua = &m_uniformArrays[*storeIndex];
534 }
535
536 if (!ua)
537 return;
538
539 if (ua->offset == SIZE_MAX && ua->maybeExists) {
540 auto it = m_ub0.constFind(QByteArray::fromRawData(ua->name, strlen(ua->name)));
541 if (it != m_ub0.constEnd()) {
542 ua->offset = it->offset;
543 ua->size = it->size;
544 }
545 }
546 if (ua->offset == SIZE_MAX) {
547 // must silently ignore uniforms that are not in the actual shader
548 ua->maybeExists = false; // but do not try again
549 return;
550 }
551
552#ifdef QT_DEBUG
553 auto checkSize = [std140BaseTypeSize](QSSGRhiShaderUniformArray *ua) -> bool {
554 Q_UNUSED(std140BaseTypeSize); // Silence clang warning about unneeded lambda capture
555 const size_t uniformSize = std140BaseTypeSize < ua->typeSize ? ua->typeSize * ua->itemCount : std140BaseTypeSize * ua->itemCount;
556 if (uniformSize != ua->size) {
557 qWarning("Uniform block member '%s' got %d bytes whereas the true size is %d",
558 ua->name,
559 int(uniformSize),
560 int(ua->size));
561 return false;
562 }
563 return true;
564 };
565#endif
566
567 char *p = ubufData + ua->offset;
568
569 switch (type) {
571 {
572 const qint32 *v = static_cast<const qint32 *>(data);
573 if (sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
574 ua->typeSize = sizeof(qint32);
575 ua->itemCount = itemCount;
576 }
577#ifdef QT_DEBUG
578 if (!checkSize(ua))
579 return;
580#endif
581 for (size_t i = 0; i < itemCount; ++i)
582 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
583 }
584 break;
586 {
587 const qint32_2 *v = static_cast<const qint32_2 *>(data);
588 if (2 * sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
589 ua->typeSize = 2 * sizeof(qint32);
590 ua->itemCount = itemCount;
591 }
592#ifdef QT_DEBUG
593 if (!checkSize(ua))
594 return;
595#endif
596 for (size_t i = 0; i < itemCount; ++i)
597 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
598 }
599 break;
601 {
602 const qint32_3 *v = static_cast<const qint32_3 *>(data);
603 if (3 * sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
604 ua->typeSize = 3 * sizeof(qint32);
605 ua->itemCount = itemCount;
606 }
607#ifdef QT_DEBUG
608 if (!checkSize(ua))
609 return;
610#endif
611 for (size_t i = 0; i < itemCount; ++i)
612 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
613 }
614 break;
616 {
617 const qint32_4 *v = static_cast<const qint32_4 *>(data);
618 if (4 * sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
619 ua->typeSize = 4 * sizeof(qint32);
620 ua->itemCount = itemCount;
621 }
622#ifdef QT_DEBUG
623 if (!checkSize(ua))
624 return;
625#endif
626 memcpy(p, v, ua->typeSize * ua->itemCount);
627 }
628 break;
630 {
631 const float *v = static_cast<const float *>(data);
632 if (sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
633 ua->typeSize = sizeof(float);
634 ua->itemCount = itemCount;
635 }
636#ifdef QT_DEBUG
637 if (!checkSize(ua))
638 return;
639#endif
640 for (size_t i = 0; i < itemCount; ++i)
641 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
642 }
643 break;
645 {
646 const QVector2D *v = static_cast<const QVector2D *>(data);
647 if (2 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
648 ua->typeSize = 2 * sizeof(float);
649 ua->itemCount = itemCount;
650 }
651#ifdef QT_DEBUG
652 if (!checkSize(ua))
653 return;
654#endif
655 for (size_t i = 0; i < itemCount; ++i)
656 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
657 }
658 break;
660 {
661 const QVector3D *v = static_cast<const QVector3D *>(data);
662 if (3 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
663 ua->typeSize = 3 * sizeof(float);
664 ua->itemCount = itemCount;
665 }
666#ifdef QT_DEBUG
667 if (!checkSize(ua))
668 return;
669#endif
670 for (size_t i = 0; i < itemCount; ++i)
671 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
672 }
673 break;
675 {
676 const QVector4D *v = static_cast<const QVector4D *>(data);
677 if (4 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
678 ua->typeSize = 4 * sizeof(float);
679 ua->itemCount = itemCount;
680 }
681#ifdef QT_DEBUG
682 if (!checkSize(ua))
683 return;
684#endif
685 memcpy(p, v, ua->typeSize * ua->itemCount);
686 }
687 break;
689 {
690 const QColor *v = static_cast<const QColor *>(data);
691 if (4 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
692 ua->typeSize = 4 * sizeof(float);
693 ua->itemCount = itemCount;
694 }
695#ifdef QT_DEBUG
696 if (!checkSize(ua))
697 return;
698#endif
699 for (size_t i = 0; i < itemCount; ++i) {
700 const QVector4D vi = color::sRGBToLinear(v[i]);
701 memcpy(p + i * std140BaseTypeSize, &vi, ua->typeSize);
702 }
703 }
704 break;
706 {
707 const quint32 *v = static_cast<const quint32 *>(data);
708 if (sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
709 ua->typeSize = sizeof(quint32);
710 ua->itemCount = itemCount;
711 }
712#ifdef QT_DEBUG
713 if (!checkSize(ua))
714 return;
715#endif
716 for (size_t i = 0; i < itemCount; ++i)
717 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
718 }
719 break;
721 {
722 const quint32_2 *v = static_cast<const quint32_2 *>(data);
723 if (2 * sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
724 ua->typeSize = 2 * sizeof(quint32);
725 ua->itemCount = itemCount;
726 }
727#ifdef QT_DEBUG
728 if (!checkSize(ua))
729 return;
730#endif
731 for (size_t i = 0; i < itemCount; ++i)
732 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
733 }
734 break;
736 {
737 const quint32_3 *v = static_cast<const quint32_3 *>(data);
738 if (3 * sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
739 ua->typeSize = 3 * sizeof(quint32);
740 ua->itemCount = itemCount;
741 }
742#ifdef QT_DEBUG
743 if (!checkSize(ua))
744 return;
745#endif
746 for (size_t i = 0; i < itemCount; ++i)
747 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
748 }
749 break;
751 {
752 const quint32_4 *v = static_cast<const quint32_4 *>(data);
753 if (4 * sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
754 ua->typeSize = 4 * sizeof(quint32);
755 ua->itemCount = itemCount;
756 }
757#ifdef QT_DEBUG
758 if (!checkSize(ua))
759 return;
760#endif
761 memcpy(p, v, ua->typeSize * ua->itemCount);
762 }
763 break;
765 {
766 const QMatrix3x3 *v = static_cast<const QMatrix3x3 *>(data);
767 if (12 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
768 ua->typeSize = 12 * sizeof(float);
769 ua->itemCount = itemCount;
770 }
771#ifdef QT_DEBUG
772 if (!checkSize(ua))
773 return;
774#endif
775 for (uint i = 0; i < ua->itemCount; ++i) {
776 memcpy(p + i * ua->typeSize, v[i].constData(), 3 * sizeof(float));
777 memcpy(p + i * ua->typeSize + 4 * sizeof(float), v[i].constData() + 3, 3 * sizeof(float));
778 memcpy(p + i * ua->typeSize + 8 * sizeof(float), v[i].constData() + 6, 3 * sizeof(float));
779 }
780 }
781 break;
783 {
784 const QMatrix4x4 *v = static_cast<const QMatrix4x4 *>(data);
785 if (16 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
786 ua->typeSize = 16 * sizeof(float);
787 ua->itemCount = itemCount;
788 }
789#ifdef QT_DEBUG
790 if (!checkSize(ua))
791 return;
792#endif
793 for (uint i = 0; i < ua->itemCount; ++i)
794 memcpy(p + i * ua->typeSize, &v[i] , ua->typeSize);
795 }
796 break;
808 default:
809 qWarning("Attempted to set uniform %s value with type %d that is unsupported for uniform arrays",
810 name, int(type));
811 break;
812 }
813}
814
816{
817 const quint32 totalBufferSize = m_ub0NextUBufOffset + sizeof(QSSGShaderLightsUniformData);
818 if (!*ubuf) {
819 *ubuf = m_context.rhi()->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, totalBufferSize);
820 (*ubuf)->create();
821 }
822 if ((*ubuf)->size() < totalBufferSize) {
823 (*ubuf)->setSize(totalBufferSize);
824 (*ubuf)->create();
825 }
826}
827
829{
830 if (!*ubuf) {
831 *ubuf = m_context.rhi()->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, m_ub0Size);
832 (*ubuf)->create();
833 }
834}
835
837{
838 if (hint >= 0) {
839 const int binding = m_materialImageSamplerBindings[hint];
840 if (binding >= 0)
841 return binding;
842 }
843
844 auto it = m_combinedImageSamplers.constFind(QByteArray::fromRawData(name, strlen(name)));
845 const int binding = it != m_combinedImageSamplers.cend() ? it->binding : -1;
846 if (hint >= 0)
847 m_materialImageSamplerBindings[hint] = binding;
848
849 return binding;
850}
851
853 : m_rhi(rhi)
854 , m_stats(*this)
855{
856 Q_STATIC_ASSERT(int(QSSGRhiSamplerBindingHints::LightProbe) > int(QSSGRenderableImage::Type::Occlusion));
857}
858
859
861{
863
864 qDeleteAll(m_textures);
865 qDeleteAll(m_meshes);
866}
867
869{
870 for (QSSGRhiDrawCallData &dcd : m_drawCallData)
872
873 m_drawCallData.clear();
874
875 qDeleteAll(m_pipelines);
876 qDeleteAll(m_computePipelines);
877 qDeleteAll(m_srbCache);
878 qDeleteAll(m_dummyTextures);
879
880 m_pipelines.clear();
881 m_computePipelines.clear();
882 m_srbCache.clear();
883 m_dummyTextures.clear();
884
885 for (const auto &samplerInfo : std::as_const(m_samplers))
886 delete samplerInfo.second;
887
888 m_samplers.clear();
889
890 for (const auto &particleData : std::as_const(m_particleData))
891 delete particleData.texture;
892
893 m_particleData.clear();
894
895 for (const auto &instanceData : std::as_const(m_instanceBuffers)) {
896 if (instanceData.owned)
897 delete instanceData.buffer;
898 }
899
900 m_instanceBuffers.clear();
901
902 for (const auto &instanceData : std::as_const(m_instanceBuffersLod)) {
903 if (instanceData.owned)
904 delete instanceData.buffer;
905 }
906
907 m_instanceBuffersLod.clear();
908}
909
911{
912 Q_ASSERT(rhi && !m_rhi);
913 m_rhi = rhi;
914}
915
917{
918 auto it = m_srbCache.constFind(bindings);
919 if (it != m_srbCache.constEnd())
920 return *it;
921
923 srb->setBindings(bindings.v, bindings.v + bindings.p);
924 if (srb->create()) {
925 m_srbCache.insert(bindings, srb);
926 } else {
927 qWarning("Failed to build srb");
928 delete srb;
929 srb = nullptr;
930 }
931 return srb;
932}
933
935{
936 delete dcd.ubuf;
937 dcd.ubuf = nullptr;
938 auto srb = m_srbCache.take(dcd.bindings);
939 QSSG_CHECK(srb == dcd.srb);
940 delete srb;
941 dcd.srb = nullptr;
942 dcd.pipeline = nullptr;
943}
944
948{
949 auto it = m_pipelines.constFind(key);
950 if (it != m_pipelines.constEnd())
951 return it.value();
952
953 // Build a new one. This is potentially expensive.
955
956 ps->setShaderStages(key.state.shaderPipeline->cbeginStages(), key.state.shaderPipeline->cendStages());
957 ps->setVertexInputLayout(key.state.ia.inputLayout);
959 ps->setRenderPassDescriptor(rpDesc);
960
961 QRhiGraphicsPipeline::Flags flags;
962 if (key.state.scissorEnable)
964
965 static const bool shaderDebugInfo = qEnvironmentVariableIntValue("QT_QUICK3D_SHADER_DEBUG_INFO");
966 if (shaderDebugInfo)
968 ps->setFlags(flags);
969
970 ps->setTopology(key.state.ia.topology);
971 ps->setCullMode(key.state.cullMode);
972 if (key.state.ia.topology == QRhiGraphicsPipeline::Lines || key.state.ia.topology == QRhiGraphicsPipeline::LineStrip)
973 ps->setLineWidth(key.state.lineWidth);
974
975 QRhiGraphicsPipeline::TargetBlend blend = key.state.targetBlend;
976 blend.enable = key.state.blendEnable;
977 QVarLengthArray<QRhiGraphicsPipeline::TargetBlend, 8> targetBlends(key.state.colorAttachmentCount);
978 for (int i = 0; i < key.state.colorAttachmentCount; ++i)
979 targetBlends[i] = blend;
980 ps->setTargetBlends(targetBlends.cbegin(), targetBlends.cend());
981
982 ps->setSampleCount(key.state.samples);
983
984 ps->setDepthTest(key.state.depthTestEnable);
985 ps->setDepthWrite(key.state.depthWriteEnable);
986 ps->setDepthOp(key.state.depthFunc);
987
988 ps->setDepthBias(key.state.depthBias);
989 ps->setSlopeScaledDepthBias(key.state.slopeScaledDepthBias);
990 ps->setPolygonMode(key.state.polygonMode);
991
992 if (key.state.usesStencilRef)
994 ps->setFlags(flags);
995 ps->setStencilFront(key.state.stencilOpFrontState);
996 ps->setStencilTest(key.state.usesStencilRef);
997 ps->setStencilWriteMask(key.state.stencilWriteMask);
998
999 if (!ps->create()) {
1000 qWarning("Failed to build graphics pipeline state");
1001 delete ps;
1002 return nullptr;
1003 }
1004
1005 m_pipelines.insert(key, ps);
1006 return ps;
1007}
1008
1011{
1012 auto it = m_computePipelines.constFind(key);
1013 if (it != m_computePipelines.constEnd())
1014 return it.value();
1015
1019 if (!computePipeline->create()) {
1020 qWarning("Failed to build compute pipeline");
1021 delete computePipeline;
1022 return nullptr;
1023 }
1024 m_computePipelines.insert(key, computePipeline);
1025 return computePipeline;
1026}
1027
1029
1031{
1032 auto compareSampler = [samplerDescription](const SamplerInfo &info){ return info.first == samplerDescription; };
1033 const auto found = std::find_if(m_samplers.cbegin(), m_samplers.cend(), compareSampler);
1034 if (found != m_samplers.cend())
1035 return found->second;
1036
1037 QRhiSampler *newSampler = m_rhi->newSampler(samplerDescription.magFilter,
1038 samplerDescription.minFilter,
1039 samplerDescription.mipmap,
1040 samplerDescription.hTiling,
1041 samplerDescription.vTiling,
1042 samplerDescription.zTiling);
1043 if (!newSampler->create()) {
1044 qWarning("Failed to build image sampler");
1045 delete newSampler;
1046 return nullptr;
1047 }
1048 m_samplers << SamplerInfo{samplerDescription, newSampler};
1049 return newSampler;
1050}
1051
1053{
1054 if (samplerDescription->mipmap != QRhiSampler::None
1055 || samplerDescription->hTiling != QRhiSampler::ClampToEdge
1056 || samplerDescription->vTiling != QRhiSampler::ClampToEdge
1057 || samplerDescription->zTiling != QRhiSampler::ClampToEdge)
1058 {
1060 return;
1061
1062 const QSize pixelSize = texture->pixelSize();
1063 const int w = qNextPowerOfTwo(pixelSize.width() - 1);
1064 const int h = qNextPowerOfTwo(pixelSize.height() - 1);
1065 if (w != pixelSize.width() || h != pixelSize.height()) {
1066 static bool warnShown = false;
1067 if (!warnShown) {
1068 warnShown = true;
1069 qWarning("Attempted to use an unsupported filtering or wrap mode, "
1070 "this is likely due to lacking proper support for non-power-of-two textures on this platform.\n"
1071 "If this is with WebGL, try updating the application to use QQuick3D::idealSurfaceFormat() in main() "
1072 "in order to ensure WebGL 2 is used.");
1073 }
1074 samplerDescription->mipmap = QRhiSampler::None;
1075 samplerDescription->hTiling = QRhiSampler::ClampToEdge;
1076 samplerDescription->vTiling = QRhiSampler::ClampToEdge;
1077 samplerDescription->zTiling = QRhiSampler::ClampToEdge;
1078 }
1079 }
1080}
1081
1083{
1084 m_textures.insert(texture);
1085}
1086
1088{
1089 m_textures.remove(texture);
1090 delete texture;
1091}
1092
1094{
1095 m_meshes.insert(mesh);
1096}
1097
1099{
1100 QSSG_ASSERT(mesh, return);
1101 for (auto subset : mesh->subsets) {
1102 if (subset.rhi.targetsTexture)
1103 releaseTexture(subset.rhi.targetsTexture);
1104 }
1105 m_meshes.remove(mesh);
1106 delete mesh;
1107}
1108
1110{
1111 // Find all QSSGRhiUniformBufferSet that reference model
1112 // and delete them
1113 const void *modelNode = model;
1114 auto it = m_drawCallData.begin();
1115 while (it != m_drawCallData.end()) {
1116 if (it.key().model == modelNode) {
1118 it = m_drawCallData.erase(it);
1119 } else {
1120 ++it;
1121 }
1122 }
1123}
1124
1126 const QSize &size, const QColor &fillColor)
1127{
1128 auto it = m_dummyTextures.constFind({flags, size, fillColor});
1129 if (it != m_dummyTextures.constEnd())
1130 return *it;
1131
1133 if (t->create()) {
1134 QImage image(t->pixelSize(), QImage::Format_RGBA8888);
1135 image.fill(fillColor);
1136 rub->uploadTexture(t, image);
1137 } else {
1138 qWarning("Failed to build dummy texture");
1139 }
1140
1141 m_dummyTextures.insert({flags, size, fillColor}, t);
1142 return t;
1143}
1144
1146{
1147 static const bool isSet = (qEnvironmentVariableIntValue("QT_RHI_SHADER_DEBUG") != 0);
1148 return isSet;
1149}
1150
1152{
1153 static const bool isSet = (qEnvironmentVariableIntValue("QT_QUICK3D_EDITORMODE") != 0);
1154 return isSet;
1155}
1156
1158{
1159 layerKey = layer;
1161 info.renderPasses.clear();
1162 info.externalRenderPass = {};
1163 info.currentRenderPassIndex = -1;
1164}
1165
1167{
1168 if (rendererDebugEnabled()) {
1170 const int rpCount = info.renderPasses.size();
1171 qDebug("%d render passes in 3D renderer %p", rpCount, layer);
1172 for (int i = 0; i < rpCount; ++i) {
1173 const RenderPassInfo &rp(info.renderPasses[i]);
1174 qDebug("Render pass %d: rt name='%s' target size %dx%d pixels",
1175 i, rp.rtName.constData(), rp.pixelSize.width(), rp.pixelSize.height());
1176 printRenderPass(rp);
1177 }
1178 if (info.externalRenderPass.indexedDraws.callCount || info.externalRenderPass.instancedIndexedDraws.callCount
1179 || info.externalRenderPass.draws.callCount || info.externalRenderPass.instancedDraws.callCount)
1180 {
1181 qDebug("Within external render passes:");
1182 printRenderPass(info.externalRenderPass);
1183 }
1184 }
1185
1186 // a new start() may preceed stop() for the previous View3D, must handle this gracefully
1187 if (layerKey == layer)
1188 layerKey = nullptr;
1189
1190 // The data must stay valid until the next start() with the same key, the
1191 // QQuick3DRenderStats and DebugView may read it.
1192}
1193
1195{
1196 perLayerInfo.remove(layer);
1198}
1199
1201{
1203 Q_TRACE(QSSG_renderPass_entry, QString::fromUtf8(rt->name()));
1204 info.renderPasses.append({ rt->name(), rt->pixelSize(), {}, {}, {}, {} });
1205 info.currentRenderPassIndex = info.renderPasses.size() - 1;
1206}
1207
1209{
1210 Q_TRACE(QSSG_renderPass_exit);
1212 info.currentRenderPassIndex = -1;
1213}
1214
1216{
1218 || Q_TRACE_ENABLED(QSSG_draw);
1219}
1220
1222{
1223 Q_TRACE(QSSG_drawIndexed, indexCount, instanceCount);
1225 RenderPassInfo &rp(info.currentRenderPassIndex >= 0 ? info.renderPasses[info.currentRenderPassIndex] : info.externalRenderPass);
1226 if (instanceCount > 1) {
1228 rp.instancedIndexedDraws.vertexOrIndexCount += indexCount;
1229 rp.instancedIndexedDraws.instanceCount += instanceCount;
1230 } else {
1231 rp.indexedDraws.callCount += 1;
1232 rp.indexedDraws.vertexOrIndexCount += indexCount;
1233 }
1234}
1235
1237{
1238 Q_TRACE(QSSG_draw, vertexCount, instanceCount);
1240 RenderPassInfo &rp(info.currentRenderPassIndex >= 0 ? info.renderPasses[info.currentRenderPassIndex] : info.externalRenderPass);
1241 if (instanceCount > 1) {
1242 rp.instancedDraws.callCount += 1;
1243 rp.instancedDraws.vertexOrIndexCount += vertexCount;
1244 rp.instancedDraws.instanceCount += instanceCount;
1245 } else {
1246 rp.draws.callCount += 1;
1247 rp.draws.vertexOrIndexCount += vertexCount;
1248 }
1249}
1250
1252{
1253 qDebug("%llu indexed draw calls with %llu indices in total, "
1254 "%llu non-indexed draw calls with %llu vertices in total",
1258 qDebug("%llu instanced indexed draw calls with %llu indices and %llu instances in total, "
1259 "%llu instanced non-indexed draw calls with %llu indices and %llu instances in total",
1262 }
1263}
1264
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
qint64 size() const
Returns the file size in bytes.
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1202
const_iterator constFind(const Key &key) const noexcept
Definition qhash.h:1279
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1209
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it.
Definition qhash.h:975
iterator erase(const_iterator it)
Definition qhash.h:1223
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1206
const_iterator cend() const noexcept
Definition qhash.h:1208
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
\inmodule QtGui
Definition qimage.h:37
@ Format_RGBA8888
Definition qimage.h:59
Definition qlist.h:74
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
\inmodule QtCore\reentrant
Definition qpoint.h:214
\inmodule QtCore\reentrant
Definition qpoint.h:23
The QQuaternion class represents a quaternion consisting of a vector and scalar.
Definition qquaternion.h:21
\inmodule QtCore\reentrant
Definition qrect.h:483
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtGui
Definition qrhi.h:834
quint32 size() const
Definition qrhi.h:863
Type
Specifies storage type of buffer resource.
Definition qrhi.h:836
@ Dynamic
Definition qrhi.h:839
@ UniformBuffer
Definition qrhi.h:845
virtual bool create()=0
Creates the corresponding native graphics resources.
IndexFormat
Specifies the index data type.
Definition qrhi.h:1616
\inmodule QtGui
Definition qrhi.h:1585
virtual bool create()=0
void setShaderStage(const QRhiShaderStage &stage)
Sets the shader to use.
Definition qrhi.h:1599
void setShaderResourceBindings(QRhiShaderResourceBindings *srb)
Associates with srb describing the resource binding layout and the resources (QRhiBuffer,...
Definition qrhi.h:1602
\inmodule QtGui
Definition qrhi.h:1241
@ CompileShadersWithDebugInfo
Definition qrhi.h:1247
void setStencilFront(const StencilOpState &state)
Sets the stencil test state for front faces.
Definition qrhi.h:1394
void setCullMode(CullMode mode)
Sets the specified face culling mode.
Definition qrhi.h:1364
void setTargetBlends(std::initializer_list< TargetBlend > list)
Sets the list of render target blend settings.
Definition qrhi.h:1369
void setStencilTest(bool enable)
Enables or disables stencil tests based on enable.
Definition qrhi.h:1391
void setDepthWrite(bool enable)
Controls the writing out of depth data into the depth buffer based on enable.
Definition qrhi.h:1385
void setShaderResourceBindings(QRhiShaderResourceBindings *srb)
Associates with srb describing the resource binding layout and the resources (QRhiBuffer,...
Definition qrhi.h:1433
void setDepthOp(CompareOp op)
Sets the depth comparison function op.
Definition qrhi.h:1388
void setSlopeScaledDepthBias(float bias)
Sets the slope scaled depth bias.
Definition qrhi.h:1415
void setVertexInputLayout(const QRhiVertexInputLayout &layout)
Specifies the vertex input layout.
Definition qrhi.h:1430
CullMode
Specifies the culling mode.
Definition qrhi.h:1261
void setFlags(Flags f)
Sets the flags f.
Definition qrhi.h:1358
void setShaderStages(std::initializer_list< QRhiShaderStage > list)
Sets the list of shader stages.
Definition qrhi.h:1417
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Associates with the specified QRhiRenderPassDescriptor desc.
Definition qrhi.h:1436
void setSampleCount(int s)
Sets the sample count.
Definition qrhi.h:1406
void setTopology(Topology t)
Sets the primitive topology t.
Definition qrhi.h:1361
Topology
Specifies the primitive topology.
Definition qrhi.h:1251
virtual bool create()=0
Creates the corresponding native graphics resources.
void setDepthTest(bool enable)
Enables or disables depth testing based on enable.
Definition qrhi.h:1382
void setDepthBias(int bias)
Sets the depth bias.
Definition qrhi.h:1412
void setPolygonMode(PolygonMode mode)
Sets the polygon mode.
Definition qrhi.h:1442
void setLineWidth(float width)
Sets the line width.
Definition qrhi.h:1409
void setStencilWriteMask(quint32 mask)
Sets the stencil write mask.
Definition qrhi.h:1403
\inmodule QtGui
Definition qrhi.h:1119
virtual QSize pixelSize() const =0
\inmodule QtGui
Definition qrhi.h:1694
void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
Enqueues uploading the image data for one or more mip levels in one or more layers of the texture tex...
Definition qrhi.cpp:8681
QByteArray name() const
Definition qrhi.cpp:3430
\inmodule QtGui
Definition qrhi.h:1007
virtual bool create()=0
@ ClampToEdge
Definition qrhi.h:1017
\inmodule QtGui
Definition qrhi.h:1190
void setBindings(std::initializer_list< QRhiShaderResourceBinding > list)
Sets the list of bindings.
Definition qrhi.h:1194
virtual bool create()=0
\inmodule QtGui
Definition qrhi.h:371
QShader shader() const
Definition qrhi.h:389
Type type() const
Definition qrhi.h:386
\inmodule QtGui
Definition qrhi.h:1161
\inmodule QtGui
Definition qrhi.h:883
\inmodule QtGui
Definition qrhi.h:232
Format
Specifies the type of the element data.
Definition qrhi.h:234
const QRhiVertexInputAttribute * cendAttributes() const
Definition qrhi.h:337
void setAttributes(std::initializer_list< QRhiVertexInputAttribute > list)
Sets the attributes from the specified list.
Definition qrhi.h:329
const QRhiVertexInputAttribute * cbeginAttributes() const
Definition qrhi.h:336
\inmodule QtGui
Definition qrhi.h:1767
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
Definition qrhi.cpp:10079
int ubufAligned(int v) const
Definition qrhi.cpp:9570
bool isFeatureSupported(QRhi::Feature feature) const
Definition qrhi.cpp:9681
QRhiShaderResourceBindings * newShaderResourceBindings()
Definition qrhi.cpp:10060
QRhiComputePipeline * newComputePipeline()
Definition qrhi.cpp:10050
QRhiSampler * newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW=QRhiSampler::Repeat)
Definition qrhi.cpp:10228
QRhiGraphicsPipeline * newGraphicsPipeline()
Definition qrhi.cpp:10037
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition qrhi.cpp:10133
@ NPOTTextureRepeat
Definition qrhi.h:1803
virtual ~QSSGRhiBuffer()
QSSGRhiBuffer(QSSGRhiContext &context, QRhiBuffer::Type type, QRhiBuffer::UsageFlags usageMask, quint32 stride, qsizetype size, QRhiCommandBuffer::IndexFormat indexFormat=QRhiCommandBuffer::IndexUInt16)
static bool rendererDebugEnabled()
void start(QSSGRenderLayer *layer)
QSSGRenderLayer * layerKey
void cleanupLayerInfo(QSSGRenderLayer *layer)
void beginRenderPass(QRhiTextureRenderTarget *rt)
static bool profilingEnabled()
QHash< QSSGRenderLayer *, PerLayerInfo > perLayerInfo
void drawIndexed(quint32 indexCount, quint32 instanceCount)
void draw(quint32 vertexCount, quint32 instanceCount)
void stop(QSSGRenderLayer *layer)
QSet< QSSGRenderLayer * > dynamicDataSources
void printRenderPass(const RenderPassInfo &rp)
QRhiTexture * dummyTexture(QRhiTexture::Flags flags, QRhiResourceUpdateBatch *rub, const QSize &size=QSize(64, 64), const QColor &fillColor=Qt::black)
void releaseDrawCallData(QSSGRhiDrawCallData &dcd)
void initialize(QRhi *rhi)
void cleanupDrawCallData(const QSSGRenderModel *model)
void releaseMesh(QSSGRenderMesh *mesh)
static bool shaderDebuggingEnabled()
QSSGRhiContext(QRhi *rhi=nullptr)
static bool editorMode()
void checkAndAdjustForNPoT(QRhiTexture *texture, QSSGRhiSamplerDescription *samplerDescription)
void registerMesh(QSSGRenderMesh *mesh)
void releaseCachedResources()
void releaseTexture(QRhiTexture *texture)
void registerTexture(QRhiTexture *texture)
QRhiShaderResourceBindings * srb(const QSSGRhiShaderResourceBindingList &bindings)
QRhiComputePipeline * computePipeline(const QSSGComputePipelineStateKey &key, QRhiShaderResourceBindings *srb)
QRhiGraphicsPipeline * pipeline(const QSSGGraphicsPipelineStateKey &key, QRhiRenderPassDescriptor *rpDesc, QRhiShaderResourceBindings *srb)
QRhi * rhi() const
QRhiSampler * sampler(const QSSGRhiSamplerDescription &samplerDescription)
QSSGRhiParticleData & particleData(const QSSGRenderGraphObject *particlesOrModel)
void setUniformValue(char *ubufData, const char *name, const QVariant &value, QSSGRenderShaderDataType type)
void addStage(const QRhiShaderStage &stage, StageFlags flags={})
void ensureUniformBuffer(QRhiBuffer **ubuf)
int offsetOfUniform(const QByteArray &name)
void ensureCombinedMainLightsUniformBuffer(QRhiBuffer **ubuf)
int bindingForTexture(const char *name, int hint=-1)
void setUniformArray(char *ubufData, const char *name, const void *data, size_t itemCount, QSSGRenderShaderDataType type, int *storeIndex=nullptr)
struct QSSGRhiShaderPipeline::InstanceLocations instanceLocations
void setUniform(char *ubufData, const char *name, const void *data, size_t size, int *storeIndex=nullptr, UniformFlags flags={})
qsizetype size() const
Definition qset.h:50
bool remove(const T &value)
Definition qset.h:63
bool isEmpty() const
Definition qset.h:52
iterator insert(const T &value)
Definition qset.h:155
QList< InOutVariable > inputVariables() const
QList< InOutVariable > combinedImageSamplers() const
QList< UniformBlock > uniformBlocks() const
QShaderDescription description() const
Definition qshader.cpp:340
\inmodule QtCore
Definition qsize.h:207
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
constexpr size_type size() const noexcept
const T & at(qsizetype idx) const
const_iterator cbegin() const noexcept
const_iterator cend() const noexcept
void append(const T &t)
void push_back(const T &t)
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
const void * constData() const
Definition qvariant.h:446
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
#define this
Definition dialogs.cpp:9
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
Definition image.cpp:4
static void * context
#define Q_STATIC_ASSERT(Condition)
Definition qassert.h:105
std::pair< T1, T2 > QPair
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
static int instanceCount
static struct AttrInfo attrs[]
EGLOutputLayerEXT layer
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
constexpr quint32 qNextPowerOfTwo(quint32 v)
Definition qmath.h:335
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLenum src
const void GLsizei GLsizei stride
GLenum type
GLenum GLenum dst
GLbitfield flags
GLenum GLuint texture
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLfloat GLfloat GLfloat GLfloat h
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei GLsizei GLuint * shaders
Definition qopenglext.h:677
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QSSG_ASSERT_X(cond, msg, action)
#define QSSG_CHECK(cond)
#define QSSG_ASSERT(cond, action)
QSSGRenderShaderDataType
QSSGRenderComponentType
QPair< QSSGRhiSamplerDescription, QRhiSampler * > SamplerInfo
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define Q_UNUSED(x)
#define Q_TRACE_ENABLED(x)
Definition qtrace_p.h:148
#define Q_TRACE(x,...)
Definition qtrace_p.h:144
#define Q_TRACE_POINT(provider, tracepoint,...)
Definition qtrace_p.h:232
unsigned int quint32
Definition qtypes.h:45
int qint32
Definition qtypes.h:44
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
QSqlQueryModel * model
[16]
QByteArray ba
[0]
QFileInfo info(fileName)
[8]
QSemaphore sem(5)
[0]
static const char * getLightmapUVAttrName()
Definition qssgmesh_p.h:353
static const char * getNormalAttrName()
Definition qssgmesh_p.h:350
static const char * getUV1AttrName()
Definition qssgmesh_p.h:352
static const char * getTexBinormalAttrName()
Definition qssgmesh_p.h:355
static const char * getPositionAttrName()
Definition qssgmesh_p.h:349
static const char * getTexTanAttrName()
Definition qssgmesh_p.h:354
static const char * getColorAttrName()
Definition qssgmesh_p.h:356
static const char * getJointAttrName()
Definition qssgmesh_p.h:357
static const char * getUV0AttrName()
Definition qssgmesh_p.h:351
static const char * getWeightAttrName()
Definition qssgmesh_p.h:358
QVector< QSSGRenderSubset > subsets
QSSGRhiShaderResourceBindingList bindings
QRhiShaderResourceBindings * srb
QRhiGraphicsPipeline * pipeline
static QRhiGraphicsPipeline::CullMode toCullMode(QSSGCullFaceMode cullFaceMode)
static QRhiVertexInputAttribute::Format toVertexInputFormat(QSSGRenderComponentType compType, quint32 numComps)
static QRhiGraphicsPipeline::Topology toTopology(QSSGRenderDrawMode drawMode)
void bakeVertexInputLocations(const QSSGRhiShaderPipeline &shaders, int instanceBufferBinding=0)
QVarLengthArray< InputSemantic, 8 > inputs
QRhiVertexInputLayout inputLayout
QRhiSampler::AddressMode hTiling
QRhiSampler::Filter minFilter
QRhiSampler::Filter magFilter
QRhiSampler::AddressMode vTiling
QRhiSampler::Filter mipmap
QRhiSampler::AddressMode zTiling
QRhiShaderResourceBinding v[MAX_SIZE]
\variable QShaderDescription::InOutVariable::name
\variable QShaderDescription::BlockVariable::name