Browse Source

vulkan: fix all memory leaks

Now now errors regarding resource management appear in the debug output / validation layers.
niki 3 years ago
parent
commit
9d04ec0030

+ 10 - 1
src/modules/graphics/vulkan/Buffer.cpp

@@ -26,11 +26,14 @@ 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)
 			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), usageFlags(settings.usageFlags), allocator(allocator) {
+				: love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), allocator(allocator), gfx(gfx) {
 				loadVolatile();
 				loadVolatile();
 			}
 			}
 
 
 			bool Buffer::loadVolatile() {
 			bool Buffer::loadVolatile() {
+				Graphics* vgfx = (Graphics*)gfx;
+				allocator = vgfx->getVmaAllocator();
+
 				VkBufferCreateInfo bufferInfo{};
 				VkBufferCreateInfo bufferInfo{};
 				bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
 				bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
 				bufferInfo.size = getSize();
 				bufferInfo.size = getSize();
@@ -49,6 +52,12 @@ namespace love {
 				if (buffer == VK_NULL_HANDLE)
 				if (buffer == VK_NULL_HANDLE)
 					return;
 					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);
 				vmaDestroyBuffer(allocator, buffer, allocation);
 				buffer = VK_NULL_HANDLE;
 				buffer = VK_NULL_HANDLE;
 			}
 			}

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

