From ef373662f248be83127679a4957a9c900e6a03a6 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 4 Mar 2022 16:20:41 +0000 Subject: [PATCH] ipc: Impelement xrt_compositor_semaphore interfaces --- src/xrt/ipc/client/ipc_client_compositor.c | 110 ++++++++++++++ src/xrt/ipc/server/ipc_server.h | 7 + src/xrt/ipc/server/ipc_server_handler.c | 136 ++++++++++++++++++ .../ipc/server/ipc_server_per_client_thread.c | 6 + src/xrt/ipc/shared/proto.json | 25 ++++ 5 files changed, 284 insertions(+) diff --git a/src/xrt/ipc/client/ipc_client_compositor.c b/src/xrt/ipc/client/ipc_client_compositor.c index 608aa4af2..7f03db8b9 100644 --- a/src/xrt/ipc/client/ipc_client_compositor.c +++ b/src/xrt/ipc/client/ipc_client_compositor.c @@ -89,6 +89,26 @@ struct ipc_client_swapchain uint32_t id; }; +/*! + * Client proxy for an xrt_compositor_semaphore implementation over IPC. + * @implements xrt_compositor_semaphore + */ +struct ipc_client_compositor_semaphore +{ + struct xrt_compositor_semaphore base; + + struct ipc_client_compositor *icc; + + uint32_t id; +}; + + +/* + * + * Helper functions. + * + */ + static inline struct ipc_client_compositor * ipc_client_compositor(struct xrt_compositor *xc) { @@ -101,6 +121,12 @@ ipc_client_swapchain(struct xrt_swapchain *xs) return (struct ipc_client_swapchain *)xs; } +static inline struct ipc_client_compositor_semaphore * +ipc_client_compositor_semaphore(struct xrt_compositor_semaphore *xcsem) +{ + return (struct ipc_client_compositor_semaphore *)xcsem; +} + /* * @@ -190,6 +216,35 @@ ipc_compositor_swapchain_release_image(struct xrt_swapchain *xsc, uint32_t index } +/* + * + * Compositor semaphore functions. + * + */ + +static xrt_result_t +ipc_client_compositor_semaphore_wait(struct xrt_compositor_semaphore *xcsem, uint64_t value, uint64_t timeout_ns) +{ + struct ipc_client_compositor_semaphore *iccs = ipc_client_compositor_semaphore(xcsem); + struct ipc_client_compositor *icc = iccs->icc; + + IPC_ERROR(icc->ipc_c, "Can not call wait on client side!"); + + return XRT_ERROR_IPC_FAILURE; +} + +static void +ipc_client_compositor_semaphore_destroy(struct xrt_compositor_semaphore *xcsem) +{ + struct ipc_client_compositor_semaphore *iccs = ipc_client_compositor_semaphore(xcsem); + struct ipc_client_compositor *icc = iccs->icc; + + IPC_CALL_CHK(ipc_call_compositor_semaphore_destroy(icc->ipc_c, iccs->id)); + + free(iccs); +} + + /* * * Compositor functions. @@ -350,6 +405,30 @@ ipc_compositor_swapchain_import(struct xrt_compositor *xc, return swapchain_server_import(icc, info, native_images, image_count, out_xsc); } +static xrt_result_t +ipc_compositor_semaphore_create(struct xrt_compositor *xc, + xrt_graphics_sync_handle_t *out_handle, + struct xrt_compositor_semaphore **out_xcsem) +{ + struct ipc_client_compositor *icc = ipc_client_compositor(xc); + uint32_t id = 0; + xrt_graphics_sync_handle_t handle = XRT_GRAPHICS_SYNC_HANDLE_INVALID; + + IPC_CALL_CHK(ipc_call_compositor_semaphore_create(icc->ipc_c, &id, &handle, 1)); + + struct ipc_client_compositor_semaphore *iccs = U_TYPED_CALLOC(struct ipc_client_compositor_semaphore); + iccs->base.reference.count = 1; + iccs->base.wait = ipc_client_compositor_semaphore_wait; + iccs->base.destroy = ipc_client_compositor_semaphore_destroy; + iccs->id = id; + iccs->icc = icc; + + *out_handle = handle; + *out_xcsem = &iccs->base; + + return XRT_SUCCESS; +} + static xrt_result_t ipc_compositor_poll_events(struct xrt_compositor *xc, union xrt_compositor_event *out_xce) { @@ -648,6 +727,35 @@ ipc_compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id, xrt_gra return res; } +static xrt_result_t +ipc_compositor_layer_commit_with_semaphore(struct xrt_compositor *xc, + int64_t frame_id, + struct xrt_compositor_semaphore *xcsem, + uint64_t value) +{ + struct ipc_client_compositor *icc = ipc_client_compositor(xc); + struct ipc_client_compositor_semaphore *iccs = ipc_client_compositor_semaphore(xcsem); + + struct ipc_shared_memory *ism = icc->ipc_c->ism; + struct ipc_layer_slot *slot = &ism->slots[icc->layers.slot_id]; + + // Last bit of data to put in the shared memory area. + slot->layer_count = icc->layers.layer_count; + + IPC_CALL_CHK(ipc_call_compositor_layer_sync_with_semaphore( // + icc->ipc_c, // + frame_id, // + icc->layers.slot_id, // + iccs->id, // + value, // + &icc->layers.slot_id)); // + + // Reset. + icc->layers.layer_count = 0; + + return res; +} + static xrt_result_t ipc_compositor_discard_frame(struct xrt_compositor *xc, int64_t frame_id) { @@ -675,6 +783,7 @@ ipc_compositor_init(struct ipc_client_compositor *icc, struct xrt_compositor_nat { icc->base.base.create_swapchain = ipc_compositor_swapchain_create; icc->base.base.import_swapchain = ipc_compositor_swapchain_import; + icc->base.base.create_semaphore = ipc_compositor_semaphore_create; icc->base.base.begin_session = ipc_compositor_begin_session; icc->base.base.end_session = ipc_compositor_end_session; icc->base.base.wait_frame = ipc_compositor_wait_frame; @@ -689,6 +798,7 @@ ipc_compositor_init(struct ipc_client_compositor *icc, struct xrt_compositor_nat icc->base.base.layer_equirect1 = ipc_compositor_layer_equirect1; icc->base.base.layer_equirect2 = ipc_compositor_layer_equirect2; icc->base.base.layer_commit = ipc_compositor_layer_commit; + icc->base.base.layer_commit_with_semaphore = ipc_compositor_layer_commit_with_semaphore; icc->base.base.destroy = ipc_compositor_destroy; icc->base.base.poll_events = ipc_compositor_poll_events; diff --git a/src/xrt/ipc/server/ipc_server.h b/src/xrt/ipc/server/ipc_server.h index 43be929d3..3b09e5ee8 100644 --- a/src/xrt/ipc/server/ipc_server.h +++ b/src/xrt/ipc/server/ipc_server.h @@ -45,6 +45,7 @@ extern "C" { */ #define IPC_SERVER_NUM_XDEVS 8 +#define IPC_MAX_CLIENT_SEMAPHORES 8 #define IPC_MAX_CLIENT_SWAPCHAINS 32 //#define IPC_MAX_CLIENTS 8 @@ -93,6 +94,12 @@ struct ipc_client_state //! Data for the swapchains. struct ipc_swapchain_data swapchain_data[IPC_MAX_CLIENT_SWAPCHAINS]; + //! Number of compositor semaphores in use by client + uint32_t compositor_semaphore_count; + + //! Ptrs to the semaphores. + struct xrt_compositor_semaphore *xcsems[IPC_MAX_CLIENT_SEMAPHORES]; + //! Socket fd used for client comms struct ipc_message_channel imc; diff --git a/src/xrt/ipc/server/ipc_server_handler.c b/src/xrt/ipc/server/ipc_server_handler.c index 13cb1539b..42ed67ce2 100644 --- a/src/xrt/ipc/server/ipc_server_handler.c +++ b/src/xrt/ipc/server/ipc_server_handler.c @@ -558,6 +558,63 @@ ipc_handle_compositor_layer_sync(volatile struct ipc_client_state *ics, return XRT_SUCCESS; } +xrt_result_t +ipc_handle_compositor_layer_sync_with_semaphore(volatile struct ipc_client_state *ics, + int64_t frame_id, + uint32_t slot_id, + uint32_t semaphore_id, + uint64_t semaphore_value, + uint32_t *out_free_slot_id) +{ + IPC_TRACE_MARKER(); + + if (ics->xc == NULL) { + return XRT_ERROR_IPC_SESSION_NOT_CREATED; + } + if (semaphore_id >= IPC_MAX_CLIENT_SEMAPHORES) { + IPC_ERROR(ics->server, "Invalid semaphore_id"); + return XRT_ERROR_IPC_FAILURE; + } + if (ics->xcsems[semaphore_id] == NULL) { + IPC_ERROR(ics->server, "Semaphore of id %u not created!", semaphore_id); + return XRT_ERROR_IPC_FAILURE; + } + + struct xrt_compositor_semaphore *xcsem = ics->xcsems[semaphore_id]; + + struct ipc_shared_memory *ism = ics->server->ism; + struct ipc_layer_slot *slot = &ism->slots[slot_id]; + + // Copy current slot data. + struct ipc_layer_slot copy = *slot; + + + + /* + * Transfer data to underlying compositor. + */ + + xrt_comp_layer_begin(ics->xc, frame_id, copy.display_time_ns, copy.env_blend_mode); + + _update_layers(ics, ics->xc, ©); + + xrt_comp_layer_commit_with_semaphore(ics->xc, frame_id, xcsem, semaphore_value); + + + /* + * Manage shared state. + */ + + os_mutex_lock(&ics->server->global_state.lock); + + *out_free_slot_id = (ics->server->current_slot_index + 1) % IPC_MAX_SLOTS; + ics->server->current_slot_index = *out_free_slot_id; + + os_mutex_unlock(&ics->server->global_state.lock); + + return XRT_SUCCESS; +} + xrt_result_t ipc_handle_compositor_poll_events(volatile struct ipc_client_state *ics, union xrt_compositor_event *out_xce) { @@ -843,6 +900,85 @@ ipc_handle_swapchain_destroy(volatile struct ipc_client_state *ics, uint32_t id) return XRT_SUCCESS; } + +/* + * + * Compositor semaphore function.. + * + */ + +xrt_result_t +ipc_handle_compositor_semaphore_create(volatile struct ipc_client_state *ics, + uint32_t *out_id, + uint32_t max_handle_count, + xrt_graphics_sync_handle_t *out_handles, + uint32_t *out_handle_count) +{ + xrt_result_t xret; + + if (ics->xc == NULL) { + return XRT_ERROR_IPC_SESSION_NOT_CREATED; + } + + int id = 0; + for (; id < IPC_MAX_CLIENT_SEMAPHORES; id++) { + if (ics->xcsems[id] == NULL) { + break; + } + } + + if (id == IPC_MAX_CLIENT_SEMAPHORES) { + IPC_ERROR(ics->server, "Too many compositor semaphores alive!"); + return XRT_ERROR_IPC_FAILURE; + } + + struct xrt_compositor_semaphore *xcsem = NULL; + xrt_graphics_sync_handle_t handle = XRT_GRAPHICS_SYNC_HANDLE_INVALID; + + xret = xrt_comp_create_semaphore(ics->xc, &handle, &xcsem); + if (xret != XRT_SUCCESS) { + IPC_ERROR(ics->server, "Failed to create compositor semaphore!"); + return XRT_SUCCESS; + } + + // Set it directly, no need to use reference here. + ics->xcsems[id] = xcsem; + + // Set out parameters. + *out_id = id; + out_handles[0] = handle; + *out_handle_count = 1; + + return XRT_SUCCESS; +} + +xrt_result_t +ipc_handle_compositor_semaphore_destroy(volatile struct ipc_client_state *ics, uint32_t id) +{ + if (ics->xc == NULL) { + return XRT_ERROR_IPC_SESSION_NOT_CREATED; + } + + if (ics->xcsems[id] == NULL) { + IPC_ERROR(ics->server, "Client tried to delete non-existent compositor semaphore!"); + return XRT_ERROR_IPC_FAILURE; + } + + ics->compositor_semaphore_count--; + + // Drop our reference, does NULL checking. Cast away volatile. + xrt_compositor_semaphore_reference((struct xrt_compositor_semaphore **)&ics->xcsems[id], NULL); + + return XRT_SUCCESS; +} + + +/* + * + * Device functions. + * + */ + xrt_result_t ipc_handle_device_update_input(volatile struct ipc_client_state *ics, uint32_t id) { diff --git a/src/xrt/ipc/server/ipc_server_per_client_thread.c b/src/xrt/ipc/server/ipc_server_per_client_thread.c index 346448648..bb17e9859 100644 --- a/src/xrt/ipc/server/ipc_server_per_client_thread.c +++ b/src/xrt/ipc/server/ipc_server_per_client_thread.c @@ -163,6 +163,12 @@ ipc_server_client_destroy_compositor(volatile struct ipc_client_state *ics) IPC_TRACE(ics->server, "Destroyed swapchain %d.", j); } + for (uint32_t j = 0; j < IPC_MAX_CLIENT_SEMAPHORES; j++) { + // Drop our reference, does NULL checking. Cast away volatile. + xrt_compositor_semaphore_reference((struct xrt_compositor_semaphore **)&ics->xcsems[j], NULL); + IPC_TRACE(ics->server, "Destroyed compositor semaphore %d.", j); + } + os_mutex_unlock(&ics->server->global_state.lock); // Cast away volatile. diff --git a/src/xrt/ipc/shared/proto.json b/src/xrt/ipc/shared/proto.json index 852014025..ae3456204 100644 --- a/src/xrt/ipc/shared/proto.json +++ b/src/xrt/ipc/shared/proto.json @@ -112,6 +112,18 @@ ] }, + "compositor_layer_sync_with_semaphore": { + "in": [ + {"name": "frame_id", "type": "int64_t"}, + {"name": "slot_id", "type": "uint32_t"}, + {"name": "semaphore_id", "type": "uint32_t"}, + {"name": "semaphore_value", "type": "uint64_t"} + ], + "out": [ + {"name": "free_slot_id", "type": "uint32_t"} + ] + }, + "compositor_poll_events": { "out": [ {"name": "event", "type": "union xrt_compositor_event"} @@ -172,6 +184,19 @@ ] }, + "compositor_semaphore_create": { + "out": [ + {"name": "id", "type": "uint32_t"} + ], + "out_handles": {"type": "xrt_graphics_sync_handle_t"} + }, + + "compositor_semaphore_destroy": { + "in": [ + {"name": "id", "type": "uint32_t"} + ] + }, + "device_update_input": { "in": [ {"name": "id", "type": "uint32_t"}