Skip to content

Commit

Permalink
GPU: Make perspective-correct color interpolation toggleable
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Oct 3, 2022
1 parent 6af5a24 commit 971bba0
Show file tree
Hide file tree
Showing 20 changed files with 145 additions and 80 deletions.
15 changes: 15 additions & 0 deletions data/resources/database/gamesettings.ini
Expand Up @@ -109,6 +109,21 @@ DisableUpscaling = true
DisablePGXP = true


# SCUS-94244 (Crash Bandicoot - Warped (USA))
[SCUS-94244]
DisablePGXPColorCorrection = true


# SCES-01420 (Crash Bandicoot 3 - Warped (Europe) (En,Fr,De,Es,It))
[SCES-01420]
DisablePGXPColorCorrection = true


# SCPS-10073 (Crash Bandicoot 3 - Buttobi! Sekai Isshuu (Japan))
[SCPS-10073]
DisablePGXPColorCorrection = true


# Pop'n Music 6 (Japan) (SLPM-87089)
[SLPM-87089]
ForceInterlacing = true
Expand Down
20 changes: 17 additions & 3 deletions src/core/game_database.cpp
Expand Up @@ -28,7 +28,7 @@ namespace GameDatabase {
enum : u32
{
GAME_DATABASE_CACHE_SIGNATURE = 0x45434C48,
GAME_DATABASE_CACHE_VERSION = 1
GAME_DATABASE_CACHE_VERSION = 2,
};

static Entry* GetMutableEntry(const std::string_view& serial);
Expand Down Expand Up @@ -56,7 +56,8 @@ std::array<std::pair<const char*, const char*>, static_cast<u32>(GameDatabase::T
{"DisableWidescreen", TRANSLATABLE("GameSettingsTrait", "Disable Widescreen")},
{"DisablePGXP", TRANSLATABLE("GameSettingsTrait", "Disable PGXP")},
{"DisablePGXPCulling", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Culling")},
{"DisablePGXPTextureCorrection", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Texture Correction")},
{"DisablePGXPTextureCorrection", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Perspective Correct Textures")},
{"DisablePGXPColorCorrection", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Perspective Correct Colors")},
{"DisablePGXPDepthBuffer", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Depth Buffer")},
{"ForcePGXPVertexCache", TRANSLATABLE("GameSettingsTrait", "Force PGXP Vertex Cache")},
{"ForcePGXPCPUMode", TRANSLATABLE("GameSettingsTrait", "Force PGXP CPU Mode")},
Expand Down Expand Up @@ -364,12 +365,25 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
{
Host::AddKeyedOSDMessage(
"gamedb_disable_pgxp_texture",
Host::TranslateStdString("OSDMessage", "PGXP texture correction disabled by game settings."), osd_duration);
Host::TranslateStdString("OSDMessage", "PGXP perspective corrected textures disabled by game settings."), osd_duration);
}

settings.gpu_pgxp_texture_correction = false;
}

if (HasTrait(Trait::DisablePGXPColorCorrection))
{
if (display_osd_messages && settings.gpu_pgxp_enable && settings.gpu_pgxp_texture_correction &&
settings.gpu_pgxp_color_correction)
{
Host::AddKeyedOSDMessage(
"gamedb_disable_pgxp_texture",
Host::TranslateStdString("OSDMessage", "PGXP perspective corrected colors disabled by game settings."), osd_duration);
}

settings.gpu_pgxp_color_correction = false;
}

if (HasTrait(Trait::ForcePGXPVertexCache))
{
if (display_osd_messages && settings.gpu_pgxp_enable && !settings.gpu_pgxp_vertex_cache)
Expand Down
1 change: 1 addition & 0 deletions src/core/game_database.h
Expand Up @@ -37,6 +37,7 @@ enum class Trait : u32
DisablePGXP,
DisablePGXPCulling,
DisablePGXPTextureCorrection,
DisablePGXPColorCorrection,
DisablePGXPDepthBuffer,
ForcePGXPVertexCache,
ForcePGXPCPUMode,
Expand Down
11 changes: 10 additions & 1 deletion src/core/gpu_hw.cpp
Expand Up @@ -30,6 +30,11 @@ ALWAYS_INLINE static bool ShouldUseUVLimits()
return g_settings.gpu_pgxp_enable || g_settings.gpu_texture_filter != GPUTextureFilter::Nearest;
}

ALWAYS_INLINE static bool ShouldDisableColorPerspective()
{
return g_settings.gpu_pgxp_enable && g_settings.gpu_pgxp_texture_correction && !g_settings.gpu_pgxp_color_correction;
}

GPU_HW::GPU_HW() : GPU()
{
m_vram_ptr = m_vram_shadow.data();
Expand Down Expand Up @@ -64,6 +69,7 @@ bool GPU_HW::Initialize()
m_using_uv_limits = ShouldUseUVLimits();
m_chroma_smoothing = g_settings.gpu_24bit_chroma_smoothing;
m_downsample_mode = GetDownsampleMode(m_resolution_scale);
m_disable_color_perspective = ShouldDisableColorPerspective();

if (m_multisamples != g_settings.gpu_multisamples)
{
Expand Down Expand Up @@ -140,6 +146,7 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
const bool per_sample_shading = g_settings.gpu_per_sample_shading && m_supports_per_sample_shading;
const GPUDownsampleMode downsample_mode = GetDownsampleMode(resolution_scale);
const bool use_uv_limits = ShouldUseUVLimits();
const bool disable_color_perspective = ShouldDisableColorPerspective();

*framebuffer_changed =
(m_resolution_scale != resolution_scale || m_multisamples != multisamples || m_downsample_mode != downsample_mode);
Expand All @@ -148,7 +155,8 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
m_true_color != g_settings.gpu_true_color || m_per_sample_shading != per_sample_shading ||
m_scaled_dithering != g_settings.gpu_scaled_dithering || m_texture_filtering != g_settings.gpu_texture_filter ||
m_using_uv_limits != use_uv_limits || m_chroma_smoothing != g_settings.gpu_24bit_chroma_smoothing ||
m_downsample_mode != downsample_mode || m_pgxp_depth_buffer != g_settings.UsingPGXPDepthBuffer());
m_downsample_mode != downsample_mode || m_pgxp_depth_buffer != g_settings.UsingPGXPDepthBuffer() ||
m_disable_color_perspective != disable_color_perspective);

if (m_resolution_scale != resolution_scale)
{
Expand Down Expand Up @@ -184,6 +192,7 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
m_using_uv_limits = use_uv_limits;
m_chroma_smoothing = g_settings.gpu_24bit_chroma_smoothing;
m_downsample_mode = downsample_mode;
m_disable_color_perspective = disable_color_perspective;

if (!m_supports_dual_source_blend && TextureFilterRequiresDualSourceBlend(m_texture_filtering))
m_texture_filtering = GPUTextureFilter::Nearest;
Expand Down
1 change: 1 addition & 0 deletions src/core/gpu_hw.h
Expand Up @@ -377,6 +377,7 @@ class GPU_HW : public GPU
BitField<u8, bool, 3, 1> m_per_sample_shading;
BitField<u8, bool, 4, 1> m_scaled_dithering;
BitField<u8, bool, 5, 1> m_chroma_smoothing;
BitField<u8, bool, 6, 1> m_disable_color_perspective;

u8 bits = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion src/core/gpu_hw_d3d11.cpp
Expand Up @@ -506,7 +506,7 @@ bool GPU_HW_D3D11::CompileShaders()

GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
m_pgxp_depth_buffer, m_supports_dual_source_blend);
m_pgxp_depth_buffer, m_disable_color_perspective, m_supports_dual_source_blend);

ShaderCompileProgressTracker progress("Compiling Shaders",
1 + 1 + 2 + (4 * 9 * 2 * 2) + 1 + (2 * 2) + 4 + (2 * 3) + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/core/gpu_hw_d3d12.cpp
Expand Up @@ -416,7 +416,7 @@ bool GPU_HW_D3D12::CompilePipelines()

GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
m_pgxp_depth_buffer, m_supports_dual_source_blend);
m_pgxp_depth_buffer, m_disable_color_perspective, m_supports_dual_source_blend);

ShaderCompileProgressTracker progress("Compiling Pipelines", 2 + (4 * 9 * 2 * 2) + (2 * 4 * 5 * 9 * 2 * 2) + 1 +
(2 * 2) + 2 + 2 + 1 + 1 + (2 * 3) + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/core/gpu_hw_opengl.cpp
Expand Up @@ -518,7 +518,7 @@ bool GPU_HW_OpenGL::CompilePrograms()
const bool use_binding_layout = GPU_HW_ShaderGen::UseGLSLBindingLayout();
GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
m_pgxp_depth_buffer, m_supports_dual_source_blend);
m_pgxp_depth_buffer, m_disable_color_perspective, m_supports_dual_source_blend);

ShaderCompileProgressTracker progress("Compiling Programs", (4 * 9 * 2 * 2) + (2 * 3) + (2 * 2) + 1 + 1 + 1 + 1 + 1);

Expand Down
20 changes: 11 additions & 9 deletions src/core/gpu_hw_shadergen.cpp
Expand Up @@ -5,11 +5,11 @@
GPU_HW_ShaderGen::GPU_HW_ShaderGen(RenderAPI render_api, u32 resolution_scale, u32 multisamples,
bool per_sample_shading, bool true_color, bool scaled_dithering,
GPUTextureFilter texture_filtering, bool uv_limits, bool pgxp_depth,
bool supports_dual_source_blend)
bool disable_color_perspective, bool supports_dual_source_blend)
: ShaderGen(render_api, supports_dual_source_blend), m_resolution_scale(resolution_scale),
m_multisamples(multisamples), m_per_sample_shading(per_sample_shading), m_true_color(true_color),
m_scaled_dithering(scaled_dithering), m_texture_filter(texture_filtering), m_uv_limits(uv_limits),
m_pgxp_depth(pgxp_depth)
m_pgxp_depth(pgxp_depth), m_disable_color_perspective(disable_color_perspective)
{
}

Expand Down Expand Up @@ -109,19 +109,19 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
DeclareVertexEntryPoint(
ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage", "float4 a_uv_limits"}, 1, 1,
{{"nointerpolation", "uint4 v_texpage"}, {"nointerpolation", "float4 v_uv_limits"}}, false, "", UsingMSAA(),
UsingPerSampleShading());
UsingPerSampleShading(), m_disable_color_perspective);
}
else
{
DeclareVertexEntryPoint(ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage"}, 1, 1,
{{"nointerpolation", "uint4 v_texpage"}}, false, "", UsingMSAA(),
UsingPerSampleShading());
{{"nointerpolation", "uint4 v_texpage"}}, false, "", UsingMSAA(), UsingPerSampleShading(),
m_disable_color_perspective);
}
}
else
{
DeclareVertexEntryPoint(ss, {"float4 a_pos", "float4 a_col0"}, 1, 0, {}, false, "", UsingMSAA(),
UsingPerSampleShading());
UsingPerSampleShading(), m_disable_color_perspective);
}

