8#include <QtQuick/private/qquickitem_p.h>
9#include <QtQuick/private/qquickwindow_p.h>
11#include <QtGui/qwindow.h>
14#include <QtGui/private/qvulkandefaultinstance_p.h>
17#include <QOperatingSystemVersion>
20#include <QStandardPaths>
24#include <QOffscreenSurface>
27#include <dxgiformat.h>
34QSGRhiSupport::QSGRhiSupport()
38void QSGRhiSupport::applySettings()
42 m_settingsApplied =
true;
48 QSGRhiSupport::checkEnvQSgInfo();
50 if (m_requested.valid) {
52 switch (m_requested.api) {
53 case QSGRendererInterface::OpenGL:
54 m_rhiBackend = QRhi::OpenGLES2;
56 case QSGRendererInterface::Direct3D11:
57 m_rhiBackend = QRhi::D3D11;
59 case QSGRendererInterface::Direct3D12:
60 m_rhiBackend = QRhi::D3D12;
62 case QSGRendererInterface::Vulkan:
63 m_rhiBackend = QRhi::Vulkan;
65 case QSGRendererInterface::Metal:
66 m_rhiBackend = QRhi::Metal;
68 case QSGRendererInterface::Null:
69 m_rhiBackend = QRhi::Null;
72 Q_ASSERT_X(
false,
"QSGRhiSupport",
"Internal error: unhandled GraphicsApi type");
77 const QByteArray rhiBackend = qgetenv(
"QSG_RHI_BACKEND");
78 if (rhiBackend == QByteArrayLiteral(
"gl")
79 || rhiBackend == QByteArrayLiteral(
"gles2")
80 || rhiBackend == QByteArrayLiteral(
"opengl"))
82 m_rhiBackend = QRhi::OpenGLES2;
83 }
else if (rhiBackend == QByteArrayLiteral(
"d3d11") || rhiBackend == QByteArrayLiteral(
"d3d")) {
84 m_rhiBackend = QRhi::D3D11;
85 }
else if (rhiBackend == QByteArrayLiteral(
"d3d12")) {
86 m_rhiBackend = QRhi::D3D12;
87 }
else if (rhiBackend == QByteArrayLiteral(
"vulkan")) {
88 m_rhiBackend = QRhi::Vulkan;
89 }
else if (rhiBackend == QByteArrayLiteral(
"metal")) {
90 m_rhiBackend = QRhi::Metal;
91 }
else if (rhiBackend == QByteArrayLiteral(
"null")) {
92 m_rhiBackend = QRhi::Null;
94 if (!rhiBackend.isEmpty()) {
95 qWarning(
"Unknown key \"%s\" for QSG_RHI_BACKEND, falling back to default backend.",
96 rhiBackend.constData());
99 m_rhiBackend = QRhi::D3D11;
100#elif QT_CONFIG(metal)
101 m_rhiBackend = QRhi::Metal;
102#elif QT_CONFIG(opengl)
103 m_rhiBackend = QRhi::OpenGLES2;
105 m_rhiBackend = QRhi::Vulkan;
110 adjustToPlatformQuirks();
121void QSGRhiSupport::adjustToPlatformQuirks()
127 if (m_rhiBackend == QRhi::Metal) {
128 QRhiMetalInitParams rhiParams;
129 if (!QRhi::probe(m_rhiBackend, &rhiParams)) {
130 m_rhiBackend = QRhi::OpenGLES2;
131 qCDebug(QSG_LOG_INFO,
"Metal does not seem to be supported. Falling back to OpenGL.");
137void QSGRhiSupport::checkEnvQSgInfo()
140 if (qEnvironmentVariableIsSet(
"QSG_INFO"))
141 const_cast<QLoggingCategory &>(QSG_LOG_INFO()).setEnabled(QtDebugMsg,
true);
147#define GL_BGRA 0x80E1
167#define GL_RG16 0x822C
175#define GL_RGBA8 0x8058
179#define GL_RGBA32F 0x8814
183#define GL_RGBA16F 0x881A
187#define GL_R16F 0x822D
191#define GL_R32F 0x822E
194#ifndef GL_DEPTH_COMPONENT16
195#define GL_DEPTH_COMPONENT16 0x81A5
198#ifndef GL_DEPTH_COMPONENT24
199#define GL_DEPTH_COMPONENT24 0x81A6
202#ifndef GL_DEPTH_COMPONENT32F
203#define GL_DEPTH_COMPONENT32F 0x8CAC
206#ifndef GL_DEPTH24_STENCIL8
207#define GL_DEPTH24_STENCIL8 0x88F0
210#ifndef GL_DEPTH_STENCIL
211#define GL_DEPTH_STENCIL 0x84F9
215#define GL_RGB10_A2 0x8059
219#define GL_SRGB_ALPHA 0x8C42
222#ifndef GL_SRGB8_ALPHA8
223#define GL_SRGB8_ALPHA8 0x8C43
226QRhiTexture::Format QSGRhiSupport::toRhiTextureFormatFromGL(uint format, QRhiTexture::Flags *flags)
229 auto rhiFormat = QRhiTexture::UnknownFormat;
232 case GL_SRGB8_ALPHA8:
238 rhiFormat = QRhiTexture::RGBA8;
241 rhiFormat = QRhiTexture::BGRA8;
244 rhiFormat = QRhiTexture::R16;
247 rhiFormat = QRhiTexture::RG16;
252 rhiFormat = QRhiTexture::R8;
257 rhiFormat = QRhiTexture::RG8;
260 rhiFormat = QRhiTexture::RED_OR_ALPHA8;
263 rhiFormat = QRhiTexture::RGBA16F;
266 rhiFormat = QRhiTexture::RGBA32F;
269 rhiFormat = QRhiTexture::R16F;
272 rhiFormat = QRhiTexture::R32F;
275 rhiFormat = QRhiTexture::RGB10A2;
277 case GL_DEPTH_COMPONENT:
279 case GL_DEPTH_COMPONENT16:
280 rhiFormat = QRhiTexture::D16;
282 case GL_DEPTH_COMPONENT24:
283 rhiFormat = QRhiTexture::D24;
285 case GL_DEPTH_STENCIL:
287 case GL_DEPTH24_STENCIL8:
288 rhiFormat = QRhiTexture::D24S8;
290 case GL_DEPTH_COMPONENT32F:
291 rhiFormat = QRhiTexture::D32F;
294 qWarning(
"GL format %d is not supported", format);
298 (*flags) |=(QRhiTexture::sRGB);
304QRhiTexture::Format QSGRhiSupport::toRhiTextureFormatFromVulkan(uint format, QRhiTexture::Flags *flags)
306 auto rhiFormat = QRhiTexture::UnknownFormat;
309 case VK_FORMAT_R8G8B8A8_SRGB:
312 case VK_FORMAT_R8G8B8A8_UNORM:
313 case VK_FORMAT_UNDEFINED:
314 rhiFormat = QRhiTexture::RGBA8;
316 case VK_FORMAT_B8G8R8A8_SRGB:
319 case VK_FORMAT_B8G8R8A8_UNORM:
320 rhiFormat = QRhiTexture::BGRA8;
322 case VK_FORMAT_R8_SRGB:
325 case VK_FORMAT_R8_UNORM:
326 rhiFormat = QRhiTexture::R8;
328 case VK_FORMAT_R8G8_SRGB:
331 case VK_FORMAT_R8G8_UNORM:
332 rhiFormat = QRhiTexture::RG8;
334 case VK_FORMAT_R16_UNORM:
335 rhiFormat = QRhiTexture::R16;
337 case VK_FORMAT_R16G16_UNORM:
338 rhiFormat = QRhiTexture::RG16;
340 case VK_FORMAT_R16G16B16A16_SFLOAT:
341 rhiFormat = QRhiTexture::RGBA16F;
343 case VK_FORMAT_R32G32B32A32_SFLOAT:
344 rhiFormat = QRhiTexture::RGBA32F;
346 case VK_FORMAT_R16_SFLOAT:
347 rhiFormat = QRhiTexture::R16F;
349 case VK_FORMAT_R32_SFLOAT:
350 rhiFormat = QRhiTexture::R32F;
352 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
354 case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
355 rhiFormat = QRhiTexture::RGB10A2;
357 case VK_FORMAT_D16_UNORM:
358 rhiFormat = QRhiTexture::D16;
360 case VK_FORMAT_X8_D24_UNORM_PACK32:
361 rhiFormat = QRhiTexture::D24;
363 case VK_FORMAT_D24_UNORM_S8_UINT:
364 rhiFormat = QRhiTexture::D24S8;
366 case VK_FORMAT_D32_SFLOAT:
367 rhiFormat = QRhiTexture::D32F;
369 case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
372 case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
373 rhiFormat = QRhiTexture::BC1;
375 case VK_FORMAT_BC2_SRGB_BLOCK:
378 case VK_FORMAT_BC2_UNORM_BLOCK:
379 rhiFormat = QRhiTexture::BC2;
381 case VK_FORMAT_BC3_SRGB_BLOCK:
384 case VK_FORMAT_BC3_UNORM_BLOCK:
385 rhiFormat = QRhiTexture::BC3;
387 case VK_FORMAT_BC4_UNORM_BLOCK:
388 rhiFormat = QRhiTexture::BC4;
390 case VK_FORMAT_BC5_UNORM_BLOCK:
391 rhiFormat = QRhiTexture::BC5;
393 case VK_FORMAT_BC6H_UFLOAT_BLOCK:
394 rhiFormat = QRhiTexture::BC6H;
396 case VK_FORMAT_BC7_SRGB_BLOCK:
399 case VK_FORMAT_BC7_UNORM_BLOCK:
400 rhiFormat = QRhiTexture::BC7;
402 case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
405 case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
406 rhiFormat = QRhiTexture::ETC2_RGB8;
408 case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
411 case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
412 rhiFormat = QRhiTexture::ETC2_RGB8A1;
414 case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
417 case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
418 rhiFormat = QRhiTexture::ETC2_RGBA8;
420 case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
423 case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
424 rhiFormat = QRhiTexture::ASTC_4x4;
426 case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
429 case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
430 rhiFormat = QRhiTexture::ASTC_5x4;
432 case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
435 case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
436 rhiFormat = QRhiTexture::ASTC_5x5;
438 case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
441 case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
442 rhiFormat = QRhiTexture::ASTC_6x5;
444 case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
447 case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
448 rhiFormat = QRhiTexture::ASTC_6x6;
450 case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
453 case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
454 rhiFormat = QRhiTexture::ASTC_8x5;
456 case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
459 case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
460 rhiFormat = QRhiTexture::ASTC_8x6;
462 case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
465 case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
466 rhiFormat = QRhiTexture::ASTC_8x8;
468 case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
471 case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
472 rhiFormat = QRhiTexture::ASTC_10x5;
474 case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
477 case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
478 rhiFormat = QRhiTexture::ASTC_10x6;
480 case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
483 case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
484 rhiFormat = QRhiTexture::ASTC_10x8;
486 case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
489 case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
490 rhiFormat = QRhiTexture::ASTC_10x10;
492 case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
495 case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
496 rhiFormat = QRhiTexture::ASTC_12x10;
498 case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
501 case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
502 rhiFormat = QRhiTexture::ASTC_12x12;
505 qWarning(
"VkFormat %d is not supported", format);
509 (*flags) |=(QRhiTexture::sRGB);
515QRhiTexture::Format QSGRhiSupport::toRhiTextureFormatFromDXGI(uint format, QRhiTexture::Flags *flags)
517 auto rhiFormat = QRhiTexture::UnknownFormat;
520 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
523 case DXGI_FORMAT_R8G8B8A8_UNORM:
524 case DXGI_FORMAT_UNKNOWN:
525 rhiFormat = QRhiTexture::RGBA8;
527 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
530 case DXGI_FORMAT_B8G8R8A8_UNORM:
531 rhiFormat = QRhiTexture::BGRA8;
533 case DXGI_FORMAT_R8_UNORM:
534 rhiFormat = QRhiTexture::R8;
536 case DXGI_FORMAT_R8G8_UNORM:
537 rhiFormat = QRhiTexture::RG8;
539 case DXGI_FORMAT_R16_UNORM:
540 rhiFormat = QRhiTexture::R16;
542 case DXGI_FORMAT_R16G16_UNORM:
543 rhiFormat = QRhiTexture::RG16;
545 case DXGI_FORMAT_R16G16B16A16_FLOAT:
546 rhiFormat = QRhiTexture::RGBA16F;
548 case DXGI_FORMAT_R32G32B32A32_FLOAT:
549 rhiFormat = QRhiTexture::RGBA32F;
551 case DXGI_FORMAT_R16_FLOAT:
552 rhiFormat = QRhiTexture::R16F;
554 case DXGI_FORMAT_R32_FLOAT:
555 rhiFormat = QRhiTexture::R32F;
557 case DXGI_FORMAT_R10G10B10A2_UNORM:
558 rhiFormat = QRhiTexture::RGB10A2;
560 case DXGI_FORMAT_R16_TYPELESS:
561 rhiFormat = QRhiTexture::D16;
563 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
564 rhiFormat = QRhiTexture::D24;
566 case DXGI_FORMAT_D24_UNORM_S8_UINT:
567 rhiFormat = QRhiTexture::D24S8;
569 case DXGI_FORMAT_R32_TYPELESS:
570 rhiFormat = QRhiTexture::D32F;
572 case DXGI_FORMAT_BC1_UNORM_SRGB:
575 case DXGI_FORMAT_BC1_UNORM:
576 rhiFormat = QRhiTexture::BC1;
578 case DXGI_FORMAT_BC2_UNORM_SRGB:
581 case DXGI_FORMAT_BC2_UNORM:
582 rhiFormat = QRhiTexture::BC2;
584 case DXGI_FORMAT_BC3_UNORM_SRGB:
587 case DXGI_FORMAT_BC3_UNORM:
588 rhiFormat = QRhiTexture::BC3;
590 case DXGI_FORMAT_BC4_UNORM:
591 rhiFormat = QRhiTexture::BC4;
593 case DXGI_FORMAT_BC5_UNORM:
594 rhiFormat = QRhiTexture::BC5;
596 case DXGI_FORMAT_BC6H_UF16:
597 rhiFormat = QRhiTexture::BC6H;
599 case DXGI_FORMAT_BC7_UNORM_SRGB:
602 case DXGI_FORMAT_BC7_UNORM:
603 rhiFormat = QRhiTexture::BC7;
606 qWarning(
"DXGI_FORMAT %d is not supported", format);
610 (*flags) |=(QRhiTexture::sRGB);
616namespace QSGRhiSupportMac {
617 QRhiTexture::Format toRhiTextureFormatFromMetal(uint format, QRhiTexture::Flags *flags);
619QRhiTexture::Format QSGRhiSupport::toRhiTextureFormatFromMetal(uint format, QRhiTexture::Flags *flags)
621 return QSGRhiSupportMac::toRhiTextureFormatFromMetal(format, flags);
625void QSGRhiSupport::configure(QSGRendererInterface::GraphicsApi api)
627 if (api == QSGRendererInterface::Unknown) {
629 m_requested.valid =
false;
632 Q_ASSERT(QSGRendererInterface::isApiRhiBased(api));
633 m_requested.valid =
true;
634 m_requested.api = api;
639QSGRhiSupport *QSGRhiSupport::instance_internal()
641 static QSGRhiSupport inst;
645QSGRhiSupport *QSGRhiSupport::instance()
647 QSGRhiSupport *inst = instance_internal();
648 if (!inst->m_settingsApplied)
649 inst->applySettings();
653QString QSGRhiSupport::rhiBackendName()
const
655 return QString::fromUtf8(QRhi::backendName(m_rhiBackend));
658QSGRendererInterface::GraphicsApi QSGRhiSupport::graphicsApi()
const
660 switch (m_rhiBackend) {
662 return QSGRendererInterface::Null;
664 return QSGRendererInterface::Vulkan;
665 case QRhi::OpenGLES2:
666 return QSGRendererInterface::OpenGL;
668 return QSGRendererInterface::Direct3D11;
670 return QSGRendererInterface::Direct3D12;
672 return QSGRendererInterface::Metal;
674 return QSGRendererInterface::Unknown;
678QSurface::SurfaceType QSGRhiSupport::windowSurfaceType()
const
680 switch (m_rhiBackend) {
682 return QSurface::VulkanSurface;
683 case QRhi::OpenGLES2:
684 return QSurface::OpenGLSurface;
687 return QSurface::Direct3DSurface;
689 return QSurface::MetalSurface;
691 return QSurface::OpenGLSurface;
696static const void *qsgrhi_vk_rifResource(QSGRendererInterface::Resource res,
697 const QRhiNativeHandles *nat,
698 const QRhiNativeHandles *cbNat,
699 const QRhiNativeHandles *rpNat)
701 const QRhiVulkanNativeHandles *vknat =
static_cast<
const QRhiVulkanNativeHandles *>(nat);
702 const QRhiVulkanCommandBufferNativeHandles *maybeVkCbNat =
703 static_cast<
const QRhiVulkanCommandBufferNativeHandles *>(cbNat);
704 const QRhiVulkanRenderPassNativeHandles *maybeVkRpNat =
705 static_cast<
const QRhiVulkanRenderPassNativeHandles *>(rpNat);
708 case QSGRendererInterface::DeviceResource:
710 case QSGRendererInterface::CommandQueueResource:
711 return &vknat->gfxQueue;
712 case QSGRendererInterface::CommandListResource:
714 return &maybeVkCbNat->commandBuffer;
717 case QSGRendererInterface::PhysicalDeviceResource:
718 return &vknat->physDev;
719 case QSGRendererInterface::RenderPassResource:
721 return &maybeVkRpNat->renderPass;
724 case QSGRendererInterface::GraphicsQueueFamilyIndexResource:
725 return &vknat->gfxQueueFamilyIdx;
726 case QSGRendererInterface::GraphicsQueueIndexResource:
727 return &vknat->gfxQueueIdx;
735static const void *qsgrhi_gl_rifResource(QSGRendererInterface::Resource res,
const QRhiNativeHandles *nat)
737 const QRhiGles2NativeHandles *glnat =
static_cast<
const QRhiGles2NativeHandles *>(nat);
739 case QSGRendererInterface::OpenGLContextResource:
740 return glnat->context;
748static const void *qsgrhi_d3d11_rifResource(QSGRendererInterface::Resource res,
const QRhiNativeHandles *nat)
750 const QRhiD3D11NativeHandles *d3dnat =
static_cast<
const QRhiD3D11NativeHandles *>(nat);
752 case QSGRendererInterface::DeviceResource:
754 case QSGRendererInterface::DeviceContextResource:
755 return d3dnat->context;
761static const void *qsgrhi_d3d12_rifResource(QSGRendererInterface::Resource res,
const QRhiNativeHandles *nat)
763 const QRhiD3D12NativeHandles *d3dnat =
static_cast<
const QRhiD3D12NativeHandles *>(nat);
765 case QSGRendererInterface::DeviceResource:
767 case QSGRendererInterface::CommandQueueResource:
768 return d3dnat->commandQueue;
776static const void *qsgrhi_mtl_rifResource(QSGRendererInterface::Resource res,
const QRhiNativeHandles *nat,
777 const QRhiNativeHandles *cbNat)
779 const QRhiMetalNativeHandles *mtlnat =
static_cast<
const QRhiMetalNativeHandles *>(nat);
780 const QRhiMetalCommandBufferNativeHandles *maybeMtlCbNat =
781 static_cast<
const QRhiMetalCommandBufferNativeHandles *>(cbNat);
784 case QSGRendererInterface::DeviceResource:
786 case QSGRendererInterface::CommandQueueResource:
787 return mtlnat->cmdQueue;
788 case QSGRendererInterface::CommandListResource:
790 return maybeMtlCbNat->commandBuffer;
793 case QSGRendererInterface::CommandEncoderResource:
795 return maybeMtlCbNat->encoder;
804const void *QSGRhiSupport::rifResource(QSGRendererInterface::Resource res,
805 const QSGDefaultRenderContext *rc,
806 const QQuickWindow *w)
808 QRhi *rhi = rc->rhi();
815 case QSGRendererInterface::RhiResource:
817 case QSGRendererInterface::RhiSwapchainResource:
818 return QQuickWindowPrivate::get(w)->swapchain;
819 case QSGRendererInterface::RhiRedirectCommandBuffer:
820 return QQuickWindowPrivate::get(w)->redirect.commandBuffer;
821 case QSGRendererInterface::RhiRedirectRenderTarget:
822 return QQuickWindowPrivate::get(w)->redirect.rt.rt.renderTarget;
827 const QRhiNativeHandles *nat = rhi->nativeHandles();
831 switch (m_rhiBackend) {
835 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
836 QRhiRenderPassDescriptor *rp = rc->currentFrameRenderPass();
837 return qsgrhi_vk_rifResource(res, nat,
838 cb ? cb->nativeHandles() :
nullptr,
839 rp ? rp->nativeHandles() :
nullptr);
843 case QRhi::OpenGLES2:
844 return qsgrhi_gl_rifResource(res, nat);
848 return qsgrhi_d3d11_rifResource(res, nat);
850 return qsgrhi_d3d12_rifResource(res, nat);
855 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
856 return qsgrhi_mtl_rifResource(res, nat, cb ? cb->nativeHandles() :
nullptr);
864int QSGRhiSupport::chooseSampleCount(
int samples, QRhi *rhi)
866 int msaaSampleCount = samples;
867 if (qEnvironmentVariableIsSet(
"QSG_SAMPLES"))
868 msaaSampleCount = qEnvironmentVariableIntValue(
"QSG_SAMPLES");
869 msaaSampleCount = qMax(1, msaaSampleCount);
870 if (msaaSampleCount > 1) {
871 const QVector<
int> supportedSampleCounts = rhi->supportedSampleCounts();
872 if (!supportedSampleCounts.contains(msaaSampleCount)) {
873 int reducedSampleCount = 1;
874 for (
int i = supportedSampleCounts.size() - 1; i >= 0; --i) {
875 if (supportedSampleCounts[i] <= msaaSampleCount) {
876 reducedSampleCount = supportedSampleCounts[i];
880 qWarning() <<
"Requested MSAA sample count" << msaaSampleCount
881 <<
"but supported sample counts are" << supportedSampleCounts
882 <<
", using sample count" << reducedSampleCount <<
"instead";
883 msaaSampleCount = reducedSampleCount;
886 return msaaSampleCount;
889int QSGRhiSupport::chooseSampleCountForWindowWithRhi(QWindow *window, QRhi *rhi)
891 return chooseSampleCount(qMax(QSurfaceFormat::defaultFormat().samples(), window->requestedFormat().samples()), rhi);
895QOffscreenSurface *QSGRhiSupport::maybeCreateOffscreenSurface(QWindow *window)
897 QOffscreenSurface *offscreenSurface =
nullptr;
899 if (rhiBackend() == QRhi::OpenGLES2) {
900 const QSurfaceFormat format = window->requestedFormat();
901 offscreenSurface = QRhiGles2InitParams::newFallbackSurface(format);
906 return offscreenSurface;
909void QSGRhiSupport::prepareWindowForRhi(QQuickWindow *window)
912 if (rhiBackend() == QRhi::Vulkan) {
913 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
921 if (!window->vulkanInstance() && !wd->renderControl) {
922 QVulkanInstance *vkinst = QVulkanDefaultInstance::instance();
924 qCDebug(QSG_LOG_INFO) <<
"Got Vulkan instance from QVulkanDefaultInstance, requested api version was" << vkinst->apiVersion();
926 qCDebug(QSG_LOG_INFO) <<
"No Vulkan instance from QVulkanDefaultInstance, expect problems";
927 window->setVulkanInstance(vkinst);
937 QDir::root().mkpath(name);
938 return QFileInfo(name).isWritable();
943 static bool checked =
false;
944 static QString currentCacheDir;
945 static bool cacheWritable =
false;
948 return cacheWritable ? currentCacheDir : QString();
957 const QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
958 const QString subPath = QLatin1String(
"/qtpipelinecache-") + QSysInfo::buildAbi() + QLatin1Char(
'/');
960 if (!cachePath.isEmpty()) {
961 currentCacheDir = cachePath + subPath;
962 cacheWritable = ensureWritableDir(currentCacheDir);
965 return cacheWritable ? currentCacheDir : QString();
970 const QString cacheDir = automaticPipelineCacheDir();
971 if (!cacheDir.isEmpty())
972 return cacheDir + QLatin1String(
"qqpc_") + QString::fromLatin1(rhi->backendName()).toLower();
979 return wflags.testFlag(Qt::ToolTip) || wflags.testFlag(Qt::SplashScreen);
985 return wflags.testFlag(Qt::Dialog) || wflags.testFlag(Qt::Popup);
988#if !QT_CONFIG(temporaryfile)
989static inline QString pipelineCacheLockFileName(
const QString &name)
991 return name + QLatin1String(
".lck");
995void QSGRhiSupport::preparePipelineCache(QRhi *rhi, QQuickWindow *window)
997 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
1000 QString pipelineCacheLoad = wd->graphicsConfig.pipelineCacheLoadFile();
1001 bool isAutomatic =
false;
1002 if (pipelineCacheLoad.isEmpty() && wd->graphicsConfig.isAutomaticPipelineCacheEnabled()) {
1003 if (!isAutomaticPipelineCacheLoadSkippedForWindow(window->flags())) {
1004 pipelineCacheLoad = automaticPipelineCacheFileName(rhi);
1009 if (pipelineCacheLoad.isEmpty())
1012#if !QT_CONFIG(temporaryfile)
1013 QLockFile lock(pipelineCacheLockFileName(pipelineCacheLoad));
1015 qWarning(
"Could not create pipeline cache lock file '%s'",
1016 qPrintable(lock.fileName()));
1021 QFile f(pipelineCacheLoad);
1022 if (!f.open(QIODevice::ReadOnly)) {
1024 qWarning(
"Could not open pipeline cache source file '%s'",
1025 qPrintable(pipelineCacheLoad));
1030 const QByteArray buf = f.readAll();
1031 if (!buf.isEmpty()) {
1032 qCDebug(QSG_LOG_INFO,
"Attempting to seed pipeline cache for QRhi %p from '%s'",
1033 rhi, qPrintable(pipelineCacheLoad));
1034 rhi->setPipelineCacheData(buf);
1038void QSGRhiSupport::finalizePipelineCache(QRhi *rhi,
const QQuickGraphicsConfiguration &config)
1041 qCDebug(QSG_LOG_INFO,
"Total time spent on pipeline creation during the lifetime of the QRhi %p was %lld ms",
1042 rhi, rhi->statistics().totalPipelineCreationTime);
1045 QString pipelineCacheSave = config.pipelineCacheSaveFile();
1046 bool isAutomatic =
false;
1047 if (pipelineCacheSave.isEmpty() && config.isAutomaticPipelineCacheEnabled()) {
1048 pipelineCacheSave = automaticPipelineCacheFileName(rhi);
1052 if (pipelineCacheSave.isEmpty())
1055 const QByteArray buf = rhi->pipelineCacheData();
1059 if (buf.isEmpty()) {
1067 QDir().remove(pipelineCacheSave);
1073#if QT_CONFIG(temporaryfile)
1074 QSaveFile f(pipelineCacheSave);
1076 QLockFile lock(pipelineCacheLockFileName(pipelineCacheSave));
1078 qWarning(
"Could not create pipeline cache lock file '%s'",
1079 qPrintable(lock.fileName()));
1082 QFile f(pipelineCacheSave);
1084 if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
1086 const QString msg = f.errorString();
1087 qWarning(
"Could not open pipeline cache output file '%s': %s",
1088 qPrintable(pipelineCacheSave), qPrintable(msg));
1093 qCDebug(QSG_LOG_INFO,
"Writing pipeline cache contents (%d bytes) for QRhi %p to '%s'",
1094 int(buf.size()), rhi, qPrintable(pipelineCacheSave));
1096 if (f.write(buf) != buf.size()
1097#if QT_CONFIG(temporaryfile)
1103 const QString msg = f.errorString();
1104 qWarning(
"Could not write pipeline cache: %s", qPrintable(msg));
1111QSGRhiSupport::RhiCreateResult QSGRhiSupport::createRhi(QQuickWindow *window, QSurface *offscreenSurface,
bool forcePreferSwRenderer)
1113 QRhi *rhi =
nullptr;
1114 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
1115 const QQuickGraphicsDevicePrivate *customDevD = QQuickGraphicsDevicePrivate::get(&wd->customDeviceObjects);
1116 if (customDevD->type == QQuickGraphicsDevicePrivate::Type::Rhi) {
1117 rhi = customDevD->u.rhi;
1119 preparePipelineCache(rhi, window);
1120 return { rhi,
false };
1124 const bool debugLayer = wd->graphicsConfig.isDebugLayerEnabled();
1125 const bool debugMarkers = wd->graphicsConfig.isDebugMarkersEnabled();
1126 const bool timestamps = wd->graphicsConfig.timestampsEnabled();
1127 const bool preferSoftware = wd->graphicsConfig.prefersSoftwareDevice() || forcePreferSwRenderer;
1128 const bool pipelineCacheSave = !wd->graphicsConfig.pipelineCacheSaveFile().isEmpty()
1129 || (wd->graphicsConfig.isAutomaticPipelineCacheEnabled()
1130 && !isAutomaticPipelineCacheSaveSkippedForWindow(window->flags()));
1132 const QString backendName = rhiBackendName();
1133 qCDebug(QSG_LOG_INFO,
1134 "Creating QRhi with backend %s for window %p (wflags 0x%X)\n"
1135 " Graphics API debug/validation layers: %d\n"
1136 " Debug markers: %d\n"
1138 " Prefer software device: %d%s\n"
1139 " Shader/pipeline cache collection: %d",
1140 qPrintable(backendName), window,
int(window->flags()), debugLayer,
1141 debugMarkers, timestamps, preferSoftware, forcePreferSwRenderer ?
" [FORCED]" :
"", pipelineCacheSave);
1144 flags |= QRhi::SuppressSmokeTestWarnings;
1146 flags |= QRhi::EnableDebugMarkers;
1148 flags |= QRhi::EnableTimestamps;
1150 flags |= QRhi::PreferSoftwareRenderer;
1151 if (pipelineCacheSave)
1152 flags |= QRhi::EnablePipelineCacheDataSave;
1154 QRhiAdapter *rhiAdapter = customDevD->type == QQuickGraphicsDevicePrivate::Type::RhiAdapter ? customDevD->u.rhiAdapter :
nullptr;
1155 const QRhi::Implementation backend = rhiBackend();
1156 if (backend == QRhi::Null) {
1157 QRhiNullInitParams rhiParams;
1158 rhi = QRhi::create(backend, &rhiParams, flags,
nullptr, rhiAdapter);
1160#if QT_CONFIG(opengl)
1161 if (backend == QRhi::OpenGLES2) {
1162 const QSurfaceFormat format = window->requestedFormat();
1163 QRhiGles2InitParams rhiParams;
1164 rhiParams.format = format;
1165 rhiParams.fallbackSurface = offscreenSurface;
1166 rhiParams.window = window;
1167 if (customDevD->type == QQuickGraphicsDevicePrivate::Type::OpenGLContext) {
1168 QRhiGles2NativeHandles importDev;
1169 importDev.context = customDevD->u.context;
1170 qCDebug(QSG_LOG_INFO,
"Using existing QOpenGLContext %p", importDev.context);
1171 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1173 rhi = QRhi::create(backend, &rhiParams, flags,
nullptr, rhiAdapter);
1177 Q_UNUSED(offscreenSurface);
1178 if (backend == QRhi::OpenGLES2)
1179 qWarning(
"OpenGL was requested for Qt Quick, but this build of Qt has no OpenGL support.");
1181#if QT_CONFIG(vulkan)
1182 if (backend == QRhi::Vulkan) {
1184 QVulkanDefaultInstance::setFlag(QVulkanDefaultInstance::EnableValidation,
true);
1185 QRhiVulkanInitParams rhiParams;
1186 prepareWindowForRhi(window);
1187 rhiParams.inst = window->vulkanInstance();
1188 if (!rhiParams.inst)
1189 qWarning(
"No QVulkanInstance set for QQuickWindow, this is wrong.");
1190 if (window->handle())
1191 rhiParams.window = window;
1192 rhiParams.deviceExtensions = wd->graphicsConfig.deviceExtensions();
1193 if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceObjects) {
1194 QRhiVulkanNativeHandles importDev;
1195 importDev.physDev =
reinterpret_cast<VkPhysicalDevice>(customDevD->u.deviceObjects.physicalDevice);
1196 importDev.dev =
reinterpret_cast<VkDevice>(customDevD->u.deviceObjects.device);
1197 importDev.gfxQueueFamilyIdx = customDevD->u.deviceObjects.queueFamilyIndex;
1198 importDev.gfxQueueIdx = customDevD->u.deviceObjects.queueIndex;
1199 qCDebug(QSG_LOG_INFO,
"Using existing native Vulkan physical device %p device %p graphics queue family index %d",
1200 importDev.physDev, importDev.dev, importDev.gfxQueueFamilyIdx);
1201 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1202 }
else if (customDevD->type == QQuickGraphicsDevicePrivate::Type::PhysicalDevice) {
1203 QRhiVulkanNativeHandles importDev;
1204 importDev.physDev =
reinterpret_cast<VkPhysicalDevice>(customDevD->u.physicalDevice.physicalDevice);
1205 qCDebug(QSG_LOG_INFO,
"Using existing native Vulkan physical device %p", importDev.physDev);
1206 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1208 rhi = QRhi::create(backend, &rhiParams, flags,
nullptr, rhiAdapter);
1212 if (backend == QRhi::Vulkan)
1213 qWarning(
"Vulkan was requested for Qt Quick, but this build of Qt has no Vulkan support.");
1216 if (backend == QRhi::D3D11) {
1217 QRhiD3D11InitParams rhiParams;
1218 rhiParams.enableDebugLayer = debugLayer;
1219 if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceAndContext) {
1220 QRhiD3D11NativeHandles importDev;
1221 importDev.dev = customDevD->u.deviceAndContext.device;
1222 importDev.context = customDevD->u.deviceAndContext.context;
1223 qCDebug(QSG_LOG_INFO,
"Using existing native D3D11 device %p and context %p",
1224 importDev.dev, importDev.context);
1225 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1226 }
else if (customDevD->type == QQuickGraphicsDevicePrivate::Type::Adapter) {
1227 QRhiD3D11NativeHandles importDev;
1228 importDev.adapterLuidLow = customDevD->u.adapter.luidLow;
1229 importDev.adapterLuidHigh = customDevD->u.adapter.luidHigh;
1230 importDev.featureLevel = customDevD->u.adapter.featureLevel;
1231 qCDebug(QSG_LOG_INFO,
"Using D3D11 adapter LUID %u, %d and feature level %d",
1232 importDev.adapterLuidLow, importDev.adapterLuidHigh, importDev.featureLevel);
1233 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1235 rhi = QRhi::create(backend, &rhiParams, flags,
nullptr, rhiAdapter);
1236 if (!rhi && attemptReinitWithSwRastUponFail() && !flags.testFlag(QRhi::PreferSoftwareRenderer) && !rhiAdapter) {
1237 qCDebug(QSG_LOG_INFO,
"Failed to create a D3D device with default settings; "
1238 "attempting to get a software rasterizer backed device instead");
1239 flags |= QRhi::PreferSoftwareRenderer;
1240 rhi = QRhi::create(backend, &rhiParams, flags);
1243 }
else if (backend == QRhi::D3D12) {
1244 QRhiD3D12InitParams rhiParams;
1245 rhiParams.enableDebugLayer = debugLayer;
1246 if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceAndContext) {
1247 QRhiD3D12NativeHandles importDev;
1248 importDev.dev = customDevD->u.deviceAndContext.device;
1249 qCDebug(QSG_LOG_INFO,
"Using existing native D3D12 device %p", importDev.dev);
1250 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1251 }
else if (customDevD->type == QQuickGraphicsDevicePrivate::Type::Adapter) {
1252 QRhiD3D12NativeHandles importDev;
1253 importDev.adapterLuidLow = customDevD->u.adapter.luidLow;
1254 importDev.adapterLuidHigh = customDevD->u.adapter.luidHigh;
1255 importDev.minimumFeatureLevel = customDevD->u.adapter.featureLevel;
1256 qCDebug(QSG_LOG_INFO,
"Using D3D12 adapter LUID %u, %d and minimum feature level %d",
1257 importDev.adapterLuidLow, importDev.adapterLuidHigh, importDev.minimumFeatureLevel);
1258 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1260 QRhiAdapter *rhiAdapter = customDevD->type == QQuickGraphicsDevicePrivate::Type::RhiAdapter ? customDevD->u.rhiAdapter :
nullptr;
1261 rhi = QRhi::create(backend, &rhiParams, flags,
nullptr, rhiAdapter);
1262 if (!rhi && attemptReinitWithSwRastUponFail() && !flags.testFlag(QRhi::PreferSoftwareRenderer) && !rhiAdapter) {
1263 qCDebug(QSG_LOG_INFO,
"Failed to create a D3D device with default settings; "
1264 "attempting to get a software rasterizer backed device instead");
1265 flags |= QRhi::PreferSoftwareRenderer;
1266 rhi = QRhi::create(backend, &rhiParams, flags);
1272 if (backend == QRhi::Metal) {
1273 QRhiMetalInitParams rhiParams;
1274 if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceAndCommandQueue) {
1275 QRhiMetalNativeHandles importDev;
1276 importDev.dev = (MTLDevice *) customDevD->u.deviceAndCommandQueue.device;
1277 importDev.cmdQueue = (MTLCommandQueue *) customDevD->u.deviceAndCommandQueue.cmdQueue;
1278 qCDebug(QSG_LOG_INFO,
"Using existing native Metal device %p and command queue %p",
1279 importDev.dev, importDev.cmdQueue);
1280 rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
1282 rhi = QRhi::create(backend, &rhiParams, flags,
nullptr, rhiAdapter);
1288 qCDebug(QSG_LOG_INFO,
"Created QRhi %p for window %p", rhi, window);
1289 preparePipelineCache(rhi, window);
1291 qWarning(
"Failed to create RHI (backend %d)", backend);
1294 return { rhi,
true };
1297void QSGRhiSupport::destroyRhi(QRhi *rhi,
const QQuickGraphicsConfiguration &config)
1302 if (!rhi->isDeviceLost())
1303 finalizePipelineCache(rhi, config);
1308QImage QSGRhiSupport::grabAndBlockInCurrentFrame(QRhi *rhi, QRhiCommandBuffer *cb, QRhiTexture *src)
1310 Q_ASSERT(rhi->isRecordingFrame());
1312 QRhiReadbackResult result;
1313 QRhiReadbackDescription readbackDesc(src);
1314 QRhiResourceUpdateBatch *resourceUpdates = rhi->nextResourceUpdateBatch();
1315 resourceUpdates->readBackTexture(readbackDesc, &result);
1317 cb->resourceUpdate(resourceUpdates);
1321 QImage::Format imageFormat;
1322 if (result.format == QRhiTexture::BGRA8) {
1323#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1324 imageFormat = QImage::Format_ARGB32_Premultiplied;
1326 imageFormat = QImage::Format_RGBA8888_Premultiplied;
1330 imageFormat = QImage::Format_RGBA8888_Premultiplied;
1333 const uchar *p =
reinterpret_cast<
const uchar *>(result.data.constData());
1334 const QImage img(p, result.pixelSize.width(), result.pixelSize.height(), imageFormat);
1336 if (rhi->isYUpInFramebuffer())
1337 return img.flipped();
1342QImage QSGRhiSupport::grabOffscreen(QQuickWindow *window)
1349 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
1352 Q_ASSERT(!wd->renderControl);
1354 QScopedPointer<QOffscreenSurface> offscreenSurface(maybeCreateOffscreenSurface(window));
1355 RhiCreateResult rhiResult = createRhi(window, offscreenSurface.data());
1356 if (!rhiResult.rhi) {
1357 qWarning(
"Failed to initialize QRhi for offscreen readback");
1360 std::unique_ptr<QRhi> rhiOwner(rhiResult.rhi);
1361 QRhi *rhi = rhiResult.own ? rhiOwner.get() : rhiOwner.release();
1363 const QSize pixelSize = window->size() * window->devicePixelRatio();
1364 QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, pixelSize, 1,
1365 QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
1366 if (!texture->create()) {
1367 qWarning(
"Failed to build texture for offscreen readback");
1370 QScopedPointer<QRhiRenderBuffer> depthStencil(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, pixelSize, 1));
1371 if (!depthStencil->create()) {
1372 qWarning(
"Failed to create depth/stencil buffer for offscreen readback");
1375 QRhiTextureRenderTargetDescription rtDesc(texture.data());
1376 rtDesc.setDepthStencilBuffer(depthStencil.data());
1377 QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1378 QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
1379 rt->setRenderPassDescriptor(rpDesc.data());
1380 if (!rt->create()) {
1381 qWarning(
"Failed to build render target for offscreen readback");
1387 QSGDefaultRenderContext::InitParams params;
1389 params.sampleCount = 1;
1390 params.initialSurfacePixelSize = pixelSize;
1391 params.maybeSurface = window;
1392 wd->context->initialize(¶ms);
1396 auto renderTarget = QQuickRenderTarget::fromRhiRenderTarget(rt.data());
1399 renderTarget.setDevicePixelRatio(window->devicePixelRatio());
1400 window->setRenderTarget(renderTarget);
1402 QRhiCommandBuffer *cb =
nullptr;
1403 if (rhi->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess) {
1404 qWarning(
"Failed to start recording the frame for offscreen readback");
1408 wd->setCustomCommandBuffer(cb);
1410 wd->syncSceneGraph();
1411 wd->renderSceneGraph();
1412 wd->setCustomCommandBuffer(
nullptr);
1414 QImage image = grabAndBlockInCurrentFrame(rhi, cb, texture.data());
1415 rhi->endOffscreenFrame();
1417 image.setDevicePixelRatio(window->devicePixelRatio());
1418 wd->cleanupNodesOnShutdown();
1419 wd->context->invalidate();
1421 window->setRenderTarget(QQuickRenderTarget());
1428QImage QSGRhiSupport::grabOffscreenForProtectedContent(QQuickWindow *window)
1436 QScopedPointer<QQuickWindow> offscreenWindow;
1437 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
1440 Q_ASSERT(!wd->renderControl);
1444 if (window->requestedFormat().testOption(QSurfaceFormat::ProtectedContent)) {
1445 QSurfaceFormat surfaceFormat = window->requestedFormat();
1446 surfaceFormat.setOption(QSurfaceFormat::ProtectedContent,
false);
1447 offscreenWindow.reset(
new QQuickWindow());
1448 offscreenWindow->setFormat(surfaceFormat);
1451 QScopedPointer<QOffscreenSurface> offscreenSurface(maybeCreateOffscreenSurface(window));
1452 RhiCreateResult rhiResult = createRhi(offscreenWindow.data() ? offscreenWindow.data() : window, offscreenSurface.data());
1453 if (!rhiResult.rhi) {
1454 qWarning(
"Failed to initialize QRhi for offscreen readback");
1457 QScopedPointer<QRhi> rhiOwner(rhiResult.rhi);
1458 QRhi *rhi = rhiResult.own ? rhiOwner.data() : rhiOwner.take();
1460 const QSize pixelSize = window->size() * window->devicePixelRatio();
1461 QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, pixelSize, 1,
1462 QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
1463 if (!texture->create()) {
1464 qWarning(
"Failed to build texture for offscreen readback");
1467 QScopedPointer<QRhiRenderBuffer> depthStencil(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, pixelSize, 1));
1468 if (!depthStencil->create()) {
1469 qWarning(
"Failed to create depth/stencil buffer for offscreen readback");
1472 QRhiTextureRenderTargetDescription rtDesc(texture.data());
1473 rtDesc.setDepthStencilBuffer(depthStencil.data());
1474 QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1475 QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
1476 rt->setRenderPassDescriptor(rpDesc.data());
1477 if (!rt->create()) {
1478 qWarning(
"Failed to build render target for offscreen readback");
1483 QRhi *currentRhi = wd->rhi;
1486 QSGDefaultRenderContext::InitParams params;
1488 params.sampleCount = 1;
1489 params.initialSurfacePixelSize = pixelSize;
1490 params.maybeSurface = window;
1491 wd->context->initialize(¶ms);
1494 QQuickRenderTarget currentRenderTarget = window->renderTarget();
1497 window->setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(rt.data()));
1499 QRhiCommandBuffer *cb =
nullptr;
1500 if (rhi->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess) {
1501 qWarning(
"Failed to start recording the frame for offscreen readback");
1505 wd->setCustomCommandBuffer(cb);
1507 wd->syncSceneGraph();
1508 wd->renderSceneGraph();
1509 wd->setCustomCommandBuffer(
nullptr);
1511 QImage image = grabAndBlockInCurrentFrame(rhi, cb, texture.data());
1512 rhi->endOffscreenFrame();
1514 image.setDevicePixelRatio(window->devicePixelRatio());
1518 wd->cleanupNodesOnShutdown();
1519 wd->context->invalidate();
1521 window->setRenderTarget(QQuickRenderTarget());
1526 window->setRenderTarget(currentRenderTarget);
1527 wd->rhi = currentRhi;
1528 params.rhi = currentRhi;
1529 wd->context->initialize(¶ms);
1536void QSGRhiSupport::applySwapChainFormat(QRhiSwapChain *scWithWindowSet, QQuickWindow *window)
1538 Q_ASSERT(scWithWindowSet->window() == window);
1540 QRhiSwapChain::Format swapChainFormat = QRhiSwapChain::SDR;
1542 QByteArray hdrRequest = qgetenv(
"QSG_RHI_HDR");
1543 if (hdrRequest.isEmpty())
1544 hdrRequest = window->property(
"_qt_sg_hdr_format").toByteArray();
1546 if (!hdrRequest.isEmpty()) {
1547 hdrRequest = hdrRequest.toLower();
1548 if (hdrRequest == QByteArrayLiteral(
"scrgb") || hdrRequest == QByteArrayLiteral(
"extendedsrgblinear"))
1549 swapChainFormat = QRhiSwapChain::HDRExtendedSrgbLinear;
1550 else if (hdrRequest == QByteArrayLiteral(
"hdr10"))
1551 swapChainFormat = QRhiSwapChain::HDR10;
1552 else if (hdrRequest == QByteArrayLiteral(
"p3"))
1553 swapChainFormat = QRhiSwapChain::HDRExtendedDisplayP3Linear;
1556 const char *fmtStr =
"unknown";
1557 switch (swapChainFormat) {
1558 case QRhiSwapChain::SDR:
1561 case QRhiSwapChain::HDRExtendedSrgbLinear:
1564 case QRhiSwapChain::HDR10:
1567 case QRhiSwapChain::HDRExtendedDisplayP3Linear:
1568 fmtStr =
"Extended Linear Display P3";
1574 if (!scWithWindowSet->isFormatSupported(swapChainFormat)) {
1575 if (swapChainFormat != QRhiSwapChain::SDR) {
1576 qCDebug(QSG_LOG_INFO,
"Requested a %s swapchain but it is reported to be unsupported with the current display(s). "
1577 "In multi-screen configurations make sure the window is located on a HDR-enabled screen. "
1578 "Request ignored, using SDR swapchain.", fmtStr);
1583 scWithWindowSet->setFormat(swapChainFormat);
1585 if (swapChainFormat != QRhiSwapChain::SDR) {
1586 qCDebug(QSG_LOG_INFO,
"Creating %s swapchain", fmtStr);
1587 qCDebug(QSG_LOG_INFO) <<
"HDR output info:" << scWithWindowSet->hdrInfo();
1591QRhiTexture::Format QSGRhiSupport::toRhiTextureFormat(uint nativeFormat, QRhiTexture::Flags *flags)
const
1593 switch (m_rhiBackend) {
1594#if QT_CONFIG(vulkan)
1596 return toRhiTextureFormatFromVulkan(nativeFormat, flags);
1598#if QT_CONFIG(opengl)
1599 case QRhi::OpenGLES2:
1601 return toRhiTextureFormatFromGL(nativeFormat, flags);
1606 return toRhiTextureFormatFromDXGI(nativeFormat, flags);
1610 return toRhiTextureFormatFromMetal(nativeFormat, flags);
1613 return QRhiTexture::UnknownFormat;
1615 Q_UNUSED(nativeFormat)
1619bool QSGRhiSupport::attemptReinitWithSwRastUponFail()
const
1621 const QRhi::Implementation backend = rhiBackend();
1627 if (backend == QRhi::D3D11 || backend == QRhi::D3D12)
static bool isAutomaticPipelineCacheLoadSkippedForWindow(Qt::WindowFlags wflags)
static QString automaticPipelineCacheDir()
static bool ensureWritableDir(const QString &name)
static QString automaticPipelineCacheFileName(QRhi *rhi)
static bool isAutomaticPipelineCacheSaveSkippedForWindow(Qt::WindowFlags wflags)