diff --git a/src/vulkan/application.cpp b/src/vulkan/application.cpp index 7086384..1564711 100644 --- a/src/vulkan/application.cpp +++ b/src/vulkan/application.cpp @@ -1,5 +1,4 @@ #include "application.hpp" -#include "vertex.hpp" #include "swapchain.hpp" #include "pipeline.hpp" #include "instance.hpp" @@ -10,8 +9,13 @@ Application::Application() { instance = new Instance; swapchain = new Swapchain(instance); pipeline = new Pipeline(instance, swapchain->renderPass); - buffer = new Buffer(instance); + stagingBuffer = Buffer::createStagingBuffer(instance); + vertexBuffer = new Buffer(instance, stagingBuffer->size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); commandPool = new CommandPool(instance); + stagingBuffer->copyTo(vertexBuffer, commandPool); + createSyncObjects(); mainLoop(); @@ -129,7 +133,7 @@ void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t im scissor.extent = swapchain->extent; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - VkBuffer buffers[] = {buffer->vertexHandle}; + VkBuffer buffers[] = {vertexBuffer->handle}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets); @@ -147,7 +151,8 @@ Application::~Application() { vkDestroyFence(instance->device, inFlightFences[i], nullptr); } delete commandPool; - delete buffer; + delete stagingBuffer; + delete vertexBuffer; delete pipeline; delete instance; } diff --git a/src/vulkan/application.hpp b/src/vulkan/application.hpp index a7b0370..1168a2d 100644 --- a/src/vulkan/application.hpp +++ b/src/vulkan/application.hpp @@ -45,7 +45,8 @@ private: Instance* instance = nullptr; Swapchain* swapchain = nullptr; Pipeline* pipeline = nullptr; - Buffer* buffer = nullptr; + Buffer* stagingBuffer = nullptr; + Buffer* vertexBuffer = nullptr; CommandPool* commandPool = nullptr; void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); diff --git a/src/vulkan/buffer.cpp b/src/vulkan/buffer.cpp index 6102a17..12a8023 100644 --- a/src/vulkan/buffer.cpp +++ b/src/vulkan/buffer.cpp @@ -3,6 +3,7 @@ #include "buffer.hpp" #include "vertex.hpp" #include "instance.hpp" +#include "command_pool.hpp" const std::vector vertices = { {{0.0, -0.5}, {1, 0, 0}}, @@ -10,31 +11,26 @@ const std::vector vertices = { {{-0.5, 0.5}, {0, 0, 1}} }; -Buffer::Buffer(Instance* instance) : instance(instance) { +Buffer::Buffer(Instance* instance, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) : instance(instance), size(size){ VkBufferCreateInfo bufferInfo{}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = vertices.size() * sizeof(Vertex); - bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + bufferInfo.size = size; + bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - vkCreateBuffer(instance->device, &bufferInfo, nullptr, &vertexHandle); + vkCreateBuffer(instance->device, &bufferInfo, nullptr, &handle); VkMemoryRequirements memoryRequirements; - vkGetBufferMemoryRequirements(instance->device, vertexHandle, &memoryRequirements); + vkGetBufferMemoryRequirements(instance->device, handle, &memoryRequirements); VkMemoryAllocateInfo allocateInfo {}; allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocateInfo.allocationSize = memoryRequirements.size; - allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, properties); - vkAllocateMemory(instance->device, &allocateInfo, nullptr, &vertexMemory); + vkAllocateMemory(instance->device, &allocateInfo, nullptr, &memory); - vkBindBufferMemory(instance->device, vertexHandle, vertexMemory, 0); - - void* data; - vkMapMemory(instance->device, vertexMemory, 0, bufferInfo.size, 0, &data); - memcpy(data, vertices.data(), bufferInfo.size); - vkUnmapMemory(instance->device, vertexMemory); + vkBindBufferMemory(instance->device, handle, memory, 0); } uint32_t Buffer::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags) { @@ -51,6 +47,52 @@ uint32_t Buffer::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags prope } Buffer::~Buffer() { - vkFreeMemory(instance->device, vertexMemory, nullptr); - vkDestroyBuffer(instance->device, vertexHandle, nullptr); + vkFreeMemory(instance->device, memory, nullptr); + vkDestroyBuffer(instance->device, handle, nullptr); +} + +Buffer* Buffer::createStagingBuffer(Instance* instance) { + VkDeviceSize size = vertices.size() * sizeof(Vertex); + VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + VkMemoryPropertyFlags properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + auto stagingBuffer = new Buffer(instance, size, usage, properties); + + void* data; + vkMapMemory(instance->device, stagingBuffer->memory, 0, size, 0, &data); + memcpy(data, vertices.data(), size); + vkUnmapMemory(instance->device, stagingBuffer->memory); + + return stagingBuffer; +} + +void Buffer::copyTo(Buffer *dst, CommandPool* commandPool) { + VkCommandBufferAllocateInfo allocateInfo {}; + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocateInfo.commandPool = commandPool->handle; + allocateInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer; + vkAllocateCommandBuffers(instance->device, &allocateInfo, &commandBuffer); + + VkCommandBufferBeginInfo beginInfo {}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + vkBeginCommandBuffer(commandBuffer, &beginInfo); + VkBufferCopy copyRegion {}; + copyRegion.size = size; + vkCmdCopyBuffer(commandBuffer, handle, dst->handle, 1, ©Region); + vkEndCommandBuffer(commandBuffer); + + VkSubmitInfo submitInfo {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + vkQueueSubmit(instance->graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); + vkDeviceWaitIdle(instance->device); + + vkFreeCommandBuffers(instance->device, commandPool->handle, 1, &commandBuffer); } diff --git a/src/vulkan/buffer.hpp b/src/vulkan/buffer.hpp index 7deffb5..b176e8b 100644 --- a/src/vulkan/buffer.hpp +++ b/src/vulkan/buffer.hpp @@ -4,17 +4,22 @@ #include class Instance; - +class CommandPool; class Buffer { public: - explicit Buffer(Instance* instance); + explicit Buffer(Instance* instance, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties); ~Buffer(); - VkBuffer vertexHandle = VK_NULL_HANDLE; + VkBuffer handle = VK_NULL_HANDLE; + VkDeviceMemory memory = VK_NULL_HANDLE; + VkDeviceSize size; + + static Buffer* createStagingBuffer(Instance* instance); + + void copyTo(Buffer* dst, CommandPool* commandPool); private: Instance* instance = nullptr; - VkDeviceMemory vertexMemory = VK_NULL_HANDLE; uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags); }; \ No newline at end of file diff --git a/src/vulkan/command_pool.hpp b/src/vulkan/command_pool.hpp index e945ccc..f80c350 100644 --- a/src/vulkan/command_pool.hpp +++ b/src/vulkan/command_pool.hpp @@ -10,9 +10,9 @@ public: explicit CommandPool(Instance* instance); ~CommandPool(); std::vector buffers; + VkCommandPool handle = VK_NULL_HANDLE; private: Instance* instance; - VkCommandPool handle = VK_NULL_HANDLE; void createBuffers(); }; \ No newline at end of file