summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/RenderState.cpp
diff options
context:
space:
mode:
authorPokechu22 <Pokechu022@gmail.com>2021-08-08 21:11:50 -0700
committerPokechu22 <Pokechu022@gmail.com>2021-11-17 20:04:34 -0800
commit4a9b26de86aa7e99af51016e07a755968b8777e0 (patch)
treec8b81ec25625e1d33d3b5a89e76329cf02d25e12 /Source/Core/VideoCommon/RenderState.cpp
parent9ef228503abe24820985e431ef942c6ebb312442 (diff)
VideoCommon: Expose SamplerState to shaders
The benefit to exposing this over the raw BP state is that adjustments Dolphin makes, such as LOD biases from arbitrary mipmap detection, will work properly.
Diffstat (limited to 'Source/Core/VideoCommon/RenderState.cpp')
-rw-r--r--Source/Core/VideoCommon/RenderState.cpp86
1 files changed, 53 insertions, 33 deletions
diff --git a/Source/Core/VideoCommon/RenderState.cpp b/Source/Core/VideoCommon/RenderState.cpp
index d84a17257e..15559ae67f 100644
--- a/Source/Core/VideoCommon/RenderState.cpp
+++ b/Source/Core/VideoCommon/RenderState.cpp
@@ -202,27 +202,42 @@ void BlendingState::ApproximateLogicOpWithBlending()
void SamplerState::Generate(const BPMemory& bp, u32 index)
{
auto tex = bp.tex.GetUnit(index);
- const TexMode0& tm0 = tex.texMode0;
- const TexMode1& tm1 = tex.texMode1;
+ const TexMode0& bp_tm0 = tex.texMode0;
+ const TexMode1& bp_tm1 = tex.texMode1;
// GX can configure the mip filter to none. However, D3D and Vulkan can't express this in their
// sampler states. Therefore, we set the min/max LOD to zero if this option is used.
- min_filter = tm0.min_filter == FilterMode::Linear ? Filter::Linear : Filter::Point;
- mipmap_filter = tm0.mipmap_filter == MipMode::Linear ? Filter::Linear : Filter::Point;
- mag_filter = tm0.mag_filter == FilterMode::Linear ? Filter::Linear : Filter::Point;
+ tm0.min_filter = bp_tm0.min_filter;
+ tm0.mipmap_filter =
+ bp_tm0.mipmap_filter == MipMode::Linear ? FilterMode::Linear : FilterMode::Near;
+ tm0.mag_filter = bp_tm0.mag_filter;
// If mipmaps are disabled, clamp min/max lod
- max_lod = tm0.mipmap_filter != MipMode::None ? tm1.max_lod.Value() : 0;
- min_lod = std::min(max_lod.Value(), static_cast<u64>(tm1.min_lod));
- lod_bias = tm0.mipmap_filter != MipMode::None ? tm0.lod_bias * (256 / 32) : 0;
+ if (bp_tm0.mipmap_filter == MipMode::None)
+ {
+ tm1.max_lod = 0;
+ tm1.min_lod = 0;
+ tm0.lod_bias = 0;
+ }
+ else
+ {
+ // NOTE: When comparing, max is checked first, then min; if max is less than min, max wins
+ tm1.max_lod = bp_tm1.max_lod.Value();
+ tm1.min_lod = std::min(tm1.max_lod.Value(), bp_tm1.min_lod.Value());
+ tm0.lod_bias = bp_tm0.lod_bias * (256 / 32);
+ }
- // Address modes
+ // Wrap modes
// Hardware testing indicates that wrap_mode set to 3 behaves the same as clamp.
- static constexpr std::array<AddressMode, 4> address_modes = {
- {AddressMode::Clamp, AddressMode::Repeat, AddressMode::MirroredRepeat, AddressMode::Clamp}};
- wrap_u = address_modes[u32(tm0.wrap_s.Value())];
- wrap_v = address_modes[u32(tm0.wrap_t.Value())];
- anisotropic_filtering = 0;
+ auto filter_invalid_wrap = [](WrapMode mode) {
+ return (mode <= WrapMode::Mirror) ? mode : WrapMode::Clamp;
+ };
+ tm0.wrap_u = filter_invalid_wrap(bp_tm0.wrap_s);
+ tm0.wrap_v = filter_invalid_wrap(bp_tm0.wrap_t);
+
+ tm0.diag_lod = bp_tm0.diag_lod;
+ tm0.anisotropic_filtering = false; // TODO: Respect BP anisotropic filtering mode
+ tm0.lod_clamp = bp_tm0.lod_clamp; // TODO: What does this do?
}
namespace RenderState
@@ -315,37 +330,42 @@ BlendingState GetNoColorWriteBlendState()
SamplerState GetInvalidSamplerState()
{
SamplerState state;
- state.hex = UINT64_C(0xFFFFFFFFFFFFFFFF);
+ state.tm0.hex = 0xFFFFFFFF;
+ state.tm1.hex = 0xFFFFFFFF;
return state;
}
SamplerState GetPointSamplerState()
{
SamplerState state = {};
- state.min_filter = SamplerState::Filter::Point;
- state.mag_filter = SamplerState::Filter::Point;
- state.mipmap_filter = SamplerState::Filter::Point;
- state.wrap_u = SamplerState::AddressMode::Clamp;
- state.wrap_v = SamplerState::AddressMode::Clamp;
- state.min_lod = 0;
- state.max_lod = 255;
- state.lod_bias = 0;
- state.anisotropic_filtering = false;
+ state.tm0.min_filter = FilterMode::Near;
+ state.tm0.mag_filter = FilterMode::Near;
+ state.tm0.mipmap_filter = FilterMode::Near;
+ state.tm0.wrap_u = WrapMode::Clamp;
+ state.tm0.wrap_v = WrapMode::Clamp;
+ state.tm1.min_lod = 0;
+ state.tm1.max_lod = 255;
+ state.tm0.lod_bias = 0;
+ state.tm0.anisotropic_filtering = false;
+ state.tm0.diag_lod = LODType::Edge;
+ state.tm0.lod_clamp = false;
return state;
}
SamplerState GetLinearSamplerState()
{
SamplerState state = {};
- state.min_filter = SamplerState::Filter::Linear;
- state.mag_filter = SamplerState::Filter::Linear;
- state.mipmap_filter = SamplerState::Filter::Linear;
- state.wrap_u = SamplerState::AddressMode::Clamp;
- state.wrap_v = SamplerState::AddressMode::Clamp;
- state.min_lod = 0;
- state.max_lod = 255;
- state.lod_bias = 0;
- state.anisotropic_filtering = false;
+ state.tm0.min_filter = FilterMode::Linear;
+ state.tm0.mag_filter = FilterMode::Linear;
+ state.tm0.mipmap_filter = FilterMode::Linear;
+ state.tm0.wrap_u = WrapMode::Clamp;
+ state.tm0.wrap_v = WrapMode::Clamp;
+ state.tm1.min_lod = 0;
+ state.tm1.max_lod = 255;
+ state.tm0.lod_bias = 0;
+ state.tm0.anisotropic_filtering = false;
+ state.tm0.diag_lod = LODType::Edge;
+ state.tm0.lod_clamp = false;
return state;
}