From e06288320d1ce3afb6f3fb26d03ae3f8da9b74ab Mon Sep 17 00:00:00 2001 From: Piotr Krygier Date: Tue, 4 Apr 2023 14:56:31 +0200 Subject: [PATCH] Enable multiple buffers Enables creation of multiple mesh objects in a single buffer. This is still WIP. --- graphics/src/mesh_controller.cpp | 14 +- graphics/src/mesh_controller.hpp | 16 +- graphics/src/rse_graphics.cpp | 22 +-- graphics/src/vulkan_buffers.cpp | 242 ++++++++++++++++++------------- graphics/src/vulkan_buffers.hpp | 6 + graphics/src/vulkan_commons.hpp | 11 ++ 6 files changed, 188 insertions(+), 123 deletions(-) diff --git a/graphics/src/mesh_controller.cpp b/graphics/src/mesh_controller.cpp index ecbc4141..f05948c1 100644 --- a/graphics/src/mesh_controller.cpp +++ b/graphics/src/mesh_controller.cpp @@ -4,6 +4,8 @@ #include #include +#include "vulkan_buffers.hpp" + namespace rse::graphics::mesh { @@ -12,7 +14,9 @@ std::queue free_ids; std::map> instance_free_ids; -uint16_t create_mesh(std::vector vertices, std::vector indices) +uint16_t create_mesh(rse::graphics::vulkanbase::VulkanState& vulkan_state, + std::vector vertices, + std::vector indices) { static uint16_t last_id = 0U; uint16_t assignable_id = 0U; @@ -30,10 +34,14 @@ uint16_t create_mesh(std::vector vertices, st indices )); + rse::graphics::vulkanbase::update_mesh_buffers(vulkan_state, vertices, indices); + return assignable_id; } -void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data) +void create_mesh_instance(rse::graphics::vulkanbase::VulkanState& vulkan_state, + uint16_t mesh_id, + InstanceData instance_data) { uint16_t instance_id = 0U; auto& instances = g_meshes[mesh_id].instances; @@ -50,6 +58,8 @@ void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data) instance_id, instance_data ); + + rse::graphics::vulkanbase::update_mesh_instances(vulkan_state, instance_data); } //TODO: Replace with something else. It will take to much time to do this each time we draw frame for all the objects diff --git a/graphics/src/mesh_controller.hpp b/graphics/src/mesh_controller.hpp index e21bd0c4..847b29ef 100644 --- a/graphics/src/mesh_controller.hpp +++ b/graphics/src/mesh_controller.hpp @@ -17,8 +17,6 @@ #include #include -#include - #include "vulkan_commons.hpp" namespace rse::graphics::mesh @@ -27,12 +25,6 @@ namespace rse::graphics::mesh /* Forward declarations */ struct MeshInstance; -struct InstanceData { - glm::vec3 pos; - glm::vec3 rot; - float scale; -}; - struct MeshInstance { uint32_t instance_id; @@ -55,7 +47,9 @@ struct Mesh * @param indices indices for mesh * @return uint16_t Mesh identifier. Can be useful for getting vertices, indices and instances */ -uint16_t create_mesh(std::vector vertices, std::vector indices); +uint16_t create_mesh(rse::graphics::vulkanbase::VulkanState& vulkan_state, + std::vector vertices, + std::vector indices); /** * @brief Create a instance for the selected mesh. Instance can have its own location, rotation and scale @@ -63,7 +57,9 @@ uint16_t create_mesh(std::vector vertices, st * @param mesh_id Mesh id * @param instance_data Transformation info */ -void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data); +void create_mesh_instance(rse::graphics::vulkanbase::VulkanState& vulkan_state, + uint16_t mesh_id, + InstanceData instance_data); std::vector get_mesh_vertices(uint16_t mesh_id); std::vector get_mesh_indices(uint16_t mesh_id); diff --git a/graphics/src/rse_graphics.cpp b/graphics/src/rse_graphics.cpp index 1943bc5c..4b25e605 100644 --- a/graphics/src/rse_graphics.cpp +++ b/graphics/src/rse_graphics.cpp @@ -34,6 +34,11 @@ uint8_t RseGraphics::graphics_run(void) window::windowInit(); + + + if (0 != vulkanbase::initVulkan(vulkan_state)) + return -1; + // FIXME: Temporary array of vertices, for testing purposes const std::vector vertices = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}}, {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 1.0f}}, @@ -43,21 +48,18 @@ uint8_t RseGraphics::graphics_run(void) // FIXME: Temporary array of vertices, for testing purposes std::vector indices = {0, 1, 2, 2, 3, 0}; - uint16_t mesh_id = rse::graphics::mesh::create_mesh(vertices, indices); - rse::graphics::mesh::create_mesh_instance(mesh_id, rse::graphics::mesh::InstanceData( + uint16_t mesh_id = rse::graphics::mesh::create_mesh(vulkan_state, vertices, indices); + rse::graphics::mesh::create_mesh_instance(vulkan_state, mesh_id, rse::graphics::mesh::InstanceData( glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, glm::radians(45.0f)), 1.0f )); - rse::graphics::mesh::create_mesh_instance(mesh_id, rse::graphics::mesh::InstanceData( - glm::vec3(-1.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 0.0f), - 1.0f - )); - - if (0 != vulkanbase::initVulkan(vulkan_state)) - return -1; + // rse::graphics::mesh::create_mesh_instance(vulkan_state, mesh_id, rse::graphics::mesh::InstanceData( + // glm::vec3(-1.0f, 0.0f, 0.0f), + // glm::vec3(0.0f, 0.0f, 0.0f), + // 1.0f + // )); window::windowLoop(vulkan_state); diff --git a/graphics/src/vulkan_buffers.cpp b/graphics/src/vulkan_buffers.cpp index a9988994..5b2c34f7 100644 --- a/graphics/src/vulkan_buffers.cpp +++ b/graphics/src/vulkan_buffers.cpp @@ -14,6 +14,7 @@ namespace rse::graphics::vulkanbase { +#define MAX_VERTEX_BUFFER_SIZE 33554432 /* 32 MB*/ using namespace locale::vulkan; @@ -27,9 +28,9 @@ using namespace locale::vulkan; // std::vector indices = {0, 1, 2, 2, 3, 0}; /* GPU visible buffer */ -Buffer gVertexBuffer = {}; -Buffer gIndexBuffer = {}; -Buffer gInstancesBuffer = {}; +std::vector gVertexBuffers = {}; +std::vector gIndexBuffers = {}; +std::vector gInstanceBuffers = {}; /* CPU visible buffer. TODO: Do we need this global? */ VkCommandPool gCommandPool = VK_NULL_HANDLE; @@ -37,8 +38,7 @@ VkCommandPool gCommandPool = VK_NULL_HANDLE; static uint8_t createBuffer(VulkanState& vulkan_state, const VkDeviceSize size, VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage, const VmaAllocationCreateFlags allocationFlags, Buffer& buffer); -static uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size); - +static uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset = 0); static uint8_t createCommandPools(VulkanState& vulkan_state); static uint8_t createVertexBuffer(VulkanState& vulkan_state); @@ -99,7 +99,7 @@ uint8_t createBuffer(VulkanState& vulkan_state, const VkDeviceSize size, VkBuffe * @param size Size of buffer to copy * @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: */ -uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size) +uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset) { /* Vulkan buffers can only be copied using command buffers */ VkBufferCopy copyRegion; @@ -120,7 +120,7 @@ uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDevi beginInfo.pInheritanceInfo = nullptr; copyRegion.srcOffset = 0; - copyRegion.dstOffset = 0; + copyRegion.dstOffset = dest_offset; copyRegion.size = size; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -134,15 +134,19 @@ uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDevi submitInfo.pSignalSemaphores = nullptr; // FIXME: At result checks - vkAllocateCommandBuffers(vulkan_state.device, &allocInfo, ©CommandBuffer); - vkBeginCommandBuffer(copyCommandBuffer, &beginInfo); + VkResult status; + status = vkAllocateCommandBuffers(vulkan_state.device, &allocInfo, ©CommandBuffer); + status = vkBeginCommandBuffer(copyCommandBuffer, &beginInfo); vkCmdCopyBuffer(copyCommandBuffer, src, dst, 1, ©Region); - vkEndCommandBuffer(copyCommandBuffer); - vkQueueSubmit(vulkan_state.graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); + status = vkEndCommandBuffer(copyCommandBuffer); + status = vkQueueSubmit(vulkan_state.graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); /* TODO: Use fences to wait instead of idle */ - vkQueueWaitIdle(vulkan_state.graphicsQueue); + status = vkQueueWaitIdle(vulkan_state.graphicsQueue); vkFreeCommandBuffers(vulkan_state.device, gCommandPool, 1, ©CommandBuffer); + if (status != VK_SUCCESS) { + return VULKAN_ERROR_NO_ERROR; + } return VULKAN_ERROR_NO_ERROR; } @@ -181,41 +185,21 @@ uint8_t createCommandPools(VulkanState& vulkan_state) */ uint8_t createVertexBuffer(VulkanState& vulkan_state) { - void* mappedData; VkDeviceSize bufferSize; - Buffer staging_buffer; + Buffer vertex_buffer; - auto vertices = rse::graphics::mesh::get_mesh_vertices(0); - - bufferSize = sizeof(vertices[0]) * vertices.size(); - - /* Creating staging buffer*/ - if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST, - VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, staging_buffer)) { - LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; - return VULKAN_ERROR_BUFFER_CREATION_FAILED; - } + bufferSize = MAX_VERTEX_BUFFER_SIZE; /* Create Vertex Buffer*/ if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */ - gVertexBuffer)) { + vertex_buffer)) { LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; return VULKAN_ERROR_BUFFER_CREATION_FAILED; } - /* Fill staging buffer */ - if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) { - LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED]; - return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED; - } - memcpy(mappedData, vertices.data(), sizeof(Vertex) * vertices.size()); - vmaUnmapMemory(vulkan_state.allocator, staging_buffer.allocation); - - copyBuffer(vulkan_state, staging_buffer.buffer, gVertexBuffer.buffer, bufferSize); - - vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); - + vertex_buffer.allocated_size = 0; + gVertexBuffers.push_back(std::move(vertex_buffer)); return VULKAN_ERROR_NO_ERROR; } @@ -227,79 +211,43 @@ uint8_t createVertexBuffer(VulkanState& vulkan_state) */ uint8_t createIndexBuffer(VulkanState& vulkan_state) { - void* mappedData; VkDeviceSize bufferSize; - Buffer staging_buffer; + Buffer index_buffer; - auto indices = rse::graphics::mesh::get_mesh_indices(0); + bufferSize = MAX_VERTEX_BUFFER_SIZE; - bufferSize = sizeof(indices[0]) * indices.size(); - - /* Creating staging buffer*/ - if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST, - VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, staging_buffer)) { - LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; - return VULKAN_ERROR_BUFFER_CREATION_FAILED; - } - - /* Create Vertex Buffer*/ + /* Create Index Buffer*/ if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */ - gIndexBuffer)) { + index_buffer)) { LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; return VULKAN_ERROR_BUFFER_CREATION_FAILED; } - /* Fill staging buffer */ - if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) { - LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED]; - return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED; - } - memcpy(mappedData, indices.data(), static_cast(bufferSize)); - vmaUnmapMemory(vulkan_state.allocator, staging_buffer.allocation); - - copyBuffer(vulkan_state, staging_buffer.buffer, gIndexBuffer.buffer, bufferSize); - vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); - + index_buffer.allocated_size = 0; + gIndexBuffers.push_back(std::move(index_buffer)); return VULKAN_ERROR_NO_ERROR; } -uint8_t createInstancesBuffer(VulkanState& vulkan_state) +uint8_t createInstanceBuffer(VulkanState& vulkan_state) { - void* mappedData; VkDeviceSize bufferSize; - Buffer staging_buffer; + Buffer instance_buffer; - auto instances = rse::graphics::mesh::get_instance_data_for_mesh(0); - bufferSize = sizeof(instances[0]) * instances.size(); + bufferSize = MAX_VERTEX_BUFFER_SIZE; - /* Creating staging buffer*/ - if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST, - VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, staging_buffer)) { - LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; - return VULKAN_ERROR_BUFFER_CREATION_FAILED; - } - - /* Create Vertex Buffer*/ + /* Create Instance Buffer*/ if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */ - gInstancesBuffer)) { + instance_buffer)) { LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; return VULKAN_ERROR_BUFFER_CREATION_FAILED; } - /* Fill staging buffer */ - if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) { - LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED]; - return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED; - } - memcpy(mappedData, instances.data(), static_cast(bufferSize)); - vmaUnmapMemory(vulkan_state.allocator, staging_buffer.allocation); - - copyBuffer(vulkan_state, staging_buffer.buffer, gInstancesBuffer.buffer, bufferSize); - vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); + instance_buffer.allocated_size = 0; + gInstanceBuffers.push_back(std::move(instance_buffer)); return VULKAN_ERROR_NO_ERROR; } @@ -342,7 +290,9 @@ uint8_t allocateCommandBuffers(VulkanState& vulkan_state) allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; /* TODO: When needed, add secondary command buffer */ allocateInfo.commandBufferCount = SWAP_BUFFER_COUNT; - if (VK_SUCCESS != vkAllocateCommandBuffers(vulkan_state.device, &allocateInfo, vulkan_state.pCommandBuffers.data())) { + if (VK_SUCCESS != vkAllocateCommandBuffers(vulkan_state.device, + &allocateInfo, + vulkan_state.pCommandBuffers.data())) { LOGF << vulkanErrorMesssages[VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED]; return VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED; } @@ -360,12 +310,95 @@ void updateUniformBuffer(VulkanState& vulkan_state) // ubo.model = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f, 0.0f, 0.0f)) * glm::rotate(glm::mat4(1.0f), glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) * glm::scale(glm::mat4(1.0f), glm::vec3(2, 1, 1)); ubo.model = glm::mat4(1.0f); ubo.view = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - ubo.proj = - glm::perspective(glm::radians(45.0f), vulkan_state.swapchainExtent.width / (float)vulkan_state.swapchainExtent.height, 0.1f, 20.0f); + ubo.proj = glm::perspective(glm::radians(45.0f), + vulkan_state.swapchainExtent.width / (float)vulkan_state.swapchainExtent.height, + 0.1f, + 20.0f); ubo.proj[1][1] *= -1; /* GLM was developed for OpenGL, where Y coordinate of the clip is inverted */ memcpy(vulkan_state.uniformBuffers[vulkan_state.currentFrame].allocationInfo.pMappedData, &ubo, sizeof(ubo)); } +uint8_t update_mesh_buffers(VulkanState& vulkan_state, + const std::vector& vertices, + const std::vector& indices) +{ + // void* mapped_data; + Buffer staging_buffer; + auto vertices_size = sizeof(vertices[0]) * vertices.size(); + auto indices_size = sizeof(indices[0]) * indices.size(); + + auto last_vertex_buffer = &gVertexBuffers[gVertexBuffers.size() - 1]; + auto last_index_buffer = &gIndexBuffers[gIndexBuffers.size() - 1]; + + /* Creating staging buffer*/ + if (VK_SUCCESS != createBuffer(vulkan_state, + MAX_VERTEX_BUFFER_SIZE, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VMA_MEMORY_USAGE_AUTO_PREFER_HOST, + VMA_ALLOCATION_CREATE_MAPPED_BIT + | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + staging_buffer)) { + LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; + return VULKAN_ERROR_BUFFER_CREATION_FAILED; + } + + /* Fill staging buffer with vertex data */ + memset(staging_buffer.allocationInfo.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE); + memcpy(staging_buffer.allocationInfo.pMappedData, vertices.data(), vertices_size); + copyBuffer(vulkan_state, + staging_buffer.buffer, + last_vertex_buffer->buffer, + vertices_size, + last_vertex_buffer->allocated_size); + + /* Fill staging buffer with index data */ + memset(staging_buffer.allocationInfo.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE); + memcpy(staging_buffer.allocationInfo.pMappedData, indices.data(), indices_size); + copyBuffer(vulkan_state, + staging_buffer.buffer, + last_index_buffer->buffer, + indices_size, + last_index_buffer->allocated_size); + + vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); + + return VULKAN_ERROR_NO_ERROR; +} + +uint8_t update_mesh_instances(VulkanState& vulkan_state, + rse::graphics::mesh::InstanceData& instance_data) +{ + Buffer staging_buffer; + + auto last_instance_buffer = &gInstanceBuffers[gInstanceBuffers.size() - 1]; + auto instance_size = sizeof(instance_data); + + /* Creating staging buffer*/ + if (VK_SUCCESS != createBuffer(vulkan_state, + MAX_VERTEX_BUFFER_SIZE, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VMA_MEMORY_USAGE_AUTO_PREFER_HOST, + VMA_ALLOCATION_CREATE_MAPPED_BIT + | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + staging_buffer)) { + LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED]; + return VULKAN_ERROR_BUFFER_CREATION_FAILED; + } + + memcpy(staging_buffer.allocationInfo.pMappedData, &instance_data, instance_size); + copyBuffer(vulkan_state, + staging_buffer.buffer, + last_instance_buffer->buffer, + instance_size, + last_instance_buffer->allocated_size); + + vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); + + last_instance_buffer->allocated_size += instance_size; + + return VULKAN_ERROR_NO_ERROR; +} + /** * @brief Records commands for provided command buffer * @@ -382,8 +415,6 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex) VkRenderPassBeginInfo renderPassInfo{}; VkViewport viewport{}; VkRect2D scissor{}; - VkBuffer vertexBuffers[] = {gVertexBuffer.buffer}; - VkBuffer instanceBuffers[] = {gInstancesBuffer.buffer}; VkDeviceSize offsets[] = {0}; auto indices = rse::graphics::mesh::get_mesh_indices(0); @@ -421,13 +452,20 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex) scissor.extent = vulkan_state.swapchainExtent; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); - vkCmdBindVertexBuffers(commandBuffer, 1, 1, instanceBuffers, offsets); - vkCmdBindIndexBuffer(commandBuffer, gIndexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_state.pipelineLayout, 0, 1, - &vulkan_state.descriptorSets[vulkan_state.currentFrame], 0, nullptr); + for (size_t i = 0; i < gVertexBuffers.size(); ++i) { + VkBuffer vertexBuffers[] = {gVertexBuffers[i].buffer}; + VkBuffer indexBuffer = {gIndexBuffers[i].buffer}; + VkBuffer instanceBuffers[] = {gInstanceBuffers[i].buffer}; - vkCmdDrawIndexed(commandBuffer, static_cast(indices.size()), instances.size(), 0, 0, 0); + /* TODO: Figure out the offset */ + vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); + vkCmdBindVertexBuffers(commandBuffer, 1, 1, instanceBuffers, offsets); + vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_state.pipelineLayout, 0, 1, + &vulkan_state.descriptorSets[vulkan_state.currentFrame], 0, nullptr); + + vkCmdDrawIndexed(commandBuffer, static_cast(indices.size()), instances.size(), 0, 0, 0); + } vkCmdEndRenderPass(commandBuffer); @@ -446,7 +484,7 @@ uint8_t create_buffers(VulkanState& vulkan_state) STATUS_CHECK(createCommandPools(vulkan_state)); STATUS_CHECK(createVertexBuffer(vulkan_state)); STATUS_CHECK(createIndexBuffer(vulkan_state)); - STATUS_CHECK(createInstancesBuffer(vulkan_state)); + STATUS_CHECK(createInstanceBuffer(vulkan_state)); STATUS_CHECK(createUniformBuffers(vulkan_state)); STATUS_CHECK(allocateCommandBuffers(vulkan_state)); @@ -464,9 +502,11 @@ void destroy_buffers(VulkanState& vulkan_state) vmaDestroyBuffer(vulkan_state.allocator, vulkan_state.uniformBuffers[i].buffer, vulkan_state.uniformBuffers[i].allocation); } - vmaDestroyBuffer(vulkan_state.allocator, gVertexBuffer.buffer, gVertexBuffer.allocation); - vmaDestroyBuffer(vulkan_state.allocator, gIndexBuffer.buffer, gIndexBuffer.allocation); - vmaDestroyBuffer(vulkan_state.allocator, gInstancesBuffer.buffer, gInstancesBuffer.allocation); + for (size_t i = 0; i < gVertexBuffers.size(); ++i) { + vmaDestroyBuffer(vulkan_state.allocator, gVertexBuffers[i].buffer, gVertexBuffers[i].allocation); + vmaDestroyBuffer(vulkan_state.allocator, gIndexBuffers[i].buffer, gIndexBuffers[i].allocation); + vmaDestroyBuffer(vulkan_state.allocator, gInstanceBuffers[i].buffer, gInstanceBuffers[i].allocation); + } vkDestroyCommandPool(vulkan_state.device, gCommandPool, nullptr); } diff --git a/graphics/src/vulkan_buffers.hpp b/graphics/src/vulkan_buffers.hpp index 033a7177..61b13c15 100644 --- a/graphics/src/vulkan_buffers.hpp +++ b/graphics/src/vulkan_buffers.hpp @@ -27,6 +27,12 @@ uint8_t create_buffers(VulkanState& vulkan_state); */ void updateUniformBuffer(VulkanState& vulkan_state); +uint8_t update_mesh_buffers(VulkanState& vulkan_state, + const std::vector& vertices, + const std::vector& indices); + +uint8_t update_mesh_instances(VulkanState& vulkan_state, + rse::graphics::mesh::InstanceData& instance_data); /** * @brief Record commands for given image index * diff --git a/graphics/src/vulkan_commons.hpp b/graphics/src/vulkan_commons.hpp index 7ee49e51..b728d2de 100644 --- a/graphics/src/vulkan_commons.hpp +++ b/graphics/src/vulkan_commons.hpp @@ -65,6 +65,7 @@ struct Vertex */ struct Buffer { + uint32_t allocated_size; VkBuffer buffer; VmaAllocation allocation; VmaAllocationInfo allocationInfo; @@ -101,4 +102,14 @@ struct VulkanState } // namespace rse::graphics::vulkanbase +namespace rse::graphics::mesh +{ +struct InstanceData { + glm::vec3 pos; + glm::vec3 rot; + float scale; +}; + +} // namespace rse::graphics::mesh + #endif