mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 15:31:17 +01:00
4a9b26de86
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.
119 lines
3.8 KiB
C++
119 lines
3.8 KiB
C++
// Copyright 2013 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "VideoBackends/OGL/SamplerCache.h"
|
|
#include "VideoBackends/OGL/OGLRender.h"
|
|
|
|
#include <memory>
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "VideoCommon/VideoConfig.h"
|
|
|
|
namespace OGL
|
|
{
|
|
std::unique_ptr<SamplerCache> g_sampler_cache;
|
|
|
|
SamplerCache::SamplerCache()
|
|
{
|
|
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(1, &m_point_sampler);
|
|
glDeleteSamplers(1, &m_linear_sampler);
|
|
}
|
|
|
|
void SamplerCache::BindNearestSampler(int stage)
|
|
{
|
|
glBindSampler(stage, m_point_sampler);
|
|
}
|
|
|
|
void SamplerCache::BindLinearSampler(int stage)
|
|
{
|
|
glBindSampler(stage, m_linear_sampler);
|
|
}
|
|
|
|
void SamplerCache::SetSamplerState(u32 stage, const SamplerState& state)
|
|
{
|
|
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())
|
|
{
|
|
GLuint sampler;
|
|
glGenSamplers(1, &sampler);
|
|
SetParameters(sampler, state);
|
|
it = m_cache.emplace(state, sampler).first;
|
|
}
|
|
|
|
m_active_samplers[stage].first = state;
|
|
m_active_samplers[stage].second = it->second;
|
|
glBindSampler(stage, it->second);
|
|
}
|
|
|
|
void SamplerCache::InvalidateBinding(u32 stage)
|
|
{
|
|
m_active_samplers[stage].second = 0;
|
|
}
|
|
|
|
void SamplerCache::SetParameters(GLuint sampler_id, const SamplerState& params)
|
|
{
|
|
GLenum min_filter;
|
|
GLenum mag_filter = (params.tm0.mag_filter == FilterMode::Near) ? GL_NEAREST : GL_LINEAR;
|
|
if (params.tm0.mipmap_filter == FilterMode::Linear)
|
|
{
|
|
min_filter = (params.tm0.min_filter == FilterMode::Near) ? GL_NEAREST_MIPMAP_LINEAR :
|
|
GL_LINEAR_MIPMAP_LINEAR;
|
|
}
|
|
else
|
|
{
|
|
min_filter = (params.tm0.min_filter == FilterMode::Near) ? 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.tm0.wrap_u.Value())]);
|
|
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T,
|
|
address_modes[static_cast<u32>(params.tm0.wrap_v.Value())]);
|
|
|
|
glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, params.tm1.min_lod / 16.f);
|
|
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, params.tm1.max_lod / 16.f);
|
|
|
|
if (!static_cast<Renderer*>(g_renderer.get())->IsGLES())
|
|
glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, params.tm0.lod_bias / 256.f);
|
|
|
|
if (params.tm0.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);
|
|
for (auto& p : m_active_samplers)
|
|
p.second = 0;
|
|
m_cache.clear();
|
|
}
|
|
} // namespace OGL
|