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