mirror of https://github.com/PCSX2/pcsx2.git
gsdx: split texture filtering option
Bilinear applies to all renderer * Common code done in GSVertexTrace * Extend it with forced but sprite (trade-off between linear/upscale glitches) * Linux GUI option was moved at the top with the renderer selection Trilinear is moved to OGL hack close #1837 Thanks to Flatout for the review and feedback. It will take care to update the Window GUI :)
This commit is contained in:
parent
f443804b35
commit
b54a824abd
|
@ -1416,14 +1416,19 @@ enum class GSVideoMode : uint8
|
||||||
DTV_1080I
|
DTV_1080I
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Filtering : uint8
|
enum class BiFiltering : uint8
|
||||||
{
|
{
|
||||||
Nearest,
|
Nearest,
|
||||||
Bilinear_Forced,
|
PS2,
|
||||||
Bilinear_PS2,
|
Forced_But_Sprite,
|
||||||
Trilinear,
|
Forced,
|
||||||
Trilinear_Bilinear_Forced,
|
};
|
||||||
Trilinear_Always
|
|
||||||
|
enum class TriFiltering : uint8
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
PS2,
|
||||||
|
Forced,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CRCHackLevel : uint8
|
enum class CRCHackLevel : uint8
|
||||||
|
|
|
@ -76,7 +76,9 @@ GSDeviceOGL::GSDeviceOGL()
|
||||||
GLState::Clear();
|
GLState::Clear();
|
||||||
|
|
||||||
m_mipmap = theApp.GetConfigI("mipmap");
|
m_mipmap = theApp.GetConfigI("mipmap");
|
||||||
m_filter = static_cast<Filtering>(theApp.GetConfigI("filter"));
|
m_filter = static_cast<TriFiltering>(theApp.GetConfigI("UserHacks_TriFilter"));
|
||||||
|
if (!theApp.GetConfigB("UserHacks"))
|
||||||
|
m_filter = TriFiltering::None;
|
||||||
|
|
||||||
// Reset the debug file
|
// Reset the debug file
|
||||||
#ifdef ENABLE_OGL_DEBUG
|
#ifdef ENABLE_OGL_DEBUG
|
||||||
|
@ -234,9 +236,8 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt
|
||||||
{
|
{
|
||||||
GL_PUSH("Create surface");
|
GL_PUSH("Create surface");
|
||||||
|
|
||||||
bool trilinear = m_filter == Filtering::Trilinear || m_filter == Filtering::Trilinear_Bilinear_Forced || m_filter == Filtering::Trilinear_Always;
|
|
||||||
// A wrapper to call GSTextureOGL, with the different kind of parameter
|
// A wrapper to call GSTextureOGL, with the different kind of parameter
|
||||||
GSTextureOGL* t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1 || trilinear);
|
GSTextureOGL* t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1 || m_filter != TriFiltering::None);
|
||||||
|
|
||||||
// NOTE: I'm not sure RenderTarget always need to be cleared. It could be costly for big upscale.
|
// NOTE: I'm not sure RenderTarget always need to be cleared. It could be costly for big upscale.
|
||||||
// FIXME: it will be more logical to do it in FetchSurface. This code is only called at first creation
|
// FIXME: it will be more logical to do it in FetchSurface. This code is only called at first creation
|
||||||
|
|
|
@ -411,7 +411,7 @@ public:
|
||||||
uint32 m_msaa; // Level of Msaa
|
uint32 m_msaa; // Level of Msaa
|
||||||
int m_force_texture_clear;
|
int m_force_texture_clear;
|
||||||
int m_mipmap;
|
int m_mipmap;
|
||||||
Filtering m_filter;
|
TriFiltering m_filter;
|
||||||
|
|
||||||
static bool m_debug_gl_call;
|
static bool m_debug_gl_call;
|
||||||
static FILE* m_debug_gl_file;
|
static FILE* m_debug_gl_file;
|
||||||
|
|
|
@ -219,9 +219,6 @@ GtkWidget* CreateTableInBox(GtkWidget* parent_box, const char* frame_title, int
|
||||||
|
|
||||||
void populate_hw_table(GtkWidget* hw_table)
|
void populate_hw_table(GtkWidget* hw_table)
|
||||||
{
|
{
|
||||||
GtkWidget* filter_label = left_label("Texture Filtering:");
|
|
||||||
GtkWidget* filter_combo_box = CreateComboBoxFromVector(theApp.m_gs_filter, "filter");
|
|
||||||
|
|
||||||
GtkWidget* fsaa_label = left_label("Internal Resolution:");
|
GtkWidget* fsaa_label = left_label("Internal Resolution:");
|
||||||
GtkWidget* fsaa_combo_box = CreateComboBoxFromVector(theApp.m_gs_upscale_multiplier, "upscale_multiplier");
|
GtkWidget* fsaa_combo_box = CreateComboBoxFromVector(theApp.m_gs_upscale_multiplier, "upscale_multiplier");
|
||||||
|
|
||||||
|
@ -249,7 +246,6 @@ void populate_hw_table(GtkWidget* hw_table)
|
||||||
AddTooltip(large_fb_check, IDC_LARGE_FB);
|
AddTooltip(large_fb_check, IDC_LARGE_FB);
|
||||||
AddTooltip(crc_label, crc_combo_box, IDC_CRC_LEVEL);
|
AddTooltip(crc_label, crc_combo_box, IDC_CRC_LEVEL);
|
||||||
AddTooltip(acc_bld_label, acc_bld_combo_box, IDC_ACCURATE_BLEND_UNIT);
|
AddTooltip(acc_bld_label, acc_bld_combo_box, IDC_ACCURATE_BLEND_UNIT);
|
||||||
AddTooltip(filter_label, filter_combo_box, IDC_FILTER);
|
|
||||||
AddTooltip(af_label, af_combo_box, IDC_AFCOMBO);
|
AddTooltip(af_label, af_combo_box, IDC_AFCOMBO);
|
||||||
gtk_widget_set_tooltip_text(hack_enable_check, "Enable the HW hack option panel");
|
gtk_widget_set_tooltip_text(hack_enable_check, "Enable the HW hack option panel");
|
||||||
AddTooltip(mipmap_label, IDC_MIPMAP_HW);
|
AddTooltip(mipmap_label, IDC_MIPMAP_HW);
|
||||||
|
@ -259,7 +255,6 @@ void populate_hw_table(GtkWidget* hw_table)
|
||||||
InsertWidgetInTable(hw_table , paltex_check , acc_date_check);
|
InsertWidgetInTable(hw_table , paltex_check , acc_date_check);
|
||||||
InsertWidgetInTable(hw_table , large_fb_check, hack_enable_check);
|
InsertWidgetInTable(hw_table , large_fb_check, hack_enable_check);
|
||||||
InsertWidgetInTable(hw_table , fsaa_label , fsaa_combo_box);
|
InsertWidgetInTable(hw_table , fsaa_label , fsaa_combo_box);
|
||||||
InsertWidgetInTable(hw_table , filter_label , filter_combo_box);
|
|
||||||
InsertWidgetInTable(hw_table , af_label , af_combo_box);
|
InsertWidgetInTable(hw_table , af_label , af_combo_box);
|
||||||
InsertWidgetInTable(hw_table , acc_bld_label , acc_bld_combo_box);
|
InsertWidgetInTable(hw_table , acc_bld_label , acc_bld_combo_box);
|
||||||
InsertWidgetInTable(hw_table , crc_label , crc_combo_box);
|
InsertWidgetInTable(hw_table , crc_label , crc_combo_box);
|
||||||
|
@ -359,6 +354,8 @@ void populate_hack_table(GtkWidget* hack_table)
|
||||||
GtkWidget* hack_sprite_label = left_label("Alpha-Sprite Hack:");
|
GtkWidget* hack_sprite_label = left_label("Alpha-Sprite Hack:");
|
||||||
GtkWidget* stretch_hack_box = CreateComboBoxFromVector(theApp.m_gs_hack, "UserHacks_round_sprite_offset");
|
GtkWidget* stretch_hack_box = CreateComboBoxFromVector(theApp.m_gs_hack, "UserHacks_round_sprite_offset");
|
||||||
GtkWidget* stretch_hack_label = left_label("Align Sprite Texture:");
|
GtkWidget* stretch_hack_label = left_label("Align Sprite Texture:");
|
||||||
|
GtkWidget* trilinear_box = CreateComboBoxFromVector(theApp.m_gs_trifilter, "UserHacks_TriFilter");
|
||||||
|
GtkWidget* trilinear_label = left_label("Trilinear Filtering:");
|
||||||
|
|
||||||
// Reuse windows helper string :)
|
// Reuse windows helper string :)
|
||||||
AddTooltip(hack_offset_label, IDC_OFFSETHACK);
|
AddTooltip(hack_offset_label, IDC_OFFSETHACK);
|
||||||
|
@ -376,6 +373,8 @@ void populate_hack_table(GtkWidget* hack_table)
|
||||||
AddTooltip(hack_depth_check, IDC_TC_DEPTH);
|
AddTooltip(hack_depth_check, IDC_TC_DEPTH);
|
||||||
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(trilinear_box, IDC_TRI_FILTER);
|
||||||
|
AddTooltip(trilinear_label, IDC_TRI_FILTER);
|
||||||
|
|
||||||
|
|
||||||
s_table_line = 0;
|
s_table_line = 0;
|
||||||
|
@ -390,6 +389,7 @@ void populate_hack_table(GtkWidget* hack_table)
|
||||||
InsertWidgetInTable(hack_table , stretch_hack_label , stretch_hack_box );
|
InsertWidgetInTable(hack_table , stretch_hack_label , stretch_hack_box );
|
||||||
InsertWidgetInTable(hack_table , hack_skipdraw_label , hack_skipdraw_spin);
|
InsertWidgetInTable(hack_table , hack_skipdraw_label , hack_skipdraw_spin);
|
||||||
InsertWidgetInTable(hack_table , hack_tco_label , hack_tco_entry);
|
InsertWidgetInTable(hack_table , hack_tco_label , hack_tco_entry);
|
||||||
|
InsertWidgetInTable(hack_table , trilinear_label , trilinear_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
void populate_main_table(GtkWidget* main_table)
|
void populate_main_table(GtkWidget* main_table)
|
||||||
|
@ -398,11 +398,15 @@ void populate_main_table(GtkWidget* main_table)
|
||||||
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_combo_box = CreateComboBoxFromVector(theApp.m_gs_bifilter, "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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void populate_debug_table(GtkWidget* debug_table)
|
void populate_debug_table(GtkWidget* debug_table)
|
||||||
|
|
|
@ -45,7 +45,6 @@ GSRenderer::GSRenderer()
|
||||||
m_interlace = theApp.GetConfigI("interlace") % s_interlace_nb;
|
m_interlace = theApp.GetConfigI("interlace") % s_interlace_nb;
|
||||||
m_aspectratio = theApp.GetConfigI("AspectRatio") % s_aspect_ratio_nb;
|
m_aspectratio = theApp.GetConfigI("AspectRatio") % s_aspect_ratio_nb;
|
||||||
m_shader = theApp.GetConfigI("TVShader") % s_post_shader_nb;
|
m_shader = theApp.GetConfigI("TVShader") % s_post_shader_nb;
|
||||||
m_filter = static_cast<Filtering>(theApp.GetConfigI("filter"));
|
|
||||||
m_vsync = theApp.GetConfigB("vsync");
|
m_vsync = theApp.GetConfigB("vsync");
|
||||||
m_aa1 = theApp.GetConfigB("aa1");
|
m_aa1 = theApp.GetConfigB("aa1");
|
||||||
m_fxaa = theApp.GetConfigB("fxaa");
|
m_fxaa = theApp.GetConfigB("fxaa");
|
||||||
|
|
|
@ -48,7 +48,6 @@ protected:
|
||||||
bool m_fxaa;
|
bool m_fxaa;
|
||||||
bool m_shadeboost;
|
bool m_shadeboost;
|
||||||
bool m_texture_shuffle;
|
bool m_texture_shuffle;
|
||||||
Filtering m_filter;
|
|
||||||
GSVector2i m_real_size;
|
GSVector2i m_real_size;
|
||||||
|
|
||||||
virtual GSTexture* GetOutput(int i, int& y_offset) = 0;
|
virtual GSTexture* GetOutput(int i, int& y_offset) = 0;
|
||||||
|
|
|
@ -478,10 +478,8 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc
|
||||||
// After the conversion the texture will be RGBA8 (aka 32 bits) hence the 0 below
|
// After the conversion the texture will be RGBA8 (aka 32 bits) hence the 0 below
|
||||||
int gpu_tex_fmt = (tex->m_target) ? cpsm.fmt : 0;
|
int gpu_tex_fmt = (tex->m_target) ? cpsm.fmt : 0;
|
||||||
|
|
||||||
bool bilinear = m_filter == Filtering::Bilinear_PS2 || m_filter == Filtering::Trilinear ? m_vt.IsLinear() : m_filter != Filtering::Nearest;
|
bool bilinear = m_vt.IsLinear();
|
||||||
bool simple_sample = !tex->m_palette && gpu_tex_fmt == 0 && m_context->CLAMP.WMS < 2 && m_context->CLAMP.WMT < 2;
|
bool simple_sample = !tex->m_palette && gpu_tex_fmt == 0 && m_context->CLAMP.WMS < 2 && m_context->CLAMP.WMT < 2;
|
||||||
// Don't force extra filtering on sprite (it creates various upscaling issue)
|
|
||||||
bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear());
|
|
||||||
|
|
||||||
ps_sel.wms = m_context->CLAMP.WMS;
|
ps_sel.wms = m_context->CLAMP.WMS;
|
||||||
ps_sel.wmt = m_context->CLAMP.WMT;
|
ps_sel.wmt = m_context->CLAMP.WMT;
|
||||||
|
|
|
@ -40,6 +40,7 @@ GSRendererOGL::GSRendererOGL()
|
||||||
UserHacks_merge_sprite = theApp.GetConfigB("UserHacks_merge_pp_sprite");
|
UserHacks_merge_sprite = theApp.GetConfigB("UserHacks_merge_pp_sprite");
|
||||||
UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line");
|
UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line");
|
||||||
UserHacks_HPO = theApp.GetConfigI("UserHacks_HalfPixelOffset");
|
UserHacks_HPO = theApp.GetConfigI("UserHacks_HalfPixelOffset");
|
||||||
|
UserHacks_tri_filter = static_cast<TriFiltering>(theApp.GetConfigI("UserHacks_TriFilter"));
|
||||||
|
|
||||||
m_prim_overlap = PRIM_OVERLAP_UNKNOW;
|
m_prim_overlap = PRIM_OVERLAP_UNKNOW;
|
||||||
ResetStates();
|
ResetStates();
|
||||||
|
@ -51,6 +52,7 @@ GSRendererOGL::GSRendererOGL()
|
||||||
UserHacks_merge_sprite = false;
|
UserHacks_merge_sprite = false;
|
||||||
UserHacks_unscale_pt_ln = false;
|
UserHacks_unscale_pt_ln = false;
|
||||||
UserHacks_HPO = 0;
|
UserHacks_HPO = 0;
|
||||||
|
UserHacks_tri_filter = TriFiltering::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,7 +746,7 @@ void GSRendererOGL::RealignTargetTextureCoordinate(const GSTextureCache::Source*
|
||||||
|
|
||||||
GSVertex* v = &m_vertex.buff[0];
|
GSVertex* v = &m_vertex.buff[0];
|
||||||
const GSVector2& scale = tex->m_texture->GetScale();
|
const GSVector2& scale = tex->m_texture->GetScale();
|
||||||
bool linear = m_vt.IsLinear();
|
bool linear = m_vt.IsRealLinear();
|
||||||
int t_position = v[0].U;
|
int t_position = v[0].U;
|
||||||
GSVector4 half_offset(0.0f);
|
GSVector4 half_offset(0.0f);
|
||||||
|
|
||||||
|
@ -814,50 +816,28 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
||||||
bool shader_emulated_sampler = tex->m_palette || cpsm.fmt != 0 || complex_wms_wmt || psm.depth;
|
bool shader_emulated_sampler = tex->m_palette || cpsm.fmt != 0 || complex_wms_wmt || psm.depth;
|
||||||
bool trilinear_manual = need_mipmap && m_mipmap == 2;
|
bool trilinear_manual = need_mipmap && m_mipmap == 2;
|
||||||
|
|
||||||
bool bilinear = false;
|
bool bilinear = m_vt.IsLinear();
|
||||||
int trilinear = 0;
|
int trilinear = 0;
|
||||||
bool trilinear_auto = false;
|
bool trilinear_auto = false;
|
||||||
switch (m_filter)
|
switch (UserHacks_tri_filter)
|
||||||
{
|
{
|
||||||
case Filtering::Nearest:
|
case TriFiltering::Forced:
|
||||||
bilinear = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Filtering::Bilinear_Forced:
|
|
||||||
bilinear = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Filtering::Bilinear_PS2:
|
|
||||||
bilinear = m_vt.IsLinear();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Filtering::Trilinear_Always:
|
|
||||||
bilinear = true;
|
|
||||||
trilinear = static_cast<uint8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
|
trilinear = static_cast<uint8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
|
||||||
trilinear_auto = m_mipmap != 2;
|
trilinear_auto = m_mipmap != 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Filtering::Trilinear:
|
case TriFiltering::PS2:
|
||||||
bilinear = m_vt.IsLinear();
|
|
||||||
if (need_mipmap && m_mipmap != 2) {
|
if (need_mipmap && m_mipmap != 2) {
|
||||||
trilinear = m_context->TEX1.MMIN;
|
trilinear = m_context->TEX1.MMIN;
|
||||||
trilinear_auto = true;
|
trilinear_auto = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Filtering::Trilinear_Bilinear_Forced:
|
case TriFiltering::None:
|
||||||
bilinear = true;
|
|
||||||
if (need_mipmap && m_mipmap != 2) {
|
|
||||||
trilinear = (m_context->TEX1.MMIN | 4) & 0x5;
|
|
||||||
trilinear_auto = true;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't force extra filtering on sprite (it creates various upscaling issue)
|
|
||||||
bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear());
|
|
||||||
|
|
||||||
// 1 and 0 are equivalent
|
// 1 and 0 are equivalent
|
||||||
m_ps_sel.wms = (wms & 2) ? wms : 0;
|
m_ps_sel.wms = (wms & 2) ? wms : 0;
|
||||||
m_ps_sel.wmt = (wmt & 2) ? wmt : 0;
|
m_ps_sel.wmt = (wmt & 2) ? wmt : 0;
|
||||||
|
|
|
@ -55,6 +55,7 @@ class GSRendererOGL final : public GSRendererHW
|
||||||
bool UserHacks_merge_sprite;
|
bool UserHacks_merge_sprite;
|
||||||
bool UserHacks_unscale_pt_ln;
|
bool UserHacks_unscale_pt_ln;
|
||||||
int UserHacks_HPO;
|
int UserHacks_HPO;
|
||||||
|
TriFiltering UserHacks_tri_filter;
|
||||||
|
|
||||||
GSDeviceOGL::VSConstantBuffer vs_cb;
|
GSDeviceOGL::VSConstantBuffer vs_cb;
|
||||||
GSDeviceOGL::PSConstantBuffer ps_cb;
|
GSDeviceOGL::PSConstantBuffer ps_cb;
|
||||||
|
|
|
@ -33,11 +33,17 @@ const char* dialog_message(int ID, bool* updateText) {
|
||||||
case IDC_FILTER:
|
case IDC_FILTER:
|
||||||
return "Control the texture filtering of the emulation.\n\n"
|
return "Control the texture filtering of the emulation.\n\n"
|
||||||
"Nearest:\nAlways disable interpolation, rendering will be blocky.\n\n"
|
"Nearest:\nAlways disable interpolation, rendering will be blocky.\n\n"
|
||||||
|
"Bilinear Forced (excluding sprite):\nAlways enable interpolation except for sprites (FMV/Text/2D elements)."
|
||||||
|
" Rendering is smoother but it could generate a few glitches. If upscaling is enabled, this setting is recommended over 'Bilinear Forced'\n\n"
|
||||||
"Bilinear Forced:\nAlways enable interpolation. Rendering is smoother but it could generate some glitches.\n\n"
|
"Bilinear Forced:\nAlways enable interpolation. Rendering is smoother but it could generate some glitches.\n\n"
|
||||||
"Bilinear PS2:\nUse same mode as the PS2. It is the more accurate option.\n\n"
|
"Bilinear PS2:\nUse same mode as the PS2. It is the more accurate option.\n\n";
|
||||||
|
#ifdef __unix__
|
||||||
|
case IDC_TRI_FILTER:
|
||||||
|
return "Control the texture tri-filtering of the emulation.\n\n"
|
||||||
|
"None:\nNo extra trilinear filtering.\n\n"
|
||||||
"Trilinear:\nUse OpenGL trilinear interpolation when PS2 uses mipmaps.\n\n"
|
"Trilinear:\nUse OpenGL trilinear interpolation when PS2 uses mipmaps.\n\n"
|
||||||
"Trilinear Forced Bilinear:\nSame as above but always enable bilinear interpolation.\n\n"
|
"Trilinear Forced:\nAlways enable full trilinear interpolation. Warning Slow!\n\n";
|
||||||
"Trilinear Ultra:\nAlways enable full trilinear interpolation. Warning Slow!\n\n";
|
#endif
|
||||||
case IDC_CRC_LEVEL:
|
case IDC_CRC_LEVEL:
|
||||||
return "Control the number of Auto-CRC hacks applied to games.\n\n"
|
return "Control the number of Auto-CRC hacks applied to games.\n\n"
|
||||||
"None:\nRemove nearly all CRC hacks (debug only).\n\n"
|
"None:\nRemove nearly all CRC hacks (debug only).\n\n"
|
||||||
|
|
|
@ -43,6 +43,7 @@ const char* dialog_message(int ID, bool* updateText = NULL);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
enum {
|
enum {
|
||||||
IDC_FILTER,
|
IDC_FILTER,
|
||||||
|
IDC_TRI_FILTER,
|
||||||
IDC_SKIPDRAWHACK,
|
IDC_SKIPDRAWHACK,
|
||||||
IDC_SKIPDRAWHACKEDIT,
|
IDC_SKIPDRAWHACKEDIT,
|
||||||
IDC_ALPHAHACK,
|
IDC_ALPHAHACK,
|
||||||
|
|
|
@ -151,7 +151,7 @@ void GSSettingsDlg::OnInit()
|
||||||
ComboBoxInit(IDC_INTERLACE, theApp.m_gs_interlace, theApp.GetConfigI("interlace"));
|
ComboBoxInit(IDC_INTERLACE, theApp.m_gs_interlace, theApp.GetConfigI("interlace"));
|
||||||
ComboBoxInit(IDC_UPSCALE_MULTIPLIER, theApp.m_gs_upscale_multiplier, theApp.GetConfigI("upscale_multiplier"));
|
ComboBoxInit(IDC_UPSCALE_MULTIPLIER, theApp.m_gs_upscale_multiplier, theApp.GetConfigI("upscale_multiplier"));
|
||||||
ComboBoxInit(IDC_AFCOMBO, theApp.m_gs_max_anisotropy, theApp.GetConfigI("MaxAnisotropy"));
|
ComboBoxInit(IDC_AFCOMBO, theApp.m_gs_max_anisotropy, theApp.GetConfigI("MaxAnisotropy"));
|
||||||
ComboBoxInit(IDC_FILTER, theApp.m_gs_filter, theApp.GetConfigI("filter"));
|
ComboBoxInit(IDC_FILTER, theApp.m_gs_bifilter, theApp.GetConfigI("filter"));
|
||||||
ComboBoxInit(IDC_ACCURATE_BLEND_UNIT, theApp.m_gs_acc_blend_level, theApp.GetConfigI("accurate_blending_unit"));
|
ComboBoxInit(IDC_ACCURATE_BLEND_UNIT, theApp.m_gs_acc_blend_level, theApp.GetConfigI("accurate_blending_unit"));
|
||||||
ComboBoxInit(IDC_CRC_LEVEL, theApp.m_gs_crc_level, theApp.GetConfigI("crc_hack_level"));
|
ComboBoxInit(IDC_CRC_LEVEL, theApp.m_gs_crc_level, theApp.GetConfigI("crc_hack_level"));
|
||||||
|
|
||||||
|
@ -190,33 +190,9 @@ void GSSettingsDlg::OnInit()
|
||||||
AddTooltip(IDC_LOGZ);
|
AddTooltip(IDC_LOGZ);
|
||||||
AddTooltip(IDC_LARGE_FB);
|
AddTooltip(IDC_LARGE_FB);
|
||||||
|
|
||||||
UpdateFilteringCombobox();
|
|
||||||
UpdateControls();
|
UpdateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSSettingsDlg::UpdateFilteringCombobox()
|
|
||||||
{
|
|
||||||
INT_PTR i;
|
|
||||||
ComboBoxGetSelData(IDC_RENDERER, i);
|
|
||||||
bool opengl = static_cast<GSRendererType>(i) == GSRendererType::OGL_HW;
|
|
||||||
bool hw_mode = opengl || static_cast<GSRendererType>(i) == GSRendererType::DX1011_HW || static_cast<GSRendererType>(i) == GSRendererType::DX9_HW;
|
|
||||||
if (!hw_mode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint8 filter = (ComboBoxGetSelData(IDC_FILTER, i)) ? static_cast<uint8>(i) : static_cast<uint8>(theApp.GetConfigI("filter"));
|
|
||||||
if (!opengl) //Currently Trilinear is only exclusive to OpenGL, remove those combobox items when any other renderer is used
|
|
||||||
{
|
|
||||||
auto head = theApp.m_gs_filter.begin();
|
|
||||||
auto tail = head + static_cast<uint8>(Filtering::Trilinear);
|
|
||||||
vector<GSSetting> list(head, tail);
|
|
||||||
ComboBoxInit(IDC_FILTER, list, std::max(uint8(Filtering::Nearest), std::min(filter, uint8(Filtering::Bilinear_PS2))));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ComboBoxInit(IDC_FILTER, theApp.m_gs_filter, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code)
|
bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code)
|
||||||
{
|
{
|
||||||
switch (id)
|
switch (id)
|
||||||
|
@ -231,7 +207,6 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code)
|
||||||
case IDC_RENDERER:
|
case IDC_RENDERER:
|
||||||
if (code == CBN_SELCHANGE)
|
if (code == CBN_SELCHANGE)
|
||||||
{
|
{
|
||||||
UpdateFilteringCombobox();
|
|
||||||
UpdateControls();
|
UpdateControls();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -96,7 +96,6 @@ class GSSettingsDlg : public GSDialog
|
||||||
|
|
||||||
void UpdateRenderers();
|
void UpdateRenderers();
|
||||||
void UpdateControls();
|
void UpdateControls();
|
||||||
void UpdateFilteringCombobox();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void OnInit();
|
void OnInit();
|
||||||
|
|
|
@ -32,9 +32,9 @@ void GSVertexTrace::InitVectors()
|
||||||
}
|
}
|
||||||
|
|
||||||
GSVertexTrace::GSVertexTrace(const GSState* state)
|
GSVertexTrace::GSVertexTrace(const GSState* state)
|
||||||
: m_state(state)
|
: m_state(state), m_primclass(GS_INVALID_CLASS)
|
||||||
{
|
{
|
||||||
m_primclass = GS_INVALID_CLASS;
|
m_force_filter = static_cast<BiFiltering>(theApp.GetConfigI("filter"));
|
||||||
memset(&m_alpha, 0, sizeof(m_alpha));
|
memset(&m_alpha, 0, sizeof(m_alpha));
|
||||||
|
|
||||||
#define InitUpdate3(P, IIP, TME, FST, COLOR) \
|
#define InitUpdate3(P, IIP, TME, FST, COLOR) \
|
||||||
|
@ -88,10 +88,9 @@ void GSVertexTrace::Update(const void* vertex, const uint32* index, int v_count,
|
||||||
if(TEX1.MXL == 0) // MXL == 0 => MMIN ignored, tested it on ps2
|
if(TEX1.MXL == 0) // MXL == 0 => MMIN ignored, tested it on ps2
|
||||||
{
|
{
|
||||||
m_filter.linear = m_filter.mmag;
|
m_filter.linear = m_filter.mmag;
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
float K = (float)TEX1.K / 16;
|
float K = (float)TEX1.K / 16;
|
||||||
|
|
||||||
if(TEX1.LCM == 0 && m_state->PRIM->FST == 0) // FST == 1 => Q is not interpolated
|
if(TEX1.LCM == 0 && m_state->PRIM->FST == 0) // FST == 1 => Q is not interpolated
|
||||||
|
@ -121,6 +120,28 @@ void GSVertexTrace::Update(const void* vertex, const uint32* index, int v_count,
|
||||||
m_filter.linear = m_filter.mmag | m_filter.mmin;
|
m_filter.linear = m_filter.mmag | m_filter.mmin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (m_force_filter)
|
||||||
|
{
|
||||||
|
case BiFiltering::Nearest:
|
||||||
|
m_filter.opt_linear = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiFiltering::Forced_But_Sprite:
|
||||||
|
// Special case to reduce the number of glitch when upscaling is enabled
|
||||||
|
m_filter.opt_linear = (m_primclass == GS_SPRITE_CLASS) ? m_filter.linear : 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiFiltering::Forced:
|
||||||
|
m_filter.opt_linear = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiFiltering::PS2:
|
||||||
|
default:
|
||||||
|
m_filter.opt_linear = m_filter.linear;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<GS_PRIM_CLASS primclass, uint32 iip, uint32 tme, uint32 fst, uint32 color>
|
template<GS_PRIM_CLASS primclass, uint32 iip, uint32 tme, uint32 fst, uint32 color>
|
||||||
|
|
|
@ -31,6 +31,8 @@ class GSState;
|
||||||
|
|
||||||
class alignas(32) GSVertexTrace : public GSAlignedClass<32>
|
class alignas(32) GSVertexTrace : public GSAlignedClass<32>
|
||||||
{
|
{
|
||||||
|
BiFiltering m_force_filter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Vertex {GSVector4i c; GSVector4 p, t;};
|
struct Vertex {GSVector4i c; GSVector4 p, t;};
|
||||||
struct VertexAlpha {int min, max; bool valid;};
|
struct VertexAlpha {int min, max; bool valid;};
|
||||||
|
@ -63,7 +65,7 @@ public:
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct {uint32 mmag:1, mmin:1, linear:1;};
|
struct {uint32 mmag:1, mmin:1, linear:1, opt_linear:1;};
|
||||||
} m_filter;
|
} m_filter;
|
||||||
|
|
||||||
GSVector2 m_lod; // x = min, y = max
|
GSVector2 m_lod; // x = min, y = max
|
||||||
|
@ -76,7 +78,8 @@ public:
|
||||||
|
|
||||||
void Update(const void* vertex, const uint32* index, int v_count, int i_count, GS_PRIM_CLASS primclass);
|
void Update(const void* vertex, const uint32* index, int v_count, int i_count, GS_PRIM_CLASS primclass);
|
||||||
|
|
||||||
bool IsLinear() const {return m_filter.linear;}
|
bool IsLinear() const {return m_filter.opt_linear;}
|
||||||
|
bool IsRealLinear() const {return m_filter.linear;}
|
||||||
|
|
||||||
void CorrectDepthTrace(const void* vertex, int count);
|
void CorrectDepthTrace(const void* vertex, int count);
|
||||||
};
|
};
|
||||||
|
|
|
@ -201,12 +201,14 @@ void GSdxApp::Init()
|
||||||
m_gs_max_anisotropy.push_back(GSSetting(8, "8x", ""));
|
m_gs_max_anisotropy.push_back(GSSetting(8, "8x", ""));
|
||||||
m_gs_max_anisotropy.push_back(GSSetting(16, "16x", ""));
|
m_gs_max_anisotropy.push_back(GSSetting(16, "16x", ""));
|
||||||
|
|
||||||
m_gs_filter.push_back(GSSetting(static_cast<uint32>(Filtering::Nearest), "Nearest", ""));
|
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::Nearest), "Nearest", ""));
|
||||||
m_gs_filter.push_back(GSSetting(static_cast<uint32>(Filtering::Bilinear_Forced), "Bilinear", "Forced"));
|
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::Forced_But_Sprite), "Bilinear", "Forced excluding sprite"));
|
||||||
m_gs_filter.push_back(GSSetting(static_cast<uint32>(Filtering::Bilinear_PS2), "Bilinear", "PS2"));
|
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::Forced), "Bilinear", "Forced"));
|
||||||
m_gs_filter.push_back(GSSetting(static_cast<uint32>(Filtering::Trilinear), "Trilinear", ""));
|
m_gs_bifilter.push_back(GSSetting(static_cast<uint32>(BiFiltering::PS2), "Bilinear", "PS2"));
|
||||||
m_gs_filter.push_back(GSSetting(static_cast<uint32>(Filtering::Trilinear_Bilinear_Forced), "Trilinear", "Forced Bilinear"));
|
|
||||||
m_gs_filter.push_back(GSSetting(static_cast<uint32>(Filtering::Trilinear_Always), "Trilinear", "Ultra/Slow"));
|
m_gs_trifilter.push_back(GSSetting(static_cast<uint32>(TriFiltering::None), "None", ""));
|
||||||
|
m_gs_trifilter.push_back(GSSetting(static_cast<uint32>(TriFiltering::PS2), "Trilinear", ""));
|
||||||
|
m_gs_trifilter.push_back(GSSetting(static_cast<uint32>(TriFiltering::Forced), "Trilinear", "Ultra/Slow"));
|
||||||
|
|
||||||
m_gs_gl_ext.push_back(GSSetting(-1, "Auto", ""));
|
m_gs_gl_ext.push_back(GSSetting(-1, "Auto", ""));
|
||||||
m_gs_gl_ext.push_back(GSSetting(0, "Force-Disabled", ""));
|
m_gs_gl_ext.push_back(GSSetting(0, "Force-Disabled", ""));
|
||||||
|
@ -307,7 +309,7 @@ void GSdxApp::Init()
|
||||||
m_default_configuration["dump"] = "0";
|
m_default_configuration["dump"] = "0";
|
||||||
m_default_configuration["extrathreads"] = "2";
|
m_default_configuration["extrathreads"] = "2";
|
||||||
m_default_configuration["extrathreads_height"] = "4";
|
m_default_configuration["extrathreads_height"] = "4";
|
||||||
m_default_configuration["filter"] = "2";
|
m_default_configuration["filter"] = to_string(static_cast<int8>(BiFiltering::PS2));
|
||||||
m_default_configuration["force_texture_clear"] = "0";
|
m_default_configuration["force_texture_clear"] = "0";
|
||||||
m_default_configuration["fxaa"] = "0";
|
m_default_configuration["fxaa"] = "0";
|
||||||
m_default_configuration["interlace"] = "7";
|
m_default_configuration["interlace"] = "7";
|
||||||
|
@ -380,6 +382,7 @@ void GSdxApp::Init()
|
||||||
m_default_configuration["UserHacks_SpriteHack"] = "0";
|
m_default_configuration["UserHacks_SpriteHack"] = "0";
|
||||||
m_default_configuration["UserHacks_TCOffset"] = "0";
|
m_default_configuration["UserHacks_TCOffset"] = "0";
|
||||||
m_default_configuration["UserHacks_TextureInsideRt"] = "0";
|
m_default_configuration["UserHacks_TextureInsideRt"] = "0";
|
||||||
|
m_default_configuration["UserHacks_TriFilter"] = to_string(static_cast<int8>(TriFiltering::None));
|
||||||
m_default_configuration["UserHacks_WildHack"] = "0";
|
m_default_configuration["UserHacks_WildHack"] = "0";
|
||||||
m_default_configuration["wrap_gs_mem"] = "0";
|
m_default_configuration["wrap_gs_mem"] = "0";
|
||||||
m_default_configuration["vsync"] = "0";
|
m_default_configuration["vsync"] = "0";
|
||||||
|
|
|
@ -68,7 +68,8 @@ public:
|
||||||
vector<GSSetting> m_gs_aspectratio;
|
vector<GSSetting> m_gs_aspectratio;
|
||||||
vector<GSSetting> m_gs_upscale_multiplier;
|
vector<GSSetting> m_gs_upscale_multiplier;
|
||||||
vector<GSSetting> m_gs_max_anisotropy;
|
vector<GSSetting> m_gs_max_anisotropy;
|
||||||
vector<GSSetting> m_gs_filter;
|
vector<GSSetting> m_gs_bifilter;
|
||||||
|
vector<GSSetting> m_gs_trifilter;
|
||||||
vector<GSSetting> m_gs_gl_ext;
|
vector<GSSetting> m_gs_gl_ext;
|
||||||
vector<GSSetting> m_gs_hack;
|
vector<GSSetting> m_gs_hack;
|
||||||
vector<GSSetting> m_gs_offset_hack;
|
vector<GSSetting> m_gs_offset_hack;
|
||||||
|
|
Loading…
Reference in New Issue