58 PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR =
nullptr;
60 "xrGetVulkanGraphicsRequirementsKHR",
61 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsRequirementsKHR)),
64 if (!pfnGetVulkanGraphicsRequirementsKHR) {
65 qWarning(
"Could not resolve xrGetVulkanGraphicsRequirementsKHR; perhaps the OpenXR implementation does not support Vulkan?");
69 PFN_xrGetVulkanInstanceExtensionsKHR pfnGetVulkanInstanceExtensionsKHR =
nullptr;
71 "xrGetVulkanInstanceExtensionsKHR",
72 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanInstanceExtensionsKHR)),
75 XrGraphicsRequirementsVulkanKHR graphicsRequirements{};
76 graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR;
77 OpenXRHelpers::checkXrResult(pfnGetVulkanGraphicsRequirementsKHR(instance,
79 &graphicsRequirements),
82 quint32 extensionNamesSize = 0;
83 OpenXRHelpers::checkXrResult(pfnGetVulkanInstanceExtensionsKHR(instance,
90 QByteArray extensionNames;
91 extensionNames.resize(extensionNamesSize);
92 OpenXRHelpers::checkXrResult(pfnGetVulkanInstanceExtensionsKHR(instance,
96 extensionNames.data()),
102 auto stripNullChars = [](
const QByteArray &string) {
103 auto begin = string.begin();
104 auto end = string.end();
105 while (begin < end && end[-1] ==
'\x00')
107 return QByteArray(begin, end - begin);
110 QByteArrayList extensions = extensionNames.split(
' ');
111 for (
auto &ext : extensions)
112 ext = stripNullChars(ext);
114 for (
auto &rhiExt : QRhiVulkanInitParams::preferredInstanceExtensions()) {
115 if (!extensions.contains(rhiExt))
116 extensions.append(rhiExt);
119 m_vulkanInstance.setExtensions(extensions);
122 const QVersionNumber supportedVersion = m_vulkanInstance.supportedApiVersion();
123 if (supportedVersion >= QVersionNumber(1, 3))
124 m_vulkanInstance.setApiVersion(QVersionNumber(1, 3));
125 else if (supportedVersion >= QVersionNumber(1, 2))
126 m_vulkanInstance.setApiVersion(QVersionNumber(1, 2));
127 else if (supportedVersion >= QVersionNumber(1, 1))
128 m_vulkanInstance.setApiVersion(QVersionNumber(1, 1));
130 if (quickConfig.isDebugLayerEnabled())
131 m_vulkanInstance.setLayers({
"VK_LAYER_LUNARG_standard_validation" });
133 if (!m_vulkanInstance.create()) {
134 qWarning(
"Quick 3D XR: Failed to create Vulkan instance");
139 PFN_xrGetVulkanDeviceExtensionsKHR pfnGetVulkanDeviceExtensionsKHR =
nullptr;
141 "xrGetVulkanDeviceExtensionsKHR",
142 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanDeviceExtensionsKHR)),
145 uint32_t deviceExtensionNamesSize = 0;
146 OpenXRHelpers::checkXrResult(pfnGetVulkanDeviceExtensionsKHR(instance,
149 &deviceExtensionNamesSize,
152 QByteArray deviceExtensionNames;
153 deviceExtensionNames.resize(deviceExtensionNamesSize);
154 OpenXRHelpers::checkXrResult(pfnGetVulkanDeviceExtensionsKHR(instance,
156 deviceExtensionNamesSize,
157 &deviceExtensionNamesSize,
158 deviceExtensionNames.data()),
161 auto deviceExtensions = deviceExtensionNames.split(
' ');
162 for (
auto &ext : deviceExtensions) {
163 ext = stripNullChars(ext);
165 m_graphicsConfiguration.setDeviceExtensions(deviceExtensions);
168 PFN_xrGetVulkanGraphicsDeviceKHR pfnGetVulkanGraphicsDeviceKHR =
nullptr;
169 OpenXRHelpers::checkXrResult(xrGetInstanceProcAddr(instance,
"xrGetVulkanGraphicsDeviceKHR",
170 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsDeviceKHR)), instance);
172 OpenXRHelpers::checkXrResult(pfnGetVulkanGraphicsDeviceKHR(instance, systemId, m_vulkanInstance.vkInstance(), &m_vulkanPhysicalDevice), instance);
179 const QRhiVulkanNativeHandles *vulkanRhi =
static_cast<
const QRhiVulkanNativeHandles *>(rhi->nativeHandles());
180 m_vulkanDevice = vulkanRhi->dev;
181 Q_ASSERT(m_vulkanPhysicalDevice == vulkanRhi->physDev);
182 m_vulkanCommandQueue = vulkanRhi->gfxQueue;
183 m_queueFamilyIndex = vulkanRhi->gfxQueueFamilyIdx;
185 m_graphicsBinding.instance = m_vulkanInstance.vkInstance();
186 m_graphicsBinding.physicalDevice = m_vulkanPhysicalDevice;
187 m_graphicsBinding.device = m_vulkanDevice;
188 m_graphicsBinding.queueFamilyIndex = m_queueFamilyIndex;
189 m_graphicsBinding.queueIndex = 0;
217 QVarLengthArray<int64_t, 4> supportedDepthSwapchainFormats;
218 constexpr std::pair<int64_t, QRhiTexture::Format> nativeDepthSwapchainFormats[] = {
219 { VK_FORMAT_D24_UNORM_S8_UINT, QRhiTexture::D24S8 },
220 { VK_FORMAT_D32_SFLOAT_S8_UINT, QRhiTexture::D32F },
221 { VK_FORMAT_D32_SFLOAT, QRhiTexture::D32F },
222 { VK_FORMAT_D16_UNORM, QRhiTexture::D16 }
224 for (
const auto &format : nativeDepthSwapchainFormats) {
225 if (m_rhi->isTextureFormatSupported(format.second))
226 supportedDepthSwapchainFormats.append(format.first);
229 if (supportedDepthSwapchainFormats.isEmpty())
233 return *std::find_first_of(std::begin(supportedDepthSwapchainFormats),
234 std::end(supportedDepthSwapchainFormats),
235 swapchainFormats.begin(),
236 swapchainFormats.end());
253 const XrSwapchainImageBaseHeader *swapchainImage,
254 quint64 swapchainFormat,
257 const XrSwapchainImageBaseHeader *depthSwapchainImage,
258 quint64 depthSwapchainFormat)
const
260 VkImage colorTexture =
reinterpret_cast<
const XrSwapchainImageVulkanKHR*>(swapchainImage)->image;
262 VkFormat viewFormat = VkFormat(swapchainFormat);
263 switch (swapchainFormat) {
264 case VK_FORMAT_R8G8B8A8_SRGB:
265 viewFormat = VK_FORMAT_R8G8B8A8_UNORM;
267 case VK_FORMAT_B8G8R8A8_SRGB:
268 viewFormat = VK_FORMAT_B8G8R8A8_UNORM;
274 QQuickRenderTarget::Flags flags;
276 flags |= QQuickRenderTarget::Flag::MultisampleResolve;
278 const QSize pixelSize(subImage.imageRect.extent.width, subImage.imageRect.extent.height);
279 QQuickRenderTarget rt = QQuickRenderTarget::fromVulkanImage(colorTexture,
280 VK_IMAGE_LAYOUT_UNDEFINED,
281 VkFormat(swapchainFormat),
287 if (depthSwapchainImage) {
293 QRhiTexture::Format format = QRhiTexture::D24S8;
294 switch (depthSwapchainFormat) {
295 case VK_FORMAT_D32_SFLOAT_S8_UINT:
296 case VK_FORMAT_D32_SFLOAT:
297 format = QRhiTexture::D32F;
299 case VK_FORMAT_D16_UNORM:
300 format = QRhiTexture::D16;
303 VkImage depthImage =
reinterpret_cast<
const XrSwapchainImageVulkanKHR*>(depthSwapchainImage)->image;
304 if (m_depthTexture && (m_depthTexture->format() != format || m_depthTexture->pixelSize() != pixelSize || m_depthTexture->arraySize() != arraySize)) {
305 delete m_depthTexture;
306 m_depthTexture =
nullptr;
308 if (!m_depthTexture) {
311 m_depthTexture = m_rhi->newTextureArray(format, arraySize, pixelSize, 1, QRhiTexture::RenderTarget);
313 m_depthTexture = m_rhi->newTexture(format, pixelSize, 1, QRhiTexture::RenderTarget);
315 m_depthTexture->createFrom({ quint64(depthImage), VK_IMAGE_LAYOUT_UNDEFINED });
316 rt.setDepthTexture(m_depthTexture);