From b30342d38f372ac987322d9d01d9296eb2511f79 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 17 Jul 2018 13:22:48 +1000 Subject: [PATCH 1/3] VideoBackends: Support D24S8 abstract texture format --- Source/Core/VideoBackends/D3D/DXTexture.cpp | 6 ++++++ Source/Core/VideoBackends/OGL/OGLTexture.cpp | 5 +++++ .../Core/VideoBackends/Vulkan/Texture2D.cpp | 10 ++++----- Source/Core/VideoBackends/Vulkan/Util.cpp | 21 +++++++++++++++++++ Source/Core/VideoBackends/Vulkan/Util.h | 1 + .../Core/VideoBackends/Vulkan/VKTexture.cpp | 4 ++-- Source/Core/VideoCommon/AbstractTexture.cpp | 5 ++++- Source/Core/VideoCommon/TextureConfig.h | 1 + 8 files changed, 44 insertions(+), 9 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index 4f0dec113f..127a922146 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -49,6 +49,8 @@ DXGI_FORMAT GetDXGIFormatForHostFormat(AbstractTextureFormat format) return DXGI_FORMAT_R32_FLOAT; case AbstractTextureFormat::D16: return DXGI_FORMAT_R16_TYPELESS; + case AbstractTextureFormat::D24_S8: + return DXGI_FORMAT_R24G8_TYPELESS; case AbstractTextureFormat::D32F: return DXGI_FORMAT_R32_TYPELESS; case AbstractTextureFormat::D32F_S8: @@ -64,6 +66,8 @@ DXGI_FORMAT GetSRVFormatForHostFormat(AbstractTextureFormat format) { case AbstractTextureFormat::D16: return DXGI_FORMAT_R16_UNORM; + case AbstractTextureFormat::D24_S8: + return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; case AbstractTextureFormat::D32F: return DXGI_FORMAT_R32_FLOAT; case AbstractTextureFormat::D32F_S8: @@ -78,6 +82,8 @@ DXGI_FORMAT GetDSVFormatForHostFormat(AbstractTextureFormat format) { case AbstractTextureFormat::D16: return DXGI_FORMAT_D16_UNORM; + case AbstractTextureFormat::D24_S8: + return DXGI_FORMAT_D24_UNORM_S8_UINT; case AbstractTextureFormat::D32F: return DXGI_FORMAT_D32_FLOAT; case AbstractTextureFormat::D32F_S8: diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index 4ce9aa398c..5399a11d04 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -41,6 +41,8 @@ GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool st return GL_R32F; case AbstractTextureFormat::D16: return GL_DEPTH_COMPONENT16; + case AbstractTextureFormat::D24_S8: + return GL_DEPTH24_STENCIL8; case AbstractTextureFormat::D32F: return GL_DEPTH_COMPONENT32F; case AbstractTextureFormat::D32F_S8: @@ -65,6 +67,7 @@ GLenum GetGLFormatForTextureFormat(AbstractTextureFormat format) case AbstractTextureFormat::D16: case AbstractTextureFormat::D32F: return GL_DEPTH_COMPONENT; + case AbstractTextureFormat::D24_S8: case AbstractTextureFormat::D32F_S8: return GL_DEPTH_STENCIL; // Compressed texture formats don't use this parameter. @@ -86,6 +89,8 @@ GLenum GetGLTypeForTextureFormat(AbstractTextureFormat format) return GL_FLOAT; case AbstractTextureFormat::D16: return GL_UNSIGNED_SHORT; + case AbstractTextureFormat::D24_S8: + return GL_UNSIGNED_INT_24_8; case AbstractTextureFormat::D32F: return GL_FLOAT; case AbstractTextureFormat::D32F_S8: diff --git a/Source/Core/VideoBackends/Vulkan/Texture2D.cpp b/Source/Core/VideoBackends/Vulkan/Texture2D.cpp index 39eb9bfcd8..96bfba6538 100644 --- a/Source/Core/VideoBackends/Vulkan/Texture2D.cpp +++ b/Source/Core/VideoBackends/Vulkan/Texture2D.cpp @@ -169,9 +169,8 @@ void Texture2D::TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex m_image, // VkImage image - {static_cast(Util::IsDepthFormat(m_format) ? VK_IMAGE_ASPECT_DEPTH_BIT : - VK_IMAGE_ASPECT_COLOR_BIT), - 0, m_levels, 0, m_layers} // VkImageSubresourceRange subresourceRange + {Util::GetImageAspectForFormat(m_format), 0, m_levels, 0, + m_layers} // VkImageSubresourceRange subresourceRange }; // srcStageMask -> Stages that must complete before the barrier @@ -316,9 +315,8 @@ void Texture2D::TransitionToLayout(VkCommandBuffer command_buffer, ComputeImageL VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex m_image, // VkImage image - {static_cast(Util::IsDepthFormat(m_format) ? VK_IMAGE_ASPECT_DEPTH_BIT : - VK_IMAGE_ASPECT_COLOR_BIT), - 0, m_levels, 0, m_layers} // VkImageSubresourceRange subresourceRange + {Util::GetImageAspectForFormat(m_format), 0, m_levels, 0, + m_layers} // VkImageSubresourceRange subresourceRange }; VkPipelineStageFlags srcStageMask, dstStageMask; diff --git a/Source/Core/VideoBackends/Vulkan/Util.cpp b/Source/Core/VideoBackends/Vulkan/Util.cpp index 9e9060c5a3..4ffa5c0146 100644 --- a/Source/Core/VideoBackends/Vulkan/Util.cpp +++ b/Source/Core/VideoBackends/Vulkan/Util.cpp @@ -118,6 +118,9 @@ VkFormat GetVkFormatForHostTextureFormat(AbstractTextureFormat format) case AbstractTextureFormat::D16: return VK_FORMAT_D16_UNORM; + case AbstractTextureFormat::D24_S8: + return VK_FORMAT_D24_UNORM_S8_UINT; + case AbstractTextureFormat::R32F: return VK_FORMAT_R32_SFLOAT; @@ -133,6 +136,24 @@ VkFormat GetVkFormatForHostTextureFormat(AbstractTextureFormat format) } } +VkImageAspectFlags GetImageAspectForFormat(VkFormat format) +{ + switch (format) + { + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D32_SFLOAT: + return VK_IMAGE_ASPECT_DEPTH_BIT; + + default: + return VK_IMAGE_ASPECT_COLOR_BIT; + } +} + u32 GetTexelSize(VkFormat format) { // Only contains pixel formats we use. diff --git a/Source/Core/VideoBackends/Vulkan/Util.h b/Source/Core/VideoBackends/Vulkan/Util.h index 56d8d58ff0..ced63ef06b 100644 --- a/Source/Core/VideoBackends/Vulkan/Util.h +++ b/Source/Core/VideoBackends/Vulkan/Util.h @@ -29,6 +29,7 @@ bool IsDepthFormat(VkFormat format); bool IsCompressedFormat(VkFormat format); VkFormat GetLinearFormat(VkFormat format); VkFormat GetVkFormatForHostTextureFormat(AbstractTextureFormat format); +VkImageAspectFlags GetImageAspectForFormat(VkFormat format); u32 GetTexelSize(VkFormat format); u32 GetBlockSize(VkFormat format); diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp index cee60012a8..b3c111d5a2 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp @@ -94,8 +94,8 @@ std::unique_ptr VKTexture::Create(const TextureConfig& tex_config) { // 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}; + VkImageSubresourceRange clear_range = {Util::GetImageAspectForFormat(vk_format), 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(), diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp index b01fbce085..6190f0e51b 100644 --- a/Source/Core/VideoCommon/AbstractTexture.cpp +++ b/Source/Core/VideoCommon/AbstractTexture.cpp @@ -69,6 +69,7 @@ bool AbstractTexture::IsDepthFormat(AbstractTextureFormat format) switch (format) { case AbstractTextureFormat::D16: + case AbstractTextureFormat::D24_S8: case AbstractTextureFormat::D32F: case AbstractTextureFormat::D32F_S8: return true; @@ -80,7 +81,7 @@ bool AbstractTexture::IsDepthFormat(AbstractTextureFormat format) bool AbstractTexture::IsStencilFormat(AbstractTextureFormat format) { - return format == AbstractTextureFormat::D32F_S8; + return format == AbstractTextureFormat::D24_S8 || format == AbstractTextureFormat::D32F_S8; } size_t AbstractTexture::CalculateStrideForFormat(AbstractTextureFormat format, u32 row_length) @@ -100,6 +101,7 @@ size_t AbstractTexture::CalculateStrideForFormat(AbstractTextureFormat format, u case AbstractTextureFormat::BGRA8: case AbstractTextureFormat::R32F: case AbstractTextureFormat::D32F: + case AbstractTextureFormat::D24_S8: return static_cast(row_length) * 4; case AbstractTextureFormat::D32F_S8: return static_cast(row_length) * 8; @@ -124,6 +126,7 @@ size_t AbstractTexture::GetTexelSizeForFormat(AbstractTextureFormat format) return 2; case AbstractTextureFormat::RGBA8: case AbstractTextureFormat::BGRA8: + case AbstractTextureFormat::D24_S8: case AbstractTextureFormat::R32F: case AbstractTextureFormat::D32F: return 4; diff --git a/Source/Core/VideoCommon/TextureConfig.h b/Source/Core/VideoCommon/TextureConfig.h index 1aa27cca4c..a2358ff3b0 100644 --- a/Source/Core/VideoCommon/TextureConfig.h +++ b/Source/Core/VideoCommon/TextureConfig.h @@ -20,6 +20,7 @@ enum class AbstractTextureFormat : u32 BPTC, R16, D16, + D24_S8, R32F, D32F, D32F_S8, From 3323265d9113c5c2cf4f3ca92766458411ac8b5e Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 17 Jul 2018 13:24:36 +1000 Subject: [PATCH 2/3] FramebufferManager: Dynamic selection of EFB depth format --- .../VideoBackends/Vulkan/FramebufferManager.cpp | 15 ++++++++------- .../Core/VideoCommon/FramebufferManagerBase.cpp | 6 ++++++ Source/Core/VideoCommon/FramebufferManagerBase.h | 3 +++ Source/Core/VideoCommon/ShaderCache.cpp | 4 +++- Source/Core/VideoCommon/ShaderCache.h | 2 ++ 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp index 1713b0c514..27eeeb58ba 100644 --- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp @@ -142,12 +142,12 @@ bool FramebufferManager::Initialize() bool FramebufferManager::CreateEFBRenderPasses() { - m_efb_load_render_pass = - g_object_cache->GetRenderPass(EFB_COLOR_TEXTURE_FORMAT, EFB_DEPTH_TEXTURE_FORMAT, - g_ActiveConfig.iMultisamples, VK_ATTACHMENT_LOAD_OP_LOAD); - m_efb_clear_render_pass = - g_object_cache->GetRenderPass(EFB_COLOR_TEXTURE_FORMAT, EFB_DEPTH_TEXTURE_FORMAT, - g_ActiveConfig.iMultisamples, VK_ATTACHMENT_LOAD_OP_CLEAR); + m_efb_load_render_pass = g_object_cache->GetRenderPass( + EFB_COLOR_TEXTURE_FORMAT, Util::GetVkFormatForHostTextureFormat(GetEFBDepthFormat()), + g_ActiveConfig.iMultisamples, VK_ATTACHMENT_LOAD_OP_LOAD); + m_efb_clear_render_pass = g_object_cache->GetRenderPass( + EFB_COLOR_TEXTURE_FORMAT, Util::GetVkFormatForHostTextureFormat(GetEFBDepthFormat()), + g_ActiveConfig.iMultisamples, VK_ATTACHMENT_LOAD_OP_CLEAR); m_depth_resolve_render_pass = g_object_cache->GetRenderPass( EFB_DEPTH_AS_COLOR_TEXTURE_FORMAT, VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE); return m_efb_load_render_pass != VK_NULL_HANDLE && m_efb_clear_render_pass != VK_NULL_HANDLE && @@ -181,7 +181,8 @@ bool FramebufferManager::CreateEFBFramebuffer() VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); m_efb_depth_texture = Texture2D::Create( - efb_width, efb_height, 1, efb_layers, EFB_DEPTH_TEXTURE_FORMAT, efb_samples, + efb_width, efb_height, 1, efb_layers, + Util::GetVkFormatForHostTextureFormat(GetEFBDepthFormat()), efb_samples, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp index af8ad87256..d33f72b2d8 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp @@ -6,6 +6,7 @@ #include +#include "VideoCommon/AbstractTexture.h" #include "VideoCommon/RenderBase.h" std::unique_ptr g_framebuffer_manager; @@ -13,3 +14,8 @@ std::unique_ptr g_framebuffer_manager; unsigned int FramebufferManagerBase::m_EFBLayers = 1; FramebufferManagerBase::~FramebufferManagerBase() = default; + +AbstractTextureFormat FramebufferManagerBase::GetEFBDepthFormat() +{ + return AbstractTextureFormat::D32F; +} diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.h b/Source/Core/VideoCommon/FramebufferManagerBase.h index c77b741e41..ff9ff0cc2e 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.h +++ b/Source/Core/VideoCommon/FramebufferManagerBase.h @@ -8,6 +8,8 @@ #include "Common/CommonTypes.h" +enum class AbstractTextureFormat : u32; + inline bool AddressRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) { return !((aLower >= bUpper) || (bLower >= aUpper)); @@ -19,6 +21,7 @@ public: virtual ~FramebufferManagerBase(); static unsigned int GetEFBLayers() { return m_EFBLayers; } + static AbstractTextureFormat GetEFBDepthFormat(); protected: static unsigned int m_EFBLayers; diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 13b1bfc0fc..f369118962 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -10,6 +10,7 @@ #include "Core/ConfigManager.h" #include "Core/Host.h" +#include "VideoCommon/FramebufferManagerBase.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexLoaderManager.h" @@ -26,6 +27,7 @@ bool ShaderCache::Initialize() { m_api_type = g_ActiveConfig.backend_info.api_type; m_host_config = ShaderHostConfig::GetCurrent(); + m_efb_depth_format = FramebufferManagerBase::GetEFBDepthFormat(); m_efb_multisamples = g_ActiveConfig.iMultisamples; // Create the async compiler, and start the worker threads. @@ -441,7 +443,7 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig( config.depth_state = depth_state; config.blending_state = blending_state; config.framebuffer_state.color_texture_format = AbstractTextureFormat::RGBA8; - config.framebuffer_state.depth_texture_format = AbstractTextureFormat::D32F; + config.framebuffer_state.depth_texture_format = m_efb_depth_format; config.framebuffer_state.per_sample_shading = m_host_config.ssaa; config.framebuffer_state.samples = m_efb_multisamples; return config; diff --git a/Source/Core/VideoCommon/ShaderCache.h b/Source/Core/VideoCommon/ShaderCache.h index c1a8b06367..a91559c965 100644 --- a/Source/Core/VideoCommon/ShaderCache.h +++ b/Source/Core/VideoCommon/ShaderCache.h @@ -30,6 +30,7 @@ #include "VideoCommon/VertexShaderGen.h" class NativeVertexFormat; +enum class AbstractTextureFormat : u32; namespace VideoCommon { @@ -129,6 +130,7 @@ private: // Configuration bits. APIType m_api_type = APIType::Nothing; ShaderHostConfig m_host_config = {}; + AbstractTextureFormat m_efb_depth_format; u32 m_efb_multisamples = 1; std::unique_ptr m_async_shader_compiler; From dae161e1385f6f8904bbcc0803d7ae01fdf4bd8d Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 17 Jul 2018 13:26:37 +1000 Subject: [PATCH 3/3] FramebufferManager: Use D24S8 on Adreno when using Vulkan D32F clears are broken on Adreno, which resulted in smeared geometry across the screen. --- Source/Core/VideoCommon/DriverDetails.cpp | 3 ++- Source/Core/VideoCommon/DriverDetails.h | 7 +++++++ Source/Core/VideoCommon/FramebufferManagerBase.cpp | 9 ++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 1626e24d18..301c73d89f 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -108,7 +108,8 @@ static BugInfo m_known_bugs[] = { -1.0, true}, {API_VULKAN, OS_ALL, VENDOR_IMGTEC, DRIVER_IMGTEC, Family::UNKNOWN, BUG_BROKEN_CLEAR_LOADOP_RENDERPASS, -1.0, -1.0, true}, -}; + {API_VULKAN, OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM, Family::UNKNOWN, BUG_BROKEN_D32F_CLEAR, + -1.0, -1.0, true}}; static std::map m_bugs; diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h index 65b6c89fcb..9ace5f83b4 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -269,6 +269,13 @@ enum Bug // Started Version: 1.7 // Ended Version: 1.10 BUG_BROKEN_CLEAR_LOADOP_RENDERPASS, + + // BUG: 32-bit depth clears are broken in the Adreno Vulkan driver, and have no effect. + // To work around this, we use a D24_S8 buffer instead, which results in a loss of accuracy. + // We still resolve this to a R32F texture, as there is no 24-bit format. + // Started version: -1 + // Ended version: -1 + BUG_BROKEN_D32F_CLEAR, }; // Initializes our internal vendor, device family, and driver version diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp index d33f72b2d8..530aac7584 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp @@ -7,6 +7,7 @@ #include #include "VideoCommon/AbstractTexture.h" +#include "VideoCommon/DriverDetails.h" #include "VideoCommon/RenderBase.h" std::unique_ptr g_framebuffer_manager; @@ -17,5 +18,11 @@ FramebufferManagerBase::~FramebufferManagerBase() = default; AbstractTextureFormat FramebufferManagerBase::GetEFBDepthFormat() { - return AbstractTextureFormat::D32F; + // 32-bit depth clears are broken in the Adreno Vulkan driver, and have no effect. + // To work around this, we use a D24_S8 buffer instead, which results in a loss of accuracy. + // We still resolve this to a R32F texture, as there is no 24-bit format. + if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_D32F_CLEAR)) + return AbstractTextureFormat::D24_S8; + else + return AbstractTextureFormat::D32F; }