Upgrading pool pattern
This commit is contained in:
@@ -1,81 +1,22 @@
|
||||
#include "resources/pools/render_target_pool.hpp"
|
||||
|
||||
#include <sophia/util/assert.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
namespace {
|
||||
constexpr u32 GENERATION_MASK = (1u << 12) - 1;
|
||||
} // namespace
|
||||
|
||||
RenderTargetPool::RenderTargetPool(Device& device, vk::Format format)
|
||||
: device{device}, format{format} {}
|
||||
|
||||
RenderTargetPool::~RenderTargetPool() = default;
|
||||
|
||||
RenderTargetHandle RenderTargetPool::create(u32 width, u32 height) {
|
||||
auto target = std::make_unique<RenderTarget>(device, format, width, height);
|
||||
|
||||
if (!freeList.empty()) {
|
||||
u32 index = freeList.back();
|
||||
freeList.pop_back();
|
||||
slots[index].target = std::move(target);
|
||||
return RenderTargetHandle{index, slots[index].generation};
|
||||
}
|
||||
|
||||
slots.push_back(Slot{std::move(target), 0});
|
||||
return RenderTargetHandle{static_cast<u32>(slots.size() - 1), 0};
|
||||
}
|
||||
|
||||
const RenderTargetPool::Slot& RenderTargetPool::validate(
|
||||
RenderTargetHandle handle) const {
|
||||
SOPHIA_ASSERT(handle.isValid(), "invalid RenderTargetHandle");
|
||||
SOPHIA_ASSERT(handle.index < slots.size(),
|
||||
"RenderTargetHandle index out of range:", handle.index);
|
||||
|
||||
const Slot& slot = slots[handle.index];
|
||||
SOPHIA_ASSERT(
|
||||
slot.generation == handle.generation,
|
||||
"stale RenderTargetHandle (generation mismatch):", handle.index);
|
||||
SOPHIA_ASSERT(
|
||||
slot.target != nullptr,
|
||||
"RenderTargetHandle refers to a released target:", handle.index);
|
||||
return slot;
|
||||
}
|
||||
|
||||
RenderTarget& RenderTargetPool::get(RenderTargetHandle handle) {
|
||||
return const_cast<RenderTarget&>(std::as_const(*this).get(handle));
|
||||
}
|
||||
|
||||
const RenderTarget& RenderTargetPool::get(RenderTargetHandle handle) const {
|
||||
return *validate(handle).target;
|
||||
return pool.create(device, format, width, height);
|
||||
}
|
||||
|
||||
void RenderTargetPool::release(RenderTargetHandle handle) {
|
||||
validate(handle);
|
||||
|
||||
// Earlier frames may still be rendering into or sampling the target.
|
||||
SOPHIA_ASSERT(pool.isAlive(handle), "invalid RenderTargetHandle");
|
||||
device.waitIdle();
|
||||
|
||||
Slot& slot = slots[handle.index];
|
||||
slot.target.reset();
|
||||
slot.generation = (slot.generation + 1) & GENERATION_MASK;
|
||||
freeList.push_back(handle.index);
|
||||
}
|
||||
|
||||
bool RenderTargetPool::isAlive(RenderTargetHandle handle) const {
|
||||
return handle.isValid() && handle.index < slots.size() &&
|
||||
slots[handle.index].generation == handle.generation &&
|
||||
slots[handle.index].target != nullptr;
|
||||
pool.release(handle);
|
||||
}
|
||||
|
||||
void RenderTargetPool::applyPendingResizes() {
|
||||
for (Slot& slot : slots) {
|
||||
if (slot.target) {
|
||||
slot.target->applyPendingResize();
|
||||
}
|
||||
}
|
||||
pool.forEach([](RenderTarget& target) { target.applyPendingResize(); });
|
||||
}
|
||||
|
||||
} // namespace sophia
|
||||
|
||||
Reference in New Issue
Block a user