FramebufferManager: Fix invalid readback of EFB D24S8 depth
Fixes assertion tripping when saving state on Adreno.
This commit is contained in:
parent
393ce529af
commit
ad373950a2
|
@ -188,11 +188,18 @@ 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));
|
||||||
|
if (!m_efb_resolve_color_texture)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We also need one to convert the D24S8 to R32F if that is being used (Adreno).
|
||||||
|
if (g_ActiveConfig.MultisamplingEnabled() || GetEFBDepthFormat() != AbstractTextureFormat::R32F)
|
||||||
|
{
|
||||||
m_efb_depth_resolve_texture = g_renderer->CreateTexture(
|
m_efb_depth_resolve_texture = g_renderer->CreateTexture(
|
||||||
TextureConfig(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, GetEFBDepthCopyFormat(),
|
efb_depth_texture_config.layers, 1, GetEFBDepthCopyFormat(),
|
||||||
AbstractTextureFlag_RenderTarget));
|
AbstractTextureFlag_RenderTarget));
|
||||||
if (!m_efb_resolve_color_texture || !m_efb_depth_resolve_texture)
|
if (!m_efb_depth_resolve_texture)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_efb_depth_resolve_framebuffer =
|
m_efb_depth_resolve_framebuffer =
|
||||||
|
@ -246,10 +253,14 @@ AbstractTexture* FramebufferManager::ResolveEFBColorTexture(const MathUtil::Rect
|
||||||
return m_efb_resolve_color_texture.get();
|
return m_efb_resolve_color_texture.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractTexture* FramebufferManager::ResolveEFBDepthTexture(const MathUtil::Rectangle<int>& region)
|
AbstractTexture* FramebufferManager::ResolveEFBDepthTexture(const MathUtil::Rectangle<int>& region,
|
||||||
|
bool force_r32f)
|
||||||
{
|
{
|
||||||
if (!IsEFBMultisampled())
|
if (!IsEFBMultisampled() || !force_r32f ||
|
||||||
|
m_efb_depth_texture->GetFormat() == AbstractTextureFormat::R32F)
|
||||||
|
{
|
||||||
return m_efb_depth_texture.get();
|
return m_efb_depth_texture.get();
|
||||||
|
}
|
||||||
|
|
||||||
// It's not valid to resolve an out-of-range rectangle.
|
// It's not valid to resolve an out-of-range rectangle.
|
||||||
MathUtil::Rectangle<int> clamped_region = region;
|
MathUtil::Rectangle<int> clamped_region = region;
|
||||||
|
@ -896,7 +907,7 @@ void FramebufferManager::DoSaveState(PointerWrap& p)
|
||||||
// This won't be bit-exact when loading, which could cause interesting rendering side-effects for
|
// This won't be bit-exact when loading, which could cause interesting rendering side-effects for
|
||||||
// a frame. But whatever, MSAA doesn't exactly behave that well anyway.
|
// a frame. But whatever, MSAA doesn't exactly behave that well anyway.
|
||||||
AbstractTexture* color_texture = ResolveEFBColorTexture(m_efb_color_texture->GetRect());
|
AbstractTexture* color_texture = ResolveEFBColorTexture(m_efb_color_texture->GetRect());
|
||||||
AbstractTexture* depth_texture = ResolveEFBDepthTexture(m_efb_depth_texture->GetRect());
|
AbstractTexture* depth_texture = ResolveEFBDepthTexture(m_efb_depth_texture->GetRect(), true);
|
||||||
|
|
||||||
// We don't want to save these as rendertarget textures, just the data itself when deserializing.
|
// We don't want to save these as rendertarget textures, just the data itself when deserializing.
|
||||||
const TextureConfig color_texture_config(color_texture->GetWidth(), color_texture->GetHeight(),
|
const TextureConfig color_texture_config(color_texture->GetWidth(), color_texture->GetHeight(),
|
||||||
|
@ -904,39 +915,10 @@ 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 (AbstractTexture::IsCompatibleDepthAndColorFormats(m_efb_depth_texture->GetFormat(),
|
const TextureConfig depth_texture_config(depth_texture->GetWidth(), depth_texture->GetHeight(),
|
||||||
GetEFBDepthCopyFormat()))
|
depth_texture->GetLevels(), depth_texture->GetLayers(),
|
||||||
{
|
1, GetEFBDepthCopyFormat(), 0);
|
||||||
const TextureConfig depth_texture_config(depth_texture->GetWidth(), depth_texture->GetHeight(),
|
g_texture_cache->SerializeTexture(depth_texture, depth_texture_config, p);
|
||||||
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, 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);
|
|
||||||
if (temp_texture && temp_fb)
|
|
||||||
{
|
|
||||||
g_renderer->ScaleTexture(temp_fb.get(), temp_texture->GetRect(), depth_texture,
|
|
||||||
depth_texture->GetRect());
|
|
||||||
|
|
||||||
const TextureConfig depth_texture_config(
|
|
||||||
depth_texture->GetWidth(), depth_texture->GetHeight(), depth_texture->GetLevels(),
|
|
||||||
depth_texture->GetLayers(), 1, temp_texture->GetFormat(), 0);
|
|
||||||
g_texture_cache->SerializeTexture(depth_texture, depth_texture_config, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to create temp texture for depth saving");
|
|
||||||
g_texture_cache->SerializeTexture(color_texture, color_texture_config, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::DoLoadState(PointerWrap& p)
|
void FramebufferManager::DoLoadState(PointerWrap& p)
|
||||||
|
|
|
@ -74,7 +74,8 @@ public:
|
||||||
|
|
||||||
// Resolve color/depth textures to a non-msaa texture, and return it.
|
// Resolve color/depth textures to a non-msaa texture, and return it.
|
||||||
AbstractTexture* ResolveEFBColorTexture(const MathUtil::Rectangle<int>& region);
|
AbstractTexture* ResolveEFBColorTexture(const MathUtil::Rectangle<int>& region);
|
||||||
AbstractTexture* ResolveEFBDepthTexture(const MathUtil::Rectangle<int>& region);
|
AbstractTexture* ResolveEFBDepthTexture(const MathUtil::Rectangle<int>& region,
|
||||||
|
bool force_r32f = false);
|
||||||
|
|
||||||
// Reinterpret pixel format of EFB color texture.
|
// Reinterpret pixel format of EFB color texture.
|
||||||
// Assumes no render pass is currently in progress.
|
// Assumes no render pass is currently in progress.
|
||||||
|
|
Loading…
Reference in New Issue