GS: Remove separate GSTextureCaches

This commit is contained in:
TellowKrinkle 2021-11-13 17:34:04 -06:00 committed by tellowkrinkle
parent 8b086a3898
commit 8d6569be95
24 changed files with 202 additions and 456 deletions

View File

@ -650,7 +650,6 @@ set(pcsx2GSSources
GS/Renderers/OpenGL/GSDeviceOGL.cpp
GS/Renderers/OpenGL/GSRendererOGL.cpp
GS/Renderers/OpenGL/GSShaderOGL.cpp
GS/Renderers/OpenGL/GSTextureCacheOGL.cpp
GS/Renderers/OpenGL/GSTextureOGL.cpp
GS/Window/GSSetting.cpp
GS/Window/GSwxDialog.cpp
@ -721,7 +720,6 @@ set(pcsx2GSHeaders
GS/Renderers/OpenGL/GSDeviceOGL.h
GS/Renderers/OpenGL/GSRendererOGL.h
GS/Renderers/OpenGL/GSShaderOGL.h
GS/Renderers/OpenGL/GSTextureCacheOGL.h
GS/Renderers/OpenGL/GSTextureOGL.h
GS/Renderers/OpenGL/GSUniformBufferOGL.h
GS/Window/GSCaptureDlg.h
@ -796,7 +794,6 @@ if(WIN32)
GS/Renderers/DX11/GSDevice11.cpp
GS/Renderers/DX11/GSRendererDX11.cpp
GS/Renderers/DX11/GSTexture11.cpp
GS/Renderers/DX11/GSTextureCache11.cpp
GS/Renderers/DX11/GSTextureFX11.cpp
GS/Window/GSCaptureDlg.cpp
GS/Window/GSDialog.cpp
@ -806,7 +803,6 @@ if(WIN32)
GS/Renderers/DX11/GSDevice11.h
GS/Renderers/DX11/GSRendererDX11.h
GS/Renderers/DX11/GSTexture11.h
GS/Renderers/DX11/GSTextureCache11.h
)
else(WIN32)
list(APPEND pcsx2SPU2Sources

View File

@ -261,6 +261,23 @@ GSTexture::Format GSDevice::GetDefaultTextureFormat(GSTexture::Type type)
return GSTexture::Format::Color;
}
bool GSDevice::DownloadTextureConvert(GSTexture* src, const GSVector4& sRect, const GSVector2i& dSize, GSTexture::Format format, ShaderConvert ps_shader, GSTexture::GSMap& out_map)
{
ASSERT(src);
ASSERT(format == GSTexture::Format::Color || format == GSTexture::Format::UInt16 || format == GSTexture::Format::UInt32);
GSTexture* dst = CreateRenderTarget(dSize.x, dSize.y, format);
if (!dst)
return false;
GSVector4i dRect(0, 0, dSize.x, dSize.y);
StretchRect(src, sRect, dst, GSVector4(dRect), ps_shader);
bool ret = DownloadTexture(src, dRect, out_map);
Recycle(dst);
return ret;
}
void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
{
StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, linear);

View File

@ -228,7 +228,16 @@ public:
GSTexture* CreateOffscreen(int w, int h, GSTexture::Format format);
GSTexture::Format GetDefaultTextureFormat(GSTexture::Type type);
virtual GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, GSTexture::Format format, ShaderConvert ps_shader = ShaderConvert::COPY) { return NULL; }
/// Download the region `rect` of `src` into `out_map`
/// `out_map` will be valid a call to `DownloadTextureComplete`
virtual bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) { return false; }
/// Scale the region `sRect` of `src` to the size `dSize` using `ps_shader` and store the result in `out_map`
/// `out_map` will be valid a call to `DownloadTextureComplete`
virtual bool DownloadTextureConvert(GSTexture* src, const GSVector4& sRect, const GSVector2i& dSize, GSTexture::Format format, ShaderConvert ps_shader, GSTexture::GSMap& out_map);
/// Must be called to free resources after calling `DownloadTexture` or `DownloadTextureConvert`
virtual void DownloadTextureComplete() {}
virtual void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) {}
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) {}

View File

