GSdx: Add CPU Frame buffer Conversion Hack

Add HW Hack that enables Framebuffer Conversion on the CPU instead of the GPU.
Can fix broken textures on games but at the cost of slower performance.
List of games: Harry Potter games, FIFA Street games.
Games like Call of Duty, Kung fu Panda might also be affected as well as others
especially on Direct3D.
Add HW Hack GUI option on Windows/Linux for 4-bit and 8-bit Framebuffer conversion hack
named "Frame Buffer Conversion".
This commit is contained in:
lightningterror 2017-10-04 23:50:36 +02:00 committed by Gregory Hainaut
parent 574e0a7531
commit 1cbd4c5387
9 changed files with 41 additions and 25 deletions

View File

@ -380,7 +380,7 @@ void populate_shader_table(GtkWidget* shader_table)
InsertWidgetInTable(shader_table , shaderfx_check); InsertWidgetInTable(shader_table , shaderfx_check);
InsertWidgetInTable(shader_table , shader_label , shader); InsertWidgetInTable(shader_table , shader_label , shader);
InsertWidgetInTable(shader_table , shader_conf_label , shader_conf); InsertWidgetInTable(shader_table , shader_conf_label , shader_conf);
InsertWidgetInTable(shader_table , tv_shader_label, tv_shader); InsertWidgetInTable(shader_table , tv_shader_label , tv_shader);
} }
void populate_hack_table(GtkWidget* hack_table) void populate_hack_table(GtkWidget* hack_table)
@ -396,6 +396,7 @@ void populate_hack_table(GtkWidget* hack_table)
GtkWidget* preload_gs_check = CreateCheckBox("Preload Frame", "preload_frame_with_gs_data"); GtkWidget* preload_gs_check = CreateCheckBox("Preload Frame", "preload_frame_with_gs_data");
GtkWidget* hack_fast_inv = CreateCheckBox("Fast Texture Invalidation", "UserHacks_DisablePartialInvalidation"); GtkWidget* hack_fast_inv = CreateCheckBox("Fast Texture Invalidation", "UserHacks_DisablePartialInvalidation");
GtkWidget* hack_depth_check = CreateCheckBox("Disable Depth Emulation", "UserHacks_DisableDepthSupport"); GtkWidget* hack_depth_check = CreateCheckBox("Disable Depth Emulation", "UserHacks_DisableDepthSupport");
GtkWidget* hack_cpu_fbcv = CreateCheckBox("Frame Buffer Conversion", "UserHacks_CPU_FB_Conversion");
GtkWidget* hack_auto_flush = CreateCheckBox("Auto Flush Primitives", "UserHacks_AutoFlush"); GtkWidget* hack_auto_flush = CreateCheckBox("Auto Flush Primitives", "UserHacks_AutoFlush");
GtkWidget* hack_unscale_prim = CreateCheckBox("Unscale Point&Line Primitives", "UserHacks_unscale_point_line"); GtkWidget* hack_unscale_prim = CreateCheckBox("Unscale Point&Line Primitives", "UserHacks_unscale_point_line");
GtkWidget* hack_merge_sprite = CreateCheckBox("Merge Sprite", "UserHacks_merge_pp_sprite"); GtkWidget* hack_merge_sprite = CreateCheckBox("Merge Sprite", "UserHacks_merge_pp_sprite");
@ -422,6 +423,7 @@ void populate_hack_table(GtkWidget* hack_table)
AddTooltip(preload_gs_check, IDC_PRELOAD_GS); AddTooltip(preload_gs_check, IDC_PRELOAD_GS);
AddTooltip(hack_fast_inv, IDC_FAST_TC_INV); AddTooltip(hack_fast_inv, IDC_FAST_TC_INV);
AddTooltip(hack_depth_check, IDC_TC_DEPTH); AddTooltip(hack_depth_check, IDC_TC_DEPTH);
AddTooltip(hack_cpu_fbcv, IDC_CPU_FB_CONVERSION);
AddTooltip(hack_auto_flush, IDC_AUTO_FLUSH); AddTooltip(hack_auto_flush, IDC_AUTO_FLUSH);
AddTooltip(hack_unscale_prim, IDC_UNSCALE_POINT_LINE); AddTooltip(hack_unscale_prim, IDC_UNSCALE_POINT_LINE);
AddTooltip(hack_merge_sprite, IDC_MERGE_PP_SPRITE); AddTooltip(hack_merge_sprite, IDC_MERGE_PP_SPRITE);
@ -434,7 +436,7 @@ void populate_hack_table(GtkWidget* hack_table)
// Hack // Hack
InsertWidgetInTable(hack_table , hack_fast_inv , hack_auto_flush); InsertWidgetInTable(hack_table , hack_fast_inv , hack_auto_flush);
InsertWidgetInTable(hack_table , hack_depth_check , preload_gs_check); InsertWidgetInTable(hack_table , hack_depth_check , preload_gs_check);
InsertWidgetInTable(hack_table , hack_wrap_mem); InsertWidgetInTable(hack_table , hack_wrap_mem , hack_cpu_fbcv);
// Upscaling hack // Upscaling hack
InsertWidgetInTable(hack_table , hack_wild_check , align_sprite_check); InsertWidgetInTable(hack_table , hack_wild_check , align_sprite_check);
InsertWidgetInTable(hack_table , hack_unscale_prim , hack_merge_sprite); InsertWidgetInTable(hack_table , hack_unscale_prim , hack_merge_sprite);
@ -448,19 +450,19 @@ void populate_hack_table(GtkWidget* hack_table)
void populate_main_table(GtkWidget* main_table) void populate_main_table(GtkWidget* main_table)
{ {
GtkWidget* render_label = left_label("Renderer:"); GtkWidget* render_label = left_label("Renderer:");
GtkWidget* render_combo_box = CreateComboBoxFromVector(theApp.m_gs_renderers, "Renderer"); GtkWidget* render_combo_box = CreateComboBoxFromVector(theApp.m_gs_renderers, "Renderer");
GtkWidget* interlace_label = left_label("Interlacing (F5):"); GtkWidget* interlace_label = left_label("Interlacing (F5):");
GtkWidget* interlace_combo_box = CreateComboBoxFromVector(theApp.m_gs_interlace, "interlace"); GtkWidget* interlace_combo_box = CreateComboBoxFromVector(theApp.m_gs_interlace, "interlace");
GtkWidget* filter_label = left_label("Texture Filtering:"); GtkWidget* filter_label = left_label("Texture Filtering:");
GtkWidget* filter_combo_box = CreateComboBoxFromVector(theApp.m_gs_bifilter, "filter"); GtkWidget* filter_combo_box = CreateComboBoxFromVector(theApp.m_gs_bifilter, "filter");
AddTooltip(filter_label, filter_combo_box, IDC_FILTER); AddTooltip(filter_label, filter_combo_box, IDC_FILTER);
s_table_line = 0; s_table_line = 0;
InsertWidgetInTable(main_table, render_label, render_combo_box); InsertWidgetInTable(main_table, render_label, render_combo_box);
InsertWidgetInTable(main_table, interlace_label, interlace_combo_box); InsertWidgetInTable(main_table, interlace_label, interlace_combo_box);
InsertWidgetInTable(main_table, filter_label , filter_combo_box); InsertWidgetInTable(main_table, filter_label, filter_combo_box);
} }
void populate_debug_table(GtkWidget* debug_table) void populate_debug_table(GtkWidget* debug_table)

