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]
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.
render_gfx_begin(rr);
// Build the command buffer.
comp_render_gfx_dispatch( //
rr, // rr
&r->scratch, // rsi
r->scratch_targets, // rsi_rtrs
layers, // layers
layer_count, // layer_count
world_poses, // world_poses
eye_poses, // eye_poses
fovs, // fovs
vertex_rots, // vertex_rots
rtr, // rtr
viewport_datas, // viewport_datas
fast_path, // fast_path
do_timewarp); // do_timewarp
&data); // d
// Make the command buffer submittable.
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;
// Device view information.
struct xrt_fov fovs[2]; // Unused
struct xrt_fov fovs[2];
struct xrt_pose world_poses[2];
struct xrt_pose eye_poses[2];
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];
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.
render_compute_begin(crc);
// Build the command buffer.
comp_render_cs_dispatch( //
crc, // crc
&r->scratch, // rsi
world_poses, // world_poses
eye_poses, // eye_poses
layers, // layers
layer_count, // layer_count
target_image, // target_image
target_image_view, // target_image_view
views, // views
fast_path, // fast_path
do_timewarp); // do_timewarp
&data); // d
// Make the command buffer submittable.
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
/*!
* @file
@ -22,16 +22,178 @@ extern "C" {
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
* 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.
* 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
* which set the layout.
* possible to do a @p comp_render_dispatch_data::fast_path. Will use the render
* passes of the targets which set the layout.
*
* The render passes of @p rsi_rtrs must be created with a final_layout of
* VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL or there will be validation errors.
* The render passes of @p comp_render_dispatch_data::views::rtr must be created
* with a final_layout of VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL or there will
* be validation errors.
*
* Expected layouts:
* * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
@ -47,20 +209,65 @@ struct comp_layer;
*/
void
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 uint32_t layer_count,
struct xrt_pose world_poses[2],
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);
const struct comp_render_dispatch_data *d);
/*
*
* 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.
*
@ -87,7 +294,7 @@ comp_render_cs_layer(struct render_compute *crc,
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
* 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
*/
void
comp_render_cs_stereo_layers(struct render_compute *crc,
const struct comp_layer *layers,
const uint32_t layer_count,
const struct xrt_normalized_rect pre_transforms[2],
const struct xrt_pose world_poses[2],
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);
comp_render_cs_layers(struct render_compute *crc,
const struct comp_layer *layers,
const uint32_t layer_count,
const struct comp_render_dispatch_data *d,
VkImageLayout transition_to);
/*!
* 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
* change the scratch images and target images to the needed layout.
*
* Currently limited to exactly two views.
*
* Expected layouts:
* * Layer images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
* * Sratch images: Any
@ -164,16 +340,9 @@ comp_render_cs_stereo_layers_to_scratch(struct render_compute *crc,
*/
void
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 uint32_t layer_count,
VkImage target_image,
VkImageView target_image_view,
const struct render_viewport_data views[2],
bool fast_path,
bool do_timewarp);
const struct comp_render_dispatch_data *d);
#ifdef __cplusplus

View file

