GS: Allocate mipmaps for Basic+ and only on non-copy textures

This commit is contained in:
Connor McLaughlin 2022-01-01 19:56:29 +10:00 committed by refractionpcsx2
parent 220c7c271b
commit 0ce21c91ef
17 changed files with 60 additions and 70 deletions

View File

@ -39,7 +39,7 @@ GSState::GSState()
// m_nativeres seems to be a hack. Unfortunately it impacts draw call number which make debug painful in the replayer. // m_nativeres seems to be a hack. Unfortunately it impacts draw call number which make debug painful in the replayer.
// Let's keep it disabled to ease debug. // Let's keep it disabled to ease debug.
m_nativeres = theApp.GetConfigI("upscale_multiplier") == 1; m_nativeres = theApp.GetConfigI("upscale_multiplier") == 1;
m_mipmap = theApp.GetConfigI("mipmap"); m_mipmap = theApp.GetConfigB("mipmap");
m_NTSC_Saturation = theApp.GetConfigB("NTSC_Saturation"); m_NTSC_Saturation = theApp.GetConfigB("NTSC_Saturation");
if (theApp.GetConfigB("UserHacks")) if (theApp.GetConfigB("UserHacks"))
{ {

View File

@ -219,7 +219,7 @@ public:
int m_frameskip; int m_frameskip;
bool m_NTSC_Saturation; bool m_NTSC_Saturation;
bool m_nativeres; bool m_nativeres;
int m_mipmap; bool m_mipmap;
static int s_n; static int s_n;
bool s_dump; bool s_dump;

View File

@ -104,7 +104,7 @@ void GSDevice::RestoreAPIState()
{ {
} }
GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format, bool clear, bool prefer_reuse) GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format, bool clear, bool prefer_reuse)
{ {
const GSVector2i size(w, h); const GSVector2i size(w, h);
const bool prefer_new_texture = (m_features.prefer_new_textures && type == GSTexture::Type::Texture && !prefer_reuse); const bool prefer_new_texture = (m_features.prefer_new_textures && type == GSTexture::Type::Texture && !prefer_reuse);
@ -118,7 +118,7 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture:
assert(t); assert(t);
if (t->GetType() == type && t->GetFormat() == format && t->GetSize() == size) if (t->GetType() == type && t->GetFormat() == format && t->GetSize() == size && t->IsMipmap() == mipmap)
{ {
if (!prefer_new_texture) if (!prefer_new_texture)
{ {
@ -143,7 +143,7 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture:
} }
else else
{ {
t = CreateSurface(type, w, h, format); t = CreateSurface(type, w, h, mipmap, format);
if (!t) if (!t)
throw std::bad_alloc(); throw std::bad_alloc();
} }
@ -243,32 +243,32 @@ void GSDevice::PurgePool()
GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format, bool clear) GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format, bool clear)
{ {
return FetchSurface(HasColorSparse() ? GSTexture::Type::SparseRenderTarget : GSTexture::Type::RenderTarget, w, h, format, clear, true); return FetchSurface(HasColorSparse() ? GSTexture::Type::SparseRenderTarget : GSTexture::Type::RenderTarget, w, h, false, format, clear, true);
} }
GSTexture* GSDevice::CreateSparseDepthStencil(int w, int h, GSTexture::Format format, bool clear) GSTexture* GSDevice::CreateSparseDepthStencil(int w, int h, GSTexture::Format format, bool clear)
{ {
return FetchSurface(HasDepthSparse() ? GSTexture::Type::SparseDepthStencil : GSTexture::Type::DepthStencil, w, h, format, clear, true); return FetchSurface(HasDepthSparse() ? GSTexture::Type::SparseDepthStencil : GSTexture::Type::DepthStencil, w, h, false, format, clear, true);
} }
GSTexture* GSDevice::CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear) GSTexture* GSDevice::CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear)
{ {
return FetchSurface(GSTexture::Type::RenderTarget, w, h, format, clear, true); return FetchSurface(GSTexture::Type::RenderTarget, w, h, false, format, clear, true);
} }
GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format, bool clear) GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format, bool clear)
{ {
return FetchSurface(GSTexture::Type::DepthStencil, w, h, format, clear, true); return FetchSurface(GSTexture::Type::DepthStencil, w, h, false, format, clear, true);
} }
GSTexture* GSDevice::CreateTexture(int w, int h, GSTexture::Format format, bool prefer_reuse) GSTexture* GSDevice::CreateTexture(int w, int h, bool mipmap, GSTexture::Format format, bool prefer_reuse /* = false */)
{ {
return FetchSurface(GSTexture::Type::Texture, w, h, format, false, prefer_reuse); return FetchSurface(GSTexture::Type::Texture, w, h, mipmap, format, false, prefer_reuse);
} }
GSTexture* GSDevice::CreateOffscreen(int w, int h, GSTexture::Format format) GSTexture* GSDevice::CreateOffscreen(int w, int h, GSTexture::Format format)
{ {
return FetchSurface(GSTexture::Type::Offscreen, w, h, format, false, true); return FetchSurface(GSTexture::Type::Offscreen, w, h, false, format, false, true);
} }
GSTexture::Format GSDevice::GetDefaultTextureFormat(GSTexture::Type type) GSTexture::Format GSDevice::GetDefaultTextureFormat(GSTexture::Type type)
@ -428,10 +428,11 @@ bool GSDevice::ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h,
if (t2 == NULL || t2->GetWidth() != w || t2->GetHeight() != h) if (t2 == NULL || t2->GetWidth() != w || t2->GetHeight() != h)
{ {
GSTexture::Format fmt = t2 ? t2->GetFormat() : GetDefaultTextureFormat(type); const GSTexture::Format fmt = t2 ? t2->GetFormat() : GetDefaultTextureFormat(type);
const bool mipmap = t2 ? t2->IsMipmap() : false;
delete t2; delete t2;
t2 = FetchSurface(type, w, h, fmt, clear, prefer_reuse); t2 = FetchSurface(type, w, h, mipmap, fmt, clear, prefer_reuse);
*t = t2; *t = t2;
} }

