#include "renderpassmgr.h" void CRenderPassMgr::CreateRenderPass(BeginInfo *pBeginInfo, VkRenderPass *prp, VkFramebuffer *pfb) { RenderPassHandle *pRP = FindRenderPass(pBeginInfo); *prp = pRP->renderpass; if (pRP->framebuffer) { if (pRP->uWidth != pBeginInfo->uWidth) goto recreate; if (pRP->uHeight != pBeginInfo->uHeight) goto recreate; for (uint32_t i = 0; i < pRP->usages.GetSize(); i++) { RenderPassUsage *u = &pRP->usages[i]; RenderImage *im = &pBeginInfo->pRenderImages[i]; CVkImage *vku = (CVkImage*)u->pImage; CVkImage *imu = (CVkImage*)im->pImage; if (vku != imu) goto recreate; if (vku->m_imageView != imu->m_imageView) goto recreate; } if (pRP->bIsDepth) { CVkImage *vku = (CVkImage*)pRP->depth.pImage; CVkImage *imu = (CVkImage*)pBeginInfo->pDepth->pImage; if (vku != imu) goto recreate; if (vku->m_imageView != imu->m_imageView) goto recreate; } *pfb = pRP->framebuffer; return; recreate: m_scheduledReleasesFB.AppendTail(pRP->framebuffer); } CUtlVector image_views = {}; for (uint32_t i = 0; i < pRP->usages.GetSize(); i++) { RenderPassUsage *u = &pRP->usages[i]; RenderImage *im = &pBeginInfo->pRenderImages[i]; CVkImage *imu = (CVkImage*)im->pImage; u->pImage = imu; image_views.AppendTail(imu->m_imageView); } if (pRP->bIsDepth) { CVkImage *imu = (CVkImage*)pBeginInfo->pDepth->pImage; pRP->depth.pImage = imu; image_views.AppendTail(imu->m_imageView); } image_views.Reserve(pBeginInfo->uRenderImageCount); VkFramebufferCreateInfo fbci = {}; fbci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; fbci.renderPass = pRP->renderpass; fbci.attachmentCount = image_views.GetSize(); fbci.pAttachments = image_views.GetData(); fbci.width = pBeginInfo->uWidth; fbci.height = pBeginInfo->uHeight; fbci.layers = 1; vkCreateFramebuffer(m_hDevice, &fbci, NULL, &pRP->framebuffer); pRP->uWidth = pBeginInfo->uWidth; pRP->uHeight = pBeginInfo->uHeight; *pfb = pRP->framebuffer; } void CRenderPassMgr::Frame() { CUtlVector renderPassHandles = {}; for (auto &r: m_renderPassHandles) { if (r.bIsUsed) { renderPassHandles.AppendTail(r); r.bIsUsed = false; } else { m_scheduledReleasesRP.AppendTail(r.renderpass); m_scheduledReleasesFB.AppendTail(r.framebuffer); } } m_renderPassHandles = renderPassHandles; for (auto fb: m_scheduledReleasesFB) { vkDestroyFramebuffer(m_hDevice, fb, NULL); } for (auto rp: m_scheduledReleasesRP) { vkDestroyRenderPass(m_hDevice, rp, NULL); } m_scheduledReleasesFB = {}; m_scheduledReleasesRP = {}; } RenderPassHandle *CRenderPassMgr::FindRenderPass(BeginInfo *pBeginInfo) { for (auto &r: m_renderPassHandles) { if (!(pBeginInfo->pDepth && r.bIsDepth)) continue; if (pBeginInfo->uRenderImageCount != r.usages.GetSize()) continue; for (uint32_t i = 0; i < r.usages.GetSize(); i++) { RenderPassUsage *u = &r.usages[i]; RenderImage *im = &pBeginInfo->pRenderImages[i]; if (u->eLoadMode != im->eLoadMode) goto next_usage; if (u->eStoreMode != im->eStoreMode) goto next_usage; if (u->eFormat != im->pImage->GetImageFormat()) goto next_usage; if (u->eMultisampleType != im->pImage->GetMultisampleType()) goto next_usage; } r.bIsUsed = true; return &r; next_usage: continue; } VkRenderPass hRenderPass = NULL; CUtlVector attachments = {}; CUtlVector input_refs = {}; attachments.Resize(pBeginInfo->uRenderImageCount); input_refs.Resize(pBeginInfo->uRenderImageCount); uint32_t i = 0; for (uint32_t i = 0; i < pBeginInfo->uRenderImageCount; i++) { RenderImage *ri = pBeginInfo->pRenderImages+i; VkAttachmentDescription a = {}; a.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; a.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; a.format = CVkImage::GetImageFormat(ri->pImage->GetImageFormat()); a.samples = CVkImage::GetMultisampling(ri->pImage->GetMultisampleType()); V_printf("INTERNAL IMAGE %p\n",ri->pImage); V_printf(" %u\n",ri->pImage->GetImageFormat()); V_printf(" %u\n",ri->pImage->GetMultisampleType()); switch( ri->eLoadMode ) { case LOAD_MODE_DONT_CARE: a.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; break; case LOAD_MODE_LOAD: a.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; break; case LOAD_MODE_CLEAR: a.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; break; } a.storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[i] = a; VkAttachmentReference ref = {}; ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; ref.attachment = i; input_refs[i] = ref; } if (pBeginInfo->pDepth) { CVkImage *depth = (CVkImage*)pBeginInfo->pDepth->pImage; VkAttachmentDescription desc = {}; desc.format = CVkImage::GetImageFormat(depth->GetImageFormat()); desc.samples = CVkImage::GetMultisampling(depth->GetMultisampleType()); desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachments.AppendTail(desc); } VkAttachmentReference depthRef; depthRef.attachment = attachments.GetSize() - 1; depthRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass = {}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = input_refs.GetSize(); subpass.pColorAttachments = input_refs.GetData(); if (pBeginInfo->pDepth) { subpass.pDepthStencilAttachment = &depthRef; } VkRenderPassCreateInfo rpci = {}; rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; rpci.attachmentCount = attachments.GetSize(); rpci.pAttachments = attachments.GetData(); rpci.subpassCount = 1; rpci.pSubpasses = &subpass; vkCreateRenderPass(m_hDevice, &rpci, NULL, &hRenderPass); RenderPassHandle hHandle = {}; if (pBeginInfo->pDepth) { V_printf("DEPTH %p\n", pBeginInfo->pDepth->pImage); hHandle.depth.pImage = pBeginInfo->pDepth->pImage; hHandle.depth.eMultisampleType = pBeginInfo->pDepth->pImage->GetMultisampleType(); hHandle.depth.eFormat = pBeginInfo->pDepth->pImage->GetImageFormat(); hHandle.depth.eLoadMode = pBeginInfo->pDepth->eLoadMode; hHandle.depth.eStoreMode = pBeginInfo->pDepth->eStoreMode; hHandle.bIsDepth = true; } for (uint32_t i = 0; i < pBeginInfo->uRenderImageCount; i++) { RenderPassUsage hUsage = {}; RenderImage *ri = pBeginInfo->pRenderImages+i; hUsage.pImage = ri->pImage; hUsage.eMultisampleType = ri->pImage->GetMultisampleType(); hUsage.eFormat = ri->pImage->GetImageFormat(); hUsage.eLoadMode = ri->eLoadMode; hUsage.eStoreMode = ri->eStoreMode; hHandle.usages.AppendTail(hUsage); } hHandle.bIsUsed = true; hHandle.renderpass = hRenderPass; m_renderPassHandles.AppendTail(hHandle); return &m_renderPassHandles[m_renderPassHandles.GetSize()-1]; }