diff --git a/src/xrt/compositor/main/comp_compositor.c b/src/xrt/compositor/main/comp_compositor.c index 7f9d1fcdf..71b0c7446 100644 --- a/src/xrt/compositor/main/comp_compositor.c +++ b/src/xrt/compositor/main/comp_compositor.c @@ -6,6 +6,7 @@ * @author Jakob Bornecrantz <jakob@collabora.com> * @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com> * @author Ryan Pavlik <ryan.pavlik@collabora.com> + * @author Moses Turner <moses@collabora.com> * @ingroup comp_main * * @@ -363,7 +364,7 @@ compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id, xrt_graphic * We have a fast path for single projection layer that goes directly * to the distortion shader, so no need to use the layer renderer. */ - bool fast_path = can_do_one_projection_layer_fast_path(c); + bool fast_path = can_do_one_projection_layer_fast_path(c) && !c->mirroring_to_debug_gui; c->base.slot.one_projection_layer_fast_path = fast_path; @@ -1171,6 +1172,25 @@ xrt_gfx_provider_create_system(struct xrt_device *xdev, struct xrt_system_compos c->last_frame_time_ns = os_monotonic_get_ns(); + float scale = c->settings.viewport_scale; + + if (scale > 2.0) { + scale = 2.0; + COMP_DEBUG(c, "Clamped scale to 200%%\n"); + } + + uint32_t w0 = (uint32_t)(xdev->hmd->views[0].display.w_pixels * scale); + uint32_t h0 = (uint32_t)(xdev->hmd->views[0].display.h_pixels * scale); + uint32_t w1 = (uint32_t)(xdev->hmd->views[1].display.w_pixels * scale); + uint32_t h1 = (uint32_t)(xdev->hmd->views[1].display.h_pixels * scale); + + uint32_t w0_2 = xdev->hmd->views[0].display.w_pixels * 2; + uint32_t h0_2 = xdev->hmd->views[0].display.h_pixels * 2; + uint32_t w1_2 = xdev->hmd->views[1].display.w_pixels * 2; + uint32_t h1_2 = xdev->hmd->views[1].display.h_pixels * 2; + + c->view_extents.width = w0; + c->view_extents.height = h0; // Need to select window backend before creating Vulkan, then // swapchain will initialize the window fully and the swapchain, @@ -1256,22 +1276,7 @@ xrt_gfx_provider_create_system(struct xrt_device *xdev, struct xrt_system_compos memcpy(sys_info->compositor_vk_deviceUUID, c->settings.selected_gpu_deviceUUID, XRT_GPU_UUID_SIZE); memcpy(sys_info->client_vk_deviceUUID, c->settings.client_gpu_deviceUUID, XRT_GPU_UUID_SIZE); - float scale = c->settings.viewport_scale; - if (scale > 2.0) { - scale = 2.0; - COMP_DEBUG(c, "Clamped scale to 200%%\n"); - } - - uint32_t w0 = (uint32_t)(xdev->hmd->views[0].display.w_pixels * scale); - uint32_t h0 = (uint32_t)(xdev->hmd->views[0].display.h_pixels * scale); - uint32_t w1 = (uint32_t)(xdev->hmd->views[1].display.w_pixels * scale); - uint32_t h1 = (uint32_t)(xdev->hmd->views[1].display.h_pixels * scale); - - uint32_t w0_2 = xdev->hmd->views[0].display.w_pixels * 2; - uint32_t h0_2 = xdev->hmd->views[0].display.h_pixels * 2; - uint32_t w1_2 = xdev->hmd->views[1].display.w_pixels * 2; - uint32_t h1_2 = xdev->hmd->views[1].display.h_pixels * 2; // clang-format off sys_info->views[0].recommended.width_pixels = w0; @@ -1328,6 +1333,8 @@ xrt_gfx_provider_create_system(struct xrt_device *xdev, struct xrt_system_compos u_var_add_f32_timing(c, ft, "Frame Times (Compositor)"); + comp_renderer_add_debug_vars(c->r); + c->compositor_frame_times.debug_var = ft; c->state = COMP_STATE_READY; diff --git a/src/xrt/compositor/main/comp_compositor.h b/src/xrt/compositor/main/comp_compositor.h index da9952e85..0e02d26fb 100644 --- a/src/xrt/compositor/main/comp_compositor.h +++ b/src/xrt/compositor/main/comp_compositor.h @@ -99,6 +99,12 @@ struct comp_compositor //! State for generating the correct set of events. enum comp_state state; + // Extents of one view, in pixels. + VkExtent2D view_extents; + + //! Are we mirroring any of the views to the debug gui? If so, turn off the fast path. + bool mirroring_to_debug_gui; + /*! * @brief Data exclusive to the begin_frame/end_frame for computing an * estimate of the app's needs. diff --git a/src/xrt/compositor/main/comp_renderer.c b/src/xrt/compositor/main/comp_renderer.c index 49d45be81..8a46cc049 100644 --- a/src/xrt/compositor/main/comp_renderer.c +++ b/src/xrt/compositor/main/comp_renderer.c @@ -1,4 +1,4 @@ -// Copyright 2019-2021, Collabora, Ltd. +// Copyright 2019-2022, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -6,23 +6,33 @@ * @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com> * @author Jakob Bornecrantz <jakob@collabora.com> * @author Ryan Pavlik <ryan.pavlik@collabora.com> + * @author Moses Turner <moses@collabora.com> * @ingroup comp_main */ +#include "xrt/xrt_defines.h" +#include "xrt/xrt_frame.h" #include "xrt/xrt_compositor.h" #include "os/os_time.h" +#include "math/m_api.h" +#include "math/m_vec3.h" +#include "math/m_matrix_4x4_f64.h" #include "math/m_space.h" #include "util/u_misc.h" #include "util/u_trace_marker.h" #include "util/u_distortion_mesh.h" +#include "util/u_sink.h" +#include "util/u_var.h" +#include "util/u_frame.h" #include "main/comp_layer_renderer.h" -#include "math/m_api.h" -#include "math/m_vec3.h" -#include "math/m_matrix_4x4_f64.h" + + +#include "vk/vk_helpers.h" +#include "vk/vk_image_readback_to_xf_pool.h" #include <string.h> #include <stdlib.h> @@ -52,6 +62,19 @@ struct comp_renderer struct comp_compositor *c; struct comp_settings *settings; + struct + { + // Hint: enable/disable is in c->mirroring_to_debug_gui. It's there because comp_renderer is just a + // forward decl to comp_compositor.c + struct u_sink_debug debug_sink; + VkExtent2D image_extent; + uint64_t sequence; + + struct vk_image_readback_to_xf_pool *pool; + + } mirror_to_debug_gui; + + struct { VkSemaphore present_complete; @@ -433,19 +456,11 @@ renderer_create_layer_renderer(struct comp_renderer *r) } VkExtent2D extent; - if (r->c->target->surface_transform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR || - r->c->target->surface_transform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { - // Swapping width and height, since we are pre rotating - extent = (VkExtent2D){ - .width = r->c->xdev->hmd->screens[0].h_pixels, - .height = r->c->xdev->hmd->screens[0].w_pixels, - }; - } else { - extent = (VkExtent2D){ - .width = r->c->xdev->hmd->screens[0].w_pixels, - .height = r->c->xdev->hmd->screens[0].h_pixels, - }; - } + + extent = (VkExtent2D){ + .width = r->c->view_extents.width, + .height = r->c->view_extents.height, + }; r->lr = comp_layer_renderer_create(vk, &r->c->shaders, extent, VK_FORMAT_B8G8R8A8_SRGB); if (layer_count != 0) { @@ -541,6 +556,17 @@ renderer_create(struct comp_renderer *r, struct comp_compositor *c) // Try to early-allocate these, in case we can. renderer_ensure_images_and_renderings(r, false); + + double orig_width = r->lr->extent.width; + double orig_height = r->lr->extent.height; + + double mul = 1080.0 / orig_height; + + r->mirror_to_debug_gui.image_extent.width = orig_width * mul; + r->mirror_to_debug_gui.image_extent.height = orig_height * mul; + + vk_image_readback_to_xf_pool_create(vk, r->mirror_to_debug_gui.image_extent, &r->mirror_to_debug_gui.pool, + XRT_FORMAT_R8G8B8X8); } static void @@ -732,6 +758,9 @@ renderer_destroy(struct comp_renderer *r) { struct vk_bundle *vk = &r->c->base.vk; + // Left eye readback + vk_image_readback_to_xf_pool_destroy(vk, &r->mirror_to_debug_gui.pool); + // Command buffers renderer_close_renderings_and_fences(r); @@ -1235,6 +1264,154 @@ comp_renderer_set_equirect2_layer(struct comp_renderer *r, } #endif +static bool +can_mirror_to_debug_gui(struct comp_renderer *r) +{ + return r->c->mirroring_to_debug_gui && u_sink_debug_is_active(&r->mirror_to_debug_gui.debug_sink); +} + +static void +mirror_to_debug_gui_do_blit(struct comp_renderer *r) +{ + struct vk_bundle *vk = &r->c->base.vk; + + struct vk_image_readback_to_xf *wrap = NULL; + + if (!vk_image_readback_to_xf_pool_get_unused_frame(vk, r->mirror_to_debug_gui.pool, &wrap)) { + return; + } + + VkCommandBuffer cmd; + vk_init_cmd_buffer(vk, &cmd); + + VkImage copy_from = r->lr->framebuffers[0].image; + +#if 0 + bool fast = r->c->base.slot.one_projection_layer_fast_path; + + + if (fast) { + switch (layer->data.type) { + case XRT_LAYER_STEREO_PROJECTION: { + copy_from = layer->sc_array[0]->vkic.images[layer->data.stereo.l.sub.image_index].handle; + } break; + case XRT_LAYER_STEREO_PROJECTION_DEPTH: { + copy_from = layer->sc_array[0]->vkic.images[layer->data.stereo_depth.l.sub.image_index].handle; + } break; + default: assert(false); + } + } else { + + + } +#endif + + + + VkImageSubresourceRange first_color_level_subresource_range = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + // Barrier to make destination a destination + vk_insert_image_memory_barrier( // + vk, // vk_bundle + cmd, // cmdbuffer + wrap->image, // image + VK_ACCESS_HOST_READ_BIT, // srcAccessMask + VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask + wrap->layout, // oldImageLayout + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newImageLayout + VK_PIPELINE_STAGE_HOST_BIT, // srcStageMask + VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask + first_color_level_subresource_range); // subresourceRange + + // Barrier to make source a source + vk_insert_image_memory_barrier( // + vk, // vk_bundle + cmd, // cmdbuffer + copy_from, // image + VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask + VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // oldImageLayout + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newImageLayout + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // srcStageMask + VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask + first_color_level_subresource_range); // subresourceRange + + + VkImageBlit blit = {0}; + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.layerCount = 1; + + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.layerCount = 1; + + blit.srcOffsets[1].x = r->lr->extent.width; + blit.srcOffsets[1].y = r->lr->extent.height; + blit.srcOffsets[1].z = 1; + + + blit.dstOffsets[1].x = r->mirror_to_debug_gui.image_extent.width; + blit.dstOffsets[1].y = r->mirror_to_debug_gui.image_extent.height; + blit.dstOffsets[1].z = 1; + + vk->vkCmdBlitImage( // + cmd, // commandBuffer + copy_from, // srcImage + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // srcImageLayout + wrap->image, // dstImage + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // dstImageLayout + 1, // regionCount + &blit, // pRegions + VK_FILTER_LINEAR // filter + ); + + wrap->layout = VK_IMAGE_LAYOUT_GENERAL; + + // Reset destination + vk_insert_image_memory_barrier( // + vk, // vk_bundle + cmd, // cmdbuffer + wrap->image, // image + VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask + VK_ACCESS_HOST_READ_BIT, // dstAccessMask + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // oldImageLayout + wrap->layout, // newImageLayout + VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask + VK_PIPELINE_STAGE_HOST_BIT, // dstStageMask + first_color_level_subresource_range); // subresourceRange + + // Reset src + vk_insert_image_memory_barrier( // + vk, // vk_bundle + cmd, // cmdbuffer + copy_from, // image + VK_ACCESS_TRANSFER_READ_BIT, // srcAccessMask + VK_ACCESS_SHADER_WRITE_BIT, // dstAccessMask + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // oldImageLayout + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newImageLayout + VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // dstStageMask + first_color_level_subresource_range); // subresourceRange + + // Waits for command to finish. + vk_submit_cmd_buffer(vk, cmd); + + wrap->base_frame.source_timestamp = wrap->base_frame.timestamp = + r->c->frame.rendering.predicted_display_time_ns; + wrap->base_frame.source_id = r->mirror_to_debug_gui.sequence++; + + + struct xrt_frame *frame = &wrap->base_frame; + wrap = NULL; + u_sink_debug_push_frame(&r->mirror_to_debug_gui.debug_sink, frame); + xrt_frame_reference(&frame, NULL); +} + void comp_renderer_draw(struct comp_renderer *r) { @@ -1282,9 +1459,14 @@ comp_renderer_draw(struct comp_renderer *r) renderer_present_swapchain_image(r, c->frame.rendering.desired_present_time_ns, c->frame.rendering.present_slop_ns); + // Clear the frame. c->frame.rendering.id = -1; + if (can_mirror_to_debug_gui(r)) { + mirror_to_debug_gui_do_blit(r); + } + /* * This fixes a lot of validation issues as it makes sure that the * command buffer has completed and all resources referred by it can @@ -1294,6 +1476,8 @@ comp_renderer_draw(struct comp_renderer *r) */ renderer_wait_gpu_idle(r); + + if (use_compute) { comp_rendering_compute_close(&crc); } else { @@ -1352,3 +1536,11 @@ comp_renderer_destroy(struct comp_renderer **ptr_r) free(r); *ptr_r = NULL; } + +void +comp_renderer_add_debug_vars(struct comp_renderer *r) +{ + // 1.2 % 2.3; + u_var_add_bool(r->c, &r->c->mirroring_to_debug_gui, "Display left eye to GUI (slow)"); + u_var_add_sink_debug(r->c, &r->mirror_to_debug_gui.debug_sink, "Left view!"); +} diff --git a/src/xrt/compositor/main/comp_renderer.h b/src/xrt/compositor/main/comp_renderer.h index a5be40502..27d9ff7a5 100644 --- a/src/xrt/compositor/main/comp_renderer.h +++ b/src/xrt/compositor/main/comp_renderer.h @@ -128,6 +128,9 @@ comp_renderer_allocate_layers(struct comp_renderer *self, uint32_t layer_count); void comp_renderer_destroy_layers(struct comp_renderer *self); +void +comp_renderer_add_debug_vars(struct comp_renderer *self); + #ifdef __cplusplus } #endif