separate buffer stuff into modules

This commit is contained in:
jacekpoz 2024-09-24 12:29:59 +02:00
parent 88b2154c16
commit 04db7a3318
Signed by: poz
SSH key fingerprint: SHA256:JyLeVWE4bF3tDnFeUpUaJsPsNlJyBldDGV/dIKSLyN8
5 changed files with 298 additions and 236 deletions

166
src/ptk_vk/buffer.c Normal file
View file

@ -0,0 +1,166 @@
#include <ptk_vk/buffer.h>
#include <ptk_vk/init.h>
#include <ptk_vk/utils.h>
#include <string.h>
PTK_OPTION_DEFINE(uint32_t);
PTK_OPTION(uint32_t) find_memory_type(VkPhysicalDevice physical_dev, const uint32_t type_filter, const VkMemoryPropertyFlags props) {
VkPhysicalDeviceMemoryProperties mem_props;
vkGetPhysicalDeviceMemoryProperties(physical_dev, &mem_props);
for (uint32_t i = 0; i < mem_props.memoryTypeCount; ++i) {
if (type_filter & (1 << i) && (mem_props.memoryTypes[i].propertyFlags & props) == props) {
return PTK_OPTION_SOME(uint32_t, i);
}
}
return PTK_OPTION_NONE(uint32_t);
}
PTK_OPTION(BufferStuff) create_buffer(VkDevice dev, VkPhysicalDevice physical_dev, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags props) {
BufferStuff ret;
VK_TRY(PTK_OPTION_NONE(BufferStuff),
vkCreateBuffer(
dev,
&(VkBufferCreateInfo){
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.size = size,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = NULL,
},
NULL,
&ret.buffer
)
);
VkMemoryRequirements mem_reqs;
vkGetBufferMemoryRequirements(dev, ret.buffer, &mem_reqs);
const PTK_OPTION(uint32_t) memory_type = find_memory_type(physical_dev, mem_reqs.memoryTypeBits, props);
if (!memory_type.exists) {
PTK_ERR("failed to find suitable memory type");
return PTK_OPTION_NONE(BufferStuff);
}
VK_TRY(PTK_OPTION_NONE(BufferStuff),
vkAllocateMemory(
dev,
&(VkMemoryAllocateInfo){
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = NULL,
.allocationSize = mem_reqs.size,
.memoryTypeIndex = memory_type.value,
},
NULL,
&ret.buffer_memory
)
);
vkBindBufferMemory(dev, ret.buffer, ret.buffer_memory, 0);
return PTK_OPTION_SOME(BufferStuff, ret);
}
bool copy_buffer(VkDevice dev, VkCommandPool command_pool, const VkBuffer src, const VkBuffer dst, const VkDeviceSize size) {
VkCommandBuffer command_buffer;
VK_TRY(false,
vkAllocateCommandBuffers(
dev,
&(VkCommandBufferAllocateInfo){
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = NULL,
.commandPool = command_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
},
&command_buffer
)
);
VK_TRY(false,
vkBeginCommandBuffer(command_buffer, &(VkCommandBufferBeginInfo){
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.pNext = NULL,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
.pInheritanceInfo = NULL,
})
);
vkCmdCopyBuffer(command_buffer, src, dst, 1, &(VkBufferCopy){
.srcOffset = 0,
.dstOffset = 0,
.size = size,
});
VK_TRY(false,
vkEndCommandBuffer(command_buffer)
);
vkQueueSubmit(
g_graphics_queue,
1,
&(VkSubmitInfo){
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = NULL,
.waitSemaphoreCount = 0,
.pWaitSemaphores = NULL,
.pWaitDstStageMask = NULL,
.commandBufferCount = 1,
.pCommandBuffers = &command_buffer,
.signalSemaphoreCount = 0,
.pSignalSemaphores = NULL,
},
VK_NULL_HANDLE
);
vkQueueWaitIdle(g_graphics_queue);
vkFreeCommandBuffers(dev, command_pool, 1, &command_buffer);
return true;
}
bool transfer_to_buffer(VkDevice dev, VkPhysicalDevice physical_dev, VkCommandPool command_pool, void *src, size_t src_size, VkBuffer buffer) {
const VkDeviceSize buffer_size = src_size;
PTK_OPTION(BufferStuff) staging_buffer_stuff_opt = create_buffer(
dev,
physical_dev,
buffer_size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
);
if (!staging_buffer_stuff_opt.exists) {
PTK_ERR("failed creating staging vertex buffer");
return false;
}
VkBuffer staging_buffer = staging_buffer_stuff_opt.value.buffer;
VkDeviceMemory staging_buffer_memory = staging_buffer_stuff_opt.value.buffer_memory;
void *data;
vkMapMemory(dev, staging_buffer_memory, 0, buffer_size, 0, &data);
memcpy(data, src, (size_t)buffer_size);
vkUnmapMemory(dev, staging_buffer_memory);
if (!copy_buffer(dev, command_pool, staging_buffer, buffer, buffer_size)) {
PTK_ERR("failed copying staging buffer to vertex buffer");
return false;
}
vkDestroyBuffer(dev, staging_buffer, NULL);
vkFreeMemory(dev, staging_buffer_memory, NULL);
return true;
}

