diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java index ac3f86eb8a..7b488719a6 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java @@ -198,6 +198,8 @@ public enum BooleanSetting implements AbstractBooleanSetting GFX_HACK_EFB_EMULATE_FORMAT_CHANGES(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "EFBEmulateFormatChanges", false), GFX_HACK_VERTEX_ROUDING(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "VertexRounding", false), + GFX_HACK_FAST_TEXTURE_SAMPLING(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, + "FastTextureSampling", false), LOGGER_WRITE_TO_FILE(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_OPTIONS, "WriteToFile", false), diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index bc23b2042a..3eb95efa68 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -719,6 +719,8 @@ public final class SettingsFragmentPresenter R.string.vertex_rounding, R.string.vertex_rounding_description)); sl.add(new CheckBoxSetting(mContext, BooleanSetting.GFX_SAVE_TEXTURE_CACHE_TO_STATE, R.string.texture_cache_to_state, R.string.texture_cache_to_state_description)); + sl.add(new CheckBoxSetting(mContext, BooleanSetting.GFX_HACK_FAST_TEXTURE_SAMPLING, + R.string.fast_texture_sampling, R.string.fast_texture_sampling_description)); } private void addAdvancedGraphicsSettings(ArrayList sl) diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index efcdf82bd4..664e9e8343 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -277,6 +277,8 @@ Rounds 2D vertices to whole pixels. Fixes graphical problems in some games at higher internal resolutions. This setting has no effect when native internal resolution is used. If unsure, leave this unchecked. Save Texture Cache to State Includes the contents of the embedded frame buffer (EFB) and upscaled EFB copies in save states. Fixes missing and/or non-upscaled textures/objects when loading states at the cost of additional save/load time. + Fast Texture Sampling + Use the video backend\'s built-in texture sampling functionality instead of a manual implementation. Aspect Ratio Select what aspect ratio to use when rendering Shader Compilation Mode diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index d1c7b21cf9..d859cab150 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -150,6 +150,8 @@ const Info GFX_HACK_EFB_EMULATE_FORMAT_CHANGES{ const Info GFX_HACK_VERTEX_ROUDING{{System::GFX, "Hacks", "VertexRounding"}, false}; const Info GFX_HACK_MISSING_COLOR_VALUE{{System::GFX, "Hacks", "MissingColorValue"}, 0xFFFFFFFF}; +const Info GFX_HACK_FAST_TEXTURE_SAMPLING{{System::GFX, "Hacks", "FastTextureSampling"}, + false}; // Graphics.GameSpecific diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index cc112722ba..3936b65cd9 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -123,6 +123,7 @@ extern const Info GFX_HACK_COPY_EFB_SCALED; extern const Info GFX_HACK_EFB_EMULATE_FORMAT_CHANGES; extern const Info GFX_HACK_VERTEX_ROUDING; extern const Info GFX_HACK_MISSING_COLOR_VALUE; +extern const Info GFX_HACK_FAST_TEXTURE_SAMPLING; // Graphics.GameSpecific diff --git a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp index 2765e2e2fd..4dc302ce1e 100644 --- a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp @@ -106,11 +106,14 @@ void HacksWidget::CreateWidgets() m_vertex_rounding = new GraphicsBool(tr("Vertex Rounding"), Config::GFX_HACK_VERTEX_ROUDING); m_save_texture_cache_state = new GraphicsBool(tr("Save Texture Cache to State"), Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE); + m_fast_texture_sampling = + new GraphicsBool(tr("Fast Texture Sampling"), Config::GFX_HACK_FAST_TEXTURE_SAMPLING); other_layout->addWidget(m_fast_depth_calculation, 0, 0); other_layout->addWidget(m_disable_bounding_box, 0, 1); other_layout->addWidget(m_vertex_rounding, 1, 0); other_layout->addWidget(m_save_texture_cache_state, 1, 1); + other_layout->addWidget(m_fast_texture_sampling, 2, 0); main_layout->addWidget(efb_box); main_layout->addWidget(texture_cache_box); @@ -276,6 +279,17 @@ void HacksWidget::AddDescriptions() "higher internal resolutions. This setting has no effect when native internal " "resolution is used.

If unsure, leave this " "unchecked."); + static const char TR_FAST_TEXTURE_SAMPLING_DESCRIPTION[] = QT_TR_NOOP( + "Use the video backend's built-in texture sampling functionality instead of a manual " + "implementation.

" + "This setting can cause potentially improve performance, especially at higher internal " + "resolutions; additionally, Anisotropic Filtering currently only works with Fast Texture " + "Sampling.

" + "This comes at the cost of graphical issues in some games on certain GPUs, most commonly " + "vertical lines on FMVs, as well as lack of emulation of texture wrapping special cases " + "(though this also only works at 1x IR or when scaled EFB is disabled, and with custom " + "textures disabled) and worse emulation of Level of Detail calculation.