ss << R"(
Expand Down Expand Up @@ -805,18 +805,20 @@ float4 SampleFromVRAM(uint4 texpage, float2 coords)
{
DeclareFragmentEntryPoint(ss, 1, 1,
{{"nointerpolation", "uint4 v_texpage"}, {"nointerpolation", "float4 v_uv_limits"}},
true, use_dual_source ? 2 : 1, !m_pgxp_depth, UsingMSAA(), UsingPerSampleShading());
true, use_dual_source ? 2 : 1, !m_pgxp_depth, UsingMSAA(), UsingPerSampleShading(),
false, m_disable_color_perspective);
}
else
{
DeclareFragmentEntryPoint(ss, 1, 1, {{"nointerpolation", "uint4 v_texpage"}}, true, use_dual_source ? 2 : 1,
!m_pgxp_depth, UsingMSAA(), UsingPerSampleShading());
!m_pgxp_depth, UsingMSAA(), UsingPerSampleShading(), false,
m_disable_color_perspective);
}
}
else
{
DeclareFragmentEntryPoint(ss, 1, 0, {}, true, use_dual_source ? 2 : 1, !m_pgxp_depth, UsingMSAA(),
UsingPerSampleShading());
UsingPerSampleShading(), false, m_disable_color_perspective);
}

