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::initialize(const QVector<XrExtensionProperties> &extensions)
22{
23 return hasExtension(extensions, XR_KHR_METAL_ENABLE_EXTENSION_NAME);
24}
25
26QVector<const char *> QOpenXRGraphicsMetal::getRequiredExtensions() const
27{
28 return { XR_KHR_METAL_ENABLE_EXTENSION_NAME };
29}
30
31const XrBaseInStructure *QOpenXRGraphicsMetal::handle() const
32{
33 return reinterpret_cast<const XrBaseInStructure*>(&m_graphicsBinding);
34}
35
36bool QOpenXRGraphicsMetal::setupGraphics(const XrInstance &instance, XrSystemId &systemId, const QQuickGraphicsConfiguration &quickConfig)
37{
38 Q_UNUSED(quickConfig)
39 PFN_xrGetMetalGraphicsRequirementsKHR pfnGetMetalGraphicsRequirementsKHR = nullptr;
40 OpenXRHelpers::checkXrResult(xrGetInstanceProcAddr(instance, "xrGetMetalGraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetMetalGraphicsRequirementsKHR)), instance);
41
42 if (!pfnGetMetalGraphicsRequirementsKHR) {
43 qWarning("Could not resolve pfnGetMetalGraphicsRequirementsKHR; perhaps the OpenXR implementation does not support Metal?");
44 return false;
45 }
46
47 // Create the Metal device for the adapter associated with the system.
48 if (!OpenXRHelpers::checkXrResult(pfnGetMetalGraphicsRequirementsKHR(instance, systemId, &m_graphicsRequirements), instance)) {
49 qWarning("Failed to get Metal graphics requirements.");
50 return false;
51 }
52
53 // From hello_xr/graphicsplugin_metal.cpp:
54 m_device = static_cast<MTLDevice*>(m_graphicsRequirements.metalDevice);
55 auto commandQueue = [m_device newCommandQueue];
56 m_commandQueue = static_cast<MTLCommandQueue *>(commandQueue);
57 m_graphicsBinding.commandQueue = m_commandQueue;
58
59 return true;
60}
61
62bool QOpenXRGraphicsMetal::finializeGraphics(QRhi *rhi)
63{
64 // STUB
65 Q_UNUSED(rhi)
66 return true;
67}
68
69int64_t QOpenXRGraphicsMetal::colorSwapchainFormat(const QVector<int64_t> &swapchainFormats) const
70{
71 constexpr MTLPixelFormat supportedDepthSwapchainFormats[] = {MTLPixelFormatRGBA8Unorm_sRGB, MTLPixelFormatRGBA8Unorm};
72 return *std::find_first_of(std::begin(supportedDepthSwapchainFormats),
73 std::end(supportedDepthSwapchainFormats),
74 swapchainFormats.begin(),
75 swapchainFormats.end());
76}
77
78int64_t QOpenXRGraphicsMetal::depthSwapchainFormat(const QVector<int64_t> &swapchainFormats) const
79{
80 // in order of preference
81 constexpr int64_t supportedDepthSwapchainFormats[] = {
82 MTLPixelFormatDepth24Unorm_Stencil8,
83 MTLPixelFormatDepth32Float,
84 MTLPixelFormatDepth16Unorm
85 };
86 return *std::find_first_of(std::begin(supportedDepthSwapchainFormats),
87 std::end(supportedDepthSwapchainFormats),
88 swapchainFormats.begin(),
89 swapchainFormats.end());
90}
91
92QVector<XrSwapchainImageBaseHeader *> QOpenXRGraphicsMetal::allocateSwapchainImages(int count, XrSwapchain swapchain)
93{
94 QVector<XrSwapchainImageBaseHeader*> swapchainImages;
95 QVector<XrSwapchainImageMetalKHR> swapchainImageBuffer(count);
96 for (XrSwapchainImageMetalKHR& image : swapchainImageBuffer) {
97 image.type = XR_TYPE_SWAPCHAIN_IMAGE_METAL_KHR;
98 swapchainImages.append(reinterpret_cast<XrSwapchainImageBaseHeader*>(&image));
99 }
100 m_swapchainImageBuffer.insert(swapchain, swapchainImageBuffer);
101 return swapchainImages;
102}
103
104QQuickRenderTarget QOpenXRGraphicsMetal::renderTarget(const XrSwapchainSubImage &subImage,
105 const XrSwapchainImageBaseHeader *swapchainImage,
106 quint64 swapchainFormat,
107 int samples,
108 int arraySize,
109 const XrSwapchainImageBaseHeader *depthSwapchainImage,
110 quint64 depthSwapchainFormat) const
111{
112 MTLTexture *const colorTexture = static_cast<MTLTexture * const>(reinterpret_cast<const XrSwapchainImageMetalKHR*>(swapchainImage)->texture);
113 MTLPixelFormat colorFormat = static_cast<MTLPixelFormat>(swapchainFormat);
114
115 QQuickRenderTarget::Flags flags;
116 if (samples > 1)
117 flags |= QQuickRenderTarget::Flag::MultisampleResolve;
118
119 QQuickRenderTarget renderTarget = QQuickRenderTarget::fromMetalTexture(colorTexture, colorFormat, colorFormat, QSize(subImage.imageRect.extent.width, subImage.imageRect.extent.height), samples, arraySize, flags);
120
121 Q_UNUSED(depthSwapchainImage)
122 Q_UNUSED(depthSwapchainFormat)
123 return renderTarget;
124}
125
126QRhi *QOpenXRGraphicsMetal::rhi() const
127{
128 return m_rhi;
129}
130
131
132void QOpenXRGraphicsMetal::setupWindow(QQuickWindow *window)
133{
134 auto qqGraphicsDevice = QQuickGraphicsDevice::fromDeviceAndCommandQueue(static_cast<MTLDevice*>(m_device), static_cast<MTLCommandQueue *>(m_commandQueue));
135 window->setGraphicsDevice(qqGraphicsDevice);
136}
137
138QT_END_NAMESPACE
bool checkXrResult(XrResult result, XrInstance instance)
Combined button and popup list for selecting options.