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

@ -88,11 +88,13 @@ std::unique_ptr<AbstractPipeline> VKGfx::CreatePipeline(const AbstractPipelineCo
return VKPipeline::Create(config);
}
std::unique_ptr<AbstractFramebuffer> VKGfx::CreateFramebuffer(AbstractTexture* color_attachment,
AbstractTexture* depth_attachment)
std::unique_ptr<AbstractFramebuffer>
VKGfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments)
{
return VKFramebuffer::Create(static_cast<VKTexture*>(color_attachment),
static_cast<VKTexture*>(depth_attachment));
static_cast<VKTexture*>(depth_attachment),
std::move(additional_color_attachments));
}
void VKGfx::SetPipeline(const AbstractPipeline* pipeline)
@ -138,12 +140,12 @@ void VKGfx::ClearRegion(const MathUtil::Rectangle<int>& target_rc, bool color_en
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLEAR_LOADOP_RENDERPASS))
use_clear_render_pass = false;
auto* vk_frame_buffer = static_cast<VKFramebuffer*>(m_current_framebuffer);
// Fastest path: Use a render pass to clear the buffers.
if (use_clear_render_pass)
{
const std::array<VkClearValue, 2> clear_values = {{clear_color_value, clear_depth_value}};
StateTracker::GetInstance()->BeginClearRenderPass(target_vk_rc, clear_values.data(),
static_cast<u32>(clear_values.size()));
vk_frame_buffer->SetAndClear(target_vk_rc, clear_color_value, clear_depth_value);
return;
}
@ -151,26 +153,40 @@ void VKGfx::ClearRegion(const MathUtil::Rectangle<int>& target_rc, bool color_en
// We can't use this when preserving alpha but clearing color.
if (use_clear_attachments)
{
VkClearAttachment clear_attachments[2];
uint32_t num_clear_attachments = 0;
std::vector<VkClearAttachment> clear_attachments;
bool has_color = false;
if (color_enable && alpha_enable)
{
clear_attachments[num_clear_attachments].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
clear_attachments[num_clear_attachments].colorAttachment = 0;
clear_attachments[num_clear_attachments].clearValue = clear_color_value;
num_clear_attachments++;
VkClearAttachment clear_attachment;
clear_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
clear_attachment.colorAttachment = 0;
clear_attachment.clearValue = clear_color_value;
clear_attachments.push_back(std::move(clear_attachment));
color_enable = false;
alpha_enable = false;
has_color = true;
}
if (z_enable)
{
clear_attachments[num_clear_attachments].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
clear_attachments[num_clear_attachments].colorAttachment = 0;
clear_attachments[num_clear_attachments].clearValue = clear_depth_value;
num_clear_attachments++;
VkClearAttachment clear_attachment;
clear_attachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
clear_attachment.colorAttachment = 0;
clear_attachment.clearValue = clear_depth_value;
clear_attachments.push_back(std::move(clear_attachment));
z_enable = false;
}
if (num_clear_attachments > 0)
if (has_color)
{
for (std::size_t i = 0; i < vk_frame_buffer->GetNumberOfAdditonalAttachments(); i++)
{
VkClearAttachment clear_attachment;
clear_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
clear_attachment.colorAttachment = 0;
clear_attachment.clearValue = clear_color_value;
clear_attachments.push_back(std::move(clear_attachment));
}
}
if (!clear_attachments.empty())
{
VkClearRect vk_rect = {target_vk_rc, 0, g_framebuffer_manager->GetEFBLayers()};
if (!StateTracker::GetInstance()->IsWithinRenderArea(
@ -181,8 +197,9 @@ void VKGfx::ClearRegion(const MathUtil::Rectangle<int>& target_rc, bool color_en
}
StateTracker::GetInstance()->BeginRenderPass();
vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_clear_attachments,
clear_attachments, 1, &vk_rect);
vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(),
static_cast<uint32_t>(clear_attachments.size()),
clear_attachments.data(), 1, &vk_rect);
}
}
@ -405,16 +422,7 @@ void VKGfx::BindFramebuffer(VKFramebuffer* fb)
StateTracker::GetInstance()->EndRenderPass();
// Shouldn't be bound as a texture.
if (fb->GetColorAttachment())
{
StateTracker::GetInstance()->UnbindTexture(
static_cast<VKTexture*>(fb->GetColorAttachment())->GetView());
}
if (fb->GetDepthAttachment())
{
StateTracker::GetInstance()->UnbindTexture(
static_cast<VKTexture*>(fb->GetDepthAttachment())->GetView());
}
fb->Unbind();
fb->TransitionForRender();
StateTracker::GetInstance()->SetFramebuffer(fb);
@ -449,22 +457,13 @@ void VKGfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const Clear
VKFramebuffer* vkfb = static_cast<VKFramebuffer*>(framebuffer);
BindFramebuffer(vkfb);
std::array<VkClearValue, 2> clear_values;
u32 num_clear_values = 0;
if (vkfb->GetColorFormat() != AbstractTextureFormat::Undefined)
{
std::memcpy(clear_values[num_clear_values].color.float32, color_value.data(),
sizeof(clear_values[num_clear_values].color.float32));
num_clear_values++;
}
if (vkfb->GetDepthFormat() != AbstractTextureFormat::Undefined)
{
clear_values[num_clear_values].depthStencil.depth = depth_value;
clear_values[num_clear_values].depthStencil.stencil = 0;
num_clear_values++;
}
StateTracker::GetInstance()->BeginClearRenderPass(vkfb->GetRect(), clear_values.data(),
num_clear_values);
VkClearValue clear_color_value;
std::memcpy(clear_color_value.color.float32, color_value.data(),
sizeof(clear_color_value.color.float32));
VkClearValue clear_depth_value;
clear_depth_value.depthStencil.depth = depth_value;
clear_depth_value.depthStencil.stencil = 0;
vkfb->SetAndClear(vkfb->GetRect(), clear_color_value, clear_depth_value);
}
void VKGfx::SetTexture(u32 index, const AbstractTexture* texture)