From aed6595ee63cf5d2900aaa25e9e203bd4689024b Mon Sep 17 00:00:00 2001 From: niki Date: Thu, 6 Jan 2022 14:55:07 +0100 Subject: [PATCH] first draft of vulkan buffer implementation --- CMakeLists.txt | 2 + src/modules/graphics/vulkan/Buffer.cpp | 78 ++++++++++++++++++++++++ src/modules/graphics/vulkan/Buffer.h | 36 +++++++++++ src/modules/graphics/vulkan/Graphics.cpp | 5 ++ src/modules/graphics/vulkan/Graphics.h | 6 +- 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/modules/graphics/vulkan/Buffer.cpp create mode 100644 src/modules/graphics/vulkan/Buffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index aacdf76c2..b4fafef75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -578,6 +578,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_VULKAN src/modules/graphics/vulkan/Shader.cpp src/modules/graphics/vulkan/ShaderStage.h src/modules/graphics/vulkan/ShaderStage.cpp + src/modules/graphics/vulkan/Buffer.h + src/modules/graphics/vulkan/Buffer.cpp ) set(LOVE_SRC_MODULE_GRAPHICS diff --git a/src/modules/graphics/vulkan/Buffer.cpp b/src/modules/graphics/vulkan/Buffer.cpp new file mode 100644 index 000000000..1f98dea01 --- /dev/null +++ b/src/modules/graphics/vulkan/Buffer.cpp @@ -0,0 +1,78 @@ +#include "Buffer.h" +#include "Graphics.h" + +namespace love { + namespace graphics { + namespace vulkan { + static uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFtiler, VkMemoryPropertyFlags properties) { + VkPhysicalDeviceMemoryProperties memProperties; + vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); + + for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { + if ((typeFtiler & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { + return i; + } + } + + throw love::Exception("failed to find suitable memory type"); + } + + Buffer::Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) + : love::graphics::Buffer(gfx, settings, format, size, arrayLength) { + auto vgfx = (Graphics*)gfx; + device = vgfx->getDevice(); + auto physicalDevice = vgfx->getPhysicalDevice(); + + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = getSize(); + bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; // todo: only vertex buffers are allowed for now + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) { + throw love::Exception("failed to create buffer"); + } + + VkMemoryRequirements memRequirements; + vkGetBufferMemoryRequirements(device, buffer, &memRequirements); + + VkMemoryAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocInfo.allocationSize = memRequirements.size; + allocInfo.memoryTypeIndex = findMemoryType(physicalDevice, memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) { + throw love::Exception("failed to allocate vertex buffer memory"); + } + + vkBindBufferMemory(device, buffer, bufferMemory, 0); + + vkMapMemory(device, bufferMemory, 0, getSize(), 0, &mappedMemory); + memcpy(mappedMemory, data, size); + vkUnmapMemory(device, bufferMemory); + } + + Buffer::~Buffer() { + vkDestroyBuffer(device, buffer, nullptr); + vkFreeMemory(device, bufferMemory, nullptr); + } + + void* Buffer::map(MapType map, size_t offset, size_t size) { + vkMapMemory(device, bufferMemory, offset, size, 0, &mappedMemory); + return mappedMemory; + } + + void Buffer::fill(size_t offset, size_t size, const void *data) { + memcpy(mappedMemory, data, size); + } + + void Buffer::unmap(size_t usedoffset, size_t usedsize) { + vkUnmapMemory(device, bufferMemory); + } + + void Buffer::copyTo(love::graphics::Buffer* dest, size_t sourceoffset, size_t destoffset, size_t size) { + throw love::Exception("not implemented yet"); + } + } + } +} \ No newline at end of file diff --git a/src/modules/graphics/vulkan/Buffer.h b/src/modules/graphics/vulkan/Buffer.h new file mode 100644 index 000000000..d80e19890 --- /dev/null +++ b/src/modules/graphics/vulkan/Buffer.h @@ -0,0 +1,36 @@ +#include "graphics/Buffer.h" +#include + + +namespace love { + namespace graphics { + namespace vulkan { + class Buffer : public love::graphics::Buffer { + public: + Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength); + virtual ~Buffer(); + + void* map(MapType map, size_t offset, size_t size) override; + void unmap(size_t usedoffset, size_t usedsize) override; + void fill(size_t offset, size_t size, const void* data) override; + void copyTo(love::graphics::Buffer* dest, size_t sourceoffset, size_t destoffset, size_t size) override; + ptrdiff_t getHandle() const override { + return (ptrdiff_t) buffer; // todo ? + } + ptrdiff_t getTexelBufferHandle() const override { + return (ptrdiff_t) nullptr; // todo ? + } + + private: + VkDevice device; + VkPhysicalDevice physicalDevice; + + // todo use a staging buffer for improved performance + VkBuffer buffer; + VkDeviceMemory bufferMemory; + + void* mappedMemory; + }; + } + } +} diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index f7ed76d97..454da553d 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -1,4 +1,5 @@ #include "Graphics.h" +#include "Buffer.h" #include "SDL_vulkan.h" #include "window/Window.h" #include "common/Exception.h" @@ -77,6 +78,10 @@ namespace love { cleanup(); } + love::graphics::Buffer* Graphics::newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) { + return new Buffer(this, settings, format, data, size, arraylength); + } + void Graphics::present(void* screenshotCallbackdata) { vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 7d8667ec0..2cc12003f 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -27,9 +27,13 @@ namespace love { return device; } + const VkPhysicalDevice getPhysicalDevice() const { + return physicalDevice; + } + // implementation for virtual functions Texture* newTexture(const Texture::Settings& settings, const Texture::Slices* data = nullptr) override { return nullptr; } - Buffer* newBuffer(const Buffer::Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) override { return nullptr; } + love::graphics::Buffer* newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) override; void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override {} void clear(const std::vector& colors, OptionalInt stencil, OptionalDouble depth) override {} void discard(const std::vector& colorbuffers, bool depthstencil) override {}