mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-03-12 06:39:14 +01:00
FramebufferManager: Correctly handle read back D24S8 textures
Needed for the Adreno/Vulkan workaround, and if we ever switch to a D24 texture for the depth buffer w/ unrestricted depth range.
This commit is contained in:
parent
2698e311aa
commit
06daf58032
@ -88,20 +88,19 @@ bool AbstractTexture::IsStencilFormat(AbstractTextureFormat format)
|
|||||||
return format == AbstractTextureFormat::D24_S8 || format == AbstractTextureFormat::D32F_S8;
|
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:
|
case AbstractTextureFormat::D16:
|
||||||
return AbstractTextureFormat::R16;
|
return color_format == AbstractTextureFormat::R16;
|
||||||
|
|
||||||
case AbstractTextureFormat::D24_S8: // TODO: Incorrect
|
|
||||||
case AbstractTextureFormat::D32F:
|
case AbstractTextureFormat::D32F:
|
||||||
case AbstractTextureFormat::D32F_S8:
|
return color_format == AbstractTextureFormat::R32F;
|
||||||
return AbstractTextureFormat::R32F;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return format;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,8 @@ public:
|
|||||||
static bool IsCompressedFormat(AbstractTextureFormat format);
|
static bool IsCompressedFormat(AbstractTextureFormat format);
|
||||||
static bool IsDepthFormat(AbstractTextureFormat format);
|
static bool IsDepthFormat(AbstractTextureFormat format);
|
||||||
static bool IsStencilFormat(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 CalculateStrideForFormat(AbstractTextureFormat format, u32 row_length);
|
||||||
static u32 GetTexelSizeForFormat(AbstractTextureFormat format);
|
static u32 GetTexelSizeForFormat(AbstractTextureFormat format);
|
||||||
static u32 GetBlockSizeForFormat(AbstractTextureFormat format);
|
static u32 GetBlockSizeForFormat(AbstractTextureFormat format);
|
||||||
|
@ -129,6 +129,11 @@ AbstractTextureFormat FramebufferManager::GetEFBDepthFormat()
|
|||||||
return AbstractTextureFormat::D32F;
|
return AbstractTextureFormat::D32F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractTextureFormat FramebufferManager::GetEFBDepthCopyFormat()
|
||||||
|
{
|
||||||
|
return AbstractTextureFormat::R32F;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 CalculateEFBLayers()
|
static u32 CalculateEFBLayers()
|
||||||
{
|
{
|
||||||
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? 2 : 1;
|
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? 2 : 1;
|
||||||
@ -183,11 +188,10 @@ bool FramebufferManager::CreateEFBFramebuffer()
|
|||||||
m_efb_resolve_color_texture = g_renderer->CreateTexture(
|
m_efb_resolve_color_texture = g_renderer->CreateTexture(
|
||||||
TextureConfig(efb_color_texture_config.width, efb_color_texture_config.height, 1,
|
TextureConfig(efb_color_texture_config.width, efb_color_texture_config.height, 1,
|
||||||
efb_color_texture_config.layers, 1, efb_color_texture_config.format, 0));
|
efb_color_texture_config.layers, 1, efb_color_texture_config.format, 0));
|
||||||
m_efb_depth_resolve_texture = g_renderer->CreateTexture(TextureConfig(
|
m_efb_depth_resolve_texture = g_renderer->CreateTexture(
|
||||||
efb_depth_texture_config.width, efb_depth_texture_config.height, 1,
|
TextureConfig(efb_depth_texture_config.width, efb_depth_texture_config.height, 1,
|
||||||
efb_depth_texture_config.layers, 1,
|
efb_depth_texture_config.layers, 1, GetEFBDepthCopyFormat(),
|
||||||
AbstractTexture::GetColorFormatForDepthFormat(efb_depth_texture_config.format),
|
AbstractTextureFlag_RenderTarget));
|
||||||
AbstractTextureFlag_RenderTarget));
|
|
||||||
if (!m_efb_resolve_color_texture || !m_efb_depth_resolve_texture)
|
if (!m_efb_resolve_color_texture || !m_efb_depth_resolve_texture)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -447,8 +451,7 @@ bool FramebufferManager::CompileReadbackPipelines()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// same for depth, except different format
|
// same for depth, except different format
|
||||||
config.framebuffer_state.color_texture_format =
|
config.framebuffer_state.color_texture_format = GetEFBDepthCopyFormat();
|
||||||
AbstractTexture::GetColorFormatForDepthFormat(GetEFBDepthFormat());
|
|
||||||
m_efb_depth_cache.copy_pipeline = g_renderer->CreatePipeline(config);
|
m_efb_depth_cache.copy_pipeline = g_renderer->CreatePipeline(config);
|
||||||
if (!m_efb_depth_cache.copy_pipeline)
|
if (!m_efb_depth_cache.copy_pipeline)
|
||||||
return false;
|
return false;
|
||||||
@ -492,29 +495,39 @@ void FramebufferManager::DestroyReadbackPipelines()
|
|||||||
|
|
||||||
bool FramebufferManager::CreateReadbackFramebuffer()
|
bool FramebufferManager::CreateReadbackFramebuffer()
|
||||||
{
|
{
|
||||||
// Since we can't partially copy from a depth buffer directly to the staging texture in D3D, we
|
if (g_renderer->GetEFBScale() != 1)
|
||||||
// use an intermediate buffer to avoid copying the whole texture.
|
|
||||||
if ((IsUsingTiledEFBCache() && !g_ActiveConfig.backend_info.bSupportsPartialDepthCopies) ||
|
|
||||||
g_renderer->GetEFBScale() != 1)
|
|
||||||
{
|
{
|
||||||
const TextureConfig color_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH,
|
const TextureConfig color_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH,
|
||||||
IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1,
|
IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1,
|
||||||
1, 1, GetEFBColorFormat(), AbstractTextureFlag_RenderTarget);
|
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_color_cache.texture = g_renderer->CreateTexture(color_config);
|
||||||
m_efb_depth_cache.texture = g_renderer->CreateTexture(depth_config);
|
if (!m_efb_color_cache.texture)
|
||||||
if (!m_efb_color_cache.texture || !m_efb_depth_cache.texture)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_efb_color_cache.framebuffer =
|
m_efb_color_cache.framebuffer =
|
||||||
g_renderer->CreateFramebuffer(m_efb_color_cache.texture.get(), nullptr);
|
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 =
|
m_efb_depth_cache.framebuffer =
|
||||||
g_renderer->CreateFramebuffer(m_efb_depth_cache.texture.get(), nullptr);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,8 +537,7 @@ bool FramebufferManager::CreateReadbackFramebuffer()
|
|||||||
TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBColorFormat(), 0));
|
TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBColorFormat(), 0));
|
||||||
m_efb_depth_cache.readback_texture = g_renderer->CreateStagingTexture(
|
m_efb_depth_cache.readback_texture = g_renderer->CreateStagingTexture(
|
||||||
StagingTextureType::Mutable,
|
StagingTextureType::Mutable,
|
||||||
TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1,
|
TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBDepthCopyFormat(), 0));
|
||||||
AbstractTexture::GetColorFormatForDepthFormat(GetEFBDepthFormat()), 0));
|
|
||||||
if (!m_efb_color_cache.readback_texture || !m_efb_depth_cache.readback_texture)
|
if (!m_efb_color_cache.readback_texture || !m_efb_depth_cache.readback_texture)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -563,7 +575,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
|
// 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).
|
// buffer directly to a staging texture (must be the whole resource).
|
||||||
const bool force_intermediate_copy =
|
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.
|
// 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;
|
EFBCacheData& data = depth ? m_efb_depth_cache : m_efb_color_cache;
|
||||||
@ -888,21 +903,20 @@ void FramebufferManager::DoSaveState(PointerWrap& p)
|
|||||||
1, GetEFBColorFormat(), 0);
|
1, GetEFBColorFormat(), 0);
|
||||||
g_texture_cache->SerializeTexture(color_texture, color_texture_config, p);
|
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(
|
const TextureConfig depth_texture_config(depth_texture->GetWidth(), depth_texture->GetHeight(),
|
||||||
depth_texture->GetWidth(), depth_texture->GetHeight(), depth_texture->GetLevels(),
|
depth_texture->GetLevels(), depth_texture->GetLayers(),
|
||||||
depth_texture->GetLayers(), 1,
|
1, GetEFBDepthCopyFormat(), 0);
|
||||||
AbstractTexture::GetColorFormatForDepthFormat(GetEFBDepthFormat()), 0);
|
|
||||||
g_texture_cache->SerializeTexture(depth_texture, depth_texture_config, p);
|
g_texture_cache->SerializeTexture(depth_texture, depth_texture_config, p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the EFB is backed by a D24S8 texture, we first have to convert it to R32F.
|
// 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(),
|
const TextureConfig temp_texture_config(
|
||||||
depth_texture->GetLevels(), depth_texture->GetLayers(),
|
depth_texture->GetWidth(), depth_texture->GetHeight(), depth_texture->GetLevels(),
|
||||||
1, AbstractTextureFormat::R32F,
|
depth_texture->GetLayers(), 1, GetEFBDepthCopyFormat(), AbstractTextureFlag_RenderTarget);
|
||||||
AbstractTextureFlag_RenderTarget);
|
|
||||||
std::unique_ptr<AbstractTexture> temp_texture = g_renderer->CreateTexture(temp_texture_config);
|
std::unique_ptr<AbstractTexture> temp_texture = g_renderer->CreateTexture(temp_texture_config);
|
||||||
std::unique_ptr<AbstractFramebuffer> temp_fb =
|
std::unique_ptr<AbstractFramebuffer> temp_fb =
|
||||||
g_renderer->CreateFramebuffer(temp_texture.get(), nullptr);
|
g_renderer->CreateFramebuffer(temp_texture.get(), nullptr);
|
||||||
|
@ -44,6 +44,7 @@ public:
|
|||||||
// Does not require the framebuffer to be created. Slower than direct queries.
|
// Does not require the framebuffer to be created. Slower than direct queries.
|
||||||
static AbstractTextureFormat GetEFBColorFormat();
|
static AbstractTextureFormat GetEFBColorFormat();
|
||||||
static AbstractTextureFormat GetEFBDepthFormat();
|
static AbstractTextureFormat GetEFBDepthFormat();
|
||||||
|
static AbstractTextureFormat GetEFBDepthCopyFormat();
|
||||||
static TextureConfig GetEFBColorTextureConfig();
|
static TextureConfig GetEFBColorTextureConfig();
|
||||||
static TextureConfig GetEFBDepthTextureConfig();
|
static TextureConfig GetEFBDepthTextureConfig();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user