GS: Reference GSConfig instead of using theApp

Removes multiple sources of truth, enables overrides.
This commit is contained in:
Connor McLaughlin 2022-03-03 21:32:32 +10:00 committed by refractionpcsx2
parent 9d003486c2
commit d35db63d73
13 changed files with 60 additions and 121 deletions

View File

@ -544,6 +544,9 @@ struct Pcsx2Config
/// Sets user hack values to defaults when user hacks are not enabled. /// Sets user hack values to defaults when user hacks are not enabled.
void MaskUserHacks(); void MaskUserHacks();
/// Sets user hack values to defaults when upscaling is not enabled.
void MaskUpscalingHacks();
/// Returns true if any of the hardware renderers are selected. /// Returns true if any of the hardware renderers are selected.
bool UseHardwareRenderer() const; bool UseHardwareRenderer() const;

View File

@ -311,6 +311,7 @@ bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* b
GSConfig = config; GSConfig = config;
GSConfig.Renderer = renderer; GSConfig.Renderer = renderer;
GSConfig.MaskUserHacks(); GSConfig.MaskUserHacks();
GSConfig.MaskUpscalingHacks();
if (!Host::AcquireHostDisplay(GetAPIForRenderer(renderer))) if (!Host::AcquireHostDisplay(GetAPIForRenderer(renderer)))
{ {
@ -724,6 +725,7 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
GSConfig = new_config; GSConfig = new_config;
GSConfig.Renderer = (GSConfig.Renderer == GSRendererType::Auto) ? GSUtil::GetPreferredRenderer() : GSConfig.Renderer; GSConfig.Renderer = (GSConfig.Renderer == GSRendererType::Auto) ? GSUtil::GetPreferredRenderer() : GSConfig.Renderer;
GSConfig.MaskUserHacks(); GSConfig.MaskUserHacks();
GSConfig.MaskUpscalingHacks();
if (!s_gs) if (!s_gs)
return; return;

View File

@ -23,6 +23,11 @@
int GSState::s_n = 0; int GSState::s_n = 0;
static __fi bool IsAutoFlushEnabled()
{
return (GSConfig.Renderer == GSRendererType::SW) ? GSConfig.AutoFlushSW : GSConfig.UserHacks_AutoFlush;
}
GSState::GSState() GSState::GSState()
: m_version(7) : m_version(7)
, m_gsc(NULL) , m_gsc(NULL)
@ -30,6 +35,7 @@ GSState::GSState()
, m_skip_offset(0) , m_skip_offset(0)
, m_q(1.0f) , m_q(1.0f)
, m_scanmask_used(false) , m_scanmask_used(false)
, tex_flushed(true)
, m_vt(this) , m_vt(this)
, m_regs(NULL) , m_regs(NULL)
, m_crc(0) , m_crc(0)
@ -39,18 +45,8 @@ 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 = GSConfig.UpscaleMultiplier == 1; m_nativeres = GSConfig.UpscaleMultiplier == 1;
m_mipmap = theApp.GetConfigB("mipmap"); m_mipmap = GSConfig.Mipmap;
m_NTSC_Saturation = theApp.GetConfigB("NTSC_Saturation"); m_NTSC_Saturation = theApp.GetConfigB("NTSC_Saturation");
if (theApp.GetConfigB("UserHacks"))
{
m_userhacks_auto_flush = theApp.GetConfigB("UserHacks_AutoFlush");
m_userhacks_wildhack = theApp.GetConfigB("UserHacks_WildHack");
}
else
{
m_userhacks_auto_flush = false;
m_userhacks_wildhack = false;
}
s_n = 0; s_n = 0;
s_dump = theApp.GetConfigB("dump"); s_dump = theApp.GetConfigB("dump");
@ -132,7 +128,6 @@ GSState::GSState()
PRIM = &m_env.PRIM; PRIM = &m_env.PRIM;
//CSR->rREV = 0x20; //CSR->rREV = 0x20;
m_env.PRMODECONT.AC = 1; m_env.PRMODECONT.AC = 1;
tex_flushed = true;
Reset(); Reset();
@ -246,7 +241,7 @@ void GSState::ResetHandlers()
m_fpGIFPackedRegHandlers[GIF_REG_PRIM] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerPRIM; m_fpGIFPackedRegHandlers[GIF_REG_PRIM] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerPRIM;
m_fpGIFPackedRegHandlers[GIF_REG_RGBA] = &GSState::GIFPackedRegHandlerRGBA; m_fpGIFPackedRegHandlers[GIF_REG_RGBA] = &GSState::GIFPackedRegHandlerRGBA;
m_fpGIFPackedRegHandlers[GIF_REG_STQ] = &GSState::GIFPackedRegHandlerSTQ; m_fpGIFPackedRegHandlers[GIF_REG_STQ] = &GSState::GIFPackedRegHandlerSTQ;
m_fpGIFPackedRegHandlers[GIF_REG_UV] = m_userhacks_wildhack ? &GSState::GIFPackedRegHandlerUV_Hack : &GSState::GIFPackedRegHandlerUV; m_fpGIFPackedRegHandlers[GIF_REG_UV] = GSConfig.UserHacks_WildHack ? &GSState::GIFPackedRegHandlerUV_Hack : &GSState::GIFPackedRegHandlerUV;
m_fpGIFPackedRegHandlers[GIF_REG_TEX0_1] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerTEX0<0>; m_fpGIFPackedRegHandlers[GIF_REG_TEX0_1] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerTEX0<0>;
m_fpGIFPackedRegHandlers[GIF_REG_TEX0_2] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerTEX0<1>; m_fpGIFPackedRegHandlers[GIF_REG_TEX0_2] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerTEX0<1>;
m_fpGIFPackedRegHandlers[GIF_REG_CLAMP_1] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerCLAMP<0>; m_fpGIFPackedRegHandlers[GIF_REG_CLAMP_1] = (GIFPackedRegHandler)(GIFRegHandler)&GSState::GIFRegHandlerCLAMP<0>;
@ -257,7 +252,7 @@ void GSState::ResetHandlers()
// swap first/last indices when the provoking vertex is the first (D3D/Vulkan) // swap first/last indices when the provoking vertex is the first (D3D/Vulkan)
const bool index_swap = GSConfig.UseHardwareRenderer() && !g_gs_device->Features().provoking_vertex_last; const bool index_swap = GSConfig.UseHardwareRenderer() && !g_gs_device->Features().provoking_vertex_last;
if (m_userhacks_auto_flush) if (IsAutoFlushEnabled())
index_swap ? SetPrimHandlers<true, true>() : SetPrimHandlers<true, false>(); index_swap ? SetPrimHandlers<true, true>() : SetPrimHandlers<true, false>();
else else
index_swap ? SetPrimHandlers<false, true>() : SetPrimHandlers<false, false>(); index_swap ? SetPrimHandlers<false, true>() : SetPrimHandlers<false, false>();
@ -268,7 +263,7 @@ void GSState::ResetHandlers()
m_fpGIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GSState::GIFRegHandlerRGBAQ; m_fpGIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GSState::GIFRegHandlerRGBAQ;
m_fpGIFRegHandlers[GIF_A_D_REG_RGBAQ + 0x10] = &GSState::GIFRegHandlerRGBAQ; m_fpGIFRegHandlers[GIF_A_D_REG_RGBAQ + 0x10] = &GSState::GIFRegHandlerRGBAQ;
m_fpGIFRegHandlers[GIF_A_D_REG_ST] = &GSState::GIFRegHandlerST; m_fpGIFRegHandlers[GIF_A_D_REG_ST] = &GSState::GIFRegHandlerST;
m_fpGIFRegHandlers[GIF_A_D_REG_UV] = m_userhacks_wildhack ? &GSState::GIFRegHandlerUV_Hack : &GSState::GIFRegHandlerUV; m_fpGIFRegHandlers[GIF_A_D_REG_UV] = GSConfig.UserHacks_WildHack ? &GSState::GIFRegHandlerUV_Hack : &GSState::GIFRegHandlerUV;
m_fpGIFRegHandlers[GIF_A_D_REG_TEX0_1] = &GSState::GIFRegHandlerTEX0<0>; m_fpGIFRegHandlers[GIF_A_D_REG_TEX0_1] = &GSState::GIFRegHandlerTEX0<0>;
m_fpGIFRegHandlers[GIF_A_D_REG_TEX0_2] = &GSState::GIFRegHandlerTEX0<1>; m_fpGIFRegHandlers[GIF_A_D_REG_TEX0_2] = &GSState::GIFRegHandlerTEX0<1>;
m_fpGIFRegHandlers[GIF_A_D_REG_CLAMP_1] = &GSState::GIFRegHandlerCLAMP<0>; m_fpGIFRegHandlers[GIF_A_D_REG_CLAMP_1] = &GSState::GIFRegHandlerCLAMP<0>;
@ -1136,7 +1131,7 @@ void GSState::GIFRegHandlerTEXFLUSH(const GIFReg* RESTRICT r)
// Some games do a single sprite draw to itself, then flush the texture cache, then use that texture again. // Some games do a single sprite draw to itself, then flush the texture cache, then use that texture again.
// This won't get picked up by the new autoflush logic (which checks for page crossings for the PS2 Texture Cache flush) // This won't get picked up by the new autoflush logic (which checks for page crossings for the PS2 Texture Cache flush)
// so we need to do it here. // so we need to do it here.
if(m_userhacks_auto_flush) if (IsAutoFlushEnabled())
Flush(); Flush();
} }

