diff options
| author | Stenzek <stenzek@users.noreply.github.com> | 2018-03-08 00:52:49 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-08 00:52:49 +1000 |
| commit | 24a46dc6af007ba5085a0425de7a7937623eb333 (patch) | |
| tree | 05f61d35ff03d15e07455c458ae2069af455264f /Source/Core/VideoBackends/Vulkan/VKTexture.cpp | |
| parent | aee977e32a0054e6a32a750c90c941d979db9d5a (diff) | |
| parent | 4c24a697106471b33973da619a43167c947276aa (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.cpp | 194 |
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 |
