From 63e332f7225463a051fd7fddd443ca2e765dd093 Mon Sep 17 00:00:00 2001 From: Lucas Alber Date: Fri, 23 Aug 2024 10:07:35 +0200 Subject: [PATCH] merian: SamplerPool: fix duplicate sampler creation --- include/merian/utils/hash.hpp | 29 ++++++++++++++++++---- include/merian/vk/sampler/sampler_pool.hpp | 15 ++++++++++- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/include/merian/utils/hash.hpp b/include/merian/utils/hash.hpp index 5ce2ff6f..8633e208 100644 --- a/include/merian/utils/hash.hpp +++ b/include/merian/utils/hash.hpp @@ -15,7 +15,7 @@ template void hash_combine(std::size_t& seed, co hash_combine(seed, args...); } // Optional auxiliary generic functions to support hash_val() without arguments -inline void hashCombine(std::size_t&) {} +inline void hash_combine(std::size_t& /*unused*/) {} // Generic function to create a hash value out of a heterogeneous list of arguments template std::size_t hash_val(const Types&... args) { @@ -25,12 +25,22 @@ template std::size_t hash_val(const Types&... args) { } //-------------- +template std::size_t hash_aligned_8(const T& v) { + const std::size_t size = sizeof(T) / sizeof(uint8_t); + const uint8_t* v_bits = reinterpret_cast(&v); + std::size_t seed = 0; + for (std::size_t i = 0u; i < size; i++) { + hash_combine(seed, v_bits[i]); + } + return seed; +} + template std::size_t hash_aligned_32(const T& v) { - const uint32_t size = sizeof(T) / sizeof(uint32_t); - const uint32_t* vBits = reinterpret_cast(&v); + const std::size_t size = sizeof(T) / sizeof(uint32_t); + const uint32_t* v_bits = reinterpret_cast(&v); std::size_t seed = 0; - for (uint32_t i = 0u; i < size; i++) { - hash_combine(seed, vBits[i]); + for (std::size_t i = 0u; i < size; i++) { + hash_combine(seed, v_bits[i]); } return seed; } @@ -44,4 +54,13 @@ template struct HashAligned32 { } }; +// Generic hash function to use when using a struct aligned to 8-bit as std::map-like container key +// Important: this only works if the struct contains integral types, as it will not +// do any pointer chasing +template struct HashAligned8 { + std::size_t operator()(const T& s) const { + return hash_aligned_8(s); + } +}; + } // namespace merian diff --git a/include/merian/vk/sampler/sampler_pool.hpp b/include/merian/vk/sampler/sampler_pool.hpp index 8d7a3d7f..4f393ca5 100644 --- a/include/merian/vk/sampler/sampler_pool.hpp +++ b/include/merian/vk/sampler/sampler_pool.hpp @@ -6,6 +6,7 @@ #include #include +#include #include @@ -59,6 +60,18 @@ class SamplerPool : public std::enable_shared_from_this { auto operator<=>(const SamplerState&) const = default; }; + struct SamplerStateHash { + std::size_t operator()(const SamplerState& s) const { + return hash_val(create_hash(s.createInfo), reduction_hash(s.reduction), + ycbcr_conversion_hash(s.ycbr)); + } + + private: + std::hash create_hash; + std::hash reduction_hash; + std::hash ycbcr_conversion_hash; + }; + struct Chain { VkStructureType sType; const Chain* pNext; @@ -66,7 +79,7 @@ class SamplerPool : public std::enable_shared_from_this { const ContextHandle context; - std::unordered_map, HashAligned32> state_map; + std::unordered_map, SamplerStateHash> state_map; }; using SamplerPoolHandle = std::shared_ptr;