Merge pull request 'perf(device): pop retired deletions off the front in O(ready) (#116)' (#135) from claude/issue-116 into master
This commit is contained in:
commit
5948bb91c1
2 changed files with 20 additions and 15 deletions
|
|
@ -1010,21 +1010,22 @@ void Device::EnqueueDeletion(VkBuffer buffer, VkDeviceMemory memory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ReclaimDeletions() {
|
void Device::ReclaimDeletions() {
|
||||||
// Free every entry whose retire frame has been reached, compacting the
|
// Free every entry whose retire frame has been reached. An entry tagged at
|
||||||
// survivors down in place. An entry tagged at frame F retires at
|
// frame F retires at F + framesInFlight: by the time the CPU has begun that
|
||||||
// F + framesInFlight: by the time the CPU has begun that many later
|
// many later frames (each gated by a per-image fence wait), single-queue
|
||||||
// frames (each gated by a per-image fence wait), single-queue submission
|
// submission order guarantees all GPU work from frame F is complete.
|
||||||
// order guarantees all GPU work from frame F is complete.
|
//
|
||||||
std::size_t kept = 0;
|
// frameCounter is monotonic, so retireAfter is non-decreasing down the
|
||||||
for (PendingDeletion& entry : deletionQueue) {
|
// queue and the ready entries are a contiguous prefix: pop them off the
|
||||||
if (entry.retireAfter + framesInFlight <= frameCounter) {
|
// front and stop at the first one still in flight (everything behind it is
|
||||||
|
// newer, hence also in flight). O(ready), not O(queue).
|
||||||
|
while (!deletionQueue.empty() &&
|
||||||
|
deletionQueue.front().retireAfter + framesInFlight <= frameCounter) {
|
||||||
|
const PendingDeletion& entry = deletionQueue.front();
|
||||||
vkDestroyBuffer(device, entry.buffer, nullptr);
|
vkDestroyBuffer(device, entry.buffer, nullptr);
|
||||||
vkFreeMemory(device, entry.memory, nullptr);
|
vkFreeMemory(device, entry.memory, nullptr);
|
||||||
} else {
|
deletionQueue.pop_front();
|
||||||
deletionQueue[kept++] = entry;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
deletionQueue.resize(kept);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::DrainDeletions() {
|
void Device::DrainDeletions() {
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,11 @@ export namespace Crafter {
|
||||||
// Zero until set, which only makes ReclaimDeletions more eager — and it
|
// Zero until set, which only makes ReclaimDeletions more eager — and it
|
||||||
// is never called before a Window (which sets this) starts rendering.
|
// is never called before a Window (which sets this) starts rendering.
|
||||||
inline static std::uint8_t framesInFlight = 0;
|
inline static std::uint8_t framesInFlight = 0;
|
||||||
inline static std::vector<PendingDeletion> deletionQueue;
|
// A deque, not a vector: frameCounter is monotonic, so retireAfter is
|
||||||
|
// non-decreasing down the queue and the entries ready to reclaim are
|
||||||
|
// always a prefix. ReclaimDeletions pops that prefix off the front in
|
||||||
|
// O(ready) instead of walking and compacting the whole queue.
|
||||||
|
inline static std::deque<PendingDeletion> deletionQueue;
|
||||||
// Tag {buffer, memory} for deletion after framesInFlight more frames.
|
// Tag {buffer, memory} for deletion after framesInFlight more frames.
|
||||||
// A VK_NULL_HANDLE buffer is ignored (nothing to free).
|
// A VK_NULL_HANDLE buffer is ignored (nothing to free).
|
||||||
static void EnqueueDeletion(VkBuffer buffer, VkDeviceMemory memory);
|
static void EnqueueDeletion(VkBuffer buffer, VkDeviceMemory memory);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue