Use indexed drawing
This commit is contained in:
1 parent
6d8fdb2f8c
commit
c770895217
3 files changed
+102
-38
No files matched your search
@@ -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, ©_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, ©_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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user