@ -512,18 +512,17 @@ void GSRenderer::VSync(int field)
{
GSVector2i size = m_capture.GetSize();
if (GSTexture* offscreen = m_dev->CopyOffscreen(current, GSVector4(0, 0, 1, 1), size.x, size.y, GSTexture::Format::Color))
bool res;
GSTexture::GSMap m;
if (size == current->GetSize())
res = m_dev->DownloadTexture(current, GSVector4i(0, 0, size.x, size.y), m);
else
res = m_dev->DownloadTextureConvert(current, GSVector4(0, 0, 1, 1), size, GSTexture::Format::Color, ShaderConvert::COPY, m);
if (res)
{
GSTexture::GSMap m;
if (offscreen->Map(m))
{
m_capture.DeliverFrame(m.bits, m.pitch, !m_dev->IsRBSwapped());
offscreen->Unmap();
}
m_dev->Recycle(offscreen);
m_capture.DeliverFrame(m.bits, m.pitch, !m_dev->IsRBSwapped());
m_dev->DownloadTextureComplete();
}
}
}

View File

@ -648,29 +648,24 @@ GSTexture* GSDevice11::FetchSurface(GSTexture::Type type, int w, int h, GSTextur
return __super::FetchSurface(type, w, h, format);
}
GSTexture* GSDevice11::CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, GSTexture::Format format, ShaderConvert ps_shader)
bool GSDevice11::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map)
{
GSTexture* dst = NULL;
ASSERT(src);
ASSERT(!m_download_tex);
m_download_tex.reset(static_cast<GSTexture11*>(CreateOffscreen(rect.width(), rect.height(), src->GetFormat())));
if (!m_download_tex)
return false;
m_ctx->CopyResource(*m_download_tex, *static_cast<GSTexture11*>(src));
return m_download_tex->Map(out_map);
}
ASSERT(format == GSTexture::Format::Color || format == GSTexture::Format::UInt16 || format == GSTexture::Format::UInt32);
if (GSTexture* rt = CreateRenderTarget(w, h, format))
void GSDevice11::DownloadTextureComplete()
{
if (m_download_tex)
{
GSVector4 dRect(0, 0, w, h);
StretchRect(src, sRect, rt, dRect, m_convert.ps[static_cast<int>(ps_shader)].get(), NULL);
dst = CreateOffscreen(w, h, format);
if (dst)
{
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
}
Recycle(rt);
m_download_tex->Unmap();
Recycle(m_download_tex.release());
}
return dst;
}
void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r)

View File

@ -513,6 +513,7 @@ private:
PSConstantBuffer m_ps_cb_cache;
std::unique_ptr<GSTexture> m_font;
std::unique_ptr<GSTexture11> m_download_tex;
protected:
struct
@ -542,7 +543,8 @@ public:
void ClearDepth(GSTexture* t) final;
void ClearStencil(GSTexture* t, u8 c) final;
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, GSTexture::Format format, ShaderConvert ps_shader = ShaderConvert::COPY) final;
bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) final;
void DownloadTextureComplete() final;
void CloneTexture(GSTexture* src, GSTexture** dest);

View File

