Updated to use vertex buffer for color/position of 2d vertices

main
noah metz 2024-01-08 09:44:47 -07:00
parent 3e1cc2ce5a
commit 4e2a8cf156
4 changed files with 149 additions and 27 deletions

1
.gitignore vendored

@ -3,3 +3,4 @@ spacegame
.compdb
compile_commands.json
.cache
*.spv

@ -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;
}

@ -0,0 +1,20 @@
#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)
);
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)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}

@ -7,8 +7,8 @@
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <cglm/mat4.h>
#include <cglm/vec4.h>
#include <cglm/vec3.h>
#include <cglm/vec2.h>
#include <stdio.h>
#include <string.h>
@ -40,6 +40,11 @@ typedef struct SwapchainImagesStruct {
uint32_t count;
} SwapchainImages;
typedef struct AllocatedBufferStruct {
VkBuffer buffer;
VkDeviceMemory memory;
} AllocatedBuffer;
typedef struct VulkanContextStruct {
VkInstance instance;
VkDebugUtilsMessengerEXT debug_messenger;
@ -77,10 +82,22 @@ typedef struct VulkanContextStruct {
VkPipelineLayout triangle_pipeline_layout;
VkPipeline triangle_pipeline;
AllocatedBuffer triangle_buffer;
uint32_t current_frame;
} VulkanContext;
struct Vertex{
vec2 pos;
vec3 color;
};
const struct Vertex vertices[] = {
{.pos = { 0.0f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}},
{.pos = { 0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}},
{.pos = {-0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}},
};
const char * validation_layers[] = {
"VK_LAYER_KHRONOS_validation",
};
@ -103,6 +120,30 @@ void glfw_error(int error, const char* description) {
fprintf(stderr, "GLFW_ERR: 0x%02x - %s\n", error, description);
}
VkVertexInputBindingDescription vertex_bindings[1];
VkVertexInputBindingDescription* vertex_binding_descriptions() {
vertex_bindings[0].binding = 0;
vertex_bindings[0].stride = sizeof(struct Vertex);
vertex_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return vertex_bindings;
}
VkVertexInputAttributeDescription vertex_attributes[2];
VkVertexInputAttributeDescription* vertex_attribute_descriptions() {
vertex_attributes[0].binding = 0;
vertex_attributes[0].location = 0;
vertex_attributes[0].format = VK_FORMAT_R32G32_SFLOAT;
vertex_attributes[0].offset = offsetof(struct Vertex, pos);
vertex_attributes[1].binding = 0;
vertex_attributes[1].location = 1;
vertex_attributes[1].format = VK_FORMAT_R32G32B32_SFLOAT;
vertex_attributes[1].offset = offsetof(struct Vertex, color);
return vertex_attributes;
}
GLFWwindow* init_window(int width, int height) {
glfwInit();
glfwSetErrorCallback(glfw_error);
@ -699,11 +740,69 @@ VkPipelineLayout create_pipeline_layout(VkDevice device, uint32_t set_count, VkD
return layout;
}
uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter, VkMemoryPropertyFlags properties) {
VkPhysicalDeviceMemoryProperties memory_properties;
vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
for(uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) {
if ((type_filter & (1 << i)) && (memory_properties.memoryTypes[i].propertyFlags & properties) == properties) {
return i;
}
}
return 0xFFFFFFFF;
}
AllocatedBuffer create_vertex_buffer(VkPhysicalDevice physical_device, VkDevice device, void* data, uint32_t size) {
AllocatedBuffer allocated_buffer = {};
allocated_buffer.buffer = VK_NULL_HANDLE;
allocated_buffer.memory = VK_NULL_HANDLE;
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size;
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkResult result = vkCreateBuffer(device, &buffer_info, 0, &allocated_buffer.buffer);
if(result != VK_SUCCESS) {
return allocated_buffer;
}
VkMemoryRequirements memory_requirements;
vkGetBufferMemoryRequirements(device, allocated_buffer.buffer, &memory_requirements);
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = memory_requirements.size;
alloc_info.memoryTypeIndex = find_memory_type(physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
result = vkAllocateMemory(device, &alloc_info, 0, &allocated_buffer.memory);
if(result != VK_SUCCESS) {
return allocated_buffer;
}
result = vkBindBufferMemory(device, allocated_buffer.buffer, allocated_buffer.memory, 0);
if(result != VK_SUCCESS) {
return allocated_buffer;
}
void* buffer_data;
result = vkMapMemory(device, allocated_buffer.memory, 0, buffer_info.size, 0, &buffer_data);
if(result != VK_SUCCESS) {
return allocated_buffer;
}
memcpy(buffer_data, data, size);
vkUnmapMemory(device, allocated_buffer.memory);
return allocated_buffer;
}
VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipelineLayout layout, VkRenderPass render_pass) {
VkShaderModule vert_shader = load_shader_file(2048, "vert.spv", device);
fprintf(stderr, "Loaded vert_shader: %p\n", vert_shader);
VkShaderModule frag_shader = load_shader_file(2048, "frag.spv", device);
fprintf(stderr, "Loaded frag_shader: %p\n", frag_shader);
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device);
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device);
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
@ -729,10 +828,10 @@ VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipeli
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_input_info.vertexBindingDescriptionCount = 0;
vertex_input_info.pVertexBindingDescriptions = 0;
vertex_input_info.vertexAttributeDescriptionCount = 0;
vertex_input_info.pVertexAttributeDescriptions = 0;
vertex_input_info.vertexBindingDescriptionCount = 1;
vertex_input_info.pVertexBindingDescriptions = vertex_binding_descriptions();
vertex_input_info.vertexAttributeDescriptionCount = 2;
vertex_input_info.pVertexAttributeDescriptions = vertex_attribute_descriptions();
VkPipelineInputAssemblyStateCreateInfo input_assemvly_info = {};
input_assemvly_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
@ -844,7 +943,7 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) {
return command_pool;
}
VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t image_index, VkRenderPass render_pass, VkFramebuffer* framebuffers, VkExtent2D extent, VkPipeline graphics_pipeline) {
VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t image_index, VkRenderPass render_pass, VkFramebuffer* framebuffers, VkExtent2D extent, VkPipeline graphics_pipeline, VkBuffer vertex_buffer, uint32_t num_vertices) {
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = 0;
@ -869,6 +968,10 @@ VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t
vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline);
VkBuffer vertex_buffers[] = {vertex_buffer};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
@ -884,7 +987,7 @@ VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t
scissor.extent = extent;
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
vkCmdDraw(command_buffer, 3, 1, 0, 0);
vkCmdDraw(command_buffer, num_vertices, 1, 0, 0);
vkCmdEndRenderPass(command_buffer);
return vkEndCommandBuffer(command_buffer);
@ -1114,6 +1217,13 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->triangle_pipeline = triangle_pipeline;
}
AllocatedBuffer triangle_buffer = create_vertex_buffer(context->physical_device, context->device, (void*)vertices, sizeof(vertices));
if(triangle_buffer.memory == VK_NULL_HANDLE) {
fprintf(stderr, "failed to allocate vulkan buffer for triangle buffer\n");
} else {
context->triangle_buffer = triangle_buffer;
}
return context;
}
@ -1140,7 +1250,7 @@ VkResult draw_frame(VulkanContext* context) {
return result;
}
result = record_command_buffer_triangle(context->swapchain_command_buffers[context->current_frame], image_index, context->render_pass, context->swapchain_framebuffers, context->swapchain_extent, context->triangle_pipeline);
result = record_command_buffer_triangle(context->swapchain_command_buffers[context->current_frame], image_index, context->render_pass, context->swapchain_framebuffers, context->swapchain_extent, context->triangle_pipeline, context->triangle_buffer.buffer, 3);
if(result != VK_SUCCESS) {
return result;
}