Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qopenxrgraphics_metal.mm
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5
7
8#include <rhi/qrhi.h>
9#include <QQuickGraphicsDevice>
10#include <QQuickWindow>
11
12#include <Metal/Metal.h>
13
15
16QOpenXRGraphicsMetal::QOpenXRGraphicsMetal()
17{
18
19}
20
21bool QOpenXRGraphicsMetal::isExtensionSupported(const QVector<XrExtensionProperties> &extensions) const
22{
23 for (const auto &extension : extensions) {
24 if (!strcmp(XR_KHR_METAL_ENABLE_EXTENSION_NAME,
25 extension.extensionName))
26 return true;
27 }
28 return false;
29}
30
31const char *QOpenXRGraphicsMetal::extensionName() const
32{
33 return XR_KHR_METAL_ENABLE_EXTENSION_NAME;
34}
35
36const XrBaseInStructure *QOpenXRGraphicsMetal::handle() const
37{
38 return reinterpret_cast<const XrBaseInStructure*>(&m_graphicsBinding);
39}
40
41bool QOpenXRGraphicsMetal::setupGraphics(const XrInstance &instance, XrSystemId &systemId, const QQuickGraphicsConfiguration &quickConfig)
42{
43 Q_UNUSED(quickConfig)
44 PFN_xrGetMetalGraphicsRequirementsKHR pfnGetMetalGraphicsRequirementsKHR = nullptr;
45 OpenXRHelpers::checkXrResult(xrGetInstanceProcAddr(instance, "xrGetMetalGraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetMetalGraphicsRequirementsKHR)), instance);
46
47 if (!pfnGetMetalGraphicsRequirementsKHR) {
48 qWarning("Could not resolve pfnGetMetalGraphicsRequirementsKHR; perhaps the OpenXR implementation does not support Metal?");
49 return false;
50 }
51
52 // Create the Metal device for the adapter associated with the system.
53 if (!OpenXRHelpers::checkXrResult(pfnGetMetalGraphicsRequirementsKHR(instance, systemId, &m_graphicsRequirements), instance)) {
54 qWarning("Failed to get Metal graphics requirements.");
55 return false;
56 }
57
58 // From hello_xr/graphicsplugin_metal.cpp:
59 m_device = static_cast<MTLDevice*>(m_graphicsRequirements.metalDevice);
60 auto commandQueue = [m_device newCommandQueue];
61 m_commandQueue = static_cast<MTLCommandQueue *>(commandQueue);
62 m_graphicsBinding.commandQueue = m_commandQueue;
63
64 return true;
65}
66
67bool QOpenXRGraphicsMetal::finializeGraphics(QRhi *rhi)
68{
69 // STUB
70 Q_UNUSED(rhi)
71 return true;
72}
73
74int64_t QOpenXRGraphicsMetal::colorSwapchainFormat(const QVector<int64_t> &swapchainFormats) const
75{
76 constexpr MTLPixelFormat supportedDepthSwapchainFormats[] = {MTLPixelFormatRGBA8Unorm_sRGB, MTLPixelFormatRGBA8Unorm};
77 return *std::find_first_of(std::begin(supportedDepthSwapchainFormats),
78 std::end(supportedDepthSwapchainFormats),
79 swapchainFormats.begin(),
80 swapchainFormats.end());
81}
82
83int64_t QOpenXRGraphicsMetal::depthSwapchainFormat(const QVector<int64_t> &swapchainFormats) const
84{
85 // in order of preference
86 constexpr int64_t supportedDepthSwapchainFormats[] = {
87 MTLPixelFormatDepth24Unorm_Stencil8,
88 MTLPixelFormatDepth32Float,
89 MTLPixelFormatDepth16Unorm
90 };
91 return *std::find_first_of(std::begin(supportedDepthSwapchainFormats),
92 std::end(supportedDepthSwapchainFormats),
93 swapchainFormats.begin(),
94 swapchainFormats.end());
95}
96
97QVector<XrSwapchainImageBaseHeader *> QOpenXRGraphicsMetal::allocateSwapchainImages(int count, XrSwapchain swapchain)
98{
99 QVector<XrSwapchainImageBaseHeader*> swapchainImages;
100 QVector<XrSwapchainImageMetalKHR> swapchainImageBuffer(count);
101 for (XrSwapchainImageMetalKHR& image : swapchainImageBuffer) {
102 image.type = XR_TYPE_SWAPCHAIN_IMAGE_METAL_KHR;
103 swapchainImages.append(reinterpret_cast<XrSwapchainImageBaseHeader*>(&image));
104 }
105 m_swapchainImageBuffer.insert(swapchain, swapchainImageBuffer);
106 return swapchainImages;
107}
108
109QQuickRenderTarget QOpenXRGraphicsMetal::renderTarget(const XrSwapchainSubImage &subImage,
110 const XrSwapchainImageBaseHeader *swapchainImage,
111 quint64 swapchainFormat,
112 int samples,
113 int arraySize,
114 const XrSwapchainImageBaseHeader *depthSwapchainImage,
115 quint64 depthSwapchainFormat) const
116{
117 MTLTexture *const colorTexture = static_cast<MTLTexture * const>(reinterpret_cast<const XrSwapchainImageMetalKHR*>(swapchainImage)->texture);
118 MTLPixelFormat colorFormat = static_cast<MTLPixelFormat>(swapchainFormat);
119
120 QQuickRenderTarget::Flags flags;
121 if (samples > 1)
122 flags |= QQuickRenderTarget::Flag::MultisampleResolve;
123
124 QQuickRenderTarget renderTarget = QQuickRenderTarget::fromMetalTexture(colorTexture, colorFormat, colorFormat, QSize(subImage.imageRect.extent.width, subImage.imageRect.extent.height), samples, arraySize, flags);
125
126 Q_UNUSED(depthSwapchainImage)
127 Q_UNUSED(depthSwapchainFormat)
128 return renderTarget;
129}
130
131QRhi *QOpenXRGraphicsMetal::rhi() const
132{
133 return m_rhi;
134}
135
136
137void QOpenXRGraphicsMetal::setupWindow(QQuickWindow *window)
138{
139 auto qqGraphicsDevice = QQuickGraphicsDevice::fromDeviceAndCommandQueue(static_cast<MTLDevice*>(m_device), static_cast<MTLCommandQueue *>(m_commandQueue));
140 window->setGraphicsDevice(qqGraphicsDevice);
141}
142
143QT_END_NAMESPACE
bool checkXrResult(XrResult result, XrInstance instance)