Path: blob/21.2-virgl/src/virtio/vulkan/vn_render_pass.c
4560 views
/*1* Copyright 2019 Google LLC2* SPDX-License-Identifier: MIT3*4* based in part on anv and radv which are:5* Copyright © 2015 Intel Corporation6* Copyright © 2016 Red Hat.7* Copyright © 2016 Bas Nieuwenhuizen8*/910#include "vn_render_pass.h"1112#include "venus-protocol/vn_protocol_driver_framebuffer.h"13#include "venus-protocol/vn_protocol_driver_render_pass.h"1415#include "vn_device.h"16#include "vn_image.h"1718#define COUNT_PRESENT_SRC(atts, att_count, initial_count, final_count) \19do { \20*initial_count = 0; \21*final_count = 0; \22for (uint32_t i = 0; i < att_count; i++) { \23if (atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) \24(*initial_count)++; \25if (atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) \26(*final_count)++; \27} \28} while (false)2930#define REPLACE_PRESENT_SRC(pass, atts, att_count, out_atts) \31do { \32struct vn_present_src_attachment *_acquire_atts = \33pass->present_src_attachments; \34struct vn_present_src_attachment *_release_atts = \35_acquire_atts + pass->acquire_count; \36\37memcpy(out_atts, atts, sizeof(*atts) * att_count); \38for (uint32_t i = 0; i < att_count; i++) { \39if (out_atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \40out_atts[i].initialLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; \41_acquire_atts->acquire = true; \42_acquire_atts->index = i; \43_acquire_atts++; \44} \45if (out_atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \46out_atts[i].finalLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; \47_release_atts->acquire = false; \48_release_atts->index = i; \49_release_atts++; \50} \51} \52} while (false)5354static void55vn_render_pass_count_present_src(const VkRenderPassCreateInfo *create_info,56uint32_t *initial_count,57uint32_t *final_count)58{59COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount,60initial_count, final_count);61}6263static void64vn_render_pass_count_present_src2(const VkRenderPassCreateInfo2 *create_info,65uint32_t *initial_count,66uint32_t *final_count)67{68COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount,69initial_count, final_count);70}7172static void73vn_render_pass_replace_present_src(struct vn_render_pass *pass,74const VkRenderPassCreateInfo *create_info,75VkAttachmentDescription *out_atts)76{77REPLACE_PRESENT_SRC(pass, create_info->pAttachments,78create_info->attachmentCount, out_atts);79}8081static void82vn_render_pass_replace_present_src2(struct vn_render_pass *pass,83const VkRenderPassCreateInfo2 *create_info,84VkAttachmentDescription2 *out_atts)85{86REPLACE_PRESENT_SRC(pass, create_info->pAttachments,87create_info->attachmentCount, out_atts);88}8990static void91vn_render_pass_setup_present_src_barriers(struct vn_render_pass *pass)92{93/* TODO parse VkSubpassDependency for more accurate barriers */94for (uint32_t i = 0; i < pass->present_src_count; i++) {95struct vn_present_src_attachment *att =96&pass->present_src_attachments[i];9798if (att->acquire) {99att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;100att->src_access_mask = 0;101102att->dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;103att->dst_access_mask =104VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;105} else {106att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;107att->src_access_mask = VK_ACCESS_MEMORY_WRITE_BIT;108109att->dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;110att->dst_access_mask = 0;111}112}113}114115static struct vn_render_pass *116vn_render_pass_create(struct vn_device *dev,117uint32_t acquire_count,118uint32_t release_count,119const VkAllocationCallbacks *alloc)120{121const uint32_t total_count = acquire_count + release_count;122struct vn_render_pass *pass = vk_zalloc(123alloc,124sizeof(*pass) + sizeof(pass->present_src_attachments[0]) * total_count,125VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);126if (!pass)127return NULL;128129vn_object_base_init(&pass->base, VK_OBJECT_TYPE_RENDER_PASS, &dev->base);130131pass->acquire_count = acquire_count;132pass->release_count = release_count;133pass->present_src_count = total_count;134135return pass;136}137138/* render pass commands */139140VkResult141vn_CreateRenderPass(VkDevice device,142const VkRenderPassCreateInfo *pCreateInfo,143const VkAllocationCallbacks *pAllocator,144VkRenderPass *pRenderPass)145{146struct vn_device *dev = vn_device_from_handle(device);147const VkAllocationCallbacks *alloc =148pAllocator ? pAllocator : &dev->base.base.alloc;149150uint32_t acquire_count;151uint32_t release_count;152vn_render_pass_count_present_src(pCreateInfo, &acquire_count,153&release_count);154155struct vn_render_pass *pass =156vn_render_pass_create(dev, acquire_count, release_count, alloc);157if (!pass)158return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);159160VkRenderPassCreateInfo local_pass_info;161if (pass->present_src_count) {162VkAttachmentDescription *temp_atts =163vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount,164VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);165if (!temp_atts) {166vk_free(alloc, pass);167return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);168}169170vn_render_pass_replace_present_src(pass, pCreateInfo, temp_atts);171vn_render_pass_setup_present_src_barriers(pass);172173local_pass_info = *pCreateInfo;174local_pass_info.pAttachments = temp_atts;175pCreateInfo = &local_pass_info;176}177178VkRenderPass pass_handle = vn_render_pass_to_handle(pass);179vn_async_vkCreateRenderPass(dev->instance, device, pCreateInfo, NULL,180&pass_handle);181182if (pCreateInfo == &local_pass_info)183vk_free(alloc, (void *)local_pass_info.pAttachments);184185*pRenderPass = pass_handle;186187return VK_SUCCESS;188}189190VkResult191vn_CreateRenderPass2(VkDevice device,192const VkRenderPassCreateInfo2 *pCreateInfo,193const VkAllocationCallbacks *pAllocator,194VkRenderPass *pRenderPass)195{196struct vn_device *dev = vn_device_from_handle(device);197const VkAllocationCallbacks *alloc =198pAllocator ? pAllocator : &dev->base.base.alloc;199200uint32_t acquire_count;201uint32_t release_count;202vn_render_pass_count_present_src2(pCreateInfo, &acquire_count,203&release_count);204205struct vn_render_pass *pass =206vn_render_pass_create(dev, acquire_count, release_count, alloc);207if (!pass)208return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);209210VkRenderPassCreateInfo2 local_pass_info;211if (pass->present_src_count) {212VkAttachmentDescription2 *temp_atts =213vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount,214VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);215if (!temp_atts) {216vk_free(alloc, pass);217return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);218}219220vn_render_pass_replace_present_src2(pass, pCreateInfo, temp_atts);221vn_render_pass_setup_present_src_barriers(pass);222223local_pass_info = *pCreateInfo;224local_pass_info.pAttachments = temp_atts;225pCreateInfo = &local_pass_info;226}227228VkRenderPass pass_handle = vn_render_pass_to_handle(pass);229vn_async_vkCreateRenderPass2(dev->instance, device, pCreateInfo, NULL,230&pass_handle);231232if (pCreateInfo == &local_pass_info)233vk_free(alloc, (void *)local_pass_info.pAttachments);234235*pRenderPass = pass_handle;236237return VK_SUCCESS;238}239240void241vn_DestroyRenderPass(VkDevice device,242VkRenderPass renderPass,243const VkAllocationCallbacks *pAllocator)244{245struct vn_device *dev = vn_device_from_handle(device);246struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass);247const VkAllocationCallbacks *alloc =248pAllocator ? pAllocator : &dev->base.base.alloc;249250if (!pass)251return;252253vn_async_vkDestroyRenderPass(dev->instance, device, renderPass, NULL);254255vn_object_base_fini(&pass->base);256vk_free(alloc, pass);257}258259void260vn_GetRenderAreaGranularity(VkDevice device,261VkRenderPass renderPass,262VkExtent2D *pGranularity)263{264struct vn_device *dev = vn_device_from_handle(device);265struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass);266267if (!pass->granularity.width) {268vn_call_vkGetRenderAreaGranularity(dev->instance, device, renderPass,269&pass->granularity);270}271272*pGranularity = pass->granularity;273}274275/* framebuffer commands */276277VkResult278vn_CreateFramebuffer(VkDevice device,279const VkFramebufferCreateInfo *pCreateInfo,280const VkAllocationCallbacks *pAllocator,281VkFramebuffer *pFramebuffer)282{283struct vn_device *dev = vn_device_from_handle(device);284const VkAllocationCallbacks *alloc =285pAllocator ? pAllocator : &dev->base.base.alloc;286287/* Two render passes differ only in attachment image layouts are considered288* compatible. We must not use pCreateInfo->renderPass here.289*/290const bool imageless =291pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;292const uint32_t view_count = imageless ? 0 : pCreateInfo->attachmentCount;293294struct vn_framebuffer *fb =295vk_zalloc(alloc, sizeof(*fb) + sizeof(*fb->image_views) * view_count,296VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);297if (!fb)298return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);299300vn_object_base_init(&fb->base, VK_OBJECT_TYPE_FRAMEBUFFER, &dev->base);301302fb->image_view_count = view_count;303memcpy(fb->image_views, pCreateInfo->pAttachments,304sizeof(*pCreateInfo->pAttachments) * view_count);305306VkFramebuffer fb_handle = vn_framebuffer_to_handle(fb);307vn_async_vkCreateFramebuffer(dev->instance, device, pCreateInfo, NULL,308&fb_handle);309310*pFramebuffer = fb_handle;311312return VK_SUCCESS;313}314315void316vn_DestroyFramebuffer(VkDevice device,317VkFramebuffer framebuffer,318const VkAllocationCallbacks *pAllocator)319{320struct vn_device *dev = vn_device_from_handle(device);321struct vn_framebuffer *fb = vn_framebuffer_from_handle(framebuffer);322const VkAllocationCallbacks *alloc =323pAllocator ? pAllocator : &dev->base.base.alloc;324325if (!fb)326return;327328vn_async_vkDestroyFramebuffer(dev->instance, device, framebuffer, NULL);329330vn_object_base_fini(&fb->base);331vk_free(alloc, fb);332}333334335