diff --git a/src/xrt/compositor/main/comp_compositor.c b/src/xrt/compositor/main/comp_compositor.c index 76366ec8f..fa4e8ca07 100644 --- a/src/xrt/compositor/main/comp_compositor.c +++ b/src/xrt/compositor/main/comp_compositor.c @@ -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 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)); // Now is a good point to garbage collect. - comp_compositor_garbage_collect(c); + comp_swapchain_garbage_collect(&c->cscgc); return XRT_SUCCESS; } @@ -576,7 +598,7 @@ compositor_destroy(struct xrt_compositor *xc) COMP_DEBUG(c, "COMP_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); @@ -611,7 +633,7 @@ compositor_destroy(struct xrt_compositor *xc) os_precise_sleeper_deinit(&c->sleeper); - u_threading_stack_fini(&c->threading.destroy_swapchains); + u_threading_stack_fini(&c->cscgc.destroy_swapchains); 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); - c->base.base.create_swapchain = comp_swapchain_create; - c->base.base.import_swapchain = comp_swapchain_import; + c->base.base.create_swapchain = compositor_swapchain_create; + c->base.base.import_swapchain = compositor_swapchain_import; c->base.base.import_fence = comp_compositor_import_fence; c->base.base.begin_session = compositor_begin_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->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); @@ -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); } - -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); - } -} diff --git a/src/xrt/compositor/main/comp_compositor.h b/src/xrt/compositor/main/comp_compositor.h index 0f0076349..bc7b599e4 100644 --- a/src/xrt/compositor/main/comp_compositor.h +++ b/src/xrt/compositor/main/comp_compositor.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020, Collabora, Ltd. +// Copyright 2019-2021, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -20,6 +20,7 @@ #include "vk/vk_image_allocator.h" #include "main/comp_settings.h" +#include "main/comp_swapchain.h" #include "main/comp_window.h" #include "main/comp_renderer.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. * @@ -221,12 +175,7 @@ struct comp_compositor struct comp_frame rendering; } frame; - struct - { - //! Thread object for safely destroying swapchain. - struct u_threading_stack destroy_swapchains; - } threading; - + struct comp_swapchain_gc cscgc; struct { @@ -250,17 +199,6 @@ struct comp_compositor bool 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. * @@ -272,47 +210,6 @@ comp_compositor(struct xrt_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 . */ diff --git a/src/xrt/compositor/main/comp_swapchain.c b/src/xrt/compositor/main/comp_swapchain.c index 5d66109a2..8e977a472 100644 --- a/src/xrt/compositor/main/comp_swapchain.c +++ b/src/xrt/compositor/main/comp_swapchain.c @@ -2,18 +2,18 @@ // SPDX-License-Identifier: BSL-1.0 /*! * @file - * @brief Swapchain code for the main compositor. + * @brief Independent swapchain implementation. * @author Jakob Bornecrantz * @ingroup comp_main */ +#include "xrt/xrt_handles.h" +#include "xrt/xrt_config_os.h" + #include "util/u_misc.h" #include "util/u_handles.h" -#include "main/comp_compositor.h" - -#include -#include +#include "main/comp_swapchain.h" #include #include @@ -30,9 +30,9 @@ swapchain_destroy(struct xrt_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 @@ -40,7 +40,7 @@ swapchain_acquire_image(struct xrt_swapchain *xsc, uint32_t *out_index) { struct comp_swapchain *sc = comp_swapchain(xsc); - COMP_SPEW(sc->c, "ACQUIRE_IMAGE"); + VK_TRACE(sc->vk, "ACQUIRE_IMAGE"); // Returns negative on empty fifo. 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); - COMP_SPEW(sc->c, "WAIT_IMAGE"); + VK_TRACE(sc->vk, "WAIT_IMAGE"); return XRT_SUCCESS; } @@ -64,7 +64,7 @@ swapchain_release_image(struct xrt_swapchain *xsc, uint32_t index) { 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); @@ -89,7 +89,7 @@ swapchain_release_image(struct xrt_swapchain *xsc, uint32_t index) } 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); 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.release_image = swapchain_release_image; sc->base.base.num_images = num_images; - sc->c = c; + sc->vk = vk; + sc->gc = cscgc; // Make sure the handles are invalid. for (uint32_t i = 0; i < ARRAY_SIZE(sc->base.images); i++) { @@ -128,11 +129,10 @@ is_stencil_only_format(VkFormat format) } 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, struct comp_swapchain *sc) { - struct vk_bundle *vk = &c->vk; uint32_t num_images = sc->vkic.num_images; VkCommandBuffer cmd_buffer; @@ -271,29 +271,40 @@ image_cleanup(struct vk_bundle *vk, struct comp_swapchain_image *image) 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 -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, struct xrt_swapchain **out_xsc) { - struct comp_compositor *c = comp_compositor(xc); - struct vk_bundle *vk = &c->vk; uint32_t num_images = 3; VkResult ret; - if (!comp_is_format_supported(c, info->format)) { + if (!is_format_supported(vk, info->format)) { return XRT_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED; } if ((info->create & XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT) != 0) { - // This compositor doesn't support creating protected content - // swapchains. + // This compositor doesn't support creating protected content swapchains. return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED; } @@ -301,11 +312,11 @@ comp_swapchain_create(struct xrt_compositor *xc, 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, // - info->width, info->height, // - vk_color_format_string(info->format), info->format); + VK_DEBUG(vk, "CREATE %p %dx%d %s (%ld)", (void *)sc, // + info->width, info->height, // + vk_color_format_string(info->format), info->format); // Use the image helper to allocate the images. 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; } - do_post_create_vulkan_setup(c, info, sc); + do_post_create_vulkan_setup(vk, info, sc); // Correctly setup refcounts. xrt_swapchain_reference(out_xsc, &sc->base.base); @@ -339,19 +350,18 @@ comp_swapchain_create(struct xrt_compositor *xc, } 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, struct xrt_image_native *native_images, uint32_t num_images, struct xrt_swapchain **out_xsc) { - struct comp_compositor *c = comp_compositor(xc); - struct vk_bundle *vk = &c->vk; 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. 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; } - do_post_create_vulkan_setup(c, info, sc); + do_post_create_vulkan_setup(vk, info, sc); // Correctly setup refcounts. xrt_swapchain_reference(out_xsc, &sc->base.base); @@ -370,9 +380,9 @@ comp_swapchain_import(struct xrt_compositor *xc, void 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++) { image_cleanup(vk, &sc->images[i]); @@ -386,3 +396,13 @@ comp_swapchain_really_destroy(struct comp_swapchain *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); + } +} diff --git a/src/xrt/compositor/main/comp_swapchain.h b/src/xrt/compositor/main/comp_swapchain.h new file mode 100644 index 000000000..de602aa4f --- /dev/null +++ b/src/xrt/compositor/main/comp_swapchain.h @@ -0,0 +1,155 @@ +// Copyright 2019-2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Independent swapchain implementation. + * @author Jakob Bornecrantz + * @author Lubosz Sarnecki + * @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