GS: Fix depth texture dumping for HW

This commit is contained in:
Stenzek 2023-08-26 15:14:35 +10:00 committed by Connor McLaughlin
parent e3a1125e84
commit 728ca8aa9d
5 changed files with 17 additions and 159 deletions

View File

@ -26,6 +26,23 @@ GSTexture::GSTexture() = default;
bool GSTexture::Save(const std::string& fn)
{
// Depth textures need special treatment - we have a stencil component.
// Just re-use the existing conversion shader instead.
if (m_format == Format::DepthStencil)
{
GSTexture* temp = g_gs_device->CreateRenderTarget(GetWidth(), GetHeight(), Format::Color, false);
if (!temp)
{
Console.Error("Failed to allocate %dx%d texture for depth conversion", GetWidth(), GetHeight());
return false;
}
g_gs_device->StretchRect(this, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), temp, GSVector4(GetRect()), ShaderConvert::FLOAT32_TO_RGBA8, false);
const bool res = temp->Save(fn);
g_gs_device->Recycle(temp);
return res;
}
#ifdef PCSX2_DEVBUILD
GSPng::Format format = GSPng::RGB_A_PNG;
#else

View File

@ -92,103 +92,6 @@ void GSTexture11::Unmap()
pxFailRel("Should not be called.");
}
bool GSTexture11::Save(const std::string& fn)
{
GSDevice11::GetInstance()->CommitClear(this);
D3D11_TEXTURE2D_DESC desc = m_desc;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
wil::com_ptr_nothrow<ID3D11Texture2D> res;
HRESULT hr = GSDevice11::GetInstance()->GetD3DDevice()->CreateTexture2D(&desc, nullptr, res.put());
if (FAILED(hr))
{
return false;
}
GSDevice11::GetInstance()->GetD3DContext()->CopyResource(res.get(), m_texture.get());
if (m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
{
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
wil::com_ptr_nothrow<ID3D11Texture2D> dst;
hr = GSDevice11::GetInstance()->GetD3DDevice()->CreateTexture2D(&desc, nullptr, dst.put());
if (FAILED(hr))
{
return false;
}
D3D11_MAPPED_SUBRESOURCE sm, dm;
hr = GSDevice11::GetInstance()->GetD3DContext()->Map(res.get(), 0, D3D11_MAP_READ, 0, &sm);
if (FAILED(hr))
{
return false;
}
auto unmap_res = wil::scope_exit([res]{ // Capture by value to preserve the original pointer
GSDevice11::GetInstance()->GetD3DContext()->Unmap(res.get(), 0);
});
hr = GSDevice11::GetInstance()->GetD3DContext()->Map(dst.get(), 0, D3D11_MAP_WRITE, 0, &dm);
if (FAILED(hr))
{
return false;
}
auto unmap_dst = wil::scope_exit([dst]{ // Capture by value to preserve the original pointer
GSDevice11::GetInstance()->GetD3DContext()->Unmap(dst.get(), 0);
});
const u8* s = static_cast<const u8*>(sm.pData);
u8* d = static_cast<u8*>(dm.pData);
for (u32 y = 0; y < desc.Height; y++, s += sm.RowPitch, d += dm.RowPitch)
{
for (u32 x = 0; x < desc.Width; x++)
{
reinterpret_cast<u32*>(d)[x] = static_cast<u32>(ldexpf(reinterpret_cast<const float*>(s)[x * 2], 32));
}
}
res = std::move(dst);
}
res->GetDesc(&desc);
#ifdef PCSX2_DEVBUILD
GSPng::Format format = GSPng::RGB_A_PNG;
#else
GSPng::Format format = GSPng::RGB_PNG;
#endif
switch (desc.Format)
{
case DXGI_FORMAT_A8_UNORM:
format = GSPng::R8I_PNG;
break;
case DXGI_FORMAT_R8G8B8A8_UNORM:
break;
default:
fprintf(stderr, "DXGI_FORMAT %d not saved to image\n", desc.Format);
return false;
}
D3D11_MAPPED_SUBRESOURCE sm;
hr = GSDevice11::GetInstance()->GetD3DContext()->Map(res.get(), 0, D3D11_MAP_READ, 0, &sm);
if (FAILED(hr))
{
return false;
}
bool success = GSPng::Save(format, fn, static_cast<u8*>(sm.pData), desc.Width, desc.Height, sm.RowPitch, GSConfig.PNGCompressionLevel);
GSDevice11::GetInstance()->GetD3DContext()->Unmap(res.get(), 0);
return success;
}
void GSTexture11::GenerateMipmap()
{
GSDevice11::GetInstance()->GetD3DContext()->GenerateMips(operator ID3D11ShaderResourceView*());

View File

@ -43,7 +43,6 @@ public:
bool Update(const GSVector4i& r, const void* data, int pitch, int layer = 0) override;
bool Map(GSMap& m, const GSVector4i* r = NULL, int layer = 0) override;
void Unmap() override;
bool Save(const std::string& fn) override;
void GenerateMipmap() override;
void Swap(GSTexture* tex) override;
bool Equal(GSTexture11* tex);

View File

@ -20,7 +20,6 @@
#include "GS/Renderers/OpenGL/GLState.h"
#include "GS/GSExtra.h"
#include "GS/GSPerfMon.h"
#include "GS/GSPng.h"
#include "GS/GSGL.h"
#include "common/BitUtils.h"
#include "common/AlignedMalloc.h"
@ -329,65 +328,6 @@ void GSTextureOGL::GenerateMipmap()
glGenerateTextureMipmap(m_texture_id);
}
bool GSTextureOGL::Save(const std::string& fn)
{
GSDeviceOGL::GetInstance()->CommitClear(this, true);
// Collect the texture data
u32 pitch = 4 * m_size.x;
u32 buf_size = pitch * m_size.y * 2; // Note *2 for security (depth/stencil)
std::unique_ptr<u8[]> image(new u8[buf_size]);
#ifdef PCSX2_DEVBUILD
GSPng::Format fmt = GSPng::RGB_A_PNG;
#else
GSPng::Format fmt = GSPng::RGB_PNG;
#endif
if (IsDepthStencil())
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, GSDeviceOGL::GetInstance()->GetFBORead());
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_texture_id, 0);
glReadPixels(0, 0, m_size.x, m_size.y, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image.get());
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
fmt = GSPng::RGB_A_PNG;
}
else if (m_format == Format::PrimID)
{
// Note: 4.5 function used for accurate DATE
glGetTextureImage(m_texture_id, 0, GL_RED_INTEGER, GL_INT, buf_size, image.get());
fmt = GSPng::R32I_PNG;
}
else
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, GSDeviceOGL::GetInstance()->GetFBORead());
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
if (m_format == Format::Color)
{
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image.get());
}
else if (m_format == Format::UInt16)
{
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED_INTEGER, GL_UNSIGNED_SHORT, image.get());
fmt = GSPng::R16I_PNG;
}
else if (m_format == Format::UNorm8)
{
fmt = GSPng::R8I_PNG;
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED, GL_UNSIGNED_BYTE, image.get());
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
return GSPng::Save(fmt, fn, image.get(), m_size.x, m_size.y, pitch, GSConfig.PNGCompressionLevel);
}
void GSTextureOGL::Swap(GSTexture* tex)
{
GSTexture::Swap(tex);

View File

@ -52,7 +52,6 @@ public:
bool Map(GSMap& m, const GSVector4i* r = NULL, int layer = 0) final;
void Unmap() final;
void GenerateMipmap() final;
bool Save(const std::string& fn) final;
void Swap(GSTexture* tex) final;
bool IsIntegerFormat() const