mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 22:29:39 -06:00
VideoBackends: Move SamplerState to common
This commit is contained in:
@ -1119,7 +1119,8 @@ bool ProgramShaderCache::ShaderCompileWorkItem::Compile()
|
||||
gcode = GenerateGeometryShaderCode(APIType::OpenGL, host_config, m_uid.guid.GetUidData());
|
||||
|
||||
CompileShader(m_program, vcode.GetBuffer(), pcode.GetBuffer(), gcode.GetBuffer());
|
||||
DrawPrerenderArray(m_program, m_uid.guid.GetUidData()->primitive_type);
|
||||
DrawPrerenderArray(m_program,
|
||||
static_cast<PrimitiveType>(m_uid.guid.GetUidData()->primitive_type));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1157,7 +1158,8 @@ bool ProgramShaderCache::UberShaderCompileWorkItem::Compile()
|
||||
gcode = GenerateGeometryShaderCode(APIType::OpenGL, host_config, m_uid.guid.GetUidData());
|
||||
|
||||
CompileShader(m_program, vcode.GetBuffer(), pcode.GetBuffer(), gcode.GetBuffer());
|
||||
DrawPrerenderArray(m_program, m_uid.guid.GetUidData()->primitive_type);
|
||||
DrawPrerenderArray(m_program,
|
||||
static_cast<PrimitiveType>(m_uid.guid.GetUidData()->primitive_type));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1503,9 +1503,13 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||
|
||||
g_Config.iSaveTargetId = 0;
|
||||
|
||||
int old_anisotropy = g_ActiveConfig.iMaxAnisotropy;
|
||||
UpdateActiveConfig();
|
||||
g_texture_cache->OnConfigChanged(g_ActiveConfig);
|
||||
|
||||
if (old_anisotropy != g_ActiveConfig.iMaxAnisotropy)
|
||||
g_sampler_cache->Clear();
|
||||
|
||||
// Invalidate shader cache when the host config changes.
|
||||
if (CheckForHostConfigChanges())
|
||||
ProgramShaderCache::Reload();
|
||||
@ -1834,13 +1838,9 @@ void Renderer::SetDepthState(const DepthState& state)
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
|
||||
void Renderer::SetSamplerState(u32 index, const SamplerState& state)
|
||||
{
|
||||
auto const& tex = bpmem.tex[texindex];
|
||||
auto const& tm0 = tex.texMode0[stage];
|
||||
auto const& tm1 = tex.texMode1[stage];
|
||||
|
||||
g_sampler_cache->SetSamplerState((texindex * 4) + stage, tm0, tm1, custom_tex);
|
||||
g_sampler_cache->SetSamplerState(index, state);
|
||||
}
|
||||
|
||||
void Renderer::SetInterlacingMode()
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
void SetScissorRect(const EFBRectangle& rc) override;
|
||||
void SetRasterizationState(const RasterizationState& state) override;
|
||||
void SetDepthState(const DepthState& state) override;
|
||||
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
|
||||
void SetSamplerState(u32 index, const SamplerState& state) override;
|
||||
void SetInterlacingMode() override;
|
||||
void SetViewport() override;
|
||||
|
||||
|
@ -15,141 +15,106 @@ namespace OGL
|
||||
{
|
||||
std::unique_ptr<SamplerCache> g_sampler_cache;
|
||||
|
||||
SamplerCache::SamplerCache() : m_last_max_anisotropy()
|
||||
SamplerCache::SamplerCache()
|
||||
{
|
||||
glGenSamplers(2, m_sampler_id);
|
||||
glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glGenSamplers(1, &m_point_sampler);
|
||||
glGenSamplers(1, &m_linear_sampler);
|
||||
glSamplerParameteri(m_point_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(m_point_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(m_point_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_point_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_linear_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(m_linear_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(m_linear_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_linear_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
SamplerCache::~SamplerCache()
|
||||
{
|
||||
Clear();
|
||||
glDeleteSamplers(2, m_sampler_id);
|
||||
glDeleteSamplers(1, &m_point_sampler);
|
||||
glDeleteSamplers(1, &m_linear_sampler);
|
||||
}
|
||||
|
||||
void SamplerCache::BindNearestSampler(int stage)
|
||||
{
|
||||
glBindSampler(stage, m_sampler_id[0]);
|
||||
glBindSampler(stage, m_point_sampler);
|
||||
}
|
||||
|
||||
void SamplerCache::BindLinearSampler(int stage)
|
||||
{
|
||||
glBindSampler(stage, m_sampler_id[1]);
|
||||
glBindSampler(stage, m_linear_sampler);
|
||||
}
|
||||
|
||||
void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1,
|
||||
bool custom_tex)
|
||||
void SamplerCache::SetSamplerState(u32 stage, const SamplerState& state)
|
||||
{
|
||||
// TODO: can this go somewhere else?
|
||||
if (m_last_max_anisotropy != g_ActiveConfig.iMaxAnisotropy)
|
||||
if (m_active_samplers[stage].first == state && m_active_samplers[stage].second != 0)
|
||||
return;
|
||||
|
||||
auto it = m_cache.find(state);
|
||||
if (it == m_cache.end())
|
||||
{
|
||||
m_last_max_anisotropy = g_ActiveConfig.iMaxAnisotropy;
|
||||
Clear();
|
||||
GLuint sampler;
|
||||
glGenSamplers(1, &sampler);
|
||||
SetParameters(sampler, state);
|
||||
it = m_cache.emplace(state, sampler).first;
|
||||
}
|
||||
|
||||
Params params(tm0, tm1);
|
||||
|
||||
// take equivalent forced linear when bForceFiltering
|
||||
if (g_ActiveConfig.bForceFiltering)
|
||||
{
|
||||
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
|
||||
if (custom_tex)
|
||||
{
|
||||
params.tm1.max_lod = 255;
|
||||
}
|
||||
|
||||
// TODO: Should keep a circular buffer for each stage of recently used samplers.
|
||||
|
||||
auto& active_sampler = m_active_samplers[stage];
|
||||
if (active_sampler.first != params || !active_sampler.second.sampler_id)
|
||||
{
|
||||
// Active sampler does not match parameters (or is invalid), bind the proper one.
|
||||
active_sampler.first = params;
|
||||
active_sampler.second = GetEntry(params);
|
||||
glBindSampler(stage, active_sampler.second.sampler_id);
|
||||
}
|
||||
m_active_samplers[stage].first = state;
|
||||
m_active_samplers[stage].second = it->second;
|
||||
glBindSampler(stage, it->second);
|
||||
}
|
||||
|
||||
SamplerCache::Value& SamplerCache::GetEntry(const Params& params)
|
||||
void SamplerCache::InvalidateBinding(u32 stage)
|
||||
{
|
||||
auto& val = m_cache[params];
|
||||
if (!val.sampler_id)
|
||||
{
|
||||
// Sampler not found in cache, create it.
|
||||
glGenSamplers(1, &val.sampler_id);
|
||||
SetParameters(val.sampler_id, params);
|
||||
|
||||
// TODO: Maybe kill old samplers if the cache gets huge. It doesn't seem to get huge though.
|
||||
// ERROR_LOG(VIDEO, "Sampler cache size is now %ld.", m_cache.size());
|
||||
}
|
||||
|
||||
return val;
|
||||
m_active_samplers[stage].second = 0;
|
||||
}
|
||||
|
||||
void SamplerCache::SetParameters(GLuint sampler_id, const Params& params)
|
||||
void SamplerCache::SetParameters(GLuint sampler_id, const SamplerState& params)
|
||||
{
|
||||
static const GLint min_filters[8] = {
|
||||
GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST,
|
||||
GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,
|
||||
};
|
||||
|
||||
static const GLint wrap_settings[4] = {
|
||||
GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT, GL_REPEAT,
|
||||
};
|
||||
|
||||
auto& tm0 = params.tm0;
|
||||
auto& tm1 = params.tm1;
|
||||
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, wrap_settings[tm0.wrap_s]);
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, wrap_settings[tm0.wrap_t]);
|
||||
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, tm1.min_lod / 16.f);
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, tm1.max_lod / 16.f);
|
||||
|
||||
if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL)
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, (s32)tm0.lod_bias / 32.f);
|
||||
|
||||
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))
|
||||
GLenum min_filter;
|
||||
GLenum mag_filter = (params.mag_filter == SamplerState::Filter::Point) ? GL_NEAREST : GL_LINEAR;
|
||||
if (params.mipmap_filter == SamplerState::Filter::Linear)
|
||||
{
|
||||
// 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));
|
||||
min_filter = (params.min_filter == SamplerState::Filter::Point) ? GL_NEAREST_MIPMAP_LINEAR :
|
||||
GL_LINEAR_MIPMAP_LINEAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_filter = (params.min_filter == SamplerState::Filter::Point) ? GL_NEAREST_MIPMAP_NEAREST :
|
||||
GL_LINEAR_MIPMAP_NEAREST;
|
||||
}
|
||||
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||
|
||||
static constexpr std::array<GLenum, 3> address_modes = {
|
||||
{GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT}};
|
||||
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S,
|
||||
address_modes[static_cast<u32>(params.wrap_u.Value())]);
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T,
|
||||
address_modes[static_cast<u32>(params.wrap_v.Value())]);
|
||||
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, params.min_lod / 16.f);
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, params.max_lod / 16.f);
|
||||
|
||||
if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL)
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, params.lod_bias / 32.f);
|
||||
|
||||
if (params.anisotropic_filtering && g_ogl_config.bSupportsAniso)
|
||||
{
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
static_cast<float>(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
}
|
||||
}
|
||||
|
||||
void SamplerCache::Clear()
|
||||
{
|
||||
for (auto& p : m_cache)
|
||||
{
|
||||
glDeleteSamplers(1, &p.second.sampler_id);
|
||||
}
|
||||
glDeleteSamplers(1, &p.second);
|
||||
for (auto& p : m_active_samplers)
|
||||
p.second = 0;
|
||||
m_cache.clear();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
@ -24,49 +25,21 @@ public:
|
||||
SamplerCache(SamplerCache&&) = delete;
|
||||
SamplerCache& operator=(SamplerCache&&) = delete;
|
||||
|
||||
void SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1, bool custom_tex);
|
||||
void SetSamplerState(u32 stage, const SamplerState& state);
|
||||
void InvalidateBinding(u32 stage);
|
||||
|
||||
void Clear();
|
||||
void BindNearestSampler(int stage);
|
||||
void BindLinearSampler(int stage);
|
||||
|
||||
private:
|
||||
struct Params
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
TexMode0 tm0;
|
||||
TexMode1 tm1;
|
||||
};
|
||||
static void SetParameters(GLuint sampler_id, const SamplerState& params);
|
||||
|
||||
u64 hex;
|
||||
};
|
||||
std::map<SamplerState, GLuint> m_cache;
|
||||
std::array<std::pair<SamplerState, GLuint>, 8> m_active_samplers{};
|
||||
|
||||
Params() : hex() {}
|
||||
Params(const TexMode0& _tm0, const TexMode1& _tm1) : tm0(_tm0), tm1(_tm1)
|
||||
{
|
||||
static_assert(sizeof(Params) == 8, "Assuming I can treat this as a 64bit int.");
|
||||
}
|
||||
|
||||
bool operator<(const Params& other) const { return hex < other.hex; }
|
||||
bool operator!=(const Params& other) const { return hex != other.hex; }
|
||||
};
|
||||
|
||||
struct Value
|
||||
{
|
||||
Value() : sampler_id() {}
|
||||
GLuint sampler_id;
|
||||
};
|
||||
|
||||
void SetParameters(GLuint sampler_id, const Params& params);
|
||||
Value& GetEntry(const Params& params);
|
||||
|
||||
std::map<Params, Value> m_cache;
|
||||
std::pair<Params, Value> m_active_samplers[8];
|
||||
|
||||
int m_last_max_anisotropy;
|
||||
u32 m_sampler_id[2];
|
||||
GLuint m_point_sampler;
|
||||
GLuint m_linear_sampler;
|
||||
};
|
||||
|
||||
extern std::unique_ptr<SamplerCache> g_sampler_cache;
|
||||
|
Reference in New Issue
Block a user