@ -17,7 +17,6 @@
#include "GSRendererDX11.h"
GSRendererDX11::GSRendererDX11()
: GSRendererHW(new GSTextureCache11(this))
{
m_sw_blending = theApp.GetConfigI("accurate_blending_unit_d3d11");

View File

@ -15,8 +15,8 @@
#pragma once
#include "GSDevice11.h"
#include "GS/Renderers/HW/GSRendererHW.h"
#include "GSTextureCache11.h"
#include "GS/Renderers/HW/GSVertexHW.h"
class GSRendererDX11 final : public GSRendererHW

View File

@ -1,137 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "GSTextureCache11.h"
// GSTextureCache11
GSTextureCache11::GSTextureCache11(GSRenderer* r)
: GSTextureCache(r)
{
}
void GSTextureCache11::Read(Target* t, const GSVector4i& r)
{
if (!t->m_dirty.empty() || r.width() == 0 || r.height() == 0)
{
return;
}
const GIFRegTEX0& TEX0 = t->m_TEX0;
GSTexture::Format format;
ShaderConvert ps_shader;
switch (TEX0.PSM)
{
case PSM_PSMCT32:
case PSM_PSMCT24:
format = GSTexture::Format::Color;
ps_shader = ShaderConvert::COPY;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
format = GSTexture::Format::UInt16;
ps_shader = ShaderConvert::RGBA8_TO_16_BITS;
break;
case PSM_PSMZ32:
case PSM_PSMZ24:
format = GSTexture::Format::UInt32;
ps_shader = ShaderConvert::FLOAT32_TO_32_BITS;
break;
case PSM_PSMZ16:
case PSM_PSMZ16S:
format = GSTexture::Format::UInt16;
ps_shader = ShaderConvert::FLOAT32_TO_32_BITS;
break;
default:
return;
}
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, TEX0.TBP0);
int w = r.width();
int h = r.height();
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
if (GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, w, h, format, ps_shader))
{
GSTexture::GSMap m;
if (offscreen->Map(m))
{
// TODO: block level write
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
switch (TEX0.PSM)
{
case PSM_PSMCT32:
case PSM_PSMZ32:
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
break;
case PSM_PSMCT24:
case PSM_PSMZ24:
m_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r);
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
case PSM_PSMZ16:
case PSM_PSMZ16S:
m_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r);
break;
default:
ASSERT(0);
}
offscreen->Unmap();
}
m_renderer->m_dev->Recycle(offscreen);
}
}
void GSTextureCache11::Read(Source* t, const GSVector4i& r)
{
// FIXME: copy was copyied from openGL. It is unlikely to work.
const GIFRegTEX0& TEX0 = t->m_TEX0;
if (GSTexture* offscreen = m_renderer->m_dev->CreateOffscreen(r.width(), r.height(), GSTexture::Format::Color))
{
m_renderer->m_dev->CopyRect(t->m_texture, offscreen, r);
GSTexture::GSMap m;
GSVector4i r_offscreen(0, 0, r.width(), r.height());
if (offscreen->Map(m, &r_offscreen))
{
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
offscreen->Unmap();
}
// FIXME invalidate data
m_renderer->m_dev->Recycle(offscreen);
}
}

View File

@ -1,31 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "GS/Renderers/HW/GSTextureCache.h"
#include "GSDevice11.h"
class GSTextureCache11 : public GSTextureCache
{
protected:
int Get8bitFormat() { return DXGI_FORMAT_A8_UNORM; }
void Read(Target* t, const GSVector4i& r);
void Read(Source* t, const GSVector4i& r);
public:
GSTextureCache11(GSRenderer* r);
};

View File

@ -19,14 +19,14 @@
const float GSRendererHW::SSR_UV_TOLERANCE = 1e-3f;
GSRendererHW::GSRendererHW(GSTextureCache* tc)
GSRendererHW::GSRendererHW()
: m_width(default_rt_size.x)
, m_height(default_rt_size.y)
, m_custom_width(1024)
, m_custom_height(1024)
, m_reset(false)
, m_userhacks_ts_half_bottom(-1)
, m_tc(tc)
, m_tc(new GSTextureCache(this))
, m_src(nullptr)
, m_userhacks_tcoffset(false)
, m_userhacks_tcoffset_x(0)

View File

@ -165,7 +165,7 @@ protected:
void CustomResolutionScaling();
public:
GSRendererHW(GSTextureCache* tc);
GSRendererHW();
virtual ~GSRendererHW();
void SetGameCRC(u32 crc, int options);

View File