ss << R"(
Expand Down
3 changes: 2 additions & 1 deletion src/core/gpu_hw_shadergen.h
Expand Up @@ -7,7 +7,7 @@ class GPU_HW_ShaderGen : public ShaderGen
public:
GPU_HW_ShaderGen(RenderAPI render_api, u32 resolution_scale, u32 multisamples, bool per_sample_shading,
bool true_color, bool scaled_dithering, GPUTextureFilter texture_filtering, bool uv_limits,
bool pgxp_depth, bool supports_dual_source_blend);
bool pgxp_depth, bool disable_color_perspective, bool supports_dual_source_blend);
~GPU_HW_ShaderGen();

std::string GenerateBatchVertexShader(bool textured);
Expand Down Expand Up @@ -42,4 +42,5 @@ class GPU_HW_ShaderGen : public ShaderGen
GPUTextureFilter m_texture_filter;
bool m_uv_limits;
bool m_pgxp_depth;
bool m_disable_color_perspective;
};
2 changes: 1 addition & 1 deletion src/core/gpu_hw_vulkan.cpp
Expand Up @@ -923,7 +923,7 @@ bool GPU_HW_Vulkan::CompilePipelines()

GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
m_pgxp_depth_buffer, m_supports_dual_source_blend);
m_pgxp_depth_buffer, m_disable_color_perspective, m_supports_dual_source_blend);

