Skip to content

Commit

Permalink
merian: SamplerPool: fix duplicate sampler creation
Browse files Browse the repository at this point in the history
  • Loading branch information
LDAP committed Aug 23, 2024
1 parent 655fcc9 commit 63e332f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 6 deletions.
29 changes: 24 additions & 5 deletions include/merian/utils/hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ template <typename T, typename... Types> 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 <typename... Types> std::size_t hash_val(const Types&... args) {
Expand All @@ -25,12 +25,22 @@ template <typename... Types> std::size_t hash_val(const Types&... args) {
}
//--------------

template <typename T> 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<const uint8_t*>(&v);
std::size_t seed = 0;
for (std::size_t i = 0u; i < size; i++) {
hash_combine(seed, v_bits[i]);
}
return seed;
}

template <typename T> std::size_t hash_aligned_32(const T& v) {
const uint32_t size = sizeof(T) / sizeof(uint32_t);
const uint32_t* vBits = reinterpret_cast<const uint32_t*>(&v);
const std::size_t size = sizeof(T) / sizeof(uint32_t);
const uint32_t* v_bits = reinterpret_cast<const uint32_t*>(&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;
}
Expand All @@ -44,4 +54,13 @@ template <typename T> 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 <typename T> struct HashAligned8 {
std::size_t operator()(const T& s) const {
return hash_aligned_8(s);
}
};

} // namespace merian
15 changes: 14 additions & 1 deletion include/merian/vk/sampler/sampler_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <spdlog/spdlog.h>
#include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_hash.hpp>

#include <unordered_map>

Expand Down Expand Up @@ -59,14 +60,26 @@ class SamplerPool : public std::enable_shared_from_this<SamplerPool> {
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<vk::SamplerCreateInfo> create_hash;
std::hash<vk::SamplerReductionModeCreateInfo> reduction_hash;
std::hash<vk::SamplerYcbcrConversionCreateInfo> ycbcr_conversion_hash;
};

struct Chain {
VkStructureType sType;
const Chain* pNext;
};

const ContextHandle context;

std::unordered_map<SamplerState, std::weak_ptr<Sampler>, HashAligned32<SamplerState>> state_map;
std::unordered_map<SamplerState, std::weak_ptr<Sampler>, SamplerStateHash> state_map;
};

using SamplerPoolHandle = std::shared_ptr<SamplerPool>;
Expand Down

0 comments on commit 63e332f

Please sign in to comment.