@ -1,4 +1,4 @@
// Copyright 2019-2023, Collabora, Ltd.
// Copyright 2019-2024, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@ -307,6 +307,7 @@ do_cs_cylinder_layer(const struct xrt_layer_data *data,
*out_cur_image = cur_image;
}
/*
*
* Compute distortion helpers.
@ -314,47 +315,87 @@ do_cs_cylinder_layer(const struct xrt_layer_data *data,
*/
static void
do_cs_distortion_for_scratch(struct render_compute *crc,
struct render_scratch_images *rsi,
VkImage target_image,
VkImageView target_image_view,
const struct render_viewport_data views[2])
do_cs_clear(struct render_compute *crc, const struct comp_render_dispatch_data *d)
{
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] = {
rsi->color[0].srgb_view, // Read with gamma curve.
rsi->color[1].srgb_view,
};
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},
const struct render_viewport_data target_viewport_datas[2] = {
d->views[0].target_viewport_data,
d->views[1].target_viewport_data,
};
render_compute_projection( //
crc, //
src_samplers, //
src_image_views, //
src_norm_rects, //
target_image, //
target_image_view, //
views //
);
render_compute_clear( //
crc, // crc
d->cs.target_image, // target_image
d->cs.target_unorm_view, // target_image_view
target_viewport_datas); // views
}
static void
do_cs_distortion_for_layer(struct render_compute *crc,
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)
do_cs_distortion_from_scratch(struct render_compute *crc, 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;
}
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;
uint32_t left_array_index = lvd->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];
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] = {
get_image_view(left, data->flags, left_array_index),
get_image_view(right, data->flags, right_array_index),
};
// Data to fill in.
struct xrt_pose world_poses[2];
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};
if (data->flip_y) {
src_norm_rects[0].h = -src_norm_rects[0].h;
src_norm_rects[0].y = 1 + src_norm_rects[0].y;
src_norm_rects[1].h = -src_norm_rects[1].h;
src_norm_rects[1].y = 1 + src_norm_rects[1].y;
for (uint32_t i = 0; i < d->view_count; i++) {
struct xrt_pose world_pose;
struct render_viewport_data viewport_data;
struct xrt_pose src_pose;
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) {
render_compute_projection( //
crc, //
src_samplers, //
src_image_views, //
src_norm_rects, //
target_image, //
target_image_view, //
views); //
if (!d->do_timewarp) {
render_compute_projection( //
crc, //
src_samplers, //
src_image_views, //
src_norm_rects, //
d->cs.target_image, //
d->cs.target_unorm_view, //
target_viewport_datas); //
} 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( //
crc, //
src_samplers, //
@ -408,9 +473,9 @@ do_cs_distortion_for_layer(struct render_compute *crc,
src_poses, //
src_fovs, //
world_poses, //
target_image, //
target_image_view, //
views); //
d->cs.target_image, //
d->cs.target_unorm_view, //
target_viewport_datas); //
}
}
@ -597,150 +662,62 @@ comp_render_cs_layer(struct render_compute *crc,
}
void
comp_render_cs_stereo_layers(struct render_compute *crc,
const struct comp_layer *layers,
const uint32_t layer_count,
const struct xrt_normalized_rect pre_transforms[2],
const struct xrt_pose world_poses[2],
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)
comp_render_cs_layers(struct render_compute *crc,
const struct comp_layer *layers,
const uint32_t layer_count,
const struct comp_render_dispatch_data *d,
VkImageLayout transition_to)
{
VkImageSubresourceRange first_color_level_subresource_range = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
cmd_barrier_view_images( //
crc->r->vk, //
d, //
crc->r->cmd, // cmd
0, // src_access_mask
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( //
crc->r->vk, //
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); //
for (uint32_t view_index = 0; view_index < d->view_count; view_index++) {
const struct comp_render_view_data *view = &d->views[view_index];
if (target_images[0] != target_images[1]) {
vk_cmd_image_barrier_gpu_locked( //
crc->r->vk, //
crc->r->cmd, //
target_images[1], //
0, //
VK_ACCESS_SHADER_WRITE_BIT, //
VK_IMAGE_LAYOUT_UNDEFINED, //
VK_IMAGE_LAYOUT_GENERAL, //
first_color_level_subresource_range); //
comp_render_cs_layer( //
crc, //
view_index, //
layers, //
layer_count, //
&view->target_pre_transform, //
&view->world_pose, //
&view->eye_pose, //
view->image, //
view->cs.unorm_view, //
&view->layer_viewport_data, //
d->do_timewarp); //
}
for (uint32_t view_index = 0; view_index < 2; view_index++) {
comp_render_cs_layer( //
crc, //
view_index, //
layers, //
layer_count, //
&pre_transforms[view_index], //
&world_poses[view_index], //
&eye_poses[view_index], //
target_images[view_index], //
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
cmd_barrier_view_images( //
crc->r->vk, //
d, //
crc->r->cmd, // cmd
VK_ACCESS_SHADER_WRITE_BIT, // src_access_mask
VK_ACCESS_MEMORY_READ_BIT, // dst_access_mask
VK_IMAGE_LAYOUT_GENERAL, // transition_from
transition_to, // transition_to
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // src_stage_mask
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); // dst_stage_mask
}
void
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 uint32_t layer_count,
VkImage target_image,
VkImageView target_image_view,
const struct render_viewport_data views[2],
bool fast_path,
bool do_timewarp)
const struct comp_render_dispatch_data *d)
{
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.
const struct xrt_normalized_rect pre_transforms[2] = {
crc->r->distortion.uv_to_tanangle[0],
crc->r->distortion.uv_to_tanangle[1],
};
assert(!fast_path || layer_count > 0);
// We want to read from the images afterwards.
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 *rvd = &stereo->r;
do_cs_distortion_for_layer( //
crc, // crc
world_poses, // world_poses
layer, // layer
lvd, // lvd
rvd, // rvd
target_image, // target_image
target_image_view, // target_image_view
views, // views
do_timewarp); // do_timewarp
do_cs_distortion_from_stereo_layer( //
crc, // crc
layer, // layer
lvd, // lvd
rvd, // rvd
d); // d
} else if (fast_path && layers[0].data.type == XRT_LAYER_STEREO_PROJECTION_DEPTH) {
int i = 0;
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 *rvd = &stereo->r;
do_cs_distortion_for_layer( //
crc, // crc
world_poses, // world_poses
layer, // layer
lvd, // lvd
rvd, // rvd
target_image, // target_image
target_image_view, // target_image_view
views, // views
do_timewarp); // do_timewarp
do_cs_distortion_from_stereo_layer( //
crc, // crc
layer, // layer
lvd, // lvd
rvd, // rvd
d); // d
} else if (layer_count > 0) {
comp_render_cs_stereo_layers_to_scratch( //
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( //
comp_render_cs_layers( //
crc, //
target_image, //
target_image_view, //
views); //
layers, //
layer_count, //
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
/*!
* @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.
VkDescriptorSet descriptor_sets[RENDER_MAX_LAYERS];
@ -64,6 +64,43 @@ struct gfx_view_state
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.
@ -87,7 +148,7 @@ static const VkClearColorValue background_color_active = {
*/
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_pose *pose,
const struct xrt_vec3 *scale,
@ -104,7 +165,7 @@ calc_mvp_full(struct gfx_view_state *state,
}
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_pose *pose,
const struct xrt_vec3 *scale,
@ -127,7 +188,7 @@ calc_mv_inv_full(struct gfx_view_state *state,
}
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_pose *pose,
const struct xrt_vec3 *scale,
@ -155,7 +216,7 @@ calc_mvp_rot_only(struct gfx_view_state *state,
*/
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++;
state->descriptor_sets[cur_layer] = descriptor_set;
@ -169,7 +230,7 @@ do_cylinder_layer(struct render_gfx *rr,
uint32_t view_index,
VkSampler clamp_to_edge,
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_cylinder_data *c = &layer_data->cylinder;
@ -233,7 +294,7 @@ do_equirect2_layer(struct render_gfx *rr,
uint32_t view_index,
VkSampler clamp_to_edge,
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_equirect2_data *eq2 = &layer_data->equirect2;
@ -297,7 +358,7 @@ do_projection_layer(struct render_gfx *rr,
uint32_t view_index,
VkSampler clamp_to_edge,
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_projection_view_data *vd = NULL;
@ -359,7 +420,7 @@ do_quad_layer(struct render_gfx *rr,
uint32_t view_index,
VkSampler clamp_to_edge,
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_quad_data *q = &layer_data->quad;
@ -406,13 +467,9 @@ do_quad_layer(struct render_gfx *rr,
static void
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,
uint32_t layer_count)
uint32_t layer_count,
const struct comp_render_dispatch_data *d)
{
COMP_TRACE_MARKER();
@ -420,37 +477,45 @@ do_layers(struct render_gfx *rr,
VkResult ret;
// 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.
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
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.
struct xrt_matrix_4x4 v;
// World
math_matrix_4x4_view_from_pose(&world_poses[view], &v);
math_matrix_4x4_multiply(&p, &v, &views[view].world_vp_full);
math_matrix_4x4_inverse(&v, &views[view].world_v_inv_full);
math_matrix_4x4_view_from_pose(&world_pose, &v);
math_matrix_4x4_multiply(&p, &v, &state->world_vp_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_multiply(&p, &v, &views[view].world_vp_rot_only);
math_matrix_4x4_multiply(&p, &v, &state->world_vp_rot_only);
// Eye
math_matrix_4x4_view_from_pose(&eye_poses[view], &v);
math_matrix_4x4_multiply(&p, &v, &views[view].eye_vp_full);
math_matrix_4x4_inverse(&v, &views[view].eye_v_inv_full);
math_matrix_4x4_view_from_pose(&eye_pose, &v);
math_matrix_4x4_multiply(&p, &v, &state->eye_vp_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_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_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++) {
const struct xrt_layer_data *data = &layers[i].data;
if (!is_layer_view_visible(data, view)) {
@ -479,7 +548,7 @@ do_layers(struct render_gfx *rr,
view, // view_index
clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black
&views[view]); // state
state); // state
VK_CHK_WITH_GOTO(ret, "do_cylinder_layer", err_layer);
break;
case XRT_LAYER_EQUIRECT2:
@ -489,7 +558,7 @@ do_layers(struct render_gfx *rr,
view, // view_index
clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black
&views[view]); // state
state); // state
VK_CHK_WITH_GOTO(ret, "do_equirect2_layer", err_layer);
break;
case XRT_LAYER_STEREO_PROJECTION:
@ -500,7 +569,7 @@ do_layers(struct render_gfx *rr,
view, // view_index
clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black
&views[view]); // state
state); // state
VK_CHK_WITH_GOTO(ret, "do_projection_layer", err_layer);
break;
case XRT_LAYER_QUAD:
@ -510,7 +579,7 @@ do_layers(struct render_gfx *rr,
view, // view_index
clamp_to_edge, // clamp_to_edge
clamp_to_border_black, // clamp_to_border_black
&views[view]); // state
state); // state
VK_CHK_WITH_GOTO(ret, "do_quad_layer", err_layer);
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;
for (uint32_t view = 0; view < ARRAY_SIZE(views); view++) {
render_gfx_begin_target( //
rr, //
&rtrs[view], //
color); //
for (uint32_t view = 0; view < d->view_count; view++) {
render_gfx_begin_view( //
// Convenience.
const struct render_viewport_data *viewport_data = &d->views[view].layer_viewport_data;
render_gfx_begin_target( //
rr, //
view, // view_index
&viewport_datas[view]); // viewport_data
d->views[view].gfx.rtr, //
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++) {
switch (state->types[i]) {
@ -591,16 +665,9 @@ err_layer:
static void
do_mesh(struct render_gfx *rr,
struct render_gfx_target_resources *rtr,
const struct render_viewport_data viewport_datas[2],
const struct xrt_matrix_2x2 vertex_rots[2],
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)
bool do_timewarp,
const struct gfx_mesh_data *md,
const struct comp_render_dispatch_data *d)
{
struct vk_bundle *vk = rr->r->vk;
VkResult ret;
@ -611,34 +678,35 @@ do_mesh(struct render_gfx *rr,
* write a copy command before the other gfx commands.
*/
VkDescriptorSet descriptor_sets[2] = XRT_STRUCT_INIT;
for (uint32_t i = 0; i < 2; i++) {
struct gfx_mesh_state ms = XRT_STRUCT_INIT;
for (uint32_t i = 0; i < d->view_count; i++) {
struct render_gfx_mesh_ubo_data data = {
.vertex_rot = vertex_rots[i],
.post_transform = src_norm_rects[i],
.vertex_rot = d->views[i].gfx.vertex_rot,
.post_transform = md->views[i].src_norm_rect,
};
// Extra arguments for 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( //
&src_poses[i], //
&src_fovs[i], //
&new_poses[i], //
&md->views[i].src_pose, //
&md->views[i].src_fov, //
&d->views[i].world_pose, //
&data.transform); //
}
ret = render_gfx_mesh_alloc_and_write( //
rr, //
&data, //
src_samplers[i], //
src_image_views[i], //
&descriptor_sets[i]); //
md->views[i].src_sampler, //
md->views[i].src_image_view, //
&ms.descriptor_sets[i]); //
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( //
rr, //
rtr, //
d->gfx.rtr, //
&background_color_active); //
for (uint32_t i = 0; i < 2; i++) {
render_gfx_begin_view( //
rr, //
i, // view_index
&viewport_datas[i]); // viewport_data
for (uint32_t i = 0; i < d->view_count; i++) {
// Convenience.
const struct render_viewport_data *viewport_data = &d->views[i].target_viewport_data;
render_gfx_mesh_draw( //
rr, // rr
i, // mesh_index
descriptor_sets[i], // descriptor_set
do_timewarp); // do_timewarp
render_gfx_begin_view( //
rr, //
i, // view_index
viewport_data); // viewport_data
render_gfx_mesh_draw( //
rr, // rr
i, // mesh_index
ms.descriptor_sets[i], // descriptor_set
do_timewarp); // do_timewarp
render_gfx_end_view(rr);
}
@ -677,14 +748,10 @@ err_no_memory:
static void
do_mesh_from_proj(struct render_gfx *rr,
struct render_gfx_target_resources *rts,
const struct render_viewport_data viewport_datas[2],
const struct xrt_matrix_2x2 vertex_rots[2],
const struct comp_render_dispatch_data *d,
const struct comp_layer *layer,
const struct xrt_layer_projection_view_data *lvd,
const struct xrt_layer_projection_view_data *rvd,
const struct xrt_pose new_poses[2],
bool do_timewarp)
const struct xrt_layer_projection_view_data *rvd)
{
const struct xrt_layer_data *data = &layer->data;
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 *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};
if (data->flip_y) {
src_norm_rects[0].h = -src_norm_rects[0].h;
src_norm_rects[0].y = 1 + src_norm_rects[0].y;
src_norm_rects[1].h = -src_norm_rects[1].h;
src_norm_rects[1].y = 1 + src_norm_rects[1].y;
VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black;
struct gfx_mesh_data md = XRT_STRUCT_INIT;
for (uint32_t i = 0; i < d->view_count; i++) {
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;
VkSampler src_samplers[2] = {
clamp_to_border_black,
clamp_to_border_black,
};
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); //
do_mesh( //
rr, //
d->do_timewarp, //
&md, //
d); //
}
/*
*
* 'Exported' function(s).
*
*/
void
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 uint32_t layer_count,
struct xrt_pose world_poses[2],
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)
const struct comp_render_dispatch_data *d)
{
// Convenience.
bool fast_path = d->fast_path;
// Only used if fast_path is true.
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 *rvd = &stereo->r;
do_mesh_from_proj( //
rr, //
rtr, //
viewport_datas, //
vertex_rots, //
layer, //
lvd, //
rvd, //
world_poses, //
do_timewarp); //
do_mesh_from_proj( //
rr, //
d, //
layer, //
lvd, //
rvd); //
} else if (fast_path && layer->data.type == XRT_LAYER_STEREO_PROJECTION_DEPTH) {
// 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 *rvd = &stereo->r;
do_mesh_from_proj( //
rr, //
rtr, //
viewport_datas, //
vertex_rots, //
layer, //
lvd, //
rvd, //
world_poses, //
do_timewarp); //
do_mesh_from_proj( //
rr, //
d, //
layer, //
lvd, //
rvd); //
} else {
if (fast_path) {
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
rsi_rtrs, // rtrs
layer_viewport_datas, // viewport_datas
fovs, // new_fovs
world_poses, // world_poses
eye_poses, // eye_poses
layers, // layers
layer_count); // layer_count
/*
* Layer squashing.
*/
do_layers( //
rr, // rr
layers, // layers
layer_count, // layer_count
d); // d
VkImageSubresourceRange first_color_level_subresource_range = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
/*
* Distortion.
*/
VkImageLayout transition_from = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_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->cmd, //
rsi->color[0].image, //
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, //
VK_ACCESS_SHADER_READ_BIT, //
transition_from, //
transition_to, //
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, //
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, //
first_color_level_subresource_range); //
d, //
rr->r->cmd, // cmd
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // src_access_mask
VK_ACCESS_SHADER_READ_BIT, // dst_access_mask
transition_from, // transition_from
transition_to, // transition_to
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // src_stage_mask
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); // dst_stage_mask
if (rsi->color[0].image != rsi->color[1].image) {
vk_cmd_image_barrier_locked( //
rr->r->vk, //
rr->r->cmd, //
rsi->color[1].image, //
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, //
VK_ACCESS_SHADER_READ_BIT, //
transition_from, //
transition_to, //
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, //
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, //
first_color_level_subresource_range); //
// Shared between all views.
VkSampler clamp_to_border_black = rr->r->samplers.clamp_to_border_black;
struct gfx_mesh_data md = XRT_STRUCT_INIT;
for (uint32_t i = 0; i < d->view_count; i++) {
struct xrt_pose src_pose = d->views[i].world_pose;
struct xrt_fov src_fov = d->views[i].fov;
VkImageView src_image_view = d->views[i].srgb_view;
struct xrt_normalized_rect src_norm_rect = d->views[i].layer_norm_rect;
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;
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.
do_mesh( //
rr, //
rtr, //
viewport_datas, //
vertex_rots, //
src_samplers, //
src_image_views, //
src_norm_rects, //
world_poses, //
fovs, //
world_poses, //
false); //
do_mesh( //
rr, //
false, // do_timewarp
&md, // md
d); // d
}
}

View file

@ -1,4 +1,4 @@
// Copyright 2023, Collabora, Ltd.
// Copyright 2023-2024, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@ -14,6 +14,7 @@
#include "render/render_interface.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;
}
/*
*
* 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
}
}