ShaderCompileProgressTracker progress("Compiling Pipelines", 2 + (4 * 9 * 2 * 2) + (3 * 4 * 5 * 9 * 2 * 2) + 1 + 2 +
(2 * 2) + 2 + 1 + 1 + (2 * 3) + 1);
Expand Down
2 changes: 2 additions & 0 deletions src/core/settings.cpp
Expand Up @@ -222,6 +222,7 @@ void Settings::Load(SettingsInterface& si)
gpu_pgxp_enable = si.GetBoolValue("GPU", "PGXPEnable", false);
gpu_pgxp_culling = si.GetBoolValue("GPU", "PGXPCulling", true);
gpu_pgxp_texture_correction = si.GetBoolValue("GPU", "PGXPTextureCorrection", true);
gpu_pgxp_color_correction = si.GetBoolValue("GPU", "PGXPColorCorrection", false);
gpu_pgxp_vertex_cache = si.GetBoolValue("GPU", "PGXPVertexCache", false);
gpu_pgxp_cpu = si.GetBoolValue("GPU", "PGXPCPU", false);
gpu_pgxp_preserve_proj_fp = si.GetBoolValue("GPU", "PGXPPreserveProjFP", false);
Expand Down Expand Up @@ -437,6 +438,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetBoolValue("GPU", "PGXPEnable", gpu_pgxp_enable);
si.SetBoolValue("GPU", "PGXPCulling", gpu_pgxp_culling);
si.SetBoolValue("GPU", "PGXPTextureCorrection", gpu_pgxp_texture_correction);
si.SetBoolValue("GPU", "PGXPColorCorrection", gpu_pgxp_color_correction);
si.SetBoolValue("GPU", "PGXPVertexCache", gpu_pgxp_vertex_cache);
si.SetBoolValue("GPU", "PGXPCPU", gpu_pgxp_cpu);
si.SetBoolValue("GPU", "PGXPPreserveProjFP", gpu_pgxp_preserve_proj_fp);
Expand Down
1 change: 1 addition & 0 deletions src/core/settings.h
Expand Up @@ -108,6 +108,7 @@ struct Settings
bool gpu_pgxp_enable = false;
bool gpu_pgxp_culling = true;
bool gpu_pgxp_texture_correction = true;
bool gpu_pgxp_color_correction = false;
bool gpu_pgxp_vertex_cache = false;
bool gpu_pgxp_cpu = false;
bool gpu_pgxp_preserve_proj_fp = false;
Expand Down
35 changes: 18 additions & 17 deletions src/core/shadergen.cpp
Expand Up @@ -11,8 +11,7 @@
Log_SetChannel(ShaderGen);