View File

@ -122,6 +122,13 @@ const char* dialog_message(int ID, bool* updateText) {
case IDC_TC_DEPTH: case IDC_TC_DEPTH:
return "Disable the support of Depth buffer in the texture cache.\n" return "Disable the support of Depth buffer in the texture cache.\n"
"It can help to increase speed but it will likely create various glitches."; "It can help to increase speed but it will likely create various glitches.";
case IDC_CPU_FB_CONVERSION:
return "Convert 4-bit and 8-bit frame buffer on the CPU instead of the GPU.\n\n"
"The hack can fix glitches in some games.\n"
"Harry Potter games (Direct3D and OpenGL).\n"
"FIFA Street games (Direct3D).\n"
"Other games might also benefit from this hack especially on Direct3D.\n\n"
"Note: This hack has an impact on performance.\n";
case IDC_AFCOMBO: case IDC_AFCOMBO:
return "Reduces texture aliasing at extreme viewing angles. High performance impact."; return "Reduces texture aliasing at extreme viewing angles. High performance impact.";
case IDC_AA1: case IDC_AA1:

View File

@ -63,6 +63,7 @@ enum {
IDC_ACCURATE_BLEND_UNIT, IDC_ACCURATE_BLEND_UNIT,
IDC_ACCURATE_DATE, IDC_ACCURATE_DATE,
IDC_TC_DEPTH, IDC_TC_DEPTH,
IDC_CPU_FB_CONVERSION,
IDC_CRC_LEVEL, IDC_CRC_LEVEL,
IDC_AFCOMBO, IDC_AFCOMBO,
IDC_AA1, IDC_AA1,

View File

@ -698,6 +698,7 @@ void GSHacksDlg::OnInit()
CheckDlgButton(m_hWnd, IDC_PRELOAD_GS, theApp.GetConfigB("preload_frame_with_gs_data")); CheckDlgButton(m_hWnd, IDC_PRELOAD_GS, theApp.GetConfigB("preload_frame_with_gs_data"));
CheckDlgButton(m_hWnd, IDC_ALIGN_SPRITE, theApp.GetConfigB("UserHacks_align_sprite_X")); CheckDlgButton(m_hWnd, IDC_ALIGN_SPRITE, theApp.GetConfigB("UserHacks_align_sprite_X"));
CheckDlgButton(m_hWnd, IDC_TC_DEPTH, theApp.GetConfigB("UserHacks_DisableDepthSupport")); CheckDlgButton(m_hWnd, IDC_TC_DEPTH, theApp.GetConfigB("UserHacks_DisableDepthSupport"));
CheckDlgButton(m_hWnd, IDC_CPU_FB_CONVERSION, theApp.GetConfigB("UserHacks_CPU_FB_Conversion"));
CheckDlgButton(m_hWnd, IDC_FAST_TC_INV, theApp.GetConfigB("UserHacks_DisablePartialInvalidation")); CheckDlgButton(m_hWnd, IDC_FAST_TC_INV, theApp.GetConfigB("UserHacks_DisablePartialInvalidation"));
CheckDlgButton(m_hWnd, IDC_AUTO_FLUSH, theApp.GetConfigB("UserHacks_AutoFlush")); CheckDlgButton(m_hWnd, IDC_AUTO_FLUSH, theApp.GetConfigB("UserHacks_AutoFlush"));
CheckDlgButton(m_hWnd, IDC_UNSCALE_POINT_LINE, theApp.GetConfigB("UserHacks_unscale_point_line")); CheckDlgButton(m_hWnd, IDC_UNSCALE_POINT_LINE, theApp.GetConfigB("UserHacks_unscale_point_line"));
@ -765,6 +766,7 @@ void GSHacksDlg::OnInit()
AddTooltip(IDC_TCOFFSETY2); AddTooltip(IDC_TCOFFSETY2);
AddTooltip(IDC_PRELOAD_GS); AddTooltip(IDC_PRELOAD_GS);
AddTooltip(IDC_TC_DEPTH); AddTooltip(IDC_TC_DEPTH);
AddTooltip(IDC_CPU_FB_CONVERSION);
AddTooltip(IDC_FAST_TC_INV); AddTooltip(IDC_FAST_TC_INV);
AddTooltip(IDC_AUTO_FLUSH); AddTooltip(IDC_AUTO_FLUSH);
AddTooltip(IDC_UNSCALE_POINT_LINE); AddTooltip(IDC_UNSCALE_POINT_LINE);
@ -823,6 +825,7 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
theApp.SetConfig("preload_frame_with_gs_data", (int)IsDlgButtonChecked(m_hWnd, IDC_PRELOAD_GS)); theApp.SetConfig("preload_frame_with_gs_data", (int)IsDlgButtonChecked(m_hWnd, IDC_PRELOAD_GS));
theApp.SetConfig("Userhacks_align_sprite_X", (int)IsDlgButtonChecked(m_hWnd, IDC_ALIGN_SPRITE)); theApp.SetConfig("Userhacks_align_sprite_X", (int)IsDlgButtonChecked(m_hWnd, IDC_ALIGN_SPRITE));
theApp.SetConfig("UserHacks_DisableDepthSupport", (int)IsDlgButtonChecked(m_hWnd, IDC_TC_DEPTH)); theApp.SetConfig("UserHacks_DisableDepthSupport", (int)IsDlgButtonChecked(m_hWnd, IDC_TC_DEPTH));
theApp.SetConfig("UserHacks_CPU_FB_Conversion", (int)IsDlgButtonChecked(m_hWnd, IDC_CPU_FB_CONVERSION));
theApp.SetConfig("UserHacks_DisablePartialInvalidation", (int)IsDlgButtonChecked(m_hWnd, IDC_FAST_TC_INV)); theApp.SetConfig("UserHacks_DisablePartialInvalidation", (int)IsDlgButtonChecked(m_hWnd, IDC_FAST_TC_INV));
theApp.SetConfig("UserHacks_AutoFlush", (int)IsDlgButtonChecked(m_hWnd, IDC_AUTO_FLUSH)); theApp.SetConfig("UserHacks_AutoFlush", (int)IsDlgButtonChecked(m_hWnd, IDC_AUTO_FLUSH));
theApp.SetConfig("UserHacks_unscale_point_line", (int)IsDlgButtonChecked(m_hWnd, IDC_UNSCALE_POINT_LINE)); theApp.SetConfig("UserHacks_unscale_point_line", (int)IsDlgButtonChecked(m_hWnd, IDC_UNSCALE_POINT_LINE));

View File

@ -38,6 +38,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r)
m_preload_frame = theApp.GetConfigB("preload_frame_with_gs_data"); m_preload_frame = theApp.GetConfigB("preload_frame_with_gs_data");
m_disable_partial_invalidation = theApp.GetConfigB("UserHacks_DisablePartialInvalidation"); m_disable_partial_invalidation = theApp.GetConfigB("UserHacks_DisablePartialInvalidation");
m_can_convert_depth = !theApp.GetConfigB("UserHacks_DisableDepthSupport"); 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_texture_inside_rt = theApp.GetConfigB("UserHacks_TextureInsideRt");
m_wrap_gs_mem = theApp.GetConfigB("wrap_gs_mem"); m_wrap_gs_mem = theApp.GetConfigB("wrap_gs_mem");
} else { } else {
@ -46,6 +47,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r)
m_preload_frame = false; m_preload_frame = false;
m_disable_partial_invalidation = false; m_disable_partial_invalidation = false;
m_can_convert_depth = true; m_can_convert_depth = true;
m_cpu_fb_conversion = false;
m_texture_inside_rt = false; m_texture_inside_rt = false;
m_wrap_gs_mem = false; m_wrap_gs_mem = false;
} }
@ -268,25 +270,21 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
uint32 t_psm = (t->m_dirty_alpha) ? t->m_TEX0.PSM & ~0x1 : t->m_TEX0.PSM; uint32 t_psm = (t->m_dirty_alpha) ? t->m_TEX0.PSM & ~0x1 : t->m_TEX0.PSM;
if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm)) { if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm)) {
if (!s_IS_OPENGL && (psm == PSM_PSMT8)) { // It is a complex to convert the code in shader. As a reference, let's do it on the CPU, it will be slow but
// OpenGL can convert the texture directly in the GPU. Not sure we want to keep this // 1/ it just works :)
// code for DX. It fixes effect but it is slow (MGS3) // 2/ even with upscaling
// 3/ for both DX and OpenGL
// It is a complex to convert the code in shader. As a reference, let's do it on the CPU, it will if (m_cpu_fb_conversion && (psm == PSM_PSMT4 || psm == PSM_PSMT8))
// be slow but // Forces 4-bit and 8-bit frame buffer conversion to be done on the CPU instead of the GPU, but performance will be slower.
// 1/ it just works :) // There is no dedicated shader to handle 4-bit conversion.
// 2/ even with upscaling // Direct3D doesn't support 8-bit fb conversion, OpenGL does support it but it doesn't render some corner cases properly.
// 3/ for both DX and OpenGL // The hack can fix glitches in some games.
// Harry Potter games (Direct3D and OpenGL).
// Gregory: to avoid a massive slow down for nothing, let's only enable // FIFA Street games (Direct3D).
// this code when CRC is below the FULL level // Other games might also benefit from this hack especially on Direct3D.
if (m_crc_hack_level < CRCHackLevel::Full) Read(t, t->m_valid);
Read(t, t->m_valid); else
else
dst = t;
} else {
dst = t; dst = t;
}
break; break;
@ -298,6 +296,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
dst = t; dst = t;
break; break;
} else if (m_texture_inside_rt && psm == PSM_PSMCT32 && bw == 1 && bp_end < t->m_end_block && t->m_TEX0.TBP0 < bp) { } else if (m_texture_inside_rt && psm == PSM_PSMCT32 && bw == 1 && bp_end < t->m_end_block && t->m_TEX0.TBP0 < bp) {
// Note bw == 1 until we find a generic formulae below // Note bw == 1 until we find a generic formulae below
dst = t; dst = t;

View File

@ -130,6 +130,7 @@ protected:
bool m_preload_frame; bool m_preload_frame;
uint8* m_temp; uint8* m_temp;
bool m_can_convert_depth; bool m_can_convert_depth;
bool m_cpu_fb_conversion;
CRCHackLevel m_crc_hack_level; CRCHackLevel m_crc_hack_level;
static bool m_disable_partial_invalidation; static bool m_disable_partial_invalidation;
bool m_texture_inside_rt; bool m_texture_inside_rt;

View File

@ -429,6 +429,7 @@ void GSdxApp::Init()
m_default_configuration["UserHacks_AlphaStencil"] = "0"; m_default_configuration["UserHacks_AlphaStencil"] = "0";
m_default_configuration["UserHacks_AutoFlush"] = "0"; m_default_configuration["UserHacks_AutoFlush"] = "0";
m_default_configuration["UserHacks_DisableDepthSupport"] = "0"; m_default_configuration["UserHacks_DisableDepthSupport"] = "0";
m_default_configuration["UserHacks_CPU_FB_Conversion"] = "0";
m_default_configuration["UserHacks_DisableGsMemClear"] = "0"; m_default_configuration["UserHacks_DisableGsMemClear"] = "0";
m_default_configuration["UserHacks_DisablePartialInvalidation"] = "0"; m_default_configuration["UserHacks_DisablePartialInvalidation"] = "0";
m_default_configuration["UserHacks_HalfPixelOffset"] = "0"; m_default_configuration["UserHacks_HalfPixelOffset"] = "0";

View File

@ -142,6 +142,7 @@ BEGIN
CONTROL "Alpha",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,71,34,8 CONTROL "Alpha",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,71,34,8
CONTROL "Alpha Stencil",IDC_ALPHASTENCIL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,71,57,8 CONTROL "Alpha Stencil",IDC_ALPHASTENCIL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,71,57,8
CONTROL "Disable Depth Emulation",IDC_TC_DEPTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,84,92,8 CONTROL "Disable Depth Emulation",IDC_TC_DEPTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,84,92,8
CONTROL "Frame Buffer Conversion",IDC_CPU_FB_CONVERSION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,84,92,8
RTEXT "MSAA:",IDC_MSAA_TEXT,54,99,22,8 RTEXT "MSAA:",IDC_MSAA_TEXT,54,99,22,8
COMBOBOX IDC_MSAACB,80,96,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_MSAACB,80,96,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
RTEXT "Trilinear Filtering:",IDC_TRI_FILTER_TEXT,16,114,60,8 RTEXT "Trilinear Filtering:",IDC_TRI_FILTER_TEXT,16,114,60,8

View File

@ -103,6 +103,7 @@
#define IDC_TRI_FILTER_TEXT 2124 #define IDC_TRI_FILTER_TEXT 2124
#define IDC_UNSCALE_POINT_LINE 2125 #define IDC_UNSCALE_POINT_LINE 2125
#define IDC_MERGE_PP_SPRITE 2126 #define IDC_MERGE_PP_SPRITE 2126
#define IDC_CPU_FB_CONVERSION 2127
// Shader: // Shader:
#define IDC_SHADEBOOST 2140 #define IDC_SHADEBOOST 2140
#define IDC_FXAA 2141 #define IDC_FXAA 2141