Add texture handler
Added functionality to load images as textures and bind them to meshes.
This commit is contained in:
1 parent
0e040dd0d5
commit
4fcda01ba2
24 files changed
+897
-200
No files matched your search
+48
-143
@@ -5,6 +5,7 @@
|
||||
#include "utilities/logger.h"
|
||||
#include "mesh_controller.h"
|
||||
#include "rse_math.h"
|
||||
#include "rse_vulkan_commands.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -19,141 +20,28 @@ struct rse_vulkan_buffer_t g_index_buffer;
|
||||
struct rse_vulkan_buffer_t g_instance_buffers[MAX_MESH_NUMBER];
|
||||
struct rse_vulkan_buffer_t g_draw_indirect_command_buffer;
|
||||
|
||||
VkCommandPool g_command_pool = VK_NULL_HANDLE;
|
||||
|
||||
/**
|
||||
* @brief Helper function. Creates a buffer object
|
||||
*
|
||||
* @param size Size of the target buffer
|
||||
* @param buffer_usage Buffer usage flags
|
||||
* @param memory_usage memory usage flags (mostly VMA_MEMORY_USAGE_AUTO)
|
||||
* @param allocation_flags VMA allocation flags
|
||||
* @param buffer Buffer, that will be allocated
|
||||
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||
* VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED
|
||||
*/
|
||||
static uint8_t create_buffer(const VkDeviceSize size,
|
||||
VkBufferUsageFlags buffer_usage,
|
||||
VmaMemoryUsage memory_usage,
|
||||
const VmaAllocationCreateFlags allocation_flags,
|
||||
struct rse_vulkan_buffer_t* buffer)
|
||||
{
|
||||
VkBufferCreateInfo vertex_buffer_info = {};
|
||||
VmaAllocationCreateInfo create_info = {};
|
||||
|
||||
vertex_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
vertex_buffer_info.pNext = NULL;
|
||||
vertex_buffer_info.flags = 0U;
|
||||
vertex_buffer_info.size = size;
|
||||
vertex_buffer_info.usage = buffer_usage;
|
||||
vertex_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
vertex_buffer_info.queueFamilyIndexCount = 0U;
|
||||
vertex_buffer_info.pQueueFamilyIndices = NULL;
|
||||
|
||||
create_info.flags = allocation_flags;
|
||||
create_info.usage = memory_usage;
|
||||
create_info.memoryTypeBits = 0U;
|
||||
create_info.requiredFlags = 0U;
|
||||
create_info.preferredFlags = 0U;
|
||||
create_info.pool = VK_NULL_HANDLE;
|
||||
create_info.pUserData = VK_NULL_HANDLE;
|
||||
create_info.priority = 0.0f;
|
||||
|
||||
if (VK_SUCCESS != vmaCreateBuffer(g_vulkan_state.allocator,
|
||||
&vertex_buffer_info,
|
||||
&create_info,
|
||||
&buffer->buffer,
|
||||
&buffer->allocation,
|
||||
&buffer->allocation_info)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy one buffer's data to another
|
||||
*
|
||||
* @param src Source buffer
|
||||
* @param dst Destination buffer
|
||||
* @param size Size of buffer to copy
|
||||
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||
*/
|
||||
static uint8_t copy_buffer(VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset)
|
||||
static void copy_buffer(VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset)
|
||||
{
|
||||
/* Vulkan buffers can only be copied using command buffers */
|
||||
VkResult status = VK_FALSE;
|
||||
VkBufferCopy copy_region = {};
|
||||
VkSubmitInfo submit_info = {};
|
||||
VkCommandBuffer copy_command_buffer = NULL;
|
||||
VkCommandBufferBeginInfo begin_info = {};
|
||||
VkCommandBufferAllocateInfo alloc_info = {};
|
||||
VkCommandBuffer command_buffer = {0};
|
||||
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
alloc_info.pNext = NULL;
|
||||
alloc_info.commandPool = g_command_pool;
|
||||
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
alloc_info.commandBufferCount = 1;
|
||||
command_buffer = rse_begin_single_time_command();
|
||||
|
||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
begin_info.pNext = NULL;
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
begin_info.pInheritanceInfo = NULL;
|
||||
|
||||
copy_region.srcOffset = 0;
|
||||
copy_region.srcOffset = 0U;
|
||||
copy_region.dstOffset = dest_offset;
|
||||
copy_region.size = size;
|
||||
|
||||
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submit_info.pNext = NULL;
|
||||
submit_info.waitSemaphoreCount = 0;
|
||||
submit_info.pWaitSemaphores = NULL;
|
||||
submit_info.pWaitDstStageMask = NULL;
|
||||
submit_info.commandBufferCount = 1;
|
||||
submit_info.pCommandBuffers = ©_command_buffer;
|
||||
submit_info.signalSemaphoreCount = 0;
|
||||
submit_info.pSignalSemaphores = NULL;
|
||||
vkCmdCopyBuffer(command_buffer, src, dst, 1, ©_region);
|
||||
|
||||
// FIXME: Add result checks
|
||||
status = vkAllocateCommandBuffers(g_vulkan_state.device, &alloc_info, ©_command_buffer);
|
||||
status = vkBeginCommandBuffer(copy_command_buffer, &begin_info);
|
||||
vkCmdCopyBuffer(copy_command_buffer, src, dst, 1, ©_region);
|
||||
status = vkEndCommandBuffer(copy_command_buffer);
|
||||
status = vkQueueSubmit(g_vulkan_state.graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
/* TODO: Use fences to wait instead of idle */
|
||||
status = vkQueueWaitIdle(g_vulkan_state.graphics_queue);
|
||||
vkFreeCommandBuffers(g_vulkan_state.device, g_command_pool, 1, ©_command_buffer);
|
||||
|
||||
if (status != VK_SUCCESS) {
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
}
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create Command Pools
|
||||
*
|
||||
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||
* VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED
|
||||
*/
|
||||
static uint8_t create_command_pools()
|
||||
{
|
||||
VkCommandPoolCreateInfo create_info;
|
||||
|
||||
create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
create_info.pNext = NULL;
|
||||
create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
create_info.queueFamilyIndex = g_vulkan_state.queue_family_indices[0]; /* TODO: Change when more families are needed */
|
||||
|
||||
if (VK_SUCCESS != vkCreateCommandPool(g_vulkan_state.device, &create_info, NULL, &g_command_pool)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_COMMAND_POOL_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED;
|
||||
}
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
rse_end_single_time_comands(command_buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -262,32 +150,52 @@ static uint8_t create_uniform_buffer()
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate Command Buffers
|
||||
*
|
||||
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||
* VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED
|
||||
*/
|
||||
static uint8_t allocate_command_buffers()
|
||||
uint8_t create_buffer(const VkDeviceSize size,
|
||||
VkBufferUsageFlags buffer_usage,
|
||||
VmaMemoryUsage memory_usage,
|
||||
const VmaAllocationCreateFlags allocation_flags,
|
||||
struct rse_vulkan_buffer_t* buffer)
|
||||
{
|
||||
VkCommandBufferAllocateInfo allocate_info;
|
||||
VkBufferCreateInfo vertex_buffer_info = {};
|
||||
VmaAllocationCreateInfo create_info = {};
|
||||
|
||||
/* Allocate memory for command buffers */
|
||||
allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
allocate_info.pNext = NULL;
|
||||
allocate_info.commandPool = g_command_pool;
|
||||
allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; /* TODO: When needed, add secondary command buffer */
|
||||
allocate_info.commandBufferCount = SWAP_BUFFER_COUNT;
|
||||
vertex_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
vertex_buffer_info.pNext = NULL;
|
||||
vertex_buffer_info.flags = 0U;
|
||||
vertex_buffer_info.size = size;
|
||||
vertex_buffer_info.usage = buffer_usage;
|
||||
vertex_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
vertex_buffer_info.queueFamilyIndexCount = 0U;
|
||||
vertex_buffer_info.pQueueFamilyIndices = NULL;
|
||||
|
||||
if (VK_SUCCESS != vkAllocateCommandBuffers(g_vulkan_state.device,
|
||||
&allocate_info,
|
||||
g_vulkan_state.command_buffers)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED]);
|
||||
return VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED;
|
||||
create_info.flags = allocation_flags;
|
||||
create_info.usage = memory_usage;
|
||||
create_info.memoryTypeBits = 0U;
|
||||
create_info.requiredFlags = 0U;
|
||||
create_info.preferredFlags = 0U;
|
||||
create_info.pool = VK_NULL_HANDLE;
|
||||
create_info.pUserData = VK_NULL_HANDLE;
|
||||
create_info.priority = 0.0f;
|
||||
|
||||
if (VK_SUCCESS != vmaCreateBuffer(g_vulkan_state.allocator,
|
||||
&vertex_buffer_info,
|
||||
&create_info,
|
||||
&buffer->buffer,
|
||||
&buffer->allocation,
|
||||
&buffer->allocation_info)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
void destroy_buffer(struct rse_vulkan_buffer_t* buffer)
|
||||
{
|
||||
vmaDestroyBuffer(g_vulkan_state.allocator, buffer->buffer, buffer->allocation);
|
||||
}
|
||||
|
||||
|
||||
void update_uniform_buffers()
|
||||
{
|
||||
struct rse_uniform_buffer_object_t ubo = {};
|
||||
@@ -492,14 +400,12 @@ uint8_t record_command_buffer(uint32_t image_index)
|
||||
|
||||
uint8_t create_buffers()
|
||||
{
|
||||
uint8_t status = VULKAN_ERROR_NO_ERROR;\
|
||||
uint8_t status = VULKAN_ERROR_NO_ERROR;
|
||||
|
||||
STATUS_CHECK(create_command_pools());
|
||||
STATUS_CHECK(create_vertex_buffer());
|
||||
STATUS_CHECK(create_index_buffer());
|
||||
STATUS_CHECK(create_instance_buffers());
|
||||
STATUS_CHECK(create_uniform_buffer());
|
||||
STATUS_CHECK(allocate_command_buffers());
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -509,6 +415,7 @@ void reset_command_buffer()
|
||||
vkResetCommandBuffer(g_vulkan_state.command_buffers[g_vulkan_state.current_frame], /*VkCommandBufferResetFlagBits*/ 0);
|
||||
}
|
||||
|
||||
|
||||
void destroy_buffers()
|
||||
{
|
||||
size_t i = 0U;
|
||||
@@ -526,6 +433,4 @@ void destroy_buffers()
|
||||
for(i = 0; i < MAX_MESH_NUMBER; ++i) {
|
||||
vmaDestroyBuffer(g_vulkan_state.allocator, g_instance_buffers[i].buffer, g_instance_buffers[i].allocation);
|
||||
}
|
||||
|
||||
vkDestroyCommandPool(g_vulkan_state.device, g_command_pool, NULL);
|
||||
}
|
||||
Reference in new issue
Block a user