@ -1655,6 +1655,103 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int
return t;
}
void GSTextureCache::Read(Target* t, const GSVector4i& r)
{
if (!t->m_dirty.empty() || r.width() == 0 || r.height() == 0)
return;
const GIFRegTEX0& TEX0 = t->m_TEX0;
GSTexture::Format fmt;
ShaderConvert ps_shader;
switch (TEX0.PSM)
{
case PSM_PSMCT32:
case PSM_PSMCT24:
fmt = GSTexture::Format::Color;
ps_shader = ShaderConvert::COPY;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
fmt = GSTexture::Format::UInt16;
ps_shader = ShaderConvert::RGBA8_TO_16_BITS;
break;
case PSM_PSMZ32:
case PSM_PSMZ24:
fmt = GSTexture::Format::UInt32;
ps_shader = ShaderConvert::FLOAT32_TO_32_BITS;
break;
case PSM_PSMZ16:
case PSM_PSMZ16S:
fmt = GSTexture::Format::UInt16;
ps_shader = ShaderConvert::FLOAT32_TO_32_BITS;
break;
default:
return;
}
// Yes lots of logging, but I'm not confident with this code
GL_PUSH("Texture Cache Read. Format(0x%x)", TEX0.PSM);
GL_PERF("TC: Read Back Target: %d (0x%x)[fmt: 0x%x]. Size %dx%d",
t->m_texture->GetID(), TEX0.TBP0, TEX0.PSM, r.width(), r.height());
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
bool res;
GSTexture::GSMap m;
if (t->m_texture->GetScale() == GSVector2(1, 1) && ps_shader == ShaderConvert::COPY)
res = m_renderer->m_dev->DownloadTexture(t->m_texture, r, m);
else
res = m_renderer->m_dev->DownloadTextureConvert(t->m_texture, src, GSVector2i(r.width(), r.height()), fmt, ps_shader, m);
if (res)
{
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
switch (TEX0.PSM)
{
case PSM_PSMCT32:
case PSM_PSMZ32:
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
break;
case PSM_PSMCT24:
case PSM_PSMZ24:
m_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r);
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
case PSM_PSMZ16:
case PSM_PSMZ16S:
m_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r);
break;
default:
ASSERT(0);
}
m_renderer->m_dev->DownloadTextureComplete();
}
}
void GSTextureCache::Read(Source* t, const GSVector4i& r)
{
const GIFRegTEX0& TEX0 = t->m_TEX0;
GSTexture::GSMap m;
if (m_renderer->m_dev->DownloadTexture(t->m_texture, r, m))
{
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
m_renderer->m_dev->DownloadTextureComplete();
}
}
void GSTextureCache::PrintMemoryUsage()
{
#ifdef ENABLE_OGL_DEBUG

View File

@ -226,19 +226,17 @@ protected:
u8 m_texture_inside_rt_cache_size = 255;
std::vector<TexInsideRtCacheEntry> m_texture_inside_rt_cache;
virtual Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL, bool half_right = false, int x_offset = 0, int y_offset = 0);
virtual Target* CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type);
virtual int Get8bitFormat() = 0;
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL, bool half_right = false, int x_offset = 0, int y_offset = 0);
Target* CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type);
// TODO: virtual void Write(Source* s, const GSVector4i& r) = 0;
// TODO: virtual void Write(Target* t, const GSVector4i& r) = 0;
public:
GSTextureCache(GSRenderer* r);
virtual ~GSTextureCache();
virtual void Read(Target* t, const GSVector4i& r) = 0;
virtual void Read(Source* t, const GSVector4i& r) = 0;
~GSTextureCache();
void Read(Target* t, const GSVector4i& r);
void Read(Source* t, const GSVector4i& r);
void RemoveAll();
void RemovePartial();

View File

@ -1271,23 +1271,14 @@ void GSDeviceOGL::SelfShaderTest()
SelfShaderTestPrint(test, nb_shader);
}
// blit a texture into an offscreen buffer
GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, GSTexture::Format format, ShaderConvert ps_shader)
bool GSDeviceOGL::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map)
{
ASSERT(src);
ASSERT(format == GSTexture::Format::Color || format == GSTexture::Format::UInt16 || format == GSTexture::Format::UInt32);
GSTexture* dst = CreateOffscreen(w, h, format);
GSTextureOGL* srcgl = static_cast<GSTextureOGL*>(src);
const GSVector4 dRect(0, 0, w, h);
// StretchRect will read an old target. However, the memory cache might contains
// invalid data (for example due to SW blending).
glTextureBarrier();
StretchRect(src, sRect, dst, dRect, m_convert.ps[(int)ps_shader]);
return dst;
out_map = srcgl->Read(rect, m_download_buffer);
return true;
}
// Copy a sub part of texture (same as below but force a conversion)

View File

@ -22,6 +22,7 @@
#include "GSUniformBufferOGL.h"
#include "GSShaderOGL.h"
#include "GLState.h"
#include "GS/GS.h"
#ifdef ENABLE_OGL_DEBUG_MEM_BW
extern u64 g_real_texture_upload_byte;
@ -558,6 +559,7 @@ private:
MiscConstantBuffer m_misc_cb_cache;
std::unique_ptr<GSTexture> m_font;
AlignedBuffer<u8, 32> m_download_buffer;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final;
GSTexture* FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final;
@ -605,7 +607,7 @@ public:
void InitPrimDateTexture(GSTexture* rt, const GSVector4i& area);
void RecycleDateTexture();
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, GSTexture::Format format, ShaderConvert ps_shader = ShaderConvert::COPY) final;
bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) final;
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) final;

