diff --git a/src/modules/graphics/vulkan/Buffer.cpp b/src/modules/graphics/vulkan/Buffer.cpp index 7e5ac6604..9eef9c713 100644 --- a/src/modules/graphics/vulkan/Buffer.cpp +++ b/src/modules/graphics/vulkan/Buffer.cpp @@ -55,10 +55,12 @@ namespace love { Graphics* vgfx = (Graphics*)gfx; auto device = vgfx->getDevice(); - // FIXME: objects for deletion should probably be put on a queue - // instead of greedy waiting here. - vkDeviceWaitIdle(device); - vmaDestroyBuffer(allocator, buffer, allocation); + vgfx->queueCleanUp( + [device=device, allocator=allocator, buffer=buffer, allocation=allocation](){ + vkDeviceWaitIdle(device); + vmaDestroyBuffer(allocator, buffer, allocation); + }); + buffer = VK_NULL_HANDLE; } diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index ea9e7a736..b3e94d753 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -556,6 +556,10 @@ namespace love { cleanUpFunctions.at(currentFrame).push_back(std::move(cleanUp)); } + void Graphics::queueCleanUp(std::function cleanUp) { + cleanUpFunctions.at(currentFrame).push_back(std::move(cleanUp)); + } + VkCommandBuffer Graphics::beginSingleTimeCommands() { VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index b0d51f938..4a0fb1cd9 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -114,7 +114,9 @@ namespace love { GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Buffer* buffer, size_t offset, size_t size, data::ByteData* dest, size_t destoffset) override { return nullptr; }; GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Texture* texture, int slice, int mipmap, const Rect& rect, image::ImageData* dest, int destx, int desty) { return nullptr; } + // fixme: better naming for these two functions? void executeCommand(std::function command, std::function cleanUp); + void queueCleanUp(std::function cleanUp); VkCommandBuffer beginSingleTimeCommands(); void endSingleTimeCommands(VkCommandBuffer); diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index b2cab1b77..ea8a279f7 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -167,19 +167,18 @@ namespace love { } auto gfx = Module::getInstance(Module::M_GRAPHICS); - auto device = gfx->getDevice(); - // fixme: we shouldn't do a greedy wait here. - vkDeviceWaitIdle(device); - for (const auto shaderModule : shaderModules) { - vkDestroyShaderModule(device, shaderModule, nullptr); - } - shaderModules.clear(); - shaderStages.clear(); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + gfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout](){ + for (const auto shaderModule : shaderModules) { + vkDestroyShaderModule(device, shaderModule, nullptr); + } + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + }); for (const auto streamBuffer : streamBuffers) { delete streamBuffer; } + shaderModules.clear(); + shaderStages.clear(); streamBuffers.clear(); } diff --git a/src/modules/graphics/vulkan/StreamBuffer.cpp b/src/modules/graphics/vulkan/StreamBuffer.cpp index a1cd2e662..7c49d679d 100644 --- a/src/modules/graphics/vulkan/StreamBuffer.cpp +++ b/src/modules/graphics/vulkan/StreamBuffer.cpp @@ -46,13 +46,10 @@ namespace love { if (buffer == VK_NULL_HANDLE) return; - Graphics* vgfx = (Graphics*)gfx; - auto device = vgfx->getDevice(); - - // FIXME: objects for deletion should probably be put on a queue - // instead of greedy waiting here. - vkDeviceWaitIdle(device); - vmaDestroyBuffer(allocator, buffer, allocation); + auto vgfx = (Graphics*)gfx; + vgfx->queueCleanUp([allocator=allocator, buffer=buffer, allocation=allocation](){ + vmaDestroyBuffer(allocator, buffer, allocation); + }); buffer = VK_NULL_HANDLE; } diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 2783e64b9..f92cd3f1d 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -74,12 +74,17 @@ namespace love { if (textureImage == VK_NULL_HANDLE) return; - // FIXME: objects for deletion should probably be put on a queue - // instead of greedy waiting here. - vkDeviceWaitIdle(device); - vkDestroySampler(device, textureSampler, nullptr); - vkDestroyImageView(device, textureImageView, nullptr); - vmaDestroyImage(allocator, textureImage, textureImageAllocation); + vgfx->queueCleanUp([ + device = device, + textureSampler = textureSampler, + textureImageView = textureImageView, + allocator = allocator, + textureImage = textureImage, + textureImageAllocation = textureImageAllocation] () { + vkDestroySampler(device, textureSampler, nullptr); + vkDestroyImageView(device, textureImageView, nullptr); + vmaDestroyImage(allocator, textureImage, textureImageAllocation); + }); textureImage = VK_NULL_HANDLE; }