+#include "destroyqueue.h"
+#include "device.h"
+#include "vulkan.h"
+
+namespace Msp {
+namespace GL {
+
+DestroyQueue::DestroyQueue(Device &d):
+ device(d)
+{ }
+
+DestroyQueue::~DestroyQueue()
+{
+ while(!queue.empty())
+ tick();
+}
+
+void DestroyQueue::destroy(VkBuffer handle, unsigned mem_id)
+{
+ destroy<VkBuffer, &VulkanFunctions::DestroyBuffer>(handle, mem_id);
+}
+
+void DestroyQueue::destroy(VkFence handle)
+{
+ destroy<VkFence, &VulkanFunctions::DestroyFence>(handle);
+}
+
+void DestroyQueue::destroy(VkFramebuffer handle)
+{
+ destroy<VkFramebuffer, &VulkanFunctions::DestroyFramebuffer>(handle);
+}
+
+void DestroyQueue::destroy(VkImageView handle)
+{
+ destroy<VkImageView, &VulkanFunctions::DestroyImageView>(handle);
+}
+
+void DestroyQueue::destroy(VkSemaphore handle)
+{
+ destroy<VkSemaphore, &VulkanFunctions::DestroySemaphore>(handle);
+}
+
+template<typename T, void (VulkanFunctions::*destroy_func)(T) const>
+void DestroyQueue::destroy(T handle, unsigned mem_id)
+{
+ Entry entry;
+ entry.handle = handle;
+ entry.destroy_func = [](const VulkanFunctions &vk, void *h){ (vk.*destroy_func)(static_cast<T>(h)); };
+ entry.memory_id = mem_id;
+ entry.on_frame = current_frame+MAX_FRAMES_IN_FLIGHT;
+ queue.push_back(entry);
+}
+
+void DestroyQueue::tick()
+{
+ const VulkanFunctions &vk = device.get_functions();
+ MemoryAllocator &allocator = device.get_allocator();
+
+ ++current_frame;
+ while(!queue.empty() && current_frame>=queue.front().on_frame)
+ {
+ const Entry &e = queue.front();
+ e.destroy_func(vk, e.handle);
+ if(e.memory_id)
+ allocator.release(e.memory_id);
+ queue.pop_front();
+ }
+}
+
+} // namespace GL
+} // namespace Msp