21
src/ptk_vk/buffer.h Normal file
View file

@ -0,0 +1,21 @@
// Copyright (jacekpoz 2024). Licensed under the EUPL-1.2 or later.
#ifndef PTK_PTK_VK_BUFFER_H_
#define PTK_PTK_VK_BUFFER_H_
#include <vulkan/vulkan_core.h>
#include <ptk_option.h>
typedef struct {
VkBuffer buffer;
VkDeviceMemory buffer_memory;
} BufferStuff;
PTK_OPTION_DEFINE(BufferStuff);
PTK_OPTION(BufferStuff) create_buffer(VkDevice dev, VkPhysicalDevice physical_dev, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags props);
bool transfer_to_buffer(VkDevice dev, VkPhysicalDevice physical_dev, VkCommandPool command_pool, void *src, size_t src_size, VkBuffer buffer);
#endif // PTK_PTK_VK_BUFFER_H_

View file

@ -2,6 +2,7 @@
#include <ptk_vk/init.h>
#include <ptk_vk/buffer.h>
#include <ptk_vk/command_pool.h>
#include <ptk_vk/components.h>
#include <ptk_vk/descriptor_set_layout.h>
@ -12,6 +13,7 @@
#include <ptk_vk/pipeline.h>
#include <ptk_vk/render_pass.h>
#include <ptk_vk/swapchain.h>
#include <ptk_vk/uniform_buffers.h>
#include <ptk_vk/utils.h>
#include <ptk_log.h>
@ -21,10 +23,6 @@
#include <stdio.h>
#include <string.h>
PTK_LIST_DEFINE(VkBuffer);
PTK_LIST_DEFINE(VkDeviceMemory);
typedef void *voidptr;
PTK_LIST_DEFINE(voidptr);
PTK_LIST_DEFINE(VkDescriptorSet);
static VkInstance m_instance;
@ -55,15 +53,10 @@ static VkDeviceMemory m_vertex_buffer_memory;
static VkBuffer m_index_buffer;
static VkDeviceMemory m_index_buffer_memory;
typedef struct {
PtkSize initial_window_size;
PtkSize window_size;
} UniformBufferObject;
static UniformBufferObject m_uniform_buffer_object;
static PTK_LIST(VkBuffer) m_uniform_buffers;
static PTK_LIST(VkDeviceMemory) m_uniform_buffers_memory;
static PTK_LIST(VkDeviceMemory) m_uniform_buffer_memories;
static PTK_LIST(voidptr) m_uniform_buffers_mapped;
VkRenderPass g_render_pass;
@ -79,161 +72,6 @@ static const PTK_ARRAY(constcharptr) m_validation_layers = PTK_ARRAY_NEW(constch
static const PTK_ARRAY(constcharptr) m_validation_layers = PTK_ARRAY_EMPTY(constcharptr);
#endif
PTK_OPTION(uint32_t) find_memory_type(const uint32_t type_filter, const VkMemoryPropertyFlags props) {
VkPhysicalDeviceMemoryProperties mem_props;
vkGetPhysicalDeviceMemoryProperties(g_physical_dev, &mem_props);
for (uint32_t i = 0; i < mem_props.memoryTypeCount; ++i) {
if (type_filter & (1 << i) && (mem_props.memoryTypes[i].propertyFlags & props) == props) {
return PTK_OPTION_SOME(uint32_t, i);
}
}
return PTK_OPTION_NONE(uint32_t);
}
bool create_buffer(const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags props, VkBuffer *buffer, VkDeviceMemory *buffer_memory) {
VK_TRY(false,
vkCreateBuffer(
g_dev,
&(VkBufferCreateInfo){
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.size = size,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = NULL,
},
NULL,
buffer
)
);
VkMemoryRequirements mem_reqs;
vkGetBufferMemoryRequirements(g_dev, *buffer, &mem_reqs);
const PTK_OPTION(uint32_t) memory_type = find_memory_type(mem_reqs.memoryTypeBits, props);
if (!memory_type.exists) {
PTK_ERR("failed to find suitable memory type");
return false;
}
VK_TRY(false,
vkAllocateMemory(
g_dev,
&(VkMemoryAllocateInfo){
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = NULL,
.allocationSize = mem_reqs.size,
.memoryTypeIndex = memory_type.value,
},
NULL,
buffer_memory
)
);
vkBindBufferMemory(g_dev, *buffer, *buffer_memory, 0);
return true;
}
bool copy_buffer(const VkBuffer src, const VkBuffer dst, const VkDeviceSize size) {
VkCommandBuffer command_buffer;
VK_TRY(false,
vkAllocateCommandBuffers(
g_dev,
&(VkCommandBufferAllocateInfo){
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = NULL,
.commandPool = m_command_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
},
&command_buffer
)
);
VK_TRY(false,
vkBeginCommandBuffer(command_buffer, &(VkCommandBufferBeginInfo){
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.pNext = NULL,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
.pInheritanceInfo = NULL,
})
);
vkCmdCopyBuffer(command_buffer, src, dst, 1, &(VkBufferCopy){
.srcOffset = 0,
.dstOffset = 0,
.size = size,
});
VK_TRY(false,
vkEndCommandBuffer(command_buffer)
);
vkQueueSubmit(
g_graphics_queue,
1,
&(VkSubmitInfo){
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = NULL,
.waitSemaphoreCount = 0,
.pWaitSemaphores = NULL,
.pWaitDstStageMask = NULL,
.commandBufferCount = 1,
.pCommandBuffers = &command_buffer,
.signalSemaphoreCount = 0,
.pSignalSemaphores = NULL,
},
VK_NULL_HANDLE
);
vkQueueWaitIdle(g_graphics_queue);
vkFreeCommandBuffers(g_dev, m_command_pool, 1, &command_buffer);
return true;
}
bool transfer_to_buffer(void *src, size_t src_size, VkBuffer buffer) {
const VkDeviceSize buffer_size = src_size;
VkBuffer staging_buffer;
VkDeviceMemory staging_buffer_memory;
if (
!create_buffer(
buffer_size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&staging_buffer,
&staging_buffer_memory
)
) {
PTK_ERR("failed creating staging vertex buffer");
return false;
}
void *data;
vkMapMemory(g_dev, staging_buffer_memory, 0, buffer_size, 0, &data);
memcpy(data, src, (size_t)buffer_size);
vkUnmapMemory(g_dev, staging_buffer_memory);
if (!copy_buffer(staging_buffer, buffer, buffer_size)) {
PTK_ERR("failed copying staging buffer to vertex buffer");
return false;
}
vkDestroyBuffer(g_dev, staging_buffer, NULL);
vkFreeMemory(g_dev, staging_buffer_memory, NULL);
return true;
}
bool vk_transfer_vertex_data(void) {
PTK_DEBUG("vertices updated!");
PTK_LIST_FOR_EACH_E(const Vertex, g_vertices, i, current, {
@ -244,7 +82,7 @@ bool vk_transfer_vertex_data(void) {
PTK_DEBUG("transferring vertices to gpu…");
const size_t vertices_size = sizeof(g_vertices.data[0]) * g_vertices.size;
if (!transfer_to_buffer(g_vertices.data, vertices_size, m_vertex_buffer)) {
if (!transfer_to_buffer(g_dev, g_physical_dev, m_command_pool, g_vertices.data, vertices_size, m_vertex_buffer)) {
PTK_ERR("failed transferring vertices");
return false;
}
@ -256,7 +94,7 @@ bool vk_transfer_vertex_data(void) {
PTK_DEBUG("transferring indices to gpu…");
const size_t indices_size = sizeof(g_indices.data[0]) * g_indices.size;
if (!transfer_to_buffer(g_indices.data, indices_size, m_index_buffer)) {
if (!transfer_to_buffer(g_dev, g_physical_dev, m_command_pool, g_indices.data, indices_size, m_index_buffer)) {
PTK_ERR("failed transferring indices");
return false;
}
@ -264,70 +102,6 @@ bool vk_transfer_vertex_data(void) {
return true;
}
bool create_vertex_buffer(void) {
// const VkDeviceSize buffer_size = sizeof(g_vertices.data[0]) * g_vertices.size;
const VkDeviceSize buffer_size = 65536;
if (
!create_buffer(
buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&m_vertex_buffer,
&m_vertex_buffer_memory
)
) {
PTK_ERR("failed creating vertex buffer");
return false;
}
return true;
}
bool create_index_buffer(void) {
const VkDeviceSize buffer_size = 65536;
if (
!create_buffer(
buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&m_index_buffer,
&m_index_buffer_memory
)
) {
PTK_ERR("failed creating index buffer");
return false;
}
return true;
}
bool create_uniform_buffers(void) {
const VkDeviceSize buffer_size = sizeof(UniformBufferObject);
m_uniform_buffers = PTK_LIST_NEW(VkBuffer, g_max_frames_in_flight);
m_uniform_buffers_memory = PTK_LIST_NEW(VkDeviceMemory, g_max_frames_in_flight);
m_uniform_buffers_mapped = PTK_LIST_NEW(voidptr, g_max_frames_in_flight);
for (size_t i = 0; i < g_max_frames_in_flight; ++i) {
if (
!create_buffer(
buffer_size,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&m_uniform_buffers.data[i],
&m_uniform_buffers_memory.data[i]
)
) {
PTK_ERR("failed creating vertex buffer");
return false;
}
vkMapMemory(g_dev, m_uniform_buffers_memory.data[i], 0, buffer_size, 0, &m_uniform_buffers_mapped.data[i]);
}
return true;
}
bool create_descriptor_pool(void) {
VK_TRY(false,
vkCreateDescriptorPool(
@ -615,21 +389,51 @@ bool vk_init(GLFWwindow *window, const size_t width, const size_t height, const
m_command_pool = command_pool_opt.value;
if (!create_vertex_buffer()) {
const VkDeviceSize buffer_size = 65536;
PTK_OPTION(BufferStuff) vertex_buffer_stuff_opt = create_buffer(
g_dev,
g_physical_dev,
buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
);
if (!vertex_buffer_stuff_opt.exists) {
PTK_ERR("failed creating vertex buffer");
return false;
}
if (!create_index_buffer()) {
m_vertex_buffer = vertex_buffer_stuff_opt.value.buffer;
m_vertex_buffer_memory = vertex_buffer_stuff_opt.value.buffer_memory;
PTK_OPTION(BufferStuff) index_buffer_stuff_opt = create_buffer(
g_dev,
g_physical_dev,
buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
);
if (!index_buffer_stuff_opt.exists) {
PTK_ERR("failed creating index buffer");
return false;
}
if (!create_uniform_buffers()) {
m_index_buffer = index_buffer_stuff_opt.value.buffer;
m_index_buffer_memory = index_buffer_stuff_opt.value.buffer_memory;
PTK_OPTION(UniformBufferStuff) uniform_buffer_stuff_opt = vk_create_uniform_buffers(g_dev, g_physical_dev);
if (!uniform_buffer_stuff_opt.exists) {
PTK_ERR("failed creating uniform buffers");
return false;
}
m_uniform_buffers = uniform_buffer_stuff_opt.value.buffers;
m_uniform_buffer_memories = uniform_buffer_stuff_opt.value.buffer_memories;
m_uniform_buffers_mapped = uniform_buffer_stuff_opt.value.buffers_mapped;
if (!create_descriptor_pool()) {
PTK_ERR("failed creating descriptor pool");
return false;
@ -663,10 +467,10 @@ void vk_cleanup(void) {
for (size_t i = 0; i < g_max_frames_in_flight; ++i) {
vkDestroyBuffer(g_dev, m_uniform_buffers.data[i], NULL);
vkFreeMemory(g_dev, m_uniform_buffers_memory.data[i], NULL);
vkFreeMemory(g_dev, m_uniform_buffer_memories.data[i], NULL);
}
PTK_LIST_FREE(m_uniform_buffers);
PTK_LIST_FREE(m_uniform_buffers_memory);
PTK_LIST_FREE(m_uniform_buffer_memories);
PTK_LIST_FREE(m_uniform_buffers_mapped);
vkDestroyDescriptorPool(g_dev, m_descriptor_pool, NULL);

View file

@ -0,0 +1,39 @@
#include <ptk_vk/uniform_buffers.h>
#include <ptk_vk/buffer.h>
#include <ptk_vk/init.h>
#include <ptk_log.h>
PTK_OPTION(UniformBufferStuff) vk_create_uniform_buffers(VkDevice dev, VkPhysicalDevice physical_dev) {
const VkDeviceSize buffer_size = sizeof(UniformBufferObject);
UniformBufferStuff ret = {
.buffers = PTK_LIST_NEW(VkBuffer, g_max_frames_in_flight),
.buffer_memories = PTK_LIST_NEW(VkDeviceMemory, g_max_frames_in_flight),
.buffers_mapped = PTK_LIST_NEW(voidptr, g_max_frames_in_flight),
};
for (size_t i = 0; i < g_max_frames_in_flight; ++i) {
PTK_OPTION(BufferStuff) uniform_buffer_stuff_opt = create_buffer(
dev,
physical_dev,
buffer_size,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
);
if (!uniform_buffer_stuff_opt.exists) {
PTK_ERR("failed creating index buffer");
return PTK_OPTION_NONE(UniformBufferStuff);
}
ret.buffers.data[i] = uniform_buffer_stuff_opt.value.buffer;
ret.buffer_memories.data[i] = uniform_buffer_stuff_opt.value.buffer_memory;
vkMapMemory(dev, ret.buffer_memories.data[i], 0, buffer_size, 0, &ret.buffers_mapped.data[i]);
}
return PTK_OPTION_SOME(UniformBufferStuff, ret);
}

View file

@ -0,0 +1,32 @@
// Copyright (jacekpoz 2024). Licensed under the EUPL-1.2 or later.
#ifndef PTK_PTK_VK_UNIFORM_BUFFERS_H_
#define PTK_PTK_VK_UNIFORM_BUFFERS_H_
#include <vulkan/vulkan_core.h>
#include <ptk_list.h>
#include <ptk_option.h>
#include <ptk_vec.h>
PTK_LIST_DEFINE(VkBuffer);
PTK_LIST_DEFINE(VkDeviceMemory);
typedef void *voidptr;
PTK_LIST_DEFINE(voidptr);
typedef struct {
PtkSize initial_window_size;
PtkSize window_size;
} UniformBufferObject;
typedef struct {
PTK_LIST(VkBuffer) buffers;
PTK_LIST(VkDeviceMemory) buffer_memories;
PTK_LIST(voidptr) buffers_mapped;
} UniformBufferStuff;
PTK_OPTION_DEFINE(UniformBufferStuff);
PTK_OPTION(UniformBufferStuff) vk_create_uniform_buffers(VkDevice dev, VkPhysicalDevice physical_dev);
#endif // PTK_PTK_VK_UNIFORM_BUFFERS_H_