evan 2026.1.4
Evan
Loading...
Searching...
No Matches
XrDeviceBackend.cpp
1/*
2** ETIB PROJECT, 2026
3** evan
4** File description:
5** XrDeviceBackend
6*/
7
8#include "evan/openxr/XrDeviceBackend.hpp"
9#include "evan/openxr/XrError.hpp"
10#include "evan/openxr/XrSwapchainContext.hpp"
11#include "evan/CheckedCast.hpp"
12
13#include <array>
14
16{
17 this->getLogger().info() << "Initializing XrDeviceBackend";
18
19 Version appVersion(0, 1, 0);
20 createXrInstance(platform);
21 getSystem();
22
23 const IXrPlatform &xrPlatform =
25 _openXrOptions = xrPlatform.getOpenXrOptions();
26
28 if (!viewConfigurations.empty()) {
29 _viewConfigurationType =
31 }
32
33 this->createInstance(platform, "Evan", appVersion);
34 this->pickPhysicalDevice();
35 this->createLogicalDevice();
36 this->createSession();
38
39 _handActionSubactionPath[LEFT_HAND_INDEX] =
41 _handActionSubactionPath[RIGHT_HAND_INDEX] =
43 _actionManager = std::make_unique<evan::XrManageActions>(*this);
44}
45
46evan::XrDeviceBackend::~XrDeviceBackend()
47{
48 this->getLogger().info() << "Destroying XrDeviceBackend";
49
50 this->getLogger().info() << "Waiting for device to be idle before cleanup";
51 vkDeviceWaitIdle(_device);
52
53 if (_device != VK_NULL_HANDLE) {
54 this->getLogger().info() << "Destroying Vulkan device";
55 vkDestroyDevice(_device, nullptr);
56 }
57 if (_session != XR_NULL_HANDLE) {
58 this->getLogger().info() << "Destroying OpenXR session";
59 xrDestroySession(_session);
60 }
61
62 this->getLogger().info() << "Destroying Vulkan instance";
63 vkDestroyInstance(_VkInstance, nullptr);
64
65 if (_XrInstance != XR_NULL_HANDLE) {
66 this->getLogger().info() << "Destroying OpenXR instance";
67 xrDestroyInstance(_XrInstance);
68 }
69}
70
72// Public Methods //
74
75evan::Error
77{
78 this->getLogger().info() << "Preprocessing frame for OpenXR session";
79
80 if (!_sessionRunning) {
81 this->getLogger().warning()
82 << "Cannot preprocess frame: XR session is not running";
83 return Error::NotReady;
84 }
88 };
90 if (result != XR_SUCCESS) {
91 this->getLogger().error()
92 << "Failed to wait for OpenXR frame: " << result;
93 return mapXrResult(result);
94 }
97 if (result != XR_SUCCESS) {
98 this->getLogger().error() << "Failed to begin OpenXR frame: " << result;
99 return mapXrResult(result);
100 }
101 _predictedDisplayTime = frameState.predictedDisplayTime;
102 if (frameState.shouldRender == XR_FALSE) {
104 frameEndInfo.displayTime = _predictedDisplayTime;
105 frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
106 frameEndInfo.layerCount = 0;
107 frameEndInfo.layers = nullptr;
108 xrEndFrame(_session, &frameEndInfo);
109 return Error::NotReady;
110 }
114 viewLocateInfo.viewConfigurationType = _viewConfigurationType;
115 viewLocateInfo.displayTime = _predictedDisplayTime;
116 viewLocateInfo.space = _space;
117 auto &xrContext =
119 std::vector<XrView> &views = xrContext._views;
121 static_cast<uint32_t>(views.size()),
122 &viewCount, views.data());
123 if (locateResult != XR_SUCCESS) {
124 this->getLogger().error()
125 << "Failed to locate OpenXR views: " << locateResult;
126 return mapXrResult(locateResult);
127 }
128
129 dynamic_cast<evan::XrSwapchainContext &>(swapchainContext).syncViewSet();
130 return Error::Ok;
131}
132
135{
136 this->getLogger().info() << "Processing frame for OpenXR session";
137
139 XrSwapchain swapchain = xrImage._swapchain;
142 };
144 if (result != XR_SUCCESS) {
145 this->getLogger().error()
146 << "Failed to release OpenXR swapchain image: " << result;
147 return mapXrResult(result);
148 }
149 return Error::Ok;
150}
151
152evan::Error
154{
155 this->getLogger().info() << "Postprocessing frame for OpenXR session";
156
157 auto &xrContext =
159 xrContext.updateProjectionLayerViews();
160 auto &projectionLayerViews = xrContext.getProjectionLayerViews();
162 layer.space = _space;
163 layer.viewCount = static_cast<uint32_t>(projectionLayerViews.size());
164 layer.views = projectionLayerViews.data();
165 std::array<XrCompositionLayerBaseHeader *, 1> layers = {
166 reinterpret_cast<XrCompositionLayerBaseHeader *>(&layer)
167 };
169 frameEndInfo.displayTime = _predictedDisplayTime;
170 frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
171 frameEndInfo.layerCount = (layer.viewCount > 0) ? 1u : 0u;
172 frameEndInfo.layers =
173 (frameEndInfo.layerCount > 0) ? layers.data() : nullptr;
174
176 if (result != XR_SUCCESS) {
177 this->getLogger().error() << "Failed to end OpenXR frame: " << result;
178 return mapXrResult(result);
179 }
180 return Error::Ok;
181}
182
184{
185 this->getLogger().info() << "Finding queue families for OpenXR session";
188
190 nullptr);
191
192 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
194 queueFamilies.data());
195 int i = 0;
196 for (const auto &queueFamily: queueFamilies) {
197 if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
198 indices.graphicsFamily = i;
199 break;
200 }
201 i++;
202 }
203
204 return indices;
205}
206
213
216{
217 this->getLogger().info()
218 << "Enumerating swapchain formats for OpenXR session";
219
220 std::vector<int64_t> swapchainFormats(swapchainFormatCount);
223 return swapchainFormats;
224}
225
226std::vector<XrViewConfigurationView>
228{
229 this->getLogger().info()
230 << "Enumerating view configurations for OpenXR session";
231
233 xrEnumerateViewConfigurationViews(_XrInstance, _systemId,
234 _viewConfigurationType, 0,
235 &viewConfigurationCount, nullptr);
236
237 if (viewConfigurationCount == 0) {
238 this->getLogger().error()
239 << "No view configurations found for the OpenXR system.";
240 return {};
241 }
242 std::vector<XrViewConfigurationView> viewConfigurations(
245 _XrInstance, _systemId, _viewConfigurationType, viewConfigurationCount,
247 return viewConfigurations;
248}
249
250std::vector<XrViewConfigurationType>
252{
253 this->getLogger().info()
254 << "Enumerating view configuration types for OpenXR system";
255
258 _XrInstance, _systemId, 0, &viewConfigurationCount, nullptr);
260 this->getLogger().error()
261 << "Failed to enumerate view configuration types: " << result;
262 return {};
263 }
264
265 std::vector<XrViewConfigurationType> viewConfigurations(
268 _XrInstance, _systemId, viewConfigurationCount, &viewConfigurationCount,
269 viewConfigurations.data());
270 if (result != XR_SUCCESS) {
271 this->getLogger().error()
272 << "Failed to enumerate view configuration types: " << result;
273 return {};
274 }
276 return viewConfigurations;
277}
278
280 const std::vector<XrViewConfigurationType> &configurations)
281{
282 for (const auto configuration: configurations) {
284 return configuration;
285 }
286 }
287 for (const auto configuration: configurations) {
289 return configuration;
290 }
291 }
292 if (!configurations.empty()) {
293 return configurations.front();
294 }
296}
297
298std::vector<std::shared_ptr<utility::event::Event>>
300{
301 this->getLogger().info() << "Polling actions for OpenXR session";
302
303 if (!_sessionRunning) {
304 this->getLogger().warning()
305 << "Cannot poll actions: XR session is not running";
306 return {};
307 }
308 if (_actionManager) {
309 return _actionManager->pollActions(*this);
310 }
311 this->getLogger().warning()
312 << "Action manager is not initialized, cannot poll actions";
313 return {};
314}
315
317// Protected Methods //
319
321 const std::string &appName,
323{
324 this->getLogger().info() << "Creating OpenXR instance for XrDeviceBackend";
325
328 nullptr;
330 std::vector<const char *> extensions;
331 std::vector<const char *> layers;
332
334 if (xrGetInstanceProcAddr(_XrInstance,
335 "xrGetVulkanGraphicsRequirements2KHR",
336 reinterpret_cast<PFN_xrVoidFunction *>(
338 != XR_SUCCESS) {
339 this->getLogger().error()
340 << "Failed to get xrGetVulkanGraphicsRequirements2KHR "
341 "function pointer.";
342 return;
343 }
345 _XrInstance, _systemId, &graphicsRequirements);
346 if (xrResult != XR_SUCCESS) {
347 this->getLogger().error()
348 << "Failed to query Vulkan graphics requirements through OpenXR.";
349 return;
350 }
352 _XrInstance, "xrCreateVulkanInstanceKHR",
353 reinterpret_cast<PFN_xrVoidFunction *>(&createVulkanInstanceKHR))
354 != XR_SUCCESS) {
355 this->getLogger().error()
356 << "Failed to get xrCreateVulkanInstanceKHR function pointer.";
357 return;
358 }
359
362 appInfo.pApplicationName = appName.c_str();
363 appInfo.applicationVersion = appVersion.to_uint32_t();
364 appInfo.pEngineName = "evan";
365 appInfo.engineVersion = VK_MAKE_VERSION(0, 1, 0);
366 // Ask for the newest API version the runtime supports: the core 1.1
367 // feature queries and the multiview feature struct require an effective
368 // 1.1 instance. If the loader cannot provide it, retry at the runtime's
369 // minimum below.
370 appInfo.apiVersion = graphicsRequirements.maxApiVersionSupported;
371
372 if (enableValidationLayers) {
373 this->getLogger().info()
374 << "Enabling validation layers for OpenXR Vulkan instance";
375 extensions = this->getRequiredInstanceExtensions();
376 if (!extensions.empty()) {
377 this->getLogger().info() << "Adding required instance extensions "
378 "for OpenXR Vulkan instance";
379 layers = this->getRequiredInstanceExtensionsAndroid();
380 }
381 }
382
383 VkInstanceCreateInfo createInfo {};
385 createInfo.pApplicationInfo = &appInfo;
386 createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
387 createInfo.ppEnabledExtensionNames = extensions.data();
388 createInfo.enabledLayerCount = static_cast<uint32_t>(layers.size());
389 createInfo.ppEnabledLayerNames = layers.data();
390
393 vulkanCreateInfoKHR.vulkanCreateInfo = &createInfo;
394 vulkanCreateInfoKHR.systemId = _systemId;
395 vulkanCreateInfoKHR.pfnGetInstanceProcAddr = &vkGetInstanceProcAddr;
396
398 createVulkanInstanceKHR(_XrInstance, &vulkanCreateInfoKHR, &_VkInstance,
399 &result);
400 if (result != VK_SUCCESS
401 && graphicsRequirements.maxApiVersionSupported
402 != graphicsRequirements.minApiVersionSupported) {
403 this->getLogger().warning()
404 << "Failed to create the Vulkan instance at the runtime's maximum "
405 "API version "
406 << VK_VERSION_MAJOR(graphicsRequirements.maxApiVersionSupported)
407 << "."
408 << VK_VERSION_MINOR(graphicsRequirements.maxApiVersionSupported)
409 << " (VkResult: " << result
410 << "). Retrying at the minimum supported version...";
411 appInfo.apiVersion = graphicsRequirements.minApiVersionSupported;
413 createVulkanInstanceKHR(_XrInstance, &vulkanCreateInfoKHR, &_VkInstance,
414 &result);
415 }
416 if (result != VK_SUCCESS) {
417 this->getLogger().error()
418 << "Failed to create Vulkan instance through OpenXR.";
419 return;
420 }
421 _vulkanApiVersion = appInfo.apiVersion;
422 this->getLogger().info()
423 << "Successfully created Vulkan instance through OpenXR with API "
424 "version "
425 << VK_VERSION_MAJOR(_vulkanApiVersion) << "."
426 << VK_VERSION_MINOR(_vulkanApiVersion) << ".";
427}
428
430{
431 this->getLogger().info()
432 << "Creating Vulkan logical device for OpenXR session";
433
434 if (_physicalDevice == VK_NULL_HANDLE) {
435 this->getLogger().error() << "Invalid Vulkan physical device provided.";
436 return;
437 }
438
440
442 _XrInstance, "xrCreateVulkanDeviceKHR",
443 reinterpret_cast<PFN_xrVoidFunction *>(&createVulkanDeviceKHR))
444 != XR_SUCCESS) {
445 this->getLogger().error()
446 << "Failed to get xrCreateVulkanDeviceKHR function pointer.";
447 return;
448 }
449 evan::QueueFamilyIndices indices = findQueueFamilies();
450 if (!indices.graphicsFamily.has_value()) {
451 this->getLogger().error()
452 << "Failed to find required queue families for the Vulkan device.";
453 return;
454 }
455
456 float queuePriority = 1.0f;
459 queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
460 queueCreateInfo.queueCount = 1;
461 queueCreateInfo.pQueuePriorities = &queuePriority;
462
464
465#ifdef DEV
466 deviceFeatures.fillModeNonSolid = VK_TRUE;
467#endif
468
469 // Multiview is opt-in: enable it only when the device and the application
470 // mode allow it, and keep the two-pass path as the fallback otherwise.
471 // The feature must be enabled whenever the installed shaders use the
472 // ViewIndex input, even for single-view render passes, because the SPIR-V
473 // MultiView capability requires it.
475 multiviewFeatures.sType =
477
478 const bool multiviewAvailable = multiviewMode() != MultiviewMode::Off
479 && queryMultiviewSupport(_physicalDevice, _vulkanApiVersion);
480 if (multiviewAvailable) {
481 multiviewFeatures.multiview = VK_TRUE;
482 _multiviewSupported = true;
483 this->getLogger().info()
484 << "Enabling the multiview feature on the Vulkan device.";
485 } else if (multiviewMode() == MultiviewMode::On) {
486 this->getLogger().error()
487 << "EVAN_MULTIVIEW=on but the device does not support the "
488 "multiview feature (or the instance is older than Vulkan "
489 "1.1). Continuing without multiview.";
490 }
491
492 VkDeviceCreateInfo createInfo {};
493 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
494 createInfo.pQueueCreateInfos = &queueCreateInfo;
495 createInfo.queueCreateInfoCount = 1;
496 createInfo.pEnabledFeatures = &deviceFeatures;
497 createInfo.pNext = _multiviewSupported ? &multiviewFeatures : nullptr;
498
501 vulkanDeviceCreateInfoKHR.systemId = _systemId;
502 vulkanDeviceCreateInfoKHR.pfnGetInstanceProcAddr = &vkGetInstanceProcAddr;
503 vulkanDeviceCreateInfoKHR.vulkanCreateInfo = &createInfo;
504 vulkanDeviceCreateInfoKHR.vulkanPhysicalDevice = _physicalDevice;
505
507 createVulkanDeviceKHR(_XrInstance, &vulkanDeviceCreateInfoKHR, &_device,
508 &result);
509 if (result != VK_SUCCESS) {
510 this->getLogger().error()
511 << "Failed to create Vulkan device through OpenXR.";
512 return;
513 }
514 this->getLogger().info()
515 << "Successfully created Vulkan device through OpenXR";
516}
517
519{
520 this->getLogger().info()
521 << "Picking Vulkan physical device for OpenXR session";
522
523 if (_VkInstance == VK_NULL_HANDLE) {
524 this->getLogger().error() << "Invalid Vulkan instance provided.";
525 return;
526 }
529
530 if (xrGetInstanceProcAddr(_XrInstance, "xrGetVulkanGraphicsDevice2KHR",
531 reinterpret_cast<PFN_xrVoidFunction *>(
533 != XR_SUCCESS) {
534 this->getLogger().error()
535 << "Failed to get xrGetVulkanGraphicsDevice2KHR function pointer.";
536 return;
537 }
538
540 deviceGetInfo.systemId = _systemId;
541 deviceGetInfo.vulkanInstance = _VkInstance;
542
544 &_physicalDevice)
545 != XR_SUCCESS) {
546 this->getLogger().error()
547 << "Failed to get Vulkan physical device through OpenXR.";
548 return;
549 }
550 this->getLogger().info()
551 << "Successfully obtained Vulkan physical device through OpenXR";
552}
553
555{
556 this->getLogger().info()
557 << "Creating visualized reference space for OpenXR session";
558
561 };
563 spaceCreateInfo.poseInReferenceSpace = { { 0, 0, 0, 1 }, { 0, 0, 0 } };
564
566 xrCreateReferenceSpace(_session, &spaceCreateInfo, &_space);
567 if (result != XR_SUCCESS) {
569 result = xrCreateReferenceSpace(_session, &spaceCreateInfo, &_space);
570 if (result != XR_SUCCESS) {
571 this->getLogger().error()
572 << "Failed to create OpenXR reference space.";
573 return;
574 }
575 }
576 this->getLogger().info()
577 << "Successfully created visualized reference space for OpenXR session";
578}
579
580std::vector<VkExtensionProperties>
582{
584 std::vector<VkExtensionProperties> extensions;
585 std::string layerName = "VK_LAYER_KHRONOS_validation";
586
588 &extensionCount, nullptr)
589 != VK_SUCCESS) {
590 this->getLogger().error()
591 << "Failed to enumerate OpenXR instance extension properties.";
592 return extensions;
593 }
594
597 layerName.c_str(), &extensionCount, extensions.data())
598 != VK_SUCCESS) {
599 this->getLogger().error()
600 << "Failed to enumerate OpenXR instance extension properties.";
601 return {};
602 }
603
604 return extensions;
605}
606
608// Private Methods //
610
611void evan::XrDeviceBackend::createXrInstance(const IPlatform &platform)
612{
613 this->getLogger().info() << "Creating OpenXR instance for XrDeviceBackend";
614
615 std::vector<std::string> requiredExtensions =
616 platform.getRequiredInstanceExtensions();
617 std::vector<const char *> extensions;
618 extensions.reserve(requiredExtensions.size());
619
620 for (const auto &ext: requiredExtensions) {
621 extensions.push_back(ext.c_str());
622 }
623
624 XrInstanceCreateInfo createInfo { XR_TYPE_INSTANCE_CREATE_INFO };
625 createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
626 createInfo.enabledExtensionNames = extensions.data();
627 createInfo.enabledApiLayerCount = 0;
628 createInfo.enabledApiLayerNames = nullptr;
629 std::strcpy(createInfo.applicationInfo.applicationName, "evan");
630 createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
631
632 const IXrPlatform &xrPlatform =
634
635 createInfo.next = xrPlatform.getInstanceCreateInfo();
636
637 XrResult result = xrCreateInstance(&createInfo, &_XrInstance);
638 if (result != XR_SUCCESS) {
639 // TODO: Throw an exception or handle the error appropriately
640 this->getLogger().error() << "Failed to create OpenXR instance.";
641 return;
642 }
643 this->getLogger().info() << "Successfully created OpenXR instance";
644}
645
646void evan::XrDeviceBackend::getSystem()
647{
648 XrSystemGetInfo systemInfo { XR_TYPE_SYSTEM_GET_INFO };
649 systemInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
650
651 XrResult result = xrGetSystem(_XrInstance, &systemInfo, &_systemId);
652 if (result != XR_SUCCESS) {
653 // TODO: Throw an exception or handle the error appropriately
654 this->getLogger().error() << "Failed to get OpenXR system.";
655 return;
656 }
657}
658
659void evan::XrDeviceBackend::createSession()
660{
661 this->getLogger().info() << "Creating OpenXR session for XrDeviceBackend";
662
663 XrSessionCreateInfo sessionCreateInfo = {};
664 XrGraphicsBindingVulkan2KHR graphicsBindingVulkan = {};
665 QueueFamilyIndices indices = findQueueFamilies();
666
667 if (indices.graphicsFamily == std::nullopt) {
668 this->getLogger().error() << "Failed to create OpenXR session: no "
669 "graphics queue family found.";
670 return;
671 }
672
673 graphicsBindingVulkan.type = XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR;
674 graphicsBindingVulkan.instance = _VkInstance;
675 graphicsBindingVulkan.physicalDevice = _physicalDevice;
676 graphicsBindingVulkan.device = _device;
677 graphicsBindingVulkan.queueFamilyIndex = indices.graphicsFamily.value();
678
679 sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO;
680 sessionCreateInfo.next = &graphicsBindingVulkan;
681 sessionCreateInfo.systemId = _systemId;
682
683 if (xrCreateSession(_XrInstance, &sessionCreateInfo, &_session)
684 != XR_SUCCESS) {
685 this->getLogger().error() << "Failed to create OpenXR session.";
686 return;
687 }
688 this->getLogger().info() << "Successfully created OpenXR session";
689}
690
691std::vector<const char *>
692 evan::XrDeviceBackend::getRequiredInstanceExtensions() const
693{
694 auto availableExtensions = getInstanceExtensions();
695 std::vector<const char *> requiredExtensions;
696
697 for (const auto &ext: availableExtensions) {
698 if (std::strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)
699 == 0) {
700 requiredExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
701 } else if (std::strcmp(ext.extensionName,
702 VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME)
703 == 0) {
704 requiredExtensions.push_back(
705 VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME);
706 }
707 }
708 return requiredExtensions;
709}
710
711std::vector<const char *>
712 evan::XrDeviceBackend::getRequiredInstanceExtensionsAndroid()
713{
714 std::vector<const char *> availableLayers;
715
716 for (const auto &layer: this->getAvailableLayers()) {
717 if (std::strcmp(layer.layerName, "VK_LAYER_KHRONOS_validation") == 0) {
718 availableLayers.emplace_back("VK_LAYER_KHRONOS_validation");
719 }
720 }
721 return availableLayers;
722}
Represents the context for managing the swapchain in the rendering system.
ASwapchainImage is a class that represents an image in the swapchain of the Evan engine....
Abstract interface for platform-specific functionality.
Definition IPlatform.hpp:36
OpenXR platform implementation.
static XrPath stringToPath(XrInstance instance, const std::string &pathString)
Converts a string to an OpenXR path.
Represents a software version using major, minor, and patch numbers.
Definition Version.hpp:35
void createLogicalDevice() override
Creates a logical device for the OpenXR session.
std::vector< int64_t > enumerateSwapchainFormats(uint32_t swapchainFormatCount) const override
Enumerates the available swapchain formats for the Vulkan device.
uint32_t countSwapchainFormats() const override
Count the number of available swapchain formats for the Vulkan device.
std::array< XrPath, _handCount > _handActionSubactionPath
std::vector< VkExtensionProperties > getInstanceExtensions() const
void createVisualizedSpace()
Creates a visualized space for the XR session.
std::vector< std::shared_ptr< utility::event::Event > > pollActions()
Polls input actions for the OpenXR session.
Error postprocessFrame(ASwapchainContext &swapchainContext) override
Postprocesses a frame and submits it to the OpenXR compositor.
std::vector< XrViewConfigurationType > enumerateViewConfigurationTypes() const
Enumerates the primary view configuration types supported by the OpenXR system.
void createInstance(const IPlatform &platform, const std::string &appName, Version &appVersion) override
Creates an OpenXR instance with the specified application name and version.
QueueFamilyIndices findQueueFamilies() override
Finds the queue family indices for graphics and presentation operations.
Error processFrame(VkPresentInfoKHR presentInfo, ASwapchainImage &swapchainImage) override
Processes a frame by releasing the OpenXR swapchain image.
static XrViewConfigurationType selectViewConfigurationType(const std::vector< XrViewConfigurationType > &configurations)
Selects a primary view configuration type from the ones supported by the runtime.
Error preprocessFrame(ASwapchainContext &swapchainContext) override
Prepares the current frame for rendering in an OpenXR session.
std::unique_ptr< XrManageActions > _actionManager
The action manager for handling input actions in the OpenXR session.
std::vector< XrViewConfigurationView > enumerateViewConfigurations() const
Enumerates the available view configurations for the OpenXR system.
XrDeviceBackend(const IPlatform &platform)
Constructs an XrDeviceBackend instance with the specified platform.
void pickPhysicalDevice() override
Picks a physical device that is compatible with the OpenXR session.
The XrSwapchainContext class manages the swapchain context for an OpenXR application using Vulkan....
A structure to represent Vulkan queue family indices.
Small result wrapper used by helpers that must return both a status and a value (e....
Definition Error.hpp:89