diff options
| author | 2019-04-17 21:45:56 -0400 | |
|---|---|---|
| committer | 2019-04-17 21:45:56 -0400 | |
| commit | 4294062516c91c8fdabbcb5b5bcde641c03c9218 (patch) | |
| tree | 8420493647f54dbab66b3b654115e8c509f536d6 /src | |
| parent | Merge pull request #2348 from FernandoS27/guest-bindless (diff) | |
| parent | gl_sampler_cache: Port sampler cache to OpenGL (diff) | |
| download | yuzu-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.txt | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 94 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 32 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_sampler_cache.cpp | 52 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_sampler_cache.h | 25 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_sampler_cache.cpp | 40 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_sampler_cache.h | 36 | ||||
| -rw-r--r-- | src/video_core/sampler_cache.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/sampler_cache.h | 60 |
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 { | |||
| 101 | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info) | 101 | RasterizerOpenGL::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 | ||
| 816 | void 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 | |||
| 833 | void 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 | |||
| 902 | void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, | 810 | void 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 | ||
| 74 | private: | 75 | private: |
| 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 | |||
| 10 | namespace OpenGL { | ||
| 11 | |||
| 12 | SamplerCacheOpenGL::SamplerCacheOpenGL() = default; | ||
| 13 | |||
| 14 | SamplerCacheOpenGL::~SamplerCacheOpenGL() = default; | ||
| 15 | |||
| 16 | OGLSampler 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 | |||
| 48 | GLuint 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 | |||
| 12 | namespace OpenGL { | ||
| 13 | |||
| 14 | class SamplerCacheOpenGL final : public VideoCommon::SamplerCache<GLuint, OGLSampler> { | ||
| 15 | public: | ||
| 16 | explicit SamplerCacheOpenGL(); | ||
| 17 | ~SamplerCacheOpenGL(); | ||
| 18 | |||
| 19 | protected: | ||
| 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 | ||
| 31 | std::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 | |||
| 37 | bool SamplerCacheKey::operator==(const SamplerCacheKey& rhs) const { | ||
| 38 | return raw == rhs.raw; | ||
| 39 | } | ||
| 40 | |||
| 41 | VKSamplerCache::VKSamplerCache(const VKDevice& device) : device{device} {} | 30 | VKSamplerCache::VKSamplerCache(const VKDevice& device) : device{device} {} |
| 42 | 31 | ||
| 43 | VKSamplerCache::~VKSamplerCache() = default; | 32 | VKSamplerCache::~VKSamplerCache() = default; |
| 44 | 33 | ||
| 45 | vk::Sampler VKSamplerCache::GetSampler(const Tegra::Texture::TSCEntry& tsc) { | 34 | UniqueSampler 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 | |||
| 54 | UniqueSampler 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 | ||
| 61 | vk::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 | ||
| 13 | namespace Vulkan { | 14 | namespace Vulkan { |
| 14 | 15 | ||
| 15 | class VKDevice; | 16 | class VKDevice; |
| 16 | 17 | ||
| 17 | struct SamplerCacheKey final : public Tegra::Texture::TSCEntry { | 18 | class 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 | |||
| 29 | namespace std { | ||
| 30 | |||
| 31 | template <> | ||
| 32 | struct 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 | |||
| 40 | namespace Vulkan { | ||
| 41 | |||
| 42 | class VKSamplerCache { | ||
| 43 | public: | 19 | public: |
| 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); | 23 | protected: |
| 24 | UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const; | ||
| 48 | 25 | ||
| 49 | private: | 26 | vk::Sampler ToSamplerType(const UniqueSampler& sampler) const; |
| 50 | UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc); | ||
| 51 | 27 | ||
| 28 | private: | ||
| 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 | |||
| 9 | namespace VideoCommon { | ||
| 10 | |||
| 11 | std::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 | |||
| 17 | bool 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 | |||
| 12 | namespace VideoCommon { | ||
| 13 | |||
| 14 | struct 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 | |||
| 26 | namespace std { | ||
| 27 | |||
| 28 | template <> | ||
| 29 | struct 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 | |||
| 37 | namespace VideoCommon { | ||
| 38 | |||
| 39 | template <typename SamplerType, typename SamplerStorageType> | ||
| 40 | class SamplerCache { | ||
| 41 | public: | ||
| 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 | |||
| 51 | protected: | ||
| 52 | virtual SamplerStorageType CreateSampler(const Tegra::Texture::TSCEntry& tsc) const = 0; | ||
| 53 | |||
| 54 | virtual SamplerType ToSamplerType(const SamplerStorageType& sampler) const = 0; | ||
| 55 | |||
| 56 | private: | ||
| 57 | std::unordered_map<SamplerCacheKey, SamplerStorageType> cache; | ||
| 58 | }; | ||
| 59 | |||
| 60 | } // namespace VideoCommon \ No newline at end of file | ||