Merge pull request #3672 from EmptyChaos/d3d-anisotropy

Fix D3D Forced Anisotropy
This commit is contained in:
Pierre Bourdon 2016-03-26 03:25:01 +01:00
commit 2fd0884347
11 changed files with 85 additions and 23 deletions

View File

@ -104,13 +104,13 @@ static wxString prog_scan_desc = wxTRANSLATE("Enables progressive scan if suppor
static wxString ar_desc = wxTRANSLATE("Select what aspect ratio to use when rendering:\nAuto: Use the native aspect ratio\nForce 16:9: Mimic an analog TV with a widescreen aspect ratio.\nForce 4:3: Mimic a standard 4:3 analog TV.\nStretch to Window: Stretch the picture to the window size.\n\nIf unsure, select Auto.");
static wxString ws_hack_desc = wxTRANSLATE("Forces the game to output graphics for any aspect ratio.\nUse with \"Aspect Ratio\" set to \"Force 16:9\" to force 4:3-only games to run at 16:9.\nRarely produces good results and often partially breaks graphics and game UIs.\nUnnecessary (and detrimental) if using any AR/Gecko-code widescreen patches.\n\nIf unsure, leave this unchecked.");
static wxString vsync_desc = wxTRANSLATE("Wait for vertical blanks in order to reduce tearing.\nDecreases performance if emulation speed is below 100%.\n\nIf unsure, leave this unchecked.");
static wxString af_desc = wxTRANSLATE("Enable anisotropic filtering.\nEnhances visual quality of textures that are at oblique viewing angles.\nMight cause issues in a small number of games.\nOn Direct3D, setting this above 1x will also have the same effect as enabling \"Force Texture Filtering\".\n\nIf unsure, select 1x.");
static wxString af_desc = wxTRANSLATE("Enable anisotropic filtering.\nEnhances visual quality of textures that are at oblique viewing angles.\nMight cause issues in a small number of games.\n\nIf unsure, select 1x.");
static wxString aa_desc = wxTRANSLATE("Reduces the amount of aliasing caused by rasterizing 3D graphics. This smooths out jagged edges on objects.\nIncreases GPU load and sometimes causes graphical issues. SSAA is significantly more demanding than MSAA, but provides top quality geometry anti-aliasing and also applies anti-aliasing to lighting, shader effects, and textures.\n\nIf unsure, select None.");
static wxString scaled_efb_copy_desc = wxTRANSLATE("Greatly increases quality of textures generated using render-to-texture effects.\nRaising the internal resolution will improve the effect of this setting.\nSlightly increases GPU load and causes relatively few graphical issues.\n\nIf unsure, leave this checked.");
static wxString pixel_lighting_desc = wxTRANSLATE("Calculates lighting of 3D objects per-pixel rather than per-vertex, smoothing out the appearance of lit polygons and making individual triangles less noticeable.\nRarely causes slowdowns or graphical issues.\n\nIf unsure, leave this unchecked.");
static wxString fast_depth_calc_desc = wxTRANSLATE("Use a less accurate algorithm to calculate depth values.\nCauses issues in a few games, but can give a decent speedup depending on the game and/or your GPU.\n\nIf unsure, leave this checked.");
static wxString disable_bbox_desc = wxTRANSLATE("Disable the bounding box emulation.\nThis may improve the GPU performance a lot, but some games will break.\n\nIf unsure, leave this checked.");
static wxString force_filtering_desc = wxTRANSLATE("Filter all textures, including any that the game explicitly set as unfiltered.\nMay improve quality of certain textures in some games, but will cause issues in others.\nOn Direct3D, setting Anisotropic Filtering above 1x will also have the same effect as enabling this option.\n\nIf unsure, leave this unchecked.");
static wxString force_filtering_desc = wxTRANSLATE("Filter all textures, including any that the game explicitly set as unfiltered.\nMay improve quality of certain textures in some games, but will cause issues in others.\n\nIf unsure, leave this unchecked.");
static wxString borderless_fullscreen_desc = wxTRANSLATE("Implement fullscreen mode with a borderless window spanning the whole screen instead of using exclusive mode.\nAllows for faster transitions between fullscreen and windowed mode, but slightly increases input latency, makes movement less smooth and slightly decreases performance.\nExclusive mode is required for Nvidia 3D Vision to work in the Direct3D backend.\n\nIf unsure, leave this unchecked.");
static wxString internal_res_desc = wxTRANSLATE("Specifies the resolution used to render at. A high resolution greatly improves visual quality, but also greatly increases GPU load and can cause issues in certain games.\n\"Multiple of 640x528\" will result in a size slightly larger than \"Window Size\" but yield fewer issues. Generally speaking, the lower the internal resolution is, the better your performance will be. Auto (Window Size), 1.5x, and 2.5x may cause issues in some games.\n\nIf unsure, select Native.");
static wxString efb_access_desc = wxTRANSLATE("Ignore any requests from the CPU to read from or write to the EFB.\nImproves performance in some games, but might disable some gameplay-related features or graphical effects.\n\nIf unsure, leave this unchecked.");

View File

@ -2,6 +2,8 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include "Common/BitSet.h"
#include "Common/CommonTypes.h"
#include "Common/MsgHandler.h"
@ -9,6 +11,7 @@
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DState.h"
#include "VideoCommon/SamplerCommon.h"
namespace DX11
{
@ -259,7 +262,7 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)
unsigned int mip = d3dMipFilters[state.min_filter & 3];
if (state.max_anisotropy > 1)
if (state.max_anisotropy > 1 && !SamplerCommon::IsBpTexMode0PointFiltering(state))
{
sampdc.Filter = D3D11_FILTER_ANISOTROPIC;
sampdc.MaxAnisotropy = (u32)state.max_anisotropy;
@ -310,8 +313,8 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)
sampdc.AddressU = d3dClamps[state.wrap_s];
sampdc.AddressV = d3dClamps[state.wrap_t];
sampdc.MaxLOD = (mip == TexMode0::TEXF_NONE) ? 0.0f : (float)state.max_lod / 16.f;
sampdc.MinLOD = (float)state.min_lod / 16.f;
sampdc.MaxLOD = SamplerCommon::AreBpTexMode0MipmapsEnabled(state) ? state.max_lod / 16.f : 0.f;
sampdc.MinLOD = std::min(state.min_lod / 16.f, sampdc.MaxLOD);
sampdc.MipLODBias = (s32)state.lod_bias / 32.0f;
ID3D11SamplerState* res = nullptr;

View File

@ -36,6 +36,7 @@
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/VideoConfig.h"
namespace DX11
@ -1200,7 +1201,8 @@ void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
if (g_ActiveConfig.bForceFiltering)
{
gx_state.sampler[stage].min_filter = 6; // 4 (linear mip) | 2 (linear min)
// Only use mipmaps if the game says they are available.
gx_state.sampler[stage].min_filter = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? 6 : 4;
gx_state.sampler[stage].mag_filter = 1; // linear mag
}
else

View File

@ -2,6 +2,8 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include "Common/BitSet.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
@ -20,6 +22,7 @@
#include "VideoBackends/D3D12/ShaderCache.h"
#include "VideoBackends/D3D12/StaticShaderCache.h"
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VideoConfig.h"
@ -185,7 +188,7 @@ D3D12_SAMPLER_DESC StateCache::GetDesc12(SamplerState state)
unsigned int mip = d3d_mip_filters[state.min_filter & 3];
sampdc.MaxAnisotropy = 1;
if (g_ActiveConfig.iMaxAnisotropy > 1)
if (g_ActiveConfig.iMaxAnisotropy > 0 && !SamplerCommon::IsBpTexMode0PointFiltering(state))
{
sampdc.Filter = D3D12_FILTER_ANISOTROPIC;
sampdc.MaxAnisotropy = 1 << g_ActiveConfig.iMaxAnisotropy;
@ -241,8 +244,8 @@ D3D12_SAMPLER_DESC StateCache::GetDesc12(SamplerState state)
sampdc.BorderColor[0] = sampdc.BorderColor[1] = sampdc.BorderColor[2] = sampdc.BorderColor[3] = 1.0f;
sampdc.MaxLOD = (mip == TexMode0::TEXF_NONE) ? 0.0f : static_cast<float>(state.max_lod) / 16.f;
sampdc.MinLOD = static_cast<float>(state.min_lod) / 16.f;
sampdc.MaxLOD = SamplerCommon::AreBpTexMode0MipmapsEnabled(state) ? state.max_lod / 16.f : 0.f;
sampdc.MinLOD = std::min(state.min_lod / 16.f, sampdc.MaxLOD);
sampdc.MipLODBias = static_cast<s32>(state.lod_bias) / 32.0f;
return sampdc;

View File

@ -39,6 +39,7 @@
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VideoConfig.h"
@ -1245,7 +1246,8 @@ void Renderer::SetSamplerState(int stage, int tex_index, bool custom_tex)
if (g_ActiveConfig.bForceFiltering)
{
new_state.min_filter = 6; // 4 (linear min) | 2 (linear mip)
// Only use mipmaps if the game says they are available.
new_state.min_filter = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? 6 : 4;
new_state.mag_filter = 1; // linear mag
}
else

View File

@ -8,6 +8,7 @@
#include "Common/CommonTypes.h"
#include "Common/GL/GLInterfaceBase.h"
#include "VideoBackends/OGL/SamplerCache.h"
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/VideoConfig.h"
namespace OGL
@ -59,8 +60,8 @@ void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode
// take equivalent forced linear when bForceFiltering
if (g_ActiveConfig.bForceFiltering)
{
params.tm0.min_filter |= 0x4;
params.tm0.mag_filter |= 0x1;
params.tm0.min_filter = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? 6 : 4;
params.tm0.mag_filter = 1;
}
// custom textures may have higher resolution, so disable the max_lod
@ -122,9 +123,6 @@ void SamplerCache::SetParameters(GLuint sampler_id, const Params& params)
auto& tm0 = params.tm0;
auto& tm1 = params.tm1;
glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER, min_filters[tm0.min_filter % ArraySize(min_filters)]);
glSamplerParameteri(sampler_id, GL_TEXTURE_MAG_FILTER, tm0.mag_filter ? GL_LINEAR : GL_NEAREST);
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, wrap_settings[tm0.wrap_s]);
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, wrap_settings[tm0.wrap_t]);
@ -134,10 +132,28 @@ void SamplerCache::SetParameters(GLuint sampler_id, const Params& params)
if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL)
glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, (s32)tm0.lod_bias / 32.f);
if (g_ActiveConfig.iMaxAnisotropy > 0 && g_ogl_config.bSupportsAniso)
GLint min_filter = min_filters[tm0.min_filter];
GLint mag_filter = tm0.mag_filter ? GL_LINEAR : GL_NEAREST;
if (g_ActiveConfig.iMaxAnisotropy > 0 && g_ogl_config.bSupportsAniso &&
!SamplerCommon::IsBpTexMode0PointFiltering(tm0))
{
// https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
// For predictable results on all hardware/drivers, only use one of:
// GL_LINEAR + GL_LINEAR (No Mipmaps [Bilinear])
// GL_LINEAR + GL_LINEAR_MIPMAP_LINEAR (w/ Mipmaps [Trilinear])
// Letting the game set other combinations will have varying arbitrary results;
// possibly being interpreted as equal to bilinear/trilinear, implicitly
// disabling anisotropy, or changing the anisotropic algorithm employed.
min_filter = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
mag_filter = GL_LINEAR;
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
}
glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER, min_filter);
glSamplerParameteri(sampler_id, GL_TEXTURE_MAG_FILTER, mag_filter);
}
void SamplerCache::Clear()
{
for (auto& p : m_cache)

View File

@ -10,6 +10,7 @@
#include "VideoBackends/Software/TextureSampler.h"
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/TextureDecoder.h"
#define ALLOW_MIPMAP 1
@ -69,14 +70,14 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
s32 lodFract = lod & 0xf;
if (lod > 0 && tm0.min_filter & 3)
if (lod > 0 && SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0))
{
// use mipmap
baseMip = lod >> 4;
mipLinear = (lodFract && tm0.min_filter & 2);
mipLinear = (lodFract && tm0.min_filter & TexMode0::TEXF_LINEAR);
// if using nearest mip filter and lodFract >= 0.5 round up to next mip
baseMip += (lodFract >> 3) & (tm0.min_filter & 1);
baseMip += (lodFract >> 3) & (tm0.min_filter & TexMode0::TEXF_POINT);
}
if (mipLinear)

