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

View file

@ -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 .
*/

View file

@ -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 <jakob@collabora.com>
* @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 <xrt/xrt_handles.h>
#include <xrt/xrt_config_os.h>
#include "main/comp_swapchain.h"
#include <stdio.h>
#include <stdlib.h>
@ -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);
}
}

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