summaryrefslogtreecommitdiff
path: root/src/render/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/mesh.c')
-rw-r--r--src/render/mesh.c83
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);
+}