When graphics module is destroyed, stop XR session;

Terrible, but better.
This commit is contained in:
bjorn 2022-08-08 23:27:35 -07:00
parent 3c71828afa
commit 31d49fe8c6
3 changed files with 29 additions and 12 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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,