mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 22:09:19 -07:00
f295182833
Approximately three or four times now, the issue of pointers being in an inconsistent state been an issue in the video backend renderers with regards to tripping up other developers. Global (ugh) resources are put into a unique_ptr and will always have a well-defined state of being - null or not null
150 lines
4.1 KiB
C++
150 lines
4.1 KiB
C++
// Copyright 2013 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <memory>
|
|
|
|
#include "Common/GL/GLInterfaceBase.h"
|
|
#include "VideoBackends/OGL/SamplerCache.h"
|
|
#include "VideoCommon/DriverDetails.h"
|
|
#include "VideoCommon/VideoConfig.h"
|
|
|
|
namespace OGL
|
|
{
|
|
|
|
std::unique_ptr<SamplerCache> g_sampler_cache;
|
|
|
|
SamplerCache::SamplerCache()
|
|
: m_last_max_anisotropy()
|
|
{
|
|
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);
|
|
}
|
|
|
|
SamplerCache::~SamplerCache()
|
|
{
|
|
Clear();
|
|
glDeleteSamplers(2, m_sampler_id);
|
|
}
|
|
|
|
void SamplerCache::BindNearestSampler(int stage)
|
|
{
|
|
glBindSampler(stage, m_sampler_id[0]);
|
|
}
|
|
|
|
void SamplerCache::BindLinearSampler(int stage)
|
|
{
|
|
glBindSampler(stage, m_sampler_id[1]);
|
|
}
|
|
|
|
void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1, bool custom_tex)
|
|
{
|
|
// TODO: can this go somewhere else?
|
|
if (m_last_max_anisotropy != g_ActiveConfig.iMaxAnisotropy)
|
|
{
|
|
m_last_max_anisotropy = g_ActiveConfig.iMaxAnisotropy;
|
|
Clear();
|
|
}
|
|
|
|
Params params(tm0, tm1);
|
|
|
|
// take equivalent forced linear when bForceFiltering
|
|
if (g_ActiveConfig.bForceFiltering)
|
|
{
|
|
params.tm0.min_filter |= 0x4;
|
|
params.tm0.mag_filter |= 0x1;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
SamplerCache::Value& SamplerCache::GetEntry(const Params& params)
|
|
{
|
|
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;
|
|
}
|
|
|
|
void SamplerCache::SetParameters(GLuint sampler_id, const Params& 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_MIN_FILTER, min_filters[tm0.min_filter % ArraySize(min_filters)]);
|
|
glSamplerParameteri(sampler_id, GL_TEXTURE_MAG_FILTER, tm0.mag_filter ? GL_LINEAR : GL_NEAREST);
|
|
|
|
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);
|
|
|
|
if (g_ActiveConfig.iMaxAnisotropy > 0 && g_ogl_config.bSupportsAniso)
|
|
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
|
}
|
|
|
|
void SamplerCache::Clear()
|
|
{
|
|
for (auto& p : m_cache)
|
|
{
|
|
glDeleteSamplers(1, &p.second.sampler_id);
|
|
}
|
|
m_cache.clear();
|
|
}
|
|
|
|
}
|