Browse Source

vulkan: fix some memory leaks

niki 3 years ago
parent
commit
0759e8d513

+ 17 - 4
src/modules/graphics/vulkan/Buffer.cpp

@@ -26,22 +26,35 @@ namespace love {
 			}
 
 			Buffer::Buffer(VmaAllocator allocator, love::graphics::Graphics* gfx, const Settings& settings, const std::vector<DataDeclaration>& format, const void* data, size_t size, size_t arraylength)
-				: love::graphics::Buffer(gfx, settings, format, size, arraylength) {
+				: love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), allocator(allocator) {
+				loadVolatile();
+			}
 
+			bool Buffer::loadVolatile() {
 				VkBufferCreateInfo bufferInfo{};
 				bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
-				bufferInfo.size = size;
-				bufferInfo.usage = getVulkanUsageFlags(settings.usageFlags);
+				bufferInfo.size = getSize();
+				bufferInfo.usage = getVulkanUsageFlags(usageFlags);
 
 				VmaAllocationCreateInfo allocCreateInfo = {};
 				allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
 				allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
 
 				vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, &allocInfo);
+
+				return true;
+			}
+
+			void Buffer::unloadVolatile() {
+				if (buffer == VK_NULL_HANDLE)
+					return;
+
+				vmaDestroyBuffer(allocator, buffer, allocation);
+				buffer = VK_NULL_HANDLE;
 			}
 
 			Buffer::~Buffer() {
-				// fixme
+				unloadVolatile();
 			}
 
 			void* Buffer::map(MapType map, size_t offset, size_t size) {

+ 8 - 2
src/modules/graphics/vulkan/Buffer.h

@@ -1,16 +1,20 @@
 #include "graphics/Buffer.h"
 #include <vulkan/vulkan.h>
 #include "vk_mem_alloc.h"
+#include "graphics/Volatile.h"
 
 
 namespace love {
 	namespace graphics {
 		namespace vulkan {
-			class Buffer : public love::graphics::Buffer {
+			class Buffer : public love::graphics::Buffer, public Volatile {
 			public:
 				Buffer(VmaAllocator allocator, love::graphics::Graphics* gfx, const Settings& settings, const std::vector<DataDeclaration>& format, const void* data, size_t size, size_t arraylength);
 				virtual ~Buffer();
 
+				virtual bool loadVolatile() override;
+				virtual void unloadVolatile() override;
+
 				void* map(MapType map, size_t offset, size_t size) override;
 				void unmap(size_t usedoffset, size_t usedsize) override;
 				bool fill(size_t offset, size_t size, const void* data) override;
@@ -25,9 +29,11 @@ namespace love {
 
 			private:
 				// todo use a staging buffer for improved performance
-				VkBuffer buffer;
+				VkBuffer buffer = VK_NULL_HANDLE;
+				VmaAllocator allocator;
 				VmaAllocation allocation;
 				VmaAllocationInfo allocInfo;
+				BufferUsageFlags usageFlags;
 			};
 		}
 	}

+ 9 - 1
src/modules/graphics/vulkan/Graphics.cpp

@@ -302,6 +302,7 @@ namespace love {
 				std::cout << "unSetMode ";
 				
 				created = false;
+				Volatile::unloadAll();
 				cleanup();
 			}
 			
@@ -1280,6 +1281,7 @@ namespace love {
 				if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
 					throw love::Exception("failed to create pipeline layout");
 				}
+				graphicsPipelineLayouts.push_back(pipelineLayout);
 
 				VkGraphicsPipelineCreateInfo pipelineInfo{};
 				pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -1485,12 +1487,18 @@ namespace love {
 				}
 				graphicsPipelines.clear();
 				currentGraphicsPipeline = VK_NULL_HANDLE;
-				// vkDestroyPipelineLayout(device, pipelineLayout, nullptr); FIXME
+				for (const auto pipelineLayout : graphicsPipelineLayouts) {
+					vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
+				}
+				graphicsPipelineLayouts.clear();
 				vkDestroyRenderPass(device, renderPass, nullptr);
 				for (size_t i = 0; i < swapChainImageViews.size(); i++) {
 					vkDestroyImageView(device, swapChainImageViews[i], nullptr);
 				}
 				vkDestroySwapchainKHR(device, swapChain, nullptr);
+				for (auto p : uniformBufferMap) {
+					delete p.second;
+				}
 				uniformBufferMap.clear();
 				descriptorSetsMap.clear();
 			}

+ 1 - 0
src/modules/graphics/vulkan/Graphics.h

@@ -190,6 +190,7 @@ namespace love {
 				VkRenderPass renderPass = VK_NULL_HANDLE;
 				VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE;
 				std::vector<std::pair<GraphicsPipelineConfiguration, VkPipeline>> graphicsPipelines;	// FIXME improve performance by using a hash map
+				std::vector<VkPipelineLayout> graphicsPipelineLayouts;
 				std::vector<VkFramebuffer> swapChainFramBuffers;
 				VkCommandPool commandPool = VK_NULL_HANDLE;
 				std::vector<VkCommandBuffer> commandBuffers;

+ 16 - 2
src/modules/graphics/vulkan/ShaderStage.cpp

@@ -185,7 +185,13 @@ namespace love {
 			}
 
 			ShaderStage::ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey)
-				: love::graphics::ShaderStage(gfx, stage, glsl, gles, cachekey) {
+				: love::graphics::ShaderStage(gfx, stage, glsl, gles, cachekey), gfx(gfx) {
+				loadVolatile();
+			}
+
+			bool ShaderStage::loadVolatile() {
+				auto stage = getStageType();
+				auto glsl = getSource();
 				auto code = compileShaderWithGlslang(glsl, stage);
 
 				VkShaderModuleCreateInfo createInfo{};
@@ -201,8 +207,16 @@ namespace love {
 				}
 			}
 
+			void ShaderStage::unloadVolatile() {
+				if (shaderModule == VK_NULL_HANDLE)
+					return;
+
+				vkDestroyShaderModule(device, shaderModule, nullptr);
+				shaderModule = VK_NULL_HANDLE;
+			}
+
 			ShaderStage::~ShaderStage() {
-				// vkDestroyShaderModule(device, shaderModule, nullptr);
+				unloadVolatile();
 			}
 		}
 	}

+ 7 - 3
src/modules/graphics/vulkan/ShaderStage.h

@@ -8,11 +8,15 @@
 namespace love {
 	namespace graphics {
 		namespace vulkan {
-			class ShaderStage final : public graphics::ShaderStage {
+			class ShaderStage final : public graphics::ShaderStage, public Volatile {
 			public:
 				ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey);
 				virtual ~ShaderStage();
 
+				virtual bool loadVolatile() override;
+
+				virtual void unloadVolatile() override;
+
 				VkShaderModule getShaderModule() const {
 					return shaderModule;
 				}
@@ -22,9 +26,9 @@ namespace love {
 				}
 
 			private:
-				VkShaderModule shaderModule;
+				VkShaderModule shaderModule = VK_NULL_HANDLE;
 				VkDevice device;
-
+				love::graphics::Graphics* gfx;
 			};
 		}
 	}

+ 15 - 1
src/modules/graphics/vulkan/StreamBuffer.cpp

@@ -18,6 +18,10 @@ namespace love {
 
 			StreamBuffer::StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size)
 				:	love::graphics::StreamBuffer(mode, size), allocator(allocator) {
+				loadVolatile();
+			}
+
+			bool StreamBuffer::loadVolatile() {
 				VkBufferCreateInfo bufferInfo{};
 				bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
 				bufferInfo.size = getSize();
@@ -31,10 +35,20 @@ namespace love {
 				vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, &allocInfo);
 
 				usedGPUMemory = 0;
+
+				return true;
+			}
+
+			void StreamBuffer::unloadVolatile() {
+				if (buffer == VK_NULL_HANDLE)
+					return;
+
+				vmaDestroyBuffer(allocator, buffer, allocation);
+				buffer = VK_NULL_HANDLE;
 			}
 
 			StreamBuffer::~StreamBuffer() {
-				// vmaDestroyBuffer(allocator, buffer, allocation);
+				unloadVolatile();
 			}
 
 			love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t minsize) {

+ 7 - 2
src/modules/graphics/vulkan/StreamBuffer.h

@@ -1,6 +1,7 @@
 #ifndef LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H
 #define LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H
 
+#include "graphics/Volatile.h"
 #include "modules/graphics/StreamBuffer.h"
 #include "vulkan/vulkan.h"
 
@@ -9,11 +10,15 @@
 namespace love {
 	namespace graphics {
 		namespace vulkan {
-			class StreamBuffer : public love::graphics::StreamBuffer {
+			class StreamBuffer : public love::graphics::StreamBuffer, public graphics::Volatile {
 			public:
 				StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size);
 				virtual ~StreamBuffer();
 
+				virtual bool loadVolatile() override;
+
+				virtual void unloadVolatile() override;
+
 				MapInfo map(size_t minsize) override;
 				size_t unmap(size_t usedSize) override;
 				void markUsed(size_t usedSize) override;
@@ -28,7 +33,7 @@ namespace love {
 				VmaAllocator allocator;
 				VmaAllocation allocation;
 				VmaAllocationInfo allocInfo;
-				VkBuffer buffer;
+				VkBuffer buffer = VK_NULL_HANDLE;
 				size_t usedGPUMemory;
 
 			};

+ 17 - 4
src/modules/graphics/vulkan/Texture.cpp

@@ -9,7 +9,11 @@ namespace love {
 	namespace graphics {
 		namespace vulkan {
 			Texture::Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data)
-				: love::graphics::Texture(gfx, settings, data), gfx(gfx) {
+				: love::graphics::Texture(gfx, settings, data), gfx(gfx), data(data) {
+				loadVolatile();
+			}
+
+			bool Texture::loadVolatile() {
 				allocator = vgfx->getVmaAllocator();
 				device = vgfx->getDevice();
 
@@ -59,10 +63,19 @@ namespace love {
 				createTextureSampler();
 			}
 
+			void Texture::unloadVolatile() {
+				if (textureImage == VK_NULL_HANDLE)
+					return;
+
+				vkDestroySampler(device, textureSampler, nullptr);
+				vkDestroyImageView(device, textureImageView, nullptr);
+				vmaDestroyImage(allocator, textureImage, nullptr);
+
+				textureImage = VK_NULL_HANDLE;
+			}
+
 			Texture::~Texture() {
-				// vkDestroySampler(device, textureSampler, nullptr);
-				// vkDestroyImageView(device, textureImageView, nullptr);
-				// vmaDestroyImage(allocator, textureImage, nullptr);
+				unloadVolatile();
 			}
 
 			void Texture::createTextureImageView() {

+ 6 - 2
src/modules/graphics/vulkan/Texture.h

@@ -12,11 +12,14 @@
 namespace love {
 	namespace graphics {
 		namespace vulkan {
-			class Texture : public graphics::Texture {
+			class Texture : public graphics::Texture, public Volatile {
 			public:
 				Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data);
 				~Texture();
 
+				virtual bool loadVolatile() override;
+				virtual void unloadVolatile() override;
+
 				void copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect& rect) override { std::cout << "Texture::copyFromBuffer "; };
 				void copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const Rect& rect, size_t destoffset, int destwidth, size_t size) override { std::cout << "Texture::copyToBuffer "; };
 
@@ -41,10 +44,11 @@ namespace love {
 				graphics::Graphics* gfx;
 				VkDevice device;
 				VmaAllocator allocator;
-				VkImage textureImage;
+				VkImage textureImage = VK_NULL_HANDLE;
 				VmaAllocation textureImageAllocation;
 				VkImageView textureImageView;
 				VkSampler textureSampler;
+				const Slices* data;
 			};
 		}
 	}