mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 17:19:44 -06:00
VideoBackends: add support to allow rendering to multiple output textures
This commit is contained in:
@ -388,66 +388,71 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info)
|
||||
}
|
||||
|
||||
VkRenderPass ObjectCache::GetRenderPass(VkFormat color_format, VkFormat depth_format,
|
||||
u32 multisamples, VkAttachmentLoadOp load_op)
|
||||
u32 multisamples, VkAttachmentLoadOp load_op,
|
||||
u8 additional_attachment_count)
|
||||
{
|
||||
auto key = std::tie(color_format, depth_format, multisamples, load_op);
|
||||
auto key =
|
||||
std::tie(color_format, depth_format, multisamples, load_op, additional_attachment_count);
|
||||
auto it = m_render_pass_cache.find(key);
|
||||
if (it != m_render_pass_cache.end())
|
||||
return it->second;
|
||||
|
||||
VkAttachmentReference color_reference;
|
||||
VkAttachmentReference* color_reference_ptr = nullptr;
|
||||
VkAttachmentReference depth_reference;
|
||||
VkAttachmentReference* depth_reference_ptr = nullptr;
|
||||
std::array<VkAttachmentDescription, 2> attachments;
|
||||
u32 num_attachments = 0;
|
||||
std::vector<VkAttachmentDescription> attachments;
|
||||
std::vector<VkAttachmentReference> color_attachment_references;
|
||||
if (color_format != VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
attachments[num_attachments] = {0,
|
||||
color_format,
|
||||
static_cast<VkSampleCountFlagBits>(multisamples),
|
||||
load_op,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||
color_reference.attachment = num_attachments;
|
||||
VkAttachmentReference color_reference;
|
||||
color_reference.attachment = static_cast<uint32_t>(attachments.size());
|
||||
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
color_reference_ptr = &color_reference;
|
||||
num_attachments++;
|
||||
color_attachment_references.push_back(std::move(color_reference));
|
||||
attachments.push_back({0, color_format, static_cast<VkSampleCountFlagBits>(multisamples),
|
||||
load_op, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
|
||||
}
|
||||
if (depth_format != VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
attachments[num_attachments] = {0,
|
||||
depth_format,
|
||||
static_cast<VkSampleCountFlagBits>(multisamples),
|
||||
load_op,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
|
||||
depth_reference.attachment = num_attachments;
|
||||
depth_reference.attachment = static_cast<uint32_t>(attachments.size());
|
||||
depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depth_reference_ptr = &depth_reference;
|
||||
num_attachments++;
|
||||
attachments.push_back({0, depth_format, static_cast<VkSampleCountFlagBits>(multisamples),
|
||||
load_op, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL});
|
||||
}
|
||||
|
||||
VkSubpassDescription subpass = {0,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
0,
|
||||
nullptr,
|
||||
color_reference_ptr ? 1u : 0u,
|
||||
color_reference_ptr ? color_reference_ptr : nullptr,
|
||||
nullptr,
|
||||
depth_reference_ptr,
|
||||
0,
|
||||
nullptr};
|
||||
for (u8 i = 0; i < additional_attachment_count; i++)
|
||||
{
|
||||
VkAttachmentReference color_reference;
|
||||
color_reference.attachment = static_cast<uint32_t>(attachments.size());
|
||||
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
color_attachment_references.push_back(std::move(color_reference));
|
||||
attachments.push_back({0, color_format, static_cast<VkSampleCountFlagBits>(multisamples),
|
||||
load_op, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
|
||||
}
|
||||
|
||||
VkSubpassDescription subpass = {
|
||||
0,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
0,
|
||||
nullptr,
|
||||
static_cast<uint32_t>(color_attachment_references.size()),
|
||||
color_attachment_references.empty() ? nullptr : color_attachment_references.data(),
|
||||
nullptr,
|
||||
depth_reference_ptr,
|
||||
0,
|
||||
nullptr};
|
||||
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
nullptr,
|
||||
0,
|
||||
num_attachments,
|
||||
static_cast<uint32_t>(attachments.size()),
|
||||
attachments.data(),
|
||||
1,
|
||||
&subpass,
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
|
||||
// Render pass cache.
|
||||
VkRenderPass GetRenderPass(VkFormat color_format, VkFormat depth_format, u32 multisamples,
|
||||
VkAttachmentLoadOp load_op);
|
||||
VkAttachmentLoadOp load_op, u8 additional_attachment_count = 0);
|
||||
|
||||
// Pipeline cache. Used when creating pipelines for drivers to store compiled programs.
|
||||
VkPipelineCache GetPipelineCache() const { return m_pipeline_cache; }
|
||||
@ -102,7 +102,7 @@ private:
|
||||
std::unique_ptr<VKTexture> m_dummy_texture;
|
||||
|
||||
// Render pass cache
|
||||
using RenderPassCacheKey = std::tuple<VkFormat, VkFormat, u32, VkAttachmentLoadOp>;
|
||||
using RenderPassCacheKey = std::tuple<VkFormat, VkFormat, u32, VkAttachmentLoadOp, std::size_t>;
|
||||
std::map<RenderPassCacheKey, VkRenderPass> m_render_pass_cache;
|
||||
|
||||
// pipeline cache
|
||||
|
@ -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)
|
||||
|
@ -35,7 +35,8 @@ public:
|
||||
std::unique_ptr<AbstractStagingTexture>
|
||||
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;
|
||||
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
|
||||
std::vector<AbstractTexture*> additional_color_attachments) override;
|
||||
|
||||
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, std::string_view source,
|
||||
std::string_view name) override;
|
||||
|
@ -72,11 +72,11 @@ static VkPipelineMultisampleStateCreateInfo GetVulkanMultisampleState(const Fram
|
||||
0, // VkPipelineMultisampleStateCreateFlags flags
|
||||
static_cast<VkSampleCountFlagBits>(
|
||||
state.samples.Value()), // VkSampleCountFlagBits rasterizationSamples
|
||||
state.per_sample_shading, // VkBool32 sampleShadingEnable
|
||||
1.0f, // float minSampleShading
|
||||
nullptr, // const VkSampleMask* pSampleMask;
|
||||
VK_FALSE, // VkBool32 alphaToCoverageEnable
|
||||
VK_FALSE // VkBool32 alphaToOneEnable
|
||||
static_cast<bool>(state.per_sample_shading), // VkBool32 sampleShadingEnable
|
||||
1.0f, // float minSampleShading
|
||||
nullptr, // const VkSampleMask* pSampleMask;
|
||||
VK_FALSE, // VkBool32 alphaToCoverageEnable
|
||||
VK_FALSE // VkBool32 alphaToOneEnable
|
||||
};
|
||||
}
|
||||
|
||||
@ -243,7 +243,14 @@ std::unique_ptr<VKPipeline> VKPipeline::Create(const AbstractPipelineConfig& con
|
||||
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||
VKTexture::GetVkFormatForHostTextureFormat(config.framebuffer_state.color_texture_format),
|
||||
VKTexture::GetVkFormatForHostTextureFormat(config.framebuffer_state.depth_texture_format),
|
||||
config.framebuffer_state.samples, VK_ATTACHMENT_LOAD_OP_LOAD);
|
||||
config.framebuffer_state.samples, VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
config.framebuffer_state.additional_color_attachment_count);
|
||||
|
||||
if (render_pass == VK_NULL_HANDLE)
|
||||
{
|
||||
PanicAlertFmt("Failed to get render pass");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get pipeline layout.
|
||||
VkPipelineLayout pipeline_layout;
|
||||
@ -343,8 +350,18 @@ std::unique_ptr<VKPipeline> VKPipeline::Create(const AbstractPipelineConfig& con
|
||||
GetVulkanDepthStencilState(config.depth_state);
|
||||
VkPipelineColorBlendAttachmentState blend_attachment_state =
|
||||
GetVulkanAttachmentBlendState(config.blending_state, config.usage);
|
||||
|
||||
std::vector<VkPipelineColorBlendAttachmentState> blend_attachment_states;
|
||||
blend_attachment_states.push_back(blend_attachment_state);
|
||||
// Right now all our attachments have the same state
|
||||
for (u8 i = 0; i < static_cast<u8>(config.framebuffer_state.additional_color_attachment_count);
|
||||
i++)
|
||||
{
|
||||
blend_attachment_states.push_back(blend_attachment_state);
|
||||
}
|
||||
VkPipelineColorBlendStateCreateInfo blend_state =
|
||||
GetVulkanColorBlendState(config.blending_state, &blend_attachment_state, 1);
|
||||
GetVulkanColorBlendState(config.blending_state, blend_attachment_states.data(),
|
||||
static_cast<uint32_t>(blend_attachment_states.size()));
|
||||
|
||||
// This viewport isn't used, but needs to be specified anyway.
|
||||
static const VkViewport viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
|
||||
|
@ -415,7 +415,7 @@ bool SwapChain::SetupSwapChainImages()
|
||||
if (!image.texture)
|
||||
return false;
|
||||
|
||||
image.framebuffer = VKFramebuffer::Create(image.texture.get(), nullptr);
|
||||
image.framebuffer = VKFramebuffer::Create(image.texture.get(), nullptr, {});
|
||||
if (!image.framebuffer)
|
||||
{
|
||||
image.texture.reset();
|
||||
|
@ -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
|
||||
|
@ -126,7 +126,8 @@ private:
|
||||
class VKFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
VKFramebuffer(VKTexture* color_attachment, VKTexture* depth_attachment, u32 width, u32 height,
|
||||
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);
|
||||
~VKFramebuffer() override;
|
||||
@ -137,10 +138,20 @@ public:
|
||||
VkRenderPass GetLoadRenderPass() const { return m_load_render_pass; }
|
||||
VkRenderPass GetDiscardRenderPass() const { return m_discard_render_pass; }
|
||||
VkRenderPass GetClearRenderPass() const { return m_clear_render_pass; }
|
||||
|
||||
void Unbind();
|
||||
void TransitionForRender();
|
||||
|
||||
static std::unique_ptr<VKFramebuffer> Create(VKTexture* color_attachments,
|
||||
VKTexture* depth_attachment);
|
||||
void SetAndClear(const VkRect2D& rect, const VkClearValue& color_value,
|
||||
const VkClearValue& depth_value);
|
||||
std::size_t GetNumberOfAdditonalAttachments() const
|
||||
{
|
||||
return m_additional_color_attachments.size();
|
||||
}
|
||||
|
||||
static std::unique_ptr<VKFramebuffer>
|
||||
Create(VKTexture* color_attachments, VKTexture* depth_attachment,
|
||||
std::vector<AbstractTexture*> additional_color_attachments);
|
||||
|
||||
protected:
|
||||
VkFramebuffer m_fb;
|
||||
|
Reference in New Issue
Block a user