From 31d49fe8c67446036cff7460e6f7e262de6ce530 Mon Sep 17 00:00:00 2001 From: bjorn Date: Mon, 8 Aug 2022 23:27:35 -0700 Subject: [PATCH] When graphics module is destroyed, stop XR session; Terrible, but better. --- src/modules/graphics/graphics.c | 8 +++++++ src/modules/headset/headset.h | 2 ++ src/modules/headset/headset_openxr.c | 31 +++++++++++++++++----------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/modules/graphics/graphics.c b/src/modules/graphics/graphics.c index 1c40ebde..2a32bcb3 100644 --- a/src/modules/graphics/graphics.c +++ b/src/modules/graphics/graphics.c @@ -640,6 +640,14 @@ bool lovrGraphicsInit(GraphicsConfig* config) { void lovrGraphicsDestroy() { if (!state.initialized) return; +#ifndef LOVR_DISABLE_HEADSET + // If there's an active headset session it needs to be stopped so it can clean up its Pass and + // swapchain textures before gpu_destroy is called. This is really hacky and should be solved + // with module-level refcounting in the future. + if (lovrHeadsetInterface && lovrHeadsetInterface->stop) { + lovrHeadsetInterface->stop(); + } +#endif for (Readback* readback = state.oldestReadback; readback; readback = readback->next) { lovrRelease(readback, lovrReadbackDestroy); } diff --git a/src/modules/headset/headset.h b/src/modules/headset/headset.h index 32741d0a..1bcdbdf8 100644 --- a/src/modules/headset/headset.h +++ b/src/modules/headset/headset.h @@ -112,6 +112,7 @@ typedef enum { // Notes: // - init is called immediately, the graphics module may not exist yet // - start is called after the graphics module is initialized, can be used to set up textures etc. +// - graphics module currently calls stop when it's destroyed, which is hacky and should be improved // - getDisplayFrequency may return 0.f if the information is unavailable. // - For isDown, changed can be set to false if change information is unavailable or inconvenient. // - getAxis may write 4 floats to the output value. The expected number is a constant (see axisCounts in l_headset). @@ -124,6 +125,7 @@ typedef struct HeadsetInterface { uint32_t (*createVulkanDevice)(void* instance, void* deviceCreateInfo, void* allocator, uintptr_t device, void* getInstanceProcAddr); bool (*init)(HeadsetConfig* config); void (*start)(void); + void (*stop)(void); void (*destroy)(void); bool (*getName)(char* name, size_t length); HeadsetOrigin (*getOriginType)(void); diff --git a/src/modules/headset/headset_openxr.c b/src/modules/headset/headset_openxr.c index a2e9618c..852639e8 100644 --- a/src/modules/headset/headset_openxr.c +++ b/src/modules/headset/headset_openxr.c @@ -1035,20 +1035,24 @@ static void openxr_start(void) { } } -static void openxr_destroy(void) { +static void openxr_stop(void) { + if (!state.session) { + return; + } + + lovrRelease(state.pass, lovrPassDestroy); + for (uint32_t i = 0; i < 2; i++) { for (uint32_t j = 0; j < state.textureCount[i]; j++) { lovrRelease(state.textures[i][j], lovrTextureDestroy); } } - lovrRelease(state.pass, lovrPassDestroy); + if (state.swapchain[COLOR]) xrDestroySwapchain(state.swapchain[COLOR]); + if (state.swapchain[DEPTH]) xrDestroySwapchain(state.swapchain[DEPTH]); - for (size_t i = 0; i < MAX_ACTIONS; i++) { - if (state.actions[i]) { - xrDestroyAction(state.actions[i]); - } - } + if (state.handTrackers[0]) xrDestroyHandTrackerEXT(state.handTrackers[0]); + if (state.handTrackers[1]) xrDestroyHandTrackerEXT(state.handTrackers[1]); for (size_t i = 0; i < MAX_DEVICES; i++) { if (state.spaces[i]) { @@ -1056,13 +1060,15 @@ static void openxr_destroy(void) { } } - if (state.handTrackers[0]) xrDestroyHandTrackerEXT(state.handTrackers[0]); - if (state.handTrackers[1]) xrDestroyHandTrackerEXT(state.handTrackers[1]); - if (state.actionSet) xrDestroyActionSet(state.actionSet); - if (state.swapchain[COLOR]) xrDestroySwapchain(state.swapchain[COLOR]); - if (state.swapchain[DEPTH]) xrDestroySwapchain(state.swapchain[DEPTH]); if (state.referenceSpace) xrDestroySpace(state.referenceSpace); if (state.session) xrDestroySession(state.session); + state.session = NULL; +} + +static void openxr_destroy(void) { + openxr_stop(); + + if (state.actionSet) xrDestroyActionSet(state.actionSet); if (state.instance) xrDestroyInstance(state.instance); memset(&state, 0, sizeof(state)); } @@ -1967,6 +1973,7 @@ HeadsetInterface lovrHeadsetOpenXRDriver = { .createVulkanDevice = openxr_createVulkanDevice, .init = openxr_init, .start = openxr_start, + .stop = openxr_stop, .destroy = openxr_destroy, .getName = openxr_getName, .getOriginType = openxr_getOriginType,