Pass vertices through buffer instead of hard-coding

This commit is contained in:
Camden Dixie O'Brien committed 2025-09-25 18:21:29 +01:00
1 parent cf7a0f099a
commit 51c01a2f9e
2 files changed
+99 -16

No files matched your search

+95 -3
View File
@@ -11,6 +11,8 @@
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define CLAMP(x, min, max) MAX((min), MIN(x, (max)))
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
#define QUEUE_FAMILY_PROP_BUFFER_SIZE 16
#define EXT_PROP_BUFFER_SIZE 256
#define SURFACE_FMT_BUFFER_SIZE 64
@@ -19,6 +21,10 @@
#define MAX_SHADER_SIZE (8 * 1024)
typedef struct {
float position[2], colour[3];
} vertex_t;
static const char *layers[] = { "VK_LAYER_KHRONOS_validation" };
static const char *extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
@@ -32,7 +38,13 @@ static const char frag_shader_code[] = {
#embed FRAG_SHADER_SPV
};
#define NEXTENSIONS (sizeof(extensions) / sizeof(extensions[0]))
static const vertex_t vertices[] = {
{ { 0.0, -0.5 }, { 1.0, 0.0, 0.0 } },
{ { 0.5, 0.5 }, { 0.0, 1.0, 0.0 } },
{ { -0.5, 0.5 }, { 0.0, 0.0, 1.0 } },
};
#define NEXTENSIONS NELEMS(extensions)
static void
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
@@ -297,8 +309,33 @@ int main()
};
// Set up input configuration
const VkVertexInputBindingDescription input_binding_descs[] = {
{
.binding = 0,
.stride = sizeof(vertex_t),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
},
};
const VkVertexInputAttributeDescription input_attribute_descs[] = {
{
.binding = 0,
.location = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(vertex_t, position),
},
{
.binding = 0,
.location = 1,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(vertex_t, colour),
},
};
const VkPipelineVertexInputStateCreateInfo vertex_input_config = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = NELEMS(input_binding_descs),
.pVertexBindingDescriptions = input_binding_descs,
.vertexAttributeDescriptionCount = NELEMS(input_attribute_descs),
.pVertexAttributeDescriptions = input_attribute_descs,
};
const VkPipelineInputAssemblyStateCreateInfo input_assembly_config = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
@@ -440,6 +477,57 @@ int main()
assert(result == VK_SUCCESS);
}
// Create vertex buffer
const VkBufferCreateInfo vertex_buffer_config = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = sizeof(vertices),
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
VkBuffer vertex_buffer;
result = vkCreateBuffer(
dev, &vertex_buffer_config, nullptr, &vertex_buffer);
assert(result == VK_SUCCESS);
// Allocate memory to vertex buffer
const VkMemoryPropertyFlags mem_flags
= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
VkMemoryRequirements mem_requirements;
vkGetBufferMemoryRequirements(dev, vertex_buffer, &mem_requirements);
VkPhysicalDeviceMemoryProperties mem_props;
vkGetPhysicalDeviceMemoryProperties(physical_dev, &mem_props);
uint32_t mem_type = UINT32_MAX;
for (unsigned i = 0; i < mem_props.memoryTypeCount; ++i) {
const bool valid_type
= (mem_requirements.memoryTypeBits & (1 << i)) != 0;
const bool has_flags
= (mem_props.memoryTypes[i].propertyFlags & mem_flags)
== mem_flags;
if (valid_type && has_flags) {
mem_type = i;
break;
}
}
assert(mem_type != UINT32_MAX);
VkMemoryAllocateInfo allocate_config = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = mem_requirements.size,
.memoryTypeIndex = mem_type,
};
VkDeviceMemory vertex_buffer_mem;
result = vkAllocateMemory(
dev, &allocate_config, nullptr, &vertex_buffer_mem);
assert(result == VK_SUCCESS);
vkBindBufferMemory(dev, vertex_buffer, vertex_buffer_mem, 0);
// Copy vertex data into vertex buffer
void *vertex_data;
vkMapMemory(
dev, vertex_buffer_mem, 0, sizeof(vertices), 0, &vertex_data);
memcpy(vertex_data, vertices, sizeof(vertices));
vkUnmapMemory(dev, vertex_buffer_mem);
// Create command pool
const VkCommandPoolCreateInfo cmd_pool_config = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
@@ -512,10 +600,12 @@ int main()
vkCmdBeginRenderPass(
cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
// Bind graphics pipeline and draw
// Bind graphics pipeline and vertex buffer, then draw
vkCmdBindPipeline(
cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdDraw(cmd_buf, 4, 1, 0, 0);
vkCmdBindVertexBuffers(
cmd_buf, 0, 1, &vertex_buffer, &(VkDeviceSize) { 0 });
vkCmdDraw(cmd_buf, NELEMS(vertices), 1, 0, 0);
// Finish render pass and end writing to command buffer
vkCmdEndRenderPass(cmd_buf);
@@ -568,6 +658,8 @@ int main()
vkDestroyImageView(dev, swapchain_img_views[i], nullptr);
}
vkDestroySwapchainKHR(dev, swapchain, nullptr);
vkDestroyBuffer(dev, vertex_buffer, nullptr);
vkFreeMemory(dev, vertex_buffer_mem, nullptr);
vkDestroyDevice(dev, nullptr);
vkDestroySurfaceKHR(inst, surface, nullptr);
vkDestroyInstance(inst, nullptr);
+4 -13
View File
@@ -1,20 +1,11 @@
#version 450
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
vec3 colours[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) in vec2 position;
layout(location = 1) in vec3 colour;
layout(location = 0) out vec3 frag_colour;
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
frag_colour = colours[gl_VertexIndex];
gl_Position = vec4(position, 0.0, 1.0);
frag_colour = colour;
}