@@ -30,6 +30,7 @@ namespace love {
 			private:
 			private:
 				// todo use a staging buffer for improved performance
 				// todo use a staging buffer for improved performance
 				VkBuffer buffer = VK_NULL_HANDLE;
 				VkBuffer buffer = VK_NULL_HANDLE;
+				love::graphics::Graphics* gfx;
 				VmaAllocator allocator;
 				VmaAllocator allocator;
 				VmaAllocation allocation;
 				VmaAllocation allocation;
 				VmaAllocationInfo allocInfo;
 				VmaAllocationInfo allocInfo;

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

@@ -234,12 +234,12 @@ namespace love {
 					batchedDrawBuffers.emplace_back();
 					batchedDrawBuffers.emplace_back();
 					// Initial sizes that should be good enough for most cases. It will
 					// Initial sizes that should be good enough for most cases. It will
 					// resize to fit if needed, later.
 					// resize to fit if needed, later.
-					batchedDrawBuffers[i].vertexBuffer1 = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
-					batchedDrawBuffers[i].vertexBuffer2 = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
-					batchedDrawBuffers[i].indexBuffer = new StreamBuffer(vmaAllocator, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
+					batchedDrawBuffers[i].vertexBuffer1 = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
+					batchedDrawBuffers[i].vertexBuffer2 = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
+					batchedDrawBuffers[i].indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
 
 
 					// sometimes the VertexColor is not set, so we manually adjust it to white color
 					// sometimes the VertexColor is not set, so we manually adjust it to white color
-					batchedDrawBuffers[i].constantColorBuffer = new StreamBuffer(vmaAllocator, BUFFERUSAGE_VERTEX, sizeof(whiteColor));
+					batchedDrawBuffers[i].constantColorBuffer = new StreamBuffer(this, BUFFERUSAGE_VERTEX, sizeof(whiteColor));
 					auto mapInfo = batchedDrawBuffers[i].constantColorBuffer->map(sizeof(whiteColor));
 					auto mapInfo = batchedDrawBuffers[i].constantColorBuffer->map(sizeof(whiteColor));
 					memcpy(mapInfo.data, whiteColor, sizeof(whiteColor));
 					memcpy(mapInfo.data, whiteColor, sizeof(whiteColor));
 					batchedDrawBuffers[i].constantColorBuffer->unmap(sizeof(whiteColor));
 					batchedDrawBuffers[i].constantColorBuffer->unmap(sizeof(whiteColor));
@@ -302,6 +302,7 @@ namespace love {
 				std::cout << "unSetMode ";
 				std::cout << "unSetMode ";
 				
 				
 				created = false;
 				created = false;
+				vkDeviceWaitIdle(device);
 				Volatile::unloadAll();
 				Volatile::unloadAll();
 				cleanup();
 				cleanup();
 			}
 			}
@@ -374,7 +375,7 @@ namespace love {
 
 
 			graphics::StreamBuffer* Graphics::newStreamBuffer(BufferUsage type, size_t size) {
 			graphics::StreamBuffer* Graphics::newStreamBuffer(BufferUsage type, size_t size) {
 				std::cout << "newStreamBuffer ";
 				std::cout << "newStreamBuffer ";
-				return new StreamBuffer(vmaAllocator, type, size);
+				return new StreamBuffer(this, type, size);
 			}
 			}
 
 
 			Matrix4 Graphics::computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const { 
 			Matrix4 Graphics::computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const { 
@@ -1135,6 +1136,8 @@ namespace love {
 
 
 				// do we need to use a constant VertexColor?
 				// do we need to use a constant VertexColor?
 				if (!usesColor) {
 				if (!usesColor) {
+					// FIXME: is there a case where gaps happen between buffer bindings?
+					// then this doesn't work. We might need to enable null buffers again.
 					const auto constantColorBufferBinding = highestBufferBinding + 1;
 					const auto constantColorBufferBinding = highestBufferBinding + 1;
 
 
 					VkVertexInputBindingDescription bindingDescription{};
 					VkVertexInputBindingDescription bindingDescription{};
@@ -1456,10 +1459,9 @@ namespace love {
 			}
 			}
 
 
 			void Graphics::cleanup() {
 			void Graphics::cleanup() {
-				vkDeviceWaitIdle(device);
-
 				cleanupSwapChain();
 				cleanupSwapChain();
 
 
+				vmaDestroyAllocator(vmaAllocator);
 				batchedDrawBuffers.clear();
 				batchedDrawBuffers.clear();
 				for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
 				for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
 					vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
 					vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);

+ 3 - 0
src/modules/graphics/vulkan/ShaderStage.cpp

@@ -213,6 +213,9 @@ namespace love {
 				if (shaderModule == VK_NULL_HANDLE)
 				if (shaderModule == VK_NULL_HANDLE)
 					return;
 					return;
 
 
+				// FIXME: objects for deletion should probably be put on a queue
+				// instead of greedy waiting here.
+				vkDeviceWaitIdle(device);
 				vkDestroyShaderModule(device, shaderModule, nullptr);
 				vkDestroyShaderModule(device, shaderModule, nullptr);
 				shaderModule = VK_NULL_HANDLE;
 				shaderModule = VK_NULL_HANDLE;
 			}
 			}

+ 12 - 3
src/modules/graphics/vulkan/StreamBuffer.cpp

@@ -1,6 +1,6 @@
 #include "StreamBuffer.h"
 #include "StreamBuffer.h"
 #include "vulkan/vulkan.h"
 #include "vulkan/vulkan.h"
-
+#include "Graphics.h"
 
 
 
 
 namespace love {
 namespace love {
@@ -16,12 +16,15 @@ namespace love {
 				}
 				}
 			}
 			}
 
 
-			StreamBuffer::StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size)
-				:	love::graphics::StreamBuffer(mode, size), allocator(allocator) {
+			StreamBuffer::StreamBuffer(graphics::Graphics* gfx, BufferUsage mode, size_t size)
+				:	love::graphics::StreamBuffer(mode, size), gfx(gfx) {
 				loadVolatile();
 				loadVolatile();
 			}
 			}
 
 
 			bool StreamBuffer::loadVolatile() {
 			bool StreamBuffer::loadVolatile() {
+				Graphics* vgfx = (Graphics*)gfx;
+				allocator = vgfx->getVmaAllocator();
+
 				VkBufferCreateInfo bufferInfo{};
 				VkBufferCreateInfo bufferInfo{};
 				bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
 				bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
 				bufferInfo.size = getSize();
 				bufferInfo.size = getSize();
@@ -43,6 +46,12 @@ namespace love {
 				if (buffer == VK_NULL_HANDLE)
 				if (buffer == VK_NULL_HANDLE)
 					return;
 					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);
 				vmaDestroyBuffer(allocator, buffer, allocation);
 				buffer = VK_NULL_HANDLE;
 				buffer = VK_NULL_HANDLE;
 			}
 			}

+ 3 - 1
src/modules/graphics/vulkan/StreamBuffer.h

@@ -4,6 +4,7 @@
 #include "graphics/Volatile.h"
 #include "graphics/Volatile.h"
 #include "modules/graphics/StreamBuffer.h"
 #include "modules/graphics/StreamBuffer.h"
 #include "vulkan/vulkan.h"
 #include "vulkan/vulkan.h"
+#include "graphics/Graphics.h"
 
 
 #include "vk_mem_alloc.h"
 #include "vk_mem_alloc.h"
 
 
@@ -12,7 +13,7 @@ namespace love {
 		namespace vulkan {
 		namespace vulkan {
 			class StreamBuffer : public love::graphics::StreamBuffer, public graphics::Volatile {
 			class StreamBuffer : public love::graphics::StreamBuffer, public graphics::Volatile {
 			public:
 			public:
-				StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size);
+				StreamBuffer(graphics::Graphics* gfx, BufferUsage mode, size_t size);
 				virtual ~StreamBuffer();
 				virtual ~StreamBuffer();
 
 
 				virtual bool loadVolatile() override;
 				virtual bool loadVolatile() override;
@@ -30,6 +31,7 @@ namespace love {
 				}
 				}
 
 
 			private:
 			private:
+				graphics::Graphics* gfx;
 				VmaAllocator allocator;
 				VmaAllocator allocator;
 				VmaAllocation allocation;
 				VmaAllocation allocation;
 				VmaAllocationInfo allocInfo;
 				VmaAllocationInfo allocInfo;

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

@@ -69,9 +69,12 @@ namespace love {
 				if (textureImage == VK_NULL_HANDLE)
 				if (textureImage == VK_NULL_HANDLE)
 					return;
 					return;
 
 
+				// FIXME: objects for deletion should probably be put on a queue
+				// instead of greedy waiting here.
+				vkDeviceWaitIdle(device);
 				vkDestroySampler(device, textureSampler, nullptr);
 				vkDestroySampler(device, textureSampler, nullptr);
 				vkDestroyImageView(device, textureImageView, nullptr);
 				vkDestroyImageView(device, textureImageView, nullptr);
-				vmaDestroyImage(allocator, textureImage, nullptr);
+				vmaDestroyImage(allocator, textureImage, textureImageAllocation);
 
 
 				textureImage = VK_NULL_HANDLE;
 				textureImage = VK_NULL_HANDLE;
 			}
 			}