" + "If unsure, leave this unchecked."); m_skip_efb_cpu->SetDescription(tr(TR_SKIP_EFB_CPU_ACCESS_DESCRIPTION)); m_ignore_format_changes->SetDescription(tr(TR_IGNORE_FORMAT_CHANGE_DESCRIPTION)); @@ -291,6 +305,7 @@ void HacksWidget::AddDescriptions() m_disable_bounding_box->SetDescription(tr(TR_DISABLE_BOUNDINGBOX_DESCRIPTION)); m_save_texture_cache_state->SetDescription(tr(TR_SAVE_TEXTURE_CACHE_TO_STATE_DESCRIPTION)); m_vertex_rounding->SetDescription(tr(TR_VERTEX_ROUNDING_DESCRIPTION)); + m_fast_texture_sampling->SetDescription(tr(TR_FAST_TEXTURE_SAMPLING_DESCRIPTION)); } void HacksWidget::UpdateDeferEFBCopiesEnabled() diff --git a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h index 2af4a12fea..c34cd27ff8 100644 --- a/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/HacksWidget.h @@ -26,6 +26,7 @@ private: GraphicsBool* m_skip_efb_cpu; GraphicsBool* m_ignore_format_changes; GraphicsBool* m_store_efb_copies; + GraphicsBool* m_defer_efb_copies; // Texture Cache QLabel* m_accuracy_label; @@ -42,7 +43,7 @@ private: GraphicsBool* m_disable_bounding_box; GraphicsBool* m_vertex_rounding; GraphicsBool* m_save_texture_cache_state; - GraphicsBool* m_defer_efb_copies; + GraphicsBool* m_fast_texture_sampling; void CreateWidgets(); void ConnectWidgets(); diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index bff76d4246..fd9933c2ae 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -537,6 +537,7 @@ void UpdateBoundingBox(float2 rawpos) {{ fmt::arg("efb_height", EFB_HEIGHT), fmt::arg("efb_scale", I_EFBSCALE)); } + if (host_config.manual_texture_sampling) { if (api_type == APIType::OpenGL || api_type == APIType::Vulkan) { @@ -596,6 +597,21 @@ uint WrapCoord(int coord, uint wrap, int size) {{ "int2 uv, int layer) {{\n"); } + if (!host_config.manual_texture_sampling) + { + out.Write(" float size_s = float(" I_TEXDIMS "[texmap].x * 128);\n" + " float size_t = float(" I_TEXDIMS "[texmap].y * 128);\n" + " float3 coords = float3(float(uv.x) / size_s, float(uv.y) / size_t, layer);\n"); + if (api_type == APIType::OpenGL || api_type == APIType::Vulkan) + { + out.Write(" return iround(255.0 * texture(tex, coords));\n}}\n"); + } + else if (api_type == APIType::D3D) + { + out.Write(" return iround(255.0 * tex.Sample(tex_samp, coords));\n}}\n"); + } + } + else { out.Write(R"( uint texmode0 = samp_texmode0(texmap); diff --git a/Source/Core/VideoCommon/ShaderGenCommon.cpp b/Source/Core/VideoCommon/ShaderGenCommon.cpp index 72a7e0d14f..49fd1c9783 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.cpp +++ b/Source/Core/VideoCommon/ShaderGenCommon.cpp @@ -39,6 +39,7 @@ ShaderHostConfig ShaderHostConfig::GetCurrent() bits.backend_logic_op = g_ActiveConfig.backend_info.bSupportsLogicOp; bits.backend_palette_conversion = g_ActiveConfig.backend_info.bSupportsPaletteConversion; bits.enable_validation_layer = g_ActiveConfig.bEnableValidationLayer; + bits.manual_texture_sampling = !g_ActiveConfig.bFastTextureSampling; return bits; } diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index ebdcda262b..46d34e18c6 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -169,6 +169,7 @@ union ShaderHostConfig BitField<21, 1, bool, u32> backend_logic_op; BitField<22, 1, bool, u32> backend_palette_conversion; BitField<23, 1, bool, u32> enable_validation_layer; + BitField<24, 1, bool, u32> manual_texture_sampling; static ShaderHostConfig GetCurrent(); }; diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 255e1722b9..88ec126c7c 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -135,6 +135,7 @@ void VideoConfig::Refresh() bVertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING); iEFBAccessTileSize = Config::Get(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE); iMissingColorValue = Config::Get(Config::GFX_HACK_MISSING_COLOR_VALUE); + bFastTextureSampling = Config::Get(Config::GFX_HACK_FAST_TEXTURE_SAMPLING); bPerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index d4307c479a..40922b3ecf 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -135,6 +135,7 @@ struct VideoConfig final int iLog = 0; // CONF_ bits int iSaveTargetId = 0; // TODO: Should be dropped u32 iMissingColorValue = 0; + bool bFastTextureSampling = false; // Stereoscopy StereoMode stereo_mode{};