c/main: Add readback to gui_window_record

This commit is contained in:
Moses Turner 2022-02-18 20:23:38 -06:00
parent 2e8f572a4d
commit 86a1ba32e5
4 changed files with 241 additions and 33 deletions

View file

@ -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;

View file

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

View file

@ -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!");
}

View file

@ -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