VideoBackends: add support to allow rendering to multiple output textures

This commit is contained in:
iwubcode
2023-05-28 20:59:02 -05:00
parent 252d3f353a
commit 834f8f7b5c
43 changed files with 713 additions and 327 deletions

View File

@ -982,12 +982,13 @@ void VKStagingTexture::Flush()
m_needs_flush = false;
}
VKFramebuffer::VKFramebuffer(VKTexture* color_attachment, VKTexture* depth_attachment, u32 width,
VKFramebuffer::VKFramebuffer(VKTexture* color_attachment, VKTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments, u32 width,
u32 height, u32 layers, u32 samples, VkFramebuffer fb,
VkRenderPass load_render_pass, VkRenderPass discard_render_pass,
VkRenderPass clear_render_pass)
: AbstractFramebuffer(
color_attachment, depth_attachment,
color_attachment, depth_attachment, std::move(additional_color_attachments),
color_attachment ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined,
depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined,
width, height, layers, samples),
@ -1001,10 +1002,11 @@ VKFramebuffer::~VKFramebuffer()
g_command_buffer_mgr->DeferFramebufferDestruction(m_fb);
}
std::unique_ptr<VKFramebuffer> VKFramebuffer::Create(VKTexture* color_attachment,
VKTexture* depth_attachment)
std::unique_ptr<VKFramebuffer>
VKFramebuffer::Create(VKTexture* color_attachment, VKTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments)
{
if (!ValidateConfig(color_attachment, depth_attachment))
if (!ValidateConfig(color_attachment, depth_attachment, additional_color_attachments))
return nullptr;
const VkFormat vk_color_format =
@ -1017,21 +1019,27 @@ std::unique_ptr<VKFramebuffer> VKFramebuffer::Create(VKTexture* color_attachment
const u32 layers = either_attachment->GetLayers();
const u32 samples = either_attachment->GetSamples();
std::array<VkImageView, 2> attachment_views{};
u32 num_attachments = 0;
std::vector<VkImageView> attachment_views;
if (color_attachment)
attachment_views[num_attachments++] = color_attachment->GetView();
attachment_views.push_back(color_attachment->GetView());
if (depth_attachment)
attachment_views[num_attachments++] = depth_attachment->GetView();
attachment_views.push_back(depth_attachment->GetView());
for (auto* attachment : additional_color_attachments)
{
attachment_views.push_back(static_cast<VKTexture*>(attachment)->GetView());
}
VkRenderPass load_render_pass = g_object_cache->GetRenderPass(
vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_LOAD);
vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_LOAD,
static_cast<u8>(additional_color_attachments.size()));
VkRenderPass discard_render_pass = g_object_cache->GetRenderPass(
vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
static_cast<u8>(additional_color_attachments.size()));
VkRenderPass clear_render_pass = g_object_cache->GetRenderPass(
vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_CLEAR);
vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_CLEAR,
static_cast<u8>(additional_color_attachments.size()));
if (load_render_pass == VK_NULL_HANDLE || discard_render_pass == VK_NULL_HANDLE ||
clear_render_pass == VK_NULL_HANDLE)
{
@ -1042,7 +1050,7 @@ std::unique_ptr<VKFramebuffer> VKFramebuffer::Create(VKTexture* color_attachment
nullptr,
0,
load_render_pass,
num_attachments,
static_cast<uint32_t>(attachment_views.size()),
attachment_views.data(),
width,
height,
@ -1057,9 +1065,27 @@ std::unique_ptr<VKFramebuffer> VKFramebuffer::Create(VKTexture* color_attachment
return nullptr;
}
return std::make_unique<VKFramebuffer>(color_attachment, depth_attachment, width, height, layers,
samples, fb, load_render_pass, discard_render_pass,
clear_render_pass);
return std::make_unique<VKFramebuffer>(
color_attachment, depth_attachment, std::move(additional_color_attachments), width, height,
layers, samples, fb, load_render_pass, discard_render_pass, clear_render_pass);
}
void VKFramebuffer::Unbind()
{
if (m_color_attachment)
{
StateTracker::GetInstance()->UnbindTexture(
static_cast<VKTexture*>(m_color_attachment)->GetView());
}
for (auto* attachment : m_additional_color_attachments)
{
StateTracker::GetInstance()->UnbindTexture(static_cast<VKTexture*>(attachment)->GetView());
}
if (m_depth_attachment)
{
StateTracker::GetInstance()->UnbindTexture(
static_cast<VKTexture*>(m_depth_attachment)->GetView());
}
}
void VKFramebuffer::TransitionForRender()
@ -1070,6 +1096,12 @@ void VKFramebuffer::TransitionForRender()
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
for (auto* attachment : m_additional_color_attachments)
{
static_cast<VKTexture*>(attachment)
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
if (m_depth_attachment)
{
@ -1078,4 +1110,24 @@ void VKFramebuffer::TransitionForRender()
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
}
void VKFramebuffer::SetAndClear(const VkRect2D& rect, const VkClearValue& color_value,
const VkClearValue& depth_value)
{
std::vector<VkClearValue> clear_values;
if (GetColorFormat() != AbstractTextureFormat::Undefined)
{
clear_values.push_back(color_value);
}
if (GetDepthFormat() != AbstractTextureFormat::Undefined)
{
clear_values.push_back(depth_value);
}
for (std::size_t i = 0; i < m_additional_color_attachments.size(); i++)
{
clear_values.push_back(color_value);
}
StateTracker::GetInstance()->BeginClearRenderPass(rect, clear_values.data(),
static_cast<u32>(clear_values.size()));
}
} // namespace Vulkan