diff --git a/graphics/src/mesh_controller.c b/graphics/src/mesh_controller.c index 46a1cfb1..6772bdfb 100644 --- a/graphics/src/mesh_controller.c +++ b/graphics/src/mesh_controller.c @@ -7,16 +7,37 @@ #include #include -#define MAX_MESH_NUMBER 256 #define MAX_INSTANCE_NUMBER 256 -#define OBJECT_FREE 0 -#define OBJECT_TAKEN 1 +#define MESH_ID_FREE 0 +#define MESH_ID_TAKEN 1 -struct rse_mesh_t g_meshes[MAX_MESH_NUMBER] = {OBJECT_FREE}; -uint16_t g_free_ids[MAX_MESH_NUMBER] = {OBJECT_FREE}; +/** + * @brief Represents instance of a mesh and shows where it's located in instance buffer + * + */ +struct rse_internal_instance_data_t +{ + uint8_t instance_taken; + uint8_t instance_buffer_offset; +}; -uint8_t g_instance_free_ids[MAX_MESH_NUMBER][MAX_INSTANCE_NUMBER] = {OBJECT_FREE}; +/** + * @brief Mesh data, with unique id and dynamic arrays holding vertices and indices. + * One mesh can have multiple instances. + * + */ +struct rse_mesh_t +{ + uint8_t is_mesh_id_taken; + uint32_t unique_id; + uint8_t instance_count; + struct rse_buffer_data_t vertex_data; + struct rse_buffer_data_t index_data; + struct rse_internal_instance_data_t instance_data[MAX_INSTANCE_NUMBER]; +}; + +struct rse_mesh_t g_meshes[MAX_MESH_NUMBER] = {MESH_ID_FREE}; uint16_t create_mesh(struct rse_vertex_t* vertices, uint16_t* indices, @@ -26,7 +47,7 @@ uint16_t create_mesh(struct rse_vertex_t* vertices, size_t iter = 0U; for(iter = 0U; iter < MAX_MESH_NUMBER; ++iter) { - if(g_free_ids[iter] == OBJECT_FREE) { + if(g_meshes[iter].is_mesh_id_taken == MESH_ID_FREE) { break; } } @@ -37,14 +58,15 @@ uint16_t create_mesh(struct rse_vertex_t* vertices, return MAX_MESH_NUMBER; } - g_free_ids[iter] = OBJECT_TAKEN; + g_meshes[iter].is_mesh_id_taken = MESH_ID_TAKEN; g_meshes[iter].unique_id = iter; - g_meshes[iter].vertices_count = vertices_count; - g_meshes[iter].indices_count = indices_count; - g_meshes[iter].instances_count = 0; + g_meshes[iter].vertex_data.count = vertices_count; + g_meshes[iter].index_data.count = indices_count; + g_meshes[iter].instance_count = 0; + memset(g_meshes[iter].instance_data, 0, sizeof(struct rse_internal_instance_data_t) * MAX_INSTANCE_NUMBER); - update_mesh_buffers(vertices, indices, vertices_count, indices_count); + rse_add_vertices(iter, vertices, indices, &g_meshes[iter].vertex_data, &g_meshes[iter].index_data); return iter; } @@ -53,10 +75,9 @@ void create_mesh_instance(uint16_t mesh_id, struct rse_instance_data_t instance_data) { size_t iter = 0U; - uint8_t* free_instance_ids = g_instance_free_ids[mesh_id]; for(iter = 0U; iter < MAX_INSTANCE_NUMBER; ++iter) { - if(free_instance_ids[iter] == OBJECT_FREE) { + if(g_meshes[mesh_id].instance_data[iter].instance_taken == MESH_ID_FREE) { break; } } @@ -67,26 +88,36 @@ void create_mesh_instance(uint16_t mesh_id, return; } - free_instance_ids[iter] = OBJECT_TAKEN; + g_meshes[mesh_id].instance_data[iter].instance_taken = MESH_ID_TAKEN; - if(iter >= g_meshes[mesh_id].instances_count) { - g_meshes[mesh_id].instances_count++; + if(iter >= g_meshes[mesh_id].instance_count) { + g_meshes[mesh_id].instance_count++; } - update_mesh_instances(&instance_data); + update_mesh_instances(mesh_id, &instance_data); } size_t get_vertices_count(uint16_t mesh_id) { - return g_meshes[mesh_id].vertices_count; -} - -size_t get_instances_count(uint16_t mesh_id) -{ - return g_meshes[mesh_id].instances_count; + return g_meshes[mesh_id].vertex_data.count; } size_t get_indices_count(uint16_t mesh_id) { - return g_meshes[mesh_id].indices_count; + return g_meshes[mesh_id].index_data.count; +} + +size_t get_instances_count(uint16_t mesh_id) +{ + return g_meshes[mesh_id].instance_count; +} + +size_t get_vertex_offset(uint16_t mesh_id) +{ + return g_meshes[mesh_id].vertex_data.buffer_offset; +} + +VkDrawIndexedIndirectCommand get_index_data_buffer(uint16_t mesh_id) +{ + } \ No newline at end of file diff --git a/graphics/src/mesh_controller.h b/graphics/src/mesh_controller.h index 065858a8..3339a8d6 100644 --- a/graphics/src/mesh_controller.h +++ b/graphics/src/mesh_controller.h @@ -14,19 +14,6 @@ #include "vulkan_commons.h" -/** - * @brief Mesh data, with unique id and dynamic arrays holding vertices and indices. - * One mesh can have multiple instances. - * - */ -struct rse_mesh_t -{ - uint32_t unique_id; - size_t vertices_count; - size_t indices_count; - size_t instances_count; -}; - /** * @brief Create a new mesh for provided vertices and indices. * @@ -73,6 +60,10 @@ size_t get_indices_count(uint16_t mesh_id); */ size_t get_instances_count(uint16_t mesh_id); +size_t get_vertex_offset(uint16_t mesh_id); + +VkDrawIndexedIndirectCommand get_indices_data_buffer(uint16_t mesh_id); + #endif /* RSE_MESH_CONTROLLER_H */ \ No newline at end of file diff --git a/graphics/src/rse_graphics.c b/graphics/src/rse_graphics.c index 8a8a156d..b2f3b0bb 100644 --- a/graphics/src/rse_graphics.c +++ b/graphics/src/rse_graphics.c @@ -48,7 +48,6 @@ uint8_t rse_graphics_run(void) {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}}, {{-0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}}}; struct rse_vertex_t vertices2[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}}, - {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}}, {{0.5f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}}, {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 0.0f}}}; @@ -56,7 +55,7 @@ uint8_t rse_graphics_run(void) // FIXME: Temporary array of vertices, for testing purposes uint16_t indices[] = {0, 1, 2, 2, 3, 0}; - uint16_t mesh_id = create_mesh(vertices, indices, 24, 6); + uint16_t mesh_id = create_mesh(vertices, indices, 8, 6); create_mesh_instance(mesh_id, (struct rse_instance_data_t){ {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, rse_math_deg_to_radians(45.0f)}, @@ -69,7 +68,7 @@ uint8_t rse_graphics_run(void) 1.0f }); - mesh_id = create_mesh(vertices, indices, 24, 6); + mesh_id = create_mesh(vertices2, indices, 8, 6); create_mesh_instance(mesh_id, (struct rse_instance_data_t){ {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, rse_math_deg_to_radians(0.0f)}, diff --git a/graphics/src/vulkan_buffers.c b/graphics/src/vulkan_buffers.c index 436dc6c2..6c43a681 100644 --- a/graphics/src/vulkan_buffers.c +++ b/graphics/src/vulkan_buffers.c @@ -10,13 +10,14 @@ #include #define MAX_VERTEX_BUFFER_SIZE 33554432 /* 32 MB*/ - -#define MAX_VULKAN_BUFFERS_COUNT 1 +#define MAX_INSTANCE_BUFFER_SIZE 8192 /* 8 MB*/ /* GPU visible buffer */ -struct rse_vulkan_buffer_t g_vertex_buffers[MAX_VULKAN_BUFFERS_COUNT]; -struct rse_vulkan_buffer_t g_index_buffers[MAX_VULKAN_BUFFERS_COUNT]; -struct rse_vulkan_buffer_t g_instance_buffers[MAX_VULKAN_BUFFERS_COUNT]; +size_t g_vertex_offset = 0; +struct rse_vulkan_buffer_t g_vertex_buffer; +struct rse_vulkan_buffer_t g_index_buffer; +struct rse_vulkan_buffer_t g_instance_buffers[MAX_MESH_NUMBER]; +struct rse_vulkan_buffer_t g_draw_indirect_command_buffer; VkCommandPool g_command_pool = VK_NULL_HANDLE; @@ -49,7 +50,6 @@ static uint8_t create_buffer(const VkDeviceSize size, vertex_buffer_info.queueFamilyIndexCount = 0U; vertex_buffer_info.pQueueFamilyIndices = NULL; - /* Disalows random access to memory. TODO: Consider changing to VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT? */ create_info.flags = allocation_flags; create_info.usage = memory_usage; create_info.memoryTypeBits = 0U; @@ -175,12 +175,12 @@ static uint8_t create_vertex_buffer() 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 */ - g_vertex_buffers)) { + &g_vertex_buffer)) { LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]); return VULKAN_ERROR_BUFFER_CREATION_FAILED; } - g_vertex_buffers->allocated_size = 0; + g_vertex_buffer.allocated_size = 0; return VULKAN_ERROR_NO_ERROR; } @@ -200,32 +200,46 @@ static uint8_t create_index_buffer() if (VK_SUCCESS != create_buffer(buffer_size, 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 */ - g_index_buffers)) { + &g_index_buffer)) { LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]); return VULKAN_ERROR_BUFFER_CREATION_FAILED; } - g_index_buffers->allocated_size = 0; + g_index_buffer.allocated_size = 0; return VULKAN_ERROR_NO_ERROR; } -static uint8_t create_instance_buffer() +static uint8_t create_instance_buffers() { + size_t iter = 0U; VkDeviceSize buffer_size; buffer_size = MAX_VERTEX_BUFFER_SIZE; - /* Create Instance Buffer*/ - if (VK_SUCCESS != create_buffer(buffer_size, - 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 */ - g_instance_buffers)) { + for (iter = 0; iter < MAX_MESH_NUMBER; ++iter) { + /* Create Instance Buffer */ + if (VK_SUCCESS != create_buffer(buffer_size, + 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 */ + &g_instance_buffers[iter])) { + LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]); + return VULKAN_ERROR_BUFFER_CREATION_FAILED; + } + + g_instance_buffers[iter].allocated_size = 0; + + } + + if (VK_SUCCESS != create_buffer(sizeof(VkDrawIndexedIndirectCommand) * MAX_MESH_NUMBER, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, + VMA_MEMORY_USAGE_AUTO_PREFER_HOST, + VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + &g_draw_indirect_command_buffer)) { LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]); return VULKAN_ERROR_BUFFER_CREATION_FAILED; } - - g_instance_buffers->allocated_size = 0; - return VULKAN_ERROR_NO_ERROR; } @@ -301,17 +315,18 @@ void update_uniform_buffers() memcpy(g_vulkan_state.uniform_buffers[g_vulkan_state.current_frame].allocation_info.pMappedData, &ubo, sizeof(ubo)); } -uint8_t update_mesh_buffers(const struct rse_vertex_t* vertices, - const uint16_t* indices, - size_t vertices_num, - size_t indices_num) +uint8_t rse_add_vertices(uint16_t mesh_id, + const struct rse_vertex_t* vertices, + const uint16_t* indices, + struct rse_buffer_data_t* vertex_data, + struct rse_buffer_data_t* index_data) { + VkDrawIndexedIndirectCommand draw_indirect_command; struct rse_vulkan_buffer_t staging_buffer; - size_t vertices_size = sizeof(vertices[0]) * vertices_num; - size_t indices_size = sizeof(indices[0]) * indices_num; + size_t vertices_size = sizeof(vertices[0]) * vertex_data->count; + size_t indices_size = sizeof(indices[0]) * index_data->count; - struct rse_vulkan_buffer_t* last_vertex_buffer = &g_vertex_buffers[MAX_VULKAN_BUFFERS_COUNT - 1]; - struct rse_vulkan_buffer_t* last_index_buffer = &g_index_buffers[MAX_VULKAN_BUFFERS_COUNT - 1]; + struct rse_vulkan_buffer_t* index_buffer = &g_index_buffer; /* Creating staging buffer*/ if (VK_SUCCESS != create_buffer(MAX_VERTEX_BUFFER_SIZE, @@ -328,28 +343,42 @@ uint8_t update_mesh_buffers(const struct rse_vertex_t* vertices, memset(staging_buffer.allocation_info.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE); memcpy(staging_buffer.allocation_info.pMappedData, vertices, vertices_size); copy_buffer(staging_buffer.buffer, - last_vertex_buffer->buffer, + g_vertex_buffer.buffer, vertices_size, - last_vertex_buffer->allocated_size); + g_vertex_buffer.allocated_size); + + vertex_data->buffer_offset = g_vertex_offset; + g_vertex_offset += vertex_data->count; + g_vertex_buffer.allocated_size += vertices_size; /* Fill staging buffer with index data */ memset(staging_buffer.allocation_info.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE); memcpy(staging_buffer.allocation_info.pMappedData, indices, indices_size); copy_buffer(staging_buffer.buffer, - last_index_buffer->buffer, + index_buffer->buffer, indices_size, - last_index_buffer->allocated_size); + index_buffer->allocated_size); + index_data->buffer_offset = index_buffer->allocated_size; + index_buffer->allocated_size += indices_size; vmaDestroyBuffer(g_vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); + draw_indirect_command.indexCount = 6; + draw_indirect_command.instanceCount = 0; + draw_indirect_command.firstIndex = 0; + draw_indirect_command.vertexOffset = vertex_data->buffer_offset; + draw_indirect_command.firstInstance = 0; + + memcpy(g_draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); + return VULKAN_ERROR_NO_ERROR; } -uint8_t update_mesh_instances(struct rse_instance_data_t* instance_data) +uint8_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* instance_data) { + VkDrawIndexedIndirectCommand draw_indirect_command; struct rse_vulkan_buffer_t staging_buffer; - - struct rse_vulkan_buffer_t* last_instance_buffer = &g_instance_buffers[MAX_VULKAN_BUFFERS_COUNT - 1]; + struct rse_vulkan_buffer_t* instance_buffer = &g_instance_buffers[mesh_id]; size_t instance_size = sizeof(struct rse_instance_data_t); /* Creating staging buffer*/ @@ -363,15 +392,20 @@ uint8_t update_mesh_instances(struct rse_instance_data_t* instance_data) return VULKAN_ERROR_BUFFER_CREATION_FAILED; } + /* Copy transformation information about instance */ memcpy(staging_buffer.allocation_info.pMappedData, instance_data, instance_size); copy_buffer(staging_buffer.buffer, - last_instance_buffer->buffer, + instance_buffer->buffer, instance_size, - last_instance_buffer->allocated_size); + instance_buffer->allocated_size); vmaDestroyBuffer(g_vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); - last_instance_buffer->allocated_size += instance_size; + instance_buffer->allocated_size += instance_size; + + memcpy(&draw_indirect_command, g_draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), sizeof(VkDrawIndexedIndirectCommand)); + draw_indirect_command.instanceCount++; + memcpy(g_draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); return VULKAN_ERROR_NO_ERROR; } @@ -429,19 +463,21 @@ uint8_t record_command_buffer(uint32_t image_index) scissor.extent = g_vulkan_state.swapchain_extent; vkCmdSetScissor(command_buffer, 0, 1, &scissor); - for (i = 0; i < MAX_VULKAN_BUFFERS_COUNT; ++i) { - VkBuffer vertex_buffers[] = {g_vertex_buffers[i].buffer}; - VkBuffer index_buffers = {g_index_buffers[i].buffer}; - VkBuffer instance_buffers[] = {g_instance_buffers[i].buffer}; + vkCmdBindVertexBuffers(command_buffer, 0, 1, &g_vertex_buffer.buffer, offsets); + vkCmdBindIndexBuffer(command_buffer, g_index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_vulkan_state.pipeline_layout, 0, 1, + &g_vulkan_state.descriptor_sets[g_vulkan_state.current_frame], 0, NULL); - /* TODO: Figure out the offset */ - vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); - vkCmdBindVertexBuffers(command_buffer, 1, 1, instance_buffers, offsets); - vkCmdBindIndexBuffer(command_buffer, index_buffers, 0, VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_vulkan_state.pipeline_layout, 0, 1, - &g_vulkan_state.descriptor_sets[g_vulkan_state.current_frame], 0, NULL); + for (i = 0; i < 2; ++i) { + VkBuffer instance_buffer = {g_instance_buffers[i].buffer}; - vkCmdDrawIndexed(command_buffer, (uint32_t)(get_indices_count(0)+3), get_instances_count(0), 0, 0, 0); + vkCmdBindVertexBuffers(command_buffer, 1, 1, &instance_buffer, offsets); + + vkCmdDrawIndexedIndirect(command_buffer, + g_draw_indirect_command_buffer.buffer, + sizeof(VkDrawIndexedIndirectCommand) * i, + 1, + 0); /* Can be 0 since we are not doing multiple draws each loop */ } vkCmdEndRenderPass(command_buffer); @@ -461,7 +497,7 @@ uint8_t create_buffers() STATUS_CHECK(create_command_pools()); STATUS_CHECK(create_vertex_buffer()); STATUS_CHECK(create_index_buffer()); - STATUS_CHECK(create_instance_buffer()); + STATUS_CHECK(create_instance_buffers()); STATUS_CHECK(create_uniform_buffer()); STATUS_CHECK(allocate_command_buffers()); @@ -483,10 +519,13 @@ void destroy_buffers() g_vulkan_state.uniform_buffers[i].allocation); } - for (i = 0; i < MAX_VULKAN_BUFFERS_COUNT; ++i) { - vmaDestroyBuffer(g_vulkan_state.allocator, g_vertex_buffers[i].buffer, g_vertex_buffers[i].allocation); - vmaDestroyBuffer(g_vulkan_state.allocator, g_index_buffers[i].buffer, g_index_buffers[i].allocation); + vmaDestroyBuffer(g_vulkan_state.allocator, g_vertex_buffer.buffer, g_vertex_buffer.allocation); + vmaDestroyBuffer(g_vulkan_state.allocator, g_index_buffer.buffer, g_index_buffer.allocation); + vmaDestroyBuffer(g_vulkan_state.allocator, g_draw_indirect_command_buffer.buffer, g_draw_indirect_command_buffer.allocation); + + for(i = 0; i < MAX_MESH_NUMBER; ++i) { vmaDestroyBuffer(g_vulkan_state.allocator, g_instance_buffers[i].buffer, g_instance_buffers[i].allocation); } + vkDestroyCommandPool(g_vulkan_state.device, g_command_pool, NULL); } \ No newline at end of file diff --git a/graphics/src/vulkan_buffers.h b/graphics/src/vulkan_buffers.h index cea6d8e2..056ff48a 100644 --- a/graphics/src/vulkan_buffers.h +++ b/graphics/src/vulkan_buffers.h @@ -6,6 +6,17 @@ #include +#define MAX_MESH_NUMBER 256 + +/** + * @brief Represents data within vertex or instance buffer. + * + */ +struct rse_buffer_data_t +{ + size_t count; + size_t buffer_offset; +}; /** * @brief Create buffers needed by vulkan pipeline @@ -25,22 +36,24 @@ void update_uniform_buffers(); * * @param vertices Vertices to add * @param indices Indices to add - * @param vertices_num Number of vertices to add - * @param indices_num Number of indices to add - * @return uint8_t VULKAN_ERROR_NO_ERROR on success + * @param vertex_data Mutable vertex data. Count will be read and buffer offset will be set + * @param index_data Mutable index data. Count will be read and buffer offset will be set + * @return uint8_t */ -uint8_t update_mesh_buffers(const struct rse_vertex_t* vertices, - const uint16_t* indices, - size_t vertices_num, - size_t indices_num); +uint8_t rse_add_vertices(uint16_t mesh_id, + const struct rse_vertex_t* vertices, + const uint16_t* indices, + struct rse_buffer_data_t* vertex_data, + struct rse_buffer_data_t* index_data); /** * @brief Add instance data to vulkan buffers * + * @param mesh_id Mesh ID * @param instance_data Instance data * @return uint8_t VULKAN_ERROR_NO_ERROR on success */ -uint8_t update_mesh_instances(struct rse_instance_data_t* instance_data); +uint8_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* instance_data); /** * @brief Record commands for given image index diff --git a/graphics/src/vulkan_commons.h b/graphics/src/vulkan_commons.h index 3a8dd8bd..ac526c20 100644 --- a/graphics/src/vulkan_commons.h +++ b/graphics/src/vulkan_commons.h @@ -38,7 +38,7 @@ struct rse_vertex_t */ struct rse_vulkan_buffer_t { - uint32_t allocated_size; + size_t allocated_size; VkBuffer buffer; VmaAllocation allocation; VmaAllocationInfo allocation_info;