#include "assets/pools/mesh_pool.hpp" #include namespace sophia { namespace { constexpr u32 GENERATION_MASK = (1u << 12) - 1; } // namespace MeshPool::MeshPool(Device& device) : device{device} {} MeshPool::~MeshPool() = default; MeshHandle MeshPool::create(const Mesh::Builder& builder) { auto mesh = std::make_unique(device, builder); if (!freeList.empty()) { u32 index = freeList.back(); freeList.pop_back(); slots[index].mesh = std::move(mesh); return MeshHandle{index, slots[index].generation}; } slots.push_back(Slot{std::move(mesh), 0}); return MeshHandle{static_cast(slots.size() - 1), 0}; } const Mesh& MeshPool::get(MeshHandle handle) const { SOPHIA_ASSERT(handle.isValid(), "invalid MeshHandle"); SOPHIA_ASSERT(handle.index < slots.size(), "MeshHandle index out of range:", handle.index); const Slot& slot = slots[handle.index]; SOPHIA_ASSERT(slot.generation == handle.generation, "stale MeshHandle (generation mismatch):", handle.index); SOPHIA_ASSERT(slot.mesh != nullptr, "MeshHandle refers to a released mesh:", handle.index); return *slot.mesh; } void MeshPool::release(MeshHandle handle) { SOPHIA_ASSERT(handle.isValid(), "invalid MeshHandle"); SOPHIA_ASSERT(handle.index < slots.size(), "MeshHandle index out of range:", handle.index); Slot& slot = slots[handle.index]; SOPHIA_ASSERT(slot.generation == handle.generation, "stale MeshHandle (generation mismatch):", handle.index); SOPHIA_ASSERT(slot.mesh != nullptr, "MeshHandle already released:", handle.index); slot.mesh.reset(); slot.generation = (slot.generation + 1) & GENERATION_MASK; freeList.push_back(handle.index); } } // namespace sophia