mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2024-12-28 18:46:18 +00:00
c/main: Move ownership of present/render semaphores to comp_target
Co-authored-by: Jakob Bornecrantz <jakob@collabora.com>
This commit is contained in:
parent
3b7f95b39e
commit
109e373e0c
|
@ -43,6 +43,20 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Small internal helpers.
|
||||
*
|
||||
*/
|
||||
|
||||
#define CHAIN(STRUCT, NEXT) \
|
||||
do { \
|
||||
(STRUCT).pNext = NEXT; \
|
||||
NEXT = (VkBaseInStructure *)&(STRUCT); \
|
||||
} while (false)
|
||||
|
||||
|
||||
/*
|
||||
|
@ -85,12 +99,6 @@ struct comp_renderer
|
|||
|
||||
} mirror_to_debug_gui;
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
VkSemaphore present_complete;
|
||||
VkSemaphore render_complete;
|
||||
} semaphores;
|
||||
//! @}
|
||||
|
||||
//! @name Image-dependent members
|
||||
|
@ -146,27 +154,6 @@ renderer_wait_gpu_idle(struct comp_renderer *r)
|
|||
os_mutex_unlock(&vk->queue_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
renderer_init_semaphores(struct comp_renderer *r)
|
||||
{
|
||||
struct vk_bundle *vk = &r->c->base.vk;
|
||||
VkResult ret;
|
||||
|
||||
VkSemaphoreCreateInfo info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
};
|
||||
|
||||
ret = vk->vkCreateSemaphore(vk->device, &info, NULL, &r->semaphores.present_complete);
|
||||
if (ret != VK_SUCCESS) {
|
||||
COMP_ERROR(r->c, "vkCreateSemaphore: %s", vk_result_string(ret));
|
||||
}
|
||||
|
||||
ret = vk->vkCreateSemaphore(vk->device, &info, NULL, &r->semaphores.render_complete);
|
||||
if (ret != VK_SUCCESS) {
|
||||
COMP_ERROR(r->c, "vkCreateSemaphore: %s", vk_result_string(ret));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calc_viewport_data(struct comp_renderer *r,
|
||||
struct render_viewport_data *out_l_viewport_data,
|
||||
|
@ -568,12 +555,8 @@ renderer_create(struct comp_renderer *r, struct comp_compositor *c)
|
|||
|
||||
r->acquired_buffer = -1;
|
||||
r->fenced_buffer = -1;
|
||||
r->semaphores.present_complete = VK_NULL_HANDLE;
|
||||
r->semaphores.render_complete = VK_NULL_HANDLE;
|
||||
r->rtr_array = NULL;
|
||||
|
||||
renderer_init_semaphores(r);
|
||||
|
||||
// Try to early-allocate these, in case we can.
|
||||
renderer_ensure_images_and_renderings(r, false);
|
||||
|
||||
|
@ -631,9 +614,9 @@ renderer_submit_queue(struct comp_renderer *r, VkCommandBuffer cmd, VkPipelineSt
|
|||
VkResult ret;
|
||||
|
||||
|
||||
#define WAIT_SEMAPHORE_COUNT 1
|
||||
VkPipelineStageFlags stage_flags[WAIT_SEMAPHORE_COUNT] = {pipeline_stage_flag};
|
||||
VkSemaphore wait_semaphores[WAIT_SEMAPHORE_COUNT] = {r->semaphores.present_complete};
|
||||
/*
|
||||
* Wait for previous frame's work to complete.
|
||||
*/
|
||||
|
||||
// Wait for the last fence, if any.
|
||||
renderer_wait_for_last_fence(r);
|
||||
|
@ -645,15 +628,59 @@ renderer_submit_queue(struct comp_renderer *r, VkCommandBuffer cmd, VkPipelineSt
|
|||
COMP_ERROR(r->c, "vkResetFences: %s", vk_result_string(ret));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Regular semaphore setup.
|
||||
*/
|
||||
|
||||
struct comp_target *ct = r->c->target;
|
||||
#define WAIT_SEMAPHORE_COUNT 1
|
||||
|
||||
VkSemaphore wait_sems[WAIT_SEMAPHORE_COUNT] = {ct->semaphores.present_complete};
|
||||
VkPipelineStageFlags stage_flags[WAIT_SEMAPHORE_COUNT] = {pipeline_stage_flag};
|
||||
|
||||
VkSemaphore *wait_sems_ptr = NULL;
|
||||
VkPipelineStageFlags *stage_flags_ptr = NULL;
|
||||
uint32_t wait_sem_count = 0;
|
||||
if (wait_sems[0] != VK_NULL_HANDLE) {
|
||||
wait_sems_ptr = wait_sems;
|
||||
stage_flags_ptr = stage_flags;
|
||||
wait_sem_count = WAIT_SEMAPHORE_COUNT;
|
||||
}
|
||||
|
||||
// Next pointer for VkSubmitInfo
|
||||
const void *next = NULL;
|
||||
|
||||
#ifdef VK_KHR_timeline_semaphore
|
||||
assert(r->c->frame.rendering.id >= 0);
|
||||
uint64_t render_complete_signal_values[WAIT_SEMAPHORE_COUNT] = {(uint64_t)r->c->frame.rendering.id};
|
||||
|
||||
VkTimelineSemaphoreSubmitInfoKHR timeline_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,
|
||||
};
|
||||
|
||||
if (ct->semaphores.render_complete_is_timeline) {
|
||||
timeline_info = (VkTimelineSemaphoreSubmitInfoKHR){
|
||||
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,
|
||||
.signalSemaphoreValueCount = WAIT_SEMAPHORE_COUNT,
|
||||
.pSignalSemaphoreValues = render_complete_signal_values,
|
||||
};
|
||||
|
||||
CHAIN(timeline_info, next);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
VkSubmitInfo comp_submit_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.waitSemaphoreCount = WAIT_SEMAPHORE_COUNT,
|
||||
.pWaitSemaphores = wait_semaphores,
|
||||
.pWaitDstStageMask = stage_flags,
|
||||
.pNext = next,
|
||||
.pWaitDstStageMask = stage_flags_ptr,
|
||||
.pWaitSemaphores = wait_sems_ptr,
|
||||
.waitSemaphoreCount = wait_sem_count,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &r->semaphores.render_complete,
|
||||
.pSignalSemaphores = &ct->semaphores.render_complete,
|
||||
};
|
||||
|
||||
ret = vk_locked_submit(vk, vk->queue, 1, &comp_submit_info, r->fences[r->acquired_buffer]);
|
||||
|
@ -722,7 +749,7 @@ renderer_acquire_swapchain_image(struct comp_renderer *r)
|
|||
// Not ready yet.
|
||||
return;
|
||||
}
|
||||
ret = comp_target_acquire(r->c->target, r->semaphores.present_complete, &buffer_index);
|
||||
ret = comp_target_acquire(r->c->target, &buffer_index);
|
||||
|
||||
if ((ret == VK_ERROR_OUT_OF_DATE_KHR) || (ret == VK_SUBOPTIMAL_KHR)) {
|
||||
COMP_DEBUG(r->c, "Received %s.", vk_result_string(ret));
|
||||
|
@ -736,7 +763,7 @@ renderer_acquire_swapchain_image(struct comp_renderer *r)
|
|||
}
|
||||
|
||||
/* Acquire image again to silence validation error */
|
||||
ret = comp_target_acquire(r->c->target, r->semaphores.present_complete, &buffer_index);
|
||||
ret = comp_target_acquire(r->c->target, &buffer_index);
|
||||
if (ret != VK_SUCCESS) {
|
||||
COMP_ERROR(r->c, "comp_target_acquire: %s", vk_result_string(ret));
|
||||
}
|
||||
|
@ -767,13 +794,16 @@ renderer_present_swapchain_image(struct comp_renderer *r, uint64_t desired_prese
|
|||
|
||||
VkResult ret;
|
||||
|
||||
ret = comp_target_present( //
|
||||
r->c->target, //
|
||||
r->c->base.vk.queue, //
|
||||
r->acquired_buffer, //
|
||||
r->semaphores.render_complete, //
|
||||
desired_present_time_ns, //
|
||||
present_slop_ns); //
|
||||
assert(r->c->frame.rendering.id >= 0);
|
||||
uint64_t render_complete_signal_value = (uint64_t)r->c->frame.rendering.id;
|
||||
|
||||
ret = comp_target_present( //
|
||||
r->c->target, //
|
||||
r->c->base.vk.queue, //
|
||||
r->acquired_buffer, //
|
||||
render_complete_signal_value, //
|
||||
desired_present_time_ns, //
|
||||
present_slop_ns); //
|
||||
r->acquired_buffer = -1;
|
||||
|
||||
if (ret == VK_ERROR_OUT_OF_DATE_KHR || ret == VK_SUBOPTIMAL_KHR) {
|
||||
|
@ -798,16 +828,6 @@ renderer_destroy(struct comp_renderer *r)
|
|||
// Command buffers
|
||||
renderer_close_renderings_and_fences(r);
|
||||
|
||||
// Semaphores
|
||||
if (r->semaphores.present_complete != VK_NULL_HANDLE) {
|
||||
vk->vkDestroySemaphore(vk->device, r->semaphores.present_complete, NULL);
|
||||
r->semaphores.present_complete = VK_NULL_HANDLE;
|
||||
}
|
||||
if (r->semaphores.render_complete != VK_NULL_HANDLE) {
|
||||
vk->vkDestroySemaphore(vk->device, r->semaphores.render_complete, NULL);
|
||||
r->semaphores.render_complete = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
comp_layer_renderer_destroy(&(r->lr));
|
||||
|
||||
u_var_remove_root(r);
|
||||
|
|
|
@ -86,6 +86,17 @@ struct comp_target
|
|||
//! Transformation of the current surface, required for pre-rotation
|
||||
VkSurfaceTransformFlagBitsKHR surface_transform;
|
||||
|
||||
struct
|
||||
{
|
||||
//! Optional semaphore the target should signal when present is complete.
|
||||
VkSemaphore present_complete;
|
||||
|
||||
//! Semaphore the renderer (consuming this target) should signal when rendering is complete.
|
||||
VkSemaphore render_complete;
|
||||
|
||||
//! If true, @ref render_complete is a timeline semaphore instead of a binary semaphore
|
||||
bool render_complete_is_timeline;
|
||||
} semaphores;
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -137,19 +148,29 @@ struct comp_target
|
|||
/*!
|
||||
* Acquire the next image for rendering.
|
||||
*
|
||||
* If @ref semaphores::present_complete is not null, your use of this image should wait on it.
|
||||
*
|
||||
* @pre @ref has_images returns true
|
||||
*/
|
||||
VkResult (*acquire)(struct comp_target *ct, VkSemaphore semaphore, uint32_t *out_index);
|
||||
VkResult (*acquire)(struct comp_target *ct, uint32_t *out_index);
|
||||
|
||||
/*!
|
||||
* Present the image at index to the screen.
|
||||
*
|
||||
* @pre @ref acquire succeeded for the same @p semaphore and @p index you are passing
|
||||
*
|
||||
* @param ct self
|
||||
* @param queue The Vulkan queue being used
|
||||
* @param index The swapchain image index to present
|
||||
* @param timeline_semaphore_value The value to await on @ref semaphores::render_complete if @ref
|
||||
* semaphores::render_complete_is_timeline is true.
|
||||
* @param desired_present_time_ns The timestamp to present at, ideally.
|
||||
* @param present_slop_ns TODO
|
||||
*/
|
||||
VkResult (*present)(struct comp_target *ct,
|
||||
VkQueue queue,
|
||||
uint32_t index,
|
||||
VkSemaphore semaphore,
|
||||
uint64_t timeline_semaphore_value,
|
||||
uint64_t desired_present_time_ns,
|
||||
uint64_t present_slop_ns);
|
||||
|
||||
|
@ -300,11 +321,11 @@ comp_target_has_images(struct comp_target *ct)
|
|||
* @ingroup comp_main
|
||||
*/
|
||||
static inline VkResult
|
||||
comp_target_acquire(struct comp_target *ct, VkSemaphore semaphore, uint32_t *out_index)
|
||||
comp_target_acquire(struct comp_target *ct, uint32_t *out_index)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
return ct->acquire(ct, semaphore, out_index);
|
||||
return ct->acquire(ct, out_index);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -317,20 +338,20 @@ static inline VkResult
|
|||
comp_target_present(struct comp_target *ct,
|
||||
VkQueue queue,
|
||||
uint32_t index,
|
||||
VkSemaphore semaphore,
|
||||
uint64_t timeline_semaphore_value,
|
||||
uint64_t desired_present_time_ns,
|
||||
uint64_t present_slop_ns)
|
||||
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
return ct->present( //
|
||||
ct, //
|
||||
queue, //
|
||||
index, //
|
||||
semaphore, //
|
||||
desired_present_time_ns, //
|
||||
present_slop_ns); //
|
||||
return ct->present( //
|
||||
ct, //
|
||||
queue, //
|
||||
index, //
|
||||
timeline_semaphore_value, //
|
||||
desired_present_time_ns, //
|
||||
present_slop_ns); //
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -594,6 +594,46 @@ create_vblank_event_thread(struct comp_target *ct)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
target_fini_semaphores(struct comp_target_swapchain *cts)
|
||||
{
|
||||
struct vk_bundle *vk = get_vk(cts);
|
||||
|
||||
if (cts->base.semaphores.present_complete != VK_NULL_HANDLE) {
|
||||
vk->vkDestroySemaphore(vk->device, cts->base.semaphores.present_complete, NULL);
|
||||
cts->base.semaphores.present_complete = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cts->base.semaphores.render_complete != VK_NULL_HANDLE) {
|
||||
vk->vkDestroySemaphore(vk->device, cts->base.semaphores.render_complete, NULL);
|
||||
cts->base.semaphores.render_complete = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
target_init_semaphores(struct comp_target_swapchain *cts)
|
||||
{
|
||||
struct vk_bundle *vk = get_vk(cts);
|
||||
VkResult ret;
|
||||
|
||||
target_fini_semaphores(cts);
|
||||
|
||||
VkSemaphoreCreateInfo info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
};
|
||||
|
||||
ret = vk->vkCreateSemaphore(vk->device, &info, NULL, &cts->base.semaphores.present_complete);
|
||||
if (ret != VK_SUCCESS) {
|
||||
COMP_ERROR(cts->base.c, "vkCreateSemaphore: %s", vk_result_string(ret));
|
||||
}
|
||||
|
||||
cts->base.semaphores.render_complete_is_timeline = false;
|
||||
ret = vk->vkCreateSemaphore(vk->device, &info, NULL, &cts->base.semaphores.render_complete);
|
||||
if (ret != VK_SUCCESS) {
|
||||
COMP_ERROR(cts->base.c, "vkCreateSemaphore: %s", vk_result_string(ret));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -628,6 +668,8 @@ comp_target_swapchain_create_images(struct comp_target *ct,
|
|||
// Free old image views.
|
||||
destroy_image_views(cts);
|
||||
|
||||
target_init_semaphores(cts);
|
||||
|
||||
VkSwapchainKHR old_swapchain_handle = cts->swapchain.handle;
|
||||
|
||||
cts->base.image_count = 0;
|
||||
|
@ -771,7 +813,7 @@ comp_target_swapchain_has_images(struct comp_target *ct)
|
|||
}
|
||||
|
||||
static VkResult
|
||||
comp_target_swapchain_acquire_next_image(struct comp_target *ct, VkSemaphore semaphore, uint32_t *out_index)
|
||||
comp_target_swapchain_acquire_next_image(struct comp_target *ct, uint32_t *out_index)
|
||||
{
|
||||
struct comp_target_swapchain *cts = (struct comp_target_swapchain *)ct;
|
||||
struct vk_bundle *vk = get_vk(cts);
|
||||
|
@ -781,20 +823,20 @@ comp_target_swapchain_acquire_next_image(struct comp_target *ct, VkSemaphore sem
|
|||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
return vk->vkAcquireNextImageKHR( //
|
||||
vk->device, // device
|
||||
cts->swapchain.handle, // swapchain
|
||||
UINT64_MAX, // timeout
|
||||
semaphore, // semaphore
|
||||
VK_NULL_HANDLE, // fence
|
||||
out_index); // pImageIndex
|
||||
return vk->vkAcquireNextImageKHR( //
|
||||
vk->device, // device
|
||||
cts->swapchain.handle, // swapchain
|
||||
UINT64_MAX, // timeout
|
||||
cts->base.semaphores.present_complete, // semaphore
|
||||
VK_NULL_HANDLE, // fence
|
||||
out_index); // pImageIndex
|
||||
}
|
||||
|
||||
static VkResult
|
||||
comp_target_swapchain_present(struct comp_target *ct,
|
||||
VkQueue queue,
|
||||
uint32_t index,
|
||||
VkSemaphore semaphore,
|
||||
uint64_t timeline_semaphore_value,
|
||||
uint64_t desired_present_time_ns,
|
||||
uint64_t present_slop_ns)
|
||||
{
|
||||
|
@ -819,7 +861,7 @@ comp_target_swapchain_present(struct comp_target *ct,
|
|||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.pNext = vk->has_GOOGLE_display_timing ? &timings : NULL,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &semaphore,
|
||||
.pWaitSemaphores = &cts->base.semaphores.render_complete,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &cts->swapchain.handle,
|
||||
.pImageIndices = &index,
|
||||
|
@ -966,6 +1008,8 @@ comp_target_swapchain_cleanup(struct comp_target_swapchain *cts)
|
|||
cts->surface.handle = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
target_fini_semaphores(cts);
|
||||
|
||||
u_pc_destroy(&cts->upc);
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ comp_window_peek_blit(struct comp_window_peek *w, VkImage src, int32_t width, in
|
|||
;
|
||||
|
||||
uint32_t current;
|
||||
VkResult ret = comp_target_acquire(&w->base.base, w->acquire, ¤t);
|
||||
VkResult ret = comp_target_acquire(&w->base.base, ¤t);
|
||||
if (ret != VK_SUCCESS) {
|
||||
COMP_ERROR(w->c, "comp_target_acquire: %s", vk_result_string(ret));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue