summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2019-04-17 21:45:56 -0400
committerGravatar GitHub2019-04-17 21:45:56 -0400
commit4294062516c91c8fdabbcb5b5bcde641c03c9218 (patch)
tree8420493647f54dbab66b3b654115e8c509f536d6 /src
parentMerge pull request #2348 from FernandoS27/guest-bindless (diff)
parentgl_sampler_cache: Port sampler cache to OpenGL (diff)
downloadyuzu-4294062516c91c8fdabbcb5b5bcde641c03c9218.tar.gz
yuzu-4294062516c91c8fdabbcb5b5bcde641c03c9218.tar.xz
yuzu-4294062516c91c8fdabbcb5b5bcde641c03c9218.zip
Merge pull request #2318 from ReinUsesLisp/sampler-cache
gl_sampler_cache: Port sampler cache to OpenGL
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp94
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h32
-rw-r--r--src/video_core/renderer_opengl/gl_sampler_cache.cpp52
-rw-r--r--src/video_core/renderer_opengl/gl_sampler_cache.h25
-rw-r--r--src/video_core/renderer_vulkan/vk_sampler_cache.cpp40
-rw-r--r--src/video_core/renderer_vulkan/vk_sampler_cache.h36
-rw-r--r--src/video_core/sampler_cache.cpp21
-rw-r--r--src/video_core/sampler_cache.h60
9 files changed, 183 insertions, 181 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 114bed20d..1e31a2900 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -46,6 +46,8 @@ add_library(video_core STATIC
46 renderer_opengl/gl_rasterizer_cache.h 46 renderer_opengl/gl_rasterizer_cache.h
47 renderer_opengl/gl_resource_manager.cpp 47 renderer_opengl/gl_resource_manager.cpp
48 renderer_opengl/gl_resource_manager.h 48 renderer_opengl/gl_resource_manager.h
49 renderer_opengl/gl_sampler_cache.cpp
50 renderer_opengl/gl_sampler_cache.h
49 renderer_opengl/gl_shader_cache.cpp 51 renderer_opengl/gl_shader_cache.cpp
50 renderer_opengl/gl_shader_cache.h 52 renderer_opengl/gl_shader_cache.h
51 renderer_opengl/gl_shader_decompiler.cpp 53 renderer_opengl/gl_shader_decompiler.cpp
@@ -67,6 +69,8 @@ add_library(video_core STATIC
67 renderer_opengl/renderer_opengl.h 69 renderer_opengl/renderer_opengl.h
68 renderer_opengl/utils.cpp 70 renderer_opengl/utils.cpp
69 renderer_opengl/utils.h 71 renderer_opengl/utils.h
72 sampler_cache.cpp
73 sampler_cache.h
70 shader/decode/arithmetic.cpp 74 shader/decode/arithmetic.cpp
71 shader/decode/arithmetic_immediate.cpp 75 shader/decode/arithmetic_immediate.cpp
72 shader/decode/bfe.cpp 76 shader/decode/bfe.cpp
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 86a2e117d..6034dc489 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -101,12 +101,6 @@ struct FramebufferCacheKey {
101RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info) 101RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
102 : res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system}, 102 : res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system},
103 screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) { 103 screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
104 // Create sampler objects
105 for (std::size_t i = 0; i < texture_samplers.size(); ++i) {
106 texture_samplers[i].Create();
107 state.texture_units[i].sampler = texture_samplers[i].sampler.handle;
108 }
109
110 OpenGLState::ApplyDefaultState(); 104 OpenGLState::ApplyDefaultState();
111 105
112 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 106 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
@@ -813,92 +807,6 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
813 return true; 807 return true;
814} 808}
815 809
816void RasterizerOpenGL::SamplerInfo::Create() {
817 sampler.Create();
818 mag_filter = Tegra::Texture::TextureFilter::Linear;
819 min_filter = Tegra::Texture::TextureFilter::Linear;
820 wrap_u = Tegra::Texture::WrapMode::Wrap;
821 wrap_v = Tegra::Texture::WrapMode::Wrap;
822 wrap_p = Tegra::Texture::WrapMode::Wrap;
823 use_depth_compare = false;
824 depth_compare_func = Tegra::Texture::DepthCompareFunc::Never;
825
826 // OpenGL's default is GL_LINEAR_MIPMAP_LINEAR
827 glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
828 glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
829
830 // Other attributes have correct defaults
831}
832
833void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) {
834 const GLuint sampler_id = sampler.handle;
835 if (mag_filter != config.mag_filter) {
836 mag_filter = config.mag_filter;
837 glSamplerParameteri(
838 sampler_id, GL_TEXTURE_MAG_FILTER,
839 MaxwellToGL::TextureFilterMode(mag_filter, Tegra::Texture::TextureMipmapFilter::None));
840 }
841 if (min_filter != config.min_filter || mipmap_filter != config.mipmap_filter) {
842 min_filter = config.min_filter;
843 mipmap_filter = config.mipmap_filter;
844 glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER,
845 MaxwellToGL::TextureFilterMode(min_filter, mipmap_filter));
846 }
847
848 if (wrap_u != config.wrap_u) {
849 wrap_u = config.wrap_u;
850 glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(wrap_u));
851 }
852 if (wrap_v != config.wrap_v) {
853 wrap_v = config.wrap_v;
854 glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(wrap_v));
855 }
856 if (wrap_p != config.wrap_p) {
857 wrap_p = config.wrap_p;
858 glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(wrap_p));
859 }
860
861 if (const bool enabled = config.depth_compare_enabled == 1; use_depth_compare != enabled) {
862 use_depth_compare = enabled;
863 glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_MODE,
864 use_depth_compare ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE);
865 }
866
867 if (depth_compare_func != config.depth_compare_func) {
868 depth_compare_func = config.depth_compare_func;
869 glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_FUNC,
870 MaxwellToGL::DepthCompareFunc(depth_compare_func));
871 }
872
873 if (const auto new_border_color = config.GetBorderColor(); border_color != new_border_color) {
874 border_color = new_border_color;
875 glSamplerParameterfv(sampler_id, GL_TEXTURE_BORDER_COLOR, border_color.data());
876 }
877
878 if (const float anisotropic = config.GetMaxAnisotropy(); max_anisotropic != anisotropic) {
879 max_anisotropic = anisotropic;
880 if (GLAD_GL_ARB_texture_filter_anisotropic) {
881 glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY, max_anisotropic);
882 } else if (GLAD_GL_EXT_texture_filter_anisotropic) {
883 glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropic);
884 }
885 }
886
887 if (const float min = config.GetMinLod(); min_lod != min) {
888 min_lod = min;
889 glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, min_lod);
890 }
891 if (const float max = config.GetMaxLod(); max_lod != max) {
892 max_lod = max;
893 glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, max_lod);
894 }
895
896 if (const float bias = config.GetLodBias(); lod_bias != bias) {
897 lod_bias = bias;
898 glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, lod_bias);
899 }
900}
901
902void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, 810void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
903 const Shader& shader, GLuint program_handle, 811 const Shader& shader, GLuint program_handle,
904 BaseBindings base_bindings) { 812 BaseBindings base_bindings) {
@@ -985,7 +893,7 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s
985 } 893 }
986 const u32 current_bindpoint = base_bindings.sampler + bindpoint; 894 const u32 current_bindpoint = base_bindings.sampler + bindpoint;
987 895
988 texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); 896 state.texture_units[current_bindpoint].sampler = sampler_cache.GetSampler(texture.tsc);
989 897
990 if (Surface surface = res_cache.GetTextureSurface(texture, entry); surface) { 898 if (Surface surface = res_cache.GetTextureSurface(texture, entry); surface) {
991 state.texture_units[current_bindpoint].texture = 899 state.texture_units[current_bindpoint].texture =
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index d4c2cf80e..a0e056142 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -25,6 +25,7 @@
25#include "video_core/renderer_opengl/gl_primitive_assembler.h" 25#include "video_core/renderer_opengl/gl_primitive_assembler.h"
26#include "video_core/renderer_opengl/gl_rasterizer_cache.h" 26#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
27#include "video_core/renderer_opengl/gl_resource_manager.h" 27#include "video_core/renderer_opengl/gl_resource_manager.h"
28#include "video_core/renderer_opengl/gl_sampler_cache.h"
28#include "video_core/renderer_opengl/gl_shader_cache.h" 29#include "video_core/renderer_opengl/gl_shader_cache.h"
29#include "video_core/renderer_opengl/gl_shader_manager.h" 30#include "video_core/renderer_opengl/gl_shader_manager.h"
30#include "video_core/renderer_opengl/gl_state.h" 31#include "video_core/renderer_opengl/gl_state.h"
@@ -72,34 +73,6 @@ public:
72 "The maximum size of a constbuffer must be a multiple of the size of GLvec4"); 73 "The maximum size of a constbuffer must be a multiple of the size of GLvec4");
73 74
74private: 75private:
75 class SamplerInfo {
76 public:
77 OGLSampler sampler;
78
79 /// Creates the sampler object, initializing its state so that it's in sync with the
80 /// SamplerInfo struct.
81 void Create();
82 /// Syncs the sampler object with the config, updating any necessary state.
83 void SyncWithConfig(const Tegra::Texture::TSCEntry& info);
84
85 private:
86 Tegra::Texture::TextureFilter mag_filter = Tegra::Texture::TextureFilter::Nearest;
87 Tegra::Texture::TextureFilter min_filter = Tegra::Texture::TextureFilter::Nearest;
88 Tegra::Texture::TextureMipmapFilter mipmap_filter =
89 Tegra::Texture::TextureMipmapFilter::None;
90 Tegra::Texture::WrapMode wrap_u = Tegra::Texture::WrapMode::ClampToEdge;
91 Tegra::Texture::WrapMode wrap_v = Tegra::Texture::WrapMode::ClampToEdge;
92 Tegra::Texture::WrapMode wrap_p = Tegra::Texture::WrapMode::ClampToEdge;
93 bool use_depth_compare = false;
94 Tegra::Texture::DepthCompareFunc depth_compare_func =
95 Tegra::Texture::DepthCompareFunc::Always;
96 GLvec4 border_color = {};
97 float min_lod = 0.0f;
98 float max_lod = 16.0f;
99 float lod_bias = 0.0f;
100 float max_anisotropic = 1.0f;
101 };
102
103 struct FramebufferConfigState { 76 struct FramebufferConfigState {
104 bool using_color_fb{}; 77 bool using_color_fb{};
105 bool using_depth_fb{}; 78 bool using_depth_fb{};
@@ -204,6 +177,7 @@ private:
204 RasterizerCacheOpenGL res_cache; 177 RasterizerCacheOpenGL res_cache;
205 ShaderCacheOpenGL shader_cache; 178 ShaderCacheOpenGL shader_cache;
206 GlobalRegionCacheOpenGL global_cache; 179 GlobalRegionCacheOpenGL global_cache;
180 SamplerCacheOpenGL sampler_cache;
207 181
208 Core::System& system; 182 Core::System& system;
209 183
@@ -219,8 +193,6 @@ private:
219 FramebufferConfigState current_framebuffer_config_state; 193 FramebufferConfigState current_framebuffer_config_state;
220 std::pair<bool, bool> current_depth_stencil_usage{}; 194 std::pair<bool, bool> current_depth_stencil_usage{};
221 195
222 std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers;
223
224 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; 196 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
225 OGLBufferCache buffer_cache; 197 OGLBufferCache buffer_cache;
226 PrimitiveAssembler primitive_assembler{buffer_cache}; 198 PrimitiveAssembler primitive_assembler{buffer_cache};
diff --git a/src/video_core/renderer_opengl/gl_sampler_cache.cpp b/src/video_core/renderer_opengl/gl_sampler_cache.cpp
new file mode 100644
index 000000000..3ded5ecea
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_sampler_cache.cpp
@@ -0,0 +1,52 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "video_core/renderer_opengl/gl_resource_manager.h"
7#include "video_core/renderer_opengl/gl_sampler_cache.h"
8#include "video_core/renderer_opengl/maxwell_to_gl.h"
9
10namespace OpenGL {
11
12SamplerCacheOpenGL::SamplerCacheOpenGL() = default;
13
14SamplerCacheOpenGL::~SamplerCacheOpenGL() = default;
15
16OGLSampler SamplerCacheOpenGL::CreateSampler(const Tegra::Texture::TSCEntry& tsc) const {
17 OGLSampler sampler;
18 sampler.Create();
19
20 const GLuint sampler_id{sampler.handle};
21 glSamplerParameteri(
22 sampler_id, GL_TEXTURE_MAG_FILTER,
23 MaxwellToGL::TextureFilterMode(tsc.mag_filter, Tegra::Texture::TextureMipmapFilter::None));
24 glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER,
25 MaxwellToGL::TextureFilterMode(tsc.min_filter, tsc.mipmap_filter));
26 glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(tsc.wrap_u));
27 glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(tsc.wrap_v));
28 glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(tsc.wrap_p));
29 glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_MODE,
30 tsc.depth_compare_enabled == 1 ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE);
31 glSamplerParameteri(sampler_id, GL_TEXTURE_COMPARE_FUNC,
32 MaxwellToGL::DepthCompareFunc(tsc.depth_compare_func));
33 glSamplerParameterfv(sampler_id, GL_TEXTURE_BORDER_COLOR, tsc.GetBorderColor().data());
34 glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, tsc.GetMinLod());
35 glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, tsc.GetMaxLod());
36 glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, tsc.GetLodBias());
37 if (GLAD_GL_ARB_texture_filter_anisotropic) {
38 glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY, tsc.GetMaxAnisotropy());
39 } else if (GLAD_GL_EXT_texture_filter_anisotropic) {
40 glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, tsc.GetMaxAnisotropy());
41 } else if (tsc.GetMaxAnisotropy() != 1) {
42 LOG_WARNING(Render_OpenGL, "Anisotropy not supported by host GPU driver");
43 }
44
45 return sampler;
46}
47
48GLuint SamplerCacheOpenGL::ToSamplerType(const OGLSampler& sampler) const {
49 return sampler.handle;
50}
51
52} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_sampler_cache.h b/src/video_core/renderer_opengl/gl_sampler_cache.h
new file mode 100644
index 000000000..defbc2d81
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_sampler_cache.h
@@ -0,0 +1,25 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <glad/glad.h>
8
9#include "video_core/renderer_opengl/gl_resource_manager.h"
10#include "video_core/sampler_cache.h"
11
12namespace OpenGL {
13
14class SamplerCacheOpenGL final : public VideoCommon::SamplerCache<GLuint, OGLSampler> {
15public:
16 explicit SamplerCacheOpenGL();
17 ~SamplerCacheOpenGL();
18
19protected:
20 OGLSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const;
21
22 GLuint ToSamplerType(const OGLSampler& sampler) const;
23};
24
25} // namespace OpenGL
diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
index ed3178f09..801826d3d 100644
--- a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
@@ -7,7 +7,6 @@
7#include <unordered_map> 7#include <unordered_map>
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/cityhash.h"
11#include "video_core/renderer_vulkan/declarations.h" 10#include "video_core/renderer_vulkan/declarations.h"
12#include "video_core/renderer_vulkan/maxwell_to_vk.h" 11#include "video_core/renderer_vulkan/maxwell_to_vk.h"
13#include "video_core/renderer_vulkan/vk_sampler_cache.h" 12#include "video_core/renderer_vulkan/vk_sampler_cache.h"
@@ -28,39 +27,20 @@ static std::optional<vk::BorderColor> TryConvertBorderColor(std::array<float, 4>
28 } 27 }
29} 28}
30 29
31std::size_t SamplerCacheKey::Hash() const {
32 static_assert(sizeof(raw) % sizeof(u64) == 0);
33 return static_cast<std::size_t>(
34 Common::CityHash64(reinterpret_cast<const char*>(raw.data()), sizeof(raw) / sizeof(u64)));
35}
36
37bool SamplerCacheKey::operator==(const SamplerCacheKey& rhs) const {
38 return raw == rhs.raw;
39}
40
41VKSamplerCache::VKSamplerCache(const VKDevice& device) : device{device} {} 30VKSamplerCache::VKSamplerCache(const VKDevice& device) : device{device} {}
42 31
43VKSamplerCache::~VKSamplerCache() = default; 32VKSamplerCache::~VKSamplerCache() = default;
44 33
45vk::Sampler VKSamplerCache::GetSampler(const Tegra::Texture::TSCEntry& tsc) { 34UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) const {
46 const auto [entry, is_cache_miss] = cache.try_emplace(SamplerCacheKey{tsc}); 35 const float max_anisotropy{tsc.GetMaxAnisotropy()};
47 auto& sampler = entry->second; 36 const bool has_anisotropy{max_anisotropy > 1.0f};
48 if (is_cache_miss) {
49 sampler = CreateSampler(tsc);
50 }
51 return *sampler;
52}
53
54UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) {
55 const float max_anisotropy = tsc.GetMaxAnisotropy();
56 const bool has_anisotropy = max_anisotropy > 1.0f;
57 37
58 const auto border_color = tsc.GetBorderColor(); 38 const auto border_color{tsc.GetBorderColor()};
59 const auto vk_border_color = TryConvertBorderColor(border_color); 39 const auto vk_border_color{TryConvertBorderColor(border_color)};
60 UNIMPLEMENTED_IF_MSG(!vk_border_color, "Unimplemented border color {} {} {} {}", 40 UNIMPLEMENTED_IF_MSG(!vk_border_color, "Unimplemented border color {} {} {} {}",
61 border_color[0], border_color[1], border_color[2], border_color[3]); 41 border_color[0], border_color[1], border_color[2], border_color[3]);
62 42
63 constexpr bool unnormalized_coords = false; 43 constexpr bool unnormalized_coords{false};
64 44
65 const vk::SamplerCreateInfo sampler_ci( 45 const vk::SamplerCreateInfo sampler_ci(
66 {}, MaxwellToVK::Sampler::Filter(tsc.mag_filter), 46 {}, MaxwellToVK::Sampler::Filter(tsc.mag_filter),
@@ -73,9 +53,13 @@ UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc)
73 tsc.GetMaxLod(), vk_border_color.value_or(vk::BorderColor::eFloatTransparentBlack), 53 tsc.GetMaxLod(), vk_border_color.value_or(vk::BorderColor::eFloatTransparentBlack),
74 unnormalized_coords); 54 unnormalized_coords);
75 55
76 const auto& dld = device.GetDispatchLoader(); 56 const auto& dld{device.GetDispatchLoader()};
77 const auto dev = device.GetLogical(); 57 const auto dev{device.GetLogical()};
78 return dev.createSamplerUnique(sampler_ci, nullptr, dld); 58 return dev.createSamplerUnique(sampler_ci, nullptr, dld);
79} 59}
80 60
61vk::Sampler VKSamplerCache::ToSamplerType(const UniqueSampler& sampler) const {
62 return *sampler;
63}
64
81} // namespace Vulkan 65} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.h b/src/video_core/renderer_vulkan/vk_sampler_cache.h
index c6394dc87..771b05c73 100644
--- a/src/video_core/renderer_vulkan/vk_sampler_cache.h
+++ b/src/video_core/renderer_vulkan/vk_sampler_cache.h
@@ -8,49 +8,25 @@
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/renderer_vulkan/declarations.h" 10#include "video_core/renderer_vulkan/declarations.h"
11#include "video_core/sampler_cache.h"
11#include "video_core/textures/texture.h" 12#include "video_core/textures/texture.h"
12 13
13namespace Vulkan { 14namespace Vulkan {
14 15
15class VKDevice; 16class VKDevice;
16 17
17struct SamplerCacheKey final : public Tegra::Texture::TSCEntry { 18class VKSamplerCache final : public VideoCommon::SamplerCache<vk::Sampler, UniqueSampler> {
18 std::size_t Hash() const;
19
20 bool operator==(const SamplerCacheKey& rhs) const;
21
22 bool operator!=(const SamplerCacheKey& rhs) const {
23 return !operator==(rhs);
24 }
25};
26
27} // namespace Vulkan
28
29namespace std {
30
31template <>
32struct hash<Vulkan::SamplerCacheKey> {
33 std::size_t operator()(const Vulkan::SamplerCacheKey& k) const noexcept {
34 return k.Hash();
35 }
36};
37
38} // namespace std
39
40namespace Vulkan {
41
42class VKSamplerCache {
43public: 19public:
44 explicit VKSamplerCache(const VKDevice& device); 20 explicit VKSamplerCache(const VKDevice& device);
45 ~VKSamplerCache(); 21 ~VKSamplerCache();
46 22
47 vk::Sampler GetSampler(const Tegra::Texture::TSCEntry& tsc); 23protected:
24 UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const;
48 25
49private: 26 vk::Sampler ToSamplerType(const UniqueSampler& sampler) const;
50 UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc);
51 27
28private:
52 const VKDevice& device; 29 const VKDevice& device;
53 std::unordered_map<SamplerCacheKey, UniqueSampler> cache;
54}; 30};
55 31
56} // namespace Vulkan 32} // namespace Vulkan
diff --git a/src/video_core/sampler_cache.cpp b/src/video_core/sampler_cache.cpp
new file mode 100644
index 000000000..53c7ef12d
--- /dev/null
+++ b/src/video_core/sampler_cache.cpp
@@ -0,0 +1,21 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/cityhash.h"
6#include "common/common_types.h"
7#include "video_core/sampler_cache.h"
8
9namespace VideoCommon {
10
11std::size_t SamplerCacheKey::Hash() const {
12 static_assert(sizeof(raw) % sizeof(u64) == 0);
13 return static_cast<std::size_t>(
14 Common::CityHash64(reinterpret_cast<const char*>(raw.data()), sizeof(raw) / sizeof(u64)));
15}
16
17bool SamplerCacheKey::operator==(const SamplerCacheKey& rhs) const {
18 return raw == rhs.raw;
19}
20
21} // namespace VideoCommon
diff --git a/src/video_core/sampler_cache.h b/src/video_core/sampler_cache.h
new file mode 100644
index 000000000..cbe3ad071
--- /dev/null
+++ b/src/video_core/sampler_cache.h
@@ -0,0 +1,60 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <cstddef>
8#include <unordered_map>
9
10#include "video_core/textures/texture.h"
11
12namespace VideoCommon {
13
14struct SamplerCacheKey final : public Tegra::Texture::TSCEntry {
15 std::size_t Hash() const;
16
17 bool operator==(const SamplerCacheKey& rhs) const;
18
19 bool operator!=(const SamplerCacheKey& rhs) const {
20 return !operator==(rhs);
21 }
22};
23
24} // namespace VideoCommon
25
26namespace std {
27
28template <>
29struct hash<VideoCommon::SamplerCacheKey> {
30 std::size_t operator()(const VideoCommon::SamplerCacheKey& k) const noexcept {
31 return k.Hash();
32 }
33};
34
35} // namespace std
36
37namespace VideoCommon {
38
39template <typename SamplerType, typename SamplerStorageType>
40class SamplerCache {
41public:
42 SamplerType GetSampler(const Tegra::Texture::TSCEntry& tsc) {
43 const auto [entry, is_cache_miss] = cache.try_emplace(SamplerCacheKey{tsc});
44 auto& sampler = entry->second;
45 if (is_cache_miss) {
46 sampler = CreateSampler(tsc);
47 }
48 return ToSamplerType(sampler);
49 }
50
51protected:
52 virtual SamplerStorageType CreateSampler(const Tegra::Texture::TSCEntry& tsc) const = 0;
53
54 virtual SamplerType ToSamplerType(const SamplerStorageType& sampler) const = 0;
55
56private:
57 std::unordered_map<SamplerCacheKey, SamplerStorageType> cache;
58};
59
60} // namespace VideoCommon \ No newline at end of file