GS/HW: Relax CPU sprite render requirements further via levels

This commit is contained in:
Stenzek 2023-03-19 22:24:29 +10:00 committed by refractionpcsx2
parent 70c1620a87
commit ebeb646e4d
11 changed files with 142 additions and 85 deletions

View File

@ -186,16 +186,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
sif, m_ui.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
SettingWidgetBinder::BindWidgetToIntSetting(
sif, m_ui.texturePreloading, "EmuCore/GS", "texture_preloading", static_cast<int>(TexturePreloadingLevel::Off));
connect(m_ui.trilinearFiltering, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onTrilinearFilteringChanged);
connect(m_ui.gpuPaletteConversion, QOverload<int>::of(&QCheckBox::stateChanged), this,
&GraphicsSettingsWidget::onGpuPaletteConversionChanged);
connect(m_ui.textureInsideRt, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onTextureInsideRtChanged);
onTrilinearFilteringChanged();
onGpuPaletteConversionChanged(m_ui.gpuPaletteConversion->checkState());
onTextureInsideRtChanged();
//////////////////////////////////////////////////////////////////////////
// HW Renderer Fixes
@ -203,6 +196,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.crcFixLevel, "EmuCore/GS", "crc_hack_level", static_cast<int>(CRCHackLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfScreenFix, "EmuCore/GS", "UserHacks_Half_Bottom_Override", -1, -1);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuSpriteRenderBW, "EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuSpriteRenderLevel, "EmuCore/GS", "UserHacks_CPUSpriteRenderLevel", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuCLUTRender, "EmuCore/GS", "UserHacks_CPUCLUTRender", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.gpuTargetCLUTMode, "EmuCore/GS", "UserHacks_GPUTargetCLUTMode", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.skipDrawStart, "EmuCore/GS", "UserHacks_SkipDraw_Start", 0);
@ -220,6 +214,15 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.targetPartialInvalidation, "EmuCore/GS", "UserHacks_TargetPartialInvalidation", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.estimateTextureRegion, "EmuCore/GS", "UserHacks_EstimateTextureRegion", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
connect(m_ui.cpuSpriteRenderBW, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onCPUSpriteRenderBWChanged);
connect(m_ui.textureInsideRt, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onTextureInsideRtChanged);
connect(m_ui.gpuPaletteConversion, QOverload<int>::of(&QCheckBox::stateChanged), this,
&GraphicsSettingsWidget::onGpuPaletteConversionChanged);
onCPUSpriteRenderBWChanged();
onTextureInsideRtChanged();
onGpuPaletteConversionChanged(m_ui.gpuPaletteConversion->checkState());
//////////////////////////////////////////////////////////////////////////
// HW Upscaling Fixes
@ -889,6 +892,12 @@ void GraphicsSettingsWidget::onGpuPaletteConversionChanged(int state)
m_ui.anisotropicFiltering->setDisabled(disabled);
}
void GraphicsSettingsWidget::onCPUSpriteRenderBWChanged()
{
const int value = m_dialog->getEffectiveIntValue("EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0);
m_ui.cpuSpriteRenderLevel->setEnabled(value != 0);
}
void GraphicsSettingsWidget::onTextureInsideRtChanged()
{
const bool disabled = static_cast<GSTextureInRtMode>(m_ui.textureInsideRt->currentIndex()) >= GSTextureInRtMode::InsideTargets;

View File

@ -41,6 +41,7 @@ private Q_SLOTS:
void onAdapterChanged(int index);
void onTrilinearFilteringChanged();
void onGpuPaletteConversionChanged(int state);
void onCPUSpriteRenderBWChanged();
void onTextureInsideRtChanged();
void onFullscreenModeChanged(int index);
void onShadeBoostChanged();

View File

@ -813,65 +813,6 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cpuSpriteRenderBW">
<item>
<property name="text">
<string>0 (Disabled)</string>
</property>
</item>
<item>
<property name="text">
<string>1 (64 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>2 (128 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>3 (192 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>4 (256 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>5 (320 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>6 (384 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>7 (448 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>8 (512 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>9 (576 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>10 (640 Max Width)</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
@ -1096,6 +1037,88 @@
</item>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,0">
<item>
<widget class="QComboBox" name="cpuSpriteRenderBW">
<item>
<property name="text">
<string>0 (Disabled)</string>
</property>
</item>
<item>
<property name="text">
<string>1 (64 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>2 (128 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>3 (192 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>4 (256 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>5 (320 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>6 (384 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>7 (448 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>8 (512 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>9 (576 Max Width)</string>
</property>
</item>
<item>
<property name="text">
<string>10 (640 Max Width)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="cpuSpriteRenderLevel">
<item>
<property name="text">
<string>Sprites Only</string>
</property>
</item>
<item>
<property name="text">
<string>Sprites/Triangles</string>
</property>
</item>
<item>
<property name="text">
<string>Blended Sprites/Triangles</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="upscalingFixesTab">

View File

@ -753,7 +753,8 @@ struct Pcsx2Config
int UserHacks_TCOffsetX{0};
int UserHacks_TCOffsetY{0};
int UserHacks_CPUSpriteRenderBW{0};
int UserHacks_CPUCLUTRender{ 0 };
int UserHacks_CPUSpriteRenderLevel{0};
int UserHacks_CPUCLUTRender{0};
GSGPUTargetCLUTMode UserHacks_GPUTargetCLUTMode{GSGPUTargetCLUTMode::Disabled};
GSTextureInRtMode UserHacks_TextureInsideRt{GSTextureInRtMode::Disabled};
TriFiltering TriFilter{TriFiltering::Automatic};

View File

@ -241,6 +241,11 @@
"minimum": 1,
"maximum": 10
},
"cpuSpriteRenderLevel": {
"type": "integer",
"minimum": 0,
"maximum": 2
},
"cpuCLUTRender": {
"type": "integer",
"minimum": 1,

View File

@ -3170,6 +3170,8 @@ void FullscreenUI::DrawGraphicsSettingsPage()
static constexpr const char* s_cpu_sprite_render_bw_options[] = {"0 (Disabled)", "1 (64 Max Width)", "2 (128 Max Width)",
"3 (192 Max Width)", "4 (256 Max Width)", "5 (320 Max Width)", "6 (384 Max Width)", "7 (448 Max Width)",
"8 (512 Max Width)", "9 (576 Max Width)", "10 (640 Max Width)"};
static constexpr const char* s_cpu_sprite_render_level_options[] = {
"Sprites Only", "Sprites/Triangles", "Blended Sprites/Triangles"};
static constexpr const char* s_cpu_clut_render_options[] = {"0 (Disabled)", "1 (Normal)", "2 (Aggressive)"};
static constexpr const char* s_texture_inside_rt_options[] = {"Disabled", "Inside Target", "Merge Targets"};
static constexpr const char* s_half_pixel_offset_options[] = {
@ -3182,6 +3184,8 @@ void FullscreenUI::DrawGraphicsSettingsPage()
"UserHacks_Half_Bottom_Override", -1, s_generic_options, std::size(s_generic_options), -1);
DrawIntListSetting(bsi, "CPU Sprite Render Size", "Uses software renderer to draw texture decompression-like sprites.",
"EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0, s_cpu_sprite_render_bw_options, std::size(s_cpu_sprite_render_bw_options));
DrawIntListSetting(bsi, "CPU Sprite Render Level", "Determines filter level for CPU sprite render.", "EmuCore/GS",
"UserHacks_CPUSpriteRenderLevel", 0, s_cpu_sprite_render_level_options, std::size(s_cpu_sprite_render_level_options));
DrawIntListSetting(bsi, "Software CLUT Render", "Uses software renderer to draw texture CLUT points/sprites.", "EmuCore/GS",
"UserHacks_CPUCLUTRender", 0, s_cpu_clut_render_options, std::size(s_cpu_clut_render_options));
DrawIntSpinBoxSetting(

View File

@ -404,7 +404,7 @@ void ImGuiManager::DrawSettingsOverlay()
if (GSConfig.UserHacks_TCOffsetX != 0 || GSConfig.UserHacks_TCOffsetY != 0)
APPEND("TCO={}/{} ", GSConfig.UserHacks_TCOffsetX, GSConfig.UserHacks_TCOffsetY);
if (GSConfig.UserHacks_CPUSpriteRenderBW != 0)
APPEND("CSBW={} ", GSConfig.UserHacks_CPUSpriteRenderBW);
APPEND("CSBW={}/{} ", GSConfig.UserHacks_CPUSpriteRenderBW, GSConfig.UserHacks_CPUSpriteRenderLevel);
if (GSConfig.UserHacks_CPUCLUTRender != 0)
APPEND("CCLUT={} ", GSConfig.UserHacks_CPUCLUTRender);
if (GSConfig.UserHacks_GPUTargetCLUTMode != GSGPUTargetCLUTMode::Disabled)

View File

@ -4568,40 +4568,42 @@ GSRendererHW::CLUTDrawTestResult GSRendererHW::PossibleCLUTDrawAggressive()
bool GSRendererHW::CanUseSwPrimRender(bool no_rt, bool no_ds, bool draw_sprite_tex)
{
// Master enable.
if (GSConfig.UserHacks_CPUSpriteRenderBW == 0)
const int bw = GSConfig.UserHacks_CPUSpriteRenderBW;
const int level = GSConfig.UserHacks_CPUSpriteRenderLevel;
if (bw == 0)
return false;
// We don't ever want to do this when we have a depth buffer, and only for textured sprites.
if (no_rt || !no_ds || !draw_sprite_tex)
if (no_rt || !no_ds || (level == 0 && !draw_sprite_tex))
return false;
// Check the size threshold. Spider-man 2 uses a FBW of 32 for some silly reason...
if (m_context->FRAME.FBW > static_cast<u32>(GSConfig.UserHacks_CPUSpriteRenderBW) && m_context->FRAME.FBW != 32)
if (m_context->FRAME.FBW > static_cast<u32>(bw) && m_context->FRAME.FBW != 32)
return false;
// We shouldn't be using mipmapping, and this shouldn't be a blended draw.
// TODO: Jak 3 builds textures semi-procedurally using blending, and would be a good candidate here.
if (IsMipMapActive() || !IsOpaque())
if (level < 2 && (IsMipMapActive() || !IsOpaque()))
return false;
// Make sure this isn't something we've actually rendered to (e.g. a texture shuffle).
// We do this by checking the texture block width against the target's block width, as all the decompression draws
// will use a much smaller block size than the framebuffer.
GSTextureCache::Target* src_target = m_tc->GetTargetWithSharedBits(m_context->TEX0.TBP0, m_context->TEX0.PSM);
if (src_target && src_target->m_TEX0.TBW == m_context->TEX0.TBW)
if (PRIM->TME)
{
// If the EE has written over our sample area, we're fine to do this on the CPU, despite the target.
if (!src_target->m_dirty.empty())
GSTextureCache::Target* src_target = m_tc->GetTargetWithSharedBits(m_context->TEX0.TBP0, m_context->TEX0.PSM);
if (src_target)
{
const GSVector4i tr(GetTextureMinMax(m_context->TEX0, m_context->CLAMP, m_vt.IsLinear()).coverage);
for (GSDirtyRect& rc : src_target->m_dirty)
// If the EE has written over our sample area, we're fine to do this on the CPU, despite the target.
if (!src_target->m_dirty.empty())
{
if (!rc.GetDirtyRect(m_context->TEX0).rintersect(tr).rempty())
return true;
const GSVector4i tr(GetTextureMinMax(m_context->TEX0, m_context->CLAMP, m_vt.IsLinear()).coverage);
for (GSDirtyRect& rc : src_target->m_dirty)
{
if (!rc.GetDirtyRect(m_context->TEX0).rintersect(tr).rempty())
return true;
}
}
}
return false;
return false;
}
}
// We can use the sw prim render path!

View File

@ -366,6 +366,7 @@ static const char* s_gs_hw_fix_names[] = {
"texturePreloading",
"deinterlace",
"cpuSpriteRenderBW",
"cpuSpriteRenderLevel",
"cpuCLUTRender",
"gpuTargetCLUT",
"gpuPaletteConversion",
@ -631,6 +632,9 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
case GSHWFixId::CPUSpriteRenderBW:
return (config.UserHacks_CPUSpriteRenderBW == value);
case GSHWFixId::CPUSpriteRenderLevel:
return (config.UserHacks_CPUSpriteRenderLevel == value);
case GSHWFixId::CPUCLUTRender:
return (config.UserHacks_CPUCLUTRender == value);
@ -814,6 +818,10 @@ u32 GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
config.UserHacks_CPUSpriteRenderBW = value;
break;
case GSHWFixId::CPUSpriteRenderLevel:
config.UserHacks_CPUSpriteRenderLevel = value;
break;
case GSHWFixId::CPUCLUTRender:
config.UserHacks_CPUCLUTRender = value;
break;

View File

@ -87,6 +87,7 @@ namespace GameDatabaseSchema
TexturePreloading,
Deinterlace,
CPUSpriteRenderBW,
CPUSpriteRenderLevel,
CPUCLUTRender,
GPUTargetCLUT,
GPUPaletteConversion,

View File

@ -524,6 +524,7 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
OpEqu(UserHacks_TCOffsetX) &&
OpEqu(UserHacks_TCOffsetY) &&
OpEqu(UserHacks_CPUSpriteRenderBW) &&
OpEqu(UserHacks_CPUSpriteRenderLevel) &&
OpEqu(UserHacks_CPUCLUTRender) &&
OpEqu(UserHacks_GPUTargetCLUTMode) &&
OpEqu(UserHacks_TextureInsideRt) &&
@ -717,6 +718,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
GSSettingIntEx(UserHacks_TCOffsetX, "UserHacks_TCOffsetX");
GSSettingIntEx(UserHacks_TCOffsetY, "UserHacks_TCOffsetY");
GSSettingIntEx(UserHacks_CPUSpriteRenderBW, "UserHacks_CPUSpriteRenderBW");
GSSettingIntEx(UserHacks_CPUSpriteRenderLevel, "UserHacks_CPUSpriteRenderLevel");
GSSettingIntEx(UserHacks_CPUCLUTRender, "UserHacks_CPUCLUTRender");
GSSettingIntEnumEx(UserHacks_GPUTargetCLUTMode, "UserHacks_GPUTargetCLUTMode");
GSSettingIntEnumEx(TriFilter, "TriFilter");
@ -792,6 +794,7 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
UserHacks_TCOffsetX = 0;
UserHacks_TCOffsetY = 0;
UserHacks_CPUSpriteRenderBW = 0;
UserHacks_CPUSpriteRenderLevel = 0;
UserHacks_CPUCLUTRender = 0;
UserHacks_GPUTargetCLUTMode = GSGPUTargetCLUTMode::Disabled;
SkipDrawStart = 0;