View File

@ -553,8 +553,8 @@ protected:
bool m_rbswapped; bool m_rbswapped;
FeatureSupport m_features; FeatureSupport m_features;
virtual GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) = 0; virtual GSTexture* CreateSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format) = 0;
virtual GSTexture* FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format, bool clear, bool prefer_reuse); GSTexture* FetchSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format, bool clear, bool prefer_reuse);
virtual void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) = 0; virtual void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) = 0;
virtual void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset) = 0; virtual void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset) = 0;
@ -614,7 +614,7 @@ public:
GSTexture* CreateSparseDepthStencil(int w, int h, GSTexture::Format format, bool clear = true); GSTexture* CreateSparseDepthStencil(int w, int h, GSTexture::Format format, bool clear = true);
GSTexture* CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear = true); GSTexture* CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear = true);
GSTexture* CreateDepthStencil(int w, int h, GSTexture::Format format, bool clear = true); GSTexture* CreateDepthStencil(int w, int h, GSTexture::Format format, bool clear = true);
GSTexture* CreateTexture(int w, int h, GSTexture::Format format, bool prefer_reuse = false); GSTexture* CreateTexture(int w, int h, bool mipmap, GSTexture::Format format, bool prefer_reuse = false);
GSTexture* CreateOffscreen(int w, int h, GSTexture::Format format); GSTexture* CreateOffscreen(int w, int h, GSTexture::Format format);
GSTexture::Format GetDefaultTextureFormat(GSTexture::Type type); GSTexture::Format GetDefaultTextureFormat(GSTexture::Type type);

View File

