diff options
Diffstat (limited to 'src/render/mesh.c')
-rw-r--r-- | src/render/mesh.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/render/mesh.c b/src/render/mesh.c new file mode 100644 index 0000000..d2229f1 --- /dev/null +++ b/src/render/mesh.c @@ -0,0 +1,83 @@ +#include "render/mesh.h" +#include "render/buffer.h" +#include "render/renderer.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static VkCommandBuffer begin_single_command(struct renderer *ren) { + VkCommandBufferAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandPool = ren->command.pool, + .commandBufferCount = 1 + }; + + VkCommandBuffer buffer; + vkAllocateCommandBuffers(ren->gpu.device, &alloc_info, &buffer); + + VkCommandBufferBeginInfo begin_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + }; + + vkBeginCommandBuffer(buffer, &begin_info); + + return buffer; +} + +static void end_single_command(struct renderer *ren, VkCommandBuffer buffer) { + vkEndCommandBuffer(buffer); + + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &buffer + }; + + vkQueueSubmit(ren->gpu.gfx_queue, 1, &submit_info, VK_NULL_HANDLE); + vkQueueWaitIdle(ren->gpu.gfx_queue); + + vkFreeCommandBuffers(ren->gpu.device, ren->command.pool, 1, &buffer); +} + +struct mesh upload_mesh(struct renderer *ren, size_t vertex_count, struct vertex vertices[vertex_count], + size_t index_count, uint32_t indices[index_count], struct vec3 position) { + const VkDeviceSize vertex_buffer_size = sizeof(*vertices) * vertex_count; + const VkDeviceSize index_buffer_size = sizeof(*indices) * index_count; + + struct mesh buf; + buffer_create(ren, vertex_buffer_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &buf.vertex); + buffer_create(ren, index_buffer_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &buf.index); + + struct buffer tmp; + buffer_create(ren, vertex_buffer_size + index_buffer_size + sizeof(mat4x4), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &tmp); + + void *data; + vkMapMemory(ren->gpu.device, tmp.memory, 0, vertex_buffer_size + index_buffer_size + sizeof(mat4x4), 0, &data); + memcpy(data, vertices, vertex_buffer_size); + memcpy((char *)data + vertex_buffer_size, indices, index_buffer_size); + vkUnmapMemory(ren->gpu.device, tmp.memory); + + VkCommandBuffer cmd = begin_single_command(ren); + vkCmdCopyBuffer(cmd, tmp.buffer, buf.vertex.buffer, 1, &(VkBufferCopy) { .size = vertex_buffer_size }); + vkCmdCopyBuffer(cmd, tmp.buffer, buf.index.buffer, 1, &(VkBufferCopy) { .size = index_buffer_size, .srcOffset = vertex_buffer_size }); + end_single_command(ren, cmd); + + buffer_destroy(ren, &tmp); + + buf.index_count = index_count; + + mat4x4_translate(buf.position, position.x, position.y, position.z); + + return buf; +} + +void mesh_destroy(struct renderer *ren, struct mesh *mesh) { + vkDeviceWaitIdle(ren->gpu.device); + buffer_destroy(ren, &mesh->vertex); + buffer_destroy(ren, &mesh->index); +} |