mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-28 19:58:53 +00: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:
parent
9ef228503a
commit
4a9b26de86
14 changed files with 188 additions and 139 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue