summaryrefslogtreecommitdiff
path: root/src/graphics.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics.c')
-rw-r--r--src/graphics.c145
1 files changed, 136 insertions, 9 deletions
diff --git a/src/graphics.c b/src/graphics.c
index 8da9c43..0e77c3a 100644
--- a/src/graphics.c
+++ b/src/graphics.c
@@ -1,10 +1,17 @@
#include <string.h>
#include <errno.h>
+#include <cglm/cglm.h>
#include <vulkan/vulkan.h>
#include "graphics.h"
#include "common.h"
+// TODO: finish buffer_copy
+
+// TODO: explicitly make a transfer queue for
+// the buffer staging/copying
+// TODO: vkAllocateMemory shouldn't be called for every buffer,
+// a memory allocator should be used (the offset parameter)
// TODO: add more error checking
// TODO: add log output
// TODO: check for memory leaks
@@ -62,11 +69,12 @@ static int create_physical_device(graphics_t graphics, struct graphics_info *inf
static int create_logical_device(graphics_t graphics, struct graphics_info *info);
static int create_pipeline(graphics_t graphics, struct graphics_info *info);
static int create_swap_chain(graphics_t graphics, struct graphics_info *info);
+static int create_vertex_buffer(graphics_t graphics, struct graphics_info *info);
static int create_command_pool(graphics_t graphics, struct graphics_info *info);
static int create_sync_objects(graphics_t graphics, struct graphics_info *info);
-static void destroy_swap_chain(graphics_t graphics);
static void destroy_pipeline(graphics_t graphics);
+static void destroy_swap_chain(graphics_t graphics);
// static void destroy_command_pool(graphics_t graphics);
static void destroy_sync_objects(graphics_t graphics);
@@ -92,6 +100,16 @@ static int command_buffer_record(graphics_t graphics, u32 image_index);
#define SYNC graphics->sync
+#define VBFF graphics->vertex_buffer
+static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding_desc, VkVertexInputAttributeDescription *attribute_desc);
+
+static int buffer_create(VkDevice device, VkPhysicalDevice physical_device,
+ VkDeviceSize size, VkBufferUsageFlags usageflg,
+ VkMemoryPropertyFlags propflg, buffer_t *buffer);
+static void buffer_destroy(VkDevice device, buffer_t buffer);
+static int buffer_copy(VkBuffer dest, VkBuffer, VkBuffer src, VkDeviceSize size, VkDevice devie, VkCommandPool pool, u32 queue_idx);
+static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx);
+
F_LOAD_FILE_ALIGNED(u32) // from config.h
// --- Debug Functions ---
@@ -127,7 +145,6 @@ graphics_t graphics_create(struct graphics_info *info)
graphics->instance = VK_NULL_HANDLE;
graphics->logical_device = VK_NULL_HANDLE;
-
PPLN.pipeline = VK_NULL_HANDLE;
PPLN.layout = VK_NULL_HANDLE;
PPLN.render_pass = VK_NULL_HANDLE;
@@ -140,6 +157,9 @@ graphics_t graphics_create(struct graphics_info *info)
SYNC.semph_image_available = VK_NULL_HANDLE;
SYNC.semph_render_finished = VK_NULL_HANDLE;
SYNC.fence_inflight = VK_NULL_HANDLE;
+
+ VBFF.buffer = VK_NULL_HANDLE;
+ VBFF.memory = VK_NULL_HANDLE;
CCHECK(create_instance);
CCHECK(create_surface);
@@ -150,6 +170,7 @@ graphics_t graphics_create(struct graphics_info *info)
CCHECK(create_logical_device);
CCHECK(create_pipeline);
CCHECK(create_swap_chain);
+ CCHECK(create_vertex_buffer);
CCHECK(create_command_pool);
CCHECK(create_sync_objects);
@@ -168,6 +189,8 @@ void graphics_destroy(graphics_t graphics)
destroy_sync_objects(graphics);
vkDestroyCommandPool(graphics->logical_device, CMND.pool, NULL);
+
+ buffer_destroy(graphics->logical_device, VBFF);
destroy_swap_chain(graphics);
destroy_pipeline(graphics);
@@ -599,13 +622,17 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info)
dynamic_state.dynamicStateCount = ARR_SIZE(dynamic_states);
dynamic_state.pDynamicStates = dynamic_states;
- // vertex things - hard coded (for now)
+ // vertex things
+ VkVertexInputBindingDescription binding_description = {0};
+ VkVertexInputAttributeDescription attribute_description[2] = {0};
+ vertex_populate_descriptions(&binding_description, attribute_description);
+
VkPipelineVertexInputStateCreateInfo vertex_input = {0};
vertex_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertex_input.vertexBindingDescriptionCount = 0;
- vertex_input.pVertexBindingDescriptions = NULL;
- vertex_input.vertexAttributeDescriptionCount = 0;
- vertex_input.pVertexAttributeDescriptions = NULL;
+ vertex_input.vertexBindingDescriptionCount = 1;
+ vertex_input.pVertexBindingDescriptions = &binding_description;
+ vertex_input.vertexAttributeDescriptionCount = ARR_SIZE(attribute_description);
+ vertex_input.pVertexAttributeDescriptions = attribute_description;
VkPipelineInputAssemblyStateCreateInfo input_assembly = {0};
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
@@ -814,6 +841,28 @@ static void destroy_sync_objects(graphics_t graphics)
vkDestroyFence(graphics->logical_device, SYNC.fence_inflight, NULL);
}
+static int create_vertex_buffer(graphics_t graphics, struct graphics_info *info)
+{
+ (void)info;
+ int ret = 1;
+
+ size_t size = sizeof(*info->vertices) * info->nvertices;
+
+ buffer_create(graphics->logical_device, graphics->physical_device,
+ size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+ (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), &VBFF);
+
+ void *data;
+ vkMapMemory(graphics->logical_device, VBFF.memory, 0, size, 0, &data);
+ memcpy(data, info->vertices, size);
+ vkUnmapMemory(graphics->logical_device, VBFF.memory);
+
+ ret = 0;
+exit:
+ return ret;
+}
+
static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family)
{
u32 count = 0;
@@ -1003,6 +1052,10 @@ static int command_buffer_record(graphics_t graphics, u32 image_index)
// Begin the drawing commands
vkCmdBindPipeline(CMND.buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PPLN.pipeline);
+ VkBuffer vertex_buffers[] = { VBFF.buffer };
+ VkDeviceSize offsets[] = {0};
+ vkCmdBindVertexBuffers(CMND.buffer, 0, 1, vertex_buffers, offsets);
+
VkViewport viewport = {0};
viewport.x = 0.0f;
viewport.y = 0.0f;
@@ -1018,8 +1071,8 @@ static int command_buffer_record(graphics_t graphics, u32 image_index)
scissor.extent = SWCH.extent;
vkCmdSetScissor(CMND.buffer, 0, 1, &scissor);
- // 3 vertices, 1 instance (for instanced rendering)
- // 0 is the first vertex, 0 is the fist instance
+ // 3 is the number of vertices
+ // TODO: fix this
vkCmdDraw(CMND.buffer, 3, 1, 0, 0);
// Cleaning up
@@ -1032,6 +1085,80 @@ exit:
return ret;
}
+static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding_desc, VkVertexInputAttributeDescription *attribute_desc)
+{
+ binding_desc->binding = 0;
+ binding_desc->stride = sizeof(struct vertex);
+ binding_desc->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+
+ attribute_desc[0].binding = 0;
+ attribute_desc[0].location = 0;
+ attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT;
+ attribute_desc[0].offset = offsetof(struct vertex, pos);
+
+ attribute_desc[1].binding = 0;
+ attribute_desc[1].location = 1;
+ attribute_desc[1].format = VK_FORMAT_R32G32B32_SFLOAT;
+ attribute_desc[1].offset = offsetof(struct vertex, color);
+
+ return 0;
+}
+
+static int buffer_create(VkDevice device, VkPhysicalDevice physical_device,
+ VkDeviceSize size, VkBufferUsageFlags usageflg,
+ VkMemoryPropertyFlags propflg, buffer_t *buffer)
+{
+ int ret = 1;
+
+ VkBufferCreateInfo buffer_info = {0};
+ buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buffer_info.size = size;
+ buffer_info.usage = usageflg;
+ buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+ VCHECK(vkCreateBuffer, device, &buffer_info, NULL, &buffer->buffer);
+
+ VkMemoryRequirements memory_requirements;
+ vkGetBufferMemoryRequirements(device, buffer->buffer, &memory_requirements);
+
+ VkMemoryAllocateInfo allocate_info = {0};
+ allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocate_info.allocationSize = memory_requirements.size;
+
+ u32 memory_type_idx;
+ buffer_find_memory_type(physical_device, memory_requirements.memoryTypeBits, propflg, &memory_type_idx);
+ allocate_info.memoryTypeIndex = memory_type_idx;
+
+ VCHECK(vkAllocateMemory, device, &allocate_info, NULL, &buffer->memory);
+ VCHECK(vkBindBufferMemory, device, buffer->buffer, buffer->memory, 0);
+
+ ret = 0;
+exit:
+ return ret;
+}
+
+static void buffer_destroy(VkDevice device, buffer_t buffer)
+{
+ vkDestroyBuffer(device, buffer.buffer, NULL);
+ vkFreeMemory(device, buffer.memory, NULL);
+}
+
+static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx)
+{
+ VkPhysicalDeviceMemoryProperties properties;
+ vkGetPhysicalDeviceMemoryProperties(device, &properties);
+
+ for(u32 i = 0; i < properties.memoryTypeCount; i++) {
+ if((type_filter & (i << i)) && ((properties.memoryTypes[i].propertyFlags & flags) == flags)) {
+ *memory_type_idx = i;
+ return 0;
+ }
+ }
+
+ err("No suitable memory type was found");
+ return 1;
+}
+
#define X_VK_RESULT_TABLE(X) \
X(VK_SUCCESS) \
X(VK_NOT_READY) \