@ -25,8 +25,6 @@
#include <X11/keysym.h> #include <X11/keysym.h>
#endif #endif
const unsigned int s_mipmap_nb = 3;
GSRenderer::GSRenderer() GSRenderer::GSRenderer()
: m_shift_key(false) : m_shift_key(false)
, m_control_key(false) , m_control_key(false)
@ -580,11 +578,6 @@ void GSRenderer::KeyEvent(const HostKeyEvent& e)
theApp.SetConfig("aa1", GSConfig.AA1); theApp.SetConfig("aa1", GSConfig.AA1);
printf("GS: (Software) Edge anti-aliasing is now %s.\n", GSConfig.AA1 ? "enabled" : "disabled"); printf("GS: (Software) Edge anti-aliasing is now %s.\n", GSConfig.AA1 ? "enabled" : "disabled");
return; return;
case VK_INSERT:
m_mipmap = (m_mipmap + s_mipmap_nb + step) % s_mipmap_nb;
theApp.SetConfig("mipmap_hw", m_mipmap);
printf("GS: Mipmapping is now %s.\n", theApp.m_gs_hack.at(m_mipmap).name.c_str());
return;
case VK_NEXT: // As requested by Prafull, to be removed later case VK_NEXT: // As requested by Prafull, to be removed later
char dither_msg[3][16] = {"disabled", "auto", "auto unscaled"}; char dither_msg[3][16] = {"disabled", "auto", "auto unscaled"};
GSConfig.Dithering = (GSConfig.Dithering + 1) % 3; GSConfig.Dithering = (GSConfig.Dithering + 1) % 3;

View File

@ -95,6 +95,7 @@ public:
int GetHeight() const { return m_size.y; } int GetHeight() const { return m_size.y; }
GSVector2i GetSize() const { return m_size; } GSVector2i GetSize() const { return m_size; }
int GetMipmapLevels() const { return m_mipmap_levels; } int GetMipmapLevels() const { return m_mipmap_levels; }
bool IsMipmap() const { return m_mipmap_levels > 1; }
Type GetType() const { return m_type; } Type GetType() const { return m_type; }
Format GetFormat() const { return m_format; } Format GetFormat() const { return m_format; }

View File

