The open source OpenXR runtime
at prediction-2 1437 lines 39 kB view raw
1// Copyright 2019-2023, Collabora, Ltd. 2// Copyright 2025, NVIDIA CORPORATION. 3// SPDX-License-Identifier: BSL-1.0 4/*! 5 * @file 6 * @brief The NEW compositor rendering code header. 7 * @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com> 8 * @author Jakob Bornecrantz <jakob@collabora.com> 9 * @ingroup comp_render 10 */ 11 12#pragma once 13 14#include "xrt/xrt_compiler.h" 15#include "xrt/xrt_defines.h" 16 17#include "vk/vk_helpers.h" 18#include "vk/vk_cmd_pool.h" 19 20 21#ifdef __cplusplus 22extern "C" { 23#endif 24 25 26/*! 27 * @defgroup comp_render Compositor render code 28 * @ingroup comp 29 * 30 * @brief Rendering helper that is used by the compositor to render. 31 */ 32 33/*! 34 * @addtogroup comp_render 35 * @{ 36 */ 37 38/* 39 * 40 * Defines 41 * 42 */ 43 44/*! 45 * The value `minUniformBufferOffsetAlignment` is defined by the Vulkan spec as 46 * having a max value of 256. Use this value to safely figure out sizes and 47 * alignment of UBO sub-allocation. It is also the max for 'nonCoherentAtomSize` 48 * which if we need to do flushing is what we need to align UBOs to. 49 * 50 * https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceLimits.html 51 * https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#limits-minmax 52 */ 53#define RENDER_ALWAYS_SAFE_UBO_ALIGNMENT (256) 54 55/*! 56 * Max number of layers for layer squasher, can be different from 57 * @ref XRT_MAX_LAYERS as the render module is separate from the compositor. 58 */ 59#define RENDER_MAX_LAYERS (XRT_MAX_LAYERS) 60 61/*! 62 * Max number of images that can be given at a single time to the layer 63 * squasher in a single dispatch. 64 */ 65#define RENDER_MAX_IMAGES_SIZE (RENDER_MAX_LAYERS * XRT_MAX_VIEWS) 66#define RENDER_MAX_IMAGES_COUNT(RENDER_RESOURCES) (RENDER_MAX_LAYERS * RENDER_RESOURCES->view_count) 67 68/*! 69 * Maximum number of times that the layer squasher shader can run per 70 * @ref render_compute. Since you run the layer squasher shader once per view 71 * this is essentially the same as number of views. But if you were to do 72 * two or more different compositions it is not the maximum number of views per 73 * composition (which is this number divided by number of composition). 74 */ 75#define RENDER_MAX_LAYER_RUNS_SIZE (XRT_MAX_VIEWS) 76#define RENDER_MAX_LAYER_RUNS_COUNT(RENDER_RESOURCES) (RENDER_RESOURCES->view_count) 77 78//! Distortion image dimension in pixels 79#define RENDER_DISTORTION_IMAGE_DIMENSIONS (128) 80 81//! How many distortion images we have, one for each channel (3 rgb) and per view. 82#define RENDER_DISTORTION_IMAGES_SIZE (3 * XRT_MAX_VIEWS) 83#define RENDER_DISTORTION_IMAGES_COUNT(RENDER_RESOURCES) (3 * RENDER_RESOURCES->view_count) 84 85//! The binding that the layer projection and quad shader have their UBO on. 86#define RENDER_BINDING_LAYER_SHARED_UBO 0 87 88//! The binding that the shared layer fragment shader has its source on. 89#define RENDER_BINDING_LAYER_SHARED_SRC 1 90 91 92/* 93 * 94 * Util functions. 95 * 96 */ 97 98/*! 99 * Create a simplified projection matrix for timewarp. 100 */ 101void 102render_calc_time_warp_projection(const struct xrt_fov *fov, struct xrt_matrix_4x4 *result); 103 104/*! 105 * Calculates a timewarp matrix which takes in NDC coords and gives out results 106 * in [-1, 1] space that needs a perspective divide. 107 */ 108void 109render_calc_time_warp_matrix(const struct xrt_pose *src_pose, 110 const struct xrt_fov *src_fov, 111 const struct xrt_pose *new_pose, 112 struct xrt_matrix_4x4 *matrix); 113 114/*! 115 * This function constructs a transformation in the form of a normalized rect 116 * that lets you go from a UV coordinate on a projection plane to the a point on 117 * the tangent plane. An example is that the UV coordinate `(0, 0)` would be 118 * transformed to `(tan(angle_left), tan(fov.angle_up))`. The tangent plane (aka 119 * tangent space) is really the tangent of the angle, aka length at unit distance. 120 * 121 * For the trivial case of an fov with 45 degrees angles, that is where the 122 * tangent length are `1` (aka `tan(45)`), the transformation would go from 123 * `[0 .. 1]` to `[-1 .. 1]` the expected returns are `x = -1`, `y = -1`, 124 * `w = 2` and `h = 2`. 125 * 126 * param fov The fov of the projection image. 127 * param[out] out_rect Transformation from UV to tangent lengths. 128 */ 129void 130render_calc_uv_to_tangent_lengths_rect(const struct xrt_fov *fov, struct xrt_normalized_rect *out_rect); 131 132 133/* 134 * 135 * Shaders. 136 * 137 */ 138 139/*! 140 * Holds all shaders. 141 */ 142struct render_shaders 143{ 144 VkShaderModule blit_comp; 145 VkShaderModule clear_comp; 146 VkShaderModule layer_comp; 147 VkShaderModule distortion_comp; 148 149 VkShaderModule mesh_vert; 150 VkShaderModule mesh_frag; 151 152 153 /* 154 * New layer renderer. 155 */ 156 157 VkShaderModule layer_cylinder_vert; 158 VkShaderModule layer_cylinder_frag; 159 160 VkShaderModule layer_equirect2_vert; 161 VkShaderModule layer_equirect2_frag; 162 163 VkShaderModule layer_projection_vert; 164 VkShaderModule layer_quad_vert; 165 VkShaderModule layer_shared_frag; 166}; 167 168/*! 169 * Loads all of the shaders that the compositor uses. 170 */ 171bool 172render_shaders_load(struct render_shaders *s, struct vk_bundle *vk); 173 174/*! 175 * Unload and cleanup shaders. 176 */ 177void 178render_shaders_fini(struct render_shaders *s, struct vk_bundle *vk); 179 180 181/* 182 * 183 * Buffer 184 * 185 */ 186 187/*! 188 * Helper struct holding a buffer and its memory. 189 */ 190struct render_buffer 191{ 192 //! Backing memory. 193 VkDeviceMemory memory; 194 195 //! Buffer. 196 VkBuffer buffer; 197 198 //! Size requested for the buffer. 199 VkDeviceSize size; 200 201 //! Size of the memory allocation. 202 VkDeviceSize allocation_size; 203 204 //! Alignment of the buffer. 205 VkDeviceSize alignment; 206 207 void *mapped; 208}; 209 210/*! 211 * Initialize a buffer. 212 */ 213VkResult 214render_buffer_init(struct vk_bundle *vk, 215 struct render_buffer *buffer, 216 VkBufferUsageFlags usage_flags, 217 VkMemoryPropertyFlags memory_property_flags, 218 VkDeviceSize size); 219 220/*! 221 * Initialize a buffer, making it exportable. 222 */ 223VkResult 224render_buffer_init_exportable(struct vk_bundle *vk, 225 struct render_buffer *buffer, 226 VkBufferUsageFlags usage_flags, 227 VkMemoryPropertyFlags memory_property_flags, 228 VkDeviceSize size); 229 230/*! 231 * Frees all resources that this buffer has, but does not free the buffer itself. 232 */ 233void 234render_buffer_fini(struct vk_bundle *vk, struct render_buffer *buffer); 235 236/*! 237 * Maps the memory, sets render_buffer::mapped to the memory. 238 */ 239VkResult 240render_buffer_map(struct vk_bundle *vk, struct render_buffer *buffer); 241 242/*! 243 * Unmaps the memory. 244 */ 245void 246render_buffer_unmap(struct vk_bundle *vk, struct render_buffer *buffer); 247 248/*! 249 * Maps the buffer, and copies the given data to the buffer. 250 */ 251VkResult 252render_buffer_map_and_write(struct vk_bundle *vk, struct render_buffer *buffer, void *data, VkDeviceSize size); 253 254/*! 255 * Writes the given data to the buffer, will map it temporarily if not mapped. 256 */ 257VkResult 258render_buffer_write(struct vk_bundle *vk, struct render_buffer *buffer, void *data, VkDeviceSize size); 259 260 261/* 262 * 263 * Sub-alloc. 264 * 265 */ 266 267/*! 268 * Per frame sub-allocation into a buffer, used to reduce the number of UBO 269 * objects we need to create. There is no way to free a sub-allocation, this is 270 * done implicitly at the end of the frame when @ref render_sub_alloc_tracker is 271 * zeroed out. 272 * 273 * @see render_sub_alloc_tracker 274 */ 275struct render_sub_alloc 276{ 277 /*! 278 * The buffer this is allocated from, it is the caller's responsibility 279 * to keep it alive for as long as the sub-allocation is used. 280 */ 281 VkBuffer buffer; 282 283 //! Size of sub-allocation. 284 VkDeviceSize size; 285 286 //! Offset into buffer. 287 VkDeviceSize offset; 288}; 289 290/*! 291 * A per-frame tracker of sub-allocation out of a buffer, used to reduce the 292 * number of UBO objects we need to create. This code is designed with one 293 * constraint in mind, that the lifetime of a sub-allocation is only for one 294 * frame and is discarded at the end of it, but also alive for the entire frame. 295 * This removes the need to free individual sub-allocation, or even track them 296 * beyond filling the UBO data and descriptor sets. 297 * 298 * @see render_sub_alloc 299 */ 300struct render_sub_alloc_tracker 301{ 302 /*! 303 * The buffer to allocate from, it is the caller's responsibility to keep 304 * it alive for as long as the sub-allocations are in used. 305 */ 306 VkBuffer buffer; 307 308 //! Start of memory, if buffer was mapped with initialised. 309 void *mapped; 310 311 //! Total size of buffer. 312 VkDeviceSize total_size; 313 314 //! Currently used memory. 315 VkDeviceSize used; 316}; 317 318/*! 319 * Init a @ref render_sub_alloc_tracker struct from a @ref render_buffer, the 320 * caller is responsible for keeping @p buffer alive while the sub allocator 321 * is being used. 322 */ 323void 324render_sub_alloc_tracker_init(struct render_sub_alloc_tracker *rsat, struct render_buffer *buffer); 325 326/*! 327 * Allocate enough memory (with constraints of UBOs) of @p size, return the 328 * pointer to the mapped memory or null if the buffer wasn't allocated. 329 */ 330XRT_CHECK_RESULT VkResult 331render_sub_alloc_ubo_alloc_and_get_ptr(struct vk_bundle *vk, 332 struct render_sub_alloc_tracker *rsat, 333 VkDeviceSize size, 334 void **out_ptr, 335 struct render_sub_alloc *out_rsa); 336 337/*! 338 * Allocate enough memory (with constraints of UBOs) to hold the memory in @p ptr 339 * and copy that memory to the buffer using the CPU. 340 */ 341XRT_CHECK_RESULT VkResult 342render_sub_alloc_ubo_alloc_and_write(struct vk_bundle *vk, 343 struct render_sub_alloc_tracker *rsat, 344 const void *ptr, 345 VkDeviceSize size, 346 struct render_sub_alloc *out_rsa); 347 348 349/* 350 * 351 * Resources 352 * 353 */ 354 355/*! 356 * Holds all pools and static resources for rendering. 357 */ 358struct render_resources 359{ 360 //! The count of views that we are rendering to. 361 uint32_t view_count; 362 363 //! Vulkan resources. 364 struct vk_bundle *vk; 365 366 /* 367 * Loaded resources. 368 */ 369 370 //! All shaders loaded. 371 struct render_shaders *shaders; 372 373 374 /* 375 * Shared pools and caches. 376 */ 377 378 //! Pool used for distortion image uploads. 379 struct vk_cmd_pool distortion_pool; 380 381 //! Shared for all rendering. 382 VkPipelineCache pipeline_cache; 383 384 VkCommandPool cmd_pool; 385 386 VkQueryPool query_pool; 387 388 389 /* 390 * Static 391 */ 392 393 //! Command buffer for recording everything. 394 VkCommandBuffer cmd; 395 396 struct 397 { 398 //! Sampler for mock/null images. 399 VkSampler mock; 400 401 //! Sampler that repeats the texture in all directions. 402 VkSampler repeat; 403 404 //! Sampler that clamps the coordinates to the edge in all directions. 405 VkSampler clamp_to_edge; 406 407 //! Sampler that clamps color samples to black in all directions. 408 VkSampler clamp_to_border_black; 409 } samplers; 410 411 struct 412 { 413 //! Pool for shaders that uses one ubo and sampler. 414 VkDescriptorPool ubo_and_src_descriptor_pool; 415 416 /*! 417 * Shared UBO buffer that we sub-allocate out of, this is to 418 * have fewer buffers that the kernel needs to validate on 419 * command submission time. 420 * 421 * https://registry.khronos.org/vulkan/site/guide/latest/memory_allocation.html 422 */ 423 struct render_buffer shared_ubo; 424 425 struct 426 { 427 struct 428 { 429 //! For projection and quad layer. 430 VkDescriptorSetLayout descriptor_set_layout; 431 432 //! For projection and quad layer. 433 VkPipelineLayout pipeline_layout; 434 } shared; 435 } layer; 436 } gfx; 437 438 struct 439 { 440 //! The binding index for the source texture. 441 uint32_t src_binding; 442 443 //! The binding index for the UBO. 444 uint32_t ubo_binding; 445 446 //! Descriptor set layout for mesh distortion. 447 VkDescriptorSetLayout descriptor_set_layout; 448 449 //! Pipeline layout used for mesh. 450 VkPipelineLayout pipeline_layout; 451 452 struct render_buffer vbo; 453 struct render_buffer ibo; 454 455 uint32_t vertex_count; 456 uint32_t index_counts[XRT_MAX_VIEWS]; 457 uint32_t stride; 458 uint32_t index_offsets[XRT_MAX_VIEWS]; 459 uint32_t index_count_total; 460 461 //! Info UBOs. 462 struct render_buffer ubos[XRT_MAX_VIEWS]; 463 } mesh; 464 465 /*! 466 * Used as a default image empty image when none is given or to pad 467 * out fixed sized descriptor sets. 468 */ 469 struct 470 { 471 struct 472 { 473 VkImage image; 474 VkImageView image_view; 475 VkDeviceMemory memory; 476 } color; 477 } mock; 478 479 struct 480 { 481 //! Descriptor pool for compute work. 482 VkDescriptorPool descriptor_pool; 483 484 //! The source projection view binding point. 485 uint32_t src_binding; 486 487 //! Image storing the distortion. 488 uint32_t distortion_binding; 489 490 //! Writing the image out too. 491 uint32_t target_binding; 492 493 //! Uniform data binding. 494 uint32_t ubo_binding; 495 496 struct 497 { 498 //! Descriptor set layout for compute. 499 VkDescriptorSetLayout descriptor_set_layout; 500 501 //! Pipeline layout used for compute distortion. 502 VkPipelineLayout pipeline_layout; 503 504 //! Doesn't depend on target so is static. 505 VkPipeline non_timewarp_pipeline; 506 507 //! Doesn't depend on target so is static. 508 VkPipeline timewarp_pipeline; 509 510 //! Size of combined image sampler array 511 uint32_t image_array_size; 512 513 //! Target info. 514 struct render_buffer ubos[RENDER_MAX_LAYER_RUNS_SIZE]; 515 } layer; 516 517 struct 518 { 519 //! Descriptor set layout for compute distortion. 520 VkDescriptorSetLayout descriptor_set_layout; 521 522 //! Pipeline layout used for compute distortion, shared with clear. 523 VkPipelineLayout pipeline_layout; 524 525 //! Doesn't depend on target so is static. 526 VkPipeline pipeline; 527 528 //! Doesn't depend on target so is static. 529 VkPipeline timewarp_pipeline; 530 531 //! Target info. 532 struct render_buffer ubo; 533 } distortion; 534 535 struct 536 { 537 //! Doesn't depend on target so is static. 538 VkPipeline pipeline; 539 540 //! Target info. 541 struct render_buffer ubo; 542 543 //! @todo other resources 544 } clear; 545 } compute; 546 547 struct 548 { 549 //! Transform to go from UV to tangle angles. 550 struct xrt_normalized_rect uv_to_tanangle[XRT_MAX_VIEWS]; 551 552 //! Backing memory to distortion images. 553 VkDeviceMemory device_memories[RENDER_DISTORTION_IMAGES_SIZE]; 554 555 //! Distortion images. 556 VkImage images[RENDER_DISTORTION_IMAGES_SIZE]; 557 558 //! The views into the distortion images. 559 VkImageView image_views[RENDER_DISTORTION_IMAGES_SIZE]; 560 561 //! Whether distortion images have been pre-rotated 90 degrees. 562 bool pre_rotated; 563 } distortion; 564}; 565 566/*! 567 * Allocate pools and static resources. 568 * 569 * @ingroup comp_main 570 * 571 * @public @memberof render_resources 572 */ 573bool 574render_resources_init(struct render_resources *r, 575 struct render_shaders *shaders, 576 struct vk_bundle *vk, 577 struct xrt_device *xdev); 578 579/*! 580 * Free all pools and static resources, does not free the struct itself. 581 * 582 * @public @memberof render_resources 583 */ 584void 585render_resources_fini(struct render_resources *r); 586 587/*! 588 * Creates or recreates the compute distortion textures if necessary. 589 * 590 * @see render_distortion_images_fini 591 * @public @memberof render_resources 592 */ 593bool 594render_distortion_images_ensure(struct render_resources *r, 595 struct vk_bundle *vk, 596 struct xrt_device *xdev, 597 bool pre_rotate); 598 599/*! 600 * Free distortion images. 601 * 602 * @see render_distortion_images_ensure 603 * @public @memberof render_resources 604 */ 605void 606render_distortion_images_fini(struct render_resources *r); 607 608/*! 609 * Returns the timestamps for when the latest GPU work started and stopped that 610 * was submitted using @ref render_gfx or @ref render_compute cmd buf builders. 611 * 612 * Returned in the same time domain as returned by @ref os_monotonic_get_ns . 613 * Behaviour for this function is undefined if the GPU has not completed before 614 * calling this function, so make sure to call vkQueueWaitIdle or wait on the 615 * fence that the work was submitted with have fully completed. See other 616 * limitation mentioned for @ref vk_convert_timestamps_to_host_ns . 617 * 618 * @see vk_convert_timestamps_to_host_ns 619 * 620 * @public @memberof render_resources 621 */ 622bool 623render_resources_get_timestamps(struct render_resources *r, uint64_t *out_gpu_start_ns, uint64_t *out_gpu_end_ns); 624 625/*! 626 * Returns the duration for the latest GPU work that was submitted using 627 * @ref render_gfx or @ref render_compute cmd buf builders. 628 * 629 * Behaviour for this function is undefined if the GPU has not completed before 630 * calling this function, so make sure to call vkQueueWaitIdle or wait on the 631 * fence that the work was submitted with have fully completed. 632 * 633 * @public @memberof render_resources 634 */ 635bool 636render_resources_get_duration(struct render_resources *r, uint64_t *out_gpu_duration_ns); 637 638 639/* 640 * 641 * Scratch images. 642 * 643 */ 644 645/*! 646 * Small helper struct to hold a scratch image, intended to be used with the 647 * compute pipeline where both srgb and unorm views are needed. 648 */ 649struct render_scratch_color_image 650{ 651 VkDeviceMemory device_memory; 652 VkImage image; 653 VkImageView srgb_view; 654 VkImageView unorm_view; 655}; 656 657/*! 658 * Helper struct to hold scratch images. 659 */ 660struct render_scratch_images 661{ 662 VkExtent2D extent; 663 664 struct render_scratch_color_image color[XRT_MAX_VIEWS]; 665}; 666 667/*! 668 * Ensure that the scratch images are created and have the given extent. 669 * 670 * @public @memberof render_scratch_images 671 */ 672bool 673render_scratch_images_ensure(struct render_resources *r, struct render_scratch_images *rsi, VkExtent2D extent); 674 675/*! 676 * Close all resources on the given @ref render_scratch_images. 677 * 678 * @public @memberof render_scratch_images 679 */ 680void 681render_scratch_images_fini(struct render_resources *r, struct render_scratch_images *rsi); 682 683 684/* 685 * 686 * Shared between both gfx and compute. 687 * 688 */ 689 690/*! 691 * The pure data information about a view that the renderer is rendering to. 692 */ 693struct render_viewport_data 694{ 695 uint32_t x, y; 696 uint32_t w, h; 697}; 698 699 700/* 701 * 702 * Render pass 703 * 704 */ 705 706/*! 707 * A render pass, while not depending on a @p VkFramebuffer, does depend on the 708 * format of the target image(s), and other options for the render pass. These 709 * are used to create a @p VkRenderPass, all @p VkFramebuffer(s) and 710 * @p VkPipeline depends on the @p VkRenderPass so hang off this struct. 711 */ 712struct render_gfx_render_pass 713{ 714 struct render_resources *r; 715 716 //! The format of the image(s) we are rendering to. 717 VkFormat format; 718 719 //! Sample count for this render pass. 720 VkSampleCountFlagBits sample_count; 721 722 //! Load op used on the attachment(s). 723 VkAttachmentLoadOp load_op; 724 725 //! Final layout of the target image(s). 726 VkImageLayout final_layout; 727 728 //! Render pass used for rendering. 729 VkRenderPass render_pass; 730 731 struct 732 { 733 //! Pipeline layout used for mesh, without timewarp. 734 VkPipeline pipeline; 735 736 //! Pipeline layout used for mesh, with timewarp. 737 VkPipeline pipeline_timewarp; 738 } mesh; 739 740 struct 741 { 742 VkPipeline cylinder_premultiplied_alpha; 743 VkPipeline cylinder_unpremultiplied_alpha; 744 745 VkPipeline equirect2_premultiplied_alpha; 746 VkPipeline equirect2_unpremultiplied_alpha; 747 748 VkPipeline proj_premultiplied_alpha; 749 VkPipeline proj_unpremultiplied_alpha; 750 751 VkPipeline quad_premultiplied_alpha; 752 VkPipeline quad_unpremultiplied_alpha; 753 } layer; 754}; 755 756/*! 757 * Creates all resources held by the render pass. 758 * 759 * @public @memberof render_gfx_render_pass 760 */ 761bool 762render_gfx_render_pass_init(struct render_gfx_render_pass *rgrp, 763 struct render_resources *r, 764 VkFormat format, 765 VkAttachmentLoadOp load_op, 766 VkImageLayout final_layout); 767 768/*! 769 * Frees all resources held by the render pass, does not free the struct itself. 770 * 771 * @public @memberof render_gfx_render_pass 772 */ 773void 774render_gfx_render_pass_fini(struct render_gfx_render_pass *rgrp); 775 776 777/* 778 * 779 * Rendering target 780 * 781 */ 782 783/*! 784 * Each rendering (@ref render_gfx) render to one or more targets 785 * (@ref render_gfx_target_resources), the target points to one render pass and 786 * its pipelines (@ref render_gfx_render_pass). It is up to the code using 787 * these to do reuse of render passes and ensure they match. 788 * 789 * @see comp_render_gfx 790 */ 791struct render_gfx_target_resources 792{ 793 //! Collections of static resources. 794 struct render_resources *r; 795 796 //! Render pass. 797 struct render_gfx_render_pass *rgrp; 798 799 // The extent of the framebuffer. 800 VkExtent2D extent; 801 802 //! Framebuffer for this target, depends on given VkImageView. 803 VkFramebuffer framebuffer; 804}; 805 806/*! 807 * Init a target resource struct, caller has to keep target alive until closed. 808 * 809 * @public @memberof render_gfx_target_resources 810 */ 811bool 812render_gfx_target_resources_init(struct render_gfx_target_resources *rtr, 813 struct render_resources *r, 814 struct render_gfx_render_pass *rgrp, 815 VkImageView target, 816 VkExtent2D extent); 817 818/*! 819 * Frees all resources held by the target, does not free the struct itself. 820 * 821 * @public @memberof render_gfx_target_resources 822 */ 823void 824render_gfx_target_resources_fini(struct render_gfx_target_resources *rtr); 825 826 827/* 828 * 829 * Rendering 830 * 831 */ 832 833/*! 834 * The low-level resources and operations to perform layer squashing and/or 835 * mesh distortion for a single frame using graphics shaders. 836 * 837 * It uses a two-stage process to render a frame. This means 838 * consumers iterate layers (or other operations) **twice**, within each target and view. 839 * There is a preparation stage, where the uniform buffer is sub-allocated and written. 840 * This must be completed for all layers before the actual draw stage begins. 841 * The second stage is recording the draw commands into a command buffer. 842 * 843 * You must make equivalent calls in the same order between the two stages. The second stage 844 * additionally has @ref render_gfx_begin_target, @ref render_gfx_end_target, 845 * @ref render_gfx_begin_view, and @ref render_gfx_end_view lacked by the first stage, 846 * but if you exclude those functions, the others must line up. 847 * 848 * Furthermore, the struct needs to be kept alive until the work has been waited on, 849 * or you get validation warnings. Either wait on the `VkFence` for the submit, or call 850 * `vkDeviceWaitIdle`/`vkQueueWaitIdle` on the device/queue. 851 * 852 * @see comp_render_gfx 853 */ 854struct render_gfx 855{ 856 //! Resources that we are based on. 857 struct render_resources *r; 858 859 //! Shared buffer that we sub-allocate UBOs from. 860 struct render_sub_alloc_tracker ubo_tracker; 861 862 //! The current target we are rendering to, can change during command building. 863 struct render_gfx_target_resources *rtr; 864}; 865 866/*! 867 * Init struct and create resources needed for rendering. 868 * 869 * @public @memberof render_gfx 870 */ 871bool 872render_gfx_init(struct render_gfx *render, struct render_resources *r); 873 874/*! 875 * Begins the rendering, takes the vk_bundle's pool lock and leaves it locked. 876 * 877 * @public @memberof render_gfx 878 */ 879bool 880render_gfx_begin(struct render_gfx *render); 881 882/*! 883 * Frees any unneeded resources and ends the command buffer so it can be used, 884 * also unlocks the vk_bundle's pool lock that was taken by begin. 885 * 886 * @public @memberof render_gfx 887 */ 888bool 889render_gfx_end(struct render_gfx *render); 890 891/*! 892 * Frees all resources held by the rendering, does not free the struct itself. 893 * 894 * @public @memberof render_gfx 895 */ 896void 897render_gfx_fini(struct render_gfx *render); 898 899 900/* 901 * 902 * Drawing 903 * 904 */ 905 906/*! 907 * UBO data that is sent to the mesh shaders. 908 * 909 * @relates render_gfx 910 */ 911struct render_gfx_mesh_ubo_data 912{ 913 struct xrt_matrix_2x2 vertex_rot; 914 struct xrt_normalized_rect post_transform; 915 916 // Only used for timewarp. 917 struct xrt_normalized_rect pre_transform; 918 struct xrt_matrix_4x4 transform; 919}; 920 921/*! 922 * UBO data that is sent to the layer cylinder shader. 923 * 924 * @relates render_gfx 925 */ 926struct render_gfx_layer_cylinder_data 927{ 928 struct xrt_normalized_rect post_transform; 929 struct xrt_matrix_4x4 mvp; 930 float radius; 931 float central_angle; 932 float aspect_ratio; 933 float _pad; 934}; 935 936/*! 937 * UBO data that is sent to the layer equirect2 shader. 938 * 939 * @relates render_gfx 940 */ 941struct render_gfx_layer_equirect2_data 942{ 943 struct xrt_normalized_rect post_transform; 944 struct xrt_matrix_4x4 mv_inverse; 945 946 //! See @ref render_calc_uv_to_tangent_lengths_rect. 947 struct xrt_normalized_rect to_tangent; 948 949 float radius; 950 float central_horizontal_angle; 951 float upper_vertical_angle; 952 float lower_vertical_angle; 953}; 954 955/*! 956 * UBO data that is sent to the layer projection shader. 957 * 958 * @relates render_gfx 959 */ 960struct render_gfx_layer_projection_data 961{ 962 struct xrt_normalized_rect post_transform; 963 struct xrt_normalized_rect to_tanget; 964 struct xrt_matrix_4x4 mvp; 965}; 966 967/*! 968 * UBO data that is sent to the layer quad shader. 969 * 970 * @relates render_gfx 971 */ 972struct render_gfx_layer_quad_data 973{ 974 struct xrt_normalized_rect post_transform; 975 struct xrt_matrix_4x4 mvp; 976}; 977 978/*! 979 * @name Preparation functions - first stage 980 * @{ 981 */ 982 983/*! 984 * Allocate needed resources for one mesh shader dispatch, will also update the 985 * descriptor set, UBO will be filled out with the given @p data argument. 986 * 987 * Uses the @ref render_sub_alloc_tracker of the @ref render_gfx and the 988 * descriptor pool of @ref render_resources, both of which will be reset once 989 * closed, so don't save any reference to these objects beyond the frame. 990 * 991 * @public @memberof render_gfx 992 */ 993XRT_CHECK_RESULT VkResult 994render_gfx_mesh_alloc_and_write(struct render_gfx *render, 995 const struct render_gfx_mesh_ubo_data *data, 996 VkSampler src_sampler, 997 VkImageView src_image_view, 998 VkDescriptorSet *out_descriptor_set); 999 1000/*! 1001 * Allocate and write a UBO and descriptor_set to be used for cylinder layer 1002 * rendering, the content of @p data need to be valid at the time of the call. 1003 * 1004 * @public @memberof render_gfx 1005 */ 1006XRT_CHECK_RESULT VkResult 1007render_gfx_layer_cylinder_alloc_and_write(struct render_gfx *render, 1008 const struct render_gfx_layer_cylinder_data *data, 1009 VkSampler src_sampler, 1010 VkImageView src_image_view, 1011 VkDescriptorSet *out_descriptor_set); 1012 1013/*! 1014 * Allocate and write a UBO and descriptor_set to be used for equirect2 layer 1015 * rendering, the content of @p data need to be valid at the time of the call. 1016 * 1017 * @public @memberof render_gfx 1018 */ 1019XRT_CHECK_RESULT VkResult 1020render_gfx_layer_equirect2_alloc_and_write(struct render_gfx *render, 1021 const struct render_gfx_layer_equirect2_data *data, 1022 VkSampler src_sampler, 1023 VkImageView src_image_view, 1024 VkDescriptorSet *out_descriptor_set); 1025 1026/*! 1027 * Allocate and write a UBO and descriptor_set to be used for projection layer 1028 * rendering, the content of @p data need to be valid at the time of the call. 1029 * 1030 * @public @memberof render_gfx 1031 */ 1032XRT_CHECK_RESULT VkResult 1033render_gfx_layer_projection_alloc_and_write(struct render_gfx *render, 1034 const struct render_gfx_layer_projection_data *data, 1035 VkSampler src_sampler, 1036 VkImageView src_image_view, 1037 VkDescriptorSet *out_descriptor_set); 1038 1039/*! 1040 * Allocate and write a UBO and descriptor_set to be used for quad layer 1041 * rendering, the content of @p data need to be valid at the time of the call. 1042 * 1043 * @public @memberof render_gfx 1044 */ 1045XRT_CHECK_RESULT VkResult 1046render_gfx_layer_quad_alloc_and_write(struct render_gfx *render, 1047 const struct render_gfx_layer_quad_data *data, 1048 VkSampler src_sampler, 1049 VkImageView src_image_view, 1050 VkDescriptorSet *out_descriptor_set); 1051 1052 1053/*! 1054 * @} 1055 */ 1056 1057/*! 1058 * @name Drawing functions - second stage 1059 * @{ 1060 */ 1061 1062/*! 1063 * This function allocates everything to start a single rendering. This is the 1064 * first function you call when you start the drawiing stage, you follow up with a call 1065 * to @ref render_gfx_begin_view. 1066 * 1067 * @public @memberof render_gfx 1068 */ 1069bool 1070render_gfx_begin_target(struct render_gfx *render, 1071 struct render_gfx_target_resources *rtr, 1072 const VkClearColorValue *color); 1073 1074/*! 1075 * @pre successful @ref render_gfx_begin_target call, 1076 * no @ref render_gfx_begin_view without matching @ref render_gfx_end_view 1077 * @public @memberof render_gfx 1078 */ 1079void 1080render_gfx_end_target(struct render_gfx *render); 1081 1082/*! 1083 * @pre successful @ref render_gfx_begin_target call 1084 * @public @memberof render_gfx 1085 */ 1086void 1087render_gfx_begin_view(struct render_gfx *render, uint32_t view, const struct render_viewport_data *viewport_data); 1088 1089/*! 1090 * @pre successful @ref render_gfx_begin_view call without a matching call to this function 1091 * @public @memberof render_gfx 1092 */ 1093void 1094render_gfx_end_view(struct render_gfx *render); 1095 1096/*! 1097 * Dispatch one mesh shader instance, using the give @p mesh_index as source for 1098 * mesh geometry, timewarp selectable via @p do_timewarp. 1099 * 1100 * Must have successfully called @ref render_gfx_mesh_alloc_and_write 1101 * before @ref render_gfx_begin_target to allocate @p descriptor_set and UBO. 1102 * 1103 * @pre successful @ref render_gfx_mesh_alloc_and_write call, successful @ref render_gfx_begin_view call 1104 * @public @memberof render_gfx 1105 */ 1106void 1107render_gfx_mesh_draw(struct render_gfx *render, uint32_t mesh_index, VkDescriptorSet descriptor_set, bool do_timewarp); 1108 1109/*! 1110 * Dispatch a cylinder layer shader into the current target and view. 1111 * 1112 * Must have successfully called @ref render_gfx_layer_cylinder_alloc_and_write 1113 * before @ref render_gfx_begin_target to allocate @p descriptor_set and UBO. 1114 * 1115 * @public @memberof render_gfx 1116 */ 1117void 1118render_gfx_layer_cylinder(struct render_gfx *render, bool premultiplied_alpha, VkDescriptorSet descriptor_set); 1119 1120/*! 1121 * Dispatch a equirect2 layer shader into the current target and view. 1122 * 1123 * Must have successfully called @ref render_gfx_layer_equirect2_alloc_and_write 1124 * before @ref render_gfx_begin_target to allocate @p descriptor_set and UBO. 1125 * 1126 * @public @memberof render_gfx 1127 */ 1128void 1129render_gfx_layer_equirect2(struct render_gfx *render, bool premultiplied_alpha, VkDescriptorSet descriptor_set); 1130 1131/*! 1132 * Dispatch a projection layer shader into the current target and view. 1133 * 1134 * Must have successfully called @ref render_gfx_layer_projection_alloc_and_write 1135 * before @ref render_gfx_begin_target to allocate @p descriptor_set and UBO. 1136 * 1137 * @public @memberof render_gfx 1138 */ 1139void 1140render_gfx_layer_projection(struct render_gfx *render, bool premultiplied_alpha, VkDescriptorSet descriptor_set); 1141 1142/*! 1143 * Dispatch a quad layer shader into the current target and view. 1144 * 1145 * Must have successfully called @ref render_gfx_layer_quad_alloc_and_write 1146 * before @ref render_gfx_begin_target to allocate @p descriptor_set and UBO. 1147 * 1148 * @public @memberof render_gfx 1149 */ 1150void 1151render_gfx_layer_quad(struct render_gfx *render, bool premultiplied_alpha, VkDescriptorSet descriptor_set); 1152 1153/*! 1154 * @} 1155 */ 1156 1157 1158/* 1159 * 1160 * Compute distortion. 1161 * 1162 */ 1163 1164/*! 1165 * The semi-low level resources and operations required to squash layers and/or 1166 * apply distortion for a single frame using compute shaders. 1167 * 1168 * Unlike @ref render_gfx, this is a single stage process, and you pass all layers at a single time. 1169 * 1170 * @see comp_render_cs 1171 */ 1172struct render_compute 1173{ 1174 //! Shared resources. 1175 struct render_resources *r; 1176 1177 //! Layer descriptor set. 1178 VkDescriptorSet layer_descriptor_sets[RENDER_MAX_LAYER_RUNS_SIZE]; 1179 1180 /*! 1181 * Shared descriptor set, used for the clear and distortion shaders. It 1182 * is used in the functions @ref render_compute_projection_timewarp, 1183 * @ref render_compute_projection, and @ref render_compute_clear. 1184 */ 1185 VkDescriptorSet shared_descriptor_set; 1186}; 1187 1188/*! 1189 * Push data that is sent to the blit shader. 1190 * 1191 * @relates render_compute 1192 */ 1193struct render_compute_blit_push_data 1194{ 1195 struct xrt_normalized_rect source_rect; 1196 struct xrt_rect target_rect; 1197}; 1198 1199/*! 1200 * UBO data that is sent to the compute layer shaders. 1201 * 1202 * @relates render_compute 1203 */ 1204struct render_compute_layer_ubo_data 1205{ 1206 struct render_viewport_data view; 1207 1208 struct 1209 { 1210 uint32_t value; 1211 uint32_t padding[3]; // Padding up to a vec4. 1212 } layer_count; 1213 1214 struct xrt_normalized_rect pre_transform; 1215 struct xrt_normalized_rect post_transforms[RENDER_MAX_LAYERS]; 1216 1217 /*! 1218 * Corresponds to enum xrt_layer_type and unpremultiplied alpha. 1219 * 1220 * std140 uvec2, because it is an array it gets padded to vec4. 1221 */ 1222 struct 1223 { 1224 uint32_t layer_type; 1225 uint32_t unpremultiplied_alpha; 1226 uint32_t _padding0; 1227 uint32_t _padding1; 1228 } layer_data[RENDER_MAX_LAYERS]; 1229 1230 /*! 1231 * Which image/sampler(s) correspond to each layer. 1232 * 1233 * std140 uvec2, because it is an array it gets padded to vec4. 1234 */ 1235 struct 1236 { 1237 uint32_t color_image_index; 1238 uint32_t depth_image_index; 1239 1240 //! @todo Implement separated samplers and images (and change to samplers[2]) 1241 uint32_t _padding0; 1242 uint32_t _padding1; 1243 } image_info[RENDER_MAX_LAYERS]; 1244 1245 //! Shared between cylinder and equirect2. 1246 struct xrt_matrix_4x4 mv_inverse[RENDER_MAX_LAYERS]; 1247 1248 1249 /*! 1250 * For cylinder layer 1251 */ 1252 struct 1253 { 1254 float radius; 1255 float central_angle; 1256 float aspect_ratio; 1257 float padding; 1258 } cylinder_data[RENDER_MAX_LAYERS]; 1259 1260 1261 /*! 1262 * For equirect2 layers 1263 */ 1264 struct 1265 { 1266 float radius; 1267 float central_horizontal_angle; 1268 float upper_vertical_angle; 1269 float lower_vertical_angle; 1270 } eq2_data[RENDER_MAX_LAYERS]; 1271 1272 1273 /*! 1274 * For projection layers 1275 */ 1276 1277 //! Timewarp matrices 1278 struct xrt_matrix_4x4 transforms_timewarp[RENDER_MAX_LAYERS]; 1279 1280 /*! 1281 * For quad layers 1282 */ 1283 1284 //! All quad transforms and coordinates are in view space 1285 struct 1286 { 1287 struct xrt_vec3 val; 1288 float padding; 1289 } quad_position[RENDER_MAX_LAYERS]; 1290 struct 1291 { 1292 struct xrt_vec3 val; 1293 float padding; 1294 } quad_normal[RENDER_MAX_LAYERS]; 1295 struct xrt_matrix_4x4 inverse_quad_transform[RENDER_MAX_LAYERS]; 1296 1297 //! Quad extent in world scale 1298 struct 1299 { 1300 struct xrt_vec2 val; 1301 float padding[XRT_MAX_VIEWS]; 1302 } quad_extent[RENDER_MAX_LAYERS]; 1303}; 1304 1305/*! 1306 * UBO data that is sent to the compute distortion shaders. 1307 * 1308 * @relates render_compute 1309 */ 1310struct render_compute_distortion_ubo_data 1311{ 1312 struct render_viewport_data views[XRT_MAX_VIEWS]; 1313 struct xrt_normalized_rect pre_transforms[XRT_MAX_VIEWS]; 1314 struct xrt_normalized_rect post_transforms[XRT_MAX_VIEWS]; 1315 struct xrt_matrix_4x4 transform_timewarp_scanout_begin[XRT_MAX_VIEWS]; 1316 struct xrt_matrix_4x4 transform_timewarp_scanout_end[XRT_MAX_VIEWS]; 1317}; 1318 1319/*! 1320 * Init struct and create resources needed for compute rendering. 1321 * 1322 * @public @memberof render_compute 1323 */ 1324bool 1325render_compute_init(struct render_compute *render, struct render_resources *r); 1326 1327/*! 1328 * Frees all resources held by the compute rendering, does not free the struct itself. 1329 * 1330 * @public @memberof render_compute 1331 */ 1332void 1333render_compute_fini(struct render_compute *render); 1334 1335/*! 1336 * Begin the compute command buffer building, takes the vk_bundle's pool lock 1337 * and leaves it locked. 1338 * 1339 * @public @memberof render_compute 1340 */ 1341bool 1342render_compute_begin(struct render_compute *render); 1343 1344/*! 1345 * Frees any unneeded resources and ends the command buffer so it can be used, 1346 * also unlocks the vk_bundle's pool lock that was taken by begin. 1347 * 1348 * @public @memberof render_compute 1349 */ 1350bool 1351render_compute_end(struct render_compute *render); 1352 1353/*! 1354 * Updates the given @p descriptor_set and dispatches the layer shader. Unlike 1355 * other dispatch functions below this function doesn't do any layer barriers 1356 * before or after dispatching, this is to allow the callee to batch any such 1357 * image transitions. 1358 * 1359 * Expected layouts: 1360 * * Source images: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 1361 * * Target image: VK_IMAGE_LAYOUT_GENERAL 1362 * 1363 * @public @memberof render_compute 1364 */ 1365void 1366render_compute_layers(struct render_compute *render, 1367 VkDescriptorSet descriptor_set, 1368 VkBuffer ubo, 1369 VkSampler src_samplers[RENDER_MAX_IMAGES_SIZE], 1370 VkImageView src_image_views[RENDER_MAX_IMAGES_SIZE], 1371 uint32_t num_srcs, 1372 VkImageView target_image_view, 1373 const struct render_viewport_data *view, 1374 bool timewarp); 1375 1376/*! 1377 * @public @memberof render_compute 1378 */ 1379void 1380render_compute_projection_timewarp(struct render_compute *render, 1381 VkSampler src_samplers[XRT_MAX_VIEWS], 1382 VkImageView src_image_views[XRT_MAX_VIEWS], 1383 const struct xrt_normalized_rect src_rects[XRT_MAX_VIEWS], 1384 const struct xrt_pose src_poses[XRT_MAX_VIEWS], 1385 const struct xrt_fov src_fovs[XRT_MAX_VIEWS], 1386 const struct xrt_pose new_poses_scanout_begin[XRT_MAX_VIEWS], 1387 const struct xrt_pose new_poses_scanout_end[XRT_MAX_VIEWS], 1388 VkImage target_image, 1389 VkImageView target_image_view, 1390 const struct render_viewport_data views[XRT_MAX_VIEWS]); 1391 1392/*! 1393 * @public @memberof render_compute 1394 */ 1395void 1396render_compute_projection_scanout_compensation(struct render_compute *render, 1397 VkSampler src_samplers[XRT_MAX_VIEWS], 1398 VkImageView src_image_views[XRT_MAX_VIEWS], 1399 const struct xrt_normalized_rect src_rects[XRT_MAX_VIEWS], 1400 const struct xrt_fov src_fovs[XRT_MAX_VIEWS], 1401 const struct xrt_pose new_poses_scanout_begin[XRT_MAX_VIEWS], 1402 const struct xrt_pose new_poses_scanout_end[XRT_MAX_VIEWS], 1403 VkImage target_image, 1404 VkImageView target_image_view, 1405 const struct render_viewport_data views[XRT_MAX_VIEWS]); 1406 1407/*! 1408 * @public @memberof render_compute 1409 */ 1410void 1411render_compute_projection_no_timewarp(struct render_compute *render, 1412 VkSampler src_samplers[XRT_MAX_VIEWS], 1413 VkImageView src_image_views[XRT_MAX_VIEWS], 1414 const struct xrt_normalized_rect src_rects[XRT_MAX_VIEWS], 1415 VkImage target_image, 1416 VkImageView target_image_view, 1417 const struct render_viewport_data views[XRT_MAX_VIEWS]); 1418 1419/*! 1420 * @public @memberof render_compute 1421 */ 1422void 1423render_compute_clear(struct render_compute *render, 1424 VkImage target_image, 1425 VkImageView target_image_view, 1426 const struct render_viewport_data views[XRT_MAX_VIEWS]); 1427 1428 1429 1430/*! 1431 * @} 1432 */ 1433 1434 1435#ifdef __cplusplus 1436} 1437#endif