diff --git a/src/xrt/compositor/main/comp_renderer.c b/src/xrt/compositor/main/comp_renderer.c index c28e4b05f..f5227e02b 100644 --- a/src/xrt/compositor/main/comp_renderer.c +++ b/src/xrt/compositor/main/comp_renderer.c @@ -962,11 +962,11 @@ dispatch_graphics(struct comp_renderer *r, // 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 + comp_render_initial_init( // + &data, // data + fast_path, // fast_path + do_timewarp); // do_timewarp + for (uint32_t i = 0; i < render->r->view_count; i++) { // Which image of the scratch images for this view are we using. uint32_t scratch_index = crss->views[i].index; @@ -993,18 +993,21 @@ dispatch_graphics(struct comp_renderer *r, VkImageView sample_view = comp_scratch_single_images_get_sample_view(scratch_view, scratch_index); - comp_render_gfx_add_view( // - &data, // - &world_poses[i], // - &eye_poses[i], // - &fovs[i], // - rsci->image, // squash_image - rsci_rtr, // squash_rtr - &layer_viewport_data, // squash_viewport_data - sample_view, // squash_as_src_sample_view - &layer_norm_rect, // squash_as_src_norm_rect - &vertex_rots[i], // target_vertex_rot - &viewport_datas[i]); // target_viewport_data + comp_render_gfx_add_squash_view( // + &data, // + &world_poses[i], // + &eye_poses[i], // + &fovs[i], // + rsci->image, // squash_image + rsci_rtr, // squash_rtr + &layer_viewport_data); // squash_viewport_data + + comp_render_gfx_add_target_view( // + &data, // + sample_view, // squash_as_src_sample_view + &layer_norm_rect, // squash_as_src_norm_rect + &vertex_rots[i], // target_vertex_rot + &viewport_datas[i]); // target_viewport_data if (layer_count == 0) { crss->views[i].used = false; @@ -1013,6 +1016,9 @@ dispatch_graphics(struct comp_renderer *r, } } + // Add the target info. + comp_render_gfx_add_target(&data, rtr); + // Start the graphics pipeline. render_gfx_begin(render); @@ -1083,12 +1089,10 @@ dispatch_compute(struct comp_renderer *r, // 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 + comp_render_initial_init( // + &data, // data + fast_path, // fast_path + do_timewarp); // do_timewarp for (uint32_t i = 0; i < render->r->view_count; i++) { // Which image of the scratch images for this view are we using. @@ -1114,17 +1118,20 @@ dispatch_compute(struct comp_renderer *r, VkImageView sample_view = comp_scratch_single_images_get_sample_view(scratch_view, scratch_index); VkImageView storage_view = comp_scratch_single_images_get_storage_view(scratch_view, scratch_index); - comp_render_cs_add_view( // - &data, // - &world_poses[i], // - &eye_poses[i], // - &fovs[i], // - rsci->image, // squash_image - storage_view, // squash_storage_view - &layer_viewport_data, // squash_viewport_data - sample_view, // squash_as_src_sample_view - &layer_norm_rect, // squash_as_src_norm_rect - &views[i]); // target_viewport_data + comp_render_cs_add_squash_view( // + &data, // + &world_poses[i], // + &eye_poses[i], // + &fovs[i], // + rsci->image, // squash_image + storage_view, // squash_storage_view + &layer_viewport_data); // squash_viewport_data + + comp_render_cs_add_target_view( // + &data, // + sample_view, // squash_as_src_sample_view + &layer_norm_rect, // squash_as_src_norm_rect + &views[i]); // target_viewport_data if (layer_count == 0) { crss->views[i].used = false; @@ -1133,6 +1140,12 @@ dispatch_compute(struct comp_renderer *r, } } + // Add the target info. + comp_render_cs_add_target( // + &data, // data + target_image, // target_image + target_image_view); // target_unorm_view + // Start the compute pipeline. render_compute_begin(render); diff --git a/src/xrt/compositor/util/comp_render.h b/src/xrt/compositor/util/comp_render.h index 0afe87393..334464256 100644 --- a/src/xrt/compositor/util/comp_render.h +++ b/src/xrt/compositor/util/comp_render.h @@ -164,8 +164,11 @@ struct comp_render_dispatch_data { struct comp_render_view_data views[XRT_MAX_VIEWS]; - //! The number of views currently in this dispatch data. - uint32_t view_count; + /*! + * The number of squash views currently in this dispatch data. + */ + uint32_t squash_view_count; + //! Fast path can be disabled for mirroing so needs to be an argument. bool fast_path; @@ -175,6 +178,16 @@ struct comp_render_dispatch_data struct { + //! Has this struct been setup to use the target. + bool initialized; + + /*! + * The number of target views currently, when calling dispatch + * this has to be either zero or the same number as + * squash_view_count, see also the target.initialized field. + */ + uint32_t view_count; + //! Members used only by GFX @ref comp_render_gfx struct { @@ -194,6 +207,22 @@ struct comp_render_dispatch_data } target; }; +/*! + * Initialize structure for use without the target step. + * + * @param[out] data Common render dispatch data. Will be zeroed and initialized. + * @param fast_path Whether we will use the "fast path" avoiding layer squashing. + * @param do_timewarp Whether timewarp (reprojection) will be performed. + */ +static inline void +comp_render_initial_init(struct comp_render_dispatch_data *data, bool fast_path, bool do_timewarp) +{ + U_ZERO(data); + + data->fast_path = fast_path; + data->do_timewarp = do_timewarp; +} + /*! * Shared implementation setting up common view params between GFX and CS. * @@ -220,17 +249,14 @@ struct comp_render_dispatch_data * @return Pointer to the @ref comp_render_view_data we have been populating, for additional setup. */ static inline struct comp_render_view_data * -comp_render_dispatch_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, - VkImage squash_image, - const struct render_viewport_data *squash_viewport_data, - VkImageView squash_as_src_sample_view, - const struct xrt_normalized_rect *squash_as_src_norm_rect, - const struct render_viewport_data *target_viewport_data) +comp_render_dispatch_add_squash_view(struct comp_render_dispatch_data *data, + const struct xrt_pose *world_pose, + const struct xrt_pose *eye_pose, + const struct xrt_fov *fov, + VkImage squash_image, + const struct render_viewport_data *squash_viewport_data) { - uint32_t i = data->view_count++; + uint32_t i = data->squash_view_count++; assert(i < ARRAY_SIZE(data->views)); @@ -247,6 +273,22 @@ comp_render_dispatch_add_view(struct comp_render_dispatch_data *data, view->squash.image = squash_image; view->squash.viewport_data = *squash_viewport_data; + return view; +} + +static inline struct comp_render_view_data * +comp_render_dispatch_add_target_view(struct comp_render_dispatch_data *data, + VkImageView squash_as_src_sample_view, + const struct xrt_normalized_rect *squash_as_src_norm_rect, + const struct render_viewport_data *target_viewport_data) +{ + uint32_t i = data->target.view_count++; + + assert(i < data->squash_view_count); + assert(i < ARRAY_SIZE(data->views)); + + struct comp_render_view_data *view = &data->views[i]; + // When using the squash (aka scratch) image as a source. view->squash_as_src.sample_view = squash_as_src_sample_view; view->squash_as_src.norm_rect = *squash_as_src_norm_rect; @@ -281,21 +323,14 @@ comp_render_dispatch_add_view(struct comp_render_dispatch_data *data, /*! * Initialize structure for use of the GFX renderer. * - * @param[out] data Common render dispatch data. Will be zeroed and initialized. + * @param[in,out] data Common render dispatch data. * @param target_rtr GFX-specific resources for the entire framebuffer. Must be populated before call. - * @param fast_path Whether we will use the "fast path" avoiding layer squashing. - * @param do_timewarp Whether timewarp (reprojection) will be performed. */ static inline void -comp_render_gfx_initial_init(struct comp_render_dispatch_data *data, - struct render_gfx_target_resources *target_rtr, - bool fast_path, - bool do_timewarp) +comp_render_gfx_add_target(struct comp_render_dispatch_data *data, struct render_gfx_target_resources *target_rtr) { - U_ZERO(data); - - data->fast_path = fast_path; - data->do_timewarp = do_timewarp; + // Error tracking. + data->target.initialized = true; // When writing into the target. data->target.gfx.rtr = target_rtr; @@ -327,31 +362,38 @@ comp_render_gfx_initial_init(struct comp_render_dispatch_data *data, * Populates @ref comp_render_view_data::target.viewport_data */ 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, - VkImage squash_image, - struct render_gfx_target_resources *squash_rtr, - const struct render_viewport_data *layer_viewport_data, - VkImageView squash_as_src_sample_view, - const struct xrt_normalized_rect *squash_as_src_norm_rect, - const struct xrt_matrix_2x2 *target_vertex_rot, - const struct render_viewport_data *target_viewport_data) +comp_render_gfx_add_squash_view(struct comp_render_dispatch_data *data, + const struct xrt_pose *world_pose, + const struct xrt_pose *eye_pose, + const struct xrt_fov *fov, + VkImage squash_image, + struct render_gfx_target_resources *squash_rtr, + const struct render_viewport_data *layer_viewport_data) { - struct comp_render_view_data *view = comp_render_dispatch_add_view( // - data, // - world_pose, // - eye_pose, // - fov, // - squash_image, // - layer_viewport_data, // - squash_as_src_sample_view, // - squash_as_src_norm_rect, // - target_viewport_data); + struct comp_render_view_data *view = comp_render_dispatch_add_squash_view( // + data, // + world_pose, // + eye_pose, // + fov, // + squash_image, // + layer_viewport_data); // // When writing into the squash (aka scratch) image. view->squash.gfx.rtr = squash_rtr; +} + +static inline void +comp_render_gfx_add_target_view(struct comp_render_dispatch_data *data, + VkImageView squash_as_src_sample_view, + const struct xrt_normalized_rect *squash_as_src_norm_rect, + const struct xrt_matrix_2x2 *target_vertex_rot, + const struct render_viewport_data *target_viewport_data) +{ + struct comp_render_view_data *view = comp_render_dispatch_add_target_view( // + data, // + squash_as_src_sample_view, // + squash_as_src_norm_rect, // + target_viewport_data); // // When writing into the target. view->target.gfx.vertex_rot = *target_vertex_rot; @@ -454,25 +496,17 @@ comp_render_gfx_dispatch(struct render_gfx *render, */ /*! - * Initialize structure for use of the CS renderer. + * Add the target info, as required by the CS renderer. * - * @param data Common render dispatch data. Will be zeroed and initialized. + * @param[in,out] data Common render dispatch data. * @param target_image Image to render into * @param target_storage_view Corresponding image view - * @param fast_path Whether we will use the "fast path" avoiding layer squashing. - * @param do_timewarp Whether timewarp (reprojection) will be performed. */ static inline void -comp_render_cs_initial_init(struct comp_render_dispatch_data *data, - VkImage target_image, - VkImageView target_storage_view, - bool fast_path, - bool do_timewarp) +comp_render_cs_add_target(struct comp_render_dispatch_data *data, VkImage target_image, VkImageView target_storage_view) { - U_ZERO(data); - - data->fast_path = fast_path; - data->do_timewarp = do_timewarp; + // Error tracking. + data->target.initialized = true; // When writing into the target. data->target.cs.image = target_image; @@ -502,32 +536,40 @@ comp_render_cs_initial_init(struct comp_render_dispatch_data *data, * Populates @ref comp_render_view_data::target::viewport_data */ 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, - VkImage squash_image, - VkImageView squash_storage_view, - const struct render_viewport_data *squash_viewport_data, - VkImageView squash_as_src_sample_view, - const struct xrt_normalized_rect *squash_as_src_norm_rect, - const struct render_viewport_data *target_viewport_data) +comp_render_cs_add_squash_view(struct comp_render_dispatch_data *data, + const struct xrt_pose *world_pose, + const struct xrt_pose *eye_pose, + const struct xrt_fov *fov, + VkImage squash_image, + VkImageView squash_storage_view, + const struct render_viewport_data *squash_viewport_data) { - struct comp_render_view_data *view = comp_render_dispatch_add_view( // - data, // - world_pose, // - eye_pose, // - fov, // - squash_image, // - squash_viewport_data, // - squash_as_src_sample_view, // - squash_as_src_norm_rect, // - target_viewport_data); // + struct comp_render_view_data *view = comp_render_dispatch_add_squash_view( // + data, // + world_pose, // + eye_pose, // + fov, // + squash_image, // + squash_viewport_data); // // When writing into the squash (aka scratch) image. view->squash.cs.storage_view = squash_storage_view; } +static inline void +comp_render_cs_add_target_view(struct comp_render_dispatch_data *data, + VkImageView squash_as_src_sample_view, + const struct xrt_normalized_rect *squash_as_src_norm_rect, + const struct render_viewport_data *target_viewport_data) +{ + struct comp_render_view_data *view = comp_render_dispatch_add_target_view( // + data, // + squash_as_src_sample_view, // + squash_as_src_norm_rect, // + target_viewport_data); // + (void)view; +} + /*! * Dispatch the layer squasher for a single view. * diff --git a/src/xrt/compositor/util/comp_render_cs.c b/src/xrt/compositor/util/comp_render_cs.c index d9d9ea8a4..4e20b32f0 100644 --- a/src/xrt/compositor/util/comp_render_cs.c +++ b/src/xrt/compositor/util/comp_render_cs.c @@ -332,14 +332,14 @@ do_cs_quad_layer(const struct comp_layer *layer, static void crc_clear_output(struct render_compute *render, const struct comp_render_dispatch_data *d) { - if (d->view_count > XRT_MAX_VIEWS) { + if (d->target.view_count > XRT_MAX_VIEWS) { U_LOG_E("Only supports max %d views!", XRT_MAX_VIEWS); - assert(d->view_count < XRT_MAX_VIEWS); + assert(d->target.view_count <= XRT_MAX_VIEWS); return; } struct render_viewport_data target_viewport_datas[XRT_MAX_VIEWS]; - for (uint32_t i = 0; i < d->view_count; ++i) { + for (uint32_t i = 0; i < d->target.view_count; ++i) { target_viewport_datas[i] = d->views[i].target.viewport_data; } @@ -361,9 +361,9 @@ crc_clear_output(struct render_compute *render, const struct comp_render_dispatc static void crc_distortion_after_squash(struct render_compute *render, const struct comp_render_dispatch_data *d) { - if (d->view_count > XRT_MAX_VIEWS) { + if (d->target.view_count > XRT_MAX_VIEWS) { U_LOG_E("Only supports max %d views!", XRT_MAX_VIEWS); - assert(d->view_count < XRT_MAX_VIEWS); + assert(d->target.view_count <= XRT_MAX_VIEWS); return; } VkSampler clamp_to_border_black = render->r->samplers.clamp_to_border_black; @@ -374,7 +374,7 @@ crc_distortion_after_squash(struct render_compute *render, const struct comp_ren struct render_viewport_data target_viewport_datas[XRT_MAX_VIEWS]; struct xrt_normalized_rect src_norm_rects[XRT_MAX_VIEWS]; - for (uint32_t i = 0; i < d->view_count; i++) { + for (uint32_t i = 0; i < d->target.view_count; i++) { // Data to be filled in. VkImageView src_image_view; struct render_viewport_data viewport_data; @@ -409,9 +409,9 @@ crc_distortion_fast_path(struct render_compute *render, const struct comp_layer *layer, const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]) { - if (d->view_count > XRT_MAX_VIEWS) { + if (d->target.view_count > XRT_MAX_VIEWS) { U_LOG_E("Only supports max %d views!", XRT_MAX_VIEWS); - assert(d->view_count < XRT_MAX_VIEWS); + assert(d->target.view_count <= XRT_MAX_VIEWS); return; } @@ -429,7 +429,7 @@ crc_distortion_fast_path(struct render_compute *render, struct xrt_pose src_poses[XRT_MAX_VIEWS]; struct xrt_pose world_poses[XRT_MAX_VIEWS]; - for (uint32_t i = 0; i < d->view_count; i++) { + for (uint32_t i = 0; i < d->target.view_count; i++) { // Data to be filled in. VkImageView src_image_view; struct render_viewport_data viewport_data; @@ -684,7 +684,7 @@ comp_render_cs_layers(struct render_compute *render, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // src_stage_mask VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); // dst_stage_mask - for (uint32_t view_index = 0; view_index < d->view_count; view_index++) { + for (uint32_t view_index = 0; view_index < d->squash_view_count; view_index++) { const struct comp_render_view_data *view = &d->views[view_index]; comp_render_cs_layer( // @@ -719,6 +719,12 @@ comp_render_cs_dispatch(struct render_compute *render, const uint32_t layer_count, const struct comp_render_dispatch_data *d) { + if (!d->target.initialized) { + VK_ERROR(render->r->vk, "Target hasn't been initialized, not rendering anything."); + assert(d->target.initialized); + return; + } + // Convenience. bool fast_path = d->fast_path; @@ -735,7 +741,7 @@ comp_render_cs_dispatch(struct render_compute *render, // Fast path. const struct xrt_layer_projection_data *proj = &layer->data.proj; const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]; - for (uint32_t view = 0; view < d->view_count; ++view) { + for (uint32_t view = 0; view < d->target.view_count; ++view) { vds[view] = &proj->v[view]; } crc_distortion_fast_path( // @@ -748,7 +754,7 @@ comp_render_cs_dispatch(struct render_compute *render, // Fast path. const struct xrt_layer_projection_depth_data *depth = &layer->data.depth; const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]; - for (uint32_t view = 0; view < d->view_count; ++view) { + for (uint32_t view = 0; view < d->target.view_count; ++view) { vds[view] = &depth->v[view]; } crc_distortion_fast_path( // diff --git a/src/xrt/compositor/util/comp_render_gfx.c b/src/xrt/compositor/util/comp_render_gfx.c index 1a5c33eb4..8e1a25aab 100644 --- a/src/xrt/compositor/util/comp_render_gfx.c +++ b/src/xrt/compositor/util/comp_render_gfx.c @@ -520,7 +520,7 @@ crg_distortion_common(struct render_gfx *render, struct gfx_mesh_state ms = XRT_STRUCT_INIT; - for (uint32_t i = 0; i < d->view_count; i++) { + for (uint32_t i = 0; i < d->target.view_count; i++) { struct render_gfx_mesh_ubo_data data = { .vertex_rot = d->views[i].target.gfx.vertex_rot, @@ -559,7 +559,7 @@ crg_distortion_common(struct render_gfx *render, d->target.gfx.rtr, // &background_color_active); // - for (uint32_t i = 0; i < d->view_count; i++) { + for (uint32_t i = 0; i < d->target.view_count; i++) { // Convenience. const struct render_viewport_data *viewport_data = &d->views[i].target.viewport_data; @@ -595,7 +595,7 @@ crg_distortion_after_squash(struct render_gfx *render, const struct comp_render_ VkSampler clamp_to_border_black = render->r->samplers.clamp_to_border_black; struct gfx_mesh_data md = XRT_STRUCT_INIT; - for (uint32_t i = 0; i < d->view_count; i++) { + for (uint32_t i = 0; i < d->target.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].squash_as_src.sample_view; @@ -631,7 +631,7 @@ crg_distortion_fast_path(struct render_gfx *render, const VkSampler clamp_to_border_black = render->r->samplers.clamp_to_border_black; struct gfx_mesh_data md = XRT_STRUCT_INIT; - for (uint32_t i = 0; i < d->view_count; i++) { + for (uint32_t i = 0; i < d->target.view_count; i++) { const uint32_t array_index = vds[i]->sub.array_index; const struct comp_swapchain_image *image = get_layer_image(layer, i, vds[i]->sub.image_index); @@ -690,7 +690,7 @@ comp_render_gfx_layers(struct render_gfx *render, // Compute MVP matrices per eye: populates gfx_layer_view_state elements in `ls` // from `comp_render_dispatch_data *d` - for (uint32_t view = 0; view < d->view_count; view++) { + for (uint32_t view = 0; view < d->squash_view_count; view++) { // Data for this view, convenience. const struct xrt_pose world_pose = d->views[view].world_pose; @@ -740,7 +740,7 @@ comp_render_gfx_layers(struct render_gfx *render, VkSampler clamp_to_edge = render->r->samplers.clamp_to_edge; VkSampler clamp_to_border_black = render->r->samplers.clamp_to_border_black; - for (uint32_t view = 0; view < d->view_count; view++) { + for (uint32_t view = 0; view < d->squash_view_count; view++) { // Source for data and written to as well, read and write. struct gfx_layer_view_state *state = &ls.views[view]; @@ -805,7 +805,7 @@ comp_render_gfx_layers(struct render_gfx *render, const VkClearColorValue *color = layer_count == 0 ? &background_color_idle : &background_color_active; - for (uint32_t view = 0; view < d->view_count; view++) { + for (uint32_t view = 0; view < d->squash_view_count; view++) { // Convenience. const struct render_viewport_data *viewport_data = &d->views[view].squash.viewport_data; @@ -886,6 +886,12 @@ comp_render_gfx_dispatch(struct render_gfx *render, const uint32_t layer_count, const struct comp_render_dispatch_data *d) { + if (!d->target.initialized) { + VK_ERROR(render->r->vk, "Target hasn't been initialized, not rendering anything."); + assert(d->target.initialized); + return; + } + // Convenience. bool fast_path = d->fast_path; @@ -902,7 +908,7 @@ comp_render_gfx_dispatch(struct render_gfx *render, // Fast path. const struct xrt_layer_projection_data *proj = &layer->data.proj; const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]; - for (uint32_t view = 0; view < d->view_count; ++view) { + for (uint32_t view = 0; view < d->target.view_count; ++view) { vds[view] = &proj->v[view]; } crg_distortion_fast_path( // @@ -915,7 +921,7 @@ comp_render_gfx_dispatch(struct render_gfx *render, // Fast path. const struct xrt_layer_projection_depth_data *depth = &layer->data.depth; const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]; - for (uint32_t view = 0; view < d->view_count; ++view) { + for (uint32_t view = 0; view < d->target.view_count; ++view) { vds[view] = &depth->v[view]; } crg_distortion_fast_path( // diff --git a/src/xrt/compositor/util/comp_render_helpers.h b/src/xrt/compositor/util/comp_render_helpers.h index ca20af0f2..9c8d60d3c 100644 --- a/src/xrt/compositor/util/comp_render_helpers.h +++ b/src/xrt/compositor/util/comp_render_helpers.h @@ -162,7 +162,7 @@ cmd_barrier_view_squash_images(struct vk_bundle *vk, .layerCount = 1, }; - for (uint32_t i = 0; i < d->view_count; i++) { + for (uint32_t i = 0; i < d->squash_view_count; i++) { bool already_barriered = false; VkImage image = d->views[i].squash.image;