c/util: Refactor how arguments are given

This commit is contained in:
Jakob Bornecrantz 2023-12-30 13:10:23 +00:00
parent df69c9da50
commit e051549668
5 changed files with 840 additions and 540 deletions

View file

@ -823,24 +823,58 @@ dispatch_graphics(struct comp_renderer *r, struct render_gfx *rr, enum comp_targ
world_poses, // world_poses[2] world_poses, // world_poses[2]
eye_poses); // eye_poses[2] eye_poses); // eye_poses[2]
// Scratch image we are rendering to.
struct render_scratch_images *rsi = &r->scratch;
// The arguments for the dispatch function.
struct comp_render_dispatch_data data;
comp_render_gfx_initial_init( //
&data, // data
rtr, // rtr
fast_path, // fast_path
do_timewarp); // do_timewarp
for (uint32_t i = 0; i < 2; i++) {
// Scratch color image.
struct render_scratch_color_image *rsci = &rsi->color[i];
// The render target resources for the scratch images.
struct render_gfx_target_resources *rsci_rtr = &r->scratch_targets[i];
// Use the whole scratch image.
struct render_viewport_data layer_viewport_data = {
.x = 0,
.y = 0,
.w = rsi->extent.width,
.h = rsi->extent.height,
};
// Scratch image covers the whole image.
struct xrt_normalized_rect layer_norm_rect = {.x = 0.0f, .y = 0.0f, .w = 1.0f, .h = 1.0f};
comp_render_gfx_add_view( //
&data, // data
&world_poses[i], // world_pose
&eye_poses[i], // eye_pose
&fovs[i], // fov
rsci_rtr, // rtr
&layer_viewport_data, // layer_viewport_data
&layer_norm_rect, // layer_norm_rect
rsci->image, // image
rsci->srgb_view, // srgb_view
&vertex_rots[i], // vertex_rot
&viewport_datas[i]); // target_viewport_data
}
// Start the graphics pipeline. // Start the graphics pipeline.
render_gfx_begin(rr); render_gfx_begin(rr);
// Build the command buffer. // Build the command buffer.
comp_render_gfx_dispatch( // comp_render_gfx_dispatch( //
rr, // rr rr, // rr
&r->scratch, // rsi
r->scratch_targets, // rsi_rtrs
layers, // layers layers, // layers
layer_count, // layer_count layer_count, // layer_count
world_poses, // world_poses &data); // d
eye_poses, // eye_poses
fovs, // fovs
vertex_rots, // vertex_rots
rtr, // rtr
viewport_datas, // viewport_datas
fast_path, // fast_path
do_timewarp); // do_timewarp
// Make the command buffer submittable. // Make the command buffer submittable.
render_gfx_end(rr); render_gfx_end(rr);
@ -880,7 +914,7 @@ dispatch_compute(struct comp_renderer *r, struct render_compute *crc, enum comp_
bool do_timewarp = !c->debug.atw_off; bool do_timewarp = !c->debug.atw_off;
// Device view information. // Device view information.
struct xrt_fov fovs[2]; // Unused struct xrt_fov fovs[2];
struct xrt_pose world_poses[2]; struct xrt_pose world_poses[2];
struct xrt_pose eye_poses[2]; struct xrt_pose eye_poses[2];
calc_pose_data( // calc_pose_data( //
@ -898,22 +932,55 @@ dispatch_compute(struct comp_renderer *r, struct render_compute *crc, enum comp_
struct render_viewport_data views[2]; struct render_viewport_data views[2];
calc_viewport_data(r, &views[0], &views[1]); calc_viewport_data(r, &views[0], &views[1]);
// Scratch image we are rendering to.
struct render_scratch_images *rsi = &r->scratch;
// The arguments for the dispatch function.
struct comp_render_dispatch_data data;
comp_render_cs_initial_init( //
&data, // data
target_image, // target_image
target_image_view, // target_unorm_view
fast_path, // fast_path
do_timewarp); // do_timewarp
for (uint32_t i = 0; i < 2; i++) {
// Scratch color image.
struct render_scratch_color_image *rsci = &rsi->color[i];
// Use the whole scratch image.
struct render_viewport_data layer_viewport_data = {
.x = 0,
.y = 0,
.w = rsi->extent.width,
.h = rsi->extent.height,
};
// Scratch image covers the whole image.
struct xrt_normalized_rect layer_norm_rect = {.x = 0.0f, .y = 0.0f, .w = 1.0f, .h = 1.0f};
comp_render_cs_add_view( //
&data, // data
&world_poses[i], // world_pose
&eye_poses[i], // eye_pose
&fovs[i], // fov
&layer_viewport_data, // layer_viewport_data
&layer_norm_rect, // layer_norm_rect
rsci->image, // image
rsci->srgb_view, // srgb_view
rsci->unorm_view, // unorm_view
&views[i]); // target_viewport_data
}
// Start the compute pipeline. // Start the compute pipeline.
render_compute_begin(crc); render_compute_begin(crc);
// Build the command buffer. // Build the command buffer.
comp_render_cs_dispatch( // comp_render_cs_dispatch( //
crc, // crc crc, // crc
&r->scratch, // rsi
world_poses, // world_poses
eye_poses, // eye_poses
layers, // layers layers, // layers
layer_count, // layer_count layer_count, // layer_count
target_image, // target_image &data); // d
target_image_view, // target_image_view
views, // views
fast_path, // fast_path
do_timewarp); // do_timewarp
// Make the command buffer submittable. // Make the command buffer submittable.
render_compute_end(crc); render_compute_end(crc);

View file

@ -1,4 +1,4 @@
// Copyright 2019-2023, Collabora, Ltd. // Copyright 2019-2024, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
/*! /*!
* @file * @file
@ -22,16 +22,178 @@ extern "C" {
struct comp_layer; struct comp_layer;
/*
*
* Input data struct.
*
*/
/*!
* The input data needed for a single view, it shared between both GFX and CS
* paths. To fully render a single view two "rendering" might be needed, the
* first being the layer squashing, and the second is the distortion step. The
* target for the layer squashing is referred to as "layer" or "scratch" and
* prefixed with `layer` if needs be. The other final step is referred to as
* "distortion target" or just "target", and is prefixed with `target`.
*/
struct comp_render_view_data
{
//! New world pose of this view.
struct xrt_pose world_pose;
//! New eye pose of this view.
struct xrt_pose eye_pose;
/*!
* New fov of this view, used for the layer scratch image. Needs to
* match distortion parameters if distortion is used.
*/
struct xrt_fov fov;
/*!
* The layer image for this view (aka scratch image),
* used for barrier operations.
*/
VkImage image;
/*!
* View into layer image (aka scratch image),
* used for both GFX (read/write) and CS (read) paths.
*/
VkImageView srgb_view;
/*!
* Pre-view layer target viewport_data (where in the image we should
* render the view).
*/
struct render_viewport_data layer_viewport_data;
/*!
* When sampling from the layer image (aka scratch image), how should we
* transform it to get to the pixels correctly.
*/
struct xrt_normalized_rect layer_norm_rect;
//! Go from UV to tanangle for the target, this needs to match @p fov.
struct xrt_normalized_rect target_pre_transform;
// Distortion target viewport data (aka target).
struct render_viewport_data target_viewport_data;
struct
{
//! Per-view layer target resources.
struct render_gfx_target_resources *rtr;
//! Distortion target vertex rotation information.
struct xrt_matrix_2x2 vertex_rot;
} gfx;
struct
{
//! Only used on compute path.
VkImageView unorm_view;
} cs;
};
/*!
* The input data needed for a complete layer squashing distortion rendering
* to a target. This struct is shared between GFX and CS paths.
*/
struct comp_render_dispatch_data
{
struct comp_render_view_data views[2];
//! The number of views currently in this dispatch data.
uint32_t view_count;
//! Fast path can be disabled for mirroing so needs to be an argument.
bool fast_path;
//! Very often true, can be disabled for debugging.
bool do_timewarp;
struct
{
// The resources needed for the target.
struct render_gfx_target_resources *rtr;
} gfx;
struct
{
// Target image for distortion, used for barrier.
VkImage target_image;
// Target image view for distortion.
VkImageView target_unorm_view;
} cs;
};
/*
*
* Gfx functions.
*
*/
static inline void
comp_render_gfx_initial_init(struct comp_render_dispatch_data *data,
struct render_gfx_target_resources *rtr,
bool fast_path,
bool do_timewarp)
{
U_ZERO(data);
data->fast_path = fast_path;
data->do_timewarp = do_timewarp;
data->gfx.rtr = rtr;
}
static inline void
comp_render_gfx_add_view(struct comp_render_dispatch_data *data,
const struct xrt_pose *world_pose,
const struct xrt_pose *eye_pose,
const struct xrt_fov *fov,
struct render_gfx_target_resources *rtr,
const struct render_viewport_data *layer_viewport_data,
const struct xrt_normalized_rect *layer_norm_rect,
VkImage image,
VkImageView srgb_view,
const struct xrt_matrix_2x2 *vertex_rot,
const struct render_viewport_data *target_viewport_data)
{
uint32_t i = data->view_count++;
assert(i < ARRAY_SIZE(data->views));
struct comp_render_view_data *view = &data->views[i];
render_calc_uv_to_tangent_lengths_rect(fov, &view->target_pre_transform);
view->world_pose = *world_pose;
view->eye_pose = *eye_pose;
view->fov = *fov;
view->image = image;
view->srgb_view = srgb_view;
view->layer_viewport_data = *layer_viewport_data;
view->layer_norm_rect = *layer_norm_rect;
view->target_viewport_data = *target_viewport_data;
view->gfx.rtr = rtr;
view->gfx.vertex_rot = *vertex_rot;
}
/*! /*!
* Helper function that takes a set of layers, new device poses, a scratch * Helper function that takes a set of layers, new device poses, a scratch
* images with associated @ref render_gfx_target_resources and writes the needed * images with associated @ref render_gfx_target_resources and writes the needed
* commands to the @ref render_gfx to do a full composition with distortion. * commands to the @ref render_gfx to do a full composition with distortion.
* The scratch images are optionally used to squash layers should it not be * The scratch images are optionally used to squash layers should it not be
* possible to do a @p fast_path. Will use the render passes of the targets * possible to do a @p comp_render_dispatch_data::fast_path. Will use the render
* which set the layout. * passes of the targets which set the layout.
* *
* The render passes of @p rsi_rtrs must be created with a final_layout of * The render passes of @p comp_render_dispatch_data::views::rtr must be created
* VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL or there will be validation errors. * with a final_layout of VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL or there will
* be validation errors.
* *
* Expected layouts: * Expected layouts:
* * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL * * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
@ -47,20 +209,65 @@ struct comp_layer;
*/ */
void void
comp_render_gfx_dispatch(struct render_gfx *rr, comp_render_gfx_dispatch(struct render_gfx *rr,
struct render_scratch_images *rsi,
struct render_gfx_target_resources rsi_rtrs[2],
const struct comp_layer *layers, const struct comp_layer *layers,
const uint32_t layer_count, const uint32_t layer_count,
struct xrt_pose world_poses[2], const struct comp_render_dispatch_data *d);
struct xrt_pose eye_poses[2],
struct xrt_fov fovs[2],
struct xrt_matrix_2x2 vertex_rots[2],
struct render_gfx_target_resources *rtr,
const struct render_viewport_data viewport_datas[2],
bool fast_path,
bool do_timewarp);
/*
*
* CS functions.
*
*/
static inline void
comp_render_cs_initial_init(struct comp_render_dispatch_data *data,
VkImage target_image,
VkImageView target_unorm_view,
bool fast_path,
bool do_timewarp)
{
U_ZERO(data);
data->fast_path = fast_path;
data->do_timewarp = do_timewarp;
data->cs.target_image = target_image;
data->cs.target_unorm_view = target_unorm_view;
}
static inline void
comp_render_cs_add_view(struct comp_render_dispatch_data *data,
const struct xrt_pose *world_pose,
const struct xrt_pose *eye_pose,
const struct xrt_fov *fov,
const struct render_viewport_data *layer_viewport_data,
const struct xrt_normalized_rect *layer_norm_rect,
VkImage image,
VkImageView srgb_view,
VkImageView unorm_view,
const struct render_viewport_data *target_viewport_data)
{
uint32_t i = data->view_count++;
assert(i < ARRAY_SIZE(data->views));
struct comp_render_view_data *view = &data->views[i];
render_calc_uv_to_tangent_lengths_rect(fov, &view->target_pre_transform);
view->world_pose = *world_pose;
view->eye_pose = *eye_pose;
view->fov = *fov;
view->layer_viewport_data = *layer_viewport_data;
view->layer_norm_rect = *layer_norm_rect;
view->image = image;
view->srgb_view = srgb_view;
view->target_viewport_data = *target_viewport_data;
view->cs.unorm_view = unorm_view;
}
/*! /*!
* Helper to dispatch the layer squasher for a single view. * Helper to dispatch the layer squasher for a single view.
* *
@ -87,7 +294,7 @@ comp_render_cs_layer(struct render_compute *crc,
bool do_timewarp); bool do_timewarp);
/*! /*!
* Helper function to dispatch the layer squasher, designed for stereo views. * Helper function to dispatch the layer squasher, works on any number of views.
* *
* All source layer images needs to be in the correct image layout, no barrier * All source layer images needs to be in the correct image layout, no barrier
* is inserted for them. The target images are barried from undefined to general * is inserted for them. The target images are barried from undefined to general
@ -104,44 +311,11 @@ comp_render_cs_layer(struct render_compute *crc,
* @ingroup comp_util * @ingroup comp_util
*/ */
void void
comp_render_cs_stereo_layers(struct render_compute *crc, comp_render_cs_layers(struct render_compute *crc,
const struct comp_layer *layers, const struct comp_layer *layers,
const uint32_t layer_count, const uint32_t layer_count,
const struct xrt_normalized_rect pre_transforms[2], const struct comp_render_dispatch_data *d,
const struct xrt_pose world_poses[2], VkImageLayout transition_to);
const struct xrt_pose eye_poses[2],
const VkImage target_images[2],
const VkImageView target_image_views[2],
const struct render_viewport_data target_views[2],
VkImageLayout transition_to,
bool do_timewarp);
/*!
* Helper function that takes a set of layers, new device poses, a scratch
* images and writes the needed commands to the @ref render_compute to squash
* the given layers into the given scratch images. Will insert barriers to
* change the scratch images to the needed layout.
*
* Expected layouts:
* * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
* * Scratch images: Any
*
* After call layouts:
* * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
* * Scratch images: @p transition_to
*
* @ingroup comp_util
*/
void
comp_render_cs_stereo_layers_to_scratch(struct render_compute *crc,
const struct xrt_normalized_rect pre_transforms[2],
struct xrt_pose world_poses[2],
struct xrt_pose eye_poses[2],
const struct comp_layer *layers,
const uint32_t layer_count,
struct render_scratch_images *rsi,
VkImageLayout transition_to,
bool do_timewarp);
/*! /*!
* Helper function that takes a set of layers, new device poses, a scratch * Helper function that takes a set of layers, new device poses, a scratch
@ -150,6 +324,8 @@ comp_render_cs_stereo_layers_to_scratch(struct render_compute *crc,
* layers should it not be possible to do a fast_path. Will insert barriers to * layers should it not be possible to do a fast_path. Will insert barriers to
* change the scratch images and target images to the needed layout. * change the scratch images and target images to the needed layout.
* *
* Currently limited to exactly two views.
*
* Expected layouts: * Expected layouts:
* * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL * * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
* * Sratch images: Any * * Sratch images: Any
@ -164,16 +340,9 @@ comp_render_cs_stereo_layers_to_scratch(struct render_compute *crc,
*/ */
void void
comp_render_cs_dispatch(struct render_compute *crc, comp_render_cs_dispatch(struct render_compute *crc,
struct render_scratch_images *rsi,
struct xrt_pose world_poses[2],
struct xrt_pose eye_poses[2],
const struct comp_layer *layers, const struct comp_layer *layers,
const uint32_t layer_count, const uint32_t layer_count,
VkImage target_image, const struct comp_render_dispatch_data *d);
VkImageView target_image_view,
const struct render_viewport_data views[2],
bool fast_path,
bool do_timewarp);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -1,4 +1,4 @@
// Copyright 2019-2023, Collabora, Ltd. // Copyright 2019-2024, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
/*! /*!
* @file * @file
@ -307,6 +307,7 @@ do_cs_cylinder_layer(const struct xrt_layer_data *data,
*out_cur_image = cur_image; *out_cur_image = cur_image;
} }
/* /*
* *
* Compute distortion helpers. * Compute distortion helpers.
@ -314,47 +315,87 @@ do_cs_cylinder_layer(const struct xrt_layer_data *data,
*/ */
static void static void
do_cs_distortion_for_scratch(struct render_compute *crc, do_cs_clear(struct render_compute *crc, const struct comp_render_dispatch_data *d)
struct render_scratch_images *rsi,
VkImage target_image,
VkImageView target_image_view,
const struct render_viewport_data views[2])
{ {
VkSampler sampler = crc->r->samplers.clamp_to_border_black; // Hardcoded to two views.
if (d->view_count != 2) {
U_LOG_E("Only supports exactly 2 views!");
assert(d->view_count == 2);
return;
}
VkImageView src_image_views[2] = { const struct render_viewport_data target_viewport_datas[2] = {
rsi->color[0].srgb_view, // Read with gamma curve. d->views[0].target_viewport_data,
rsi->color[1].srgb_view, d->views[1].target_viewport_data,
};
VkSampler src_samplers[2] = {sampler, sampler};
struct xrt_normalized_rect src_norm_rects[2] = {
{.x = 0.0f, .y = 0.0f, .w = 1.0f, .h = 1.0f},
{.x = 0.0f, .y = 0.0f, .w = 1.0f, .h = 1.0f},
}; };
render_compute_projection( // render_compute_clear( //
crc, // crc, // crc
src_samplers, // d->cs.target_image, // target_image
src_image_views, // d->cs.target_unorm_view, // target_image_view
src_norm_rects, // target_viewport_datas); // views
target_image, //
target_image_view, //
views //
);
} }
static void static void
do_cs_distortion_for_layer(struct render_compute *crc, do_cs_distortion_from_scratch(struct render_compute *crc, const struct comp_render_dispatch_data *d)
const struct xrt_pose world_poses[2],
const struct comp_layer *layer,
const struct xrt_layer_projection_view_data *lvd,
const struct xrt_layer_projection_view_data *rvd,
VkImage target_image,
VkImageView target_image_view,
const struct render_viewport_data views[2],
bool do_timewarp)
{ {
// Hardcoded to two views.
if (d->view_count != 2) {
U_LOG_E("Only supports exactly 2 views!");
assert(d->view_count == 2);
return;
}
VkSampler clamp_to_border_black = crc->r->samplers.clamp_to_border_black;
struct render_viewport_data target_viewport_datas[2];
VkImageView src_image_views[2];
VkSampler src_samplers[2];
struct xrt_normalized_rect src_norm_rects[2];
for (uint32_t i = 0; i < d->view_count; i++) {
// Data to be filled in.
struct render_viewport_data viewport_data;
VkImageView src_image_view;
struct xrt_normalized_rect src_norm_rect;
// Gather data.
viewport_data = d->views[i].target_viewport_data,
src_image_view = d->views[i].srgb_view; // Read with gamma curve.
src_norm_rect = d->views[i].layer_norm_rect;
// Fill in data.
target_viewport_datas[i] = viewport_data;
src_image_views[i] = src_image_view;
src_samplers[i] = clamp_to_border_black;
src_norm_rects[i] = src_norm_rect;
}
render_compute_projection( //
crc, // crc
src_samplers, // src_samplers
src_image_views, // src_image_views
src_norm_rects, // src_rects
d->cs.target_image, // target_image
d->cs.target_unorm_view, // target_image_view
target_viewport_datas); // views
}
static void
do_cs_distortion_from_stereo_layer(struct render_compute *crc,
const struct comp_layer *layer,
const struct xrt_layer_projection_view_data *lvd,
const struct xrt_layer_projection_view_data *rvd,
const struct comp_render_dispatch_data *d)
{
// Hardcoded to two views.
if (d->view_count != 2) {
U_LOG_E("Only supports exactly 2 views!");
assert(d->view_count == 2);
return;
}
// Fetch from this data.
const struct xrt_layer_data *data = &layer->data; const struct xrt_layer_data *data = &layer->data;
uint32_t left_array_index = lvd->sub.array_index; uint32_t left_array_index = lvd->sub.array_index;
uint32_t right_array_index = rvd->sub.array_index; uint32_t right_array_index = rvd->sub.array_index;
@ -362,44 +403,68 @@ do_cs_distortion_for_layer(struct render_compute *crc,
const struct comp_swapchain_image *right = &layer->sc_array[1]->images[rvd->sub.image_index]; const struct comp_swapchain_image *right = &layer->sc_array[1]->images[rvd->sub.image_index];
VkSampler clamp_to_border_black = crc->r->samplers.clamp_to_border_black; VkSampler clamp_to_border_black = crc->r->samplers.clamp_to_border_black;
VkSampler src_samplers[2] = {
clamp_to_border_black,
clamp_to_border_black,
};
VkImageView src_image_views[2] = { // Data to fill in.
get_image_view(left, data->flags, left_array_index), struct xrt_pose world_poses[2];
get_image_view(right, data->flags, right_array_index), struct render_viewport_data target_viewport_datas[2];
}; struct xrt_normalized_rect src_norm_rects[2];
struct xrt_pose src_poses[2];
struct xrt_fov src_fovs[2];
VkSampler src_samplers[2];
VkImageView src_image_views[2];
struct xrt_normalized_rect src_norm_rects[2] = {lvd->sub.norm_rect, rvd->sub.norm_rect}; for (uint32_t i = 0; i < d->view_count; i++) {
if (data->flip_y) {
src_norm_rects[0].h = -src_norm_rects[0].h; struct xrt_pose world_pose;
src_norm_rects[0].y = 1 + src_norm_rects[0].y; struct render_viewport_data viewport_data;
src_norm_rects[1].h = -src_norm_rects[1].h; struct xrt_pose src_pose;
src_norm_rects[1].y = 1 + src_norm_rects[1].y; struct xrt_fov src_fov;
struct xrt_normalized_rect src_norm_rect;
VkImageView src_image_view;
// Gather data.
world_pose = d->views[i].world_pose;
viewport_data = d->views[i].target_viewport_data;
if (!is_view_index_right(i)) {
// Left, aka not right.
src_pose = lvd->pose;
src_fov = lvd->fov;
src_norm_rect = lvd->sub.norm_rect;
src_image_view = get_image_view(left, data->flags, left_array_index);
} else {
// Right
src_pose = rvd->pose;
src_fov = rvd->fov;
src_norm_rect = rvd->sub.norm_rect;
src_image_view = get_image_view(right, data->flags, right_array_index);
}
if (data->flip_y) {
src_norm_rect.h = -src_norm_rect.h;
src_norm_rect.y = 1 + src_norm_rect.y;
}
// Fill in data.
world_poses[i] = world_pose;
target_viewport_datas[i] = viewport_data;
src_norm_rects[i] = src_norm_rect;
src_poses[i] = src_pose;
src_fovs[i] = src_fov;
src_samplers[i] = clamp_to_border_black;
src_image_views[i] = src_image_view;
} }
if (!do_timewarp) { if (!d->do_timewarp) {
render_compute_projection( // render_compute_projection( //
crc, // crc, //
src_samplers, // src_samplers, //
src_image_views, // src_image_views, //
src_norm_rects, // src_norm_rects, //
target_image, // d->cs.target_image, //
target_image_view, // d->cs.target_unorm_view, //
views); // target_viewport_datas); //
} else { } else {
struct xrt_pose src_poses[2] = {
lvd->pose,
rvd->pose,
};
struct xrt_fov src_fovs[2] = {
lvd->fov,
rvd->fov,
};
render_compute_projection_timewarp( // render_compute_projection_timewarp( //
crc, // crc, //
src_samplers, // src_samplers, //
@ -408,9 +473,9 @@ do_cs_distortion_for_layer(struct render_compute *crc,
src_poses, // src_poses, //
src_fovs, // src_fovs, //
world_poses, // world_poses, //
target_image, // d->cs.target_image, //
target_image_view, // d->cs.target_unorm_view, //
views); // target_viewport_datas); //
} }
} }
@ -597,150 +662,62 @@ comp_render_cs_layer(struct render_compute *crc,
} }
void void
comp_render_cs_stereo_layers(struct render_compute *crc, comp_render_cs_layers(struct render_compute *crc,
const struct comp_layer *layers, const struct comp_layer *layers,
const uint32_t layer_count, const uint32_t layer_count,
const struct xrt_normalized_rect pre_transforms[2], const struct comp_render_dispatch_data *d,
const struct xrt_pose world_poses[2], VkImageLayout transition_to)
const struct xrt_pose eye_poses[2],
const VkImage target_images[2],
const VkImageView target_image_views[2],
const struct render_viewport_data target_views[2],
VkImageLayout transition_to,
bool do_timewarp)
{ {
VkImageSubresourceRange first_color_level_subresource_range = { cmd_barrier_view_images( //
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, crc->r->vk, //
.baseMipLevel = 0, d, //
.levelCount = 1, crc->r->cmd, // cmd
.baseArrayLayer = 0, 0, // src_access_mask
.layerCount = 1, VK_ACCESS_SHADER_WRITE_BIT, // dst_access_mask
}; VK_IMAGE_LAYOUT_UNDEFINED, // transition_from
VK_IMAGE_LAYOUT_GENERAL, // transition_to
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // src_stage_mask
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); // dst_stage_mask
vk_cmd_image_barrier_gpu_locked( // for (uint32_t view_index = 0; view_index < d->view_count; view_index++) {
crc->r->vk, // const struct comp_render_view_data *view = &d->views[view_index];
crc->r->cmd, //
target_images[0], //
0, //
VK_ACCESS_SHADER_WRITE_BIT, //
VK_IMAGE_LAYOUT_UNDEFINED, //
VK_IMAGE_LAYOUT_GENERAL, //
first_color_level_subresource_range); //
if (target_images[0] != target_images[1]) { comp_render_cs_layer( //
vk_cmd_image_barrier_gpu_locked( // crc, //
crc->r->vk, // view_index, //
crc->r->cmd, // layers, //
target_images[1], // layer_count, //
0, // &view->target_pre_transform, //
VK_ACCESS_SHADER_WRITE_BIT, // &view->world_pose, //
VK_IMAGE_LAYOUT_UNDEFINED, // &view->eye_pose, //
VK_IMAGE_LAYOUT_GENERAL, // view->image, //
first_color_level_subresource_range); // view->cs.unorm_view, //
&view->layer_viewport_data, //
d->do_timewarp); //
} }
for (uint32_t view_index = 0; view_index < 2; view_index++) { cmd_barrier_view_images( //
comp_render_cs_layer( // crc->r->vk, //
crc, // d, //
view_index, // crc->r->cmd, // cmd
layers, // VK_ACCESS_SHADER_WRITE_BIT, // src_access_mask
layer_count, // VK_ACCESS_MEMORY_READ_BIT, // dst_access_mask
&pre_transforms[view_index], // VK_IMAGE_LAYOUT_GENERAL, // transition_from
&world_poses[view_index], // transition_to, // transition_to
&eye_poses[view_index], // VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // src_stage_mask
target_images[view_index], // VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); // dst_stage_mask
target_image_views[view_index], //
&target_views[view_index], //
do_timewarp); //
}
vk_cmd_image_barrier_locked( //
crc->r->vk, //
crc->r->cmd, //
target_images[0], //
VK_ACCESS_SHADER_WRITE_BIT, //
VK_ACCESS_MEMORY_READ_BIT, //
VK_IMAGE_LAYOUT_GENERAL, //
transition_to, //
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, //
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, //
first_color_level_subresource_range); //
if (target_images[0] != target_images[1]) {
vk_cmd_image_barrier_locked( //
crc->r->vk, //
crc->r->cmd, //
target_images[1], //
VK_ACCESS_SHADER_WRITE_BIT, //
VK_ACCESS_MEMORY_READ_BIT, //
VK_IMAGE_LAYOUT_GENERAL, //
transition_to, //
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, //
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, //
first_color_level_subresource_range); //
}
}
void
comp_render_cs_stereo_layers_to_scratch(struct render_compute *crc,
const struct xrt_normalized_rect pre_transforms[2],
struct xrt_pose world_poses[2],
struct xrt_pose eye_poses[2],
const struct comp_layer *layers,
const uint32_t layer_count,
struct render_scratch_images *rsi,
VkImageLayout transition_to,
bool do_timewarp)
{
struct render_viewport_data target_views[2] = {
{.w = rsi->extent.width, .h = rsi->extent.height},
{.w = rsi->extent.width, .h = rsi->extent.height},
};
VkImage target_images[2] = {
rsi->color[0].image,
rsi->color[1].image,
};
VkImageView target_image_views[2] = {
rsi->color[0].unorm_view, // Have to write in linear
rsi->color[1].unorm_view,
};
comp_render_cs_stereo_layers( //
crc, // crc
layers, // layers
layer_count, // layer_count
pre_transforms, // pre_transforms
world_poses, // world_poses
eye_poses, // eye_poses
target_images, // target_images
target_image_views, // target_image_views
target_views, // target_views
transition_to, // transition_to
do_timewarp); // do_timewarp
} }
void void
comp_render_cs_dispatch(struct render_compute *crc, comp_render_cs_dispatch(struct render_compute *crc,
struct render_scratch_images *rsi,
struct xrt_pose world_poses[2],
struct xrt_pose eye_poses[2],
const struct comp_layer *layers, const struct comp_layer *layers,
const uint32_t layer_count, const uint32_t layer_count,
VkImage target_image, const struct comp_render_dispatch_data *d)
VkImageView target_image_view,
const struct render_viewport_data views[2],
bool fast_path,
bool do_timewarp)
{ {
assert(!fast_path || layer_count > 0); // Convenience.
bool fast_path = d->fast_path;
// We make an assumption that we will be using the distortion code. assert(!fast_path || layer_count > 0);
const struct xrt_normalized_rect pre_transforms[2] = {
crc->r->distortion.uv_to_tanangle[0],
crc->r->distortion.uv_to_tanangle[1],
};
// We want to read from the images afterwards. // We want to read from the images afterwards.
VkImageLayout transition_to = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkImageLayout transition_to = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@ -752,16 +729,12 @@ comp_render_cs_dispatch(struct render_compute *crc,
const struct xrt_layer_projection_view_data *lvd = &stereo->l; const struct xrt_layer_projection_view_data *lvd = &stereo->l;
const struct xrt_layer_projection_view_data *rvd = &stereo->r; const struct xrt_layer_projection_view_data *rvd = &stereo->r;
do_cs_distortion_for_layer( // do_cs_distortion_from_stereo_layer( //
crc, // crc crc, // crc
world_poses, // world_poses layer, // layer
layer, // layer lvd, // lvd
lvd, // lvd rvd, // rvd
rvd, // rvd d); // d
target_image, // target_image
target_image_view, // target_image_view
views, // views
do_timewarp); // do_timewarp
} else if (fast_path && layers[0].data.type == XRT_LAYER_STEREO_PROJECTION_DEPTH) { } else if (fast_path && layers[0].data.type == XRT_LAYER_STEREO_PROJECTION_DEPTH) {
int i = 0; int i = 0;
const struct comp_layer *layer = &layers[i]; const struct comp_layer *layer = &layers[i];
@ -769,39 +742,26 @@ comp_render_cs_dispatch(struct render_compute *crc,
const struct xrt_layer_projection_view_data *lvd = &stereo->l; const struct xrt_layer_projection_view_data *lvd = &stereo->l;
const struct xrt_layer_projection_view_data *rvd = &stereo->r; const struct xrt_layer_projection_view_data *rvd = &stereo->r;
do_cs_distortion_for_layer( // do_cs_distortion_from_stereo_layer( //
crc, // crc crc, // crc
world_poses, // world_poses layer, // layer
layer, // layer lvd, // lvd
lvd, // lvd rvd, // rvd
rvd, // rvd d); // d
target_image, // target_image
target_image_view, // target_image_view
views, // views
do_timewarp); // do_timewarp
} else if (layer_count > 0) { } else if (layer_count > 0) {
comp_render_cs_stereo_layers_to_scratch( // comp_render_cs_layers( //
crc, //
pre_transforms, //
world_poses, //
eye_poses, //
layers, //
layer_count, //
rsi, //
transition_to, //
do_timewarp); //
do_cs_distortion_for_scratch( //
crc, //
rsi, //
target_image, //
target_image_view, //
views); //
} else {
render_compute_clear( //
crc, // crc, //
target_image, // layers, //
target_image_view, // layer_count, //
views); // d, //
transition_to); //
do_cs_distortion_from_scratch( //
crc, //
d); //
} else {
do_cs_clear( //
crc, //
d); //
} }
} }

View file

@ -1,4 +1,4 @@
// Copyright 2023, Collabora, Ltd. // Copyright 2023-2024, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
/*! /*!
* @file * @file
@ -30,9 +30,9 @@
*/ */
/* /*
* Internal state for a single view. * Internal per-view for the layer shashing render step.
*/ */
struct gfx_view_state struct gfx_layer_view_state
{ {
// Filled out descriptor sets. // Filled out descriptor sets.
VkDescriptorSet descriptor_sets[RENDER_MAX_LAYERS]; VkDescriptorSet descriptor_sets[RENDER_MAX_LAYERS];
@ -64,6 +64,43 @@ struct gfx_view_state
struct xrt_matrix_4x4 eye_vp_rot_only; struct xrt_matrix_4x4 eye_vp_rot_only;
}; };
/*
* Internal state for the layer squashing render step.
*/
struct gfx_layer_state
{
struct gfx_layer_view_state views[2];
};
/*
* Internal state for the mesh rendering step.
*/
struct gfx_mesh_state
{
VkDescriptorSet descriptor_sets[2];
};
/*
* Per-view input data for the mesh rendering step.
*/
struct gfx_mesh_view_data
{
struct xrt_pose src_pose;
struct xrt_fov src_fov;
struct xrt_normalized_rect src_norm_rect;
VkSampler src_sampler;
VkImageView src_image_view;
};
/*
* Input data for the mesh rendering step,
* combined with comp_render_dispatch_data.
*/
struct gfx_mesh_data
{
struct gfx_mesh_view_data views[2];
};
/* /*
* *
@ -80,6 +117,30 @@ static const VkClearColorValue background_color_active = {
}; };
/*
*
* Input builder functions.
*
*/
inline static void
gfx_mesh_add_view(struct gfx_mesh_data *md,
uint32_t view_index,
const struct xrt_pose *src_pose,
const struct xrt_fov *src_fov,
const struct xrt_normalized_rect *src_norm_rect,
VkSampler src_sampler,
VkImageView src_image_view)
{
md->views[view_index].src_pose = *src_pose;
md->views[view_index].src_fov = *src_fov;
md->views[view_index].src_norm_rect = *src_norm_rect;
md->views[view_index].src_sampler = src_sampler;
md->views[view_index].src_image_view = src_image_view;
}
/* /*
* *
* Model view projection helper functions. * Model view projection helper functions.
@ -87,7 +148,7 @@ static const VkClearColorValue background_color_active = {
*/ */
static inline void static inline void
calc_mvp_full(struct gfx_view_state *state, calc_mvp_full(struct gfx_layer_view_state *state,
const struct xrt_layer_data *layer_data, const struct xrt_layer_data *layer_data,
const struct xrt_pose *pose, const struct xrt_pose *pose,
const struct xrt_vec3 *scale, const struct xrt_vec3 *scale,
@ -104,7 +165,7 @@ calc_mvp_full(struct gfx_view_state *state,
} }
static inline void static inline void
calc_mv_inv_full(struct gfx_view_state *state, calc_mv_inv_full(struct gfx_layer_view_state *state,
const struct xrt_layer_data *layer_data, const struct xrt_layer_data *layer_data,
const struct xrt_pose *pose, const struct xrt_pose *pose,
const struct xrt_vec3 *scale, const struct xrt_vec3 *scale,
@ -127,7 +188,7 @@ calc_mv_inv_full(struct gfx_view_state *state,
} }
static inline void static inline void
calc_mvp_rot_only(struct gfx_view_state *state, calc_mvp_rot_only(struct gfx_layer_view_state *state,
const struct xrt_layer_data *data, const struct xrt_layer_data *data,
const struct xrt_pose *pose, const struct xrt_pose *pose,
const struct xrt_vec3 *scale, const struct xrt_vec3 *scale,
@ -155,7 +216,7 @@ calc_mvp_rot_only(struct gfx_view_state *state,
*/ */
static inline void static inline void
add_layer(struct gfx_view_state *state, const struct xrt_layer_data *data, VkDescriptorSet descriptor_set) add_layer(struct gfx_layer_view_state *state, const struct xrt_layer_data *data, VkDescriptorSet descriptor_set)
{ {
uint32_t cur_layer = state->layer_count++; uint32_t cur_layer = state->layer_count++;
state->descriptor_sets[cur_layer] = descriptor_set; state->descriptor_sets[cur_layer] = descriptor_set;
@ -169,7 +230,7 @@ do_cylinder_layer(struct render_gfx *rr,
uint32_t view_index, uint32_t view_index,
VkSampler clamp_to_edge, VkSampler clamp_to_edge,
VkSampler clamp_to_border_black, VkSampler clamp_to_border_black,
struct gfx_view_state *state) struct gfx_layer_view_state *state)
{ {
const struct xrt_layer_data *layer_data = &layer->data; const struct xrt_layer_data *layer_data = &layer->data;
const struct xrt_layer_cylinder_data *c = &layer_data->cylinder; const struct xrt_layer_cylinder_data *c = &layer_data->cylinder;
@ -233,7 +294,7 @@ do_equirect2_layer(struct render_gfx *rr,
uint32_t view_index, uint32_t view_index,
VkSampler clamp_to_edge, VkSampler clamp_to_edge,
VkSampler clamp_to_border_black, VkSampler clamp_to_border_black,
struct gfx_view_state *state) struct gfx_layer_view_state *state)
{ {
const struct xrt_layer_data *layer_data = &layer->data; const struct xrt_layer_data *layer_data = &layer->data;
const struct xrt_layer_equirect2_data *eq2 = &layer_data->equirect2; const struct xrt_layer_equirect2_data *eq2 = &layer_data->equirect2;
@ -297,7 +358,7 @@ do_projection_layer(struct render_gfx *rr,
uint32_t view_index, uint32_t view_index,
VkSampler clamp_to_edge, VkSampler clamp_to_edge,
VkSampler clamp_to_border_black, VkSampler clamp_to_border_black,
struct gfx_view_state *state) struct gfx_layer_view_state *state)
{ {
const struct xrt_layer_data *layer_data = &layer->data; const struct xrt_layer_data *layer_data = &layer->data;
const struct xrt_layer_projection_view_data *vd = NULL; const struct xrt_layer_projection_view_data *vd = NULL;
@ -359,7 +420,7 @@ do_quad_layer(struct render_gfx *rr,
uint32_t view_index, uint32_t view_index,
VkSampler clamp_to_edge, VkSampler clamp_to_edge,
VkSampler clamp_to_border_black, VkSampler clamp_to_border_black,
struct gfx_view_state *state) struct gfx_layer_view_state *state)
{ {
const struct xrt_layer_data *layer_data = &layer->data; const struct xrt_layer_data *layer_data = &layer->data;
const struct xrt_layer_quad_data *q = &layer_data->quad; const struct xrt_layer_quad_data *q = &layer_data->quad;
@ -406,13 +467,9 @@ do_quad_layer(struct render_gfx *rr,
static void static void
do_layers(struct render_gfx *rr, do_layers(struct render_gfx *rr,
struct render_gfx_target_resources rtrs[2],
const struct render_viewport_data viewport_datas[2],
const struct xrt_fov new_fovs[2],
const struct xrt_pose world_poses[2],
const struct xrt_pose eye_poses[2],
const struct comp_layer *layers, const struct comp_layer *layers,
uint32_t layer_count) uint32_t layer_count,
const struct comp_render_dispatch_data *d)
{ {
COMP_TRACE_MARKER(); COMP_TRACE_MARKER();
@ -420,37 +477,45 @@ do_layers(struct render_gfx *rr,
VkResult ret; VkResult ret;
// Hardcoded to stereo. // Hardcoded to stereo.
struct gfx_view_state views[2] = XRT_STRUCT_INIT; struct gfx_layer_state ls = XRT_STRUCT_INIT;
for (uint32_t view = 0; view < ARRAY_SIZE(views); view++) { for (uint32_t view = 0; view < d->view_count; view++) {
// Data for this view, convenience.
const struct xrt_pose world_pose = d->views[view].world_pose;
const struct xrt_pose eye_pose = d->views[view].eye_pose;
const struct xrt_fov new_fov = d->views[view].fov;
// Current state we are writing to.
struct gfx_layer_view_state *state = &ls.views[view];
// Used to go from UV to tangent space. // Used to go from UV to tangent space.
render_calc_uv_to_tangent_lengths_rect(&new_fovs[view], &views[view].to_tangent); render_calc_uv_to_tangent_lengths_rect(&new_fov, &state->to_tangent);
// Projection // Projection
struct xrt_matrix_4x4 p; struct xrt_matrix_4x4 p;
math_matrix_4x4_projection_vulkan_infinite_reverse(&new_fovs[view], 0.1, &p); math_matrix_4x4_projection_vulkan_infinite_reverse(&new_fov, 0.1, &p);
// Reused view matrix. // Reused view matrix.
struct xrt_matrix_4x4 v; struct xrt_matrix_4x4 v;
// World // World
math_matrix_4x4_view_from_pose(&world_poses[view], &v); math_matrix_4x4_view_from_pose(&world_pose, &v);
math_matrix_4x4_multiply(&p, &v, &views[view].world_vp_full); math_matrix_4x4_multiply(&p, &v, &state->world_vp_full);
math_matrix_4x4_inverse(&v, &views[view].world_v_inv_full); math_matrix_4x4_inverse(&v, &state->world_v_inv_full);
struct xrt_pose world_rot_only = {world_poses[view].orientation, XRT_VEC3_ZERO}; struct xrt_pose world_rot_only = {world_pose.orientation, XRT_VEC3_ZERO};
math_matrix_4x4_view_from_pose(&world_rot_only, &v); math_matrix_4x4_view_from_pose(&world_rot_only, &v);
math_matrix_4x4_multiply(&p, &v, &views[view].world_vp_rot_only); math_matrix_4x4_multiply(&p, &v, &state->world_vp_rot_only);
// Eye // Eye
math_matrix_4x4_view_from_pose(&eye_poses[view], &v); math_matrix_4x4_view_from_pose(&eye_pose, &v);
math_matrix_4x4_multiply(&p, &v, &views[view].eye_vp_full); math_matrix_4x4_multiply(&p, &v, &state->eye_vp_full);
math_matrix_4x4_inverse(&v, &views[view].eye_v_inv_full); math_matrix_4x4_inverse(&v, &state->eye_v_inv_full);
struct xrt_pose eye_rot_only = {eye_poses[view].orientation, XRT_VEC3_ZERO}; struct xrt_pose eye_rot_only = {eye_pose.orientation, XRT_VEC3_ZERO};
math_matrix_4x4_view_from_pose(&eye_rot_only, &v); math_matrix_4x4_view_from_pose(&eye_rot_only, &v);
math_matrix_4x4_multiply(&p, &v, &views[view].eye_vp_rot_only); math_matrix_4x4_multiply(&p, &v, &state->eye_vp_rot_only);
} }
/* /*
@ -464,7 +529,11 @@ do_layers(struct render_gfx *rr,
VkSampler clamp_to_edge = rr->r->samplers.clamp_to_edge; VkSampler clamp_to_edge = rr->r->samplers.clamp_to_edge;
VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black; VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black;
for (uint32_t view = 0; view < ARRAY_SIZE(views); view++) { for (uint32_t view = 0; view < d->view_count; view++) {
// Source for data and written to as well, read and write.
struct gfx_layer_view_state *state = &ls.views[view];
for (uint32_t i = 0; i < layer_count; i++) { for (uint32_t i = 0; i < layer_count; i++) {
const struct xrt_layer_data *data = &layers[i].data; const struct xrt_layer_data *data = &layers[i].data;
if (!is_layer_view_visible(data, view)) { if (!is_layer_view_visible(data, view)) {
@ -479,7 +548,7 @@ do_layers(struct render_gfx *rr,
view, // view_index view, // view_index
clamp_to_edge, // clamp_to_edge clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black clamp_to_border_black, // clamp_to_border_black
&views[view]); // state state); // state
VK_CHK_WITH_GOTO(ret, "do_cylinder_layer", err_layer); VK_CHK_WITH_GOTO(ret, "do_cylinder_layer", err_layer);
break; break;
case XRT_LAYER_EQUIRECT2: case XRT_LAYER_EQUIRECT2:
@ -489,7 +558,7 @@ do_layers(struct render_gfx *rr,
view, // view_index view, // view_index
clamp_to_edge, // clamp_to_edge clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black clamp_to_border_black, // clamp_to_border_black
&views[view]); // state state); // state
VK_CHK_WITH_GOTO(ret, "do_equirect2_layer", err_layer); VK_CHK_WITH_GOTO(ret, "do_equirect2_layer", err_layer);
break; break;
case XRT_LAYER_STEREO_PROJECTION: case XRT_LAYER_STEREO_PROJECTION:
@ -500,7 +569,7 @@ do_layers(struct render_gfx *rr,
view, // view_index view, // view_index
clamp_to_edge, // clamp_to_edge clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black clamp_to_border_black, // clamp_to_border_black
&views[view]); // state state); // state
VK_CHK_WITH_GOTO(ret, "do_projection_layer", err_layer); VK_CHK_WITH_GOTO(ret, "do_projection_layer", err_layer);
break; break;
case XRT_LAYER_QUAD: case XRT_LAYER_QUAD:
@ -510,7 +579,7 @@ do_layers(struct render_gfx *rr,
view, // view_index view, // view_index
clamp_to_edge, // clamp_to_edge clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black clamp_to_border_black, // clamp_to_border_black
&views[view]); // state state); // state
VK_CHK_WITH_GOTO(ret, "do_quad_layer", err_layer); VK_CHK_WITH_GOTO(ret, "do_quad_layer", err_layer);
break; break;
default: break; default: break;
@ -525,18 +594,23 @@ do_layers(struct render_gfx *rr,
const VkClearColorValue *color = layer_count == 0 ? &background_color_idle : &background_color_active; const VkClearColorValue *color = layer_count == 0 ? &background_color_idle : &background_color_active;
for (uint32_t view = 0; view < ARRAY_SIZE(views); view++) { for (uint32_t view = 0; view < d->view_count; view++) {
render_gfx_begin_target( //
rr, //
&rtrs[view], //
color); //
render_gfx_begin_view( // // Convenience.
const struct render_viewport_data *viewport_data = &d->views[view].layer_viewport_data;
render_gfx_begin_target( //
rr, // rr, //
view, // view_index d->views[view].gfx.rtr, //
&viewport_datas[view]); // viewport_data color); //
struct gfx_view_state *state = &views[view]; render_gfx_begin_view( //
rr, //
view, // view_index
viewport_data); // viewport_data
// Only source for data here, read only.
const struct gfx_layer_view_state *state = &ls.views[view];
for (uint32_t i = 0; i < state->layer_count; i++) { for (uint32_t i = 0; i < state->layer_count; i++) {
switch (state->types[i]) { switch (state->types[i]) {
@ -591,16 +665,9 @@ err_layer:
static void static void
do_mesh(struct render_gfx *rr, do_mesh(struct render_gfx *rr,
struct render_gfx_target_resources *rtr, bool do_timewarp,
const struct render_viewport_data viewport_datas[2], const struct gfx_mesh_data *md,
const struct xrt_matrix_2x2 vertex_rots[2], const struct comp_render_dispatch_data *d)
VkSampler src_samplers[2],
VkImageView src_image_views[2],
const struct xrt_normalized_rect src_norm_rects[2],
const struct xrt_pose src_poses[2],
const struct xrt_fov src_fovs[2],
const struct xrt_pose new_poses[2],
bool do_timewarp)
{ {
struct vk_bundle *vk = rr->r->vk; struct vk_bundle *vk = rr->r->vk;
VkResult ret; VkResult ret;
@ -611,34 +678,35 @@ do_mesh(struct render_gfx *rr,
* write a copy command before the other gfx commands. * write a copy command before the other gfx commands.
*/ */
VkDescriptorSet descriptor_sets[2] = XRT_STRUCT_INIT; struct gfx_mesh_state ms = XRT_STRUCT_INIT;
for (uint32_t i = 0; i < 2; i++) {
for (uint32_t i = 0; i < d->view_count; i++) {
struct render_gfx_mesh_ubo_data data = { struct render_gfx_mesh_ubo_data data = {
.vertex_rot = vertex_rots[i], .vertex_rot = d->views[i].gfx.vertex_rot,
.post_transform = src_norm_rects[i], .post_transform = md->views[i].src_norm_rect,
}; };
// Extra arguments for timewarp. // Extra arguments for timewarp.
if (do_timewarp) { if (do_timewarp) {
data.pre_transform = rr->r->distortion.uv_to_tanangle[i]; data.pre_transform = d->views[i].target_pre_transform;
render_calc_time_warp_matrix( // render_calc_time_warp_matrix( //
&src_poses[i], // &md->views[i].src_pose, //
&src_fovs[i], // &md->views[i].src_fov, //
&new_poses[i], // &d->views[i].world_pose, //
&data.transform); // &data.transform); //
} }
ret = render_gfx_mesh_alloc_and_write( // ret = render_gfx_mesh_alloc_and_write( //
rr, // rr, //
&data, // &data, //
src_samplers[i], // md->views[i].src_sampler, //
src_image_views[i], // md->views[i].src_image_view, //
&descriptor_sets[i]); // &ms.descriptor_sets[i]); //
VK_CHK_WITH_GOTO(ret, "render_gfx_mesh_alloc", err_no_memory); VK_CHK_WITH_GOTO(ret, "render_gfx_mesh_alloc", err_no_memory);
VK_NAME_DESCRIPTOR_SET(vk, descriptor_sets[i], "render_gfx mesh descriptor sets"); VK_NAME_DESCRIPTOR_SET(vk, ms.descriptor_sets[i], "render_gfx mesh descriptor sets");
} }
@ -648,20 +716,23 @@ do_mesh(struct render_gfx *rr,
render_gfx_begin_target( // render_gfx_begin_target( //
rr, // rr, //
rtr, // d->gfx.rtr, //
&background_color_active); // &background_color_active); //
for (uint32_t i = 0; i < 2; i++) { for (uint32_t i = 0; i < d->view_count; i++) {
render_gfx_begin_view( // // Convenience.
rr, // const struct render_viewport_data *viewport_data = &d->views[i].target_viewport_data;
i, // view_index
&viewport_datas[i]); // viewport_data
render_gfx_mesh_draw( // render_gfx_begin_view( //
rr, // rr rr, //
i, // mesh_index i, // view_index
descriptor_sets[i], // descriptor_set viewport_data); // viewport_data
do_timewarp); // do_timewarp
render_gfx_mesh_draw( //
rr, // rr
i, // mesh_index
ms.descriptor_sets[i], // descriptor_set
do_timewarp); // do_timewarp
render_gfx_end_view(rr); render_gfx_end_view(rr);
} }
@ -677,14 +748,10 @@ err_no_memory:
static void static void
do_mesh_from_proj(struct render_gfx *rr, do_mesh_from_proj(struct render_gfx *rr,
struct render_gfx_target_resources *rts, const struct comp_render_dispatch_data *d,
const struct render_viewport_data viewport_datas[2],
const struct xrt_matrix_2x2 vertex_rots[2],
const struct comp_layer *layer, const struct comp_layer *layer,
const struct xrt_layer_projection_view_data *lvd, const struct xrt_layer_projection_view_data *lvd,
const struct xrt_layer_projection_view_data *rvd, const struct xrt_layer_projection_view_data *rvd)
const struct xrt_pose new_poses[2],
bool do_timewarp)
{ {
const struct xrt_layer_data *data = &layer->data; const struct xrt_layer_data *data = &layer->data;
const uint32_t left_array_index = lvd->sub.array_index; const uint32_t left_array_index = lvd->sub.array_index;
@ -692,58 +759,68 @@ do_mesh_from_proj(struct render_gfx *rr,
const struct comp_swapchain_image *left = &layer->sc_array[0]->images[lvd->sub.image_index]; const struct comp_swapchain_image *left = &layer->sc_array[0]->images[lvd->sub.image_index];
const struct comp_swapchain_image *right = &layer->sc_array[1]->images[rvd->sub.image_index]; const struct comp_swapchain_image *right = &layer->sc_array[1]->images[rvd->sub.image_index];
struct xrt_normalized_rect src_norm_rects[2] = {lvd->sub.norm_rect, rvd->sub.norm_rect}; VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black;
if (data->flip_y) {
src_norm_rects[0].h = -src_norm_rects[0].h; struct gfx_mesh_data md = XRT_STRUCT_INIT;
src_norm_rects[0].y = 1 + src_norm_rects[0].y; for (uint32_t i = 0; i < d->view_count; i++) {
src_norm_rects[1].h = -src_norm_rects[1].h;
src_norm_rects[1].y = 1 + src_norm_rects[1].y; struct xrt_pose src_pose;
struct xrt_fov src_fov;
struct xrt_normalized_rect src_norm_rect;
VkImageView src_image_view;
if (!is_view_index_right(i)) {
// Left, aka not right.
src_pose = lvd->pose;
src_fov = lvd->fov;
src_norm_rect = lvd->sub.norm_rect;
src_image_view = get_image_view(left, data->flags, left_array_index);
} else {
// Right
src_pose = rvd->pose;
src_fov = rvd->fov;
src_norm_rect = rvd->sub.norm_rect;
src_image_view = get_image_view(right, data->flags, right_array_index);
}
if (data->flip_y) {
src_norm_rect.h = -src_norm_rect.h;
src_norm_rect.y = 1 + src_norm_rect.y;
}
gfx_mesh_add_view( //
&md, // md
i, // view_index
&src_pose, // src_pose
&src_fov, // src_fov
&src_norm_rect, // src_norm_rect
clamp_to_border_black, // src_sampler
src_image_view); // src_image_view
} }
VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black; do_mesh( //
VkSampler src_samplers[2] = { rr, //
clamp_to_border_black, d->do_timewarp, //
clamp_to_border_black, &md, //
}; d); //
VkImageView src_image_views[2] = {
get_image_view(left, data->flags, left_array_index),
get_image_view(right, data->flags, right_array_index),
};
const struct xrt_pose src_poses[2] = {lvd->pose, rvd->pose};
const struct xrt_fov src_fovs[2] = {lvd->fov, rvd->fov};
do_mesh( //
rr, //
rts, //
viewport_datas, //
vertex_rots, //
src_samplers, //
src_image_views, //
src_norm_rects, //
src_poses, //
src_fovs, //
new_poses, //
do_timewarp); //
} }
/*
*
* 'Exported' function(s).
*
*/
void void
comp_render_gfx_dispatch(struct render_gfx *rr, comp_render_gfx_dispatch(struct render_gfx *rr,
struct render_scratch_images *rsi,
struct render_gfx_target_resources rsi_rtrs[2],
const struct comp_layer *layers, const struct comp_layer *layers,
const uint32_t layer_count, const uint32_t layer_count,
struct xrt_pose world_poses[2], const struct comp_render_dispatch_data *d)
struct xrt_pose eye_poses[2],
struct xrt_fov fovs[2],
struct xrt_matrix_2x2 vertex_rots[2],
struct render_gfx_target_resources *rtr,
const struct render_viewport_data viewport_datas[2],
bool fast_path,
bool do_timewarp)
{ {
// Convenience.
bool fast_path = d->fast_path;
// Only used if fast_path is true. // Only used if fast_path is true.
const struct comp_layer *layer = &layers[0]; const struct comp_layer *layer = &layers[0];
@ -756,16 +833,12 @@ comp_render_gfx_dispatch(struct render_gfx *rr,
const struct xrt_layer_projection_view_data *lvd = &stereo->l; const struct xrt_layer_projection_view_data *lvd = &stereo->l;
const struct xrt_layer_projection_view_data *rvd = &stereo->r; const struct xrt_layer_projection_view_data *rvd = &stereo->r;
do_mesh_from_proj( // do_mesh_from_proj( //
rr, // rr, //
rtr, // d, //
viewport_datas, // layer, //
vertex_rots, // lvd, //
layer, // rvd); //
lvd, //
rvd, //
world_poses, //
do_timewarp); //
} else if (fast_path && layer->data.type == XRT_LAYER_STEREO_PROJECTION_DEPTH) { } else if (fast_path && layer->data.type == XRT_LAYER_STEREO_PROJECTION_DEPTH) {
// Fast path. // Fast path.
@ -773,102 +846,73 @@ comp_render_gfx_dispatch(struct render_gfx *rr,
const struct xrt_layer_projection_view_data *lvd = &stereo->l; const struct xrt_layer_projection_view_data *lvd = &stereo->l;
const struct xrt_layer_projection_view_data *rvd = &stereo->r; const struct xrt_layer_projection_view_data *rvd = &stereo->r;
do_mesh_from_proj( // do_mesh_from_proj( //
rr, // rr, //
rtr, // d, //
viewport_datas, // layer, //
vertex_rots, // lvd, //
layer, // rvd); //
lvd, //
rvd, //
world_poses, //
do_timewarp); //
} else { } else {
if (fast_path) { if (fast_path) {
U_LOG_W("Wanted fast path but no projection layer, falling back to layer squasher."); U_LOG_W("Wanted fast path but no projection layer, falling back to layer squasher.");
} }
struct render_viewport_data layer_viewport_datas[2] = {
{.x = 0, .y = 0, .w = rsi->extent.width, .h = rsi->extent.height},
{.x = 0, .y = 0, .w = rsi->extent.width, .h = rsi->extent.height},
};
do_layers( // /*
rr, // rr * Layer squashing.
rsi_rtrs, // rtrs */
layer_viewport_datas, // viewport_datas
fovs, // new_fovs do_layers( //
world_poses, // world_poses rr, // rr
eye_poses, // eye_poses layers, // layers
layers, // layers layer_count, // layer_count
layer_count); // layer_count d); // d
VkImageSubresourceRange first_color_level_subresource_range = { /*
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, * Distortion.
.baseMipLevel = 0, */
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
VkImageLayout transition_from = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkImageLayout transition_from = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkImageLayout transition_to = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkImageLayout transition_to = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
vk_cmd_image_barrier_locked( // cmd_barrier_view_images( //
rr->r->vk, // rr->r->vk, //
rr->r->cmd, // d, //
rsi->color[0].image, // rr->r->cmd, // cmd
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // src_access_mask
VK_ACCESS_SHADER_READ_BIT, // VK_ACCESS_SHADER_READ_BIT, // dst_access_mask
transition_from, // transition_from, // transition_from
transition_to, // transition_to, // transition_to
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // src_stage_mask
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); // dst_stage_mask
first_color_level_subresource_range); //
if (rsi->color[0].image != rsi->color[1].image) { // Shared between all views.
vk_cmd_image_barrier_locked( // VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black;
rr->r->vk, //
rr->r->cmd, // struct gfx_mesh_data md = XRT_STRUCT_INIT;
rsi->color[1].image, // for (uint32_t i = 0; i < d->view_count; i++) {
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // struct xrt_pose src_pose = d->views[i].world_pose;
VK_ACCESS_SHADER_READ_BIT, // struct xrt_fov src_fov = d->views[i].fov;
transition_from, // VkImageView src_image_view = d->views[i].srgb_view;
transition_to, // struct xrt_normalized_rect src_norm_rect = d->views[i].layer_norm_rect;
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, //
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // gfx_mesh_add_view( //
first_color_level_subresource_range); // &md, // md
i, // view_index
&src_pose, // src_pose
&src_fov, // src_fov
&src_norm_rect, // src_norm_rect
clamp_to_border_black, // src_sampler
src_image_view); // src_image_view
} }
VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black;
VkSampler src_samplers[2] = {
clamp_to_border_black,
clamp_to_border_black,
};
VkImageView src_image_views[2] = {
rsi->color[0].srgb_view,
rsi->color[1].srgb_view,
};
struct xrt_normalized_rect src_norm_rects[2] = {
{.x = 0, .y = 0, .w = 1, .h = 1},
{.x = 0, .y = 0, .w = 1, .h = 1},
};
// We are passing in the same old and new poses. // We are passing in the same old and new poses.
do_mesh( // do_mesh( //
rr, // rr, //
rtr, // false, // do_timewarp
viewport_datas, // &md, // md
vertex_rots, // d); // d
src_samplers, //
src_image_views, //
src_norm_rects, //
world_poses, //
fovs, //
world_poses, //
false); //
} }
} }

View file

@ -1,4 +1,4 @@
// Copyright 2023, Collabora, Ltd. // Copyright 2023-2024, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
/*! /*!
* @file * @file
@ -14,6 +14,7 @@
#include "render/render_interface.h" #include "render/render_interface.h"
#include "util/comp_base.h" #include "util/comp_base.h"
#include "util/comp_render.h"
/* /*
@ -136,3 +137,62 @@ set_post_transform_rect(const struct xrt_layer_data *data,
*out_norm_rect = rect; *out_norm_rect = rect;
} }
/*
*
* Command helpers.
*
*/
static inline void
cmd_barrier_view_images(struct vk_bundle *vk,
const struct comp_render_dispatch_data *d,
VkCommandBuffer cmd,
VkAccessFlags src_access_mask,
VkAccessFlags dst_access_mask,
VkImageLayout transition_from,
VkImageLayout transition_to,
VkPipelineStageFlags src_stage_mask,
VkPipelineStageFlags dst_stage_mask)
{
VkImageSubresourceRange first_color_level_subresource_range = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
for (uint32_t i = 0; i < d->view_count; i++) {
bool already_barried = false;
VkImage image = d->views[i].image;
uint32_t k = i;
while (k > 0) {
k--; // k is always greater then zero.
if (d->views[k].image == image) {
already_barried = true;
break;
}
}
if (already_barried) {
continue;
}
vk_cmd_image_barrier_locked( //
vk, // vk_bundle
cmd, // cmd_buffer
image, // image
src_access_mask, // src_access_mask
dst_access_mask, // dst_access_mask
transition_from, // old_image_layout
transition_to, // new_image_layout
src_stage_mask, // src_stage_mask
dst_stage_mask, // dst_stage_mask
first_color_level_subresource_range); // subresource_range
}
}