63 PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR =
nullptr;
65 "xrGetVulkanGraphicsRequirementsKHR",
66 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsRequirementsKHR)),
69 if (!pfnGetVulkanGraphicsRequirementsKHR) {
70 qWarning(
"Could not resolve xrGetVulkanGraphicsRequirementsKHR; perhaps the OpenXR implementation does not support Vulkan?");
74 PFN_xrGetVulkanInstanceExtensionsKHR pfnGetVulkanInstanceExtensionsKHR =
nullptr;
76 "xrGetVulkanInstanceExtensionsKHR",
77 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanInstanceExtensionsKHR)),
80 XrGraphicsRequirementsVulkanKHR graphicsRequirements{};
81 graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR;
84 &graphicsRequirements),
87 quint32 extensionNamesSize = 0;
95 QByteArray extensionNames;
96 extensionNames.resize(extensionNamesSize);
101 extensionNames.data()),
107 auto stripNullChars = [](
const QByteArray &string) {
108 auto begin = string.begin();
109 auto end = string.end();
110 while (begin < end && end[-1] ==
'\x00')
112 return QByteArray(begin, end - begin);
115 QByteArrayList extensions = extensionNames.split(
' ');
116 for (
auto &ext : extensions)
117 ext = stripNullChars(ext);
119 for (
auto &rhiExt : QRhiVulkanInitParams::preferredInstanceExtensions()) {
120 if (!extensions.contains(rhiExt))
121 extensions.append(rhiExt);
124 m_vulkanInstance.setExtensions(extensions);
127 const QVersionNumber supportedVersion = m_vulkanInstance.supportedApiVersion();
128 if (supportedVersion >= QVersionNumber(1, 3))
129 m_vulkanInstance.setApiVersion(QVersionNumber(1, 3));
130 else if (supportedVersion >= QVersionNumber(1, 2))
131 m_vulkanInstance.setApiVersion(QVersionNumber(1, 2));
132 else if (supportedVersion >= QVersionNumber(1, 1))
133 m_vulkanInstance.setApiVersion(QVersionNumber(1, 1));
135 if (quickConfig.isDebugLayerEnabled())
136 m_vulkanInstance.setLayers({
"VK_LAYER_LUNARG_standard_validation" });
138 if (!m_vulkanInstance.create()) {
139 qWarning(
"Quick 3D XR: Failed to create Vulkan instance");
144 PFN_xrGetVulkanDeviceExtensionsKHR pfnGetVulkanDeviceExtensionsKHR =
nullptr;
146 "xrGetVulkanDeviceExtensionsKHR",
147 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanDeviceExtensionsKHR)),
150 uint32_t deviceExtensionNamesSize = 0;
154 &deviceExtensionNamesSize,
157 QByteArray deviceExtensionNames;
158 deviceExtensionNames.resize(deviceExtensionNamesSize);
161 deviceExtensionNamesSize,
162 &deviceExtensionNamesSize,
163 deviceExtensionNames.data()),
166 auto deviceExtensions = deviceExtensionNames.split(
' ');
167 for (
auto &ext : deviceExtensions) {
168 ext = stripNullChars(ext);
170 m_graphicsConfiguration.setDeviceExtensions(deviceExtensions);
173 PFN_xrGetVulkanGraphicsDeviceKHR pfnGetVulkanGraphicsDeviceKHR =
nullptr;
175 reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsDeviceKHR)), instance);
177 OpenXRHelpers::checkXrResult(pfnGetVulkanGraphicsDeviceKHR(instance, systemId, m_vulkanInstance.vkInstance(), &m_vulkanPhysicalDevice), instance);
184 const QRhiVulkanNativeHandles *vulkanRhi =
static_cast<
const QRhiVulkanNativeHandles *>(rhi->nativeHandles());
185 m_vulkanDevice = vulkanRhi->dev;
186 Q_ASSERT(m_vulkanPhysicalDevice == vulkanRhi->physDev);
187 m_vulkanCommandQueue = vulkanRhi->gfxQueue;
188 m_queueFamilyIndex = vulkanRhi->gfxQueueFamilyIdx;
190 m_graphicsBinding.instance = m_vulkanInstance.vkInstance();
191 m_graphicsBinding.physicalDevice = m_vulkanPhysicalDevice;
192 m_graphicsBinding.device = m_vulkanDevice;
193 m_graphicsBinding.queueFamilyIndex = m_queueFamilyIndex;
194 m_graphicsBinding.queueIndex = 0;
222 QVarLengthArray<int64_t, 4> supportedDepthSwapchainFormats;
223 constexpr std::pair<int64_t, QRhiTexture::Format> nativeDepthSwapchainFormats[] = {
224 { VK_FORMAT_D24_UNORM_S8_UINT, QRhiTexture::D24S8 },
225 { VK_FORMAT_D32_SFLOAT_S8_UINT, QRhiTexture::D32F },
226 { VK_FORMAT_D32_SFLOAT, QRhiTexture::D32F },
227 { VK_FORMAT_D16_UNORM, QRhiTexture::D16 }
229 for (
const auto &format : nativeDepthSwapchainFormats) {
230 if (m_rhi->isTextureFormatSupported(format.second))
231 supportedDepthSwapchainFormats.append(format.first);
234 if (supportedDepthSwapchainFormats.isEmpty())
238 return *std::find_first_of(std::begin(supportedDepthSwapchainFormats),
239 std::end(supportedDepthSwapchainFormats),
240 swapchainFormats.begin(),
241 swapchainFormats.end());
258 const XrSwapchainImageBaseHeader *swapchainImage,
259 quint64 swapchainFormat,
262 const XrSwapchainImageBaseHeader *depthSwapchainImage,
263 quint64 depthSwapchainFormat)
const
265 VkImage colorTexture =
reinterpret_cast<
const XrSwapchainImageVulkanKHR*>(swapchainImage)->image;
267 VkFormat viewFormat = VkFormat(swapchainFormat);
268 switch (swapchainFormat) {
269 case VK_FORMAT_R8G8B8A8_SRGB:
270 viewFormat = VK_FORMAT_R8G8B8A8_UNORM;
272 case VK_FORMAT_B8G8R8A8_SRGB:
273 viewFormat = VK_FORMAT_B8G8R8A8_UNORM;
279 QQuickRenderTarget::Flags flags;
281 flags |= QQuickRenderTarget::Flag::MultisampleResolve;
283 const QSize pixelSize(subImage.imageRect.extent.width, subImage.imageRect.extent.height);
284 QQuickRenderTarget rt = QQuickRenderTarget::fromVulkanImage(colorTexture,
285 VK_IMAGE_LAYOUT_UNDEFINED,
286 VkFormat(swapchainFormat),
292 if (depthSwapchainImage) {
298 QRhiTexture::Format format = QRhiTexture::D24S8;
299 switch (depthSwapchainFormat) {
300 case VK_FORMAT_D32_SFLOAT_S8_UINT:
301 case VK_FORMAT_D32_SFLOAT:
302 format = QRhiTexture::D32F;
304 case VK_FORMAT_D16_UNORM:
305 format = QRhiTexture::D16;
308 VkImage depthImage =
reinterpret_cast<
const XrSwapchainImageVulkanKHR*>(depthSwapchainImage)->image;
309 if (m_depthTexture && (m_depthTexture->format() != format || m_depthTexture->pixelSize() != pixelSize || m_depthTexture->arraySize() != arraySize)) {
310 delete m_depthTexture;
311 m_depthTexture =
nullptr;
313 if (!m_depthTexture) {
316 m_depthTexture = m_rhi->newTextureArray(format, arraySize, pixelSize, 1, QRhiTexture::RenderTarget);
318 m_depthTexture = m_rhi->newTexture(format, pixelSize, 1, QRhiTexture::RenderTarget);
320 m_depthTexture->createFrom({ quint64(depthImage), VK_IMAGE_LAYOUT_UNDEFINED });
321 rt.setDepthTexture(m_depthTexture);