17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2019 Google LLC 37ec681f3Smrg * SPDX-License-Identifier: MIT 47ec681f3Smrg * 57ec681f3Smrg * based in part on anv and radv which are: 67ec681f3Smrg * Copyright © 2015 Intel Corporation 77ec681f3Smrg * Copyright © 2016 Red Hat. 87ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen 97ec681f3Smrg */ 107ec681f3Smrg 117ec681f3Smrg#include "vn_render_pass.h" 127ec681f3Smrg 137ec681f3Smrg#include "venus-protocol/vn_protocol_driver_framebuffer.h" 147ec681f3Smrg#include "venus-protocol/vn_protocol_driver_render_pass.h" 157ec681f3Smrg 167ec681f3Smrg#include "vn_device.h" 177ec681f3Smrg#include "vn_image.h" 187ec681f3Smrg 197ec681f3Smrg#define COUNT_PRESENT_SRC(atts, att_count, initial_count, final_count) \ 207ec681f3Smrg do { \ 217ec681f3Smrg *initial_count = 0; \ 227ec681f3Smrg *final_count = 0; \ 237ec681f3Smrg for (uint32_t i = 0; i < att_count; i++) { \ 247ec681f3Smrg if (atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) \ 257ec681f3Smrg (*initial_count)++; \ 267ec681f3Smrg if (atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) \ 277ec681f3Smrg (*final_count)++; \ 287ec681f3Smrg } \ 297ec681f3Smrg } while (false) 307ec681f3Smrg 317ec681f3Smrg#define REPLACE_PRESENT_SRC(pass, atts, att_count, out_atts) \ 327ec681f3Smrg do { \ 337ec681f3Smrg struct vn_present_src_attachment *_acquire_atts = \ 347ec681f3Smrg pass->present_src_attachments; \ 357ec681f3Smrg struct vn_present_src_attachment *_release_atts = \ 367ec681f3Smrg _acquire_atts + pass->acquire_count; \ 377ec681f3Smrg \ 387ec681f3Smrg memcpy(out_atts, atts, sizeof(*atts) * att_count); \ 397ec681f3Smrg for (uint32_t i = 0; i < att_count; i++) { \ 407ec681f3Smrg if (out_atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \ 417ec681f3Smrg out_atts[i].initialLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; \ 427ec681f3Smrg _acquire_atts->acquire = true; \ 437ec681f3Smrg _acquire_atts->index = i; \ 447ec681f3Smrg _acquire_atts++; \ 457ec681f3Smrg } \ 467ec681f3Smrg if (out_atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \ 477ec681f3Smrg out_atts[i].finalLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; \ 487ec681f3Smrg _release_atts->acquire = false; \ 497ec681f3Smrg _release_atts->index = i; \ 507ec681f3Smrg _release_atts++; \ 517ec681f3Smrg } \ 527ec681f3Smrg } \ 537ec681f3Smrg } while (false) 547ec681f3Smrg 557ec681f3Smrgstatic void 567ec681f3Smrgvn_render_pass_count_present_src(const VkRenderPassCreateInfo *create_info, 577ec681f3Smrg uint32_t *initial_count, 587ec681f3Smrg uint32_t *final_count) 597ec681f3Smrg{ 607ec681f3Smrg COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount, 617ec681f3Smrg initial_count, final_count); 627ec681f3Smrg} 637ec681f3Smrg 647ec681f3Smrgstatic void 657ec681f3Smrgvn_render_pass_count_present_src2(const VkRenderPassCreateInfo2 *create_info, 667ec681f3Smrg uint32_t *initial_count, 677ec681f3Smrg uint32_t *final_count) 687ec681f3Smrg{ 697ec681f3Smrg COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount, 707ec681f3Smrg initial_count, final_count); 717ec681f3Smrg} 727ec681f3Smrg 737ec681f3Smrgstatic void 747ec681f3Smrgvn_render_pass_replace_present_src(struct vn_render_pass *pass, 757ec681f3Smrg const VkRenderPassCreateInfo *create_info, 767ec681f3Smrg VkAttachmentDescription *out_atts) 777ec681f3Smrg{ 787ec681f3Smrg REPLACE_PRESENT_SRC(pass, create_info->pAttachments, 797ec681f3Smrg create_info->attachmentCount, out_atts); 807ec681f3Smrg} 817ec681f3Smrg 827ec681f3Smrgstatic void 837ec681f3Smrgvn_render_pass_replace_present_src2(struct vn_render_pass *pass, 847ec681f3Smrg const VkRenderPassCreateInfo2 *create_info, 857ec681f3Smrg VkAttachmentDescription2 *out_atts) 867ec681f3Smrg{ 877ec681f3Smrg REPLACE_PRESENT_SRC(pass, create_info->pAttachments, 887ec681f3Smrg create_info->attachmentCount, out_atts); 897ec681f3Smrg} 907ec681f3Smrg 917ec681f3Smrgstatic void 927ec681f3Smrgvn_render_pass_setup_present_src_barriers(struct vn_render_pass *pass) 937ec681f3Smrg{ 947ec681f3Smrg /* TODO parse VkSubpassDependency for more accurate barriers */ 957ec681f3Smrg for (uint32_t i = 0; i < pass->present_src_count; i++) { 967ec681f3Smrg struct vn_present_src_attachment *att = 977ec681f3Smrg &pass->present_src_attachments[i]; 987ec681f3Smrg 997ec681f3Smrg if (att->acquire) { 1007ec681f3Smrg att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 1017ec681f3Smrg att->src_access_mask = 0; 1027ec681f3Smrg 1037ec681f3Smrg att->dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 1047ec681f3Smrg att->dst_access_mask = 1057ec681f3Smrg VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; 1067ec681f3Smrg } else { 1077ec681f3Smrg att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 1087ec681f3Smrg att->src_access_mask = VK_ACCESS_MEMORY_WRITE_BIT; 1097ec681f3Smrg 1107ec681f3Smrg att->dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; 1117ec681f3Smrg att->dst_access_mask = 0; 1127ec681f3Smrg } 1137ec681f3Smrg } 1147ec681f3Smrg} 1157ec681f3Smrg 1167ec681f3Smrgstatic struct vn_render_pass * 1177ec681f3Smrgvn_render_pass_create(struct vn_device *dev, 1187ec681f3Smrg uint32_t acquire_count, 1197ec681f3Smrg uint32_t release_count, 1207ec681f3Smrg const VkAllocationCallbacks *alloc) 1217ec681f3Smrg{ 1227ec681f3Smrg const uint32_t total_count = acquire_count + release_count; 1237ec681f3Smrg struct vn_render_pass *pass = vk_zalloc( 1247ec681f3Smrg alloc, 1257ec681f3Smrg sizeof(*pass) + sizeof(pass->present_src_attachments[0]) * total_count, 1267ec681f3Smrg VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1277ec681f3Smrg if (!pass) 1287ec681f3Smrg return NULL; 1297ec681f3Smrg 1307ec681f3Smrg vn_object_base_init(&pass->base, VK_OBJECT_TYPE_RENDER_PASS, &dev->base); 1317ec681f3Smrg 1327ec681f3Smrg pass->acquire_count = acquire_count; 1337ec681f3Smrg pass->release_count = release_count; 1347ec681f3Smrg pass->present_src_count = total_count; 1357ec681f3Smrg 1367ec681f3Smrg return pass; 1377ec681f3Smrg} 1387ec681f3Smrg 1397ec681f3Smrg/* render pass commands */ 1407ec681f3Smrg 1417ec681f3SmrgVkResult 1427ec681f3Smrgvn_CreateRenderPass(VkDevice device, 1437ec681f3Smrg const VkRenderPassCreateInfo *pCreateInfo, 1447ec681f3Smrg const VkAllocationCallbacks *pAllocator, 1457ec681f3Smrg VkRenderPass *pRenderPass) 1467ec681f3Smrg{ 1477ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 1487ec681f3Smrg const VkAllocationCallbacks *alloc = 1497ec681f3Smrg pAllocator ? pAllocator : &dev->base.base.alloc; 1507ec681f3Smrg 1517ec681f3Smrg uint32_t acquire_count; 1527ec681f3Smrg uint32_t release_count; 1537ec681f3Smrg vn_render_pass_count_present_src(pCreateInfo, &acquire_count, 1547ec681f3Smrg &release_count); 1557ec681f3Smrg 1567ec681f3Smrg struct vn_render_pass *pass = 1577ec681f3Smrg vn_render_pass_create(dev, acquire_count, release_count, alloc); 1587ec681f3Smrg if (!pass) 1597ec681f3Smrg return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1607ec681f3Smrg 1617ec681f3Smrg VkRenderPassCreateInfo local_pass_info; 1627ec681f3Smrg if (pass->present_src_count) { 1637ec681f3Smrg VkAttachmentDescription *temp_atts = 1647ec681f3Smrg vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount, 1657ec681f3Smrg VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1667ec681f3Smrg if (!temp_atts) { 1677ec681f3Smrg vk_free(alloc, pass); 1687ec681f3Smrg return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1697ec681f3Smrg } 1707ec681f3Smrg 1717ec681f3Smrg vn_render_pass_replace_present_src(pass, pCreateInfo, temp_atts); 1727ec681f3Smrg vn_render_pass_setup_present_src_barriers(pass); 1737ec681f3Smrg 1747ec681f3Smrg local_pass_info = *pCreateInfo; 1757ec681f3Smrg local_pass_info.pAttachments = temp_atts; 1767ec681f3Smrg pCreateInfo = &local_pass_info; 1777ec681f3Smrg } 1787ec681f3Smrg 1797ec681f3Smrg VkRenderPass pass_handle = vn_render_pass_to_handle(pass); 1807ec681f3Smrg vn_async_vkCreateRenderPass(dev->instance, device, pCreateInfo, NULL, 1817ec681f3Smrg &pass_handle); 1827ec681f3Smrg 1837ec681f3Smrg if (pCreateInfo == &local_pass_info) 1847ec681f3Smrg vk_free(alloc, (void *)local_pass_info.pAttachments); 1857ec681f3Smrg 1867ec681f3Smrg *pRenderPass = pass_handle; 1877ec681f3Smrg 1887ec681f3Smrg return VK_SUCCESS; 1897ec681f3Smrg} 1907ec681f3Smrg 1917ec681f3SmrgVkResult 1927ec681f3Smrgvn_CreateRenderPass2(VkDevice device, 1937ec681f3Smrg const VkRenderPassCreateInfo2 *pCreateInfo, 1947ec681f3Smrg const VkAllocationCallbacks *pAllocator, 1957ec681f3Smrg VkRenderPass *pRenderPass) 1967ec681f3Smrg{ 1977ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 1987ec681f3Smrg const VkAllocationCallbacks *alloc = 1997ec681f3Smrg pAllocator ? pAllocator : &dev->base.base.alloc; 2007ec681f3Smrg 2017ec681f3Smrg uint32_t acquire_count; 2027ec681f3Smrg uint32_t release_count; 2037ec681f3Smrg vn_render_pass_count_present_src2(pCreateInfo, &acquire_count, 2047ec681f3Smrg &release_count); 2057ec681f3Smrg 2067ec681f3Smrg struct vn_render_pass *pass = 2077ec681f3Smrg vn_render_pass_create(dev, acquire_count, release_count, alloc); 2087ec681f3Smrg if (!pass) 2097ec681f3Smrg return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 2107ec681f3Smrg 2117ec681f3Smrg VkRenderPassCreateInfo2 local_pass_info; 2127ec681f3Smrg if (pass->present_src_count) { 2137ec681f3Smrg VkAttachmentDescription2 *temp_atts = 2147ec681f3Smrg vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount, 2157ec681f3Smrg VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2167ec681f3Smrg if (!temp_atts) { 2177ec681f3Smrg vk_free(alloc, pass); 2187ec681f3Smrg return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 2197ec681f3Smrg } 2207ec681f3Smrg 2217ec681f3Smrg vn_render_pass_replace_present_src2(pass, pCreateInfo, temp_atts); 2227ec681f3Smrg vn_render_pass_setup_present_src_barriers(pass); 2237ec681f3Smrg 2247ec681f3Smrg local_pass_info = *pCreateInfo; 2257ec681f3Smrg local_pass_info.pAttachments = temp_atts; 2267ec681f3Smrg pCreateInfo = &local_pass_info; 2277ec681f3Smrg } 2287ec681f3Smrg 2297ec681f3Smrg VkRenderPass pass_handle = vn_render_pass_to_handle(pass); 2307ec681f3Smrg vn_async_vkCreateRenderPass2(dev->instance, device, pCreateInfo, NULL, 2317ec681f3Smrg &pass_handle); 2327ec681f3Smrg 2337ec681f3Smrg if (pCreateInfo == &local_pass_info) 2347ec681f3Smrg vk_free(alloc, (void *)local_pass_info.pAttachments); 2357ec681f3Smrg 2367ec681f3Smrg *pRenderPass = pass_handle; 2377ec681f3Smrg 2387ec681f3Smrg return VK_SUCCESS; 2397ec681f3Smrg} 2407ec681f3Smrg 2417ec681f3Smrgvoid 2427ec681f3Smrgvn_DestroyRenderPass(VkDevice device, 2437ec681f3Smrg VkRenderPass renderPass, 2447ec681f3Smrg const VkAllocationCallbacks *pAllocator) 2457ec681f3Smrg{ 2467ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 2477ec681f3Smrg struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass); 2487ec681f3Smrg const VkAllocationCallbacks *alloc = 2497ec681f3Smrg pAllocator ? pAllocator : &dev->base.base.alloc; 2507ec681f3Smrg 2517ec681f3Smrg if (!pass) 2527ec681f3Smrg return; 2537ec681f3Smrg 2547ec681f3Smrg vn_async_vkDestroyRenderPass(dev->instance, device, renderPass, NULL); 2557ec681f3Smrg 2567ec681f3Smrg vn_object_base_fini(&pass->base); 2577ec681f3Smrg vk_free(alloc, pass); 2587ec681f3Smrg} 2597ec681f3Smrg 2607ec681f3Smrgvoid 2617ec681f3Smrgvn_GetRenderAreaGranularity(VkDevice device, 2627ec681f3Smrg VkRenderPass renderPass, 2637ec681f3Smrg VkExtent2D *pGranularity) 2647ec681f3Smrg{ 2657ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 2667ec681f3Smrg struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass); 2677ec681f3Smrg 2687ec681f3Smrg if (!pass->granularity.width) { 2697ec681f3Smrg vn_call_vkGetRenderAreaGranularity(dev->instance, device, renderPass, 2707ec681f3Smrg &pass->granularity); 2717ec681f3Smrg } 2727ec681f3Smrg 2737ec681f3Smrg *pGranularity = pass->granularity; 2747ec681f3Smrg} 2757ec681f3Smrg 2767ec681f3Smrg/* framebuffer commands */ 2777ec681f3Smrg 2787ec681f3SmrgVkResult 2797ec681f3Smrgvn_CreateFramebuffer(VkDevice device, 2807ec681f3Smrg const VkFramebufferCreateInfo *pCreateInfo, 2817ec681f3Smrg const VkAllocationCallbacks *pAllocator, 2827ec681f3Smrg VkFramebuffer *pFramebuffer) 2837ec681f3Smrg{ 2847ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 2857ec681f3Smrg const VkAllocationCallbacks *alloc = 2867ec681f3Smrg pAllocator ? pAllocator : &dev->base.base.alloc; 2877ec681f3Smrg 2887ec681f3Smrg /* Two render passes differ only in attachment image layouts are considered 2897ec681f3Smrg * compatible. We must not use pCreateInfo->renderPass here. 2907ec681f3Smrg */ 2917ec681f3Smrg const bool imageless = 2927ec681f3Smrg pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT; 2937ec681f3Smrg const uint32_t view_count = imageless ? 0 : pCreateInfo->attachmentCount; 2947ec681f3Smrg 2957ec681f3Smrg struct vn_framebuffer *fb = 2967ec681f3Smrg vk_zalloc(alloc, sizeof(*fb) + sizeof(*fb->image_views) * view_count, 2977ec681f3Smrg VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 2987ec681f3Smrg if (!fb) 2997ec681f3Smrg return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 3007ec681f3Smrg 3017ec681f3Smrg vn_object_base_init(&fb->base, VK_OBJECT_TYPE_FRAMEBUFFER, &dev->base); 3027ec681f3Smrg 3037ec681f3Smrg fb->image_view_count = view_count; 3047ec681f3Smrg memcpy(fb->image_views, pCreateInfo->pAttachments, 3057ec681f3Smrg sizeof(*pCreateInfo->pAttachments) * view_count); 3067ec681f3Smrg 3077ec681f3Smrg VkFramebuffer fb_handle = vn_framebuffer_to_handle(fb); 3087ec681f3Smrg vn_async_vkCreateFramebuffer(dev->instance, device, pCreateInfo, NULL, 3097ec681f3Smrg &fb_handle); 3107ec681f3Smrg 3117ec681f3Smrg *pFramebuffer = fb_handle; 3127ec681f3Smrg 3137ec681f3Smrg return VK_SUCCESS; 3147ec681f3Smrg} 3157ec681f3Smrg 3167ec681f3Smrgvoid 3177ec681f3Smrgvn_DestroyFramebuffer(VkDevice device, 3187ec681f3Smrg VkFramebuffer framebuffer, 3197ec681f3Smrg const VkAllocationCallbacks *pAllocator) 3207ec681f3Smrg{ 3217ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 3227ec681f3Smrg struct vn_framebuffer *fb = vn_framebuffer_from_handle(framebuffer); 3237ec681f3Smrg const VkAllocationCallbacks *alloc = 3247ec681f3Smrg pAllocator ? pAllocator : &dev->base.base.alloc; 3257ec681f3Smrg 3267ec681f3Smrg if (!fb) 3277ec681f3Smrg return; 3287ec681f3Smrg 3297ec681f3Smrg vn_async_vkDestroyFramebuffer(dev->instance, device, framebuffer, NULL); 3307ec681f3Smrg 3317ec681f3Smrg vn_object_base_fini(&fb->base); 3327ec681f3Smrg vk_free(alloc, fb); 3337ec681f3Smrg} 334