Files
funnygame/materialsystem/vulkan/renderpassmgr.cpp
T
2026-08-29 12:31:10 +03:00

230 lines
6.9 KiB
C++

#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<VkImageView> 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<RenderPassHandle> 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<VkAttachmentDescription> attachments = {};
CUtlVector<VkAttachmentReference> 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];
}