summaryrefslogtreecommitdiff
path: root/src/render/mesh.c
blob: d2229f19a44f1cea3148b0382bbdf092064544c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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);
}