Huge changes #3
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
namespace sophia {
|
namespace sophia {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr u32 GENERATION_MASK = (1u << 12) - 1;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
MeshPool::MeshPool(Device& device) : device{device} {}
|
MeshPool::MeshPool(Device& device) : device{device} {}
|
||||||
|
|
||||||
MeshPool::~MeshPool() = default;
|
MeshPool::~MeshPool() = default;
|
||||||
@@ -12,30 +16,43 @@ MeshHandle MeshPool::create(const Mesh::Builder& builder) {
|
|||||||
auto mesh = std::make_unique<Mesh>(device, builder);
|
auto mesh = std::make_unique<Mesh>(device, builder);
|
||||||
|
|
||||||
if (!freeList.empty()) {
|
if (!freeList.empty()) {
|
||||||
MeshHandle handle = freeList.back();
|
u32 index = freeList.back();
|
||||||
freeList.pop_back();
|
freeList.pop_back();
|
||||||
meshes[handle] = std::move(mesh);
|
slots[index].mesh = std::move(mesh);
|
||||||
return handle;
|
return MeshHandle{index, slots[index].generation};
|
||||||
}
|
}
|
||||||
|
|
||||||
meshes.push_back(std::move(mesh));
|
slots.push_back(Slot{std::move(mesh), 0});
|
||||||
return static_cast<MeshHandle>(meshes.size() - 1);
|
return MeshHandle{static_cast<u32>(slots.size() - 1), 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Mesh& MeshPool::get(MeshHandle handle) const {
|
const Mesh& MeshPool::get(MeshHandle handle) const {
|
||||||
SOPHIA_ASSERT(handle < meshes.size(), "invalid MeshHandle:", handle);
|
SOPHIA_ASSERT(handle.isValid(), "invalid MeshHandle");
|
||||||
SOPHIA_ASSERT(meshes[handle] != nullptr,
|
SOPHIA_ASSERT(handle.index < slots.size(),
|
||||||
"MeshHandle refers to a released mesh:", handle);
|
"MeshHandle index out of range:", handle.index);
|
||||||
return *meshes[handle];
|
|
||||||
|
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) {
|
void MeshPool::release(MeshHandle handle) {
|
||||||
SOPHIA_ASSERT(handle < meshes.size(), "invalid MeshHandle:", handle);
|
SOPHIA_ASSERT(handle.isValid(), "invalid MeshHandle");
|
||||||
SOPHIA_ASSERT(meshes[handle] != nullptr,
|
SOPHIA_ASSERT(handle.index < slots.size(),
|
||||||
"MeshHandle already released:", handle);
|
"MeshHandle index out of range:", handle.index);
|
||||||
|
|
||||||
meshes[handle].reset();
|
Slot& slot = slots[handle.index];
|
||||||
freeList.push_back(handle);
|
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
|
} // namespace sophia
|
||||||
|
|||||||
@@ -21,10 +21,15 @@ class MeshPool {
|
|||||||
void release(MeshHandle handle);
|
void release(MeshHandle handle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Slot {
|
||||||
|
std::unique_ptr<Mesh> mesh;
|
||||||
|
u32 generation = 0;
|
||||||
|
};
|
||||||
|
|
||||||
Device& device;
|
Device& device;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Mesh>> meshes;
|
std::vector<Slot> slots;
|
||||||
std::vector<MeshHandle> freeList;
|
std::vector<u32> freeList;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sophia
|
} // namespace sophia
|
||||||
|
|||||||
Reference in New Issue
Block a user