View File

@ -149,14 +149,11 @@ protected:
bool IsBadFrame(); bool IsBadFrame();
void SetupCrcHack(); void SetupCrcHack();
bool m_userhacks_wildhack;
bool m_isPackedUV_HackFlag; bool m_isPackedUV_HackFlag;
CRCHackLevel m_crc_hack_level; CRCHackLevel m_crc_hack_level;
GetSkipCount m_gsc; GetSkipCount m_gsc;
int m_skip; int m_skip;
int m_skip_offset; int m_skip_offset;
bool m_userhacks_auto_flush;
bool tex_flushed;
GSVertex m_v; GSVertex m_v;
float m_q; float m_q;
@ -164,6 +161,7 @@ protected:
GSVector4i m_ofxy; GSVector4i m_ofxy;
bool m_scanmask_used; bool m_scanmask_used;
bool tex_flushed;
struct struct
{ {

View File

@ -18,7 +18,6 @@
bool s_nativeres; bool s_nativeres;
static CRCHackLevel s_crc_hack_level = CRCHackLevel::Full; static CRCHackLevel s_crc_hack_level = CRCHackLevel::Full;
bool s_autoflush;
// hacks // hacks
#define CRC_Partial (s_crc_hack_level >= CRCHackLevel::Partial) #define CRC_Partial (s_crc_hack_level >= CRCHackLevel::Partial)
#define CRC_Full (s_crc_hack_level >= CRCHackLevel::Full) #define CRC_Full (s_crc_hack_level >= CRCHackLevel::Full)
@ -419,7 +418,7 @@ bool GSC_BurnoutGames(const GSFrameInfo& fi, int& skip)
// 0x01dc0 01c00(MP) ntsc, 0x01f00 0x01d40(MP) ntsc progressive, 0x02200(MP) pal. // 0x01dc0 01c00(MP) ntsc, 0x01f00 0x01d40(MP) ntsc progressive, 0x02200(MP) pal.
// Yellow stripes. // Yellow stripes.
// Multiplayer tested only on Takedown. // Multiplayer tested only on Takedown.
skip = s_autoflush ? 2 : 4; skip = GSConfig.UserHacks_AutoFlush ? 2 : 4;
} }
} }
@ -950,7 +949,6 @@ void GSState::SetupCrcHack()
s_nativeres = m_nativeres; s_nativeres = m_nativeres;
s_crc_hack_level = m_crc_hack_level; s_crc_hack_level = m_crc_hack_level;
s_autoflush = m_userhacks_auto_flush;
memset(lut, 0, sizeof(lut)); memset(lut, 0, sizeof(lut));
@ -1055,7 +1053,7 @@ bool GSState::IsBadFrame()
return false; return false;
} }
if (m_skip == 0 && GSConfig.UserHacks && (GSConfig.SkipDraw > 0)) if (m_skip == 0 && GSConfig.SkipDraw > 0)
{ {
if (fi.TME) if (fi.TME)
{ {

View File

@ -25,7 +25,6 @@ GSRendererHW::GSRendererHW()
, m_height(default_rt_size.y) , m_height(default_rt_size.y)
, m_custom_width(1024) , m_custom_width(1024)
, m_custom_height(1024) , m_custom_height(1024)
, 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_hw_mipmap(GSConfig.HWMipmap)
@ -37,29 +36,13 @@ GSRendererHW::GSRendererHW()
, m_lod(GSVector2i(0, 0)) , m_lod(GSVector2i(0, 0))
{ {
m_mipmap = (m_hw_mipmap >= HWMipmapLevel::Basic); m_mipmap = (m_hw_mipmap >= HWMipmapLevel::Basic);
m_conservative_framebuffer = theApp.GetConfigB("conservative_framebuffer");
if (theApp.GetConfigB("UserHacks")) if (GSConfig.UserHacks)
{ {
m_userhacks_enabled_gs_mem_clear = !theApp.GetConfigB("UserHacks_Disable_Safe_Features"); m_userhacks_tcoffset_x = GSConfig.UserHacks_TCOffsetX / -1000.0f;
m_userHacks_enabled_unscale_ptln = !theApp.GetConfigB("UserHacks_Disable_Safe_Features"); m_userhacks_tcoffset_y = GSConfig.UserHacks_TCOffsetY / -1000.0f;
m_userhacks_align_sprite_X = theApp.GetConfigB("UserHacks_align_sprite_X");
m_userHacks_merge_sprite = theApp.GetConfigB("UserHacks_merge_pp_sprite");
m_userhacks_ts_half_bottom = theApp.GetConfigI("UserHacks_Half_Bottom_Override");
m_userhacks_round_sprite_offset = theApp.GetConfigI("UserHacks_round_sprite_offset");
m_userhacks_tcoffset_x = theApp.GetConfigI("UserHacks_TCOffsetX") / -1000.0f;
m_userhacks_tcoffset_y = theApp.GetConfigI("UserHacks_TCOffsetY") / -1000.0f;
m_userhacks_tcoffset = m_userhacks_tcoffset_x < 0.0f || m_userhacks_tcoffset_y < 0.0f; m_userhacks_tcoffset = m_userhacks_tcoffset_x < 0.0f || m_userhacks_tcoffset_y < 0.0f;
} }
else
{
m_userhacks_enabled_gs_mem_clear = true;
m_userHacks_enabled_unscale_ptln = true;
m_userhacks_align_sprite_X = false;
m_userHacks_merge_sprite = false;
m_userhacks_ts_half_bottom = -1;
m_userhacks_round_sprite_offset = 0;
}
if (!GSConfig.UpscaleMultiplier) // Custom Resolution if (!GSConfig.UpscaleMultiplier) // Custom Resolution
{ {
@ -67,13 +50,6 @@ GSRendererHW::GSRendererHW()
m_custom_height = m_height = theApp.GetConfigI("resy"); m_custom_height = m_height = theApp.GetConfigI("resy");
} }
if (GSConfig.UpscaleMultiplier == 1) // hacks are only needed for upscaling issues.
{
m_userhacks_round_sprite_offset = 0;
m_userhacks_align_sprite_X = false;
m_userHacks_merge_sprite = false;
}
m_dump_root = root_hw; m_dump_root = root_hw;
GSTextureReplacements::Initialize(m_tc); GSTextureReplacements::Initialize(m_tc);
} }
@ -127,7 +103,7 @@ void GSRendererHW::SetScaling()
// //
// m_large_framebuffer has been inverted to m_conservative_framebuffer, it isn't an option that benefits being enabled all the time for everyone. // m_large_framebuffer has been inverted to m_conservative_framebuffer, it isn't an option that benefits being enabled all the time for everyone.
int fb_height = 1280; int fb_height = 1280;
if (m_conservative_framebuffer) if (GSConfig.ConservativeFramebuffer)
{ {
fb_height = fb_width < 1024 ? std::max(512, crtc_size.y) : 1024; fb_height = fb_width < 1024 ? std::max(512, crtc_size.y) : 1024;
} }
@ -544,7 +520,7 @@ void GSRendererHW::ConvertSpriteTextureShuffle(bool& write_ba, bool& read_ba)
read_ba = (tex_pos > 112 && tex_pos < 144); read_ba = (tex_pos > 112 && tex_pos < 144);
bool half_bottom = false; bool half_bottom = false;
switch (m_userhacks_ts_half_bottom) switch (GSConfig.UserHacks_HalfBottomOverride)
{ {
case 0: case 0:
// Force Disabled. // Force Disabled.
@ -774,7 +750,7 @@ GSVector4i GSRendererHW::ComputeBoundingBox(const GSVector2& rtscale, const GSVe
void GSRendererHW::MergeSprite(GSTextureCache::Source* tex) void GSRendererHW::MergeSprite(GSTextureCache::Source* tex)
{ {
// Upscaling hack to avoid various line/grid issues // Upscaling hack to avoid various line/grid issues
if (m_userHacks_merge_sprite && tex && tex->m_target && (m_vt.m_primclass == GS_SPRITE_CLASS)) if (GSConfig.UserHacks_MergePPSprite && tex && tex->m_target && (m_vt.m_primclass == GS_SPRITE_CLASS))
{ {
if (PRIM->FST && GSLocalMemory::m_psm[tex->m_TEX0.PSM].fmt < 2 && ((m_vt.m_eq.value & 0xCFFFF) == 0xCFFFF)) if (PRIM->FST && GSLocalMemory::m_psm[tex->m_TEX0.PSM].fmt < 2 && ((m_vt.m_eq.value & 0xCFFFF) == 0xCFFFF))
{ {
@ -1732,7 +1708,7 @@ void GSRendererHW::Draw()
return; return;
} }
if (m_userhacks_enabled_gs_mem_clear) if (!GSConfig.UserHacks_DisableSafeFeatures)
{ {
// Constant Direct Write without texture/test/blending (aka a GS mem clear) // Constant Direct Write without texture/test/blending (aka a GS mem clear)
if ((m_vt.m_primclass == GS_SPRITE_CLASS) && !PRIM->TME // Direct write if ((m_vt.m_primclass == GS_SPRITE_CLASS) && !PRIM->TME // Direct write
@ -1758,7 +1734,7 @@ void GSRendererHW::Draw()
GSVertex* v = &m_vertex.buff[0]; GSVertex* v = &m_vertex.buff[0];
// Hack to avoid vertical black line in various games (ace combat/tekken) // Hack to avoid vertical black line in various games (ace combat/tekken)
if (m_userhacks_align_sprite_X) if (GSConfig.UserHacks_AlignSpriteX)
{ {
// Note for performance reason I do the check only once on the first // Note for performance reason I do the check only once on the first
// primitive // primitive
@ -1784,7 +1760,7 @@ void GSRendererHW::Draw()
// Noting to do if no texture is sampled // Noting to do if no texture is sampled
if (PRIM->FST && draw_sprite_tex) if (PRIM->FST && draw_sprite_tex)
{ {
if ((m_userhacks_round_sprite_offset > 1) || (m_userhacks_round_sprite_offset == 1 && !m_vt.IsLinear())) if ((GSConfig.UserHacks_RoundSprite > 1) || (GSConfig.UserHacks_RoundSprite == 1 && !m_vt.IsLinear()))
{ {
if (m_vt.IsLinear()) if (m_vt.IsLinear())
RoundSpriteOffset<true>(); RoundSpriteOffset<true>();

View File

@ -27,12 +27,6 @@ private:
int m_height; int m_height;
int m_custom_width; int m_custom_width;
int m_custom_height; int m_custom_height;
int m_userhacks_ts_half_bottom;
bool m_conservative_framebuffer;
bool m_userhacks_align_sprite_X;
bool m_userhacks_enabled_gs_mem_clear;
bool m_userHacks_merge_sprite;
static constexpr float SSR_UV_TOLERANCE = 1.0f; static constexpr float SSR_UV_TOLERANCE = 1.0f;
@ -148,9 +142,6 @@ protected:
virtual void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) = 0; virtual void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) = 0;
int m_userhacks_round_sprite_offset;
bool m_userHacks_enabled_unscale_ptln;
bool m_userhacks_tcoffset; bool m_userhacks_tcoffset;
float m_userhacks_tcoffset_x; float m_userhacks_tcoffset_x;
float m_userhacks_tcoffset_y; float m_userhacks_tcoffset_y;

View File

@ -33,12 +33,12 @@ void GSRendererNew::SetupIA(const float& sx, const float& sy)
{ {
GL_PUSH("IA"); GL_PUSH("IA");
if (m_userhacks_wildhack && !m_isPackedUV_HackFlag && PRIM->TME && PRIM->FST) if (GSConfig.UserHacks_WildHack && !m_isPackedUV_HackFlag && PRIM->TME && PRIM->FST)
{ {
for (unsigned int i = 0; i < m_vertex.next; i++) for (unsigned int i = 0; i < m_vertex.next; i++)
m_vertex.buff[i].UV &= 0x3FEF3FEF; m_vertex.buff[i].UV &= 0x3FEF3FEF;
} }
const bool unscale_pt_ln = m_userHacks_enabled_unscale_ptln && (GetUpscaleMultiplier() != 1); const bool unscale_pt_ln = !GSConfig.UserHacks_DisableSafeFeatures && (GetUpscaleMultiplier() != 1);
const GSDevice::FeatureSupport features = g_gs_device->Features(); const GSDevice::FeatureSupport features = g_gs_device->Features();
switch (m_vt.m_primclass) switch (m_vt.m_primclass)

View File

@ -27,35 +27,12 @@
#define XXH_INLINE_ALL 1 #define XXH_INLINE_ALL 1
#include "xxhash.h" #include "xxhash.h"
bool GSTextureCache::m_disable_partial_invalidation = false;
bool GSTextureCache::m_wrap_gs_mem = false;
u8* GSTextureCache::m_temp; u8* GSTextureCache::m_temp;
GSTextureCache::GSTextureCache(GSRenderer* r) GSTextureCache::GSTextureCache(GSRenderer* r)
: m_renderer(r) : m_renderer(r)
, m_palette_map(r) , m_palette_map(r)
{ {
if (theApp.GetConfigB("UserHacks"))
{
UserHacks_HalfPixelOffset = theApp.GetConfigI("UserHacks_HalfPixelOffset") == 1;
m_preload_frame = theApp.GetConfigB("preload_frame_with_gs_data");
m_disable_partial_invalidation = theApp.GetConfigB("UserHacks_DisablePartialInvalidation");
m_can_convert_depth = !theApp.GetConfigB("UserHacks_DisableDepthSupport");
m_cpu_fb_conversion = theApp.GetConfigB("UserHacks_CPU_FB_Conversion");
m_texture_inside_rt = theApp.GetConfigB("UserHacks_TextureInsideRt");
m_wrap_gs_mem = theApp.GetConfigB("wrap_gs_mem");
}
else
{
UserHacks_HalfPixelOffset = false;
m_preload_frame = false;
m_disable_partial_invalidation = false;
m_can_convert_depth = true;
m_cpu_fb_conversion = false;
m_texture_inside_rt = false;
m_wrap_gs_mem = false;
}
// In theory 4MB is enough but 9MB is safer for overflow (8MB // In theory 4MB is enough but 9MB is safer for overflow (8MB
// isn't enough in custom resolution) // isn't enough in custom resolution)
// Test: onimusha 3 PAL 60Hz // Test: onimusha 3 PAL 60Hz
@ -110,7 +87,7 @@ void GSTextureCache::RemoveAll()
GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette) GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette)
{ {
if (!m_can_convert_depth) if (GSConfig.UserHacks_DisableDepthSupport)
{ {
GL_CACHE("LookupDepthSource not supported (0x%x, F:0x%x)", TEX0.TBP0, TEX0.PSM); GL_CACHE("LookupDepthSource not supported (0x%x, F:0x%x)", TEX0.TBP0, TEX0.PSM);
throw GSRecoverableError(); throw GSRecoverableError();
@ -305,7 +282,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
// 1/ it just works :) // 1/ it just works :)
// 2/ even with upscaling // 2/ even with upscaling
// 3/ for both Direct3D and OpenGL // 3/ for both Direct3D and OpenGL
if (m_cpu_fb_conversion && (psm == PSM_PSMT4 || psm == PSM_PSMT8)) if (GSConfig.UserHacks_CPUFBConversion && (psm == PSM_PSMT4 || psm == PSM_PSMT8))
// Forces 4-bit and 8-bit frame buffer conversion to be done on the CPU instead of the GPU, but performance will be slower. // Forces 4-bit and 8-bit frame buffer conversion to be done on the CPU instead of the GPU, but performance will be slower.
// There is no dedicated shader to handle 4-bit conversion (Stuntman has been confirmed to use 4-bit). // There is no dedicated shader to handle 4-bit conversion (Stuntman has been confirmed to use 4-bit).
// Direct3D10/11 and OpenGL support 8-bit fb conversion but don't render some corner cases properly (Harry Potter games). // Direct3D10/11 and OpenGL support 8-bit fb conversion but don't render some corner cases properly (Harry Potter games).
@ -366,7 +343,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
// //
// Sigh... They don't help us. // Sigh... They don't help us.
if (!found_t && m_can_convert_depth) if (!found_t && !GSConfig.UserHacks_DisableDepthSupport)
{ {
// Let's try a trick to avoid to use wrongly a depth buffer // Let's try a trick to avoid to use wrongly a depth buffer
// Unfortunately, I don't have any Arc the Lad testcase // Unfortunately, I don't have any Arc the Lad testcase
@ -441,7 +418,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
bool GSTextureCache::ShallSearchTextureInsideRt() bool GSTextureCache::ShallSearchTextureInsideRt()
{ {
return m_texture_inside_rt || (m_renderer->m_game.flags & CRC::Flags::TextureInsideRt); return GSConfig.UserHacks_TextureInsideRt || (m_renderer->m_game.flags & CRC::Flags::TextureInsideRt);
} }
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask, const bool is_frame, const int real_h) GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask, const bool is_frame, const int real_h)
@ -545,7 +522,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
if (!is_frame) if (!is_frame)
dst->m_dirty_alpha |= (psm_s.trbpp == 32 && (fbmask & 0xFF000000) != 0xFF000000) || (psm_s.trbpp == 16); dst->m_dirty_alpha |= (psm_s.trbpp == 32 && (fbmask & 0xFF000000) != 0xFF000000) || (psm_s.trbpp == 16);
} }
else if (!is_frame && m_can_convert_depth) else if (!is_frame && !GSConfig.UserHacks_DisableDepthSupport)
{ {
int rev_type = (type == DepthStencil) ? RenderTarget : DepthStencil; int rev_type = (type == DepthStencil) ? RenderTarget : DepthStencil;
@ -608,8 +585,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
// //
// From a performance point of view, it might cost a little on big upscaling // From a performance point of view, it might cost a little on big upscaling
// but normally few RT are miss so it must remain reasonable. // but normally few RT are miss so it must remain reasonable.
bool supported_fmt = m_can_convert_depth || psm_s.depth == 0; bool supported_fmt = !GSConfig.UserHacks_DisableDepthSupport || psm_s.depth == 0;
if (m_preload_frame && TEX0.TBW > 0 && supported_fmt) if (GSConfig.PreloadFrameWithGSData && TEX0.TBW > 0 && supported_fmt)
{ {
GL_INS("Preloading the RT DATA"); GL_INS("Preloading the RT DATA");
// RT doesn't have height but if we use a too big value, we will read outside of the GS memory. // RT doesn't have height but if we use a too big value, we will read outside of the GS memory.
@ -644,7 +621,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
// must invalidate the Target/Depth respectively // must invalidate the Target/Depth respectively
void GSTextureCache::InvalidateVideoMemType(int type, u32 bp) void GSTextureCache::InvalidateVideoMemType(int type, u32 bp)
{ {
if (!m_can_convert_depth) if (GSConfig.UserHacks_DisableDepthSupport)
return; return;
auto& list = m_dst[type]; auto& list = m_dst[type];
@ -761,7 +738,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
// No point keeping invalidated sources around when the hash cache is active, // No point keeping invalidated sources around when the hash cache is active,
// we can just re-hash and create a new source from the cached texture. // we can just re-hash and create a new source from the cached texture.
if (s->m_from_hash_cache || (m_disable_partial_invalidation && s->m_repeating)) if (s->m_from_hash_cache || (GSConfig.UserHacks_DisablePartialInvalidation && s->m_repeating))
{ {
m_src.RemoveAt(s); m_src.RemoveAt(s);
} }
@ -937,7 +914,7 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r
if (psm == PSM_PSMZ32 || psm == PSM_PSMZ24 || psm == PSM_PSMZ16 || psm == PSM_PSMZ16S) if (psm == PSM_PSMZ32 || psm == PSM_PSMZ24 || psm == PSM_PSMZ16 || psm == PSM_PSMZ16S)
{ {
GL_INS("ERROR: InvalidateLocalMem depth format isn't supported (%d,%d to %d,%d)", r.x, r.y, r.z, r.w); GL_INS("ERROR: InvalidateLocalMem depth format isn't supported (%d,%d to %d,%d)", r.x, r.y, r.z, r.w);
if (m_can_convert_depth) if (!GSConfig.UserHacks_DisableDepthSupport)
{ {
auto& dss = m_dst[DepthStencil]; auto& dss = m_dst[DepthStencil];
for (auto it = dss.rbegin(); it != dss.rend(); ++it) // Iterate targets from LRU to MRU. for (auto it = dss.rbegin(); it != dss.rend(); ++it) // Iterate targets from LRU to MRU.
@ -986,7 +963,7 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r
if (t->m_32_bits_fmt && t->m_TEX0.PSM > PSM_PSMCT24) if (t->m_32_bits_fmt && t->m_TEX0.PSM > PSM_PSMCT24)
t->m_TEX0.PSM = PSM_PSMCT32; t->m_TEX0.PSM = PSM_PSMCT32;
if (GSTextureCache::m_disable_partial_invalidation) if (GSConfig.UserHacks_DisablePartialInvalidation)
{ {
Read(t, r.rintersect(t->m_valid)); Read(t, r.rintersect(t->m_valid));
} }
@ -1430,7 +1407,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
float modx = 0.0f; float modx = 0.0f;
float mody = 0.0f; float mody = 0.0f;
if (UserHacks_HalfPixelOffset && hack) if (GSConfig.UserHacks_HalfPixelOffset == 1 && hack)
{ {
switch(m_renderer->GetUpscaleMultiplier()) switch(m_renderer->GetUpscaleMultiplier())
{ {
@ -1607,7 +1584,7 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int
{ {
ASSERT(type == RenderTarget || type == DepthStencil); ASSERT(type == RenderTarget || type == DepthStencil);
Target* t = new Target(m_renderer, TEX0, m_can_convert_depth, type); Target* t = new Target(m_renderer, TEX0, !GSConfig.UserHacks_DisableDepthSupport, type);
// FIXME: initial data should be unswizzled from local mem in Update() if dirty // FIXME: initial data should be unswizzled from local mem in Update() if dirty
@ -1886,7 +1863,7 @@ void GSTextureCache::Source::Update(const GSVector4i& rect, int level)
int i = (bn.blkY() << 7) + bn.blkX(); int i = (bn.blkY() << 7) + bn.blkX();
u32 block = bn.valueNoWrap(); u32 block = bn.valueNoWrap();
if (block < MAX_BLOCKS || m_wrap_gs_mem) if (block < MAX_BLOCKS || GSConfig.WrapGSMem)
{ {
u32 addr = i % MAX_BLOCKS; u32 addr = i % MAX_BLOCKS;
@ -1913,7 +1890,7 @@ void GSTextureCache::Source::Update(const GSVector4i& rect, int level)
{ {
u32 block = bn.valueNoWrap(); u32 block = bn.valueNoWrap();
if (block < MAX_BLOCKS || m_wrap_gs_mem) if (block < MAX_BLOCKS || GSConfig.WrapGSMem)
{ {
block %= MAX_BLOCKS; block %= MAX_BLOCKS;

View File

@ -282,13 +282,7 @@ protected:
std::unordered_map<HashCacheKey, HashCacheEntry, HashCacheKeyHash> m_hash_cache; std::unordered_map<HashCacheKey, HashCacheEntry, HashCacheKeyHash> m_hash_cache;
u64 m_hash_cache_memory_usage = 0; u64 m_hash_cache_memory_usage = 0;
FastList<Target*> m_dst[2]; FastList<Target*> m_dst[2];
bool m_preload_frame;
static u8* m_temp; static u8* m_temp;
bool m_can_convert_depth;
bool m_cpu_fb_conversion;
static bool m_disable_partial_invalidation;
bool m_texture_inside_rt;
static bool m_wrap_gs_mem;
constexpr static size_t S_SURFACE_OFFSET_CACHE_MAX_SIZE = std::numeric_limits<u16>::max(); constexpr static size_t S_SURFACE_OFFSET_CACHE_MAX_SIZE = std::numeric_limits<u16>::max();
std::unordered_map<SurfaceOffsetKey, SurfaceOffset, SurfaceOffsetKeyHash, SurfaceOffsetKeyEqual> m_surface_offset_cache; std::unordered_map<SurfaceOffsetKey, SurfaceOffset, SurfaceOffsetKeyHash, SurfaceOffsetKeyEqual> m_surface_offset_cache;
@ -326,7 +320,6 @@ public:
void InvalidateLocalMem(const GSOffset& off, const GSVector4i& r); void InvalidateLocalMem(const GSOffset& off, const GSVector4i& r);
void IncAge(); void IncAge();
bool UserHacks_HalfPixelOffset;
bool ShallSearchTextureInsideRt(); bool ShallSearchTextureInsideRt();

View File

@ -881,7 +881,7 @@ GLuint GSDeviceOGL::CreateSampler(PSSamplerSelector sel)
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
const int anisotropy = theApp.GetConfigI("MaxAnisotropy"); const int anisotropy = GSConfig.MaxAnisotropy;
if (anisotropy && sel.aniso) if (anisotropy && sel.aniso)
{ {
if (GLExtension::Has("GL_ARB_texture_filter_anisotropic")) if (GLExtension::Has("GL_ARB_texture_filter_anisotropic"))

View File

@ -58,14 +58,6 @@ GSRendererSW::GSRendererSW(int threads)
InitCVB(GS_SPRITE_CLASS); InitCVB(GS_SPRITE_CLASS);
m_dump_root = root_sw; m_dump_root = root_sw;
// Reset handler with the auto flush hack enabled on the SW renderer.
// Some games run better without the hack so rely on ini/gui option.
if (theApp.GetConfigB("autoflush_sw"))
{
m_userhacks_auto_flush = true;
ResetHandlers();
}
} }
GSRendererSW::~GSRendererSW() GSRendererSW::~GSRendererSW()

View File

@ -598,12 +598,15 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
UserHacks_HalfPixelOffset = 0; UserHacks_HalfPixelOffset = 0;
UserHacks_RoundSprite = 0; UserHacks_RoundSprite = 0;
PreloadFrameWithGSData = false; PreloadFrameWithGSData = false;
WrapGSMem = false;
UserHacks_DisablePartialInvalidation = false; UserHacks_DisablePartialInvalidation = false;
UserHacks_DisableDepthSupport = false; UserHacks_DisableDepthSupport = false;
UserHacks_CPUFBConversion = false; UserHacks_CPUFBConversion = false;
UserHacks_TextureInsideRt = false; UserHacks_TextureInsideRt = false;
UserHacks_TCOffsetX = 0; UserHacks_TCOffsetX = 0;
UserHacks_TCOffsetY = 0; UserHacks_TCOffsetY = 0;
SkipDraw = 0;
SkipDrawOffset = 0;
// in wx, we put trilinear filtering behind user hacks, but not in qt. // in wx, we put trilinear filtering behind user hacks, but not in qt.
#ifndef PCSX2_CORE #ifndef PCSX2_CORE
@ -611,6 +614,17 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
#endif #endif
} }
void Pcsx2Config::GSOptions::MaskUpscalingHacks()
{
if (UpscaleMultiplier == 1 || UserHacks)
return;
UserHacks_AlignSpriteX = false;
UserHacks_MergePPSprite = false;
UserHacks_HalfPixelOffset = 0;
UserHacks_RoundSprite = 0;
}
bool Pcsx2Config::GSOptions::UseHardwareRenderer() const bool Pcsx2Config::GSOptions::UseHardwareRenderer() const
{ {
return (Renderer == GSRendererType::DX11 || Renderer == GSRendererType::OGL || Renderer == GSRendererType::VK); return (Renderer == GSRendererType::DX11 || Renderer == GSRendererType::OGL || Renderer == GSRendererType::VK);