Merge pull request #2318 from ReinUsesLisp/sampler-cache
gl_sampler_cache: Port sampler cache to OpenGL
This commit is contained in:
commit
4294062516
|
@ -46,6 +46,8 @@ add_library(video_core STATIC
|
||||||
renderer_opengl/gl_rasterizer_cache.h
|
renderer_opengl/gl_rasterizer_cache.h
|
||||||
renderer_opengl/gl_resource_manager.cpp
|
renderer_opengl/gl_resource_manager.cpp
|
||||||
renderer_opengl/gl_resource_manager.h
|
renderer_opengl/gl_resource_manager.h
|
||||||
|
renderer_opengl/gl_sampler_cache.cpp
|
||||||
|
renderer_opengl/gl_sampler_cache.h
|
||||||
renderer_opengl/gl_shader_cache.cpp
|
renderer_opengl/gl_shader_cache.cpp
|
||||||
renderer_opengl/gl_shader_cache.h
|
renderer_opengl/gl_shader_cache.h
|
||||||
renderer_opengl/gl_shader_decompiler.cpp
|
renderer_opengl/gl_shader_decompiler.cpp
|
||||||
|
@ -67,6 +69,8 @@ add_library(video_core STATIC
|
||||||
renderer_opengl/renderer_opengl.h
|
renderer_opengl/renderer_opengl.h
|
||||||
renderer_opengl/utils.cpp
|
renderer_opengl/utils.cpp
|
||||||
renderer_opengl/utils.h
|
renderer_opengl/utils.h
|
||||||
|
sampler_cache.cpp
|
||||||
|
sampler_cache.h
|
||||||
shader/decode/arithmetic.cpp
|
shader/decode/arithmetic.cpp
|
||||||
shader/decode/arithmetic_immediate.cpp
|
shader/decode/arithmetic_immediate.cpp
|
||||||
shader/decode/bfe.cpp
|
shader/decode/bfe.cpp
|
||||||
|
|
|
@ -101,12 +101,6 @@ struct FramebufferCacheKey {
|
||||||
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
|
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
|
||||||
: res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system},
|
: res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system},
|
||||||
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
|
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
|
||||||
// Create sampler objects
|
|
||||||
for (std::size_t i = 0; i < texture_samplers.size(); ++i) {
|
|
||||||
texture_samplers[i].Create();
|
|
||||||
state.texture_units[i].sampler = texture_samplers[i].sampler.handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenGLState::ApplyDefaultState();
|
OpenGLState::ApplyDefaultState();
|
||||||
|
|
||||||
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
|
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
|
||||||
|
@ -813,92 +807,6 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SamplerInfo::Create() {
|
|
||||||
sampler.Create();
|
|
||||||
mag_filter = Tegra::Texture::TextureFilter::Linear;
|
|
||||||
min_filter = Tegra::Texture::TextureFilter::Linear;
|
|
||||||
wrap_u = Tegra::Texture::WrapMode::Wrap;
|
|
||||||
wrap_v = Tegra::Texture::WrapMode::Wrap;
|
|
||||||
wrap_p = Tegra::Texture::WrapMode::Wrap;
|
|
||||||
use_depth_compare = false;
|
|
||||||
depth_compare_func = Tegra::Texture::DepthCompareFunc::Never;
|
|
||||||
|
|
||||||
// OpenGL's default is GL_LINEAR_MIPMAP_LINEAR
|
|
||||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
|
|
||||||
|
|
||||||
// Other attributes have correct defaults
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) {
|
|
||||||
const GLuint sampler_id = sampler.handle;
|
|
||||||
if (mag_filter != config.mag_filter) {
|
|
||||||
mag_filter = config.mag_filter;
|
|
||||||
glSamplerParameteri(
|
|
||||||
sampler_id, GL_TEXTURE_MAG_FILTER,
|
|
||||||
MaxwellToGL::TextureFilterMode(mag_filter, Tegra::Texture::TextureMipmapFilter::None));
|
|
||||||
}
|
|
||||||
if (min_filter != config.min_filter || mipmap_filter != config.mipmap_filter) {
|
|
||||||
min_filter = config.min_filter;
|
|
||||||
mipmap_filter = config.mipmap_filter;
|
|
||||||
glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER,
|
|
||||||
MaxwellToGL::TextureFilterMode(min_filter, mipmap_filter));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wrap_u != config.wrap_u) {
|
|
||||||
wrap_u = config.wrap_u;
|
|
||||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(wrap_u));
|
|
||||||
}
|
|
||||||
if (wrap_v != config.wrap_v) {
|
|
||||||
wrap_v = config.wrap_v;
|
|
||||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(wrap_v));
|
|
||||||
}
|
|
||||||
if (wrap_p != config.wrap_p) {
|
|
||||||
wrap_p = config.wrap_p;
|
|
||||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(wrap_p));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const bool enabled = config.depth_compare_enabled == 1; use_depth_compare != enabled) {
|
|
||||||
use_depth_compare = enabled;
|
|
||||||
glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_MODE,
|
|
||||||
use_depth_compare ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth_compare_func != config.depth_compare_func) {
|
|
||||||
depth_compare_func = config.depth_compare_func;
|
|
||||||
glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_FUNC,
|
|
||||||
MaxwellToGL::DepthCompareFunc(depth_compare_func));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto new_border_color = config.GetBorderColor(); border_color != new_border_color) {
|
|
||||||
border_color = new_border_color;
|
|
||||||
glSamplerParameterfv(sampler_id, GL_TEXTURE_BORDER_COLOR, border_color.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const float anisotropic = config.GetMaxAnisotropy(); max_anisotropic != anisotropic) {
|
|
||||||
max_anisotropic = anisotropic;
|
|
||||||
if (GLAD_GL_ARB_texture_filter_anisotropic) {
|
|
||||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY, max_anisotropic);
|
|
||||||
} else if (GLAD_GL_EXT_texture_filter_anisotropic) {
|
|
||||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const float min = config.GetMinLod(); min_lod != min) {
|
|
||||||
min_lod = min;
|
|
||||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, min_lod);
|
|
||||||
}
|
|
||||||
if (const float max = config.GetMaxLod(); max_lod != max) {
|
|
||||||
max_lod = max;
|
|
||||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, max_lod);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const float bias = config.GetLodBias(); lod_bias != bias) {
|
|
||||||
lod_bias = bias;
|
|
||||||
glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, lod_bias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
||||||
const Shader& shader, GLuint program_handle,
|
const Shader& shader, GLuint program_handle,
|
||||||
BaseBindings base_bindings) {
|
BaseBindings base_bindings) {
|
||||||
|
@ -985,7 +893,7 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s
|
||||||
}
|
}
|
||||||
const u32 current_bindpoint = base_bindings.sampler + bindpoint;
|
const u32 current_bindpoint = base_bindings.sampler + bindpoint;
|
||||||
|
|
||||||
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
|
state.texture_units[current_bindpoint].sampler = sampler_cache.GetSampler(texture.tsc);
|
||||||
|
|
||||||
if (Surface surface = res_cache.GetTextureSurface(texture, entry); surface) {
|
if (Surface surface = res_cache.GetTextureSurface(texture, entry); surface) {
|
||||||
state.texture_units[current_bindpoint].texture =
|
state.texture_units[current_bindpoint].texture =
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "video_core/renderer_opengl/gl_primitive_assembler.h"
|
#include "video_core/renderer_opengl/gl_primitive_assembler.h"
|
||||||
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
|
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
|
#include "video_core/renderer_opengl/gl_sampler_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_state.h"
|
#include "video_core/renderer_opengl/gl_state.h"
|
||||||
|
@ -72,34 +73,6 @@ public:
|
||||||
"The maximum size of a constbuffer must be a multiple of the size of GLvec4");
|
"The maximum size of a constbuffer must be a multiple of the size of GLvec4");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class SamplerInfo {
|
|
||||||
public:
|
|
||||||
OGLSampler sampler;
|
|
||||||
|
|
||||||
/// Creates the sampler object, initializing its state so that it's in sync with the
|
|
||||||
/// SamplerInfo struct.
|
|
||||||
void Create();
|
|
||||||
/// Syncs the sampler object with the config, updating any necessary state.
|
|
||||||
void SyncWithConfig(const Tegra::Texture::TSCEntry& info);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Tegra::Texture::TextureFilter mag_filter = Tegra::Texture::TextureFilter::Nearest;
|
|
||||||
Tegra::Texture::TextureFilter min_filter = Tegra::Texture::TextureFilter::Nearest;
|
|
||||||
Tegra::Texture::TextureMipmapFilter mipmap_filter =
|
|
||||||
Tegra::Texture::TextureMipmapFilter::None;
|
|
||||||
Tegra::Texture::WrapMode wrap_u = Tegra::Texture::WrapMode::ClampToEdge;
|
|
||||||
Tegra::Texture::WrapMode wrap_v = Tegra::Texture::WrapMode::ClampToEdge;
|
|
||||||
Tegra::Texture::WrapMode wrap_p = Tegra::Texture::WrapMode::ClampToEdge;
|
|
||||||
bool use_depth_compare = false;
|
|
||||||
Tegra::Texture::DepthCompareFunc depth_compare_func =
|
|
||||||
Tegra::Texture::DepthCompareFunc::Always;
|
|
||||||
GLvec4 border_color = {};
|
|
||||||
float min_lod = 0.0f;
|
|
||||||
float max_lod = 16.0f;
|
|
||||||
float lod_bias = 0.0f;
|
|
||||||
float max_anisotropic = 1.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FramebufferConfigState {
|
struct FramebufferConfigState {
|
||||||
bool using_color_fb{};
|
bool using_color_fb{};
|
||||||
bool using_depth_fb{};
|
bool using_depth_fb{};
|
||||||
|
@ -204,6 +177,7 @@ private:
|
||||||
RasterizerCacheOpenGL res_cache;
|
RasterizerCacheOpenGL res_cache;
|
||||||
ShaderCacheOpenGL shader_cache;
|
ShaderCacheOpenGL shader_cache;
|
||||||
GlobalRegionCacheOpenGL global_cache;
|
GlobalRegionCacheOpenGL global_cache;
|
||||||
|
SamplerCacheOpenGL sampler_cache;
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
|
@ -219,8 +193,6 @@ private:
|
||||||
FramebufferConfigState current_framebuffer_config_state;
|
FramebufferConfigState current_framebuffer_config_state;
|
||||||
std::pair<bool, bool> current_depth_stencil_usage{};
|
std::pair<bool, bool> current_depth_stencil_usage{};
|
||||||
|
|
||||||
std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers;
|
|
||||||
|
|
||||||
static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
|
static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
|
||||||
OGLBufferCache buffer_cache;
|
OGLBufferCache buffer_cache;
|
||||||
PrimitiveAssembler primitive_assembler{buffer_cache};
|
PrimitiveAssembler primitive_assembler{buffer_cache};
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
|
#include "video_core/renderer_opengl/gl_sampler_cache.h"
|
||||||
|
#include "video_core/renderer_opengl/maxwell_to_gl.h"
|
||||||
|
|
||||||
|
namespace OpenGL {
|
||||||
|
|
||||||
|
SamplerCacheOpenGL::SamplerCacheOpenGL() = default;
|
||||||
|
|
||||||
|
SamplerCacheOpenGL::~SamplerCacheOpenGL() = default;
|
||||||
|
|
||||||
|
OGLSampler SamplerCacheOpenGL::CreateSampler(const Tegra::Texture::TSCEntry& tsc) const {
|
||||||
|
OGLSampler sampler;
|
||||||
|
sampler.Create();
|
||||||
|
|
||||||
|
const GLuint sampler_id{sampler.handle};
|
||||||
|
glSamplerParameteri(
|
||||||
|
sampler_id, GL_TEXTURE_MAG_FILTER,
|
||||||
|
MaxwellToGL::TextureFilterMode(tsc.mag_filter, Tegra::Texture::TextureMipmapFilter::None));
|
||||||
|
glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER,
|
||||||
|
MaxwellToGL::TextureFilterMode(tsc.min_filter, tsc.mipmap_filter));
|
||||||
|
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(tsc.wrap_u));
|
||||||
|
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(tsc.wrap_v));
|
||||||
|
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(tsc.wrap_p));
|
||||||
|
glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_MODE,
|
||||||
|
tsc.depth_compare_enabled == 1 ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE);
|
||||||
|
glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_FUNC,
|
||||||
|
MaxwellToGL::DepthCompareFunc(tsc.depth_compare_func));
|
||||||
|
glSamplerParameterfv(sampler_id, GL_TEXTURE_BORDER_COLOR, tsc.GetBorderColor().data());
|
||||||
|
glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, tsc.GetMinLod());
|
||||||
|
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, tsc.GetMaxLod());
|
||||||
|
glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, tsc.GetLodBias());
|
||||||
|
if (GLAD_GL_ARB_texture_filter_anisotropic) {
|
||||||
|
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY, tsc.GetMaxAnisotropy());
|
||||||
|
} else if (GLAD_GL_EXT_texture_filter_anisotropic) {
|
||||||
|
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, tsc.GetMaxAnisotropy());
|
||||||
|
} else if (tsc.GetMaxAnisotropy() != 1) {
|
||||||
|
LOG_WARNING(Render_OpenGL, "Anisotropy not supported by host GPU driver");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint SamplerCacheOpenGL::ToSamplerType(const OGLSampler& sampler) const {
|
||||||
|
return sampler.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace OpenGL
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
|
#include "video_core/sampler_cache.h"
|
||||||
|
|
||||||
|
namespace OpenGL {
|
||||||
|
|
||||||
|
class SamplerCacheOpenGL final : public VideoCommon::SamplerCache<GLuint, OGLSampler> {
|
||||||
|
public:
|
||||||
|
explicit SamplerCacheOpenGL();
|
||||||
|
~SamplerCacheOpenGL();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OGLSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const;
|
||||||
|
|
||||||
|
GLuint ToSamplerType(const OGLSampler& sampler) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace OpenGL
|
|
@ -7,7 +7,6 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/cityhash.h"
|
|
||||||
#include "video_core/renderer_vulkan/declarations.h"
|
#include "video_core/renderer_vulkan/declarations.h"
|
||||||
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
||||||
#include "video_core/renderer_vulkan/vk_sampler_cache.h"
|
#include "video_core/renderer_vulkan/vk_sampler_cache.h"
|
||||||
|
@ -28,39 +27,20 @@ static std::optional<vk::BorderColor> TryConvertBorderColor(std::array<float, 4>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SamplerCacheKey::Hash() const {
|
|
||||||
static_assert(sizeof(raw) % sizeof(u64) == 0);
|
|
||||||
return static_cast<std::size_t>(
|
|
||||||
Common::CityHash64(reinterpret_cast<const char*>(raw.data()), sizeof(raw) / sizeof(u64)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SamplerCacheKey::operator==(const SamplerCacheKey& rhs) const {
|
|
||||||
return raw == rhs.raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
VKSamplerCache::VKSamplerCache(const VKDevice& device) : device{device} {}
|
VKSamplerCache::VKSamplerCache(const VKDevice& device) : device{device} {}
|
||||||
|
|
||||||
VKSamplerCache::~VKSamplerCache() = default;
|
VKSamplerCache::~VKSamplerCache() = default;
|
||||||
|
|
||||||
vk::Sampler VKSamplerCache::GetSampler(const Tegra::Texture::TSCEntry& tsc) {
|
UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) const {
|
||||||
const auto [entry, is_cache_miss] = cache.try_emplace(SamplerCacheKey{tsc});
|
const float max_anisotropy{tsc.GetMaxAnisotropy()};
|
||||||
auto& sampler = entry->second;
|
const bool has_anisotropy{max_anisotropy > 1.0f};
|
||||||
if (is_cache_miss) {
|
|
||||||
sampler = CreateSampler(tsc);
|
|
||||||
}
|
|
||||||
return *sampler;
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) {
|
const auto border_color{tsc.GetBorderColor()};
|
||||||
const float max_anisotropy = tsc.GetMaxAnisotropy();
|
const auto vk_border_color{TryConvertBorderColor(border_color)};
|
||||||
const bool has_anisotropy = max_anisotropy > 1.0f;
|
|
||||||
|
|
||||||
const auto border_color = tsc.GetBorderColor();
|
|
||||||
const auto vk_border_color = TryConvertBorderColor(border_color);
|
|
||||||
UNIMPLEMENTED_IF_MSG(!vk_border_color, "Unimplemented border color {} {} {} {}",
|
UNIMPLEMENTED_IF_MSG(!vk_border_color, "Unimplemented border color {} {} {} {}",
|
||||||
border_color[0], border_color[1], border_color[2], border_color[3]);
|
border_color[0], border_color[1], border_color[2], border_color[3]);
|
||||||
|
|
||||||
constexpr bool unnormalized_coords = false;
|
constexpr bool unnormalized_coords{false};
|
||||||
|
|
||||||
const vk::SamplerCreateInfo sampler_ci(
|
const vk::SamplerCreateInfo sampler_ci(
|
||||||
{}, MaxwellToVK::Sampler::Filter(tsc.mag_filter),
|
{}, MaxwellToVK::Sampler::Filter(tsc.mag_filter),
|
||||||
|
@ -73,9 +53,13 @@ UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc)
|
||||||
tsc.GetMaxLod(), vk_border_color.value_or(vk::BorderColor::eFloatTransparentBlack),
|
tsc.GetMaxLod(), vk_border_color.value_or(vk::BorderColor::eFloatTransparentBlack),
|
||||||
unnormalized_coords);
|
unnormalized_coords);
|
||||||
|
|
||||||
const auto& dld = device.GetDispatchLoader();
|
const auto& dld{device.GetDispatchLoader()};
|
||||||
const auto dev = device.GetLogical();
|
const auto dev{device.GetLogical()};
|
||||||
return dev.createSamplerUnique(sampler_ci, nullptr, dld);
|
return dev.createSamplerUnique(sampler_ci, nullptr, dld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::Sampler VKSamplerCache::ToSamplerType(const UniqueSampler& sampler) const {
|
||||||
|
return *sampler;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -8,49 +8,25 @@
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/renderer_vulkan/declarations.h"
|
#include "video_core/renderer_vulkan/declarations.h"
|
||||||
|
#include "video_core/sampler_cache.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
class VKDevice;
|
class VKDevice;
|
||||||
|
|
||||||
struct SamplerCacheKey final : public Tegra::Texture::TSCEntry {
|
class VKSamplerCache final : public VideoCommon::SamplerCache<vk::Sampler, UniqueSampler> {
|
||||||
std::size_t Hash() const;
|
|
||||||
|
|
||||||
bool operator==(const SamplerCacheKey& rhs) const;
|
|
||||||
|
|
||||||
bool operator!=(const SamplerCacheKey& rhs) const {
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Vulkan
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct hash<Vulkan::SamplerCacheKey> {
|
|
||||||
std::size_t operator()(const Vulkan::SamplerCacheKey& k) const noexcept {
|
|
||||||
return k.Hash();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
namespace Vulkan {
|
|
||||||
|
|
||||||
class VKSamplerCache {
|
|
||||||
public:
|
public:
|
||||||
explicit VKSamplerCache(const VKDevice& device);
|
explicit VKSamplerCache(const VKDevice& device);
|
||||||
~VKSamplerCache();
|
~VKSamplerCache();
|
||||||
|
|
||||||
vk::Sampler GetSampler(const Tegra::Texture::TSCEntry& tsc);
|
protected:
|
||||||
|
UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const;
|
||||||
|
|
||||||
|
vk::Sampler ToSamplerType(const UniqueSampler& sampler) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc);
|
|
||||||
|
|
||||||
const VKDevice& device;
|
const VKDevice& device;
|
||||||
std::unordered_map<SamplerCacheKey, UniqueSampler> cache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/cityhash.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "video_core/sampler_cache.h"
|
||||||
|
|
||||||
|
namespace VideoCommon {
|
||||||
|
|
||||||
|
std::size_t SamplerCacheKey::Hash() const {
|
||||||
|
static_assert(sizeof(raw) % sizeof(u64) == 0);
|
||||||
|
return static_cast<std::size_t>(
|
||||||
|
Common::CityHash64(reinterpret_cast<const char*>(raw.data()), sizeof(raw) / sizeof(u64)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SamplerCacheKey::operator==(const SamplerCacheKey& rhs) const {
|
||||||
|
return raw == rhs.raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace VideoCommon
|
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "video_core/textures/texture.h"
|
||||||
|
|
||||||
|
namespace VideoCommon {
|
||||||
|
|
||||||
|
struct SamplerCacheKey final : public Tegra::Texture::TSCEntry {
|
||||||
|
std::size_t Hash() const;
|
||||||
|
|
||||||
|
bool operator==(const SamplerCacheKey& rhs) const;
|
||||||
|
|
||||||
|
bool operator!=(const SamplerCacheKey& rhs) const {
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace VideoCommon
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<VideoCommon::SamplerCacheKey> {
|
||||||
|
std::size_t operator()(const VideoCommon::SamplerCacheKey& k) const noexcept {
|
||||||
|
return k.Hash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
namespace VideoCommon {
|
||||||
|
|
||||||
|
template <typename SamplerType, typename SamplerStorageType>
|
||||||
|
class SamplerCache {
|
||||||
|
public:
|
||||||
|
SamplerType GetSampler(const Tegra::Texture::TSCEntry& tsc) {
|
||||||
|
const auto [entry, is_cache_miss] = cache.try_emplace(SamplerCacheKey{tsc});
|
||||||
|
auto& sampler = entry->second;
|
||||||
|
if (is_cache_miss) {
|
||||||
|
sampler = CreateSampler(tsc);
|
||||||
|
}
|
||||||
|
return ToSamplerType(sampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual SamplerStorageType CreateSampler(const Tegra::Texture::TSCEntry& tsc) const = 0;
|
||||||
|
|
||||||
|
virtual SamplerType ToSamplerType(const SamplerStorageType& sampler) const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<SamplerCacheKey, SamplerStorageType> cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace VideoCommon
|
Loading…
Reference in New Issue