The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

st/oxr: Refactor swapchains to use explicit transitions

+296 -89
+1 -18
src/xrt/state_trackers/oxr/oxr_objects.h
··· 803 803 return XRT_CAST_PTR_TO_OXR_HANDLE(XrSwapchain, sc); 804 804 } 805 805 806 - /*! 807 - * Shared create function for swapchains, called by grahpics API specific 808 - * implementations list below. Does most init, but not @ref xrt_swapchain 809 - * allocation and other API specific things. 810 - * 811 - * @param log Logger set with the current OpenXR function call context. 812 - * @param sess OpenXR session 813 - * @param createInfo Creation info. 814 - * @param sc Swapchain. 815 - * @param[out] out_swapchain Return of the allocated swapchain. 816 - */ 817 - XrResult 818 - oxr_swapchain_common_create(struct oxr_logger *log, 819 - struct oxr_session *sess, 820 - const XrSwapchainCreateInfo *createInfo, 821 - struct oxr_swapchain **out_swapchain); 822 - 823 806 824 807 /* 825 808 * ··· 2000 1983 { 2001 1984 bool yes; 2002 1985 int index; 2003 - } waited; 1986 + } inflight; // This is the image that the app is working on. 2004 1987 2005 1988 struct 2006 1989 {
+122 -71
src/xrt/state_trackers/oxr/oxr_swapchain.c
··· 13 13 #include "oxr_objects.h" 14 14 #include "oxr_logger.h" 15 15 #include "oxr_handle.h" 16 + #include "oxr_swapchain_common.h" 16 17 #include "oxr_xret.h" 17 18 18 19 ··· 83 84 struct oxr_swapchain *sc, 84 85 const XrSwapchainImageAcquireInfo *acquireInfo, 85 86 uint32_t *out_index) 87 + { 88 + CHECK_OXR_RET(oxr_swapchain_common_acquire(log, sc, out_index)); 89 + 90 + return oxr_session_success_result(sc->sess); 91 + } 92 + 93 + static XrResult 94 + implicit_wait_image(struct oxr_logger *log, struct oxr_swapchain *sc, const XrSwapchainImageWaitInfo *waitInfo) 95 + { 96 + struct xrt_swapchain *xsc = (struct xrt_swapchain *)sc->swapchain; 97 + xrt_result_t xret; 98 + 99 + CHECK_OXR_RET(oxr_swapchain_verify_wait_state(log, sc)); 100 + CHECK_OXR_RET(oxr_swapchain_common_wait(log, sc, waitInfo->timeout)); 101 + 102 + // Check and grab the index. 103 + if (sc->inflight.index < 0) { 104 + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "Invalid state: sc->inflight.index < 0"); 105 + } 106 + uint32_t index = (uint32_t)sc->inflight.index; 107 + 108 + // Okay to transition here for all APIs except Vulkan, who has it's own implementation of this function. 109 + xret = xrt_swapchain_barrier_image(xsc, XRT_BARRIER_TO_COMP, index); 110 + OXR_CHECK_XRET(log, sc->sess, xret, xrt_swapchain_barrier_image); 111 + 112 + return oxr_session_success_result(sc->sess); 113 + } 114 + 115 + static XrResult 116 + implicit_release_image(struct oxr_logger *log, struct oxr_swapchain *sc, const XrSwapchainImageReleaseInfo *releaseInfo) 117 + { 118 + struct xrt_swapchain *xsc = (struct xrt_swapchain *)sc->swapchain; 119 + xrt_result_t xret; 120 + 121 + // Error checking. 122 + if (!sc->inflight.yes) { 123 + return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "No swapchain images waited on"); 124 + } 125 + 126 + // Check and grab the index. 127 + if (sc->inflight.index < 0) { 128 + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "Invalid state: sc->inflight.index < 0"); 129 + } 130 + uint32_t index = (uint32_t)sc->inflight.index; 131 + 132 + if (sc->images[index].state != OXR_IMAGE_STATE_WAITED) { 133 + return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "No swapchain images waited on"); 134 + } 135 + 136 + // Need to do a automatic transition here. 137 + xret = xrt_swapchain_barrier_image(xsc, XRT_BARRIER_TO_COMP, index); 138 + OXR_CHECK_XRET(log, sc->sess, xret, xrt_swapchain_barrier_image); 139 + 140 + CHECK_OXR_RET(oxr_swapchain_common_release(log, sc)); 141 + 142 + return oxr_session_success_result(sc->sess); 143 + } 144 + 145 + static XrResult 146 + destroy(struct oxr_logger *log, struct oxr_swapchain *sc) 147 + { 148 + // It is not safe to do transitions here for some Graphics APIs, and 149 + // the ipc layer has to be robust enough to handle a disconnect. 150 + 151 + // Drop our reference, does NULL checking. 152 + xrt_swapchain_reference(&sc->swapchain, NULL); 153 + 154 + return XR_SUCCESS; 155 + } 156 + 157 + 158 + /* 159 + * 160 + * Handle function. 161 + * 162 + */ 163 + 164 + static XrResult 165 + destroy_handle(struct oxr_logger *log, struct oxr_handle_base *hb) 166 + { 167 + struct oxr_swapchain *sc = (struct oxr_swapchain *)hb; 168 + 169 + XrResult ret = sc->destroy(log, sc); 170 + free(sc); 171 + return ret; 172 + } 173 + 174 + 175 + /* 176 + * 177 + * 'Exported' functions. 178 + * 179 + */ 180 + 181 + XrResult 182 + oxr_swapchain_common_acquire(struct oxr_logger *log, struct oxr_swapchain *sc, uint32_t *out_index) 86 183 { 87 184 uint32_t index; 185 + 88 186 if (sc->acquired.num >= sc->swapchain->image_count) { 89 187 return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "All images have been acquired"); 90 188 } 91 189 92 - if (sc->is_static && (sc->released.yes || sc->waited.yes)) { 190 + if (sc->is_static && (sc->released.yes || sc->images[0].state != OXR_IMAGE_STATE_READY)) { 93 191 return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "Can only acquire once on a static swapchain"); 94 192 } 95 193 ··· 116 214 117 215 *out_index = index; 118 216 119 - return oxr_session_success_result(sc->sess); 217 + return XR_SUCCESS; 120 218 } 121 219 122 - static XrResult 123 - wait_image(struct oxr_logger *log, struct oxr_swapchain *sc, const XrSwapchainImageWaitInfo *waitInfo) 220 + XrResult 221 + oxr_swapchain_common_wait(struct oxr_logger *log, struct oxr_swapchain *sc, XrDuration timeout) 124 222 { 125 - if (sc->waited.yes) { 126 - return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "Swapchain has already been waited, call release"); 127 - } 128 - 129 - if (u_index_fifo_is_empty(&sc->acquired.fifo)) { 130 - return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "No image acquired"); 131 - } 132 - 133 223 uint32_t index; 134 224 u_index_fifo_pop(&sc->acquired.fifo, &index); 135 225 136 226 struct xrt_swapchain *xsc = (struct xrt_swapchain *)sc->swapchain; 137 227 138 - xrt_result_t xret = xrt_swapchain_wait_image(xsc, waitInfo->timeout, index); 228 + xrt_result_t xret = xrt_swapchain_wait_image(xsc, timeout, index); 139 229 OXR_CHECK_XRET(log, sc->sess, xret, xrt_swapchain_wait_image); 140 230 141 231 // The app can only wait on one image. 142 - sc->waited.yes = true; 143 - sc->waited.index = index; 232 + sc->inflight.yes = true; 233 + sc->inflight.index = index; 144 234 sc->images[index].state = OXR_IMAGE_STATE_WAITED; 145 235 146 - return oxr_session_success_result(sc->sess); 236 + return XR_SUCCESS; 147 237 } 148 238 149 - static XrResult 150 - release_image(struct oxr_logger *log, struct oxr_swapchain *sc, const XrSwapchainImageReleaseInfo *releaseInfo) 239 + XrResult 240 + oxr_swapchain_common_release(struct oxr_logger *log, struct oxr_swapchain *sc) 151 241 { 152 - if (!sc->waited.yes) { 153 - return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "No swapchain images waited on"); 242 + struct xrt_swapchain *xsc = (struct xrt_swapchain *)sc->swapchain; 243 + 244 + // Check and grab the index. 245 + if (sc->inflight.index < 0) { 246 + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "Invalid state: sc->inflight.index < 0"); 154 247 } 248 + uint32_t index = (uint32_t)sc->inflight.index; 155 249 156 - sc->waited.yes = false; 157 - uint32_t index = sc->waited.index; 250 + // Clear inflight. 251 + sc->inflight.yes = false; 252 + sc->inflight.index = -1; 158 253 159 - struct xrt_swapchain *xsc = (struct xrt_swapchain *)sc->swapchain; 160 254 xrt_result_t xret = xrt_swapchain_release_image(xsc, index); 161 255 OXR_CHECK_XRET(log, sc->sess, xret, xrt_swapchain_release_image); 162 256 ··· 168 262 sc->released.index = index; 169 263 sc->images[index].state = OXR_IMAGE_STATE_READY; 170 264 171 - return oxr_session_success_result(sc->sess); 172 - } 173 - 174 - static XrResult 175 - destroy(struct oxr_logger *log, struct oxr_swapchain *sc) 176 - { 177 - // Release any waited image. 178 - if (sc->waited.yes) { 179 - sc->release_image(log, sc, NULL); 180 - } 181 - 182 - // Release any acquired images. 183 - XrSwapchainImageWaitInfo waitInfo = {0}; 184 - while (!u_index_fifo_is_empty(&sc->acquired.fifo)) { 185 - sc->wait_image(log, sc, &waitInfo); 186 - sc->release_image(log, sc, NULL); 187 - } 188 - 189 - // Drop our reference, does NULL checking. 190 - xrt_swapchain_reference(&sc->swapchain, NULL); 191 - 192 265 return XR_SUCCESS; 193 266 } 194 267 195 - 196 - /* 197 - * 198 - * Handle function. 199 - * 200 - */ 201 - 202 - static XrResult 203 - destroy_handle(struct oxr_logger *log, struct oxr_handle_base *hb) 204 - { 205 - struct oxr_swapchain *sc = (struct oxr_swapchain *)hb; 206 - 207 - XrResult ret = sc->destroy(log, sc); 208 - free(sc); 209 - return ret; 210 - } 211 - 212 - 213 - /* 214 - * 215 - * 'Exported' functions. 216 - * 217 - */ 218 - 219 268 XrResult 220 269 oxr_swapchain_common_create(struct oxr_logger *log, 221 270 struct oxr_session *sess, ··· 259 308 sc->height = createInfo->height; 260 309 sc->array_layer_count = createInfo->arraySize; 261 310 sc->face_count = createInfo->faceCount; 311 + sc->is_static = (createInfo->createFlags & XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT) != 0; 312 + 313 + // Functions. 314 + sc->wait_image = implicit_wait_image; 315 + sc->release_image = implicit_release_image; 262 316 sc->acquire_image = acquire_image; 263 - sc->wait_image = wait_image; 264 - sc->release_image = release_image; 265 317 sc->destroy = destroy; 266 - sc->is_static = (createInfo->createFlags & XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT) != 0; 267 318 268 319 *out_swapchain = sc; 269 320
+102
src/xrt/state_trackers/oxr/oxr_swapchain_common.h
··· 1 + // Copyright 2019-2023, Collabora, Ltd. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Helper functions for @ref oxr_swapchain functions. 6 + * @author Jakob Bornecrantz <jakob@collabora.com> 7 + * @ingroup oxr_main 8 + * @ingroup comp_client 9 + */ 10 + 11 + #pragma once 12 + 13 + #include "oxr_objects.h" 14 + 15 + 16 + /* 17 + * 18 + * Helper defines. 19 + * 20 + */ 21 + 22 + #define CHECK_OXR_RET(THING) \ 23 + do { \ 24 + XrResult check_ret = (THING); \ 25 + if (check_ret != XR_SUCCESS) { \ 26 + return check_ret; \ 27 + } \ 28 + } while (false) 29 + 30 + 31 + /* 32 + * 33 + * Verify functions. 34 + * 35 + */ 36 + 37 + static inline XrResult 38 + oxr_swapchain_verify_wait_state(struct oxr_logger *log, struct oxr_swapchain *sc) 39 + { 40 + if (sc->inflight.yes) { 41 + return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "Swapchain has already been waited, call release"); 42 + } 43 + 44 + if (u_index_fifo_is_empty(&sc->acquired.fifo)) { 45 + return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID, "No image acquired"); 46 + } 47 + 48 + return XR_SUCCESS; 49 + } 50 + 51 + 52 + /* 53 + * 54 + * Common shared functions. 55 + * 56 + */ 57 + 58 + /*! 59 + * The shared code of the acquire call used by all graphics APIs. 60 + * 61 + * @param log Logger set with the current OpenXR function call context. 62 + * @param sc Swapchain. 63 + * @param[out] out_index Return of the acquired index. 64 + */ 65 + XrResult 66 + oxr_swapchain_common_acquire(struct oxr_logger *log, struct oxr_swapchain *sc, uint32_t *out_index); 67 + 68 + /*! 69 + * The shared code of the wait call used by all graphics APIs. 70 + * 71 + * @param log Logger set with the current OpenXR function call context. 72 + * @param sc Swapchain. 73 + * @param timeout Return of the acquired index. 74 + */ 75 + XrResult 76 + oxr_swapchain_common_wait(struct oxr_logger *log, struct oxr_swapchain *sc, XrDuration timeout); 77 + 78 + /*! 79 + * The shared code of the release call used by all graphics APIs. 80 + * 81 + * @param log Logger set with the current OpenXR function call context. 82 + * @param sc Swapchain. 83 + */ 84 + XrResult 85 + oxr_swapchain_common_release(struct oxr_logger *log, struct oxr_swapchain *sc); 86 + 87 + /*! 88 + * Shared create function for swapchains, called by grahpics API specific 89 + * implementations list below. Does most init, but not @ref xrt_swapchain 90 + * allocation and other API specific things. 91 + * 92 + * @param log Logger set with the current OpenXR function call context. 93 + * @param sess OpenXR session 94 + * @param createInfo Creation info. 95 + * @param sc Swapchain. 96 + * @param[out] out_swapchain Return of the allocated swapchain. 97 + */ 98 + XrResult 99 + oxr_swapchain_common_create(struct oxr_logger *log, 100 + struct oxr_session *sess, 101 + const XrSwapchainCreateInfo *createInfo, 102 + struct oxr_swapchain **out_swapchain);
+1
src/xrt/state_trackers/oxr/oxr_swapchain_d3d11.c
··· 16 16 17 17 #include "oxr_objects.h" 18 18 #include "oxr_logger.h" 19 + #include "oxr_swapchain_common.h" 19 20 20 21 21 22 static XrResult
+1
src/xrt/state_trackers/oxr/oxr_swapchain_d3d12.c
··· 17 17 #include "oxr_objects.h" 18 18 #include "oxr_logger.h" 19 19 #include "oxr_api_verify.h" 20 + #include "oxr_swapchain_common.h" 20 21 21 22 22 23 static XrResult
+1
src/xrt/state_trackers/oxr/oxr_swapchain_gl.c
··· 12 12 13 13 #include "oxr_objects.h" 14 14 #include "oxr_logger.h" 15 + #include "oxr_swapchain_common.h" 15 16 16 17 #include <assert.h> 17 18 #include <stdlib.h>
+68
src/xrt/state_trackers/oxr/oxr_swapchain_vk.c
··· 12 12 13 13 #include "oxr_objects.h" 14 14 #include "oxr_logger.h" 15 + #include "oxr_swapchain_common.h" 16 + #include "oxr_xret.h" 17 + 18 + #define WAIT_IN_ACQUIRE (true) 15 19 16 20 17 21 static XrResult 22 + vk_implicit_acquire_image(struct oxr_logger *log, 23 + struct oxr_swapchain *sc, 24 + const XrSwapchainImageAcquireInfo *acquireInfo, 25 + uint32_t *out_index) 26 + { 27 + struct xrt_swapchain *xsc = (struct xrt_swapchain *)sc->swapchain; 28 + xrt_result_t xret; 29 + 30 + uint32_t index; 31 + CHECK_OXR_RET(oxr_swapchain_common_acquire(log, sc, &index)); 32 + 33 + /* 34 + * We have to wait here in order to be fully conformat to the Vulkan 35 + * spec, it stats that the compositor has to have completed the GPU 36 + * commands to transfer the image to an external queue in order for us 37 + * to be able to insert our transition. 38 + */ 39 + if (WAIT_IN_ACQUIRE) { 40 + xret = xrt_swapchain_wait_image(xsc, 0, index); 41 + OXR_CHECK_XRET(log, sc->sess, xret, xrt_swapchain_wait_image); 42 + } 43 + 44 + /* 45 + * The non-explicit transition versions of XR_vulkan_enable[_2] states 46 + * that we can only use the queue in xrAcquireSwapchainImage so must be 47 + * done here. 48 + */ 49 + xret = xrt_swapchain_barrier_image(xsc, XRT_BARRIER_TO_APP, index); 50 + OXR_CHECK_XRET(log, sc->sess, xret, xrt_swapchain_barrier_image); 51 + 52 + *out_index = index; 53 + 54 + return oxr_session_success_result(sc->sess); 55 + } 56 + 57 + static XrResult 58 + vk_implicit_wait_image(struct oxr_logger *log, struct oxr_swapchain *sc, const XrSwapchainImageWaitInfo *waitInfo) 59 + { 60 + CHECK_OXR_RET(oxr_swapchain_verify_wait_state(log, sc)); 61 + 62 + uint32_t index; 63 + u_index_fifo_pop(&sc->acquired.fifo, &index); 64 + 65 + struct xrt_swapchain *xsc = (struct xrt_swapchain *)sc->swapchain; 66 + 67 + if (!WAIT_IN_ACQUIRE) { 68 + XrDuration timeout = waitInfo->timeout; 69 + 70 + // We have already waited in acquire. 71 + xrt_result_t xret = xrt_swapchain_wait_image(xsc, timeout, index); 72 + OXR_CHECK_XRET(log, sc->sess, xret, xrt_swapchain_wait_image); 73 + } 74 + 75 + // The app can only wait on one image. 76 + sc->inflight.yes = true; 77 + sc->inflight.index = index; 78 + sc->images[index].state = OXR_IMAGE_STATE_WAITED; 79 + 80 + return XR_SUCCESS; 81 + } 82 + 83 + static XrResult 18 84 vk_enumerate_images(struct oxr_logger *log, 19 85 struct oxr_swapchain *sc, 20 86 uint32_t count, ··· 46 112 47 113 // Set our API specific function(s). 48 114 sc->enumerate_images = vk_enumerate_images; 115 + sc->acquire_image = vk_implicit_acquire_image; 116 + sc->wait_image = vk_implicit_wait_image; 49 117 50 118 *out_swapchain = sc; 51 119