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