mirror of https://github.com/PCSX2/pcsx2.git
GS: Fix depth texture dumping for HW
This commit is contained in:
parent
e3a1125e84
commit
728ca8aa9d
|
@ -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
|
||||
|
|
|
@ -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*());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue