diff options
| author | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2024-06-30 22:23:08 +0200 | 
|---|---|---|
| committer | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2024-06-30 22:29:30 +0200 | 
| commit | 87c8428df0bf1b2f6932bb16390f69be57e21f6b (patch) | |
| tree | 0cc0f7cab79a0373ef366898df8f5773391bae17 /src/buffer.c | |
| download | libvlkn-main.tar.xz | |
Signed-off-by: Anna (navi) Figueiredo Gomes <navi@vlhl.dev>
Diffstat (limited to 'src/buffer.c')
| -rw-r--r-- | src/buffer.c | 195 | 
1 files changed, 195 insertions, 0 deletions
| diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..81e8ae6 --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,195 @@ +#include "renderer.h" +#include "buffer.h" + +#include <string.h> + +static inline ssize_t find_memory_type(struct vlkn_renderer *ren, uint32_t filter, VkMemoryPropertyFlags props) { +	VkPhysicalDeviceMemoryProperties mem_props; +	vkGetPhysicalDeviceMemoryProperties(ren->phy_gpus.chosen->gpu, &mem_props); + +	for (size_t i = 0; i < mem_props.memoryTypeCount; i++) +		if (filter & (1 << i) && (mem_props.memoryTypes[i].propertyFlags & props) == props) +			return i; + +	return -1; +} + +VkResult buffer_create(struct vlkn_renderer *ren, VkDeviceSize size, +		VkBufferUsageFlags usage, VkMemoryPropertyFlags props, struct vlkn_buffer *buffer) { +	VkBufferCreateInfo buffer_info = { +		.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, +		.size = size, +		.usage = usage, +		.sharingMode = VK_SHARING_MODE_EXCLUSIVE, +	}; + +	VkResult res = vkCreateBuffer(ren->gpu.device, &buffer_info, NULL, &buffer->buffer); +	if (res != VK_SUCCESS) +		return res; + +	VkMemoryRequirements mem_reqs; +	vkGetBufferMemoryRequirements(ren->gpu.device, buffer->buffer, &mem_reqs); + +	ssize_t mem_type_index = find_memory_type(ren, mem_reqs.memoryTypeBits, props); +	if (mem_type_index == -1) +		return VK_ERROR_UNKNOWN; + +	VkMemoryAllocateInfo alloc_info = { +		.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, +		.allocationSize = mem_reqs.size, +		.memoryTypeIndex = mem_type_index +	}; + +	res = vkAllocateMemory(ren->gpu.device, &alloc_info, NULL, &buffer->memory); +	if (res != VK_SUCCESS) +		return res; + +	buffer->size = size; +	return vkBindBufferMemory(ren->gpu.device, buffer->buffer, buffer->memory, 0); +} + +VkResult buffer_upload(struct vlkn_renderer *ren, struct vlkn_buffer *buffer, +		size_t offset, size_t size, uint8_t data[size]) { +	struct vlkn_buffer tmp; +	size_t end_size = offset + size; +	// TODO: reallocate buffer? +	if (end_size > buffer->size) { +		end_size = buffer->size - offset; +	} +	VkResult res = buffer_create(ren, end_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, +			VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &tmp); +	if (res != VK_SUCCESS) +		return res; + +	void *map; +	res = vkMapMemory(ren->gpu.device, tmp.memory, 0, end_size, 0, &map); +	if (res != VK_SUCCESS) +		return res; +	memcpy(map, data, size < buffer->size ? size : end_size); +	vkUnmapMemory(ren->gpu.device, tmp.memory); + +	VkCommandBuffer cmd = begin_single_command(ren); +	vkCmdCopyBuffer(cmd, tmp.buffer, buffer->buffer, 1, &(VkBufferCopy) { .size = end_size }); +	end_single_command(ren, cmd); + +	buffer_destroy(ren, &tmp); + +	return VK_SUCCESS; +} + +void buffer_destroy(struct vlkn_renderer *ren, struct vlkn_buffer *buffer) { +	vkDestroyBuffer(ren->gpu.device, buffer->buffer, NULL); +	vkFreeMemory(ren->gpu.device, buffer->memory, NULL); +} + +VkResult image_view_create(struct vlkn_renderer *ren, VkFormat format, +		VkImageAspectFlags aspect, VkImage image, VkImageView *view) { +	VkImageViewCreateInfo view_info = { +		.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, +		.image = image, +		.viewType = VK_IMAGE_VIEW_TYPE_2D, +		.format = format, +		.components = { +			.r = VK_COMPONENT_SWIZZLE_IDENTITY, +			.g = VK_COMPONENT_SWIZZLE_IDENTITY, +			.b = VK_COMPONENT_SWIZZLE_IDENTITY, +			.a = VK_COMPONENT_SWIZZLE_IDENTITY, +		}, +		.subresourceRange = { +			.aspectMask = aspect, +			.baseMipLevel = 0, +			.levelCount = 1, +			.baseArrayLayer = 0, +			.layerCount = 1 +		} +	}; + +	return vkCreateImageView(ren->gpu.device, &view_info, NULL, view); +} + +VkResult image_create(struct vlkn_renderer *ren, struct image_opts opts, struct vlkn_images *image) { +	VkImageCreateInfo image_info = { +		.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, +		.imageType = VK_IMAGE_TYPE_2D, +		.extent = { +			.width = opts.extent.width, +			.height = opts.extent.height, +			.depth = 1 +		}, +		.mipLevels = opts.mip_level, +		.arrayLayers = 1, +		.format = opts.format, +		.tiling = opts.tiling, +		.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, +		.usage = opts.usage, +		.sharingMode = VK_SHARING_MODE_EXCLUSIVE, +		.samples = VK_SAMPLE_COUNT_1_BIT +	}; + +	VkResult res = vkCreateImage(ren->gpu.device, &image_info, NULL, &image->image); +	if (res != VK_SUCCESS) +		return res; + +	VkMemoryRequirements mem_reqs; +	vkGetImageMemoryRequirements(ren->gpu.device, image->image, &mem_reqs); + +	ssize_t mem_type_index = find_memory_type(ren, mem_reqs.memoryTypeBits, opts.mem_props); +	if (mem_type_index == -1) +		return VK_ERROR_UNKNOWN; + +	VkMemoryAllocateInfo alloc_info = { +		.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, +		.allocationSize = mem_reqs.size, +		.memoryTypeIndex = mem_type_index +	}; + +	res = vkAllocateMemory(ren->gpu.device, &alloc_info, NULL, &image->memory); +	if (res != VK_SUCCESS) +		return res; + +	res = vkBindImageMemory(ren->gpu.device, image->image, image->memory, 0); +	if (res != VK_SUCCESS) +		return res; + +	return image_view_create(ren, opts.format, opts.aspect, image->image, &image->view); +} + +void image_destroy(struct vlkn_renderer *ren, struct vlkn_images *image) { +	vkDestroyImageView(ren->gpu.device, image->view, NULL); +	vkDestroyImage(ren->gpu.device, image->image, NULL); +	vkFreeMemory(ren->gpu.device, image->memory, NULL); +} + +struct vlkn_mesh vlkn_mesh_upload(struct vlkn_renderer *renderer, size_t vertex_count, struct vlkn_vertex vertices[vertex_count], +		size_t index_count, uint32_t indices[index_count], struct vec3 position) { +	(void) position; +	const VkDeviceSize vertex_size = sizeof(*vertices) * vertex_count; +	const VkDeviceSize index_size = sizeof(*indices) * index_count; + +	struct vlkn_mesh mesh; +	buffer_create(renderer, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, +			VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mesh.vertex); +	buffer_create(renderer, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, +			VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mesh.index); + +	struct vlkn_buffer tmp; +	buffer_create(renderer, vertex_size + index_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, +			VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &tmp); + +	void *data; +	vkMapMemory(renderer->gpu.device, tmp.memory, 0, vertex_size + index_size, 0, &data); +	memcpy(data, vertices, vertex_size); +	memcpy((char *)data + vertex_size, indices, index_size); +	vkUnmapMemory(renderer->gpu.device, tmp.memory); + +	VkCommandBuffer cmd = begin_single_command(renderer); +	vkCmdCopyBuffer(cmd, tmp.buffer, mesh.vertex.buffer, 1, &(VkBufferCopy) { .size = vertex_size }); +	vkCmdCopyBuffer(cmd, tmp.buffer, mesh.index.buffer, 1, &(VkBufferCopy) { .size = index_size, .srcOffset = vertex_size }); +	end_single_command(renderer, cmd); + +	buffer_destroy(renderer, &tmp); +	mesh.index_count = index_count; +	mesh.position = position; + +	return mesh; +} | 
