Monado OpenXR Runtime
comp_compositor.c File Reference

Main compositor written using Vulkan implementation. More...

#include "xrt/xrt_compiler.h"
#include "xrt/xrt_compositor.h"
#include "xrt/xrt_config_have.h"
#include "xrt/xrt_results.h"
#include "math/m_api.h"
#include "os/os_time.h"
#include "util/u_var.h"
#include "util/u_misc.h"
#include "util/u_time.h"
#include "util/u_debug.h"
#include "util/u_pacing.h"
#include "util/u_handles.h"
#include "util/u_trace_marker.h"
#include "util/u_pretty_print.h"
#include "util/u_distortion_mesh.h"
#include "util/u_verify.h"
#include "util/comp_vulkan.h"
#include "main/comp_compositor.h"
#include "main/comp_frame.h"
#include "multi/comp_multi_interface.h"
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
Include dependency graph for comp_compositor.c:

Macros

#define WINDOW_TITLE   "Monado"
 

Functions

static double ns_to_ms (int64_t ns)
 
static double ts_ms (void)
 
static struct vk_bundleget_vk (struct comp_compositor *c)
 
static bool compositor_init_window_post_vulkan (struct comp_compositor *c)
 
static bool compositor_init_swapchain (struct comp_compositor *c)
 
static bool compositor_init_renderer (struct comp_compositor *c)
 
static xrt_result_t compositor_begin_session (struct xrt_compositor *xc, const struct xrt_begin_session_info *info)
 
static xrt_result_t compositor_end_session (struct xrt_compositor *xc)
 
static xrt_result_t compositor_predict_frame (struct xrt_compositor *xc, int64_t *out_frame_id, int64_t *out_wake_time_ns, int64_t *out_predicted_gpu_time_ns, int64_t *out_predicted_display_time_ns, int64_t *out_predicted_display_period_ns)
 
static xrt_result_t compositor_mark_frame (struct xrt_compositor *xc, int64_t frame_id, enum xrt_compositor_frame_point point, int64_t when_ns)
 
static xrt_result_t compositor_begin_frame (struct xrt_compositor *xc, int64_t frame_id)
 
static xrt_result_t compositor_discard_frame (struct xrt_compositor *xc, int64_t frame_id)
 
static bool can_do_one_projection_layer_fast_path (struct comp_compositor *c)
 We have a fast path for single projection layer that goes directly to the distortion shader, so no need to use the layer renderer. More...
 
static XRT_CHECK_RESULT xrt_result_t compositor_layer_commit (struct xrt_compositor *xc, xrt_graphics_sync_handle_t sync_handle)
 
static xrt_result_t compositor_get_display_refresh_rate (struct xrt_compositor *xc, float *out_display_refresh_rate_hz)
 
static xrt_result_t compositor_request_display_refresh_rate (struct xrt_compositor *xc, float display_refresh_rate_hz)
 
static void compositor_destroy (struct xrt_compositor *xc)
 
static bool compositor_check_and_prepare_xdev (struct comp_compositor *c, struct xrt_device *xdev)
 
static bool compositor_init_vulkan (struct comp_compositor *c)
 
static void error_msg_with_list (struct comp_compositor *c, const char *msg)
 
static bool compositor_check_deferred (struct comp_compositor *c, const struct comp_target_factory *ctf)
 
static bool compositor_try_window (struct comp_compositor *c, const struct comp_target_factory *ctf)
 
static bool select_target_factory_from_settings (struct comp_compositor *c, const struct comp_target_factory **out_ctf)
 
static bool select_target_factory_by_detecting (struct comp_compositor *c, const struct comp_target_factory **out_ctf)
 
static bool compositor_init_window_pre_vulkan (struct comp_compositor *c, const struct comp_target_factory *selected_ctf)
 
static bool compositor_init_render_resources (struct comp_compositor *c)
 
xrt_result_t comp_main_create_system_compositor (struct xrt_device *xdev, const struct comp_target_factory *ctf, struct xrt_system_compositor **out_xsysc)
 

Variables

static const char * instance_extensions_common []
 
static const char * optional_instance_extensions []
 
static const char * required_device_extensions []
 
static const char * optional_device_extensions []
 
const struct comp_target_factoryctfs []
 

Detailed Description

Main compositor written using Vulkan implementation.

Author
Jakob Bornecrantz jakob.nosp@m.@col.nosp@m.labor.nosp@m.a.co.nosp@m.m
Lubosz Sarnecki lubos.nosp@m.z.sa.nosp@m.rneck.nosp@m.i@co.nosp@m.llabo.nosp@m.ra.c.nosp@m.om
Rylie Pavlik rylie.nosp@m..pav.nosp@m.lik@c.nosp@m.olla.nosp@m.bora..nosp@m.com
Moses Turner moses.nosp@m.@col.nosp@m.labor.nosp@m.a.co.nosp@m.m

begin_frame and end_frame delimit the application's work on graphics for a single frame. end_frame updates our estimate of the current estimated app graphics duration, as well as the "swap interval" for scheduling the application.

We have some known overhead work required to composite a frame: eventually this may be measured as well. Overhead plus the estimated app render duration is compared to the frame duration: if it's longer, then we go to a "swap interval" of 2.

wait_frame must be the one to produce the next predicted display time, because we cannot distinguish two sequential wait_frame calls (an app skipping a frame) from an OS scheduling blip causing the second wait_frame to happen before the first begin_frame actually gets executed. It cannot use the last display time in this computation for this reason. (Except perhaps to align the period at a sub-frame level? e.g. should be a multiple of the frame duration after the last displayed time).

wait_frame should not actually produce the predicted display time until it's done waiting: it should wake up once a frame and see what the current swap interval suggests: this handles the case where end_frame changes the swap interval from 2 to 1 during a wait_frame call. (That is, we should wait until whichever is closer of the next vsync or the time we currently predict we should release the app.)

Sleeping can be a bit hairy: in general right now we'll use a combination of operating system sleeps and busy-waits (for fine-grained waiting). Some platforms provide vsync-related sync primitives that may get us closer to our desired time. This is also convenient for the "wait until next frame" behavior.

Function Documentation

◆ can_do_one_projection_layer_fast_path()

static bool can_do_one_projection_layer_fast_path ( struct comp_compositor c)
static

We have a fast path for single projection layer that goes directly to the distortion shader, so no need to use the layer renderer.

References comp_base::layer_accum, comp_layer_accum::layer_count, and comp_layer_accum::layers.

◆ comp_main_create_system_compositor()

xrt_result_t comp_main_create_system_compositor ( struct xrt_device xdev,
const struct comp_target_factory ctf,
struct xrt_system_compositor **  out_xsysc 
)
related
Todo:
Support more like, depth/float formats etc, remember to update the GL client as well.
Todo:
: Query all supported refresh rates of the current mode

◆ compositor_get_display_refresh_rate()

static xrt_result_t compositor_get_display_refresh_rate ( struct xrt_compositor xc,
float *  out_display_refresh_rate_hz 
)
static
Todo:
: Implement the method to change display refresh rate.

Variable Documentation

◆ ctfs

const struct comp_target_factory* ctfs[]
Initial value:
= {
&comp_target_factory_wayland,
&comp_target_factory_direct_randr,
&comp_target_factory_xcb,
&comp_target_factory_direct_nvidia,
}

◆ instance_extensions_common

const char* instance_extensions_common[]
static
Initial value:
= {
COMP_INSTANCE_EXTENSIONS_COMMON,
}

◆ optional_instance_extensions

const char* optional_instance_extensions[]
static
Initial value:
= {
}