c/main: Refactor swapchain to be more independent

This commit is contained in:
Jakob Bornecrantz 2021-11-03 14:08:25 +00:00
parent 208690b115
commit 293d617dd5
4 changed files with 240 additions and 156 deletions

View file

@ -102,6 +102,28 @@ ts_ms()
* *
*/ */
static xrt_result_t
compositor_swapchain_create(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain **out_xsc)
{
struct comp_compositor *c = comp_compositor(xc);
return comp_swapchain_create(&c->vk, &c->cscgc, info, out_xsc);
}
static xrt_result_t
compositor_swapchain_import(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_image_native *native_images,
uint32_t num_images,
struct xrt_swapchain **out_xsc)
{
struct comp_compositor *c = comp_compositor(xc);
return comp_swapchain_import(&c->vk, &c->cscgc, info, native_images, num_images, out_xsc);
}
static xrt_result_t static xrt_result_t
compositor_begin_session(struct xrt_compositor *xc, enum xrt_view_type type) compositor_begin_session(struct xrt_compositor *xc, enum xrt_view_type type)
{ {
@ -526,7 +548,7 @@ compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id, xrt_graphic
COMP_SPEW(c, "LAYER_COMMIT finished drawing at %8.3fms", ns_to_ms(c->last_frame_time_ns)); COMP_SPEW(c, "LAYER_COMMIT finished drawing at %8.3fms", ns_to_ms(c->last_frame_time_ns));
// Now is a good point to garbage collect. // Now is a good point to garbage collect.
comp_compositor_garbage_collect(c); comp_swapchain_garbage_collect(&c->cscgc);
return XRT_SUCCESS; return XRT_SUCCESS;
} }
@ -576,7 +598,7 @@ compositor_destroy(struct xrt_compositor *xc)
COMP_DEBUG(c, "COMP_DESTROY"); COMP_DEBUG(c, "COMP_DESTROY");
// Make sure we don't have anything to destroy. // Make sure we don't have anything to destroy.
comp_compositor_garbage_collect(c); comp_swapchain_garbage_collect(&c->cscgc);
comp_renderer_destroy(&c->r); comp_renderer_destroy(&c->r);
@ -611,7 +633,7 @@ compositor_destroy(struct xrt_compositor *xc)
os_precise_sleeper_deinit(&c->sleeper); os_precise_sleeper_deinit(&c->sleeper);
u_threading_stack_fini(&c->threading.destroy_swapchains); u_threading_stack_fini(&c->cscgc.destroy_swapchains);
free(c); free(c);
} }
@ -1401,8 +1423,8 @@ xrt_gfx_provider_create_system(struct xrt_device *xdev, struct xrt_system_compos
{ {
struct comp_compositor *c = U_TYPED_CALLOC(struct comp_compositor); struct comp_compositor *c = U_TYPED_CALLOC(struct comp_compositor);
c->base.base.create_swapchain = comp_swapchain_create; c->base.base.create_swapchain = compositor_swapchain_create;
c->base.base.import_swapchain = comp_swapchain_import; c->base.base.import_swapchain = compositor_swapchain_import;
c->base.base.import_fence = comp_compositor_import_fence; c->base.base.import_fence = comp_compositor_import_fence;
c->base.base.begin_session = compositor_begin_session; c->base.base.begin_session = compositor_begin_session;
c->base.base.end_session = compositor_end_session; c->base.base.end_session = compositor_end_session;
@ -1426,7 +1448,7 @@ xrt_gfx_provider_create_system(struct xrt_device *xdev, struct xrt_system_compos
c->frame.rendering.id = -1; c->frame.rendering.id = -1;
c->xdev = xdev; c->xdev = xdev;
u_threading_stack_init(&c->threading.destroy_swapchains); u_threading_stack_init(&c->cscgc.destroy_swapchains);
COMP_DEBUG(c, "Doing init %p", (void *)c); COMP_DEBUG(c, "Doing init %p", (void *)c);
@ -1583,13 +1605,3 @@ xrt_gfx_provider_create_system(struct xrt_device *xdev, struct xrt_system_compos
return comp_multi_create_system_compositor(&c->base, sys_info, out_xsysc); return comp_multi_create_system_compositor(&c->base, sys_info, out_xsysc);
} }
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

@ -1,4 +1,4 @@
// Copyright 2019-2020, Collabora, Ltd. // Copyright 2019-2021, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
/*! /*!
* @file * @file
@ -20,6 +20,7 @@
#include "vk/vk_image_allocator.h" #include "vk/vk_image_allocator.h"
#include "main/comp_settings.h" #include "main/comp_settings.h"
#include "main/comp_swapchain.h"
#include "main/comp_window.h" #include "main/comp_window.h"
#include "main/comp_renderer.h" #include "main/comp_renderer.h"
#include "main/comp_target.h" #include "main/comp_target.h"
@ -40,53 +41,6 @@ extern "C" {
* *
*/ */
/*!
* A single swapchain image, holds the needed state for tracking image usage.
*
* @ingroup comp_main
* @see comp_swapchain
*/
struct comp_swapchain_image
{
//! Sampler used by the renderer and distortion code.
VkSampler sampler;
VkSampler repeat_sampler;
//! Views used by the renderer and distortion code, for each array
//! layer.
struct
{
VkImageView *alpha;
VkImageView *no_alpha;
} views;
//! The number of array slices in a texture, 1 == regular 2D texture.
size_t array_size;
};
/*!
* A swapchain that is almost a one to one mapping to a OpenXR swapchain.
*
* Not used by the window backend that uses the vk_swapchain to render to.
*
* @ingroup comp_main
* @implements xrt_swapchain_native
* @see comp_compositor
*/
struct comp_swapchain
{
struct xrt_swapchain_native base;
struct comp_compositor *c;
struct vk_image_collection vkic;
struct comp_swapchain_image images[XRT_MAX_SWAPCHAIN_IMAGES];
/*!
* This fifo is used to always give out the oldest image to acquire
* image, this should probably be made even smarter.
*/
struct u_index_fifo fifo;
};
/*! /*!
* A single layer. * A single layer.
* *
@ -221,12 +175,7 @@ struct comp_compositor
struct comp_frame rendering; struct comp_frame rendering;
} frame; } frame;
struct struct comp_swapchain_gc cscgc;
{
//! Thread object for safely destroying swapchain.
struct u_threading_stack destroy_swapchains;
} threading;
struct struct
{ {
@ -250,17 +199,6 @@ struct comp_compositor
bool bool
comp_is_format_supported(struct comp_compositor *c, VkFormat format); comp_is_format_supported(struct comp_compositor *c, VkFormat format);
/*!
* Convenience function to convert a xrt_swapchain to a comp_swapchain.
*
* @private @memberof comp_swapchain
*/
static inline struct comp_swapchain *
comp_swapchain(struct xrt_swapchain *xsc)
{
return (struct comp_swapchain *)xsc;
}
/*! /*!
* Convenience function to convert a xrt_compositor to a comp_compositor. * Convenience function to convert a xrt_compositor to a comp_compositor.
* *
@ -272,47 +210,6 @@ 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.
*
* @public @memberof comp_compositor
*/
void
comp_compositor_garbage_collect(struct comp_compositor *c);
/*!
* A compositor function that is implemented in the swapchain code.
*
* @public @memberof comp_compositor
*/
xrt_result_t
comp_swapchain_create(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain **out_xsc);
/*!
* A compositor function that is implemented in the swapchain code.
*
* @public @memberof comp_compositor
*/
xrt_result_t
comp_swapchain_import(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_image_native *native_images,
uint32_t num_images,
struct xrt_swapchain **out_xsc);
/*!
* 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.
*
* @private @memberof comp_swapchain
*/
void
comp_swapchain_really_destroy(struct comp_swapchain *sc);
/*! /*!
* For importing fences, defined in comp_sync.c . * For importing fences, defined in comp_sync.c .
*/ */

View file

@ -2,18 +2,18 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
/*! /*!
* @file * @file
* @brief Swapchain code for the main compositor. * @brief Independent swapchain implementation.
* @author Jakob Bornecrantz <jakob@collabora.com> * @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup comp_main * @ingroup comp_main
*/ */
#include "xrt/xrt_handles.h"
#include "xrt/xrt_config_os.h"
#include "util/u_misc.h" #include "util/u_misc.h"
#include "util/u_handles.h" #include "util/u_handles.h"
#include "main/comp_compositor.h" #include "main/comp_swapchain.h"
#include <xrt/xrt_handles.h>
#include <xrt/xrt_config_os.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -30,9 +30,9 @@ swapchain_destroy(struct xrt_swapchain *xsc)
{ {
struct comp_swapchain *sc = comp_swapchain(xsc); struct comp_swapchain *sc = comp_swapchain(xsc);
COMP_SPEW(sc->c, "DESTROY"); VK_TRACE(sc->vk, "DESTROY");
u_threading_stack_push(&sc->c->threading.destroy_swapchains, sc); u_threading_stack_push(&sc->gc->destroy_swapchains, sc);
} }
static xrt_result_t static xrt_result_t
@ -40,7 +40,7 @@ swapchain_acquire_image(struct xrt_swapchain *xsc, uint32_t *out_index)
{ {
struct comp_swapchain *sc = comp_swapchain(xsc); struct comp_swapchain *sc = comp_swapchain(xsc);
COMP_SPEW(sc->c, "ACQUIRE_IMAGE"); VK_TRACE(sc->vk, "ACQUIRE_IMAGE");
// Returns negative on empty fifo. // Returns negative on empty fifo.
int res = u_index_fifo_pop(&sc->fifo, out_index); int res = u_index_fifo_pop(&sc->fifo, out_index);
@ -55,7 +55,7 @@ swapchain_wait_image(struct xrt_swapchain *xsc, uint64_t timeout, uint32_t index
{ {
struct comp_swapchain *sc = comp_swapchain(xsc); struct comp_swapchain *sc = comp_swapchain(xsc);
COMP_SPEW(sc->c, "WAIT_IMAGE"); VK_TRACE(sc->vk, "WAIT_IMAGE");
return XRT_SUCCESS; return XRT_SUCCESS;
} }
@ -64,7 +64,7 @@ swapchain_release_image(struct xrt_swapchain *xsc, uint32_t index)
{ {
struct comp_swapchain *sc = comp_swapchain(xsc); struct comp_swapchain *sc = comp_swapchain(xsc);
COMP_SPEW(sc->c, "RELEASE_IMAGE"); VK_TRACE(sc->vk, "RELEASE_IMAGE");
int res = u_index_fifo_push(&sc->fifo, index); int res = u_index_fifo_push(&sc->fifo, index);
@ -89,7 +89,7 @@ swapchain_release_image(struct xrt_swapchain *xsc, uint32_t index)
} }
static struct comp_swapchain * static struct comp_swapchain *
alloc_and_set_funcs(struct comp_compositor *c, uint32_t num_images) alloc_and_set_funcs(struct vk_bundle *vk, struct comp_swapchain_gc *cscgc, uint32_t num_images)
{ {
struct comp_swapchain *sc = U_TYPED_CALLOC(struct comp_swapchain); struct comp_swapchain *sc = U_TYPED_CALLOC(struct comp_swapchain);
sc->base.base.destroy = swapchain_destroy; sc->base.base.destroy = swapchain_destroy;
@ -97,7 +97,8 @@ alloc_and_set_funcs(struct comp_compositor *c, uint32_t num_images)
sc->base.base.wait_image = swapchain_wait_image; sc->base.base.wait_image = swapchain_wait_image;
sc->base.base.release_image = swapchain_release_image; sc->base.base.release_image = swapchain_release_image;
sc->base.base.num_images = num_images; sc->base.base.num_images = num_images;
sc->c = c; sc->vk = vk;
sc->gc = cscgc;
// Make sure the handles are invalid. // Make sure the handles are invalid.
for (uint32_t i = 0; i < ARRAY_SIZE(sc->base.images); i++) { for (uint32_t i = 0; i < ARRAY_SIZE(sc->base.images); i++) {
@ -128,11 +129,10 @@ is_stencil_only_format(VkFormat format)
} }
static void static void
do_post_create_vulkan_setup(struct comp_compositor *c, do_post_create_vulkan_setup(struct vk_bundle *vk,
const struct xrt_swapchain_create_info *info, const struct xrt_swapchain_create_info *info,
struct comp_swapchain *sc) struct comp_swapchain *sc)
{ {
struct vk_bundle *vk = &c->vk;
uint32_t num_images = sc->vkic.num_images; uint32_t num_images = sc->vkic.num_images;
VkCommandBuffer cmd_buffer; VkCommandBuffer cmd_buffer;
@ -271,29 +271,40 @@ image_cleanup(struct vk_bundle *vk, struct comp_swapchain_image *image)
D(Sampler, image->repeat_sampler); D(Sampler, image->repeat_sampler);
} }
static bool
is_format_supported(struct vk_bundle *vk, VkFormat format)
{
VkFormatProperties prop;
vk->vkGetPhysicalDeviceFormatProperties(vk->physical_device, format, &prop);
// This is a fairly crude way of checking support,
// but works well enough.
return prop.optimalTilingFeatures != 0;
}
/* /*
* *
* Exported functions. * 'Exported' functions.
* *
*/ */
xrt_result_t xrt_result_t
comp_swapchain_create(struct xrt_compositor *xc, comp_swapchain_create(struct vk_bundle *vk,
struct comp_swapchain_gc *cscgc,
const struct xrt_swapchain_create_info *info, const struct xrt_swapchain_create_info *info,
struct xrt_swapchain **out_xsc) struct xrt_swapchain **out_xsc)
{ {
struct comp_compositor *c = comp_compositor(xc);
struct vk_bundle *vk = &c->vk;
uint32_t num_images = 3; uint32_t num_images = 3;
VkResult ret; VkResult ret;
if (!comp_is_format_supported(c, info->format)) { if (!is_format_supported(vk, info->format)) {
return XRT_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED; return XRT_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED;
} }
if ((info->create & XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT) != 0) { if ((info->create & XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT) != 0) {
// This compositor doesn't support creating protected content // This compositor doesn't support creating protected content swapchains.
// swapchains.
return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED; return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED;
} }
@ -301,11 +312,11 @@ comp_swapchain_create(struct xrt_compositor *xc,
num_images = 1; num_images = 1;
} }
struct comp_swapchain *sc = alloc_and_set_funcs(c, num_images); struct comp_swapchain *sc = alloc_and_set_funcs(vk, cscgc, num_images);
COMP_DEBUG(c, "CREATE %p %dx%d %s (%ld)", (void *)sc, // VK_DEBUG(vk, "CREATE %p %dx%d %s (%ld)", (void *)sc, //
info->width, info->height, // info->width, info->height, //
vk_color_format_string(info->format), info->format); vk_color_format_string(info->format), info->format);
// Use the image helper to allocate the images. // Use the image helper to allocate the images.
ret = vk_ic_allocate(vk, info, num_images, &sc->vkic); ret = vk_ic_allocate(vk, info, num_images, &sc->vkic);
@ -330,7 +341,7 @@ comp_swapchain_create(struct xrt_compositor *xc,
sc->base.images[i].use_dedicated_allocation = sc->vkic.images[i].use_dedicated_allocation; sc->base.images[i].use_dedicated_allocation = sc->vkic.images[i].use_dedicated_allocation;
} }
do_post_create_vulkan_setup(c, info, sc); do_post_create_vulkan_setup(vk, info, sc);
// Correctly setup refcounts. // Correctly setup refcounts.
xrt_swapchain_reference(out_xsc, &sc->base.base); xrt_swapchain_reference(out_xsc, &sc->base.base);
@ -339,19 +350,18 @@ comp_swapchain_create(struct xrt_compositor *xc,
} }
xrt_result_t xrt_result_t
comp_swapchain_import(struct xrt_compositor *xc, comp_swapchain_import(struct vk_bundle *vk,
struct comp_swapchain_gc *cscgc,
const struct xrt_swapchain_create_info *info, const struct xrt_swapchain_create_info *info,
struct xrt_image_native *native_images, struct xrt_image_native *native_images,
uint32_t num_images, uint32_t num_images,
struct xrt_swapchain **out_xsc) struct xrt_swapchain **out_xsc)
{ {
struct comp_compositor *c = comp_compositor(xc);
struct vk_bundle *vk = &c->vk;
VkResult ret; VkResult ret;
struct comp_swapchain *sc = alloc_and_set_funcs(c, num_images); struct comp_swapchain *sc = alloc_and_set_funcs(vk, cscgc, num_images);
COMP_DEBUG(c, "CREATE FROM NATIVE %p %dx%d", (void *)sc, info->width, info->height); VK_DEBUG(vk, "CREATE FROM NATIVE %p %dx%d", (void *)sc, info->width, info->height);
// Use the image helper to get the images. // Use the image helper to get the images.
ret = vk_ic_from_natives(vk, info, native_images, num_images, &sc->vkic); ret = vk_ic_from_natives(vk, info, native_images, num_images, &sc->vkic);
@ -359,7 +369,7 @@ comp_swapchain_import(struct xrt_compositor *xc,
return XRT_ERROR_VULKAN; return XRT_ERROR_VULKAN;
} }
do_post_create_vulkan_setup(c, info, sc); do_post_create_vulkan_setup(vk, info, sc);
// Correctly setup refcounts. // Correctly setup refcounts.
xrt_swapchain_reference(out_xsc, &sc->base.base); xrt_swapchain_reference(out_xsc, &sc->base.base);
@ -370,9 +380,9 @@ comp_swapchain_import(struct xrt_compositor *xc,
void void
comp_swapchain_really_destroy(struct comp_swapchain *sc) comp_swapchain_really_destroy(struct comp_swapchain *sc)
{ {
struct vk_bundle *vk = &sc->c->vk; struct vk_bundle *vk = sc->vk;
COMP_SPEW(sc->c, "REALLY DESTROY"); VK_TRACE(vk, "REALLY DESTROY");
for (uint32_t i = 0; i < sc->base.base.num_images; i++) { for (uint32_t i = 0; i < sc->base.base.num_images; i++) {
image_cleanup(vk, &sc->images[i]); image_cleanup(vk, &sc->images[i]);
@ -386,3 +396,13 @@ comp_swapchain_really_destroy(struct comp_swapchain *sc)
free(sc); free(sc);
} }
void
comp_swapchain_garbage_collect(struct comp_swapchain_gc *cscgc)
{
struct comp_swapchain *sc;
while ((sc = u_threading_stack_pop(&cscgc->destroy_swapchains))) {
comp_swapchain_really_destroy(sc);
}
}

View file

@ -0,0 +1,155 @@
// Copyright 2019-2021, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Independent swapchain implementation.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
* @ingroup comp_main
*/
#pragma once
#include "vk/vk_image_allocator.h"
#include "util/u_threading.h"
#include "util/u_index_fifo.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* A garbage collector that collects swapchains to be safely destroyed.
*/
struct comp_swapchain_gc
{
//! Thread object for safely destroying swapchain.
struct u_threading_stack destroy_swapchains;
};
/*!
* A single swapchain image, holds the needed state for tracking image usage.
*
* @ingroup comp_main
* @see comp_swapchain
*/
struct comp_swapchain_image
{
//! Sampler used by the renderer and distortion code.
VkSampler sampler;
VkSampler repeat_sampler;
//! Views used by the renderer and distortion code, for each array layer.
struct
{
VkImageView *alpha;
VkImageView *no_alpha;
} views;
//! The number of array slices in a texture, 1 == regular 2D texture.
size_t array_size;
};
/*!
* A swapchain that is almost a one to one mapping to a OpenXR swapchain.
*
* Not used by the window backend that uses the comp_target to render to.
*
* The vk_bundle is owned by the compositor, its the state trackers job to make
* sure that compositor lives for as long as the swapchain does and that all
* swapchains are destroyed before the compositor is destroyed.
*
* @ingroup comp_main
* @implements xrt_swapchain_native
* @see comp_compositor
*/
struct comp_swapchain
{
struct xrt_swapchain_native base;
struct vk_bundle *vk;
struct comp_swapchain_gc *gc;
struct vk_image_collection vkic;
struct comp_swapchain_image images[XRT_MAX_SWAPCHAIN_IMAGES];
/*!
* This fifo is used to always give out the oldest image to acquire
* image, this should probably be made even smarter.
*/
struct u_index_fifo fifo;
};
/*
*
* Helper functions.
*
*/
/*!
* Convenience function to convert a xrt_swapchain to a comp_swapchain.
*
* @private @memberof comp_swapchain
*/
static inline struct comp_swapchain *
comp_swapchain(struct xrt_swapchain *xsc)
{
return (struct comp_swapchain *)xsc;
}
/*
*
* 'Exported' functions.
*
*/
/*!
* Do garbage collection, destroying any resources that has been scheduled for
* destruction from other threads.
*
* @public @memberof comp_compositor
*/
void
comp_swapchain_garbage_collect(struct comp_swapchain_gc *cscgc);
/*!
* A compositor function that is implemented in the swapchain code.
*
* @public @memberof comp_compositor
*/
xrt_result_t
comp_swapchain_create(struct vk_bundle *vk,
struct comp_swapchain_gc *cscgc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain **out_xsc);
/*!
* A compositor function that is implemented in the swapchain code.
*
* @public @memberof comp_compositor
*/
xrt_result_t
comp_swapchain_import(struct vk_bundle *vk,
struct comp_swapchain_gc *cscgc,
const struct xrt_swapchain_create_info *info,
struct xrt_image_native *native_images,
uint32_t num_images,
struct xrt_swapchain **out_xsc);
/*!
* Swapchain destruct is delayed until it is safe to destroy them, this function
* does the actual destruction and is called from @ref
* comp_swapchain_garbage_collect.
*
* @private @memberof comp_swapchain
*/
void
comp_swapchain_really_destroy(struct comp_swapchain *sc);
#ifdef __cplusplus
}
#endif