View File

@ -18,7 +18,6 @@
GSRendererOGL::GSRendererOGL()
: GSRendererHW(new GSTextureCacheOGL(this))
{
m_sw_blending = theApp.GetConfigI("accurate_blending_unit");
if (theApp.GetConfigB("UserHacks"))

View File

@ -15,8 +15,8 @@
#pragma once
#include "GSDeviceOGL.h"
#include "GS/Renderers/HW/GSRendererHW.h"
#include "GSTextureCacheOGL.h"
#include "GS/Renderers/HW/GSVertexHW.h"
class GSRendererOGL final : public GSRendererHW

View File

@ -1,138 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "GSTextureCacheOGL.h"
GSTextureCacheOGL::GSTextureCacheOGL(GSRenderer* r)
: GSTextureCache(r)
{
}
void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
{
if (!t->m_dirty.empty() || r.width() == 0 || r.height() == 0)
return;
const GIFRegTEX0& TEX0 = t->m_TEX0;
GSTexture::Format fmt;
ShaderConvert ps_shader;
switch (TEX0.PSM)
{
case PSM_PSMCT32:
case PSM_PSMCT24:
fmt = GSTexture::Format::Color;
ps_shader = ShaderConvert::COPY;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
fmt = GSTexture::Format::UInt16;
ps_shader = ShaderConvert::RGBA8_TO_16_BITS;
break;
case PSM_PSMZ32:
case PSM_PSMZ24:
fmt = GSTexture::Format::UInt32;
ps_shader = ShaderConvert::FLOAT32_TO_32_BITS;
break;
case PSM_PSMZ16:
case PSM_PSMZ16S:
fmt = GSTexture::Format::UInt16;
ps_shader = ShaderConvert::FLOAT32_TO_32_BITS;
break;
default:
return;
}
// Yes lots of logging, but I'm not confident with this code
GL_PUSH("Texture Cache Read. Format(0x%x)", TEX0.PSM);
GL_PERF("TC: Read Back Target: %d (0x%x)[fmt: 0x%x]. Size %dx%d",
t->m_texture->GetID(), TEX0.TBP0, TEX0.PSM, r.width(), r.height());
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
if (GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, r.width(), r.height(), fmt, ps_shader))
{
GSTexture::GSMap m;
GSVector4i r_offscreen(0, 0, r.width(), r.height());
if (offscreen->Map(m, &r_offscreen))
{
// TODO: block level write
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
switch (TEX0.PSM)
{
case PSM_PSMCT32:
case PSM_PSMZ32:
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
break;
case PSM_PSMCT24:
case PSM_PSMZ24:
m_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r);
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
case PSM_PSMZ16:
case PSM_PSMZ16S:
m_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r);
break;
default:
ASSERT(0);
}
offscreen->Unmap();
}
// FIXME invalidate data
m_renderer->m_dev->Recycle(offscreen);
}
}
void GSTextureCacheOGL::Read(Source* t, const GSVector4i& r)
{
const GIFRegTEX0& TEX0 = t->m_TEX0;
// FIXME Create a get function to avoid the useless copy
// Note: With openGL 4.5 you can use glGetTextureSubImage
if (GSTexture* offscreen = m_renderer->m_dev->CreateOffscreen(r.width(), r.height(), GSTexture::Format::Color))
{
m_renderer->m_dev->CopyRect(t->m_texture, offscreen, r);
GSTexture::GSMap m;
GSVector4i r_offscreen(0, 0, r.width(), r.height());
if (offscreen->Map(m, &r_offscreen))
{
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
offscreen->Unmap();
}
// FIXME invalidate data
m_renderer->m_dev->Recycle(offscreen);
}
}

View File

@ -1,31 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "GS/Renderers/HW/GSTextureCache.h"
#include "GSDeviceOGL.h"
class GSTextureCacheOGL final : public GSTextureCache
{
protected:
int Get8bitFormat() { return GL_R8; }
void Read(Target* t, const GSVector4i& r);
void Read(Source* t, const GSVector4i& r);
public:
GSTextureCacheOGL(GSRenderer* r);
};

View File

