56 PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR =
nullptr;
58 "xrGetVulkanGraphicsRequirementsKHR",
59 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsRequirementsKHR)),
62 if (!pfnGetVulkanGraphicsRequirementsKHR) {
63 qWarning(
"Could not resolve xrGetVulkanGraphicsRequirementsKHR; perhaps the OpenXR implementation does not support Vulkan?");
67 PFN_xrGetVulkanInstanceExtensionsKHR pfnGetVulkanInstanceExtensionsKHR =
nullptr;
69 "xrGetVulkanInstanceExtensionsKHR",
70 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanInstanceExtensionsKHR)),
73 XrGraphicsRequirementsVulkanKHR graphicsRequirements{};
74 graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR;
77 &graphicsRequirements),
80 quint32 extensionNamesSize = 0;
88 QByteArray extensionNames;
89 extensionNames.resize(extensionNamesSize);
94 extensionNames.data()),
100 auto stripNullChars = [](
const QByteArray &string) {
101 auto begin = string.begin();
102 auto end = string.end();
103 while (begin < end && end[-1] ==
'\x00')
105 return QByteArray(begin, end - begin);
108 QByteArrayList extensions = extensionNames.split(
' ');
109 for (
auto &ext : extensions)
110 ext = stripNullChars(ext);
112 for (
auto &rhiExt : QRhiVulkanInitParams::preferredInstanceExtensions()) {
113 if (!extensions.contains(rhiExt))
114 extensions.append(rhiExt);
117 m_vulkanInstance.setExtensions(extensions);
120 const QVersionNumber supportedVersion = m_vulkanInstance.supportedApiVersion();
121 if (supportedVersion >= QVersionNumber(1, 3))
122 m_vulkanInstance.setApiVersion(QVersionNumber(1, 3));
123 else if (supportedVersion >= QVersionNumber(1, 2))
124 m_vulkanInstance.setApiVersion(QVersionNumber(1, 2));
125 else if (supportedVersion >= QVersionNumber(1, 1))
126 m_vulkanInstance.setApiVersion(QVersionNumber(1, 1));
128 if (quickConfig.isDebugLayerEnabled())
129 m_vulkanInstance.setLayers({
"VK_LAYER_LUNARG_standard_validation" });
131 if (!m_vulkanInstance.create()) {
132 qWarning(
"Quick 3D XR: Failed to create Vulkan instance");
137 PFN_xrGetVulkanDeviceExtensionsKHR pfnGetVulkanDeviceExtensionsKHR =
nullptr;
139 "xrGetVulkanDeviceExtensionsKHR",
140 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanDeviceExtensionsKHR)),
143 uint32_t deviceExtensionNamesSize = 0;
147 &deviceExtensionNamesSize,
150 QByteArray deviceExtensionNames;
151 deviceExtensionNames.resize(deviceExtensionNamesSize);
154 deviceExtensionNamesSize,
155 &deviceExtensionNamesSize,
156 deviceExtensionNames.data()),
159 auto deviceExtensions = deviceExtensionNames.split(
' ');
160 for (
auto &ext : deviceExtensions) {
161 ext = stripNullChars(ext);
163 m_graphicsConfiguration.setDeviceExtensions(deviceExtensions);
166 PFN_xrGetVulkanGraphicsDeviceKHR pfnGetVulkanGraphicsDeviceKHR =
nullptr;
168 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsDeviceKHR)), instance);
170 OpenXRHelpers::checkXrResult(pfnGetVulkanGraphicsDeviceKHR(instance, systemId, m_vulkanInstance.vkInstance(), &m_vulkanPhysicalDevice), instance);
177 const QRhiVulkanNativeHandles *vulkanRhi =
static_cast<
const QRhiVulkanNativeHandles *>(rhi->nativeHandles());
178 m_vulkanDevice = vulkanRhi->dev;
179 Q_ASSERT(m_vulkanPhysicalDevice == vulkanRhi->physDev);
180 m_vulkanCommandQueue = vulkanRhi->gfxQueue;
181 m_queueFamilyIndex = vulkanRhi->gfxQueueFamilyIdx;
183 m_graphicsBinding.instance = m_vulkanInstance.vkInstance();
184 m_graphicsBinding.physicalDevice = m_vulkanPhysicalDevice;
185 m_graphicsBinding.device = m_vulkanDevice;
186 m_graphicsBinding.queueFamilyIndex = m_queueFamilyIndex;
187 m_graphicsBinding.queueIndex = 0;
215 QVarLengthArray<int64_t, 4> supportedDepthSwapchainFormats;
216 constexpr std::pair<int64_t, QRhiTexture::Format> nativeDepthSwapchainFormats[] = {
217 { VK_FORMAT_D24_UNORM_S8_UINT, QRhiTexture::D24S8 },
218 { VK_FORMAT_D32_SFLOAT_S8_UINT, QRhiTexture::D32F },
219 { VK_FORMAT_D32_SFLOAT, QRhiTexture::D32F },
220 { VK_FORMAT_D16_UNORM, QRhiTexture::D16 }
222 for (
const auto &format : nativeDepthSwapchainFormats) {
223 if (m_rhi->isTextureFormatSupported(format.second))
224 supportedDepthSwapchainFormats.append(format.first);
227 if (supportedDepthSwapchainFormats.isEmpty())
231 return *std::find_first_of(std::begin(supportedDepthSwapchainFormats),
232 std::end(supportedDepthSwapchainFormats),
233 swapchainFormats.begin(),
234 swapchainFormats.end());
251 const XrSwapchainImageBaseHeader *swapchainImage,
252 quint64 swapchainFormat,
255 const XrSwapchainImageBaseHeader *depthSwapchainImage,
256 quint64 depthSwapchainFormat)
const
258 VkImage colorTexture =
reinterpret_cast<
const XrSwapchainImageVulkanKHR*>(swapchainImage)->image;
260 VkFormat viewFormat = VkFormat(swapchainFormat);
261 switch (swapchainFormat) {
262 case VK_FORMAT_R8G8B8A8_SRGB:
263 viewFormat = VK_FORMAT_R8G8B8A8_UNORM;
265 case VK_FORMAT_B8G8R8A8_SRGB:
266 viewFormat = VK_FORMAT_B8G8R8A8_UNORM;
272 QQuickRenderTarget::Flags flags;
274 flags |= QQuickRenderTarget::Flag::MultisampleResolve;
276 const QSize pixelSize(subImage.imageRect.extent.width, subImage.imageRect.extent.height);
277 QQuickRenderTarget rt = QQuickRenderTarget::fromVulkanImage(colorTexture,
278 VK_IMAGE_LAYOUT_UNDEFINED,
279 VkFormat(swapchainFormat),
285 if (depthSwapchainImage) {
291 QRhiTexture::Format format = QRhiTexture::D24S8;
292 switch (depthSwapchainFormat) {
293 case VK_FORMAT_D32_SFLOAT_S8_UINT:
294 case VK_FORMAT_D32_SFLOAT:
295 format = QRhiTexture::D32F;
297 case VK_FORMAT_D16_UNORM:
298 format = QRhiTexture::D16;
301 VkImage depthImage =
reinterpret_cast<
const XrSwapchainImageVulkanKHR*>(depthSwapchainImage)->image;
302 if (m_depthTexture && (m_depthTexture->format() != format || m_depthTexture->pixelSize() != pixelSize || m_depthTexture->arraySize() != arraySize)) {
303 delete m_depthTexture;
304 m_depthTexture =
nullptr;
306 if (!m_depthTexture) {
309 m_depthTexture = m_rhi->newTextureArray(format, arraySize, pixelSize, 1, QRhiTexture::RenderTarget);
311 m_depthTexture = m_rhi->newTexture(format, pixelSize, 1, QRhiTexture::RenderTarget);
313 m_depthTexture->createFrom({ quint64(depthImage), VK_IMAGE_LAYOUT_UNDEFINED });
314 rt.setDepthTexture(m_depthTexture);