mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
vulkan: fix some memory leaks
This commit is contained in:
@@ -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)
|
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{};
|
VkBufferCreateInfo bufferInfo{};
|
||||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
bufferInfo.size = size;
|
bufferInfo.size = getSize();
|
||||||
bufferInfo.usage = getVulkanUsageFlags(settings.usageFlags);
|
bufferInfo.usage = getVulkanUsageFlags(usageFlags);
|
||||||
|
|
||||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||||
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||||
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
|
|
||||||
vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, &allocInfo);
|
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() {
|
Buffer::~Buffer() {
|
||||||
// fixme
|
unloadVolatile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Buffer::map(MapType map, size_t offset, size_t size) {
|
void* Buffer::map(MapType map, size_t offset, size_t size) {
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
#include "graphics/Buffer.h"
|
#include "graphics/Buffer.h"
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vk_mem_alloc.h"
|
#include "vk_mem_alloc.h"
|
||||||
|
#include "graphics/Volatile.h"
|
||||||
|
|
||||||
|
|
||||||
namespace love {
|
namespace love {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
class Buffer : public love::graphics::Buffer {
|
class Buffer : public love::graphics::Buffer, public Volatile {
|
||||||
public:
|
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);
|
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 ~Buffer();
|
||||||
|
|
||||||
|
virtual bool loadVolatile() override;
|
||||||
|
virtual void unloadVolatile() override;
|
||||||
|
|
||||||
void* map(MapType map, size_t offset, size_t size) override;
|
void* map(MapType map, size_t offset, size_t size) override;
|
||||||
void unmap(size_t usedoffset, size_t usedsize) override;
|
void unmap(size_t usedoffset, size_t usedsize) override;
|
||||||
bool fill(size_t offset, size_t size, const void* data) override;
|
bool fill(size_t offset, size_t size, const void* data) override;
|
||||||
@@ -25,9 +29,11 @@ namespace love {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// todo use a staging buffer for improved performance
|
// todo use a staging buffer for improved performance
|
||||||
VkBuffer buffer;
|
VkBuffer buffer = VK_NULL_HANDLE;
|
||||||
|
VmaAllocator allocator;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
VmaAllocationInfo allocInfo;
|
VmaAllocationInfo allocInfo;
|
||||||
|
BufferUsageFlags usageFlags;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ namespace love {
|
|||||||
std::cout << "unSetMode ";
|
std::cout << "unSetMode ";
|
||||||
|
|
||||||
created = false;
|
created = false;
|
||||||
|
Volatile::unloadAll();
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1280,6 +1281,7 @@ namespace love {
|
|||||||
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
|
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
|
||||||
throw love::Exception("failed to create pipeline layout");
|
throw love::Exception("failed to create pipeline layout");
|
||||||
}
|
}
|
||||||
|
graphicsPipelineLayouts.push_back(pipelineLayout);
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
@@ -1485,12 +1487,18 @@ namespace love {
|
|||||||
}
|
}
|
||||||
graphicsPipelines.clear();
|
graphicsPipelines.clear();
|
||||||
currentGraphicsPipeline = VK_NULL_HANDLE;
|
currentGraphicsPipeline = VK_NULL_HANDLE;
|
||||||
// vkDestroyPipelineLayout(device, pipelineLayout, nullptr); FIXME
|
for (const auto pipelineLayout : graphicsPipelineLayouts) {
|
||||||
|
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||||
|
}
|
||||||
|
graphicsPipelineLayouts.clear();
|
||||||
vkDestroyRenderPass(device, renderPass, nullptr);
|
vkDestroyRenderPass(device, renderPass, nullptr);
|
||||||
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
|
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
|
||||||
vkDestroyImageView(device, swapChainImageViews[i], nullptr);
|
vkDestroyImageView(device, swapChainImageViews[i], nullptr);
|
||||||
}
|
}
|
||||||
vkDestroySwapchainKHR(device, swapChain, nullptr);
|
vkDestroySwapchainKHR(device, swapChain, nullptr);
|
||||||
|
for (auto p : uniformBufferMap) {
|
||||||
|
delete p.second;
|
||||||
|
}
|
||||||
uniformBufferMap.clear();
|
uniformBufferMap.clear();
|
||||||
descriptorSetsMap.clear();
|
descriptorSetsMap.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ namespace love {
|
|||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
VkPipeline currentGraphicsPipeline = 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<std::pair<GraphicsPipelineConfiguration, VkPipeline>> graphicsPipelines; // FIXME improve performance by using a hash map
|
||||||
|
std::vector<VkPipelineLayout> graphicsPipelineLayouts;
|
||||||
std::vector<VkFramebuffer> swapChainFramBuffers;
|
std::vector<VkFramebuffer> swapChainFramBuffers;
|
||||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||||
std::vector<VkCommandBuffer> commandBuffers;
|
std::vector<VkCommandBuffer> commandBuffers;
|
||||||
|
|||||||
@@ -185,7 +185,13 @@ namespace love {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShaderStage::ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey)
|
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);
|
auto code = compileShaderWithGlslang(glsl, stage);
|
||||||
|
|
||||||
VkShaderModuleCreateInfo createInfo{};
|
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() {
|
ShaderStage::~ShaderStage() {
|
||||||
// vkDestroyShaderModule(device, shaderModule, nullptr);
|
unloadVolatile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,15 @@
|
|||||||
namespace love {
|
namespace love {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
class ShaderStage final : public graphics::ShaderStage {
|
class ShaderStage final : public graphics::ShaderStage, public Volatile {
|
||||||
public:
|
public:
|
||||||
ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey);
|
ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey);
|
||||||
virtual ~ShaderStage();
|
virtual ~ShaderStage();
|
||||||
|
|
||||||
|
virtual bool loadVolatile() override;
|
||||||
|
|
||||||
|
virtual void unloadVolatile() override;
|
||||||
|
|
||||||
VkShaderModule getShaderModule() const {
|
VkShaderModule getShaderModule() const {
|
||||||
return shaderModule;
|
return shaderModule;
|
||||||
}
|
}
|
||||||
@@ -22,9 +26,9 @@ namespace love {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkShaderModule shaderModule;
|
VkShaderModule shaderModule = VK_NULL_HANDLE;
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
|
love::graphics::Graphics* gfx;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ namespace love {
|
|||||||
|
|
||||||
StreamBuffer::StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size)
|
StreamBuffer::StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size)
|
||||||
: love::graphics::StreamBuffer(mode, size), allocator(allocator) {
|
: love::graphics::StreamBuffer(mode, size), allocator(allocator) {
|
||||||
|
loadVolatile();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamBuffer::loadVolatile() {
|
||||||
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();
|
||||||
@@ -31,10 +35,20 @@ namespace love {
|
|||||||
vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, &allocInfo);
|
vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, &allocInfo);
|
||||||
|
|
||||||
usedGPUMemory = 0;
|
usedGPUMemory = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamBuffer::unloadVolatile() {
|
||||||
|
if (buffer == VK_NULL_HANDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vmaDestroyBuffer(allocator, buffer, allocation);
|
||||||
|
buffer = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamBuffer::~StreamBuffer() {
|
StreamBuffer::~StreamBuffer() {
|
||||||
// vmaDestroyBuffer(allocator, buffer, allocation);
|
unloadVolatile();
|
||||||
}
|
}
|
||||||
|
|
||||||
love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t minsize) {
|
love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t minsize) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H
|
#ifndef LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H
|
||||||
#define LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H
|
#define LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H
|
||||||
|
|
||||||
|
#include "graphics/Volatile.h"
|
||||||
#include "modules/graphics/StreamBuffer.h"
|
#include "modules/graphics/StreamBuffer.h"
|
||||||
#include "vulkan/vulkan.h"
|
#include "vulkan/vulkan.h"
|
||||||
|
|
||||||
@@ -9,11 +10,15 @@
|
|||||||
namespace love {
|
namespace love {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
class StreamBuffer : public love::graphics::StreamBuffer {
|
class StreamBuffer : public love::graphics::StreamBuffer, public graphics::Volatile {
|
||||||
public:
|
public:
|
||||||
StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size);
|
StreamBuffer(VmaAllocator allocator, BufferUsage mode, size_t size);
|
||||||
virtual ~StreamBuffer();
|
virtual ~StreamBuffer();
|
||||||
|
|
||||||
|
virtual bool loadVolatile() override;
|
||||||
|
|
||||||
|
virtual void unloadVolatile() override;
|
||||||
|
|
||||||
MapInfo map(size_t minsize) override;
|
MapInfo map(size_t minsize) override;
|
||||||
size_t unmap(size_t usedSize) override;
|
size_t unmap(size_t usedSize) override;
|
||||||
void markUsed(size_t usedSize) override;
|
void markUsed(size_t usedSize) override;
|
||||||
@@ -28,7 +33,7 @@ namespace love {
|
|||||||
VmaAllocator allocator;
|
VmaAllocator allocator;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
VmaAllocationInfo allocInfo;
|
VmaAllocationInfo allocInfo;
|
||||||
VkBuffer buffer;
|
VkBuffer buffer = VK_NULL_HANDLE;
|
||||||
size_t usedGPUMemory;
|
size_t usedGPUMemory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ namespace love {
|
|||||||
namespace graphics {
|
namespace graphics {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
Texture::Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data)
|
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();
|
allocator = vgfx->getVmaAllocator();
|
||||||
device = vgfx->getDevice();
|
device = vgfx->getDevice();
|
||||||
|
|
||||||
@@ -59,10 +63,19 @@ namespace love {
|
|||||||
createTextureSampler();
|
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() {
|
Texture::~Texture() {
|
||||||
// vkDestroySampler(device, textureSampler, nullptr);
|
unloadVolatile();
|
||||||
// vkDestroyImageView(device, textureImageView, nullptr);
|
|
||||||
// vmaDestroyImage(allocator, textureImage, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::createTextureImageView() {
|
void Texture::createTextureImageView() {
|
||||||
|
|||||||
@@ -12,11 +12,14 @@
|
|||||||
namespace love {
|
namespace love {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
class Texture : public graphics::Texture {
|
class Texture : public graphics::Texture, public Volatile {
|
||||||
public:
|
public:
|
||||||
Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data);
|
Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data);
|
||||||
~Texture();
|
~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 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 "; };
|
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;
|
graphics::Graphics* gfx;
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
VmaAllocator allocator;
|
VmaAllocator allocator;
|
||||||
VkImage textureImage;
|
VkImage textureImage = VK_NULL_HANDLE;
|
||||||
VmaAllocation textureImageAllocation;
|
VmaAllocation textureImageAllocation;
|
||||||
VkImageView textureImageView;
|
VkImageView textureImageView;
|
||||||
VkSampler textureSampler;
|
VkSampler textureSampler;
|
||||||
|
const Slices* data;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user