summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConnor McLaughlin <stenzek@gmail.com>2019-08-08 12:23:27 +1000
committerGitHub <noreply@github.com>2019-08-08 12:23:27 +1000
commit1092efa77ae302fc677ebb67cdf2f93024b93f79 (patch)
treef589368c3ae471cb03a79cf631d87cd3bc7aed80
parent9477c8b0ed834efc3b7cf5b9fcd48caf57611a8a (diff)
parent06daf5803243c5f36069d8f7a936e62857ce1eca (diff)
Merge pull request #8276 from stenzek/adreno-efb-access
Fix CPU EFB access on Adreno with Vulkan backend
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKTexture.cpp19
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKTexture.h1
-rw-r--r--Source/Core/VideoCommon/AbstractTexture.cpp13
-rw-r--r--Source/Core/VideoCommon/AbstractTexture.h3
-rw-r--r--Source/Core/VideoCommon/FramebufferManager.cpp76
-rw-r--r--Source/Core/VideoCommon/FramebufferManager.h1
6 files changed, 72 insertions, 41 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
index 27b079a779..89e4a29d41 100644
--- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp
@@ -138,7 +138,7 @@ bool VKTexture::CreateView(VkImageViewType type)
GetVkFormat(),
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY},
- {GetImageAspectForFormat(GetFormat()), 0, GetLevels(), 0, GetLayers()}};
+ {GetImageViewAspectForFormat(GetFormat()), 0, GetLevels(), 0, GetLayers()}};
VkResult res = vkCreateImageView(g_vulkan_context->GetDevice(), &view_info, nullptr, &m_view);
if (res != VK_SUCCESS)
@@ -237,6 +237,21 @@ VkImageAspectFlags VKTexture::GetImageAspectForFormat(AbstractTextureFormat form
}
}
+VkImageAspectFlags VKTexture::GetImageViewAspectForFormat(AbstractTextureFormat format)
+{
+ switch (format)
+ {
+ case AbstractTextureFormat::D16:
+ case AbstractTextureFormat::D24_S8:
+ case AbstractTextureFormat::D32F_S8:
+ case AbstractTextureFormat::D32F:
+ return VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ default:
+ return VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+}
+
void VKTexture::CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
@@ -743,7 +758,7 @@ void VKStagingTexture::CopyFromTexture(const AbstractTexture* src,
// Issue the image->buffer copy, but delay it for now.
VkBufferImageCopy image_copy = {};
- const VkImageAspectFlags aspect = VKTexture::GetImageAspectForFormat(src_tex->GetFormat());
+ const VkImageAspectFlags aspect = VKTexture::GetImageViewAspectForFormat(src_tex->GetFormat());
image_copy.bufferOffset =
static_cast<VkDeviceSize>(static_cast<size_t>(dst_rect.top) * m_config.GetStride() +
static_cast<size_t>(dst_rect.left) * m_texel_size);
diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.h b/Source/Core/VideoBackends/Vulkan/VKTexture.h
index 2a194acc4d..91d3e54eac 100644
--- a/Source/Core/VideoBackends/Vulkan/VKTexture.h
+++ b/Source/Core/VideoBackends/Vulkan/VKTexture.h
@@ -37,6 +37,7 @@ public:
static VkFormat GetLinearFormat(VkFormat format);
static VkFormat GetVkFormatForHostTextureFormat(AbstractTextureFormat format);
static VkImageAspectFlags GetImageAspectForFormat(AbstractTextureFormat format);
+ static VkImageAspectFlags GetImageViewAspectForFormat(AbstractTextureFormat format);
void CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp
index d0c27617db..23ade1f99b 100644
--- a/Source/Core/VideoCommon/AbstractTexture.cpp
+++ b/Source/Core/VideoCommon/AbstractTexture.cpp
@@ -88,20 +88,19 @@ bool AbstractTexture::IsStencilFormat(AbstractTextureFormat format)
return format == AbstractTextureFormat::D24_S8 || format == AbstractTextureFormat::D32F_S8;
}
-AbstractTextureFormat AbstractTexture::GetColorFormatForDepthFormat(AbstractTextureFormat format)
+bool AbstractTexture::IsCompatibleDepthAndColorFormats(AbstractTextureFormat depth_format,
+ AbstractTextureFormat color_format)
{
- switch (format)
+ switch (depth_format)
{
case AbstractTextureFormat::D16:
- return AbstractTextureFormat::R16;
+ return color_format == AbstractTextureFormat::R16;
- case AbstractTextureFormat::D24_S8: // TODO: Incorrect
case AbstractTextureFormat::D32F:
- case AbstractTextureFormat::D32F_S8:
- return AbstractTextureFormat::R32F;
+ return color_format == AbstractTextureFormat::R32F;
default:
- return format;
+ return false;
}
}
diff --git a/Source/Core/VideoCommon/AbstractTexture.h b/Source/Core/VideoCommon/AbstractTexture.h
index 6ff80e9703..99b5c0c398 100644
--- a/Source/Core/VideoCommon/AbstractTexture.h
+++ b/Source/Core/VideoCommon/AbstractTexture.h
@@ -44,7 +44,8 @@ public:
static bool IsCompressedFormat(AbstractTextureFormat format);
static bool IsDepthFormat(AbstractTextureFormat format);
static bool IsStencilFormat(AbstractTextureFormat format);
- static AbstractTextureFormat GetColorFormatForDepthFormat(AbstractTextureFormat format);
+ static bool IsCompatibleDepthAndColorFormats(AbstractTextureFormat depth_format,
+ AbstractTextureFormat color_format);
static u32 CalculateStrideForFormat(AbstractTextureFormat format, u32 row_length);
static u32 GetTexelSizeForFormat(AbstractTextureFormat format);
static u32 GetBlockSizeForFormat(AbstractTextureFormat format);
diff --git a/Source/Core/VideoCommon/FramebufferManager.cpp b/Source/Core/VideoCommon/FramebufferManager.cpp
index 48bef4b276..de3ca7457d 100644
--- a/Source/Core/VideoCommon/FramebufferManager.cpp
+++ b/Source/Core/VideoCommon/FramebufferManager.cpp
@@ -129,6 +129,11 @@ AbstractTextureFormat FramebufferManager::GetEFBDepthFormat()
return AbstractTextureFormat::D32F;
}
+AbstractTextureFormat FramebufferManager::GetEFBDepthCopyFormat()
+{
+ return AbstractTextureFormat::R32F;
+}
+
static u32 CalculateEFBLayers()
{
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? 2 : 1;
@@ -183,11 +188,10 @@ bool FramebufferManager::CreateEFBFramebuffer()
m_efb_resolve_color_texture = g_renderer->CreateTexture(
TextureConfig(efb_color_texture_config.width, efb_color_texture_config.height, 1,
efb_color_texture_config.layers, 1, efb_color_texture_config.format, 0));
- m_efb_depth_resolve_texture = g_renderer->CreateTexture(TextureConfig(
- efb_depth_texture_config.width, efb_depth_texture_config.height, 1,
- efb_depth_texture_config.layers, 1,
- AbstractTexture::GetColorFormatForDepthFormat(efb_depth_texture_config.format),
- AbstractTextureFlag_RenderTarget));
+ m_efb_depth_resolve_texture = g_renderer->CreateTexture(
+ TextureConfig(efb_depth_texture_config.width, efb_depth_texture_config.height, 1,
+ efb_depth_texture_config.layers, 1, GetEFBDepthCopyFormat(),
+ AbstractTextureFlag_RenderTarget));
if (!m_efb_resolve_color_texture || !m_efb_depth_resolve_texture)
return false;
@@ -447,8 +451,7 @@ bool FramebufferManager::CompileReadbackPipelines()
return false;
// same for depth, except different format
- config.framebuffer_state.color_texture_format =
- AbstractTexture::GetColorFormatForDepthFormat(GetEFBDepthFormat());
+ config.framebuffer_state.color_texture_format = GetEFBDepthCopyFormat();
m_efb_depth_cache.copy_pipeline = g_renderer->CreatePipeline(config);
if (!m_efb_depth_cache.copy_pipeline)
return false;
@@ -493,29 +496,39 @@ void FramebufferManager::DestroyReadbackPipelines()
bool FramebufferManager::CreateReadbackFramebuffer()
{
- // Since we can't partially copy from a depth buffer directly to the staging texture in D3D, we
- // use an intermediate buffer to avoid copying the whole texture.
- if ((IsUsingTiledEFBCache() && !g_ActiveConfig.backend_info.bSupportsPartialDepthCopies) ||
- g_renderer->GetEFBScale() != 1)
+ if (g_renderer->GetEFBScale() != 1)
{
const TextureConfig color_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH,
IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1,
1, 1, GetEFBColorFormat(), AbstractTextureFlag_RenderTarget);
- const TextureConfig depth_config(
- color_config.width, color_config.height, 1, 1, 1,
- AbstractTexture::GetColorFormatForDepthFormat(GetEFBDepthFormat()),
- AbstractTextureFlag_RenderTarget);
-
m_efb_color_cache.texture = g_renderer->CreateTexture(color_config);
- m_efb_depth_cache.texture = g_renderer->CreateTexture(depth_config);
- if (!m_efb_color_cache.texture || !m_efb_depth_cache.texture)
+ if (!m_efb_color_cache.texture)
return false;
m_efb_color_cache.framebuffer =
g_renderer->CreateFramebuffer(m_efb_color_cache.texture.get(), nullptr);
+ if (!m_efb_color_cache.framebuffer)
+ return false;
+ }
+
+ // Since we can't partially copy from a depth buffer directly to the staging texture in D3D, we
+ // use an intermediate buffer to avoid copying the whole texture.
+ if ((IsUsingTiledEFBCache() && !g_ActiveConfig.backend_info.bSupportsPartialDepthCopies) ||
+ !AbstractTexture::IsCompatibleDepthAndColorFormats(m_efb_depth_texture->GetFormat(),
+ GetEFBDepthCopyFormat()) ||
+ g_renderer->GetEFBScale() != 1)
+ {
+ const TextureConfig depth_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH,
+ IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1,
+ 1, 1, GetEFBDepthCopyFormat(),
+ AbstractTextureFlag_RenderTarget);
+ m_efb_depth_cache.texture = g_renderer->CreateTexture(depth_config);
+ if (!m_efb_depth_cache.texture)
+ return false;
+
m_efb_depth_cache.framebuffer =
g_renderer->CreateFramebuffer(m_efb_depth_cache.texture.get(), nullptr);
- if (!m_efb_color_cache.framebuffer || !m_efb_depth_cache.framebuffer)
+ if (!m_efb_depth_cache.framebuffer)
return false;
}
@@ -525,8 +538,7 @@ bool FramebufferManager::CreateReadbackFramebuffer()
TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBColorFormat(), 0));
m_efb_depth_cache.readback_texture = g_renderer->CreateStagingTexture(
StagingTextureType::Mutable,
- TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1,
- AbstractTexture::GetColorFormatForDepthFormat(GetEFBDepthFormat()), 0));
+ TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBDepthCopyFormat(), 0));
if (!m_efb_color_cache.readback_texture || !m_efb_depth_cache.readback_texture)
return false;
@@ -564,7 +576,10 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index)
// Force the path through the intermediate texture, as we can't do an image copy from a depth
// buffer directly to a staging texture (must be the whole resource).
const bool force_intermediate_copy =
- depth && !g_ActiveConfig.backend_info.bSupportsPartialDepthCopies && IsUsingTiledEFBCache();
+ depth &&
+ ((!g_ActiveConfig.backend_info.bSupportsPartialDepthCopies && IsUsingTiledEFBCache()) ||
+ !AbstractTexture::IsCompatibleDepthAndColorFormats(m_efb_depth_texture->GetFormat(),
+ GetEFBDepthCopyFormat()));
// Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on.
EFBCacheData& data = depth ? m_efb_depth_cache : m_efb_color_cache;
@@ -889,21 +904,20 @@ void FramebufferManager::DoSaveState(PointerWrap& p)
1, GetEFBColorFormat(), 0);
g_texture_cache->SerializeTexture(color_texture, color_texture_config, p);
- if (GetEFBDepthFormat() == AbstractTextureFormat::D32F)
+ if (AbstractTexture::IsCompatibleDepthAndColorFormats(m_efb_depth_texture->GetFormat(),
+ GetEFBDepthCopyFormat()))
{
- const TextureConfig depth_texture_config(
- depth_texture->GetWidth(), depth_texture->GetHeight(), depth_texture->GetLevels(),
- depth_texture->GetLayers(), 1,
- AbstractTexture::GetColorFormatForDepthFormat(GetEFBDepthFormat()), 0);
+ const TextureConfig depth_texture_config(depth_texture->GetWidth(), depth_texture->GetHeight(),
+ depth_texture->GetLevels(), depth_texture->GetLayers(),
+ 1, GetEFBDepthCopyFormat(), 0);
g_texture_cache->SerializeTexture(depth_texture, depth_texture_config, p);
}
else
{
// If the EFB is backed by a D24S8 texture, we first have to convert it to R32F.
- const TextureConfig temp_texture_config(depth_texture->GetWidth(), depth_texture->GetHeight(),
- depth_texture->GetLevels(), depth_texture->GetLayers(),
- 1, AbstractTextureFormat::R32F,
- AbstractTextureFlag_RenderTarget);
+ const TextureConfig temp_texture_config(
+ depth_texture->GetWidth(), depth_texture->GetHeight(), depth_texture->GetLevels(),
+ depth_texture->GetLayers(), 1, GetEFBDepthCopyFormat(), AbstractTextureFlag_RenderTarget);
std::unique_ptr<AbstractTexture> temp_texture = g_renderer->CreateTexture(temp_texture_config);
std::unique_ptr<AbstractFramebuffer> temp_fb =
g_renderer->CreateFramebuffer(temp_texture.get(), nullptr);
diff --git a/Source/Core/VideoCommon/FramebufferManager.h b/Source/Core/VideoCommon/FramebufferManager.h
index b4ae99361d..786f22e537 100644
--- a/Source/Core/VideoCommon/FramebufferManager.h
+++ b/Source/Core/VideoCommon/FramebufferManager.h
@@ -44,6 +44,7 @@ public:
// Does not require the framebuffer to be created. Slower than direct queries.
static AbstractTextureFormat GetEFBColorFormat();
static AbstractTextureFormat GetEFBDepthFormat();
+ static AbstractTextureFormat GetEFBDepthCopyFormat();
static TextureConfig GetEFBColorTextureConfig();
static TextureConfig GetEFBDepthTextureConfig();