summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/TextureCacheBase.cpp
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2019-01-30 00:47:01 +1000
committerStenzek <stenzek@gmail.com>2019-02-17 16:35:43 +1000
commit50bdcb8d9ce0cf7531c428c8bc565e7cead01b33 (patch)
tree3cbf1f5992115d6b9394690848790b7c9768ef49 /Source/Core/VideoCommon/TextureCacheBase.cpp
parent286aafd4ed2949f0b93230fee969c6a32fe75f07 (diff)
TextureCache: Bind textures/samplers after loading all textures
Since loading textures can result in rendering, e.g. partial copies, we don't want to disturb partially-bound GX state.
Diffstat (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp')
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp72
1 files changed, 70 insertions, 2 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index a42438e0b1..d0355b724b 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -33,6 +33,7 @@
#include "VideoCommon/Debugger.h"
#include "VideoCommon/FramebufferManagerBase.h"
#include "VideoCommon/HiresTextures.h"
+#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/Statistics.h"
@@ -482,12 +483,79 @@ static u32 CalculateLevelSize(u32 level_0_size, u32 level)
return std::max(level_0_size >> level, 1u);
}
+static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex,
+ bool has_arbitrary_mips)
+{
+ const FourTexUnits& tex = bpmem.tex[index / 4];
+ const TexMode0& tm0 = tex.texMode0[index % 4];
+
+ SamplerState state = {};
+ state.Generate(bpmem, index);
+
+ // Force texture filtering config option.
+ if (g_ActiveConfig.bForceFiltering)
+ {
+ state.min_filter = SamplerState::Filter::Linear;
+ state.mag_filter = SamplerState::Filter::Linear;
+ state.mipmap_filter = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ?
+ SamplerState::Filter::Linear :
+ SamplerState::Filter::Point;
+ }
+
+ // Custom textures may have a greater number of mips
+ if (custom_tex)
+ state.max_lod = 255;
+
+ // Anisotropic filtering option.
+ if (g_ActiveConfig.iMaxAnisotropy != 0 && !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.
+ state.min_filter = SamplerState::Filter::Linear;
+ state.mag_filter = SamplerState::Filter::Linear;
+ if (SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0))
+ state.mipmap_filter = SamplerState::Filter::Linear;
+ state.anisotropic_filtering = 1;
+ }
+ else
+ {
+ state.anisotropic_filtering = 0;
+ }
+
+ if (has_arbitrary_mips && SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0))
+ {
+ // Apply a secondary bias calculated from the IR scale to pull inwards mipmaps
+ // that have arbitrary contents, eg. are used for fog effects where the
+ // distance they kick in at is important to preserve at any resolution.
+ // Correct this with the upscaling factor of custom textures.
+ s64 lod_offset = std::log2(g_renderer->GetEFBScale() / custom_tex_scale) * 256.f;
+ state.lod_bias = MathUtil::Clamp<s64>(state.lod_bias + lod_offset, -32768, 32767);
+
+ // Anisotropic also pushes mips farther away so it cannot be used either
+ state.anisotropic_filtering = 0;
+ }
+
+ g_renderer->SetSamplerState(index, state);
+}
+
void TextureCacheBase::BindTextures()
{
for (u32 i = 0; i < bound_textures.size(); i++)
{
- if (IsValidBindPoint(i) && bound_textures[i])
- g_renderer->SetTexture(i, bound_textures[i]->texture.get());
+ const TCacheEntry* tentry = bound_textures[i];
+ if (IsValidBindPoint(i) && tentry)
+ {
+ g_renderer->SetTexture(i, tentry->texture.get());
+ PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height);
+
+ const float custom_tex_scale = tentry->GetWidth() / float(tentry->native_width);
+ SetSamplerState(i, custom_tex_scale, tentry->is_custom_tex, tentry->has_arbitrary_mips);
+ }
}
}