@ -34,7 +34,6 @@ GSDevice11::GSDevice11()
m_state.topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; m_state.topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
m_state.bf = -1; m_state.bf = -1;
m_mipmap = theApp.GetConfigI("mipmap");
m_upscale_multiplier = std::max(0, theApp.GetConfigI("upscale_multiplier")); m_upscale_multiplier = std::max(0, theApp.GetConfigI("upscale_multiplier"));
m_features.geometry_shader = true; m_features.geometry_shader = true;
@ -482,7 +481,7 @@ void GSDevice11::ClearStencil(GSTexture* t, u8 c)
m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_STENCIL, 0, c); m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_STENCIL, 0, c);
} }
GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format)
{ {
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
@ -507,16 +506,12 @@ GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTextu
desc.Width = std::max(1, std::min(w, m_d3d_texsize)); desc.Width = std::max(1, std::min(w, m_d3d_texsize));
desc.Height = std::max(1, std::min(h, m_d3d_texsize)); desc.Height = std::max(1, std::min(h, m_d3d_texsize));
desc.Format = dxformat; desc.Format = dxformat;
desc.MipLevels = 1; desc.MipLevels = mipmap ? (int)log2(std::max(w, h)) : 1;
desc.ArraySize = 1; desc.ArraySize = 1;
desc.SampleDesc.Count = 1; desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0; desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT; desc.Usage = D3D11_USAGE_DEFAULT;
// mipmap = m_mipmap > 1 || m_filter != TriFiltering::None;
const bool mipmap = m_mipmap > 1;
const int layers = mipmap && format == GSTexture::Format::Color ? (int)log2(std::max(w, h)) : 1;
switch (type) switch (type)
{ {
case GSTexture::Type::RenderTarget: case GSTexture::Type::RenderTarget:
@ -527,7 +522,6 @@ GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTextu
break; break;
case GSTexture::Type::Texture: case GSTexture::Type::Texture:
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.MipLevels = layers;
break; break;
case GSTexture::Type::Offscreen: case GSTexture::Type::Offscreen:
desc.Usage = D3D11_USAGE_STAGING; desc.Usage = D3D11_USAGE_STAGING;

View File

@ -109,10 +109,9 @@ public:
private: private:
float m_hack_topleft_offset; float m_hack_topleft_offset;
int m_upscale_multiplier; int m_upscale_multiplier;
int m_mipmap;
int m_d3d_texsize; int m_d3d_texsize;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final; GSTexture* CreateSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format) final;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) final; void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final; void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;

View File

@ -26,6 +26,7 @@ GSRendererHW::GSRendererHW()
, m_userhacks_ts_half_bottom(-1) , m_userhacks_ts_half_bottom(-1)
, m_tc(new GSTextureCache(this)) , m_tc(new GSTextureCache(this))
, m_src(nullptr) , m_src(nullptr)
, m_hw_mipmap(GSConfig.HWMipmap)
, m_userhacks_tcoffset(false) , m_userhacks_tcoffset(false)
, m_userhacks_tcoffset_x(0) , m_userhacks_tcoffset_x(0)
, m_userhacks_tcoffset_y(0) , m_userhacks_tcoffset_y(0)
@ -33,7 +34,7 @@ GSRendererHW::GSRendererHW()
, m_reset(false) , m_reset(false)
, m_lod(GSVector2i(0, 0)) , m_lod(GSVector2i(0, 0))
{ {
m_mipmap = theApp.GetConfigI("mipmap_hw"); m_mipmap = (m_hw_mipmap >= HWMipmapLevel::Basic);
m_upscale_multiplier = std::max(0, theApp.GetConfigI("upscale_multiplier")); m_upscale_multiplier = std::max(0, theApp.GetConfigI("upscale_multiplier"));
m_conservative_framebuffer = theApp.GetConfigB("conservative_framebuffer"); m_conservative_framebuffer = theApp.GetConfigB("conservative_framebuffer");
@ -198,7 +199,8 @@ void GSRendererHW::SetGameCRC(u32 crc, int options)
m_hacks.SetGameCRC(m_game); m_hacks.SetGameCRC(m_game);
// Code for Automatic Mipmapping. Relies on game CRCs. // Code for Automatic Mipmapping. Relies on game CRCs.
if (theApp.GetConfigT<HWMipmapLevel>("mipmap_hw") == HWMipmapLevel::Automatic) m_mipmap = (GSConfig.HWMipmap >= HWMipmapLevel::Basic);
if (GSConfig.HWMipmap == HWMipmapLevel::Automatic)
{ {
switch (CRC::Lookup(crc).title) switch (CRC::Lookup(crc).title)
{ {
@ -242,10 +244,12 @@ void GSRendererHW::SetGameCRC(u32 crc, int options)
case CRC::TombRaiderAnniversary: case CRC::TombRaiderAnniversary:
case CRC::TribesAerialAssault: case CRC::TribesAerialAssault:
case CRC::Whiplash: case CRC::Whiplash:
m_mipmap = static_cast<int>(HWMipmapLevel::Basic); m_hw_mipmap = HWMipmapLevel::Basic;
m_mipmap = true;
break; break;
default: default:
m_mipmap = static_cast<int>(HWMipmapLevel::Off); m_hw_mipmap = HWMipmapLevel::Off;
m_mipmap = false;
break; break;
} }
} }
@ -1398,10 +1402,12 @@ void GSRendererHW::Draw()
GetTextureMinMax(r, TEX0, MIP_CLAMP, m_vt.IsLinear()); GetTextureMinMax(r, TEX0, MIP_CLAMP, m_vt.IsLinear());
m_src = tex_psm.depth ? m_tc->LookupDepthSource(TEX0, env.TEXA, r) : m_tc->LookupSource(TEX0, env.TEXA, r); m_src = tex_psm.depth ? m_tc->LookupDepthSource(TEX0, env.TEXA, r) :
m_tc->LookupSource(TEX0, env.TEXA, r, m_hw_mipmap >= HWMipmapLevel::Basic ||
GSConfig.UserHacks_TriFilter == TriFiltering::Forced);
// Round 2 // Round 2
if (IsMipMapActive() && m_mipmap == 2 && !tex_psm.depth) if (IsMipMapActive() && m_hw_mipmap == HWMipmapLevel::Full && !tex_psm.depth)
{ {
// Upload remaining texture layers // Upload remaining texture layers
const GSVector4 tmin = m_vt.m_min.t; const GSVector4 tmin = m_vt.m_min.t;
@ -2078,7 +2084,7 @@ bool GSRendererHW::OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source
g_gs_device->Recycle(t->m_texture); g_gs_device->Recycle(t->m_texture);
t->m_texture = g_gs_device->CreateTexture(512, 512, GSTexture::Format::Color); t->m_texture = g_gs_device->CreateTexture(512, 512, false, GSTexture::Format::Color);
t->m_texture->Update(GSVector4i(0, 0, 448, lines), video, 448 * 4); t->m_texture->Update(GSVector4i(0, 0, 448, lines), video, 448 * 4);

View File

@ -146,6 +146,7 @@ protected:
GSTextureCache* m_tc; GSTextureCache* m_tc;
GSVector4i m_r; GSVector4i m_r;
GSTextureCache::Source* m_src; GSTextureCache::Source* m_src;
HWMipmapLevel m_hw_mipmap;
virtual void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) = 0; virtual void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) = 0;

View File

@ -773,7 +773,7 @@ void GSRendererNew::EmulateTextureSampler(const GSTextureCache::Source* tex)
const bool need_mipmap = IsMipMapDraw(); const bool need_mipmap = IsMipMapDraw();
const bool shader_emulated_sampler = tex->m_palette || cpsm.fmt != 0 || complex_wms_wmt || psm.depth; const bool shader_emulated_sampler = tex->m_palette || cpsm.fmt != 0 || complex_wms_wmt || psm.depth;
const bool trilinear_manual = need_mipmap && m_mipmap == 2; const bool trilinear_manual = need_mipmap && m_hw_mipmap == HWMipmapLevel::Full;
bool bilinear = m_vt.IsLinear(); bool bilinear = m_vt.IsLinear();
int trilinear = 0; int trilinear = 0;
@ -782,11 +782,11 @@ void GSRendererNew::EmulateTextureSampler(const GSTextureCache::Source* tex)
{ {
case TriFiltering::Forced: case TriFiltering::Forced:
trilinear = static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Linear); trilinear = static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
trilinear_auto = !need_mipmap || m_mipmap != 2; trilinear_auto = !need_mipmap || m_hw_mipmap != HWMipmapLevel::Full;
break; break;
case TriFiltering::PS2: case TriFiltering::PS2:
if (need_mipmap && m_mipmap != 2) if (need_mipmap && m_hw_mipmap != HWMipmapLevel::Full)
{ {
trilinear = m_context->TEX1.MMIN; trilinear = m_context->TEX1.MMIN;
trilinear_auto = true; trilinear_auto = true;

View File

@ -109,7 +109,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
{ {
// JackieChan and SVCChaos cause regressions when skipping the draw calls when depth is disabled/not supported. // JackieChan and SVCChaos cause regressions when skipping the draw calls when depth is disabled/not supported.
// This way we make sure there are no regressions on D3D as well. // This way we make sure there are no regressions on D3D as well.
return LookupSource(TEX0, TEXA, r); return LookupSource(TEX0, TEXA, r, false);
} }
else else
{ {
@ -202,7 +202,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
if (m_renderer->m_game.title == CRC::JackieChanAdv || m_renderer->m_game.title == CRC::SVCChaos) if (m_renderer->m_game.title == CRC::JackieChanAdv || m_renderer->m_game.title == CRC::SVCChaos)
{ {
// JackieChan and SVCChaos cause regressions when skipping the draw calls so we reuse the old code for these two. // JackieChan and SVCChaos cause regressions when skipping the draw calls so we reuse the old code for these two.
return LookupSource(TEX0, TEXA, r); return LookupSource(TEX0, TEXA, r, false);
} }
else else
{ {
@ -219,7 +219,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
return src; return src;
} }
GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r) GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool mipmap)
{ {
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM]; const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
//const GSLocalMemory::psm_t& cpsm = psm.pal > 0 ? GSLocalMemory::m_psm[TEX0.CPSM] : psm; //const GSLocalMemory::psm_t& cpsm = psm.pal > 0 ? GSLocalMemory::m_psm[TEX0.CPSM] : psm;
@ -475,7 +475,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
GL_CACHE("TC: src miss (0x%x, 0x%x, %s)", TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0, psm_str(TEX0.PSM)); GL_CACHE("TC: src miss (0x%x, 0x%x, %s)", TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0, psm_str(TEX0.PSM));
} }
#endif #endif
src = CreateSource(TEX0, TEXA, dst, half_right, x_offset, y_offset); src = CreateSource(TEX0, TEXA, dst, half_right, x_offset, y_offset, mipmap);
new_source = true; new_source = true;
} }
else else
@ -1282,7 +1282,7 @@ void GSTextureCache::IncAge()
} }
//Fixme: Several issues in here. Not handling depth stencil, pitch conversion doesnt work. //Fixme: Several issues in here. Not handling depth stencil, pitch conversion doesnt work.
GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst, bool half_right, int x_offset, int y_offset) GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst, bool half_right, int x_offset, int y_offset, bool mipmap)
{ {
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM]; const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
Source* src = new Source(m_renderer, TEX0, TEXA, m_temp); Source* src = new Source(m_renderer, TEX0, TEXA, m_temp);
@ -1302,7 +1302,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
int h = (int)(scale.y * th); int h = (int)(scale.y * th);
GSTexture* sTex = dst->m_texture; GSTexture* sTex = dst->m_texture;
GSTexture* dTex = g_gs_device->CreateTexture(w, h, GSTexture::Format::Color, true); GSTexture* dTex = g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color, true);
GSVector4i area(x, y, x + w, y + h); GSVector4i area(x, y, x + w, y + h);
g_gs_device->CopyRect(sTex, dTex, area); g_gs_device->CopyRect(sTex, dTex, area);
@ -1334,7 +1334,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
// So it could be tricky to put in the middle of the DrawPrims // So it could be tricky to put in the middle of the DrawPrims
// Texture is created to keep code compatibility // Texture is created to keep code compatibility
GSTexture* dTex = g_gs_device->CreateTexture(tw, th, GSTexture::Format::Color, true); GSTexture* dTex = g_gs_device->CreateTexture(tw, th, false, GSTexture::Format::Color, true);
// Keep a trace of origin of the texture // Keep a trace of origin of the texture
src->m_texture = dTex; src->m_texture = dTex;
@ -1508,7 +1508,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
// 'src' is the new texture cache entry (hence the output) // 'src' is the new texture cache entry (hence the output)
GSTexture* sTex = dst->m_texture; GSTexture* sTex = dst->m_texture;
GSTexture* dTex = use_texture ? GSTexture* dTex = use_texture ?
g_gs_device->CreateTexture(w, h, GSTexture::Format::Color, true) : g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color, true) :
g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, !texture_completely_overwritten); g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, !texture_completely_overwritten);
src->m_texture = dTex; src->m_texture = dTex;
@ -1614,12 +1614,12 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
{ {
if (m_paltex && psm.pal > 0) if (m_paltex && psm.pal > 0)
{ {
src->m_texture = g_gs_device->CreateTexture(tw, th, GSTexture::Format::UNorm8); src->m_texture = g_gs_device->CreateTexture(tw, th, false, GSTexture::Format::UNorm8);
AttachPaletteToSource(src, psm.pal, true); AttachPaletteToSource(src, psm.pal, true);
} }
else else
{ {
src->m_texture = g_gs_device->CreateTexture(tw, th, GSTexture::Format::Color); src->m_texture = g_gs_device->CreateTexture(tw, th, mipmap, GSTexture::Format::Color);
if (psm.pal > 0) if (psm.pal > 0)
{ {
AttachPaletteToSource(src, psm.pal, false); AttachPaletteToSource(src, psm.pal, false);
@ -2274,7 +2274,7 @@ void GSTextureCache::Target::Update()
TEXA.TA0 = 0; TEXA.TA0 = 0;
TEXA.TA1 = 0x80; TEXA.TA1 = 0x80;
GSTexture* t = g_gs_device->CreateTexture(w, h, GSTexture::Format::Color); GSTexture* t = g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color);
GSOffset off = m_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM); GSOffset off = m_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM);
@ -2434,7 +2434,7 @@ void GSTextureCache::Palette::InitializeTexture()
// sampling such texture are always normalized by 255. // sampling such texture are always normalized by 255.
// This is because indexes are stored as normalized values of an RGBA texture (e.g. index 15 will be read as (15/255), // This is because indexes are stored as normalized values of an RGBA texture (e.g. index 15 will be read as (15/255),
// and therefore will read texel 15/255 * texture size). // and therefore will read texel 15/255 * texture size).
m_tex_palette = g_gs_device->CreateTexture(256, 1, GSTexture::Format::Color); m_tex_palette = g_gs_device->CreateTexture(256, 1, false, GSTexture::Format::Color);
m_tex_palette->Update(GSVector4i(0, 0, m_pal, 1), m_clut, m_pal * sizeof(m_clut[0])); m_tex_palette->Update(GSVector4i(0, 0, m_pal, 1), m_clut, m_pal * sizeof(m_clut[0]));
} }
} }

