mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
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.
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user