1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2019 Google LLC 3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * based in part on anv and radv which are: 6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 7bf215546Sopenharmony_ci * Copyright © 2016 Red Hat. 8bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen 9bf215546Sopenharmony_ci */ 10bf215546Sopenharmony_ci 11bf215546Sopenharmony_ci#include "vn_render_pass.h" 12bf215546Sopenharmony_ci 13bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_framebuffer.h" 14bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_render_pass.h" 15bf215546Sopenharmony_ci 16bf215546Sopenharmony_ci#include "vn_device.h" 17bf215546Sopenharmony_ci#include "vn_image.h" 18bf215546Sopenharmony_ci 19bf215546Sopenharmony_ci#define COUNT_PRESENT_SRC(atts, att_count, initial_count, final_count) \ 20bf215546Sopenharmony_ci do { \ 21bf215546Sopenharmony_ci *initial_count = 0; \ 22bf215546Sopenharmony_ci *final_count = 0; \ 23bf215546Sopenharmony_ci for (uint32_t i = 0; i < att_count; i++) { \ 24bf215546Sopenharmony_ci if (atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) \ 25bf215546Sopenharmony_ci (*initial_count)++; \ 26bf215546Sopenharmony_ci if (atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) \ 27bf215546Sopenharmony_ci (*final_count)++; \ 28bf215546Sopenharmony_ci } \ 29bf215546Sopenharmony_ci } while (false) 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#define REPLACE_PRESENT_SRC(pass, atts, att_count, out_atts) \ 32bf215546Sopenharmony_ci do { \ 33bf215546Sopenharmony_ci struct vn_present_src_attachment *_acquire_atts = \ 34bf215546Sopenharmony_ci pass->present_src_attachments; \ 35bf215546Sopenharmony_ci struct vn_present_src_attachment *_release_atts = \ 36bf215546Sopenharmony_ci _acquire_atts + pass->acquire_count; \ 37bf215546Sopenharmony_ci \ 38bf215546Sopenharmony_ci memcpy(out_atts, atts, sizeof(*atts) * att_count); \ 39bf215546Sopenharmony_ci for (uint32_t i = 0; i < att_count; i++) { \ 40bf215546Sopenharmony_ci if (out_atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \ 41bf215546Sopenharmony_ci out_atts[i].initialLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; \ 42bf215546Sopenharmony_ci _acquire_atts->acquire = true; \ 43bf215546Sopenharmony_ci _acquire_atts->index = i; \ 44bf215546Sopenharmony_ci _acquire_atts++; \ 45bf215546Sopenharmony_ci } \ 46bf215546Sopenharmony_ci if (out_atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \ 47bf215546Sopenharmony_ci out_atts[i].finalLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; \ 48bf215546Sopenharmony_ci _release_atts->acquire = false; \ 49bf215546Sopenharmony_ci _release_atts->index = i; \ 50bf215546Sopenharmony_ci _release_atts++; \ 51bf215546Sopenharmony_ci } \ 52bf215546Sopenharmony_ci } \ 53bf215546Sopenharmony_ci } while (false) 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistatic void 56bf215546Sopenharmony_civn_render_pass_count_present_src(const VkRenderPassCreateInfo *create_info, 57bf215546Sopenharmony_ci uint32_t *initial_count, 58bf215546Sopenharmony_ci uint32_t *final_count) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount, 61bf215546Sopenharmony_ci initial_count, final_count); 62bf215546Sopenharmony_ci} 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_cistatic void 65bf215546Sopenharmony_civn_render_pass_count_present_src2(const VkRenderPassCreateInfo2 *create_info, 66bf215546Sopenharmony_ci uint32_t *initial_count, 67bf215546Sopenharmony_ci uint32_t *final_count) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount, 70bf215546Sopenharmony_ci initial_count, final_count); 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic void 74bf215546Sopenharmony_civn_render_pass_replace_present_src(struct vn_render_pass *pass, 75bf215546Sopenharmony_ci const VkRenderPassCreateInfo *create_info, 76bf215546Sopenharmony_ci VkAttachmentDescription *out_atts) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci REPLACE_PRESENT_SRC(pass, create_info->pAttachments, 79bf215546Sopenharmony_ci create_info->attachmentCount, out_atts); 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_cistatic void 83bf215546Sopenharmony_civn_render_pass_replace_present_src2(struct vn_render_pass *pass, 84bf215546Sopenharmony_ci const VkRenderPassCreateInfo2 *create_info, 85bf215546Sopenharmony_ci VkAttachmentDescription2 *out_atts) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci REPLACE_PRESENT_SRC(pass, create_info->pAttachments, 88bf215546Sopenharmony_ci create_info->attachmentCount, out_atts); 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistatic void 92bf215546Sopenharmony_civn_render_pass_setup_present_src_barriers(struct vn_render_pass *pass) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci /* TODO parse VkSubpassDependency for more accurate barriers */ 95bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->present_src_count; i++) { 96bf215546Sopenharmony_ci struct vn_present_src_attachment *att = 97bf215546Sopenharmony_ci &pass->present_src_attachments[i]; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci if (att->acquire) { 100bf215546Sopenharmony_ci att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 101bf215546Sopenharmony_ci att->src_access_mask = 0; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci att->dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 104bf215546Sopenharmony_ci att->dst_access_mask = 105bf215546Sopenharmony_ci VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; 106bf215546Sopenharmony_ci } else { 107bf215546Sopenharmony_ci att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 108bf215546Sopenharmony_ci att->src_access_mask = VK_ACCESS_MEMORY_WRITE_BIT; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci att->dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; 111bf215546Sopenharmony_ci att->dst_access_mask = 0; 112bf215546Sopenharmony_ci } 113bf215546Sopenharmony_ci } 114bf215546Sopenharmony_ci} 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_cistatic struct vn_render_pass * 117bf215546Sopenharmony_civn_render_pass_create(struct vn_device *dev, 118bf215546Sopenharmony_ci uint32_t acquire_count, 119bf215546Sopenharmony_ci uint32_t release_count, 120bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci const uint32_t total_count = acquire_count + release_count; 123bf215546Sopenharmony_ci struct vn_render_pass *pass = vk_zalloc( 124bf215546Sopenharmony_ci alloc, 125bf215546Sopenharmony_ci sizeof(*pass) + sizeof(pass->present_src_attachments[0]) * total_count, 126bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 127bf215546Sopenharmony_ci if (!pass) 128bf215546Sopenharmony_ci return NULL; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci vn_object_base_init(&pass->base, VK_OBJECT_TYPE_RENDER_PASS, &dev->base); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci pass->acquire_count = acquire_count; 133bf215546Sopenharmony_ci pass->release_count = release_count; 134bf215546Sopenharmony_ci pass->present_src_count = total_count; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci return pass; 137bf215546Sopenharmony_ci} 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci/* render pass commands */ 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ciVkResult 142bf215546Sopenharmony_civn_CreateRenderPass(VkDevice device, 143bf215546Sopenharmony_ci const VkRenderPassCreateInfo *pCreateInfo, 144bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 145bf215546Sopenharmony_ci VkRenderPass *pRenderPass) 146bf215546Sopenharmony_ci{ 147bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 148bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 149bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci uint32_t acquire_count; 152bf215546Sopenharmony_ci uint32_t release_count; 153bf215546Sopenharmony_ci vn_render_pass_count_present_src(pCreateInfo, &acquire_count, 154bf215546Sopenharmony_ci &release_count); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci struct vn_render_pass *pass = 157bf215546Sopenharmony_ci vn_render_pass_create(dev, acquire_count, release_count, alloc); 158bf215546Sopenharmony_ci if (!pass) 159bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci VkRenderPassCreateInfo local_pass_info; 162bf215546Sopenharmony_ci if (pass->present_src_count) { 163bf215546Sopenharmony_ci VkAttachmentDescription *temp_atts = 164bf215546Sopenharmony_ci vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount, 165bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 166bf215546Sopenharmony_ci if (!temp_atts) { 167bf215546Sopenharmony_ci vk_free(alloc, pass); 168bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci vn_render_pass_replace_present_src(pass, pCreateInfo, temp_atts); 172bf215546Sopenharmony_ci vn_render_pass_setup_present_src_barriers(pass); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci local_pass_info = *pCreateInfo; 175bf215546Sopenharmony_ci local_pass_info.pAttachments = temp_atts; 176bf215546Sopenharmony_ci pCreateInfo = &local_pass_info; 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci VkRenderPass pass_handle = vn_render_pass_to_handle(pass); 180bf215546Sopenharmony_ci vn_async_vkCreateRenderPass(dev->instance, device, pCreateInfo, NULL, 181bf215546Sopenharmony_ci &pass_handle); 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci if (pCreateInfo == &local_pass_info) 184bf215546Sopenharmony_ci vk_free(alloc, (void *)local_pass_info.pAttachments); 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci *pRenderPass = pass_handle; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci return VK_SUCCESS; 189bf215546Sopenharmony_ci} 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ciVkResult 192bf215546Sopenharmony_civn_CreateRenderPass2(VkDevice device, 193bf215546Sopenharmony_ci const VkRenderPassCreateInfo2 *pCreateInfo, 194bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 195bf215546Sopenharmony_ci VkRenderPass *pRenderPass) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 198bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 199bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci uint32_t acquire_count; 202bf215546Sopenharmony_ci uint32_t release_count; 203bf215546Sopenharmony_ci vn_render_pass_count_present_src2(pCreateInfo, &acquire_count, 204bf215546Sopenharmony_ci &release_count); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci struct vn_render_pass *pass = 207bf215546Sopenharmony_ci vn_render_pass_create(dev, acquire_count, release_count, alloc); 208bf215546Sopenharmony_ci if (!pass) 209bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci VkRenderPassCreateInfo2 local_pass_info; 212bf215546Sopenharmony_ci if (pass->present_src_count) { 213bf215546Sopenharmony_ci VkAttachmentDescription2 *temp_atts = 214bf215546Sopenharmony_ci vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount, 215bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 216bf215546Sopenharmony_ci if (!temp_atts) { 217bf215546Sopenharmony_ci vk_free(alloc, pass); 218bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci vn_render_pass_replace_present_src2(pass, pCreateInfo, temp_atts); 222bf215546Sopenharmony_ci vn_render_pass_setup_present_src_barriers(pass); 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci local_pass_info = *pCreateInfo; 225bf215546Sopenharmony_ci local_pass_info.pAttachments = temp_atts; 226bf215546Sopenharmony_ci pCreateInfo = &local_pass_info; 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci VkRenderPass pass_handle = vn_render_pass_to_handle(pass); 230bf215546Sopenharmony_ci vn_async_vkCreateRenderPass2(dev->instance, device, pCreateInfo, NULL, 231bf215546Sopenharmony_ci &pass_handle); 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci if (pCreateInfo == &local_pass_info) 234bf215546Sopenharmony_ci vk_free(alloc, (void *)local_pass_info.pAttachments); 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci *pRenderPass = pass_handle; 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci return VK_SUCCESS; 239bf215546Sopenharmony_ci} 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_civoid 242bf215546Sopenharmony_civn_DestroyRenderPass(VkDevice device, 243bf215546Sopenharmony_ci VkRenderPass renderPass, 244bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 245bf215546Sopenharmony_ci{ 246bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 247bf215546Sopenharmony_ci struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass); 248bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 249bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci if (!pass) 252bf215546Sopenharmony_ci return; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci vn_async_vkDestroyRenderPass(dev->instance, device, renderPass, NULL); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci vn_object_base_fini(&pass->base); 257bf215546Sopenharmony_ci vk_free(alloc, pass); 258bf215546Sopenharmony_ci} 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_civoid 261bf215546Sopenharmony_civn_GetRenderAreaGranularity(VkDevice device, 262bf215546Sopenharmony_ci VkRenderPass renderPass, 263bf215546Sopenharmony_ci VkExtent2D *pGranularity) 264bf215546Sopenharmony_ci{ 265bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 266bf215546Sopenharmony_ci struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass); 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci if (!pass->granularity.width) { 269bf215546Sopenharmony_ci vn_call_vkGetRenderAreaGranularity(dev->instance, device, renderPass, 270bf215546Sopenharmony_ci &pass->granularity); 271bf215546Sopenharmony_ci } 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci *pGranularity = pass->granularity; 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci/* framebuffer commands */ 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ciVkResult 279bf215546Sopenharmony_civn_CreateFramebuffer(VkDevice device, 280bf215546Sopenharmony_ci const VkFramebufferCreateInfo *pCreateInfo, 281bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 282bf215546Sopenharmony_ci VkFramebuffer *pFramebuffer) 283bf215546Sopenharmony_ci{ 284bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 285bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 286bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci /* Two render passes differ only in attachment image layouts are considered 289bf215546Sopenharmony_ci * compatible. We must not use pCreateInfo->renderPass here. 290bf215546Sopenharmony_ci */ 291bf215546Sopenharmony_ci const bool imageless = 292bf215546Sopenharmony_ci pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT; 293bf215546Sopenharmony_ci const uint32_t view_count = imageless ? 0 : pCreateInfo->attachmentCount; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci struct vn_framebuffer *fb = 296bf215546Sopenharmony_ci vk_zalloc(alloc, sizeof(*fb) + sizeof(*fb->image_views) * view_count, 297bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 298bf215546Sopenharmony_ci if (!fb) 299bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci vn_object_base_init(&fb->base, VK_OBJECT_TYPE_FRAMEBUFFER, &dev->base); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci fb->image_view_count = view_count; 304bf215546Sopenharmony_ci memcpy(fb->image_views, pCreateInfo->pAttachments, 305bf215546Sopenharmony_ci sizeof(*pCreateInfo->pAttachments) * view_count); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci VkFramebuffer fb_handle = vn_framebuffer_to_handle(fb); 308bf215546Sopenharmony_ci vn_async_vkCreateFramebuffer(dev->instance, device, pCreateInfo, NULL, 309bf215546Sopenharmony_ci &fb_handle); 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci *pFramebuffer = fb_handle; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci return VK_SUCCESS; 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_civoid 317bf215546Sopenharmony_civn_DestroyFramebuffer(VkDevice device, 318bf215546Sopenharmony_ci VkFramebuffer framebuffer, 319bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 320bf215546Sopenharmony_ci{ 321bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 322bf215546Sopenharmony_ci struct vn_framebuffer *fb = vn_framebuffer_from_handle(framebuffer); 323bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 324bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci if (!fb) 327bf215546Sopenharmony_ci return; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci vn_async_vkDestroyFramebuffer(dev->instance, device, framebuffer, NULL); 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci vn_object_base_fini(&fb->base); 332bf215546Sopenharmony_ci vk_free(alloc, fb); 333bf215546Sopenharmony_ci} 334