@ -162,7 +162,7 @@ namespace PboPool
} // namespace PboPool
GSTextureOGL::GSTextureOGL(Type type, int w, int h, Format format, GLuint fbo_read, bool mipmap)
: m_clean(false), m_generate_mipmap(true), m_local_buffer(nullptr), m_r_x(0), m_r_y(0), m_r_w(0), m_r_h(0), m_layer(0)
: m_clean(false), m_generate_mipmap(true), m_r_x(0), m_r_y(0), m_r_w(0), m_r_h(0), m_layer(0)
{
// OpenGL didn't like dimensions of size 0
m_size.x = std::max(1, w);
@ -248,10 +248,6 @@ GSTextureOGL::GSTextureOGL(Type type, int w, int h, Format format, GLuint fbo_re
{
case Type::Backbuffer:
return; // backbuffer isn't a real texture
case Type::Offscreen:
// Offscreen is only used to read color. So it only requires 4B by pixel
m_local_buffer = (u8*)_aligned_malloc(m_size.x * m_size.y * 4, 32);
break;
case Type::Texture:
// Only 32 bits input texture will be supported for mipmap
m_max_layer = mipmap && m_format == Format::Color ? (int)log2(std::max(w, h)) : 1;
@ -351,9 +347,6 @@ GSTextureOGL::~GSTextureOGL()
glDeleteTextures(1, &m_texture_id);
GLState::available_vram += m_mem_usage;
if (m_local_buffer)
_aligned_free(m_local_buffer);
}
void GSTextureOGL::Clear(const void* data)
@ -450,36 +443,7 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* _r, int layer)
u32 row_byte = r.width() << m_int_shift;
m.pitch = row_byte;
if (m_type == Type::Offscreen)
{
// The fastest way will be to use a PBO to read the data asynchronously. Unfortunately GSdx
// architecture is waiting the data right now.
#ifdef GL_EXT_TEX_SUB_IMAGE
// Maybe it is as good as the code below. I don't know
// With openGL 4.5 you can use glGetTextureSubImage
glGetTextureSubImage(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, 0, r.width(), r.height(), 1, m_int_format, m_int_type, m_size.x * m_size.y * 4, m_local_buffer);
#else
// Bind the texture to the read framebuffer to avoid any disturbance
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
// In case a target is 16 bits (GT4)
glPixelStorei(GL_PACK_ALIGNMENT, 1u << m_int_shift);
glReadPixels(r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, m_local_buffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
#endif
m.bits = m_local_buffer;
return true;
}
else if (m_type == Type::Texture || m_type == Type::RenderTarget)
if (m_type == Type::Texture || m_type == Type::RenderTarget)
{
GL_PUSH_("Upload Texture %d", m_texture_id); // POP is in Unmap
@ -573,6 +537,36 @@ void GSTextureOGL::CommitPages(const GSVector2i& region, bool commit)
GLState::available_vram -= m_mem_usage;
}
GSTexture::GSMap GSTextureOGL::Read(const GSVector4i& r, AlignedBuffer<u8, 32>& buffer)
{
GSMap m;
m.pitch = r.width() << m_int_shift;
buffer.MakeRoomFor(m.pitch * r.height());
m.bits = buffer.GetPtr();
// The fastest way will be to use a PBO to read the data asynchronously. Unfortunately GSdx
// architecture is waiting the data right now.
#if 0
// Maybe it is as good as the code below. I don't know
// With openGL 4.5 you can use glGetTextureSubImage
glGetTextureSubImage(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, 0, r.width(), r.height(), 1, m_int_format, m_int_type, m_size.x * m_size.y * 4, m.bits);
#else
// Bind the texture to the read framebuffer to avoid any disturbance
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
// In case a target is 16 bits (GT4)
glPixelStorei(GL_PACK_ALIGNMENT, 1u << m_int_shift);
glReadPixels(r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, m.bits);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
#endif
return m;
}
bool GSTextureOGL::Save(const std::string& fn)
{
// Collect the texture data

View File

@ -17,6 +17,7 @@
#include "GS/Renderers/Common/GSTexture.h"
#include "GS/GSGL.h"
#include "common/AlignedMalloc.h"
namespace PboPool
{
@ -41,7 +42,6 @@ private:
bool m_clean;
bool m_generate_mipmap;
u8* m_local_buffer;
// Avoid alignment constrain
//GSVector4i m_r;
int m_r_x;
@ -69,6 +69,7 @@ public:
void GenerateMipmap() final;
bool Save(const std::string& fn) final;
GSMap Read(const GSVector4i& r, AlignedBuffer<u8, 32>& buffer);
bool IsBackbuffer() { return (m_type == Type::Backbuffer); }
bool IsDss() { return (m_type == Type::DepthStencil || m_type == Type::SparseDepthStencil); }

View File

@ -499,8 +499,6 @@
<ClCompile Include="GS\Renderers\DX11\GSTexture11.cpp" />
<ClCompile Include="GS\Renderers\OpenGL\GSTextureOGL.cpp" />
<ClCompile Include="GS\Renderers\HW\GSTextureCache.cpp" />
<ClCompile Include="GS\Renderers\DX11\GSTextureCache11.cpp" />
<ClCompile Include="GS\Renderers\OpenGL\GSTextureCacheOGL.cpp" />
<ClCompile Include="GS\Renderers\SW\GSTextureCacheSW.cpp" />
<ClCompile Include="GS\Renderers\DX11\GSTextureFX11.cpp" />
<ClCompile Include="GS\Renderers\Null\GSTextureNull.cpp" />
@ -864,8 +862,6 @@
<ClInclude Include="GS\Renderers\DX11\GSTexture11.h" />
<ClInclude Include="GS\Renderers\OpenGL\GSTextureOGL.h" />
<ClInclude Include="GS\Renderers\HW\GSTextureCache.h" />
<ClInclude Include="GS\Renderers\DX11\GSTextureCache11.h" />
<ClInclude Include="GS\Renderers\OpenGL\GSTextureCacheOGL.h" />
<ClInclude Include="GS\Renderers\SW\GSTextureCacheSW.h" />
<ClInclude Include="GS\Renderers\Null\GSTextureNull.h" />
<ClInclude Include="GS\Renderers\SW\GSTextureSW.h" />

View File

@ -1493,9 +1493,6 @@
<ClCompile Include="GS\Renderers\DX11\GSTexture11.cpp">
<Filter>System\Ps2\GS\Renderers\Direct3D</Filter>
</ClCompile>
<ClCompile Include="GS\Renderers\DX11\GSTextureCache11.cpp">
<Filter>System\Ps2\GS\Renderers\Direct3D</Filter>
</ClCompile>
<ClCompile Include="GS\Renderers\DX11\GSTextureFX11.cpp">
<Filter>System\Ps2\GS\Renderers\Direct3D</Filter>
</ClCompile>
@ -1511,9 +1508,6 @@
<ClCompile Include="GS\Renderers\OpenGL\GSShaderOGL.cpp">
<Filter>System\Ps2\GS\Renderers\OpenGL</Filter>
</ClCompile>
<ClCompile Include="GS\Renderers\OpenGL\GSTextureCacheOGL.cpp">
<Filter>System\Ps2\GS\Renderers\OpenGL</Filter>
</ClCompile>
<ClCompile Include="GS\Renderers\OpenGL\GSTextureOGL.cpp">
<Filter>System\Ps2\GS\Renderers\OpenGL</Filter>
</ClCompile>
@ -2593,9 +2587,6 @@
<ClInclude Include="GS\Renderers\DX11\GSTexture11.h">
<Filter>System\Ps2\GS\Renderers\Direct3D</Filter>
</ClInclude>
<ClInclude Include="GS\Renderers\DX11\GSTextureCache11.h">
<Filter>System\Ps2\GS\Renderers\Direct3D</Filter>
</ClInclude>
<ClInclude Include="GS\Renderers\OpenGL\GLLoader.h">
<Filter>System\Ps2\GS\Renderers\OpenGL</Filter>
</ClInclude>
@ -2608,9 +2599,6 @@
<ClInclude Include="GS\Renderers\OpenGL\GSShaderOGL.h">
<Filter>System\Ps2\GS\Renderers\OpenGL</Filter>
</ClInclude>
<ClInclude Include="GS\Renderers\OpenGL\GSTextureCacheOGL.h">
<Filter>System\Ps2\GS\Renderers\OpenGL</Filter>
</ClInclude>
<ClInclude Include="GS\Renderers\OpenGL\GSTextureOGL.h">
<Filter>System\Ps2\GS\Renderers\OpenGL</Filter>
</ClInclude>