ShaderGen::ShaderGen(RenderAPI render_api, bool supports_dual_source_blend)
: m_render_api(render_api),
m_glsl(render_api != RenderAPI::D3D11 && render_api != RenderAPI::D3D12),
: m_render_api(render_api), m_glsl(render_api != RenderAPI::D3D11 && render_api != RenderAPI::D3D12),
m_supports_dual_source_blend(supports_dual_source_blend), m_use_glsl_interface_blocks(false)
{
#if defined(WITH_OPENGL) || defined(WITH_VULKAN)
Expand All @@ -24,7 +23,7 @@ ShaderGen::ShaderGen(RenderAPI render_api, bool supports_dual_source_blend)

m_use_glsl_interface_blocks = (IsVulkan() || GLAD_GL_ES_VERSION_3_2 || GLAD_GL_VERSION_3_2);
m_use_glsl_binding_layout = (IsVulkan() || UseGLSLBindingLayout());

if (m_render_api == RenderAPI::OpenGL)
{
// SSAA with interface blocks is broken on AMD's OpenGL driver.
Expand Down Expand Up @@ -355,8 +354,8 @@ const char* ShaderGen::GetInterpolationQualifier(bool interface_block, bool cent
void ShaderGen::DeclareVertexEntryPoint(
std::stringstream& ss, const std::initializer_list<const char*>& attributes, u32 num_color_outputs,
u32 num_texcoord_outputs, const std::initializer_list<std::pair<const char*, const char*>>& additional_outputs,
bool declare_vertex_id /* = false */, const char* output_block_suffix /* = "" */,
bool centroid_interpolation /* = false */, bool sample_interpolation /* = false */)
bool declare_vertex_id /* = false */, const char* output_block_suffix /* = "" */, bool msaa /* = false */,
bool ssaa /* = false */, bool noperspective_color /* = false */)
{
if (m_glsl)
{
Expand All @@ -377,7 +376,7 @@ void ShaderGen::DeclareVertexEntryPoint(

if (m_use_glsl_interface_blocks)
{
const char* qualifier = GetInterpolationQualifier(true, centroid_interpolation, sample_interpolation, true);
const char* qualifier = GetInterpolationQualifier(true, msaa, ssaa, true);

if (IsVulkan())
ss << "layout(location = 0) ";
Expand All @@ -398,7 +397,7 @@ void ShaderGen::DeclareVertexEntryPoint(
}
else
{
const char* qualifier = GetInterpolationQualifier(false, centroid_interpolation, sample_interpolation, true);
const char* qualifier = GetInterpolationQualifier(false, msaa, ssaa, true);

for (u32 i = 0; i < num_color_outputs; i++)
ss << qualifier << "out float4 v_col" << i << ";\n";
Expand Down Expand Up @@ -427,7 +426,7 @@ void ShaderGen::DeclareVertexEntryPoint(
}
else
{
const char* qualifier = GetInterpolationQualifier(false, centroid_interpolation, sample_interpolation, true);
const char* qualifier = GetInterpolationQualifier(false, msaa, ssaa, true);

ss << "void main(\n";

Expand All @@ -442,7 +441,8 @@ void ShaderGen::DeclareVertexEntryPoint(
}

for (u32 i = 0; i < num_color_outputs; i++)
ss << " " << qualifier << "out float4 v_col" << i << " : COLOR" << i << ",\n";
ss << " " << qualifier << (noperspective_color ? "noperspective " : "") << "out float4 v_col" << i << " : COLOR"
<< i << ",\n";

for (u32 i = 0; i < num_texcoord_outputs; i++)
ss << " " << qualifier << "out float2 v_tex" << i << " : TEXCOORD" << i << ",\n";
Expand All @@ -463,21 +463,21 @@ void ShaderGen::DeclareFragmentEntryPoint(
std::stringstream& ss, u32 num_color_inputs, u32 num_texcoord_inputs,
const std::initializer_list<std::pair<const char*, const char*>>& additional_inputs,
bool declare_fragcoord /* = false */, u32 num_color_outputs /* = 1 */, bool depth_output /* = false */,
bool centroid_interpolation /* = false */, bool sample_interpolation /* = false */,
bool declare_sample_id /* = false */)
bool msaa /* = false */, bool ssaa /* = false */, bool declare_sample_id /* = false */,
bool noperspective_color /* = false */)
{
if (m_glsl)
{
if (m_use_glsl_interface_blocks)
{
const char* qualifier = GetInterpolationQualifier(true, centroid_interpolation, sample_interpolation, false);
const char* qualifier = GetInterpolationQualifier(true, msaa, ssaa, false);

if (IsVulkan())
ss << "layout(location = 0) ";

ss << "in VertexData {\n";
for (u32 i = 0; i < num_color_inputs; i++)
ss << " " << qualifier << "float4 v_col" << i << ";\n";
ss << " " << qualifier << (noperspective_color ? "noperspective " : "") << "float4 v_col" << i << ";\n";

for (u32 i = 0; i < num_texcoord_inputs; i++)
ss << " " << qualifier << "float2 v_tex" << i << ";\n";
Expand All @@ -491,10 +491,10 @@ void ShaderGen::DeclareFragmentEntryPoint(
}
else
{
const char* qualifier = GetInterpolationQualifier(false, centroid_interpolation, sample_interpolation, false);
const char* qualifier = GetInterpolationQualifier(false, msaa, ssaa, false);

for (u32 i = 0; i < num_color_inputs; i++)
ss << qualifier << "in float4 v_col" << i << ";\n";
ss << qualifier << (noperspective_color ? "noperspective " : "") << "in float4 v_col" << i << ";\n";

for (u32 i = 0; i < num_texcoord_inputs; i++)
ss << qualifier << "in float2 v_tex" << i << ";\n";
Expand Down Expand Up @@ -541,12 +541,13 @@ void ShaderGen::DeclareFragmentEntryPoint(
}
else
{
const char* qualifier = GetInterpolationQualifier(false, centroid_interpolation, sample_interpolation, false);
const char* qualifier = GetInterpolationQualifier(false, msaa, ssaa, false);

ss << "void main(\n";

for (u32 i = 0; i < num_color_inputs; i++)
ss << " " << qualifier << "in float4 v_col" << i << " : COLOR" << i << ",\n";
ss << " " << qualifier << (noperspective_color ? "noperspective " : "") << "in float4 v_col" << i << " : COLOR"
<< i << ",\n";

for (u32 i = 0; i < num_texcoord_inputs; i++)
ss << " " << qualifier << "in float2 v_tex" << i << " : TEXCOORD" << i << ",\n";
Expand Down

0 comments on commit 971bba0

Please sign in to comment.