The open source OpenXR runtime
at prediction-2 848 lines 31 kB view raw
1// Copyright 2019-2024, Collabora, Ltd. 2// Copyright 2025, NVIDIA CORPORATION. 3// SPDX-License-Identifier: BSL-1.0 4/*! 5 * @file 6 * @brief Compositor (compute shader) rendering code. 7 * @author Jakob Bornecrantz <jakob@collabora.com> 8 * @author Christoph Haag <christoph.haag@collabora.com> 9 * @author Fernando Velazquez Innella <finnella@magicleap.com> 10 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 11 * @ingroup comp_util 12 */ 13 14#include "util/comp_layer_accum.h" 15#include "xrt/xrt_compositor.h" 16 17#include "os/os_time.h" 18 19#include "math/m_api.h" 20#include "math/m_mathinclude.h" 21 22#include "util/u_misc.h" 23#include "util/u_trace_marker.h" 24 25#include "vk/vk_helpers.h" 26 27#include "render/render_interface.h" 28 29#include "shaders/layer_defines.inc.glsl" 30 31#include "util/comp_render.h" 32#include "util/comp_render_helpers.h" 33#include "util/comp_base.h" 34 35 36/* 37 * 38 * Helpers 39 * 40 */ 41 42static inline const struct comp_swapchain_image * 43get_layer_image(const struct comp_layer *layer, uint32_t swapchain_index, uint32_t image_index) 44{ 45 46 const struct comp_swapchain *sc = (struct comp_swapchain *)(comp_layer_get_swapchain(layer, swapchain_index)); 47 return &sc->images[image_index]; 48} 49 50static inline const struct comp_swapchain_image * 51get_layer_depth_image(const struct comp_layer *layer, uint32_t swapchain_index, uint32_t image_index) 52{ 53 54 const struct comp_swapchain *sc = 55 (struct comp_swapchain *)(comp_layer_get_depth_swapchain(layer, swapchain_index)); 56 return &sc->images[image_index]; 57} 58 59 60static inline uint32_t 61xrt_layer_to_cs_layer_type(const struct xrt_layer_data *data) 62{ 63 switch (data->type) { 64 case XRT_LAYER_QUAD: return LAYER_COMP_TYPE_QUAD; 65 case XRT_LAYER_CYLINDER: return LAYER_COMP_TYPE_CYLINDER; 66 case XRT_LAYER_EQUIRECT2: return LAYER_COMP_TYPE_EQUIRECT2; 67 case XRT_LAYER_PROJECTION: 68 case XRT_LAYER_PROJECTION_DEPTH: return LAYER_COMP_TYPE_PROJECTION; 69 default: U_LOG_E("Invalid layer type! %u", data->type); return LAYER_COMP_TYPE_NOOP; 70 } 71} 72 73 74/* 75 * 76 * Compute layer data builders. 77 * 78 */ 79 80/// Data setup for a cylinder layer 81static inline void 82do_cs_cylinder_layer(const struct comp_layer *layer, 83 const struct xrt_matrix_4x4 *eye_view_mat, 84 const struct xrt_matrix_4x4 *world_view_mat, 85 uint32_t view_index, 86 uint32_t cur_layer, 87 uint32_t cur_image, 88 VkSampler clamp_to_edge, 89 VkSampler clamp_to_border_black, 90 VkSampler src_samplers[RENDER_MAX_IMAGES_SIZE], 91 VkImageView src_image_views[RENDER_MAX_IMAGES_SIZE], 92 struct render_compute_layer_ubo_data *ubo_data, 93 uint32_t *out_cur_image) 94{ 95 const struct xrt_layer_data *layer_data = &layer->data; 96 const struct xrt_layer_cylinder_data *c = &layer_data->cylinder; 97 const uint32_t array_index = c->sub.array_index; 98 const struct comp_swapchain_image *image = get_layer_image(layer, 0, c->sub.image_index); 99 100 // Image to use. 101 src_samplers[cur_image] = clamp_to_edge; 102 src_image_views[cur_image] = get_image_view(image, layer_data->flags, array_index); 103 104 // Used for Subimage and OpenGL flip. 105 set_post_transform_rect( // 106 layer_data, // data 107 &c->sub.norm_rect, // src_norm_rect 108 false, // invert_flip 109 &ubo_data->post_transforms[cur_layer]); // out_norm_rect 110 111 ubo_data->cylinder_data[cur_layer].central_angle = c->central_angle; 112 ubo_data->cylinder_data[cur_layer].aspect_ratio = c->aspect_ratio; 113 114 struct xrt_vec3 scale = {1.f, 1.f, 1.f}; 115 116 struct xrt_matrix_4x4 model; 117 math_matrix_4x4_model(&c->pose, &scale, &model); 118 119 struct xrt_matrix_4x4 model_inv; 120 math_matrix_4x4_inverse(&model, &model_inv); 121 122 const struct xrt_matrix_4x4 *v = is_layer_view_space(layer_data) ? eye_view_mat : world_view_mat; 123 124 struct xrt_matrix_4x4 v_inv; 125 math_matrix_4x4_inverse(v, &v_inv); 126 127 math_matrix_4x4_multiply(&model_inv, &v_inv, &ubo_data->mv_inverse[cur_layer]); 128 129 // Simplifies the shader. 130 if (c->radius >= INFINITY) { 131 ubo_data->cylinder_data[cur_layer].radius = 0.f; 132 } else { 133 ubo_data->cylinder_data[cur_layer].radius = c->radius; 134 } 135 136 ubo_data->cylinder_data[cur_layer].central_angle = c->central_angle; 137 ubo_data->cylinder_data[cur_layer].aspect_ratio = c->aspect_ratio; 138 139 ubo_data->image_info[cur_layer].color_image_index = cur_image; 140 cur_image++; 141 142 *out_cur_image = cur_image; 143} 144 145/// Data setup for an "equirect2" layer 146static inline void 147do_cs_equirect2_layer(const struct comp_layer *layer, 148 const struct xrt_matrix_4x4 *eye_view_mat, 149 const struct xrt_matrix_4x4 *world_view_mat, 150 uint32_t view_index, 151 uint32_t cur_layer, 152 uint32_t cur_image, 153 VkSampler clamp_to_edge, 154 VkSampler clamp_to_border_black, 155 VkSampler src_samplers[RENDER_MAX_IMAGES_SIZE], 156 VkImageView src_image_views[RENDER_MAX_IMAGES_SIZE], 157 struct render_compute_layer_ubo_data *ubo_data, 158 uint32_t *out_cur_image) 159{ 160 const struct xrt_layer_data *layer_data = &layer->data; 161 const struct xrt_layer_equirect2_data *eq2 = &layer_data->equirect2; 162 const uint32_t array_index = eq2->sub.array_index; 163 const struct comp_swapchain_image *image = get_layer_image(layer, 0, eq2->sub.image_index); 164 165 // Image to use. 166 src_samplers[cur_image] = clamp_to_edge; 167 src_image_views[cur_image] = get_image_view(image, layer_data->flags, array_index); 168 169 // Used for Subimage and OpenGL flip. 170 set_post_transform_rect( // 171 layer_data, // data 172 &eq2->sub.norm_rect, // src_norm_rect 173 false, // invert_flip 174 &ubo_data->post_transforms[cur_layer]); // out_norm_rect 175 176 struct xrt_vec3 scale = {1.f, 1.f, 1.f}; 177 178 struct xrt_matrix_4x4 model; 179 math_matrix_4x4_model(&eq2->pose, &scale, &model); 180 181 struct xrt_matrix_4x4 model_inv; 182 math_matrix_4x4_inverse(&model, &model_inv); 183 184 const struct xrt_matrix_4x4 *v = is_layer_view_space(layer_data) ? eye_view_mat : world_view_mat; 185 186 struct xrt_matrix_4x4 v_inv; 187 math_matrix_4x4_inverse(v, &v_inv); 188 189 math_matrix_4x4_multiply(&model_inv, &v_inv, &ubo_data->mv_inverse[cur_layer]); 190 191 // Simplifies the shader. 192 if (eq2->radius >= INFINITY) { 193 ubo_data->eq2_data[cur_layer].radius = 0.f; 194 } else { 195 ubo_data->eq2_data[cur_layer].radius = eq2->radius; 196 } 197 198 ubo_data->eq2_data[cur_layer].central_horizontal_angle = eq2->central_horizontal_angle; 199 ubo_data->eq2_data[cur_layer].upper_vertical_angle = eq2->upper_vertical_angle; 200 ubo_data->eq2_data[cur_layer].lower_vertical_angle = eq2->lower_vertical_angle; 201 202 ubo_data->image_info[cur_layer].color_image_index = cur_image; 203 cur_image++; 204 205 *out_cur_image = cur_image; 206} 207 208/// Data setup for a projection layer 209static inline void 210do_cs_projection_layer(const struct comp_layer *layer, 211 const struct xrt_pose *world_pose_scanout_begin, 212 uint32_t view_index, 213 uint32_t cur_layer, 214 uint32_t cur_image, 215 VkSampler clamp_to_edge, 216 VkSampler clamp_to_border_black, 217 VkSampler src_samplers[RENDER_MAX_IMAGES_SIZE], 218 VkImageView src_image_views[RENDER_MAX_IMAGES_SIZE], 219 struct render_compute_layer_ubo_data *ubo_data, 220 bool do_timewarp, 221 uint32_t *out_cur_image) 222{ 223 const struct xrt_layer_data *layer_data = &layer->data; 224 const struct xrt_layer_projection_view_data *vd = NULL; 225 const struct xrt_layer_depth_data *dvd = NULL; 226 227 if (layer_data->type == XRT_LAYER_PROJECTION) { 228 view_index_to_projection_data(view_index, layer_data, &vd); 229 } else { 230 view_index_to_depth_data(view_index, layer_data, &vd, &dvd); 231 } 232 233 uint32_t sc_array_index = is_view_index_right(view_index) ? 1 : 0; 234 uint32_t array_index = vd->sub.array_index; 235 const struct comp_swapchain_image *image = get_layer_image(layer, sc_array_index, vd->sub.image_index); 236 237 // Color 238 src_samplers[cur_image] = clamp_to_border_black; 239 src_image_views[cur_image] = get_image_view(image, layer_data->flags, array_index); 240 ubo_data->image_info[cur_layer + 0].color_image_index = cur_image++; 241 242 // Depth 243 if (layer_data->type == XRT_LAYER_PROJECTION_DEPTH) { 244 uint32_t d_array_index = dvd->sub.array_index; 245 const struct comp_swapchain_image *d_image = 246 get_layer_depth_image(layer, sc_array_index, dvd->sub.image_index); 247 248 src_samplers[cur_image] = clamp_to_edge; // Edge to keep depth stable at edges. 249 src_image_views[cur_image] = get_image_view(d_image, layer_data->flags, d_array_index); 250 ubo_data->image_info[cur_layer + 0].depth_image_index = cur_image++; 251 } 252 253 set_post_transform_rect( // 254 layer_data, // data 255 &vd->sub.norm_rect, // src_norm_rect 256 false, // invert_flip 257 &ubo_data->post_transforms[cur_layer]); // out_norm_rect 258 259 // unused if timewarp is off 260 if (do_timewarp) { 261 render_calc_time_warp_matrix( // 262 &vd->pose, // 263 &vd->fov, // 264 world_pose_scanout_begin, // 265 &ubo_data->transforms_timewarp[cur_layer]); // 266 } 267 268 *out_cur_image = cur_image; 269} 270 271/// Data setup for a quad layer 272static inline void 273do_cs_quad_layer(const struct comp_layer *layer, 274 const struct xrt_matrix_4x4 *eye_view_mat, 275 const struct xrt_matrix_4x4 *world_view_mat, 276 uint32_t view_index, 277 uint32_t cur_layer, 278 uint32_t cur_image, 279 VkSampler clamp_to_edge, 280 VkSampler clamp_to_border_black, 281 VkSampler src_samplers[RENDER_MAX_IMAGES_SIZE], 282 VkImageView src_image_views[RENDER_MAX_IMAGES_SIZE], 283 struct render_compute_layer_ubo_data *ubo_data, 284 uint32_t *out_cur_image) 285{ 286 const struct xrt_layer_data *layer_data = &layer->data; 287 const struct xrt_layer_quad_data *q = &layer_data->quad; 288 const uint32_t array_index = q->sub.array_index; 289 const struct comp_swapchain_image *image = get_layer_image(layer, 0, q->sub.image_index); 290 291 // Image to use. 292 src_samplers[cur_image] = clamp_to_edge; 293 src_image_views[cur_image] = get_image_view(image, layer_data->flags, array_index); 294 295 // Set the normalized post transform values. 296 struct xrt_normalized_rect post_transform = XRT_STRUCT_INIT; 297 298 // Used for Subimage and OpenGL flip. 299 set_post_transform_rect( // 300 layer_data, // data 301 &q->sub.norm_rect, // src_norm_rect 302 true, // invert_flip 303 &post_transform); // out_norm_rect 304 305 // Is this layer viewspace or not. 306 const struct xrt_matrix_4x4 *view_mat = is_layer_view_space(layer_data) ? eye_view_mat : world_view_mat; 307 308 // Transform quad pose into view space. 309 struct xrt_vec3 quad_position = XRT_STRUCT_INIT; 310 math_matrix_4x4_transform_vec3(view_mat, &layer_data->quad.pose.position, &quad_position); 311 312 // neutral quad layer faces +z, towards the user 313 struct xrt_vec3 normal = (struct xrt_vec3){.x = 0, .y = 0, .z = 1}; 314 315 // rotation of the quad normal in world space 316 struct xrt_quat rotation = layer_data->quad.pose.orientation; 317 math_quat_rotate_vec3(&rotation, &normal, &normal); 318 319 /* 320 * normal is a vector that originates on the plane, not on the origin. 321 * Instead of using the inverse quad transform to transform it into view space we can 322 * simply add up vectors: 323 * 324 * combined_normal [in world space] = plane_origin [in world space] + normal [in plane 325 * space] [with plane in world space] 326 * 327 * Then combined_normal can be transformed to view space via view matrix and a new 328 * normal_view_space retrieved: 329 * 330 * normal_view_space = combined_normal [in view space] - plane_origin [in view space] 331 */ 332 struct xrt_vec3 normal_view_space = normal; 333 math_vec3_accum(&layer_data->quad.pose.position, &normal_view_space); 334 math_matrix_4x4_transform_vec3(view_mat, &normal_view_space, &normal_view_space); 335 math_vec3_subtract(&quad_position, &normal_view_space); 336 337 struct xrt_vec3 scale = {1.f, 1.f, 1.f}; 338 struct xrt_matrix_4x4 plane_transform_view_space, inverse_quad_transform; 339 math_matrix_4x4_model(&layer_data->quad.pose, &scale, &plane_transform_view_space); 340 math_matrix_4x4_multiply(view_mat, &plane_transform_view_space, &plane_transform_view_space); 341 math_matrix_4x4_inverse(&plane_transform_view_space, &inverse_quad_transform); 342 343 // Write all of the UBO data. 344 ubo_data->post_transforms[cur_layer] = post_transform; 345 ubo_data->quad_extent[cur_layer].val = layer_data->quad.size; 346 ubo_data->quad_position[cur_layer].val = quad_position; 347 ubo_data->quad_normal[cur_layer].val = normal_view_space; 348 ubo_data->inverse_quad_transform[cur_layer] = inverse_quad_transform; 349 ubo_data->image_info[cur_layer].color_image_index = cur_image; 350 cur_image++; 351 352 *out_cur_image = cur_image; 353} 354 355static void 356crc_clear_output(struct render_compute *render, const struct comp_render_dispatch_data *d) 357{ 358 if (d->target.view_count > XRT_MAX_VIEWS) { 359 U_LOG_E("Only supports max %d views!", XRT_MAX_VIEWS); 360 assert(d->target.view_count <= XRT_MAX_VIEWS); 361 return; 362 } 363 364 struct render_viewport_data target_viewport_datas[XRT_MAX_VIEWS]; 365 for (uint32_t i = 0; i < d->target.view_count; ++i) { 366 target_viewport_datas[i] = d->views[i].target.viewport_data; 367 } 368 369 370 render_compute_clear( // 371 render, // 372 d->target.cs.image, // 373 d->target.cs.storage_view, // target_image_view 374 target_viewport_datas); // views 375} 376 377/* 378 * 379 * Compute distortion helpers. 380 * 381 */ 382 383/// For use after squashing layers 384static void 385crc_distortion_after_squash(struct render_compute *render, const struct comp_render_dispatch_data *d) 386{ 387 if (d->target.view_count > XRT_MAX_VIEWS) { 388 U_LOG_E("Only supports max %d views!", XRT_MAX_VIEWS); 389 assert(d->target.view_count <= XRT_MAX_VIEWS); 390 return; 391 } 392 VkSampler clamp_to_border_black = render->r->samplers.clamp_to_border_black; 393 394 // Data to fill in. 395 VkImageView src_image_views[XRT_MAX_VIEWS]; 396 VkSampler src_samplers[XRT_MAX_VIEWS]; 397 struct render_viewport_data target_viewport_datas[XRT_MAX_VIEWS]; 398 struct xrt_normalized_rect src_norm_rects[XRT_MAX_VIEWS]; 399 struct xrt_fov src_fovs[XRT_MAX_VIEWS]; 400 struct xrt_pose world_poses_scanout_begin[XRT_MAX_VIEWS]; 401 struct xrt_pose world_poses_scanout_end[XRT_MAX_VIEWS]; 402 403 for (uint32_t i = 0; i < d->target.view_count; i++) { 404 // Data to be filled in. 405 VkImageView src_image_view; 406 struct render_viewport_data viewport_data; 407 struct xrt_normalized_rect src_norm_rect; 408 409 // Gather data. 410 src_image_view = d->views[i].squash_as_src.sample_view; 411 src_norm_rect = d->views[i].squash_as_src.norm_rect; 412 viewport_data = d->views[i].target.viewport_data; 413 414 // Fill in data. 415 src_image_views[i] = src_image_view; 416 src_norm_rects[i] = src_norm_rect; 417 src_samplers[i] = clamp_to_border_black; 418 target_viewport_datas[i] = viewport_data; 419 420 if (d->do_timewarp) { 421 world_poses_scanout_begin[i] = d->views[i].world_pose_scanout_begin; 422 world_poses_scanout_end[i] = d->views[i].world_pose_scanout_end; 423 src_fovs[i] = d->views[i].fov; 424 } 425 } 426 427 if (!d->do_timewarp) { 428 render_compute_projection_no_timewarp( // 429 render, // 430 src_samplers, // 431 src_image_views, // 432 src_norm_rects, // 433 d->target.cs.image, // 434 d->target.cs.storage_view, // target_image_view 435 target_viewport_datas); // views 436 } else { 437 render_compute_projection_scanout_compensation( // 438 render, // 439 src_samplers, // 440 src_image_views, // 441 src_norm_rects, // 442 src_fovs, // 443 world_poses_scanout_begin, // 444 world_poses_scanout_end, // 445 d->target.cs.image, // 446 d->target.cs.storage_view, // target_image_view 447 target_viewport_datas); // views 448 } 449} 450 451/// Fast path 452static void 453crc_distortion_fast_path(struct render_compute *render, 454 const struct comp_render_dispatch_data *d, 455 const struct comp_layer *layer, 456 const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]) 457{ 458 if (d->target.view_count > XRT_MAX_VIEWS) { 459 U_LOG_E("Only supports max %d views!", XRT_MAX_VIEWS); 460 assert(d->target.view_count <= XRT_MAX_VIEWS); 461 return; 462 } 463 464 // Fetch from this data. 465 const struct xrt_layer_data *data = &layer->data; 466 467 VkSampler clamp_to_border_black = render->r->samplers.clamp_to_border_black; 468 469 // Data to fill in. 470 VkImageView src_image_views[XRT_MAX_VIEWS]; 471 VkSampler src_samplers[XRT_MAX_VIEWS]; 472 struct render_viewport_data target_viewport_datas[XRT_MAX_VIEWS]; 473 struct xrt_normalized_rect src_norm_rects[XRT_MAX_VIEWS]; 474 struct xrt_fov src_fovs[XRT_MAX_VIEWS]; 475 struct xrt_pose src_poses[XRT_MAX_VIEWS]; 476 struct xrt_pose world_poses_scanout_begin[XRT_MAX_VIEWS]; 477 struct xrt_pose world_poses_scanout_end[XRT_MAX_VIEWS]; 478 479 for (uint32_t i = 0; i < d->target.view_count; i++) { 480 // Data to be filled in. 481 VkImageView src_image_view; 482 struct render_viewport_data viewport_data; 483 struct xrt_normalized_rect src_norm_rect; 484 struct xrt_fov src_fov; 485 struct xrt_pose src_pose; 486 struct xrt_pose world_pose_scanout_begin; 487 struct xrt_pose world_pose_scanout_end; 488 uint32_t array_index = vds[i]->sub.array_index; 489 const struct comp_swapchain_image *image = get_layer_image(layer, i, vds[i]->sub.image_index); 490 491 // Gather data. 492 src_image_view = get_image_view(image, data->flags, array_index); 493 src_norm_rect = vds[i]->sub.norm_rect; 494 viewport_data = d->views[i].target.viewport_data; 495 src_fov = vds[i]->fov; 496 src_pose = vds[i]->pose; 497 world_pose_scanout_begin = d->views[i].world_pose_scanout_begin; 498 world_pose_scanout_end = d->views[i].world_pose_scanout_end; 499 500 // No layer squasher has handled this for us already 501 if (data->flip_y) { 502 src_norm_rect.y += src_norm_rect.h; 503 src_norm_rect.h = -src_norm_rect.h; 504 } 505 506 // Fill in data. 507 src_image_views[i] = src_image_view; 508 src_norm_rects[i] = src_norm_rect; 509 src_samplers[i] = clamp_to_border_black; 510 target_viewport_datas[i] = viewport_data; 511 src_fovs[i] = src_fov; 512 src_poses[i] = src_pose; 513 world_poses_scanout_begin[i] = world_pose_scanout_begin; 514 world_poses_scanout_end[i] = world_pose_scanout_end; 515 } 516 517 if (!d->do_timewarp) { 518 render_compute_projection_no_timewarp( // 519 render, // 520 src_samplers, // 521 src_image_views, // 522 src_norm_rects, // 523 d->target.cs.image, // 524 d->target.cs.storage_view, // 525 target_viewport_datas); // 526 } else { 527 render_compute_projection_timewarp( // 528 render, // 529 src_samplers, // 530 src_image_views, // 531 src_norm_rects, // 532 src_poses, // 533 src_fovs, // 534 world_poses_scanout_begin, // 535 world_poses_scanout_end, // 536 d->target.cs.image, // 537 d->target.cs.storage_view, // 538 target_viewport_datas); // 539 } 540} 541 542 543/* 544 * 545 * 'Exported' function(s). 546 * 547 */ 548 549void 550comp_render_cs_layer(struct render_compute *render, 551 uint32_t view_index, 552 const struct comp_layer *layers, 553 const uint32_t layer_count, 554 const struct xrt_normalized_rect *pre_transform, 555 const struct xrt_pose *world_pose_scanout_begin, 556 const struct xrt_pose *world_pose_scanout_end, 557 const struct xrt_pose *eye_pose, 558 const VkImage target_image, 559 const VkImageView target_image_view, 560 const struct render_viewport_data *target_view, 561 bool do_timewarp) 562{ 563 VkSampler clamp_to_edge = render->r->samplers.clamp_to_edge; 564 VkSampler clamp_to_border_black = render->r->samplers.clamp_to_border_black; 565 566 // Not the transform of the views, but the inverse: actual view matrices. 567 struct xrt_matrix_4x4 world_view_mat_scanout_begin, eye_view; 568 math_matrix_4x4_view_from_pose(world_pose_scanout_begin, &world_view_mat_scanout_begin); 569 math_matrix_4x4_view_from_pose(eye_pose, &eye_view); 570 571 struct render_buffer *ubo = &render->r->compute.layer.ubos[view_index]; 572 struct render_compute_layer_ubo_data *ubo_data = ubo->mapped; 573 574 // Tightly pack layers in data struct. 575 uint32_t cur_layer = 0; 576 577 // Tightly pack color and optional depth images. 578 uint32_t cur_image = 0; 579 VkSampler src_samplers[RENDER_MAX_IMAGES_SIZE]; 580 VkImageView src_image_views[RENDER_MAX_IMAGES_SIZE]; 581 582 ubo_data->view = *target_view; 583 ubo_data->pre_transform = *pre_transform; 584 585 for (uint32_t c_layer_i = 0; c_layer_i < layer_count; c_layer_i++) { 586 const struct comp_layer *layer = &layers[c_layer_i]; 587 const struct xrt_layer_data *data = &layer->data; 588 589 if (!is_layer_view_visible(data, view_index)) { 590 continue; 591 } 592 593 /*! 594 * Stop compositing layers if device's sampled image limit is 595 * reached. For most hardware this isn't a problem, most have 596 * well over 32 max samplers. But notably the RPi4 only have 16 597 * which is a limit we may run into. But if you got 16+ layers 598 * on a RPi4 you have more problems then max samplers. 599 */ 600 uint32_t required_image_samplers; 601 switch (data->type) { 602 case XRT_LAYER_CYLINDER: required_image_samplers = 1; break; 603 case XRT_LAYER_EQUIRECT2: required_image_samplers = 1; break; 604 case XRT_LAYER_PROJECTION: required_image_samplers = 1; break; 605 case XRT_LAYER_PROJECTION_DEPTH: required_image_samplers = 2; break; 606 case XRT_LAYER_QUAD: required_image_samplers = 1; break; 607 default: 608 VK_ERROR(render->r->vk, "Skipping layer #%u, unknown type: %u", c_layer_i, data->type); 609 continue; // Skip this layer if don't know about it. 610 } 611 612 //! Exit loop if shader cannot receive more image samplers 613 if (cur_image + required_image_samplers > render->r->compute.layer.image_array_size) { 614 break; 615 } 616 617 switch (data->type) { 618 case XRT_LAYER_CYLINDER: 619 do_cs_cylinder_layer( // 620 layer, // layer 621 &eye_view, // eye_view_mat 622 &world_view_mat_scanout_begin, // world_view_mat 623 view_index, // view_index 624 cur_layer, // cur_layer 625 cur_image, // cur_image 626 clamp_to_edge, // clamp_to_edge 627 clamp_to_border_black, // clamp_to_border_black 628 src_samplers, // src_samplers 629 src_image_views, // src_image_views 630 ubo_data, // ubo_data 631 &cur_image); // out_cur_image 632 break; 633 case XRT_LAYER_EQUIRECT2: 634 do_cs_equirect2_layer( // 635 layer, // layer 636 &eye_view, // eye_view_mat 637 &world_view_mat_scanout_begin, // world_view_mat 638 view_index, // view_index 639 cur_layer, // cur_layer 640 cur_image, // cur_image 641 clamp_to_edge, // clamp_to_edge 642 clamp_to_border_black, // clamp_to_border_black 643 src_samplers, // src_samplers 644 src_image_views, // src_image_views 645 ubo_data, // ubo_data 646 &cur_image); // out_cur_image 647 break; 648 case XRT_LAYER_PROJECTION_DEPTH: 649 case XRT_LAYER_PROJECTION: { 650 do_cs_projection_layer( // 651 layer, // layer 652 world_pose_scanout_begin, // world_pose_scanout_begin 653 view_index, // view_index 654 cur_layer, // cur_layer 655 cur_image, // cur_image 656 clamp_to_edge, // clamp_to_edge 657 clamp_to_border_black, // clamp_to_border_black 658 src_samplers, // src_samplers 659 src_image_views, // src_image_views 660 ubo_data, // ubo_data 661 do_timewarp, // do_timewarp 662 &cur_image); // out_cur_image 663 } break; 664 case XRT_LAYER_QUAD: { 665 do_cs_quad_layer( // 666 layer, // layer 667 &eye_view, // eye_view_mat 668 &world_view_mat_scanout_begin, // world_view_mat_scanout_begin 669 view_index, // view_index 670 cur_layer, // cur_layer 671 cur_image, // cur_image 672 clamp_to_edge, // clamp_to_edge 673 clamp_to_border_black, // clamp_to_border_black 674 src_samplers, // src_samplers 675 src_image_views, // src_image_views 676 ubo_data, // ubo_data 677 &cur_image); // out_cur_image 678 } break; 679 default: 680 // Should not get here! 681 assert(false); 682 VK_ERROR(render->r->vk, "Should not get here!"); 683 continue; 684 } 685 686 ubo_data->layer_data[cur_layer].layer_type = xrt_layer_to_cs_layer_type(data); 687 ubo_data->layer_data[cur_layer].unpremultiplied_alpha = is_layer_unpremultiplied(data); 688 689 // Finally okay to increment the current layer. 690 cur_layer++; 691 } 692 693 // Set the number of layers. 694 ubo_data->layer_count.value = cur_layer; 695 696 for (uint32_t i = cur_layer; i < RENDER_MAX_LAYERS; i++) { 697 ubo_data->layer_data[i].layer_type = LAYER_COMP_TYPE_NOOP; // Explicit no-op. 698 } 699 700 //! @todo: If Vulkan 1.2, use VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT and skip this 701 while (cur_image < render->r->compute.layer.image_array_size) { 702 src_samplers[cur_image] = clamp_to_edge; 703 src_image_views[cur_image] = render->r->mock.color.image_view; 704 cur_image++; 705 } 706 707 VkDescriptorSet descriptor_set = render->layer_descriptor_sets[view_index]; 708 709 render_compute_layers( // 710 render, // 711 descriptor_set, // 712 ubo->buffer, // 713 src_samplers, // 714 src_image_views, // 715 cur_image, // 716 target_image_view, // 717 target_view, // 718 do_timewarp); // 719} 720 721void 722comp_render_cs_layers(struct render_compute *render, 723 const struct comp_layer *layers, 724 const uint32_t layer_count, 725 const struct comp_render_dispatch_data *d, 726 VkImageLayout transition_to) 727{ 728 cmd_barrier_view_squash_images( // 729 render->r->vk, // 730 d, // 731 render->r->cmd, // cmd 732 0, // src_access_mask 733 VK_ACCESS_SHADER_WRITE_BIT, // dst_access_mask 734 VK_IMAGE_LAYOUT_UNDEFINED, // transition_from 735 VK_IMAGE_LAYOUT_GENERAL, // transition_to 736 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // src_stage_mask 737 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); // dst_stage_mask 738 739 for (uint32_t view_index = 0; view_index < d->squash_view_count; view_index++) { 740 const struct comp_render_view_data *view = &d->views[view_index]; 741 742 comp_render_cs_layer( // 743 render, // 744 view_index, // 745 layers, // 746 layer_count, // 747 &view->pre_transform, // 748 &view->world_pose_scanout_begin, // 749 &view->world_pose_scanout_end, // 750 &view->eye_pose, // 751 view->squash.image, // 752 view->squash.cs.storage_view, // 753 &view->squash.viewport_data, // 754 d->do_timewarp); // 755 } 756 757 cmd_barrier_view_squash_images( // 758 render->r->vk, // 759 d, // 760 render->r->cmd, // cmd 761 VK_ACCESS_SHADER_WRITE_BIT, // src_access_mask 762 VK_ACCESS_MEMORY_READ_BIT, // dst_access_mask 763 VK_IMAGE_LAYOUT_GENERAL, // transition_from 764 transition_to, // 765 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // src_stage_mask 766 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); // dst_stage_mask 767} 768 769void 770comp_render_cs_dispatch(struct render_compute *render, 771 const struct comp_layer *layers, 772 const uint32_t layer_count, 773 const struct comp_render_dispatch_data *d) 774{ 775 if (!d->target.initialized) { 776 VK_ERROR(render->r->vk, "Target hasn't been initialized, not rendering anything."); 777 assert(d->target.initialized); 778 return; 779 } 780 781 // Convenience. 782 bool fast_path = d->fast_path; 783 784 // Only used if fast_path is true. 785 const struct comp_layer *layer = &layers[0]; 786 787 // Consistency check. 788 assert(!fast_path || layer_count >= 1); 789 790 // We want to read from the images afterwards. 791 VkImageLayout transition_to = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 792 793 if (fast_path && layer->data.type == XRT_LAYER_PROJECTION) { 794 // Fast path. 795 const struct xrt_layer_projection_data *proj = &layer->data.proj; 796 const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]; 797 for (uint32_t view = 0; view < d->target.view_count; ++view) { 798 vds[view] = &proj->v[view]; 799 } 800 crc_distortion_fast_path( // 801 render, // 802 d, // 803 layer, // 804 vds); // 805 806 } else if (fast_path && layer->data.type == XRT_LAYER_PROJECTION_DEPTH) { 807 // Fast path. 808 const struct xrt_layer_projection_depth_data *depth = &layer->data.depth; 809 const struct xrt_layer_projection_view_data *vds[XRT_MAX_VIEWS]; 810 for (uint32_t view = 0; view < d->target.view_count; ++view) { 811 vds[view] = &depth->v[view]; 812 } 813 crc_distortion_fast_path( // 814 render, // 815 d, // 816 layer, // 817 vds); // 818 819 } else if (layer_count > 0) { 820 // Compute layer squasher 821 if (fast_path) { 822 U_LOG_W("Wanted fast path but no projection layer, falling back to layer squasher."); 823 } 824 825 /* 826 * Layer squashing. 827 */ 828 comp_render_cs_layers( // 829 render, // 830 layers, // 831 layer_count, // 832 d, // 833 transition_to); // 834 835 /* 836 * Distortion. 837 */ 838 crc_distortion_after_squash( // 839 render, // 840 d); // 841 842 } else { 843 // Just clear the screen 844 crc_clear_output( // 845 render, // 846 d); // 847 } 848}