HoviTron Video Pipeline
SwapchainOpenXR.cpp
1/* ----------------------
2* Copyright 2023 Université Libre de Bruxelles(ULB), Universidad Politécnica de Madrid(UPM), CREAL, Deutsches Zentrum für Luft - und Raumfahrt(DLR)
3
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at < http://www.apache.org/licenses/LICENSE-2.0>
7
8* Unless required by applicable law or agreed to in writing, software
9* distributed under the License is distributed on an "AS IS" BASIS,
10* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11* See the License for the specific language governing permissionsand
12* limitations under the License.
13---------------------- */
14
15
16#include "SwapchainOpenXR.h"
19
20void SwapchainOpenXR::createSwapchainImageViews()
21{
22 int swapSize = swapChainImagesXr.size();
23
24 auto aspect = vk::ImageAspectFlagBits::eColor;
25 if (isDepth) {
26 aspect = vk::ImageAspectFlagBits::eDepth;
27 }
28 swapchainImageViews.resize(swapSize);
29 for (uint32_t i = 0; i < swapSize; i++) {
30 swapchainImageViews[i] = createImageView(wraps->context.device,
31 swapChainImagesXr[i].image,
33 aspect);
34
35 }
36
37}
38
39SwapchainOpenXR::SwapchainOpenXR(int64_t format, const XrViewConfigurationView& vp, WindowAbstract* window, VulkanWrapper* wrapper, XrSession* session)
40{
41 this->wraps = wrapper;
42 this->window = window;
43 switch(format) {
44 case VK_FORMAT_D16_UNORM:
45 case VK_FORMAT_D24_UNORM_S8_UINT:
46 case VK_FORMAT_D32_SFLOAT:
47 isDepth = true;
48 break;
49 default:
50 isDepth = false;
51 }
52
53 createSwapchain(vp,session, format);
54 createSwapchainImageViews();
55}
56
57std::tuple<uint32_t, std::optional<vk::Semaphore>> SwapchainOpenXR::acquireImage()
58{
59 XrSwapchainImageAcquireInfo acquireInfo{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO };
60
61 uint32_t swapchainImageIndex;
62 CHECK_XRCMD(xrAcquireSwapchainImage(xrswapchain.handle, &acquireInfo, &swapchainImageIndex));
63
64 XrSwapchainImageWaitInfo waitInfo{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO };
65 waitInfo.timeout = XR_INFINITE_DURATION;
66 CHECK_XRCMD(xrWaitSwapchainImage(xrswapchain.handle, &waitInfo));
67
68 currentImage = swapchainImageIndex;
69 std::optional<vk::Semaphore> sem;
70 return std::tuple<uint32_t, std::optional<vk::Semaphore>>(swapchainImageIndex,sem);
71}
72
73void SwapchainOpenXR::presentImage(uint32_t imageIndex, vk::Semaphore & renderingFinnished)
74{
75 throw std::runtime_error("Synchronization with Semaphore is not supported with openxr swapchains");
76}
77
78void SwapchainOpenXR::presentImage(uint32_t imageIndex, vk::Fence & fence)
79{
80 assert(fence != (vk::Fence) VK_NULL_HANDLE);
81
82
83 const uint32_t timeoutNs = 1 * 1000 * 1000 * 1000;
84 for (int i = 0; i < 5; ++i) {
85 auto res = wraps->context.device.waitForFences(1, &fence, VK_TRUE, timeoutNs);
86 if (res == vk::Result::eSuccess) {
87 // Buffer can be executed multiple times...
88 break;
89 }
90 PRINT("%s", "Waiting for CmdBuffer fence timed out, retrying...");
91 }
92
93 XrSwapchainImageReleaseInfo releaseInfo{ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO };
94 CHECK_XRCMD(xrReleaseSwapchainImage(xrswapchain.handle, &releaseInfo));
95}
96
98{
99 assert(elem < swapchainImageViews.size());
100 return swapchainImageViews[elem];
101}
102
104{
105 assert(index < swapChainImagesXr.size());
106 assert(index < xrSwapchainImagesBase.size());
107 return swapChainImagesXr[index].image;
108}
109
110/*
111const Swapchain SwapchainOpenXR::getSwapchainStruct()
112{
113 return xrswapchain;
114}*/
115
117{
118 xrDestroySwapchain(xrswapchain.handle);
119}
120
122{
123 assert(swapChainImagesXr.size() == xrSwapchainImagesBase.size());
124 return swapChainImagesXr.size();
125}
126
128{
129 return swapChainImagesXr[currentImage].image;
130}
131
132void SwapchainOpenXR::createSwapchain( const XrViewConfigurationView & vp, XrSession* xrSession, int64_t format) {
133 if (isDepth) {
134 D(PRINT("%s",
135 Fmt("Creating depth swapchain with dimensions Width=%d Height=%d SampleCount=%d",
136 vp.recommendedImageRectWidth, vp.recommendedImageRectHeight, vp.recommendedSwapchainSampleCount).c_str());)
137 }else {
138 D(PRINT("%s",
139 Fmt("Creating swapchain with dimensions Width=%d Height=%d SampleCount=%d",
140 vp.recommendedImageRectWidth, vp.recommendedImageRectHeight, vp.recommendedSwapchainSampleCount).c_str());)
141 }
142
143 // Create the swapchain.
144 XrSwapchainCreateInfo swapchainCreateInfo{ XR_TYPE_SWAPCHAIN_CREATE_INFO };
145 swapchainCreateInfo.arraySize = 1;
146 swapchainCreateInfo.format = format;
147 swapchainCreateInfo.width = vp.recommendedImageRectWidth;
148 swapchainCreateInfo.height = vp.recommendedImageRectHeight;
149 swapchainCreateInfo.mipCount = 1;
150 swapchainCreateInfo.faceCount = 1;
151 swapchainCreateInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
152 auto usages = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT | XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT ;
153 if (isDepth) {
154 usages |= XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
155 }
156 else {
157 usages |= XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT;
158 }
159 swapchainCreateInfo.usageFlags = usages;
160
161 //Swapchain swapchain;
162 xrswapchain.width = swapchainCreateInfo.width;
163 xrswapchain.height = swapchainCreateInfo.height;
164 swapchainExtent.width = swapchainCreateInfo.width;
165 swapchainExtent.height = swapchainCreateInfo.height;
166
167 CHECK_XRCMD(xrCreateSwapchain(*xrSession, &swapchainCreateInfo, &xrswapchain.handle));
168
169 //xrSwapchains.push_back(swapchain);
170 handle = xrswapchain.handle;
171
172 uint32_t imageCount;
173 CHECK_XRCMD(xrEnumerateSwapchainImages(xrswapchain.handle, 0, &imageCount, nullptr));
174
175 std::vector<XrSwapchainImageBaseHeader*> swapchainImages = initPresentation(imageCount, swapchainCreateInfo);
176
177 CHECK_XRCMD(xrEnumerateSwapchainImages(xrswapchain.handle, imageCount, &imageCount, swapchainImages[0]));
178
179 xrSwapchainImagesBase = swapchainImages;
180
181#ifndef NDEBUG
182 for (int i = 0; i < swapChainImagesXr.size(); i++) {
183 auto name = "image id i: " + std::to_string(i) ;
184 name += isDepth ? "depth" : "color";
185 vk::DebugUtilsObjectNameInfoEXT debug(vk::ObjectType::eImage, (uint64_t) static_cast<VkImage>(swapChainImagesXr[i].image), name.c_str());
186 wraps->context.device.setDebugUtilsObjectNameEXT(debug);
187 }
188#endif
189}
190
191std::vector<XrSwapchainImageBaseHeader*> SwapchainOpenXR::initPresentation(uint32_t count, XrSwapchainCreateInfo swapchainInfo) {
192 vk::Format format = static_cast<vk::Format>((VkFormat)swapchainInfo.format);
193
194
195 if (format == vk::Format::eR8G8B8A8Srgb) {
196 format = vk::Format::eR8G8B8A8Unorm;
197 }
198 if (format == vk::Format::eR8G8B8A8Unorm) {
199 //format = vk::Format::eR8G8B8A8UInt;
200 }
201
202 swapchainFormat = format;
203 swapchainExtent = vk::Extent2D(swapchainInfo.width, swapchainInfo.height);
204 //swapChainImagesXr.resize(viewNum + 1);
205 swapChainImagesXr.resize(count);
206
207 std::vector<XrSwapchainImageBaseHeader*> bases(count);
208 for (uint32_t i = 0; i < count; ++i) {
209 swapChainImagesXr[i] = { XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR };
210 bases[i] = reinterpret_cast<XrSwapchainImageBaseHeader*>(&swapChainImagesXr[i]);
211 }
212 return bases;
213}
File that contains the SwapchainOpenXR class.
Class that contains helper functions for Vulkan.
file that contains the VulkanWrapper class that manages the classes related to Vulkan code and ease t...
std::vector< vk::ImageView > swapchainImageViews
vk::Extent2D swapchainExtent
std::variant< vk::SwapchainKHR > handle
vk::Format swapchainFormat
VulkanWrapper * wraps
WindowAbstract * window
int getAttachmentSize() override
SwapchainOpenXR(int64_t format, const XrViewConfigurationView &vp, WindowAbstract *window, VulkanWrapper *wrapper, XrSession *session)
vk::ImageView getSwapchainImageView(int elem) override
std::tuple< uint32_t, std::optional< vk::Semaphore > > acquireImage() override
vk::Image getSwapchainImage(int index) override
vk::Image getCurrentImage() override
void presentImage(uint32_t imageIndex, vk::Semaphore &renderingFinnished) override
void cleanup() override
vk::Device device
Definition: VulkanContext.h:87
Class that manages the classes related to Vulkan code and act as a wrapper around them.
Definition: VulkanWrapper.h:66
VulkanContext context
Abstraction of the way of the result is displayed (screen or HMD).