video_core: Abstract vk_sampler_cache into a templated class
This commit is contained in:
parent
628153cccd
commit
c5047540c9
@ -67,6 +67,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
|
||||||
|
@ -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
|
||||||
|
21
src/video_core/sampler_cache.cpp
Normal file
21
src/video_core/sampler_cache.cpp
Normal file
@ -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
|
60
src/video_core/sampler_cache.h
Normal file
60
src/video_core/sampler_cache.h
Normal file
@ -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
Block a user