View File

@ -232,7 +232,7 @@ protected:
u8 m_texture_inside_rt_cache_size = 255; u8 m_texture_inside_rt_cache_size = 255;
std::vector<TexInsideRtCacheEntry> m_texture_inside_rt_cache; std::vector<TexInsideRtCacheEntry> m_texture_inside_rt_cache;
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL, bool half_right = false, int x_offset = 0, int y_offset = 0); Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL, bool half_right = false, int x_offset = 0, int y_offset = 0, bool mipmap = false);
Target* CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type); 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(Source* s, const GSVector4i& r) = 0;
@ -246,7 +246,7 @@ public:
void RemoveAll(); void RemoveAll();
void RemovePartial(); void RemovePartial();
Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r); Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool mipmap);
Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette = false); Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette = false);
Target* LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used, u32 fbmask = 0); Target* LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used, u32 fbmask = 0);

View File

@ -63,7 +63,6 @@ GSDeviceOGL::GSDeviceOGL()
memset(&m_om_dss, 0, sizeof(m_om_dss)); memset(&m_om_dss, 0, sizeof(m_om_dss));
memset(&m_profiler, 0, sizeof(m_profiler)); memset(&m_profiler, 0, sizeof(m_profiler));
m_mipmap = theApp.GetConfigI("mipmap");
m_upscale_multiplier = std::max(1, theApp.GetConfigI("upscale_multiplier")); m_upscale_multiplier = std::max(1, theApp.GetConfigI("upscale_multiplier"));
// Reset the debug file // Reset the debug file
@ -199,12 +198,12 @@ void GSDeviceOGL::GenerateProfilerData()
} }
} }
GSTexture* GSDeviceOGL::CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format fmt) GSTexture* GSDeviceOGL::CreateSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format fmt)
{ {
GL_PUSH("Create surface"); GL_PUSH("Create surface");
// A wrapper to call GSTextureOGL, with the different kind of parameters. // A wrapper to call GSTextureOGL, with the different kind of parameters.
GSTextureOGL* t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1 || GSConfig.UserHacks_TriFilter != TriFiltering::Off); GSTextureOGL* t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, mipmap);
return t; return t;
} }
@ -950,7 +949,7 @@ void GSDeviceOGL::InitPrimDateTexture(GSTexture* rt, const GSVector4i& area)
// Create a texture to avoid the useless clean@0 // Create a texture to avoid the useless clean@0
if (m_date.t == NULL) if (m_date.t == NULL)
m_date.t = CreateTexture(rtsize.x, rtsize.y, GSTexture::Format::Int32); m_date.t = CreateTexture(rtsize.x, rtsize.y, false, GSTexture::Format::Int32);
// Clean with the max signed value // Clean with the max signed value
const int max_int = 0x7FFFFFFF; const int max_int = 0x7FFFFFFF;

