Browse Source

vulkan: fix clean up

We now don't do any more greedy waiting when destroying vulkan objects.
niki 3 years ago
parent
commit
1096b76054

+ 6 - 4
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;
 			}
 

+ 4 - 0
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<void()> cleanUp) {
+				cleanUpFunctions.at(currentFrame).push_back(std::move(cleanUp));
+			}
+
 			VkCommandBuffer Graphics::beginSingleTimeCommands() {
 				VkCommandBufferAllocateInfo allocInfo{};
 				allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;

+ 2 - 0
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<void(VkCommandBuffer)> command, std::function<void()> cleanUp);
+				void queueCleanUp(std::function<void()> cleanUp);
 
 				VkCommandBuffer beginSingleTimeCommands();
 				void endSingleTimeCommands(VkCommandBuffer);

+ 9 - 10
src/modules/graphics/vulkan/Shader.cpp

@@ -167,19 +167,18 @@ namespace love {
 				}
 
 				auto gfx = Module::getInstance<Graphics>(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();
 			}
 

+ 4 - 7
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;
 			}
 

+ 11 - 6
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;
 			}