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