diff options
Diffstat (limited to 'src/video_core')
-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 renderer_opengl/gl_rasterizer_cache.h renderer_opengl/gl_resource_manager.cpp 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.h renderer_opengl/gl_shader_decompiler.cpp @@ -67,6 +69,8 @@ add_library(video_core STATIC renderer_opengl/renderer_opengl.h renderer_opengl/utils.cpp renderer_opengl/utils.h + sampler_cache.cpp + sampler_cache.h shader/decode/arithmetic.cpp shader/decode/arithmetic_immediate.cpp 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 { RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info) : res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system}, 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(); shader_program_manager = std::make_unique<GLShader::ProgramManager>(); @@ -813,92 +807,6 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, 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, const Shader& shader, GLuint program_handle, BaseBindings base_bindings) { @@ -985,7 +893,7 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s } 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) { 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 @@ #include "video_core/renderer_opengl/gl_primitive_assembler.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_sampler_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_state.h" @@ -72,34 +73,6 @@ public: "The maximum size of a constbuffer must be a multiple of the size of GLvec4"); 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 { bool using_color_fb{}; bool using_depth_fb{}; @@ -204,6 +177,7 @@ private: RasterizerCacheOpenGL res_cache; ShaderCacheOpenGL shader_cache; GlobalRegionCacheOpenGL global_cache; + SamplerCacheOpenGL sampler_cache; Core::System& system; @@ -219,8 +193,6 @@ private: FramebufferConfigState current_framebuffer_config_state; 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; OGLBufferCache buffer_cache; 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 @@ +// 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 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 @@ +// 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 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 @@ #include <unordered_map> #include "common/assert.h" -#include "common/cityhash.h" #include "video_core/renderer_vulkan/declarations.h" #include "video_core/renderer_vulkan/maxwell_to_vk.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() = default; -vk::Sampler VKSamplerCache::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 *sampler; -} - -UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) { - const float max_anisotropy = tsc.GetMaxAnisotropy(); - const bool has_anisotropy = max_anisotropy > 1.0f; +UniqueSampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) const { + const float max_anisotropy{tsc.GetMaxAnisotropy()}; + const bool has_anisotropy{max_anisotropy > 1.0f}; - const auto border_color = tsc.GetBorderColor(); - const auto vk_border_color = TryConvertBorderColor(border_color); + const auto border_color{tsc.GetBorderColor()}; + const auto vk_border_color{TryConvertBorderColor(border_color)}; UNIMPLEMENTED_IF_MSG(!vk_border_color, "Unimplemented border color {} {} {} {}", 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( {}, 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), unnormalized_coords); - const auto& dld = device.GetDispatchLoader(); - const auto dev = device.GetLogical(); + const auto& dld{device.GetDispatchLoader()}; + const auto dev{device.GetLogical()}; return dev.createSamplerUnique(sampler_ci, nullptr, dld); } +vk::Sampler VKSamplerCache::ToSamplerType(const UniqueSampler& sampler) const { + return *sampler; +} + } // 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 @@ #include "common/common_types.h" #include "video_core/renderer_vulkan/declarations.h" +#include "video_core/sampler_cache.h" #include "video_core/textures/texture.h" namespace Vulkan { class VKDevice; -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 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 { +class VKSamplerCache final : public VideoCommon::SamplerCache<vk::Sampler, UniqueSampler> { public: explicit VKSamplerCache(const VKDevice& device); ~VKSamplerCache(); - vk::Sampler GetSampler(const Tegra::Texture::TSCEntry& tsc); +protected: + UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const; -private: - UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc); + vk::Sampler ToSamplerType(const UniqueSampler& sampler) const; +private: const VKDevice& device; - std::unordered_map<SamplerCacheKey, UniqueSampler> cache; }; } // 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 @@ +// 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 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 @@ +// 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
\ No newline at end of file |