View File

@ -214,7 +214,6 @@ private:
// Increment this constant whenever shaders change, to invalidate user's program binary cache. // Increment this constant whenever shaders change, to invalidate user's program binary cache.
static constexpr u32 SHADER_VERSION = 1; static constexpr u32 SHADER_VERSION = 1;
int m_mipmap;
int m_upscale_multiplier; int m_upscale_multiplier;
static FILE* m_debug_gl_file; static FILE* m_debug_gl_file;
@ -301,7 +300,7 @@ private:
AlignedBuffer<u8, 32> m_download_buffer; AlignedBuffer<u8, 32> m_download_buffer;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final; GSTexture* CreateSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format) final;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) final; void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final; void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;

View File

@ -338,17 +338,14 @@ void GSDeviceVK::ClearStencil(GSTexture* t, u8 c)
static_cast<GSTextureVK*>(t)->TransitionToLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); static_cast<GSTextureVK*>(t)->TransitionToLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
} }
GSTexture* GSDeviceVK::CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) GSTexture* GSDeviceVK::CreateSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format)
{ {
pxAssert(type != GSTexture::Type::Offscreen && type != GSTexture::Type::SparseRenderTarget && pxAssert(type != GSTexture::Type::Offscreen && type != GSTexture::Type::SparseRenderTarget &&
type != GSTexture::Type::SparseDepthStencil); type != GSTexture::Type::SparseDepthStencil);
const u32 width = std::max<u32>(1, std::min<u32>(w, g_vulkan_context->GetMaxImageDimension2D())); const u32 width = std::max<u32>(1, std::min<u32>(w, g_vulkan_context->GetMaxImageDimension2D()));
const u32 height = std::max<u32>(1, std::min<u32>(h, g_vulkan_context->GetMaxImageDimension2D())); const u32 height = std::max<u32>(1, std::min<u32>(h, g_vulkan_context->GetMaxImageDimension2D()));
const u32 layers = mipmap ? static_cast<u32>(log2(std::max(w, h))) : 1u;
const bool mipmap =
type == GSTexture::Type::Texture && (m_mipmap > 1 || GSConfig.UserHacks_TriFilter == TriFiltering::Forced);
const u32 layers = mipmap && format == GSTexture::Format::Color ? static_cast<u32>(log2(std::max(w, h))) : 1u;
return GSTextureVK::Create(type, width, height, layers, format).release(); return GSTextureVK::Create(type, width, height, layers, format).release();
} }

View File

@ -158,7 +158,7 @@ private:
std::string m_tfx_source; std::string m_tfx_source;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) override; GSTexture* CreateSurface(GSTexture::Type type, int w, int h, bool mipmap, GSTexture::Format format) override;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE,
const GSRegEXTBUF& EXTBUF, const GSVector4& c) final; const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;