Skip to content

Commit

Permalink
Make Id handles typesafe
Browse files Browse the repository at this point in the history
  • Loading branch information
SirBob01 committed Oct 23, 2024
1 parent af3158c commit 0ac0db2
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 37 deletions.
4 changes: 2 additions & 2 deletions src/Graphics/Material.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ namespace Dynamo::Graphics {
template <>
struct std::hash<Dynamo::Graphics::Material> {
inline size_t operator()(const Dynamo::Graphics::Material &material) const {
size_t hash0 = std::hash<unsigned>{}(material.vertex);
size_t hash1 = std::hash<unsigned>{}(material.fragment);
size_t hash0 = std::hash<Dynamo::Graphics::Shader>{}(material.vertex);
size_t hash1 = std::hash<Dynamo::Graphics::Shader>{}(material.fragment);
size_t hash2 = std::hash<unsigned>{}(static_cast<unsigned>(material.topology));
size_t hash3 = std::hash<unsigned>{}(static_cast<unsigned>(material.fill));
size_t hash4 = std::hash<unsigned>{}(static_cast<unsigned>(material.cull));
Expand Down
2 changes: 1 addition & 1 deletion src/Graphics/Mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Dynamo::Graphics {
* @brief Mesh handle.
*
*/
using Mesh = Id;
DEFINE_ID_TYPE(Mesh);

/**
* @brief Mesh index integer width.
Expand Down
2 changes: 1 addition & 1 deletion src/Graphics/Shader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Dynamo::Graphics {
* @brief Shader handle.
*
*/
using Shader = Id;
DEFINE_ID_TYPE(Shader);

/**
* @brief Shader pipeline stage.
Expand Down
4 changes: 2 additions & 2 deletions src/Graphics/Vulkan/FramebufferCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ namespace Dynamo::Graphics::Vulkan {
inline size_t operator()(const FramebufferSettings &settings) const {
size_t hash0 = std::hash<unsigned>{}(settings.extent.width);
size_t hash1 = std::hash<unsigned>{}(settings.extent.height);
size_t hash2 = std::hash<void *>{}(settings.renderpass);
size_t hash3 = std::hash<void *>{}(settings.view);
size_t hash2 = std::hash<VkRenderPass>{}(settings.renderpass);
size_t hash3 = std::hash<VkImageView>{}(settings.view);

return hash0 ^ (hash1 << 1) ^ (hash2 << 2) ^ (hash3 << 3);
}
Expand Down
8 changes: 4 additions & 4 deletions src/Graphics/Vulkan/MaterialRegistry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ namespace Dynamo::Graphics::Vulkan {
size_t hash0 = std::hash<unsigned>{}(settings.topology);
size_t hash1 = std::hash<unsigned>{}(settings.polygon_mode);
size_t hash2 = std::hash<unsigned>{}(settings.cull_mode);
size_t hash3 = std::hash<void *>{}(settings.vertex.handle);
size_t hash4 = std::hash<void *>{}(settings.fragment.handle);
size_t hash5 = std::hash<void *>{}(settings.renderpass);
size_t hash6 = std::hash<void *>{}(settings.layout);
size_t hash3 = std::hash<VkShaderModule>{}(settings.vertex.handle);
size_t hash4 = std::hash<VkShaderModule>{}(settings.fragment.handle);
size_t hash5 = std::hash<VkRenderPass>{}(settings.renderpass);
size_t hash6 = std::hash<VkPipelineLayout>{}(settings.layout);

return hash0 ^ (hash1 << 1) ^ (hash2 << 2) ^ (hash3 << 3) ^ (hash4 << 4) ^ (hash5 << 5) ^ (hash6 << 6);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Graphics/Vulkan/MeshSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ namespace Dynamo::Graphics::Vulkan {
*
*/
class MeshSet {
IdTracker _ids;
SparseSet<MeshAllocation> _allocations;
IdTracker<Mesh> _ids;
SparseSet<Mesh, MeshAllocation> _allocations;

public:
/**
Expand Down
4 changes: 2 additions & 2 deletions src/Graphics/Vulkan/ShaderSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ namespace Dynamo::Graphics::Vulkan {
*/
class ShaderSet {
VkDevice _device;
IdTracker _ids;
SparseSet<ShaderModule> _modules;
IdTracker<Shader> _ids;
SparseSet<Shader, ShaderModule> _modules;
std::unordered_map<DescriptorLayoutKey, VkDescriptorSetLayout, DescriptorLayoutKey::Hash> _descriptor_layouts;

/**
Expand Down
27 changes: 20 additions & 7 deletions src/Utils/IdTracker.hpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
#pragma once

#include <cstdint>
#include <queue>
#include <vector>

#define DEFINE_ID_TYPE(T) using T = struct T##_t *

static_assert(sizeof(void *) == sizeof(uintptr_t), "Pointer and its integer mode must be same size.");

namespace Dynamo {
/**
* @brief Unique identifier supports up to 2^32 - 1 entities simultaneously.
* @brief Id index shift.
*
*/
constexpr unsigned long long ID_INDEX_SHIFT = (sizeof(uintptr_t) * 8) >> 1;

/**
* @brief Id version mask.
*
*/
using Id = unsigned long long;
constexpr unsigned long long ID_VERSION_MASK = (1ULL << ID_INDEX_SHIFT) - 1;

/**
* @brief Generate and discard ids.
* @brief Generate and discard typesafe handles.
*
* @tparam Id
*/
template <typename Id>
class IdTracker {
unsigned _index_counter;

Expand All @@ -33,15 +46,15 @@ namespace Dynamo {
* @param id
* @return unsigned
*/
static inline unsigned get_index(Id id) { return id >> 32; }
static inline unsigned get_index(Id id) { return reinterpret_cast<uintptr_t>(id) >> ID_INDEX_SHIFT; }

/**
* @brief Get the version of an id.
*
* @param id
* @return unsigned
*/
static inline unsigned get_version(Id id) { return id & 0xFFFFFFFF; }
static inline unsigned get_version(Id id) { return reinterpret_cast<uintptr_t>(id) & ID_VERSION_MASK; }

/**
* @brief Test if an id is active.
Expand Down Expand Up @@ -77,8 +90,8 @@ namespace Dynamo {
}

// Move index to longer bitstring before compositing
Id id = index;
return (id << 32) | version;
uintptr_t id = index;
return reinterpret_cast<Id>((id << ID_INDEX_SHIFT) | version);
}

/**
Expand Down
24 changes: 8 additions & 16 deletions src/Utils/SparseSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@
#include <Utils/Log.hpp>

namespace Dynamo {
/**
* @brief Sparse set base class for polymorphism.
*
*/
class SparseSetBase {
public:
virtual ~SparseSetBase() = default;
};

/**
* @brief Sparse sets are an alternative to the hash map that allow
* for efficient association of data with unique identifier keys. Both keys
Expand All @@ -29,10 +20,11 @@ namespace Dynamo {
* Deletion: O(1).
* Search: O(1).
*
* @tparam T Type of element
* @tparam Id Unique handle type
* @tparam T Type of element
*/
template <typename T>
class SparseSet final : public SparseSetBase {
template <typename Id, typename T>
class SparseSet {
/**
* @brief Contains the actual item data
*
Expand Down Expand Up @@ -74,7 +66,7 @@ namespace Dynamo {
* @return int Index position of the value (-1 on failure).
*/
inline int find(Id id) const {
unsigned key = IdTracker::get_index(id);
unsigned key = IdTracker<Id>::get_index(id);
if (key >= _sparse.size()) {
return -1;
}
Expand Down Expand Up @@ -109,7 +101,7 @@ namespace Dynamo {
template <typename... Params>
inline void insert(Id id, Params... args) {
// Resize the sparse array or remove the existing item
unsigned key = IdTracker::get_index(id);
unsigned key = IdTracker<Id>::get_index(id);
if (key >= _sparse.size()) {
_sparse.resize((key + 1) * 2, -1);
} else if (_sparse[key] != -1) {
Expand All @@ -135,7 +127,7 @@ namespace Dynamo {
* @param id Unique identifier of the object to be removed.
*/
inline void remove(Id id) {
unsigned key = IdTracker::get_index(id);
unsigned key = IdTracker<Id>::get_index(id);
if (key >= _sparse.size()) {
return;
}
Expand All @@ -148,7 +140,7 @@ namespace Dynamo {
}

// Swap last element of dense and pool array to maintain contiguity
unsigned new_key = IdTracker::get_index(_dense.back());
unsigned new_key = IdTracker<Id>::get_index(_dense.back());
std::swap(_pool.back(), _pool[index]);
_pool.pop_back();

Expand Down

0 comments on commit 0ac0db2

Please sign in to comment.