mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
vulkan: fix all memory leaks
Now now errors regarding resource management appear in the debug output / validation layers.
This commit is contained in:
@@ -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)
|
||||
: 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();
|
||||
}
|
||||
|
||||
bool Buffer::loadVolatile() {
|
||||
Graphics* vgfx = (Graphics*)gfx;
|
||||
allocator = vgfx->getVmaAllocator();
|
||||
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = getSize();
|
||||
@@ -49,6 +52,12 @@ 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);
|
||||
buffer = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace love {
|
||||
private:
|
||||
// todo use a staging buffer for improved performance
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
love::graphics::Graphics* gfx;
|
||||
VmaAllocator allocator;
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocInfo;
|
||||
|
||||
@@ -234,12 +234,12 @@ namespace love {
|
||||
batchedDrawBuffers.emplace_back();
|
||||
// Initial sizes that should be good enough for most cases. It will
|
||||
// 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
|
||||
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));
|
||||
memcpy(mapInfo.data, whiteColor, sizeof(whiteColor));
|
||||
batchedDrawBuffers[i].constantColorBuffer->unmap(sizeof(whiteColor));
|
||||
@@ -302,6 +302,7 @@ namespace love {
|
||||
std::cout << "unSetMode ";
|
||||
|
||||
created = false;
|
||||
vkDeviceWaitIdle(device);
|
||||
Volatile::unloadAll();
|
||||
cleanup();
|
||||
}
|
||||
@@ -374,7 +375,7 @@ namespace love {
|
||||
|
||||
graphics::StreamBuffer* Graphics::newStreamBuffer(BufferUsage type, size_t size) {
|
||||
std::cout << "newStreamBuffer ";
|
||||
return new StreamBuffer(vmaAllocator, type, size);
|
||||
return new StreamBuffer(this, type, size);
|
||||
}
|
||||
|
||||
Matrix4 Graphics::computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const {
|
||||
@@ -1135,6 +1136,8 @@ namespace love {
|
||||
|
||||
// do we need to use a constant VertexColor?
|
||||
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;
|
||||
|
||||
VkVertexInputBindingDescription bindingDescription{};
|
||||
@@ -1456,10 +1459,9 @@ namespace love {
|
||||
}
|
||||
|
||||
void Graphics::cleanup() {
|
||||
vkDeviceWaitIdle(device);
|
||||
|
||||
cleanupSwapChain();
|
||||
|
||||
vmaDestroyAllocator(vmaAllocator);
|
||||
batchedDrawBuffers.clear();
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
|
||||
|
||||
@@ -213,6 +213,9 @@ namespace love {
|
||||
if (shaderModule == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
// FIXME: objects for deletion should probably be put on a queue
|
||||
// instead of greedy waiting here.
|
||||
vkDeviceWaitIdle(device);
|
||||
vkDestroyShaderModule(device, shaderModule, nullptr);
|
||||
shaderModule = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "StreamBuffer.h"
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
#include "Graphics.h"
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
bool StreamBuffer::loadVolatile() {
|
||||
Graphics* vgfx = (Graphics*)gfx;
|
||||
allocator = vgfx->getVmaAllocator();
|
||||
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = getSize();
|
||||
@@ -43,6 +46,12 @@ 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);
|
||||
buffer = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "graphics/Volatile.h"
|
||||
#include "modules/graphics/StreamBuffer.h"
|
||||
#include "vulkan/vulkan.h"
|
||||
#include "graphics/Graphics.h"
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
|
||||
@@ -12,7 +13,7 @@ namespace love {
|
||||
namespace vulkan {
|
||||
class StreamBuffer : public love::graphics::StreamBuffer, public graphics::Volatile {
|
||||
public:
|
||||
StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size);
|
||||
StreamBuffer(graphics::Graphics* gfx, BufferUsage mode, size_t size);
|
||||
virtual ~StreamBuffer();
|
||||
|
||||
virtual bool loadVolatile() override;
|
||||
@@ -30,6 +31,7 @@ namespace love {
|
||||
}
|
||||
|
||||
private:
|
||||
graphics::Graphics* gfx;
|
||||
VmaAllocator allocator;
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocInfo;
|
||||
|
||||
@@ -69,9 +69,12 @@ 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, nullptr);
|
||||
vmaDestroyImage(allocator, textureImage, textureImageAllocation);
|
||||
|
||||
textureImage = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user