summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
diff options
context:
space:
mode:
authorStenzek <stenzek@users.noreply.github.com>2018-03-08 00:52:49 +1000
committerGitHub <noreply@github.com>2018-03-08 00:52:49 +1000
commit24a46dc6af007ba5085a0425de7a7937623eb333 (patch)
tree05f61d35ff03d15e07455c458ae2069af455264f /Source/Core/VideoBackends/Vulkan/VKTexture.cpp
parentaee977e32a0054e6a32a750c90c941d979db9d5a (diff)
parent4c24a697106471b33973da619a43167c947276aa (diff)
Merge pull request #6315 from stenzek/abstract-framebuffers
Abstract Framebuffers
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/VKTexture.cpp')
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKTexture.cpp194
1 files changed, 181 insertions, 13 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
index 4a4f70c2cb..a812e87602 100644
--- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
@@ -42,9 +42,10 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config)
// Allocate texture object
VkFormat vk_format = Util::GetVkFormatForHostTextureFormat(tex_config.format);
- auto texture = Texture2D::Create(tex_config.width, tex_config.height, tex_config.levels,
- tex_config.layers, vk_format, VK_SAMPLE_COUNT_1_BIT,
- VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, usage);
+ auto texture =
+ Texture2D::Create(tex_config.width, tex_config.height, tex_config.levels, tex_config.layers,
+ vk_format, static_cast<VkSampleCountFlagBits>(tex_config.samples),
+ VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, usage);
if (!texture)
{
@@ -56,8 +57,9 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config)
if (tex_config.rendertarget)
{
VkImageView framebuffer_attachments[] = {texture->GetView()};
- VkRenderPass render_pass = g_object_cache->GetRenderPass(
- texture->GetFormat(), VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
+ VkRenderPass render_pass =
+ g_object_cache->GetRenderPass(texture->GetFormat(), VK_FORMAT_UNDEFINED, tex_config.samples,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE);
VkFramebufferCreateInfo framebuffer_info = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
nullptr,
@@ -77,14 +79,29 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config)
return nullptr;
}
- // Clear render targets before use to prevent reading uninitialized memory.
- VkClearColorValue clear_value = {{0.0f, 0.0f, 0.0f, 1.0f}};
- VkImageSubresourceRange clear_range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, tex_config.levels, 0,
- tex_config.layers};
- texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- vkCmdClearColorImage(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), texture->GetImage(),
- texture->GetLayout(), &clear_value, 1, &clear_range);
+ if (!IsDepthFormat(tex_config.format))
+ {
+ // Clear render targets before use to prevent reading uninitialized memory.
+ VkClearColorValue clear_value = {{0.0f, 0.0f, 0.0f, 1.0f}};
+ VkImageSubresourceRange clear_range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, tex_config.levels, 0,
+ tex_config.layers};
+ texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ vkCmdClearColorImage(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), texture->GetImage(),
+ texture->GetLayout(), &clear_value, 1, &clear_range);
+ }
+ else
+ {
+ // Clear render targets before use to prevent reading uninitialized memory.
+ VkClearDepthStencilValue clear_value = {0.0f, 0};
+ VkImageSubresourceRange clear_range = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, tex_config.levels, 0,
+ tex_config.layers};
+ texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ vkCmdClearDepthStencilImage(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
+ texture->GetImage(), texture->GetLayout(), &clear_value, 1,
+ &clear_range);
+ }
}
return std::unique_ptr<VKTexture>(new VKTexture(tex_config, std::move(texture), framebuffer));
@@ -195,6 +212,43 @@ void VKTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
+void VKTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
+ u32 layer, u32 level)
+{
+ const VKTexture* srcentry = static_cast<const VKTexture*>(src);
+ _dbg_assert_(VIDEO, m_config.samples == 1 && m_config.width == srcentry->m_config.width &&
+ m_config.height == srcentry->m_config.height &&
+ srcentry->m_config.samples > 1);
+ _dbg_assert_(VIDEO,
+ rect.left + rect.GetWidth() <= static_cast<int>(srcentry->m_config.width) &&
+ rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
+
+ // Resolving is considered to be a transfer operation.
+ StateTracker::GetInstance()->EndRenderPass();
+ VkImageLayout old_src_layout = srcentry->m_texture->GetLayout();
+ srcentry->m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+ m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+
+ VkImageResolve resolve = {
+ {VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // srcSubresource
+ {rect.left, rect.top, 0}, // srcOffset
+ {VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // dstSubresource
+ {rect.left, rect.top, 0}, // dstOffset
+ {static_cast<u32>(rect.GetWidth()), static_cast<u32>(rect.GetHeight()), 1} // extent
+ };
+ vkCmdResolveImage(g_command_buffer_mgr->GetCurrentCommandBuffer(),
+ srcentry->m_texture->GetImage(), srcentry->m_texture->GetLayout(),
+ m_texture->GetImage(), m_texture->GetLayout(), 1, &resolve);
+
+ // Restore old source texture layout. Destination is assumed to be bound as a shader resource.
+ srcentry->m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
+ old_src_layout);
+ m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+}
+
void VKTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size)
{
@@ -512,4 +566,118 @@ void VKStagingTexture::Flush()
m_staging_buffer->InvalidateCPUCache();
}
+VKFramebuffer::VKFramebuffer(const VKTexture* color_attachment, const VKTexture* depth_attachment,
+ 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 ? color_attachment->GetFormat() : AbstractTextureFormat::Undefined,
+ depth_attachment ? depth_attachment->GetFormat() : AbstractTextureFormat::Undefined,
+ width, height, layers, samples),
+ m_color_attachment(color_attachment), m_depth_attachment(depth_attachment), m_fb(fb),
+ m_load_render_pass(load_render_pass), m_discard_render_pass(discard_render_pass),
+ m_clear_render_pass(clear_render_pass)
+{
+}
+
+VKFramebuffer::~VKFramebuffer()
+{
+ g_command_buffer_mgr->DeferFramebufferDestruction(m_fb);
+}
+
+std::unique_ptr<VKFramebuffer> VKFramebuffer::Create(const VKTexture* color_attachment,
+ const VKTexture* depth_attachment)
+{
+ if (!ValidateConfig(color_attachment, depth_attachment))
+ return nullptr;
+
+ const VkFormat vk_color_format =
+ color_attachment ? color_attachment->GetRawTexIdentifier()->GetFormat() : VK_FORMAT_UNDEFINED;
+ const VkFormat vk_depth_format =
+ depth_attachment ? depth_attachment->GetRawTexIdentifier()->GetFormat() : VK_FORMAT_UNDEFINED;
+ const VKTexture* either_attachment = color_attachment ? color_attachment : depth_attachment;
+ const u32 width = either_attachment->GetWidth();
+ const u32 height = either_attachment->GetHeight();
+ const u32 layers = either_attachment->GetLayers();
+ const u32 samples = either_attachment->GetSamples();
+
+ std::array<VkImageView, 2> attachment_views{};
+ u32 num_attachments = 0;
+
+ if (color_attachment)
+ attachment_views[num_attachments++] = color_attachment->GetRawTexIdentifier()->GetView();
+
+ if (depth_attachment)
+ attachment_views[num_attachments++] = depth_attachment->GetRawTexIdentifier()->GetView();
+
+ VkRenderPass load_render_pass = g_object_cache->GetRenderPass(
+ vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_LOAD);
+ VkRenderPass discard_render_pass = g_object_cache->GetRenderPass(
+ vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
+ VkRenderPass clear_render_pass = g_object_cache->GetRenderPass(
+ vk_color_format, vk_depth_format, samples, VK_ATTACHMENT_LOAD_OP_CLEAR);
+ if (load_render_pass == VK_NULL_HANDLE || discard_render_pass == VK_NULL_HANDLE ||
+ clear_render_pass == VK_NULL_HANDLE)
+ {
+ return nullptr;
+ }
+
+ VkFramebufferCreateInfo framebuffer_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ nullptr,
+ 0,
+ load_render_pass,
+ num_attachments,
+ attachment_views.data(),
+ width,
+ height,
+ layers};
+
+ VkFramebuffer fb;
+ VkResult res =
+ vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr, &fb);
+ if (res != VK_SUCCESS)
+ {
+ LOG_VULKAN_ERROR(res, "vkCreateFramebuffer failed: ");
+ 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);
+}
+
+void VKFramebuffer::TransitionForRender() const
+{
+ if (m_color_attachment)
+ {
+ m_color_attachment->GetRawTexIdentifier()->TransitionToLayout(
+ g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ }
+
+ if (m_depth_attachment)
+ {
+ m_depth_attachment->GetRawTexIdentifier()->TransitionToLayout(
+ g_command_buffer_mgr->GetCurrentCommandBuffer(),
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ }
+}
+
+void VKFramebuffer::TransitionForSample() const
+{
+ if (StateTracker::GetInstance()->GetFramebuffer() == m_fb)
+ StateTracker::GetInstance()->EndRenderPass();
+
+ if (m_color_attachment)
+ {
+ m_color_attachment->GetRawTexIdentifier()->TransitionToLayout(
+ g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ }
+
+ if (m_depth_attachment)
+ {
+ m_depth_attachment->GetRawTexIdentifier()->TransitionToLayout(
+ g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ }
+}
+
} // namespace Vulkan