comp: Delay swapchain destruction until a safe time, like end frame.

This commit is contained in:
Jakob Bornecrantz 2020-04-15 17:37:34 +01:00
parent 061dbefbd0
commit c8b4a00482
4 changed files with 73 additions and 8 deletions
doc/changes/compositor
src/xrt/compositor/main

View file

@ -0,0 +1 @@
main: Delay the destruction of swapchains until a time where it is safe, this allows swapchains to be destroyed from other threads.

View file

@ -73,6 +73,9 @@ compositor_destroy(struct xrt_compositor *xc)
COMP_DEBUG(c, "DESTROY"); COMP_DEBUG(c, "DESTROY");
// Make sure we don't have anything to destroy.
comp_compositor_garbage_collect(c);
if (c->r) { if (c->r) {
comp_renderer_destroy(c->r); comp_renderer_destroy(c->r);
c->r = NULL; c->r = NULL;
@ -105,6 +108,8 @@ compositor_destroy(struct xrt_compositor *xc)
free(c->compositor_frame_times.debug_var); free(c->compositor_frame_times.debug_var);
} }
u_threading_stack_fini(&c->threading.destroy_swapchains);
free(c); free(c);
} }
@ -305,6 +310,9 @@ compositor_end_frame(struct xrt_compositor *xc,
//! @todo do a time-weighted average or something. //! @todo do a time-weighted average or something.
c->expected_app_duration_ns = c->expected_app_duration_ns =
c->app_profiling.last_end - c->app_profiling.last_begin; c->app_profiling.last_end - c->app_profiling.last_begin;
// Now is a good point to garbage collect.
comp_compositor_garbage_collect(c);
} }
@ -806,6 +814,8 @@ xrt_gfx_provider_create_fd(struct xrt_device *xdev, bool flip_y)
c->base.base.destroy = compositor_destroy; c->base.base.destroy = compositor_destroy;
c->xdev = xdev; c->xdev = xdev;
u_threading_stack_init(&c->threading.destroy_swapchains);
COMP_DEBUG(c, "Doing init %p", (void *)c); COMP_DEBUG(c, "Doing init %p", (void *)c);
// Init the settings to default. // Init the settings to default.
@ -868,3 +878,13 @@ xrt_gfx_provider_create_fd(struct xrt_device *xdev, bool flip_y)
return &c->base; return &c->base;
} }
void
comp_compositor_garbage_collect(struct comp_compositor *c)
{
struct comp_swapchain *sc;
while ((sc = u_threading_stack_pop(&c->threading.destroy_swapchains))) {
comp_swapchain_really_destroy(sc);
}
}

View file

@ -10,11 +10,14 @@
#pragma once #pragma once
#include "xrt/xrt_gfx_vk.h"
#include "util/u_threading.h"
#include "main/comp_settings.h" #include "main/comp_settings.h"
#include "main/comp_window.h" #include "main/comp_window.h"
#include "main/comp_renderer.h" #include "main/comp_renderer.h"
#include "xrt/xrt_gfx_vk.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -143,6 +146,12 @@ struct comp_compositor
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
} current; } current;
struct
{
//! Thread object for safely destroying swapchain.
struct u_threading_stack destroy_swapchains;
} threading;
}; };
@ -174,6 +183,15 @@ comp_compositor(struct xrt_compositor *xc)
return (struct comp_compositor *)xc; return (struct comp_compositor *)xc;
} }
/*!
* Do garbage collection, destroying any resources that has been scheduled for
* destruction from other threads.
*
* @ingroup comp_main
*/
void
comp_compositor_garbage_collect(struct comp_compositor *c);
/*! /*!
* A compositor function that is implemented in the swapchain code. * A compositor function that is implemented in the swapchain code.
* *
@ -191,6 +209,16 @@ comp_swapchain_create(struct xrt_compositor *xc,
uint32_t array_size, uint32_t array_size,
uint32_t mip_count); uint32_t mip_count);
/*!
* Swapchain destruct is delayed until it is safe to destroy them, this function
* does the actual destruction and is called from @ref
* comp_compositor_garbage_collect.
*
* @ingroup comp_main
*/
void
comp_swapchain_really_destroy(struct comp_swapchain *sc);
/*! /*!
* Free and destroy any initialized fields on the given image, safe to pass in * Free and destroy any initialized fields on the given image, safe to pass in
* images that has one or all fields set to NULL. * images that has one or all fields set to NULL.

View file

@ -19,16 +19,10 @@ static void
swapchain_destroy(struct xrt_swapchain *xsc) swapchain_destroy(struct xrt_swapchain *xsc)
{ {
struct comp_swapchain *sc = comp_swapchain(xsc); struct comp_swapchain *sc = comp_swapchain(xsc);
struct vk_bundle *vk = &sc->c->vk;
COMP_SPEW(sc->c, "DESTROY"); COMP_SPEW(sc->c, "DESTROY");
for (uint32_t i = 0; i < sc->base.base.num_images; i++) { u_threading_stack_push(&sc->c->threading.destroy_swapchains, sc);
comp_swapchain_image_cleanup(vk, sc->base.base.array_size,
&sc->images[i]);
}
free(sc);
} }
static bool static bool
@ -205,6 +199,13 @@ err_image:
return ret; return ret;
} }
/*
*
* Exported functions.
*
*/
struct xrt_swapchain * struct xrt_swapchain *
comp_swapchain_create(struct xrt_compositor *xc, comp_swapchain_create(struct xrt_compositor *xc,
enum xrt_swapchain_create_flags create, enum xrt_swapchain_create_flags create,
@ -334,3 +335,18 @@ comp_swapchain_image_cleanup(struct vk_bundle *vk,
image->memory = VK_NULL_HANDLE; image->memory = VK_NULL_HANDLE;
} }
} }
void
comp_swapchain_really_destroy(struct comp_swapchain *sc)
{
struct vk_bundle *vk = &sc->c->vk;
COMP_SPEW(sc->c, "REALLY DESTROY");
for (uint32_t i = 0; i < sc->base.base.num_images; i++) {
comp_swapchain_image_cleanup(vk, sc->base.base.array_size,
&sc->images[i]);
}
free(sc);
}