vladislavbelov
ffc4a56b9f
Fixes #6846 Differential Revision: https://code.wildfiregames.com/D5185 This was SVN commit r27965.
201 lines
6.7 KiB
C++
201 lines
6.7 KiB
C++
/* Copyright (C) 2023 Wildfire Games.
|
|
* This file is part of 0 A.D.
|
|
*
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
|
|
#include "RenderPassManager.h"
|
|
|
|
#include "lib/hash.h"
|
|
#include "ps/containers/StaticVector.h"
|
|
#include "renderer/backend/vulkan/Device.h"
|
|
#include "renderer/backend/vulkan/Mapping.h"
|
|
#include "renderer/backend/vulkan/Texture.h"
|
|
#include "renderer/backend/vulkan/Utilities.h"
|
|
|
|
namespace Renderer
|
|
{
|
|
|
|
namespace Backend
|
|
{
|
|
|
|
namespace Vulkan
|
|
{
|
|
|
|
size_t CRenderPassManager::DescHash::operator()(const Desc& desc) const
|
|
{
|
|
size_t seed = 0;
|
|
hash_combine(seed, desc.sampleCount);
|
|
|
|
if (desc.colorAttachment.has_value())
|
|
{
|
|
hash_combine(seed, (*desc.colorAttachment).format);
|
|
hash_combine(seed, (*desc.colorAttachment).loadOp);
|
|
hash_combine(seed, (*desc.colorAttachment).storeOp);
|
|
}
|
|
else
|
|
hash_combine(seed, VK_FORMAT_UNDEFINED);
|
|
|
|
if (desc.depthStencilAttachment.has_value())
|
|
{
|
|
hash_combine(seed, (*desc.depthStencilAttachment).format);
|
|
hash_combine(seed, (*desc.depthStencilAttachment).loadOp);
|
|
hash_combine(seed, (*desc.depthStencilAttachment).storeOp);
|
|
}
|
|
else
|
|
hash_combine(seed, VK_FORMAT_UNDEFINED);
|
|
|
|
return seed;
|
|
}
|
|
|
|
bool CRenderPassManager::DescEqual::operator()(const Desc& lhs, const Desc& rhs) const
|
|
{
|
|
auto compareAttachments = [](const std::optional<Attachment>& lhs, const std::optional<Attachment>& rhs) -> bool
|
|
{
|
|
if (lhs.has_value() != rhs.has_value())
|
|
return false;
|
|
if (!lhs.has_value())
|
|
return true;
|
|
return
|
|
(*lhs).format == (*rhs).format &&
|
|
(*lhs).loadOp == (*rhs).loadOp &&
|
|
(*lhs).storeOp == (*rhs).storeOp;
|
|
};
|
|
if (!compareAttachments(lhs.colorAttachment, rhs.colorAttachment))
|
|
return false;
|
|
if (!compareAttachments(lhs.depthStencilAttachment, rhs.depthStencilAttachment))
|
|
return false;
|
|
return lhs.sampleCount == rhs.sampleCount;
|
|
}
|
|
|
|
CRenderPassManager::CRenderPassManager(CDevice* device)
|
|
: m_Device(device)
|
|
{
|
|
}
|
|
|
|
CRenderPassManager::~CRenderPassManager()
|
|
{
|
|
for (const auto& it : m_RenderPassMap)
|
|
if (it.second != VK_NULL_HANDLE)
|
|
{
|
|
m_Device->ScheduleObjectToDestroy(
|
|
VK_OBJECT_TYPE_RENDER_PASS, it.second, VK_NULL_HANDLE);
|
|
}
|
|
m_RenderPassMap.clear();
|
|
}
|
|
|
|
VkRenderPass CRenderPassManager::GetOrCreateRenderPass(
|
|
SColorAttachment* colorAttachment,
|
|
SDepthStencilAttachment* depthStencilAttachment)
|
|
{
|
|
Desc desc{};
|
|
if (colorAttachment)
|
|
{
|
|
CTexture* colorAttachmentTexture = colorAttachment->texture->As<CTexture>();
|
|
desc.sampleCount = colorAttachmentTexture->GetSampleCount();
|
|
desc.colorAttachment.emplace(Attachment{
|
|
colorAttachmentTexture->GetVkFormat(),
|
|
colorAttachment->loadOp,
|
|
colorAttachment->storeOp});
|
|
}
|
|
if (depthStencilAttachment)
|
|
{
|
|
CTexture* depthStencilAttachmentTexture = depthStencilAttachment->texture->As<CTexture>();
|
|
desc.sampleCount = depthStencilAttachmentTexture->GetSampleCount();
|
|
desc.depthStencilAttachment.emplace(Attachment{
|
|
depthStencilAttachmentTexture->GetVkFormat(),
|
|
depthStencilAttachment->loadOp,
|
|
depthStencilAttachment->storeOp});
|
|
}
|
|
auto it = m_RenderPassMap.find(desc);
|
|
if (it != m_RenderPassMap.end())
|
|
return it->second;
|
|
|
|
uint32_t attachmentCount = 0;
|
|
PS::StaticVector<VkAttachmentDescription, 4> attachmentDescs;
|
|
std::optional<VkAttachmentReference> colorAttachmentRef;
|
|
std::optional<VkAttachmentReference> depthStencilAttachmentRef;
|
|
|
|
if (colorAttachment)
|
|
{
|
|
CTexture* colorAttachmentTexture = colorAttachment->texture->As<CTexture>();
|
|
|
|
VkAttachmentDescription colorAttachmentDesc{};
|
|
colorAttachmentDesc.format = colorAttachmentTexture->GetVkFormat();
|
|
colorAttachmentDesc.samples = Mapping::FromSampleCount(colorAttachmentTexture->GetSampleCount());
|
|
colorAttachmentDesc.loadOp = Mapping::FromAttachmentLoadOp(colorAttachment->loadOp);
|
|
colorAttachmentDesc.storeOp = Mapping::FromAttachmentStoreOp(colorAttachment->storeOp);
|
|
colorAttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
colorAttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
attachmentDescs.emplace_back(std::move(colorAttachmentDesc));
|
|
|
|
colorAttachmentRef.emplace(VkAttachmentReference{
|
|
attachmentCount++, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
|
|
}
|
|
|
|
if (depthStencilAttachment)
|
|
{
|
|
CTexture* depthStencilAttachmentTexture = depthStencilAttachment->texture->As<CTexture>();
|
|
|
|
VkAttachmentDescription depthStencilAttachmentDesc{};
|
|
depthStencilAttachmentDesc.format = depthStencilAttachmentTexture->GetVkFormat();
|
|
depthStencilAttachmentDesc.samples = Mapping::FromSampleCount(depthStencilAttachmentTexture->GetSampleCount());
|
|
depthStencilAttachmentDesc.loadOp = Mapping::FromAttachmentLoadOp(depthStencilAttachment->loadOp);
|
|
depthStencilAttachmentDesc.storeOp = Mapping::FromAttachmentStoreOp(depthStencilAttachment->storeOp);
|
|
depthStencilAttachmentDesc.stencilLoadOp = depthStencilAttachmentDesc.loadOp;
|
|
depthStencilAttachmentDesc.stencilStoreOp = depthStencilAttachmentDesc.storeOp;
|
|
depthStencilAttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
depthStencilAttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
|
attachmentDescs.emplace_back(std::move(depthStencilAttachmentDesc));
|
|
|
|
depthStencilAttachmentRef.emplace(VkAttachmentReference{
|
|
attachmentCount++, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL});
|
|
}
|
|
|
|
VkSubpassDescription subpassDesc{};
|
|
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
if (colorAttachment)
|
|
{
|
|
subpassDesc.colorAttachmentCount = 1;
|
|
subpassDesc.pColorAttachments = &(*colorAttachmentRef);
|
|
}
|
|
if (depthStencilAttachment)
|
|
subpassDesc.pDepthStencilAttachment = &(*depthStencilAttachmentRef);
|
|
|
|
VkRenderPassCreateInfo renderPassCreateInfo{};
|
|
renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
renderPassCreateInfo.attachmentCount = attachmentDescs.size();
|
|
renderPassCreateInfo.pAttachments = attachmentDescs.data();
|
|
renderPassCreateInfo.subpassCount = 1;
|
|
renderPassCreateInfo.pSubpasses = &subpassDesc;
|
|
|
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
|
ENSURE_VK_SUCCESS(
|
|
vkCreateRenderPass(
|
|
m_Device->GetVkDevice(), &renderPassCreateInfo, nullptr, &renderPass));
|
|
it = m_RenderPassMap.emplace(desc, renderPass).first;
|
|
|
|
return renderPass;
|
|
}
|
|
|
|
} // namespace Vulkan
|
|
|
|
} // namespace Backend
|
|
|
|
} // namespace Renderer
|