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