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);
|
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)
|
void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config)
|
||||||
{
|
{
|
||||||
// Initialise Vulkan instance.
|
// Initialise Vulkan instance.
|
||||||
@@ -342,7 +388,7 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config)
|
|||||||
};
|
};
|
||||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_config = {
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_config = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.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
|
// 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);
|
= vkCreateFence(ctx->dev, &fence_config, nullptr, &ctx->in_flight);
|
||||||
assert(result == VK_SUCCESS);
|
assert(result == VK_SUCCESS);
|
||||||
|
|
||||||
// Set up staging and vertex buffers
|
// Set up staging, vertex and index buffers
|
||||||
ctx->vertex_data_size = config->vertex_data_size;
|
ctx->index_count = config->index_data_size / sizeof(*config->index_data);
|
||||||
VkBuffer staging_buf;
|
VkBuffer staging_buf;
|
||||||
VkDeviceMemory staging_buf_mem;
|
VkDeviceMemory staging_buf_mem;
|
||||||
|
const size_t staging_buf_size
|
||||||
|
= MAX(config->vertex_data_size, config->index_data_size);
|
||||||
create_buffer(
|
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_VISIBLE_BIT
|
||||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||||
&staging_buf, &staging_buf_mem);
|
&staging_buf, &staging_buf_mem);
|
||||||
create_buffer(
|
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_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &ctx->vertex_buf,
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &ctx->vertex_buf,
|
||||||
&ctx->vertex_buf_mem);
|
&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
|
// Create transient command pool
|
||||||
void *staging_buf_ptr;
|
const VkCommandPoolCreateInfo transient_cmd_pool_config = {
|
||||||
vkMapMemory(
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
ctx->dev, staging_buf_mem, 0, ctx->vertex_data_size, 0,
|
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
|
||||||
&staging_buf_ptr);
|
.queueFamilyIndex = queue_family,
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin);
|
VkCommandPool transient_cmd_pool;
|
||||||
VkBufferCopy cmd_copy = { .size = ctx->vertex_data_size };
|
result = vkCreateCommandPool(
|
||||||
vkCmdCopyBuffer(
|
ctx->dev, &transient_cmd_pool_config, nullptr, &transient_cmd_pool);
|
||||||
ctx->cmd_buf, staging_buf, ctx->vertex_buf, 1, &cmd_copy);
|
assert(result == VK_SUCCESS);
|
||||||
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);
|
|
||||||
|
|
||||||
// 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);
|
vkDestroyBuffer(ctx->dev, staging_buf, nullptr);
|
||||||
vkFreeMemory(ctx->dev, staging_buf_mem, nullptr);
|
vkFreeMemory(ctx->dev, staging_buf_mem, nullptr);
|
||||||
}
|
}
|
||||||
@@ -566,22 +613,29 @@ void gpu_cleanup(const gpu_ctx_t *ctx)
|
|||||||
{
|
{
|
||||||
vkDeviceWaitIdle(ctx->dev);
|
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);
|
vkDestroyBuffer(ctx->dev, ctx->vertex_buf, nullptr);
|
||||||
vkFreeMemory(ctx->dev, ctx->vertex_buf_mem, nullptr);
|
vkFreeMemory(ctx->dev, ctx->vertex_buf_mem, nullptr);
|
||||||
|
|
||||||
vkDestroySemaphore(ctx->dev, ctx->img_avail, nullptr);
|
vkDestroySemaphore(ctx->dev, ctx->img_avail, nullptr);
|
||||||
vkDestroySemaphore(ctx->dev, ctx->render_fin, nullptr);
|
vkDestroySemaphore(ctx->dev, ctx->render_fin, nullptr);
|
||||||
vkDestroyFence(ctx->dev, ctx->in_flight, nullptr);
|
vkDestroyFence(ctx->dev, ctx->in_flight, nullptr);
|
||||||
|
|
||||||
vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, nullptr);
|
vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, nullptr);
|
||||||
|
|
||||||
vkDestroyPipeline(ctx->dev, ctx->pipeline, nullptr);
|
vkDestroyPipeline(ctx->dev, ctx->pipeline, nullptr);
|
||||||
vkDestroyRenderPass(ctx->dev, ctx->render_pass, nullptr);
|
vkDestroyRenderPass(ctx->dev, ctx->render_pass, nullptr);
|
||||||
vkDestroyPipelineLayout(ctx->dev, ctx->pipeline_layout, nullptr);
|
vkDestroyPipelineLayout(ctx->dev, ctx->pipeline_layout, nullptr);
|
||||||
vkDestroyShaderModule(ctx->dev, ctx->vert_shader, nullptr);
|
vkDestroyShaderModule(ctx->dev, ctx->vert_shader, nullptr);
|
||||||
vkDestroyShaderModule(ctx->dev, ctx->frag_shader, nullptr);
|
vkDestroyShaderModule(ctx->dev, ctx->frag_shader, nullptr);
|
||||||
|
|
||||||
for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) {
|
for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) {
|
||||||
vkDestroyFramebuffer(ctx->dev, ctx->framebuffers[i], nullptr);
|
vkDestroyFramebuffer(ctx->dev, ctx->framebuffers[i], nullptr);
|
||||||
vkDestroyImageView(ctx->dev, ctx->swapchain_img_views[i], nullptr);
|
vkDestroyImageView(ctx->dev, ctx->swapchain_img_views[i], nullptr);
|
||||||
}
|
}
|
||||||
vkDestroySwapchainKHR(ctx->dev, ctx->swapchain, nullptr);
|
vkDestroySwapchainKHR(ctx->dev, ctx->swapchain, nullptr);
|
||||||
|
|
||||||
vkDestroyDevice(ctx->dev, nullptr);
|
vkDestroyDevice(ctx->dev, nullptr);
|
||||||
vkDestroySurfaceKHR(ctx->inst, ctx->surface, nullptr);
|
vkDestroySurfaceKHR(ctx->inst, ctx->surface, nullptr);
|
||||||
vkDestroyInstance(ctx->inst, nullptr);
|
vkDestroyInstance(ctx->inst, nullptr);
|
||||||
@@ -622,14 +676,15 @@ void gpu_render(const gpu_ctx_t *ctx)
|
|||||||
};
|
};
|
||||||
vkCmdBeginRenderPass(
|
vkCmdBeginRenderPass(
|
||||||
ctx->cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
|
ctx->cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
// Bind graphics pipeline and vertex buffer, then draw
|
|
||||||
vkCmdBindPipeline(
|
vkCmdBindPipeline(
|
||||||
ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pipeline);
|
ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pipeline);
|
||||||
|
|
||||||
|
// Bind vertex and index buffers then draw
|
||||||
vkCmdBindVertexBuffers(
|
vkCmdBindVertexBuffers(
|
||||||
ctx->cmd_buf, 0, 1, &ctx->vertex_buf, &(VkDeviceSize) { 0 });
|
ctx->cmd_buf, 0, 1, &ctx->vertex_buf, &(VkDeviceSize) { 0 });
|
||||||
vkCmdDraw(
|
vkCmdBindIndexBuffer(
|
||||||
ctx->cmd_buf, ctx->vertex_data_size / sizeof(vertex_t), 1, 0, 0);
|
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
|
// Finish render pass and end writing to command buffer
|
||||||
vkCmdEndRenderPass(ctx->cmd_buf);
|
vkCmdEndRenderPass(ctx->cmd_buf);
|
||||||
|
|||||||
@@ -31,9 +31,11 @@ typedef struct {
|
|||||||
VkFence in_flight;
|
VkFence in_flight;
|
||||||
VkSemaphore render_fin;
|
VkSemaphore render_fin;
|
||||||
VkSemaphore img_avail;
|
VkSemaphore img_avail;
|
||||||
size_t vertex_data_size;
|
|
||||||
VkBuffer vertex_buf;
|
VkBuffer vertex_buf;
|
||||||
VkDeviceMemory vertex_buf_mem;
|
VkDeviceMemory vertex_buf_mem;
|
||||||
|
VkBuffer index_buf;
|
||||||
|
VkDeviceMemory index_buf_mem;
|
||||||
|
size_t index_count;
|
||||||
} gpu_ctx_t;
|
} gpu_ctx_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -41,6 +43,8 @@ typedef struct {
|
|||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
const vertex_t *vertex_data;
|
const vertex_t *vertex_data;
|
||||||
size_t vertex_data_size;
|
size_t vertex_data_size;
|
||||||
|
const uint16_t *index_data;
|
||||||
|
size_t index_data_size;
|
||||||
} gpu_config_t;
|
} gpu_config_t;
|
||||||
|
|
||||||
void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config);
|
void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config);
|
||||||
|
|||||||
@@ -4,11 +4,14 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
static const vertex_t vertices[] = {
|
static const vertex_t vertices[] = {
|
||||||
{ { 0.0, -0.5 }, { 1.0, 0.0, 0.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, 1.0, 0.0 } },
|
||||||
{ { -0.5, 0.5 }, { 0.0, 0.0, 1.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
|
static void
|
||||||
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
@@ -42,6 +45,8 @@ int main()
|
|||||||
.window = window,
|
.window = window,
|
||||||
.vertex_data = vertices,
|
.vertex_data = vertices,
|
||||||
.vertex_data_size = sizeof(vertices),
|
.vertex_data_size = sizeof(vertices),
|
||||||
|
.index_data = indices,
|
||||||
|
.index_data_size = sizeof(indices),
|
||||||
};
|
};
|
||||||
gpu_ctx_t gpu;
|
gpu_ctx_t gpu;
|
||||||
gpu_init(&gpu, &gpu_config);
|
gpu_init(&gpu, &gpu_config);
|
||||||
|
|||||||
Reference in new issue
Block a user