View File

@ -0,0 +1,30 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
namespace SamplerCommon
{
// Helper for checking if a BPMemory TexMode0 register is set to Point
// Filtering modes. This is used to decide whether Anisotropic enhancements
// are (mostly) safe in the VideoBackends.
// If both the minification and magnification filters are set to POINT modes
// then applying anisotropic filtering is equivalent to forced filtering. Point
// mode textures are usually some sort of 2D UI billboard which will end up
// misaligned from the correct pixels when filtered anisotropically.
template<class T>
constexpr bool IsBpTexMode0PointFiltering(const T& tm0)
{
return tm0.min_filter < 4 && !tm0.mag_filter;
}
// Check if the minification filter has mipmap based filtering modes enabled.
template<class T>
constexpr bool AreBpTexMode0MipmapsEnabled(const T& tm0)
{
return (tm0.min_filter & 3) != 0;
}
}

View File

@ -26,6 +26,7 @@
#include "VideoCommon/FramebufferManagerBase.h"
#include "VideoCommon/HiresTextures.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/TextureDecoder.h"
@ -440,7 +441,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
const int texformat = tex.texImage0[id].format;
const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9;
const u32 tlutfmt = tex.texTlut[id].tlut_format;
const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0;
const bool use_mipmaps = SamplerCommon::AreBpTexMode0MipmapsEnabled(tex.texMode0[id]);
u32 tex_levels = use_mipmaps ? ((tex.texMode1[id].max_lod + 0xf) / 0x10 + 1) : 1;
const bool from_tmem = tex.texImage1[id].image_type != 0;

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
@ -133,6 +133,7 @@
<ClInclude Include="PixelShaderManager.h" />
<ClInclude Include="PostProcessing.h" />
<ClInclude Include="RenderBase.h" />
<ClInclude Include="SamplerCommon.h" />
<ClInclude Include="ShaderGenCommon.h" />
<ClInclude Include="Statistics.h" />
<ClInclude Include="GeometryShaderGen.h" />

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Base">
@ -302,6 +302,9 @@
<ClInclude Include="GeometryShaderManager.h">
<Filter>Shader Managers</Filter>
</ClInclude>
<ClInclude Include="SamplerCommon.h">
<Filter>Util</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />