From 920328d35a3d5a95a9bc4cb60ce36aeee3f64f85 Mon Sep 17 00:00:00 2001 From: Amber Date: Wed, 26 Oct 2022 11:41:10 +0200 Subject: [PATCH] Use vertex buffers. --- src/main.c | 95 +++++++++++++++++++++++++++++++++++++++--- src/vertex_simple.vert | 19 +++------ 2 files changed, 94 insertions(+), 20 deletions(-) diff --git a/src/main.c b/src/main.c index 8891e5f..83b463a 100644 --- a/src/main.c +++ b/src/main.c @@ -6,6 +6,7 @@ #include #include #include +#include #define WIDTH 2560 #define HEIGHT 1440 @@ -69,6 +70,9 @@ typedef struct ApplicationState { VkSemaphore image_available_semaph[MAX_FRAMES_IN_FLIGHT]; VkSemaphore render_finished_sempah[MAX_FRAMES_IN_FLIGHT]; VkFence in_flight_frames[MAX_FRAMES_IN_FLIGHT]; + + VkBuffer vertex_buffer; + VkDeviceMemory vertex_buffer_memory; } ApplicationState; typedef struct QueueFamilyIndices { @@ -78,6 +82,17 @@ typedef struct QueueFamilyIndices { uint32_t present_queue; } QueueFamilyIndices; +typedef struct Vertex { + vec2 position; + vec3 color; +} Vertex; + +const Vertex vertices[] = { + {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, + {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, + {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} +}; + void create_window(ApplicationState* state) { glfwInit(); @@ -692,15 +707,27 @@ void create_graphics_pipeline(ApplicationState* state) { dynamic_state.dynamicStateCount = ARRSIZE(dynamic_states); dynamic_state.pDynamicStates = dynamic_states; + VkVertexInputBindingDescription binding = { + .binding = 0, + .stride = sizeof(Vertex), + .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, + }; + + //We have position and color, so we need two descriptions + VkVertexInputAttributeDescription attribute_description[2] = { + {.binding = 0, .location = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(Vertex, position)}, + {.binding = 0, .location = 1, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(Vertex, color)}, + }; + //vertex input format //bindings: spacing between data, what data is per-vertex and what data is per instance //attribute types, which bindings to load them from and at which offset VkPipelineVertexInputStateCreateInfo vertex_input_info = {0}; vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_info.vertexBindingDescriptionCount = 0; - vertex_input_info.pVertexBindingDescriptions = NULL; - vertex_input_info.vertexAttributeDescriptionCount = 0; - vertex_input_info.pVertexAttributeDescriptions = NULL; + vertex_input_info.vertexBindingDescriptionCount = 1; + vertex_input_info.pVertexBindingDescriptions = &binding; + vertex_input_info.vertexAttributeDescriptionCount = ARRSIZE(attribute_description); + vertex_input_info.pVertexAttributeDescriptions = attribute_description; //input assembly //type of geometry and primitive restart, which allows one to break lines and triangles @@ -862,13 +889,61 @@ void create_command_pool(ApplicationState* state) { pool_info.queueFamilyIndex = families.graphics_queue; if (vkCreateCommandPool(state->device, &pool_info, NULL, &state->commandPool) != VK_SUCCESS) { - printf("failed to create command pool"); + printf("failed to create command pool\n"); exit(1); } printf("created command pools\n"); } +uint32_t find_memory_type (ApplicationState* state, uint32_t type_filter, VkMemoryPropertyFlags props) { + VkPhysicalDeviceMemoryProperties mem_props; + vkGetPhysicalDeviceMemoryProperties(state->physical_device, &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 i; + } + } + + printf("no suitable memory type\n"); + exit(1); +} + +void create_vertex_buffer(ApplicationState* state) { + VkBufferCreateInfo buffer_info = {0}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = sizeof(Vertex) * ARRSIZE(vertices); + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + if (vkCreateBuffer(state->device, &buffer_info, NULL, &state->vertex_buffer) != VK_SUCCESS) { + printf("Failed to create vertex buffer\n"); + exit(1); + } + + VkMemoryRequirements mem_req; + vkGetBufferMemoryRequirements(state->device, state->vertex_buffer, &mem_req); + + VkMemoryAllocateInfo alloc_info = {0}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = mem_req.size; + alloc_info.memoryTypeIndex = find_memory_type(state, mem_req.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + if (vkAllocateMemory(state->device, &alloc_info, NULL, &state->vertex_buffer_memory) != VK_SUCCESS) { + printf("failed to allocate memory for buffer\n"); + exit(1); + } + + vkBindBufferMemory(state->device, state->vertex_buffer, state->vertex_buffer_memory, 0); + + void* data; + vkMapMemory(state->device, state->vertex_buffer_memory, 0, buffer_info.size, 0, &data); + memcpy(data, vertices, buffer_info.size); + vkUnmapMemory(state->device, state->vertex_buffer_memory); +} + void create_command_buffer(ApplicationState* state) { VkCommandBufferAllocateInfo command_buf_allocate_info = {0}; command_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; @@ -916,6 +991,10 @@ void record_command_buffer(ApplicationState* state, VkCommandBuffer command_buff vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, state->graphics_pipeline); + VkBuffer vertex_buffers[] = {state->vertex_buffer}; + VkDeviceSize offsets[] = {0}; + vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); + //setup dynamic state VkViewport viewport = {0}; viewport.x = 0.0f; @@ -935,7 +1014,7 @@ void record_command_buffer(ApplicationState* state, VkCommandBuffer command_buff vkCmdSetScissor(command_buffer, 0, 1, &scissor); //vertex count, instance count, first vertex and first instance - vkCmdDraw(command_buffer, 3, 1, 0, 0); + vkCmdDraw(command_buffer, ARRSIZE(vertices), 1, 0, 0); vkCmdEndRenderPass(command_buffer); @@ -977,6 +1056,7 @@ void init_vulkan(ApplicationState* state) { create_graphics_pipeline(state); create_framebuffers(state); create_command_pool(state); + create_vertex_buffer(state); create_command_buffer(state); create_sync_objects(state); } @@ -1057,6 +1137,9 @@ void terminate(ApplicationState* state) { for (int i = 0; i < state->swapchain_image_count; i++) { vkDestroyImageView(state->device, state->swapchain_image_views[i], NULL); } + vkDestroyBuffer(state->device, state->vertex_buffer, NULL); + vkFreeMemory(state->device, state->vertex_buffer_memory, NULL); + vkDestroySwapchainKHR(state->device, state->swapchain, NULL); vkDestroyDevice(state->device, NULL); vkDestroySurfaceKHR(state->instance, state->surface, NULL); diff --git a/src/vertex_simple.vert b/src/vertex_simple.vert index f5b2f8d..2f02ab1 100644 --- a/src/vertex_simple.vert +++ b/src/vertex_simple.vert @@ -1,20 +1,11 @@ #version 450 -layout(location = 0) out vec3 fragColor; - -vec2 positions[3] = vec2[]( - vec2(0.0, -0.5), - vec2(0.5, 0.5), - vec2(-0.5, 0.5) -); +layout (location = 0) in vec2 inPosition; +layout (location = 1) in vec3 inColor; -vec3 colors[3] = vec3[]( - vec3(1.0, 0.0, 0.0), - vec3(0.0, 1.0, 0.0), - vec3(0.0, 0.0, 1.0) -); +layout(location = 0) out vec3 fragColor; void main() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - fragColor = colors[gl_VertexIndex]; + gl_Position = vec4(inPosition, 0.0, 1.0); + fragColor = inColor; }