From 1cbd4c53873e270a4a08cd302282df4cc1bc333f Mon Sep 17 00:00:00 2001 From: lightningterror Date: Wed, 4 Oct 2017 23:50:36 +0200 Subject: [PATCH] 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". --- plugins/GSdx/GSLinuxDialog.cpp | 16 ++++++++------- plugins/GSdx/GSSetting.cpp | 7 +++++++ plugins/GSdx/GSSetting.h | 1 + plugins/GSdx/GSSettingsDlg.cpp | 3 +++ plugins/GSdx/GSTextureCache.cpp | 35 ++++++++++++++++----------------- plugins/GSdx/GSTextureCache.h | 1 + plugins/GSdx/GSdx.cpp | 1 + plugins/GSdx/GSdx.rc | 1 + plugins/GSdx/resource.h | 1 + 9 files changed, 41 insertions(+), 25 deletions(-) diff --git a/plugins/GSdx/GSLinuxDialog.cpp b/plugins/GSdx/GSLinuxDialog.cpp index e56fcb8d6a..6bb04a27d0 100644 --- a/plugins/GSdx/GSLinuxDialog.cpp +++ b/plugins/GSdx/GSLinuxDialog.cpp @@ -380,7 +380,7 @@ void populate_shader_table(GtkWidget* shader_table) InsertWidgetInTable(shader_table , shaderfx_check); InsertWidgetInTable(shader_table , shader_label , shader); 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) @@ -396,6 +396,7 @@ void populate_hack_table(GtkWidget* hack_table) GtkWidget* preload_gs_check = CreateCheckBox("Preload Frame", "preload_frame_with_gs_data"); GtkWidget* hack_fast_inv = CreateCheckBox("Fast Texture Invalidation", "UserHacks_DisablePartialInvalidation"); 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_unscale_prim = CreateCheckBox("Unscale Point&Line Primitives", "UserHacks_unscale_point_line"); 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(hack_fast_inv, IDC_FAST_TC_INV); AddTooltip(hack_depth_check, IDC_TC_DEPTH); + AddTooltip(hack_cpu_fbcv, IDC_CPU_FB_CONVERSION); AddTooltip(hack_auto_flush, IDC_AUTO_FLUSH); AddTooltip(hack_unscale_prim, IDC_UNSCALE_POINT_LINE); AddTooltip(hack_merge_sprite, IDC_MERGE_PP_SPRITE); @@ -434,7 +436,7 @@ void populate_hack_table(GtkWidget* hack_table) // Hack InsertWidgetInTable(hack_table , hack_fast_inv , hack_auto_flush); 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 InsertWidgetInTable(hack_table , hack_wild_check , align_sprite_check); 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) { - GtkWidget* render_label = left_label("Renderer:"); - GtkWidget* render_combo_box = CreateComboBoxFromVector(theApp.m_gs_renderers, "Renderer"); + GtkWidget* render_label = left_label("Renderer:"); + GtkWidget* render_combo_box = CreateComboBoxFromVector(theApp.m_gs_renderers, "Renderer"); GtkWidget* interlace_label = left_label("Interlacing (F5):"); GtkWidget* interlace_combo_box = CreateComboBoxFromVector(theApp.m_gs_interlace, "interlace"); - GtkWidget* filter_label = left_label("Texture Filtering:"); - GtkWidget* filter_combo_box = CreateComboBoxFromVector(theApp.m_gs_bifilter, "filter"); + GtkWidget* filter_label = left_label("Texture Filtering:"); + GtkWidget* filter_combo_box = CreateComboBoxFromVector(theApp.m_gs_bifilter, "filter"); AddTooltip(filter_label, filter_combo_box, IDC_FILTER); s_table_line = 0; InsertWidgetInTable(main_table, render_label, render_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) diff --git a/plugins/GSdx/GSSetting.cpp b/plugins/GSdx/GSSetting.cpp index a3aea9aa56..e578d2315c 100644 --- a/plugins/GSdx/GSSetting.cpp +++ b/plugins/GSdx/GSSetting.cpp @@ -122,6 +122,13 @@ const char* dialog_message(int ID, bool* updateText) { case IDC_TC_DEPTH: 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."; + 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: return "Reduces texture aliasing at extreme viewing angles. High performance impact."; case IDC_AA1: diff --git a/plugins/GSdx/GSSetting.h b/plugins/GSdx/GSSetting.h index 8c0be88db7..90f8594672 100644 --- a/plugins/GSdx/GSSetting.h +++ b/plugins/GSdx/GSSetting.h @@ -63,6 +63,7 @@ enum { IDC_ACCURATE_BLEND_UNIT, IDC_ACCURATE_DATE, IDC_TC_DEPTH, + IDC_CPU_FB_CONVERSION, IDC_CRC_LEVEL, IDC_AFCOMBO, IDC_AA1, diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index ef5b9b69c1..267d3fc6ee 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -698,6 +698,7 @@ void GSHacksDlg::OnInit() 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_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_AUTO_FLUSH, theApp.GetConfigB("UserHacks_AutoFlush")); 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_PRELOAD_GS); AddTooltip(IDC_TC_DEPTH); + AddTooltip(IDC_CPU_FB_CONVERSION); AddTooltip(IDC_FAST_TC_INV); AddTooltip(IDC_AUTO_FLUSH); 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("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_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_AutoFlush", (int)IsDlgButtonChecked(m_hWnd, IDC_AUTO_FLUSH)); theApp.SetConfig("UserHacks_unscale_point_line", (int)IsDlgButtonChecked(m_hWnd, IDC_UNSCALE_POINT_LINE)); diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index b29cc769ee..857591d886 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -38,6 +38,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r) 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 { @@ -46,6 +47,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r) 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; } @@ -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; if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm)) { - if (!s_IS_OPENGL && (psm == PSM_PSMT8)) { - // OpenGL can convert the texture directly in the GPU. Not sure we want to keep this - // code for DX. It fixes effect but it is slow (MGS3) - - // 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 - // 1/ it just works :) - // 2/ even with upscaling - // 3/ for both DX and OpenGL - - // Gregory: to avoid a massive slow down for nothing, let's only enable - // this code when CRC is below the FULL level - if (m_crc_hack_level < CRCHackLevel::Full) - Read(t, t->m_valid); - else - dst = t; - } else { + // 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 + // 1/ it just works :) + // 2/ even with upscaling + // 3/ for both DX and OpenGL + if (m_cpu_fb_conversion && (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. + // There is no dedicated shader to handle 4-bit conversion. + // Direct3D doesn't support 8-bit fb conversion, OpenGL does support it but it doesn't render some corner cases properly. + // The hack can fix glitches in some games. + // Harry Potter games (Direct3D and OpenGL). + // FIFA Street games (Direct3D). + // Other games might also benefit from this hack especially on Direct3D. + Read(t, t->m_valid); + else dst = t; - } break; @@ -298,6 +296,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con dst = t; break; + } 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 dst = t; diff --git a/plugins/GSdx/GSTextureCache.h b/plugins/GSdx/GSTextureCache.h index c24674927a..ef751a81db 100644 --- a/plugins/GSdx/GSTextureCache.h +++ b/plugins/GSdx/GSTextureCache.h @@ -130,6 +130,7 @@ protected: bool m_preload_frame; uint8* m_temp; bool m_can_convert_depth; + bool m_cpu_fb_conversion; CRCHackLevel m_crc_hack_level; static bool m_disable_partial_invalidation; bool m_texture_inside_rt; diff --git a/plugins/GSdx/GSdx.cpp b/plugins/GSdx/GSdx.cpp index 6f68192be2..a00bfed78f 100644 --- a/plugins/GSdx/GSdx.cpp +++ b/plugins/GSdx/GSdx.cpp @@ -429,6 +429,7 @@ void GSdxApp::Init() m_default_configuration["UserHacks_AlphaStencil"] = "0"; m_default_configuration["UserHacks_AutoFlush"] = "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_DisablePartialInvalidation"] = "0"; m_default_configuration["UserHacks_HalfPixelOffset"] = "0"; diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index 1ae055b59a..608eef882b 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -142,6 +142,7 @@ BEGIN 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 "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 COMBOBOX IDC_MSAACB,80,96,116,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP RTEXT "Trilinear Filtering:",IDC_TRI_FILTER_TEXT,16,114,60,8 diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index 3a76b8d808..96bbb07ecb 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -103,6 +103,7 @@ #define IDC_TRI_FILTER_TEXT 2124 #define IDC_UNSCALE_POINT_LINE 2125 #define IDC_MERGE_PP_SPRITE 2126 +#define IDC_CPU_FB_CONVERSION 2127 // Shader: #define IDC_SHADEBOOST 2140 #define IDC_FXAA 2141