Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
6#include <QtCore/qvariant.h>
7#include <QtGui/private/qrhi_p.h>
8
9#include <QtQuick3DUtils/private/qquick3dprofiler_p.h>
10#include <QtQuick3DUtils/private/qssgmesh_p.h>
11#include <QtQuick3DUtils/private/qssgassert_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgrenderableimage_p.h>
13#include <QtQuick3DRuntimeRender/private/qssgrendermesh_p.h>
14#include <QtQuick3DUtils/private/qssgutils_p.h>
15#include <QtQuick3DUtils/private/qssgassert_p.h>
16#include <qtquick3d_tracepoints_p.h>
17
19
20Q_TRACE_POINT(qtquick3d, QSSG_renderPass_entry, const QString &renderPass);
21Q_TRACE_POINT(qtquick3d, QSSG_renderPass_exit);
22Q_TRACE_POINT(qtquick3d, QSSG_drawIndexed, int indexCount, int instanceCount);
23Q_TRACE_POINT(qtquick3d, QSSG_draw, int vertexCount, int instanceCount);
24
236 QRhiBuffer::UsageFlags usageMask,
240 : m_context(context),
241 m_stride(stride),
242 m_indexFormat(indexFormat)
243{
244 QSSG_ASSERT(size >= 0, size = 0);
245 m_buffer = m_context.rhi()->newBuffer(type, usageMask, quint32(size));
246 if (!m_buffer->create())
247 qWarning("Failed to build QRhiBuffer with size %d", m_buffer->size());
248}
249
251{
252 delete m_buffer;
253}
254
255namespace QSSGRhiHelpers {
257{
258 if (compType == QSSGRenderComponentType::Float32) {
259 switch (numComps) {
260 case 1:
262 case 2:
264 case 3:
266 case 4:
268 default:
269 break;
270 }
271 } else if (compType == QSSGRenderComponentType::UnsignedInt32) {
272 switch (numComps) {
273 case 1:
275 case 2:
277 case 3:
279 case 4:
281 default:
282 break;
283 }
284 } else if (compType == QSSGRenderComponentType::Int32) {
285 switch (numComps) {
286 case 1:
288 case 2:
290 case 3:
292 case 4:
294 default:
295 break;
296 }
297 }
298 Q_ASSERT(false);
300}
301
323
325{
326 if (!shaders.vertexStage())
327 return;
328
329 const auto &vertexInputs = shaders.vertexInputs();
330
331 QVarLengthArray<QRhiVertexInputAttribute, 8> attrs;
332 int inputIndex = 0;
333 for (auto it = ia->inputLayout.cbeginAttributes(), itEnd = ia->inputLayout.cendAttributes(); it != itEnd; ++it) {
334 const QSSGRhiInputAssemblerState::InputSemantic sem = ia->inputs.at(inputIndex); // avoid detaching - submeshes share the same name list
335 auto vertexInputVar = vertexInputs.constFind(sem);
336 if (vertexInputVar != vertexInputs.constEnd()) {
337 attrs.append(*it);
338 attrs.last().setLocation(vertexInputVar->location);
339 } // else the mesh has an input attribute that is not declared and used in the vertex shader - that's fine
340
341 ++inputIndex;
342 }
343
344 // Add instance buffer input if necessary
345 if (instanceBufferBinding > 0) {
346 auto instanceBufferLocations = shaders.instanceBufferLocations();
347 // transform0
348 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
349 instanceBufferLocations.transform0,
351 0));
352 // transform1
353 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
354 instanceBufferLocations.transform1,
356 sizeof(float) * 4));
357 // transform2
358 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
359 instanceBufferLocations.transform2,
361 sizeof(float) * 4 * 2));
362 // color
363 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
364 instanceBufferLocations.color,
366 sizeof(float) * 4 * 3));
367 // data
368 attrs.append(QRhiVertexInputAttribute(instanceBufferBinding,
369 instanceBufferLocations.data,
371 sizeof(float) * 4 * 4));
372 }
373
374 ia->inputLayout.setAttributes(attrs.cbegin(), attrs.cend());
375}
376
377} // namespace QSSGRhiHelpers
378
380{
381 m_stages.append(stage);
382
383 // Copy all member infos for the uniform block with binding 0 into m_ub0
384 // for faster lookup.
385 if (stage.type() == QRhiShaderStage::Vertex) {
386 // Optimize by doing it only for the vertex shader. This code path is
387 // only hit for pipelines with vertex+fragment stages and an in shaders
388 // from materials an identical uniform block is present in both
389 // shaders, so go through only one of them.
390 const QVector<QShaderDescription::UniformBlock> uniformBlocks = stage.shader().description().uniformBlocks();
391 for (const QShaderDescription::UniformBlock &blk : uniformBlocks) {
392 if (blk.binding == 0) {
393 m_ub0Size = blk.size;
394 m_ub0NextUBufOffset = m_context.rhi()->ubufAligned(m_ub0Size);
395 for (const QShaderDescription::BlockVariable &var : blk.members)
396 m_ub0[var.name] = var;
397 break;
398 }
399 }
400 // Now the same for vertex inputs.
401 if (!flags.testFlag(UsedWithoutIa)) {
402 const QVector<QShaderDescription::InOutVariable> inputs = stage.shader().description().inputVariables();
403 for (const QShaderDescription::InOutVariable &var : inputs) {
405 m_vertexInputs[QSSGRhiInputAssemblerState::PositionSemantic] = var;
406 } else if (var.name == QSSGMesh::MeshInternal::getNormalAttrName()) {
407 m_vertexInputs[QSSGRhiInputAssemblerState::NormalSemantic] = var;
408 } else if (var.name == QSSGMesh::MeshInternal::getUV0AttrName()) {
409 m_vertexInputs[QSSGRhiInputAssemblerState::TexCoord0Semantic] = var;
410 } else if (var.name == QSSGMesh::MeshInternal::getUV1AttrName()) {
411 m_vertexInputs[QSSGRhiInputAssemblerState::TexCoord1Semantic] = var;
413 m_vertexInputs[QSSGRhiInputAssemblerState::TexCoordLightmapSemantic] = var;
414 } else if (var.name == QSSGMesh::MeshInternal::getTexTanAttrName()) {
415 m_vertexInputs[QSSGRhiInputAssemblerState::TangentSemantic] = var;
417 m_vertexInputs[QSSGRhiInputAssemblerState::BinormalSemantic] = var;
418 } else if (var.name == QSSGMesh::MeshInternal::getColorAttrName()) {
419 m_vertexInputs[QSSGRhiInputAssemblerState::ColorSemantic] = var;
420 } else if (var.name == QSSGMesh::MeshInternal::getJointAttrName()) {
421 m_vertexInputs[QSSGRhiInputAssemblerState::JointSemantic] = var;
422 } else if (var.name == QSSGMesh::MeshInternal::getWeightAttrName()) {
423 m_vertexInputs[QSSGRhiInputAssemblerState::WeightSemantic] = var;
424 } else if (var.name == "qt_instanceTransform0") {
425 instanceLocations.transform0 = var.location;
426 } else if (var.name == "qt_instanceTransform1") {
427 instanceLocations.transform1 = var.location;
428 } else if (var.name == "qt_instanceTransform2") {
429 instanceLocations.transform2 = var.location;
430 } else if (var.name == "qt_instanceColor") {
431 instanceLocations.color = var.location;
432 } else if (var.name == "qt_instanceData") {
433 instanceLocations.data = var.location;
434 } else {
435 qWarning("Ignoring vertex input %s in shader", var.name.constData());
436 }
437 }
438 }
439 }
440
441 const QVector<QShaderDescription::InOutVariable> combinedImageSamplers = stage.shader().description().combinedImageSamplers();
442 for (const QShaderDescription::InOutVariable &var : combinedImageSamplers)
443 m_combinedImageSamplers[var.name] = var;
444
445 std::fill(m_materialImageSamplerBindings,
446 m_materialImageSamplerBindings + size_t(QSSGRhiSamplerBindingHints::BindingMapSize),
447 -1);
448}
449
450void QSSGRhiShaderPipeline::setUniformValue(char *ubufData, const char *name, const QVariant &inValue, QSSGRenderShaderValue::Type inType)
451{
452 using namespace QSSGRenderShaderValue;
453 switch (inType) {
455 {
456 const qint32 v = inValue.toInt();
457 setUniform(ubufData, name, &v, sizeof(qint32));
458 }
459 break;
461 {
462 const ivec2 v = inValue.value<ivec2>();
463 setUniform(ubufData, name, &v, 2 * sizeof(qint32));
464 }
465 break;
467 {
468 const ivec3 v = inValue.value<ivec3>();
469 setUniform(ubufData, name, &v, 3 * sizeof(qint32));
470 }
471 break;
473 {
474 const ivec4 v = inValue.value<ivec4>();
475 setUniform(ubufData, name, &v, 4 * sizeof(qint32));
476 }
477 break;
479 {
480 // whatever bool is does not matter, what matters is that the GLSL bool is 4 bytes
481 const qint32 v = inValue.value<bool>();
482 setUniform(ubufData, name, &v, sizeof(qint32));
483 }
484 break;
486 {
487 const bvec2 b = inValue.value<bvec2>();
488 const ivec2 v(b.x, b.y);
489 setUniform(ubufData, name, &v, 2 * sizeof(qint32));
490 }
491 break;
493 {
494 const bvec3 b = inValue.value<bvec3>();
495 const ivec3 v(b.x, b.y, b.z);
496 setUniform(ubufData, name, &v, 3 * sizeof(qint32));
497 }
498 break;
500 {
501 const bvec4 b = inValue.value<bvec4>();
502 const ivec4 v(b.x, b.y, b.z, b.w);
503 setUniform(ubufData, name, &v, 4 * sizeof(qint32));
504 }
505 break;
507 {
508 const float v = inValue.value<float>();
509 setUniform(ubufData, name, &v, sizeof(float));
510 }
511 break;
513 {
514 const QVector2D v = inValue.value<QVector2D>();
515 setUniform(ubufData, name, &v, 2 * sizeof(float));
516 }
517 break;
519 {
520 const QVector3D v = inValue.value<QVector3D>();
521 setUniform(ubufData, name, &v, 3 * sizeof(float));
522 }
523 break;
525 {
526 const QVector4D v = inValue.value<QVector4D>();
527 setUniform(ubufData, name, &v, 4 * sizeof(float));
528 }
529 break;
531 {
532 const QVector4D v = QSSGUtils::color::sRGBToLinear(inValue.value<QColor>());
533 setUniform(ubufData, name, &v, 4 * sizeof(float));
534 }
535 break;
537 {
538 const quint32 v = inValue.value<quint32>();
539 setUniform(ubufData, name, &v, sizeof(quint32));
540 }
541 break;
543 {
544 const uvec2 v = inValue.value<uvec2>();
545 setUniform(ubufData, name, &v, 2 * sizeof(quint32));
546 }
547 break;
549 {
550 const uvec3 v = inValue.value<uvec3>();
551 setUniform(ubufData, name, &v, 3 * sizeof(quint32));
552 }
553 break;
555 {
556 const uvec4 v = inValue.value<uvec4>();
557 setUniform(ubufData, name, &v, 4 * sizeof(quint32));
558 }
559 break;
561 {
562 const QMatrix3x3 m = inValue.value<QMatrix3x3>();
563 setUniform(ubufData, name, m.constData(), 12 * sizeof(float), nullptr, QSSGRhiShaderPipeline::UniformFlag::Mat3);
564 }
565 break;
567 {
568 const QMatrix4x4 v = inValue.value<QMatrix4x4>();
569 setUniform(ubufData, name, v.constData(), 16 * sizeof(float));
570 }
571 break;
573 {
574 const QSize s = inValue.value<QSize>();
575 float v[2] = { float(s.width()), float(s.height()) };
576 setUniform(ubufData, name, v, 2 * sizeof(float));
577 }
578 break;
580 {
581 const QSizeF s = inValue.value<QSizeF>();
582 float v[2] = { float(s.width()), float(s.height()) };
583 setUniform(ubufData, name, v, 2 * sizeof(float));
584 }
585 break;
587 {
588 const QPoint p = inValue.value<QPoint>();
589 float v[2] = { float(p.x()), float(p.y()) };
590 setUniform(ubufData, name, v, 2 * sizeof(float));
591 }
592 break;
594 {
595 const QPointF p = inValue.value<QPointF>();
596 float v[2] = { float(p.x()), float(p.y()) };
597 setUniform(ubufData, name, v, 2 * sizeof(float));
598 }
599 break;
601 {
602 const QRect r = inValue.value<QRect>();
603 float v[4] = { float(r.x()), float(r.y()), float(r.width()), float(r.height()) };
604 setUniform(ubufData, name, v, 4 * sizeof(float));
605 }
606 break;
608 {
609 const QRectF r = inValue.value<QRectF>();
610 float v[4] = { float(r.x()), float(r.y()), float(r.width()), float(r.height()) };
611 setUniform(ubufData, name, v, 4 * sizeof(float));
612 }
613 break;
615 {
616 const QQuaternion q = inValue.value<QQuaternion>();
617 float v[4] = { float(q.x()), float(q.y()), float(q.z()), float(q.scalar()) };
618 setUniform(ubufData, name, v, 4 * sizeof(float));
619 }
620 break;
621 default:
622 qWarning("Attempted to set uniform %s value with unsupported data type %i",
623 name, int(inType));
624 break;
625 }
626}
627
629{
630 auto iter = m_ub0.constFind(name);
631 if (iter != m_ub0.cend())
632 return iter->offset;
633 return -1;
634}
635
637{
638 return QStringLiteral("Uniform block member '%1' got %2 bytes whereas the true size is %3").arg(name, QString::number(correctedSize), QString::number(requestedSize));
639}
640
641void QSSGRhiShaderPipeline::setUniform(char *ubufData, const char *name, const void *data, size_t size, int *storeIndex, UniformFlags flags)
642{
643 int index = -1;
644 if (!storeIndex || *storeIndex == -1) {
646 auto it = m_uniformIndex.constFind(ba);
647 if (it != m_uniformIndex.cend()) {
648 index = int(*it);
649 } else if (ba.size() < qsizetype(sizeof(QSSGRhiShaderUniform::name))) {
651 memcpy(u.name, name, ba.size() + 1);
652 u.size = size;
653
654 const int new_idx = m_uniforms.size();
655 m_uniformIndex[name] = new_idx; // key is name, not ba, this has to be a deep copy QByteArray
656 m_uniforms.push_back(u);
657 index = new_idx;
658 } else {
659 qWarning("Attempted to set uniform with too long name: %s", name);
660 return;
661 }
662 if (storeIndex)
663 *storeIndex = index;
664 } else {
665 index = *storeIndex;
666 }
667
668 Q_ASSERT(index >= 0);
669 QSSGRhiShaderUniform &u = m_uniforms[index];
670 if (size <= u.size) {
671 if (u.offset == SIZE_MAX && u.maybeExists) {
672 auto it = m_ub0.constFind(QByteArray::fromRawData(u.name, strlen(u.name)));
673 if (it != m_ub0.constEnd()) {
674 u.offset = it->offset;
676 }
677 }
678 if (u.offset == SIZE_MAX) {
679 // must silently ignore uniforms that are not in the actual shader
680 u.maybeExists = false; // but do not try again
681 return;
682 }
683
684 char *dst = ubufData + u.offset;
685 if (flags.testFlag(UniformFlag::Mat3)) {
686 // mat3 is still 4 floats per column in the uniform buffer (but there
687 // is no 4th column), so 48 bytes altogether, not 36 or 64.
688 const float *src = static_cast<const float *>(data);
689 memcpy(dst, src, 3 * sizeof(float));
690 memcpy(dst + 4 * sizeof(float), src + 3, 3 * sizeof(float));
691 memcpy(dst + 8 * sizeof(float), src + 6, 3 * sizeof(float));
692 } else {
693 memcpy(dst, data, size);
694 }
695 } else {
696 qWarning("Attempted to set %u bytes to uniform %s with size %u", uint(size), name, uint(u.size));
697 }
698}
699
700// Quick3D uniform buffer is std140 type and all array data should be stored in this rule.
701// You can check it in glspec45.core.pdf's 7.6.2.2.(4)
702// https://www.khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf
703void QSSGRhiShaderPipeline::setUniformArray(char *ubufData, const char *name, const void *data, size_t itemCount, QSSGRenderShaderValue::Type type, int *storeIndex)
704{
705 using namespace QSSGRenderShaderValue;
706
707 QSSGRhiShaderUniformArray *ua = nullptr;
708 constexpr size_t std140BaseTypeSize = 4 * sizeof(float);
709
710 static const auto checkSize = [std140BaseTypeSize](QSSGRhiShaderUniformArray *ua) -> bool {
711 Q_UNUSED(std140BaseTypeSize); // Silence clang warning about unneeded lambda capture (MSVC requires it be captrued).
712 const size_t uniformSize = std140BaseTypeSize < ua->typeSize ? ua->typeSize * ua->itemCount : std140BaseTypeSize * ua->itemCount;
713 QSSG_ASSERT_X(uniformSize == ua->size, qPrintable(getUBMemberSizeWarning(QLatin1StringView(ua->name), uniformSize, ua->size)), return false);
714 return true;
715 };
716
717 if (!storeIndex || *storeIndex == -1) {
718 int index = -1;
720 auto it = m_uniformIndex.constFind(ba);
721 if (it != m_uniformIndex.cend()) {
722 index = int(*it);
723 ua = &m_uniformArrays[index];
724 } else if (ba.size() < qsizetype(sizeof(QSSGRhiShaderUniformArray::name))) {
725 index = m_uniformArrays.size();
726 m_uniformArrays.push_back(QSSGRhiShaderUniformArray());
727 m_uniformIndex[name] = index; // key needs deep copy
728 ua = &m_uniformArrays.last();
729 memcpy(ua->name, name, ba.size() + 1);
730 } else {
731 qWarning("Attempted to set uniform array with too long name: %s", name);
732 return;
733 }
734 if (storeIndex)
735 *storeIndex = index;
736 } else {
737 ua = &m_uniformArrays[*storeIndex];
738 }
739
740 if (!ua)
741 return;
742
743 if (ua->offset == SIZE_MAX && ua->maybeExists) {
744 auto it = m_ub0.constFind(QByteArray::fromRawData(ua->name, strlen(ua->name)));
745 if (it != m_ub0.constEnd()) {
746 ua->offset = it->offset;
747 ua->size = it->size;
748 }
749 }
750 if (ua->offset == SIZE_MAX) {
751 // must silently ignore uniforms that are not in the actual shader
752 ua->maybeExists = false; // but do not try again
753 return;
754 }
755
756 char *p = ubufData + ua->offset;
757
758 switch (type) {
760 {
761 const qint32 *v = static_cast<const qint32 *>(data);
762 if (sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
763 ua->typeSize = sizeof(qint32);
764 ua->itemCount = itemCount;
765 }
766
767 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
768
769 for (size_t i = 0; i < itemCount; ++i)
770 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
771 }
772 break;
774 {
775 const ivec2 *v = static_cast<const ivec2 *>(data);
776 if (2 * sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
777 ua->typeSize = 2 * sizeof(qint32);
778 ua->itemCount = itemCount;
779 }
780
781 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
782
783 for (size_t i = 0; i < itemCount; ++i)
784 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
785 }
786 break;
788 {
790 if (3 * sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
791 ua->typeSize = 3 * sizeof(qint32);
792 ua->itemCount = itemCount;
793 }
794
795 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
796
797 for (size_t i = 0; i < itemCount; ++i)
798 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
799 }
800 break;
802 {
803 const ivec4 *v = static_cast<const ivec4 *>(data);
804 if (4 * sizeof(qint32) != ua->typeSize || itemCount != ua->itemCount) {
805 ua->typeSize = 4 * sizeof(qint32);
806 ua->itemCount = itemCount;
807 }
808
809 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
810
811 memcpy(p, v, ua->typeSize * ua->itemCount);
812 }
813 break;
815 {
816 const float *v = static_cast<const float *>(data);
817 if (sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
818 ua->typeSize = sizeof(float);
819 ua->itemCount = itemCount;
820 }
821
822 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
823
824 for (size_t i = 0; i < itemCount; ++i)
825 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
826 }
827 break;
829 {
830 const QVector2D *v = static_cast<const QVector2D *>(data);
831 if (2 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
832 ua->typeSize = 2 * sizeof(float);
833 ua->itemCount = itemCount;
834 }
835
836 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
837
838 for (size_t i = 0; i < itemCount; ++i)
839 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
840 }
841 break;
843 {
844 const QVector3D *v = static_cast<const QVector3D *>(data);
845 if (3 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
846 ua->typeSize = 3 * sizeof(float);
847 ua->itemCount = itemCount;
848 }
849
850 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
851
852 for (size_t i = 0; i < itemCount; ++i)
853 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
854 }
855 break;
857 {
858 const QVector4D *v = static_cast<const QVector4D *>(data);
859 if (4 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
860 ua->typeSize = 4 * sizeof(float);
861 ua->itemCount = itemCount;
862 }
863
864 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
865
866 memcpy(p, v, ua->typeSize * ua->itemCount);
867 }
868 break;
870 {
871 const QColor *v = static_cast<const QColor *>(data);
872 if (4 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
873 ua->typeSize = 4 * sizeof(float);
874 ua->itemCount = itemCount;
875 }
876
877 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
878
879 for (size_t i = 0; i < itemCount; ++i) {
880 const QVector4D vi = QSSGUtils::color::sRGBToLinear(v[i]);
881 memcpy(p + i * std140BaseTypeSize, &vi, ua->typeSize);
882 }
883 }
884 break;
886 {
887 const quint32 *v = static_cast<const quint32 *>(data);
888 if (sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
889 ua->typeSize = sizeof(quint32);
890 ua->itemCount = itemCount;
891 }
892
893 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
894
895 for (size_t i = 0; i < itemCount; ++i)
896 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
897 }
898 break;
900 {
901 const uvec2 *v = static_cast<const uvec2 *>(data);
902 if (2 * sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
903 ua->typeSize = 2 * sizeof(quint32);
904 ua->itemCount = itemCount;
905 }
906
907 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
908
909 for (size_t i = 0; i < itemCount; ++i)
910 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
911 }
912 break;
914 {
915 const uvec3 *v = static_cast<const uvec3 *>(data);
916 if (3 * sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
917 ua->typeSize = 3 * sizeof(quint32);
918 ua->itemCount = itemCount;
919 }
920
921 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
922
923 for (size_t i = 0; i < itemCount; ++i)
924 memcpy(p + i * std140BaseTypeSize, &v[i], ua->typeSize);
925 }
926 break;
928 {
929 const uvec4 *v = static_cast<const uvec4 *>(data);
930 if (4 * sizeof(quint32) != ua->typeSize || itemCount != ua->itemCount) {
931 ua->typeSize = 4 * sizeof(quint32);
932 ua->itemCount = itemCount;
933 }
934
935 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
936
937 memcpy(p, v, ua->typeSize * ua->itemCount);
938 }
939 break;
941 {
942 const QMatrix3x3 *v = static_cast<const QMatrix3x3 *>(data);
943 if (12 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
944 ua->typeSize = 12 * sizeof(float);
945 ua->itemCount = itemCount;
946 }
947
948 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
949
950 for (uint i = 0; i < ua->itemCount; ++i) {
951 memcpy(p + i * ua->typeSize, v[i].constData(), 3 * sizeof(float));
952 memcpy(p + i * ua->typeSize + 4 * sizeof(float), v[i].constData() + 3, 3 * sizeof(float));
953 memcpy(p + i * ua->typeSize + 8 * sizeof(float), v[i].constData() + 6, 3 * sizeof(float));
954 }
955 }
956 break;
958 {
959 const QMatrix4x4 *v = static_cast<const QMatrix4x4 *>(data);
960 if (16 * sizeof(float) != ua->typeSize || itemCount != ua->itemCount) {
961 ua->typeSize = 16 * sizeof(float);
962 ua->itemCount = itemCount;
963 }
964
965 QSSG_ASSERT(QSSG_DEBUG_COND(checkSize(ua)), return);
966
967 for (uint i = 0; i < ua->itemCount; ++i)
968 memcpy(p + i * ua->typeSize, &v[i] , ua->typeSize);
969 }
970 break;
982 default:
983 qWarning("Attempted to set uniform %s value with type %d that is unsupported for uniform arrays",
984 name, int(type));
985 break;
986 }
987}
988
990{
991 const quint32 totalBufferSize = m_ub0NextUBufOffset + sizeof(QSSGShaderLightsUniformData);
992 if (!*ubuf) {
993 *ubuf = m_context.rhi()->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, totalBufferSize);
994 (*ubuf)->create();
995 }
996 if ((*ubuf)->size() < totalBufferSize) {
997 (*ubuf)->setSize(totalBufferSize);
998 (*ubuf)->create();
999 }
1000}
1001
1003{
1004 if (!*ubuf) {
1005 *ubuf = m_context.rhi()->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, m_ub0Size);
1006 (*ubuf)->create();
1007 }
1008}
1009
1011{
1012 if (hint >= 0) {
1013 const int binding = m_materialImageSamplerBindings[hint];
1014 if (binding >= 0)
1015 return binding;
1016 }
1017
1018 auto it = m_combinedImageSamplers.constFind(QByteArray::fromRawData(name, strlen(name)));
1019 const int binding = it != m_combinedImageSamplers.cend() ? it->binding : -1;
1020 if (hint >= 0)
1021 m_materialImageSamplerBindings[hint] = binding;
1022
1023 return binding;
1024}
1025
1030 : d_ptr(new QSSGRhiContextPrivate(*this, rhi))
1031{
1032 Q_ASSERT(rhi);
1033 Q_STATIC_ASSERT(int(QSSGRhiSamplerBindingHints::LightProbe) > int(QSSGRenderableImage::Type::Occlusion));
1034}
1035
1040{
1041 Q_D(QSSGRhiContext);
1042 d->releaseCachedResources();
1043
1044 qDeleteAll(d->m_textures);
1045 qDeleteAll(d->m_meshes);
1046}
1047
1052{
1053 Q_D(const QSSGRhiContext);
1054 return d->m_rhi;
1055}
1056
1061{
1062 Q_D(const QSSGRhiContext);
1063 return d->m_rhi != nullptr;
1064}
1065
1070
1076{
1077 Q_D(const QSSGRhiContext);
1078 return d->m_mainRpDesc;
1079}
1080
1085
1090{
1091 Q_D(const QSSGRhiContext);
1092 return d->m_cb;
1093}
1094
1099
1111{
1112 Q_D(const QSSGRhiContext);
1113 return d->m_rt;
1114}
1115
1120
1125{
1126 Q_D(const QSSGRhiContext);
1127 return d->m_mainSamples;
1128}
1129
1131{
1132 m_mainViewCount = viewCount;
1133}
1134
1140{
1141 Q_D(const QSSGRhiContext);
1142 return d->m_mainViewCount;
1143}
1144
1146{
1147 for (QSSGRhiDrawCallData &dcd : m_drawCallData) {
1148 // We don't call releaseDrawCallData() here, since we're anyways
1149 // are going to delete the non-owned resources further down and
1150 // there's no point in removing each of those one-by-one, as is
1151 // the case with releaseDrawCallData().
1152 // This speeds up the release of cached resources greatly when there
1153 // are many entries in the map, also at application shutdown.
1154 dcd.reset();
1155 }
1156
1158
1163
1166 m_srbCache.clear();
1168
1169 for (const auto &samplerInfo : std::as_const(m_samplers))
1170 delete samplerInfo.second;
1171
1172 m_samplers.clear();
1173
1174 for (const auto &particleData : std::as_const(m_particleData))
1175 delete particleData.texture;
1176
1178
1179 for (const auto &instanceData : std::as_const(m_instanceBuffers)) {
1180 if (instanceData.owned)
1181 delete instanceData.buffer;
1182 }
1183
1185
1186 for (const auto &instanceData : std::as_const(m_instanceBuffersLod)) {
1187 if (instanceData.owned)
1188 delete instanceData.buffer;
1189 }
1190
1192}
1193
1195{
1196 auto it = m_srbCache.constFind(bindings);
1197 if (it != m_srbCache.constEnd())
1198 return *it;
1199
1201 srb->setBindings(bindings.v, bindings.v + bindings.p);
1202 if (srb->create()) {
1203 m_srbCache.insert(bindings, srb);
1204 } else {
1205 qWarning("Failed to build srb");
1206 delete srb;
1207 srb = nullptr;
1208 }
1209 return srb;
1210}
1211
1213{
1214 delete dcd.ubuf;
1215 dcd.ubuf = nullptr;
1216 auto srb = m_srbCache.take(dcd.bindings);
1217 QSSG_CHECK(srb == dcd.srb);
1218 delete srb;
1219 dcd.srb = nullptr;
1220 dcd.pipeline = nullptr;
1221}
1222
1229
1235
1240
1241using SamplerInfo = QPair<QSSGRhiSamplerDescription, QRhiSampler*>;
1242
1253{
1254 Q_D(QSSGRhiContext);
1255 auto compareSampler = [samplerDescription](const SamplerInfo &info){ return info.first == samplerDescription; };
1256 auto &samplers = d->m_samplers;
1257 const auto found = std::find_if(samplers.cbegin(), samplers.cend(), compareSampler);
1258 if (found != samplers.cend())
1259 return found->second;
1260
1261 QRhiSampler *newSampler = d->m_rhi->newSampler(samplerDescription.magFilter,
1262 samplerDescription.minFilter,
1263 samplerDescription.mipmap,
1264 samplerDescription.hTiling,
1265 samplerDescription.vTiling,
1266 samplerDescription.zTiling);
1267 if (!newSampler->create()) {
1268 qWarning("Failed to build image sampler");
1269 delete newSampler;
1270 return nullptr;
1271 }
1272 samplers << SamplerInfo{samplerDescription, newSampler};
1273 return newSampler;
1274}
1275
1290{
1291 Q_D(const QSSGRhiContext);
1292 if (samplerDescription->mipmap != QRhiSampler::None
1293 || samplerDescription->hTiling != QRhiSampler::ClampToEdge
1294 || samplerDescription->vTiling != QRhiSampler::ClampToEdge
1295 || samplerDescription->zTiling != QRhiSampler::ClampToEdge)
1296 {
1297 if (d->m_rhi->isFeatureSupported(QRhi::NPOTTextureRepeat))
1298 return;
1299
1300 const QSize pixelSize = texture->pixelSize();
1301 const int w = qNextPowerOfTwo(pixelSize.width() - 1);
1302 const int h = qNextPowerOfTwo(pixelSize.height() - 1);
1303 if (w != pixelSize.width() || h != pixelSize.height()) {
1304 static bool warnShown = false;
1305 if (!warnShown) {
1306 warnShown = true;
1307 qWarning("Attempted to use an unsupported filtering or wrap mode, "
1308 "this is likely due to lacking proper support for non-power-of-two textures on this platform.\n"
1309 "If this is with WebGL, try updating the application to use QQuick3D::idealSurfaceFormat() in main() "
1310 "in order to ensure WebGL 2 is used.");
1311 }
1312 samplerDescription->mipmap = QRhiSampler::None;
1313 samplerDescription->hTiling = QRhiSampler::ClampToEdge;
1314 samplerDescription->vTiling = QRhiSampler::ClampToEdge;
1315 samplerDescription->zTiling = QRhiSampler::ClampToEdge;
1316 }
1317 }
1318}
1319
1324
1330
1335
1337{
1338 if (mesh) {
1339 for (const auto &subset : std::as_const(mesh->subsets)) {
1340 if (subset.rhi.targetsTexture)
1341 releaseTexture(subset.rhi.targetsTexture);
1342 }
1343 }
1344 m_meshes.remove(mesh);
1345 delete mesh;
1346}
1347
1349{
1350 // Find all QSSGRhiUniformBufferSet that reference model
1351 // and delete them
1352 const void *modelNode = model;
1353 auto it = m_drawCallData.begin();
1354 while (it != m_drawCallData.end()) {
1355 if (it.key().model == modelNode) {
1358 } else {
1359 ++it;
1360 }
1361 }
1362}
1363
1381 const QSize &size, const QColor &fillColor, int arraySize)
1382{
1383 Q_D(QSSGRhiContext);
1384 auto it = d->m_dummyTextures.constFind({flags, size, fillColor, arraySize});
1385 if (it != d->m_dummyTextures.constEnd())
1386 return *it;
1387
1388 QRhiTexture *t = arraySize < 2
1389 ? d->m_rhi->newTexture(QRhiTexture::RGBA8, size, 1, flags)
1390 : d->m_rhi->newTextureArray(QRhiTexture::RGBA8, arraySize, size, 1, flags);
1391 if (t->create()) {
1392 QImage image(t->pixelSize(), QImage::Format_RGBA8888);
1393 image.fill(fillColor);
1394 rub->uploadTexture(t, image);
1395 for (int layer = 1; layer < arraySize; ++layer)
1397 } else {
1398 qWarning("Failed to build dummy texture");
1399 }
1400
1401 d->m_dummyTextures.insert({flags, size, fillColor, arraySize}, t);
1402 return t;
1403}
1404
1409
1414
1416{
1417 return m_particleData[particlesOrModel];
1418}
1419
1421{
1422 layerKey = layer;
1424 info.renderPasses.clear();
1425 info.externalRenderPass = {};
1426 info.currentRenderPassIndex = -1;
1427}
1428
1430{
1431 if (rendererDebugEnabled()) {
1433 const int rpCount = info.renderPasses.size();
1434 qDebug("%d render passes in 3D renderer %p", rpCount, layer);
1435 for (int i = 0; i < rpCount; ++i) {
1436 const RenderPassInfo &rp(info.renderPasses[i]);
1437 qDebug("Render pass %d: rt name='%s' target size %dx%d pixels",
1438 i, rp.rtName.constData(), rp.pixelSize.width(), rp.pixelSize.height());
1439 printRenderPass(rp);
1440 }
1441 if (info.externalRenderPass.indexedDraws.callCount || info.externalRenderPass.instancedIndexedDraws.callCount
1442 || info.externalRenderPass.draws.callCount || info.externalRenderPass.instancedDraws.callCount)
1443 {
1444 qDebug("Within external render passes:");
1445 printRenderPass(info.externalRenderPass);
1446 }
1447 }
1448
1449 // a new start() may preceed stop() for the previous View3D, must handle this gracefully
1450 if (layerKey == layer)
1451 layerKey = nullptr;
1452
1453 // The data must stay valid until the next start() with the same key, the
1454 // QQuick3DRenderStats and DebugView may read it.
1455}
1456
1462
1464{
1466 Q_TRACE(QSSG_renderPass_entry, QString::fromUtf8(rt->name()));
1467 info.renderPasses.append({ rt->name(), rt->pixelSize(), {}, {}, {}, {} });
1468 info.currentRenderPassIndex = info.renderPasses.size() - 1;
1469}
1470
1472{
1473 Q_TRACE(QSSG_renderPass_exit);
1475 info.currentRenderPassIndex = -1;
1476}
1477
1482
1484{
1485 return QSSGRhiContextPrivate::get(&rhiCtx)->m_stats;
1486}
1487
1489{
1491 return enabled;
1492}
1493
1495{
1496 static bool enabled = qgetenv("QSG_RENDERER_DEBUG").contains(QByteArrayLiteral("render"));
1497 return enabled;
1498}
1499
1501{
1503 || Q_TRACE_ENABLED(QSSG_draw);
1504}
1505
1507{
1508 Q_TRACE(QSSG_drawIndexed, indexCount, instanceCount);
1510 RenderPassInfo &rp(info.currentRenderPassIndex >= 0 ? info.renderPasses[info.currentRenderPassIndex] : info.externalRenderPass);
1511 if (instanceCount > 1) {
1513 rp.instancedIndexedDraws.vertexOrIndexCount += indexCount;
1514 rp.instancedIndexedDraws.instanceCount += instanceCount;
1515 } else {
1516 rp.indexedDraws.callCount += 1;
1517 rp.indexedDraws.vertexOrIndexCount += indexCount;
1518 }
1519}
1520
1522{
1523 Q_TRACE(QSSG_draw, vertexCount, instanceCount);
1525 RenderPassInfo &rp(info.currentRenderPassIndex >= 0 ? info.renderPasses[info.currentRenderPassIndex] : info.externalRenderPass);
1526 if (instanceCount > 1) {
1527 rp.instancedDraws.callCount += 1;
1528 rp.instancedDraws.vertexOrIndexCount += vertexCount;
1529 rp.instancedDraws.instanceCount += instanceCount;
1530 } else {
1531 rp.draws.callCount += 1;
1532 rp.draws.vertexOrIndexCount += vertexCount;
1533 }
1534}
1535
1537{
1538 qDebug("%llu indexed draw calls with %llu indices in total, "
1539 "%llu non-indexed draw calls with %llu vertices in total",
1543 qDebug("%llu instanced indexed draw calls with %llu indices and %llu instances in total, "
1544 "%llu instanced non-indexed draw calls with %llu indices and %llu instances in total",
1547 }
1548}
1549
1550void QSSGRhiShaderResourceBindingList::addUniformBuffer(int binding, QRhiShaderResourceBinding::StageFlags stage, QRhiBuffer *buf, int offset, int size)
1551{
1552#ifdef QT_DEBUG
1553 if (p == MAX_SIZE) {
1554 qWarning("Out of shader resource bindings slots (max is %d)", MAX_SIZE);
1555 return;
1556 }
1557#endif
1559 h ^= qintptr(buf);
1560 d->binding = binding;
1561 d->stage = stage;
1563 d->u.ubuf.buf = buf;
1564 d->u.ubuf.offset = offset;
1565 d->u.ubuf.maybeSize = size; // 0 = all
1566 d->u.ubuf.hasDynamicOffset = false;
1567}
1568
1569void QSSGRhiShaderResourceBindingList::addTexture(int binding, QRhiShaderResourceBinding::StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
1570{
1571#ifdef QT_DEBUG
1573 qWarning("Out of shader resource bindings slots (max is %d)", MAX_SIZE);
1574 return;
1575 }
1576#endif
1578 h ^= qintptr(tex) ^ qintptr(sampler);
1579 d->binding = binding;
1580 d->stage = stage;
1582 d->u.stex.count = 1;
1583 d->u.stex.texSamplers[0].tex = tex;
1584 d->u.stex.texSamplers[0].sampler = sampler;
1585}
1586
1588
1590{
1591 static const bool isSet = (qEnvironmentVariableIntValue("QT_RHI_SHADER_DEBUG") != 0);
1592 return isSet;
1593}
1594
1596{
1597 static const bool isSet = (qEnvironmentVariableIntValue("QT_QUICK3D_EDITORMODE") != 0);
1598 return isSet;
1599}
1600
1604{
1605 auto it = m_pipelines.constFind(key);
1606 if (it != m_pipelines.constEnd())
1607 return it.value();
1608
1609 // Build a new one. This is potentially expensive.
1611 const auto &ia = QSSGRhiInputAssemblerStatePrivate::get(key.state);
1612
1613 const auto *shaderPipeline = QSSGRhiGraphicsPipelineStatePrivate::getShaderPipeline(key.state);
1614 ps->setShaderStages(shaderPipeline->cbeginStages(), shaderPipeline->cendStages());
1615 ps->setVertexInputLayout(ia.inputLayout);
1617 ps->setRenderPassDescriptor(rpDesc);
1618
1619 QRhiGraphicsPipeline::Flags flags;
1620 if (key.state.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::UsesScissor))
1622
1623 static const bool shaderDebugInfo = qEnvironmentVariableIntValue("QT_QUICK3D_SHADER_DEBUG_INFO");
1624 if (shaderDebugInfo)
1626 ps->setFlags(flags);
1627
1628 ps->setTopology(ia.topology);
1629 ps->setCullMode(key.state.cullMode);
1630 if (ia.topology == QRhiGraphicsPipeline::Lines || ia.topology == QRhiGraphicsPipeline::LineStrip)
1631 ps->setLineWidth(key.state.lineWidth);
1632
1633 QRhiGraphicsPipeline::TargetBlend blend = key.state.targetBlend;
1634 blend.enable = (key.state.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled));
1635 QVarLengthArray<QRhiGraphicsPipeline::TargetBlend, 8> targetBlends(key.state.colorAttachmentCount);
1636 for (int i = 0; i < key.state.colorAttachmentCount; ++i)
1637 targetBlends[i] = blend;
1638 ps->setTargetBlends(targetBlends.cbegin(), targetBlends.cend());
1639
1640 ps->setSampleCount(key.state.samples);
1641 ps->setMultiViewCount(key.state.viewCount);
1642
1645 ps->setDepthOp(key.state.depthFunc);
1646
1647 ps->setDepthBias(key.state.depthBias);
1648 ps->setSlopeScaledDepthBias(key.state.slopeScaledDepthBias);
1649 ps->setPolygonMode(key.state.polygonMode);
1650
1651 const bool usesStencilRef = (key.state.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::UsesStencilRef));
1652 if (usesStencilRef)
1654 ps->setFlags(flags);
1655 ps->setStencilFront(key.state.stencilOpFrontState);
1656 ps->setStencilTest(usesStencilRef);
1657 ps->setStencilWriteMask(key.state.stencilWriteMask);
1658
1659 if (!ps->create()) {
1660 qWarning("Failed to build graphics pipeline state");
1661 delete ps;
1662 return nullptr;
1663 }
1664
1665 m_pipelines.insert(key, ps);
1666 return ps;
1667}
1668
1686
1690QRhiCommandBuffer::BeginPassFlags QSSGRhiContext::commonPassFlags() const
1691{
1692 // We do not use GPU compute at all at the moment, this means we can
1693 // get a small performance gain with OpenGL by declaring this.
1695}
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:409
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1212
const_iterator constFind(const Key &key) const noexcept
Definition qhash.h:1299
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:1219
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it.
Definition qhash.h:985
iterator erase(const_iterator it)
Definition qhash.h:1233
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1216
const_iterator cend() const noexcept
Definition qhash.h:1218
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:951
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
\inmodule QtGui
Definition qimage.h:37
@ Format_RGBA8888
Definition qimage.h:59
constexpr qsizetype size() const noexcept
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
\inmodule QtCore\reentrant
Definition qpoint.h:217
\inmodule QtCore\reentrant
Definition qpoint.h:25
The QQuaternion class represents a quaternion consisting of a vector and scalar.
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtGui
Definition qrhi.h:846
quint32 size() const
Definition qrhi.h:875
Type
Specifies storage type of buffer resource.
Definition qrhi.h:848
@ Dynamic
Definition qrhi.h:851
@ UniformBuffer
Definition qrhi.h:857
virtual bool create()=0
Creates the corresponding native graphics resources.
\inmodule QtGui
Definition qrhi.h:1651
@ DoNotTrackResourcesForCompute
Definition qrhi.h:1660
IndexFormat
Specifies the index data type.
Definition qrhi.h:1653
\inmodule QtGui
Definition qrhi.h:1622
virtual bool create()=0
void setShaderStage(const QRhiShaderStage &stage)
Sets the shader to use.
Definition qrhi.h:1636
void setShaderResourceBindings(QRhiShaderResourceBindings *srb)
Associates with srb describing the resource binding layout and the resources (QRhiBuffer,...
Definition qrhi.h:1639
\inmodule QtGui
Definition qrhi.h:1270
@ CompileShadersWithDebugInfo
Definition qrhi.h:1276
void setStencilFront(const StencilOpState &state)
Sets the stencil test state for front faces.
Definition qrhi.h:1423
void setCullMode(CullMode mode)
Sets the specified face culling mode.
Definition qrhi.h:1393
void setTargetBlends(std::initializer_list< TargetBlend > list)
Sets the list of render target blend settings.
Definition qrhi.h:1398
void setStencilTest(bool enable)
Enables or disables stencil tests based on enable.
Definition qrhi.h:1420
void setDepthWrite(bool enable)
Controls the writing out of depth data into the depth buffer based on enable.
Definition qrhi.h:1414
void setShaderResourceBindings(QRhiShaderResourceBindings *srb)
Associates with srb describing the resource binding layout and the resources (QRhiBuffer,...
Definition qrhi.h:1462
void setDepthOp(CompareOp op)
Sets the depth comparison function op.
Definition qrhi.h:1417
void setSlopeScaledDepthBias(float bias)
Sets the slope scaled depth bias.
Definition qrhi.h:1444
void setVertexInputLayout(const QRhiVertexInputLayout &layout)
Specifies the vertex input layout.
Definition qrhi.h:1459
void setFlags(Flags f)
Sets the flags f.
Definition qrhi.h:1387
void setShaderStages(std::initializer_list< QRhiShaderStage > list)
Sets the list of shader stages.
Definition qrhi.h:1446
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Associates with the specified QRhiRenderPassDescriptor desc.
Definition qrhi.h:1465
void setSampleCount(int s)
Sets the sample count.
Definition qrhi.h:1435
void setTopology(Topology t)
Sets the primitive topology t.
Definition qrhi.h:1390
void setMultiViewCount(int count)
Sets the view count for multiview rendering.
Definition qrhi.h:1474
Topology
Specifies the primitive topology.
Definition qrhi.h:1280
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:1411
void setDepthBias(int bias)
Sets the depth bias.
Definition qrhi.h:1441
void setPolygonMode(PolygonMode mode)
Sets the polygon mode.
Definition qrhi.h:1471
void setLineWidth(float width)
Sets the line width.
Definition qrhi.h:1438
void setStencilWriteMask(quint32 mask)
Sets the stencil write mask.
Definition qrhi.h:1432
static const QRhiShaderResourceBinding::Data * shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
Definition qrhi_p.h:220
\inmodule QtGui
Definition qrhi.h:1142
\inmodule QtGui
Definition qrhi.h:1158
virtual QSize pixelSize() const =0
\inmodule QtGui
Definition qrhi.h:1731
QByteArray name() const
Definition qrhi.cpp:3556
QRhiImplementation * m_rhi
Definition qrhi.h:840
\inmodule QtGui
Definition qrhi.h:1030
virtual bool create()=0
@ ClampToEdge
Definition qrhi.h:1040
\inmodule QtGui
Definition qrhi.h:1214
void setBindings(std::initializer_list< QRhiShaderResourceBinding > list)
Sets the list of bindings.
Definition qrhi.h:1218
virtual bool create()=0
\inmodule QtGui
Definition qrhi.h:379
QShader shader() const
Definition qrhi.h:397
Type type() const
Definition qrhi.h:394
\inmodule QtGui
Definition qrhi.h:1184
\inmodule QtGui
Definition qrhi.h:716
\inmodule QtGui
Definition qrhi.h:693
\inmodule QtGui
Definition qrhi.h:895
\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:345
void setAttributes(std::initializer_list< QRhiVertexInputAttribute > list)
Sets the attributes from the specified list.
Definition qrhi.h:337
const QRhiVertexInputAttribute * cbeginAttributes() const
Definition qrhi.h:344
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
Definition qrhi.cpp:10508
int ubufAligned(int v) const
Definition qrhi.cpp:9999
QRhiShaderResourceBindings * newShaderResourceBindings()
Definition qrhi.cpp:10489
QRhiComputePipeline * newComputePipeline()
Definition qrhi.cpp:10479
QRhiGraphicsPipeline * newGraphicsPipeline()
Definition qrhi.cpp:10466
@ NPOTTextureRepeat
Definition qrhi.h:1841
static QSSGComputePipelineStateKey create(const QShader &shader, const QRhiShaderResourceBindings *srb)
static QSSGGraphicsPipelineStateKey create(const QSSGRhiGraphicsPipelineState &state, const QRhiRenderPassDescriptor *rpDesc, const QRhiShaderResourceBindings *srb)
virtual ~QSSGRhiBuffer()
QSSGRhiBuffer(QSSGRhiContext &context, QRhiBuffer::Type type, QRhiBuffer::UsageFlags usageMask, quint32 stride, qsizetype size, QRhiCommandBuffer::IndexFormat indexFormat=QRhiCommandBuffer::IndexUInt16)
\variable QSSGRhiSamplerDescription::minFilter
void setMainRenderPassDescriptor(QRhiRenderPassDescriptor *rpDesc)
void releaseDrawCallData(QSSGRhiDrawCallData &dcd)
QRhiRenderPassDescriptor * m_mainRpDesc
QRhiShaderResourceBindings * srb(const QSSGRhiShaderResourceBindingList &bindings)
QSSGRhiDrawCallData & drawCallData(const QSSGRhiDrawCallDataKey &key)
QRhiGraphicsPipeline * pipeline(const QSSGRhiGraphicsPipelineState &ps, QRhiRenderPassDescriptor *rpDesc, QRhiShaderResourceBindings *srb)
static bool shaderDebuggingEnabled()
void releaseMesh(QSSGRenderMesh *mesh)
QHash< QSSGRenderInstanceTable *, QSSGRhiInstanceBufferData > m_instanceBuffers
void setCommandBuffer(QRhiCommandBuffer *cb)
QVector< QPair< QSSGRhiSamplerDescription, QRhiSampler * > > m_samplers
void setMainPassSampleCount(int samples)
QRhiRenderTarget * m_rt
void cleanupDrawCallData(const QSSGRenderModel *model)
QHash< const QSSGRenderGraphObject *, QSSGRhiParticleData > m_particleData
QHash< const QSSGRenderModel *, QSSGRhiInstanceBufferData > m_instanceBuffersLod
QHash< QSSGRhiDummyTextureKey, QRhiTexture * > m_dummyTextures
void registerMesh(QSSGRenderMesh *mesh)
void releaseTexture(QRhiTexture *texture)
QSSGRhiParticleData & particleData(const QSSGRenderGraphObject *particlesOrModel)
void setRenderTarget(QRhiRenderTarget *rt)
QHash< QSSGRhiShaderResourceBindingList, QRhiShaderResourceBindings * > m_srbCache
QHash< QSSGRhiDrawCallDataKey, QSSGRhiDrawCallData > m_drawCallData
void setMainPassViewCount(int viewCount)
void registerTexture(QRhiTexture *texture)
QRhiCommandBuffer * m_cb
static QSSGRhiContextPrivate * get(QSSGRhiContext *q)
QRhiComputePipeline * computePipeline(const QShader &shader, QRhiShaderResourceBindings *srb)
QHash< QSSGComputePipelineStateKey, QRhiComputePipeline * > m_computePipelines
QHash< QSSGGraphicsPipelineStateKey, QRhiGraphicsPipeline * > m_pipelines
QSSGRhiInstanceBufferData & instanceBufferData(QSSGRenderInstanceTable *instanceTable)
QSSGRhiContext * rhiCtx
static bool profilingEnabled()
static QSSGRhiContextStats & get(QSSGRhiContext &rhiCtx)
void start(QSSGRenderLayer *layer)
QSSGRenderLayer * layerKey
void cleanupLayerInfo(QSSGRenderLayer *layer)
void beginRenderPass(QRhiTextureRenderTarget *rt)
QHash< QSSGRenderLayer *, PerLayerInfo > perLayerInfo
void drawIndexed(quint32 indexCount, quint32 instanceCount)
void draw(quint32 vertexCount, quint32 instanceCount)
static bool rendererDebugEnabled()
void stop(QSSGRenderLayer *layer)
QSet< QSSGRenderLayer * > dynamicDataSources
void printRenderPass(const RenderPassInfo &rp)
\inmodule QtQuick3D
QSSGRhiContext(QRhi *rhi)
bool isValid() const
int mainPassSampleCount() const
Returns the sample count used in the main render pass.
int mainPassViewCount() const
Returns the multiview count used in the main render pass.
QRhiCommandBuffer * commandBuffer() const
QRhiTexture * dummyTexture(QRhiTexture::Flags flags, QRhiResourceUpdateBatch *rub, const QSize &size=QSize(64, 64), const QColor &fillColor=Qt::black, int arraySize=0)
void checkAndAdjustForNPoT(QRhiTexture *texture, QSSGRhiSamplerDescription *samplerDescription)
Adjusts samplerDescription's tiling and filtering modes based on the pixel size of texture.
QRhiCommandBuffer::BeginPassFlags commonPassFlags() const
QRhi * rhi() const
QRhiSampler * sampler(const QSSGRhiSamplerDescription &samplerDescription)
QRhiRenderTarget * renderTarget() const
QRhiRenderPassDescriptor * mainRenderPassDescriptor() const
void setUniformValue(char *ubufData, const char *name, const QVariant &value, QSSGRenderShaderValue::Type 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, QSSGRenderShaderValue::Type 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={})
void addUniformBuffer(int binding, QRhiShaderResourceBinding::StageFlags stage, QRhiBuffer *buf, int offset=0, int size=0)
void addTexture(int binding, QRhiShaderResourceBinding::StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
QRhiShaderResourceBinding v[MAX_SIZE]
qsizetype size() const
Definition qset.h:50
bool remove(const T &value)
Definition qset.h:63
bool isEmpty() const
Definition qset.h:52
const_iterator constEnd() const noexcept
Definition qset.h:143
const_iterator constFind(const T &value) const
Definition qset.h:161
iterator insert(const T &value)
Definition qset.h:155
QList< InOutVariable > inputVariables() const
QList< InOutVariable > combinedImageSamplers() const
QList< UniformBlock > uniformBlocks() const
\inmodule QtGui
Definition qshader.h:81
QShaderDescription description() const
Definition qshader.cpp:370
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
constexpr size_type size() const noexcept
const T & at(qsizetype idx) const
void append(const T &t)
void push_back(const T &t)
\inmodule QtCore
Definition qvariant.h:65
const void * constData() const
Definition qvariant.h:451
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
QSSGRenderGenericVec3< quint32 > uvec3
QSSGRenderGenericVec2< bool > bvec2
QSSGRenderGenericVec3< qint32 > ivec3
QSSGRenderGenericVec2< quint32 > uvec2
QSSGRenderGenericVec4< quint32 > uvec4
QSSGRenderGenericVec4< bool > bvec4
QSSGRenderGenericVec2< qint32 > ivec2
QSSGRenderGenericVec4< qint32 > ivec4
QSSGRenderGenericVec3< bool > bvec3
QRhiVertexInputAttribute::Format toVertexInputFormat(QSSGRenderComponentType compType, quint32 numComps)
QRhiGraphicsPipeline::Topology toTopology(QSSGRenderDrawMode drawMode)
void bakeVertexInputLocations(QSSGRhiInputAssemblerState *ia, const QSSGRhiShaderPipeline &shaders, int instanceBufferBinding)
Combined button and popup list for selecting options.
Definition image.cpp:4
static void * context
#define Q_STATIC_ASSERT(Condition)
Definition qassert.h:108
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
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:164
#define qWarning
Definition qlogging.h:166
constexpr quint32 qNextPowerOfTwo(quint32 v)
Definition qmath.h:335
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLsizei samples
const GLfloat * m
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint sampler
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum src
const void GLsizei GLsizei stride
GLenum type
GLenum GLenum dst
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLenum GLuint texture
GLenum GLuint GLintptr offset
GLuint name
GLfloat GLfloat GLfloat GLfloat h
GLdouble s
[6]
Definition qopenglext.h:235
GLuint shader
Definition qopenglext.h:665
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint * samplers
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei GLsizei GLuint * shaders
Definition qopenglext.h:677
GLfloat GLfloat p
[1]
#define Q_QUICK3D_PROFILING_ENABLED
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QSSG_DEBUG_COND(cond)
#define QSSG_ASSERT_X(cond, msg, action)
#define QSSG_CHECK(cond)
#define QSSG_ASSERT(cond, action)
QSSGRenderComponentType
QPair< QSSGRhiSamplerDescription, QRhiSampler * > SamplerInfo
static QString getUBMemberSizeWarning(QLatin1StringView name, qsizetype correctedSize, qsizetype requestedSize)
QSSGRhiInputAssemblerStatePrivate::InputAssemblerState QSSGRhiInputAssemblerState
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
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:50
int qint32
Definition qtypes.h:49
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
ptrdiff_t qintptr
Definition qtypes.h:166
#define enabled
QSqlQueryModel * model
[16]
QByteArray ba
[0]
QSemaphore sem(5)
[0]
QHostInfo info
[0]
static const char * getLightmapUVAttrName()
Definition qssgmesh_p.h:396
static const char * getNormalAttrName()
Definition qssgmesh_p.h:393
static const char * getUV1AttrName()
Definition qssgmesh_p.h:395
static const char * getTexBinormalAttrName()
Definition qssgmesh_p.h:398
static const char * getPositionAttrName()
Definition qssgmesh_p.h:392
static const char * getTexTanAttrName()
Definition qssgmesh_p.h:397
static const char * getColorAttrName()
Definition qssgmesh_p.h:399
static const char * getJointAttrName()
Definition qssgmesh_p.h:400
static const char * getUV0AttrName()
Definition qssgmesh_p.h:394
static const char * getWeightAttrName()
Definition qssgmesh_p.h:401
QVector< QSSGRenderSubset > subsets
static constexpr const QSSGRhiShaderPipeline * getShaderPipeline(const QSSGRhiGraphicsPipelineState &ps)
static const InputAssemblerState & get(const QSSGRhiGraphicsPipelineState &ps)
\variable QSSGRhiGraphicsPipelineState::depthFunc
\variable QShaderDescription::InOutVariable::name
\variable QShaderDescription::BlockVariable::name