Use indexed drawing

This commit is contained in:
Camden Dixie O'Brien committed 2025-09-26 14:30:38 +01:00
1 parent 6d8fdb2f8c
commit c770895217
3 files changed
+102 -38

No files matched your search

+89 -34
View File
@@ -91,6 +91,52 @@ static void create_buffer(
vkBindBufferMemory(ctx->dev, *buf_out, *mem_out, 0);
}
static void load_buffer(
const gpu_ctx_t *ctx, VkBuffer dest_buf, const void *data, size_t size,
VkBuffer staging_buf, VkDeviceMemory staging_buf_mem,
VkCommandPool cmd_pool)
{
VkResult result;
// Copy data to staging buffer
void *staging_buf_ptr;
vkMapMemory(ctx->dev, staging_buf_mem, 0, size, 0, &staging_buf_ptr);
memcpy(staging_buf_ptr, data, size);
vkUnmapMemory(ctx->dev, staging_buf_mem);
// Allocate command buffer
const VkCommandBufferAllocateInfo cmd_buf_config = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = cmd_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
VkCommandBuffer cmd_buf;
result = vkAllocateCommandBuffers(ctx->dev, &cmd_buf_config, &cmd_buf);
assert(result == VK_SUCCESS);
// Record copy command
VkCommandBufferBeginInfo cmd_begin = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
};
vkBeginCommandBuffer(cmd_buf, &cmd_begin);
VkBufferCopy cmd_copy = { .size = size };
vkCmdCopyBuffer(cmd_buf, staging_buf, dest_buf, 1, &cmd_copy);
vkEndCommandBuffer(cmd_buf);
// Send copy command
VkSubmitInfo copy_submit = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &cmd_buf,
};
vkQueueSubmit(ctx->queue, 1, &copy_submit, VK_NULL_HANDLE);
vkQueueWaitIdle(ctx->queue);
vkFreeCommandBuffers(ctx->dev, cmd_pool, 1, &cmd_buf);
}
void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config)
{
// Initialise Vulkan instance.
@@ -342,7 +388,7 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config)
};
const VkPipelineInputAssemblyStateCreateInfo input_assembly_config = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
};
// Set up viewport configuration
@@ -516,48 +562,49 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config)
= vkCreateFence(ctx->dev, &fence_config, nullptr, &ctx->in_flight);
assert(result == VK_SUCCESS);
// Set up staging and vertex buffers
ctx->vertex_data_size = config->vertex_data_size;
// Set up staging, vertex and index buffers
ctx->index_count = config->index_data_size / sizeof(*config->index_data);
VkBuffer staging_buf;
VkDeviceMemory staging_buf_mem;
const size_t staging_buf_size
= MAX(config->vertex_data_size, config->index_data_size);
create_buffer(
ctx, ctx->vertex_data_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
ctx, staging_buf_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&staging_buf, &staging_buf_mem);
create_buffer(
ctx, ctx->vertex_data_size,
ctx, config->vertex_data_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &ctx->vertex_buf,
&ctx->vertex_buf_mem);
create_buffer(
ctx, config->index_data_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &ctx->index_buf,
&ctx->index_buf_mem);
// Copy vertex data into staging buffer
void *staging_buf_ptr;
vkMapMemory(
ctx->dev, staging_buf_mem, 0, ctx->vertex_data_size, 0,
&staging_buf_ptr);
memcpy(staging_buf_ptr, config->vertex_data, ctx->vertex_data_size);
vkUnmapMemory(ctx->dev, staging_buf_mem);
// Copy staging buffer to vertex buffer
VkCommandBufferBeginInfo cmd_begin = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
// Create transient command pool
const VkCommandPoolCreateInfo transient_cmd_pool_config = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
.queueFamilyIndex = queue_family,
};
vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin);
VkBufferCopy cmd_copy = { .size = ctx->vertex_data_size };
vkCmdCopyBuffer(
ctx->cmd_buf, staging_buf, ctx->vertex_buf, 1, &cmd_copy);
vkEndCommandBuffer(ctx->cmd_buf);
VkSubmitInfo copy_submit = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &ctx->cmd_buf,
};
vkQueueSubmit(ctx->queue, 1, &copy_submit, VK_NULL_HANDLE);
vkQueueWaitIdle(ctx->queue);
VkCommandPool transient_cmd_pool;
result = vkCreateCommandPool(
ctx->dev, &transient_cmd_pool_config, nullptr, &transient_cmd_pool);
assert(result == VK_SUCCESS);
// Clean up staging buffer
// Load vertex and index data
load_buffer(
ctx, ctx->vertex_buf, config->vertex_data, config->vertex_data_size,
staging_buf, staging_buf_mem, transient_cmd_pool);
load_buffer(
ctx, ctx->index_buf, config->index_data, config->index_data_size,
staging_buf, staging_buf_mem, transient_cmd_pool);
// Clean up staging buffer and transient command pool
vkDestroyCommandPool(ctx->dev, transient_cmd_pool, nullptr);
vkDestroyBuffer(ctx->dev, staging_buf, nullptr);
vkFreeMemory(ctx->dev, staging_buf_mem, nullptr);
}
@@ -566,22 +613,29 @@ void gpu_cleanup(const gpu_ctx_t *ctx)
{
vkDeviceWaitIdle(ctx->dev);
vkDestroyBuffer(ctx->dev, ctx->index_buf, nullptr);
vkFreeMemory(ctx->dev, ctx->index_buf_mem, nullptr);
vkDestroyBuffer(ctx->dev, ctx->vertex_buf, nullptr);
vkFreeMemory(ctx->dev, ctx->vertex_buf_mem, nullptr);
vkDestroySemaphore(ctx->dev, ctx->img_avail, nullptr);
vkDestroySemaphore(ctx->dev, ctx->render_fin, nullptr);
vkDestroyFence(ctx->dev, ctx->in_flight, nullptr);
vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, nullptr);
vkDestroyPipeline(ctx->dev, ctx->pipeline, nullptr);
vkDestroyRenderPass(ctx->dev, ctx->render_pass, nullptr);
vkDestroyPipelineLayout(ctx->dev, ctx->pipeline_layout, nullptr);
vkDestroyShaderModule(ctx->dev, ctx->vert_shader, nullptr);
vkDestroyShaderModule(ctx->dev, ctx->frag_shader, nullptr);
for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) {
vkDestroyFramebuffer(ctx->dev, ctx->framebuffers[i], nullptr);
vkDestroyImageView(ctx->dev, ctx->swapchain_img_views[i], nullptr);
}
vkDestroySwapchainKHR(ctx->dev, ctx->swapchain, nullptr);
vkDestroyDevice(ctx->dev, nullptr);
vkDestroySurfaceKHR(ctx->inst, ctx->surface, nullptr);
vkDestroyInstance(ctx->inst, nullptr);
@@ -622,14 +676,15 @@ void gpu_render(const gpu_ctx_t *ctx)
};
vkCmdBeginRenderPass(
ctx->cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
// Bind graphics pipeline and vertex buffer, then draw
vkCmdBindPipeline(
ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pipeline);
// Bind vertex and index buffers then draw
vkCmdBindVertexBuffers(
ctx->cmd_buf, 0, 1, &ctx->vertex_buf, &(VkDeviceSize) { 0 });
vkCmdDraw(
ctx->cmd_buf, ctx->vertex_data_size / sizeof(vertex_t), 1, 0, 0);
vkCmdBindIndexBuffer(
ctx->cmd_buf, ctx->index_buf, 0, VK_INDEX_TYPE_UINT16);
vkCmdDrawIndexed(ctx->cmd_buf, ctx->index_count, 1, 0, 0, 0);
// Finish render pass and end writing to command buffer
vkCmdEndRenderPass(ctx->cmd_buf);
+5 -1
View File
@@ -31,9 +31,11 @@ typedef struct {
VkFence in_flight;
VkSemaphore render_fin;
VkSemaphore img_avail;
size_t vertex_data_size;
VkBuffer vertex_buf;
VkDeviceMemory vertex_buf_mem;
VkBuffer index_buf;
VkDeviceMemory index_buf_mem;
size_t index_count;
} gpu_ctx_t;
typedef struct {
@@ -41,6 +43,8 @@ typedef struct {
GLFWwindow *window;
const vertex_t *vertex_data;
size_t vertex_data_size;
const uint16_t *index_data;
size_t index_data_size;
} gpu_config_t;
void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config);
+8 -3
View File
@@ -4,11 +4,14 @@
#include <math.h>
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 } },
{ { -0.5, -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 } },
{ { -0.5, 0.5 }, { 1.0, 1.0, 1.0 } },
};
static const uint16_t indices[] = { 0, 1, 2, 2, 3, 0 };
static void
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
@@ -42,6 +45,8 @@ int main()
.window = window,
.vertex_data = vertices,
.vertex_data_size = sizeof(vertices),
.index_data = indices,
.index_data_size = sizeof(indices),
};
gpu_ctx_t gpu;
gpu_init(&gpu, &gpu_config);