summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2023-10-22 18:35:58 +0300
committerkartofen <mladenovnasko0@gmail.com>2023-10-22 18:35:58 +0300
commit560f07e306da1906720ffc8a7de32069b8b7353e (patch)
treef2ec80f50bcac515515cb5d023b58d9dfdd7c6dc
parentff2497dc2c67d2b7df29b729c763b6e09c876d76 (diff)
triangle!!!!!!!!!!
-rw-r--r--src/device.c244
-rw-r--r--src/device.h15
-rw-r--r--src/main.c7
3 files changed, 249 insertions, 17 deletions
diff --git a/src/device.c b/src/device.c
index f85b1a6..23cece2 100644
--- a/src/device.c
+++ b/src/device.c
@@ -63,9 +63,13 @@ static int create_physical_device(device_t device, struct device_info *info);
static int create_logical_device(device_t device, struct device_info *info);
static int create_swap_chain(device_t device, struct device_info *info);
static int create_pipeline(device_t device, struct device_info *info);
+static int create_command_pool(device_t device, struct device_info *info);
+static int create_sync_objects(device_t device, struct device_info *info);
static void destroy_swap_chain(device_t device);
static void destroy_pipeline(device_t device);
+// static void destroy_command_pool(device_t device);
+static void destroy_sync_objects(device_t device);
// --- Helper Function ---
static char *str_VkResult(VkResult result);
@@ -84,6 +88,11 @@ static int swap_chain_get_extent(VkSurfaceCapabilitiesKHR capabilities, VkExtent
#define PPLN device->pipeline
static int pipeline_load_shader_module(VkDevice device, char *path, VkShaderModule *module);
+#define CMND device->command
+static int command_buffer_record(device_t device, u32 image_index);
+
+#define SYNC device->sync
+
F_LOAD_FILE_ALIGNED(u32) // from config.h
// --- Debug Functions ---
@@ -125,6 +134,12 @@ device_t device_create(struct device_info *info)
PPLN.pipeline = VK_NULL_HANDLE;
PPLN.layout = VK_NULL_HANDLE;
PPLN.render_pass = VK_NULL_HANDLE;
+
+ CMND.pool = VK_NULL_HANDLE;
+
+ SYNC.semph_image_available = VK_NULL_HANDLE;
+ SYNC.semph_render_finished = VK_NULL_HANDLE;
+ SYNC.fence_inflight = VK_NULL_HANDLE;
CCHECK(create_instance);
CCHECK(create_surface);
@@ -135,6 +150,8 @@ device_t device_create(struct device_info *info)
CCHECK(create_logical_device);
CCHECK(create_swap_chain);
CCHECK(create_pipeline);
+ CCHECK(create_command_pool);
+ CCHECK(create_sync_objects);
return device;
fail:
@@ -146,6 +163,12 @@ void device_destroy(device_t device)
{
if(!device) return;
+ vkDeviceWaitIdle(device->logical_device);
+
+ destroy_sync_objects(device);
+
+ vkDestroyCommandPool(device->logical_device, CMND.pool, NULL);
+
destroy_pipeline(device);
destroy_swap_chain(device);
@@ -161,6 +184,62 @@ void device_destroy(device_t device)
free(device);
}
+int device_draw_frame(device_t device)
+{
+ int ret = 1;
+
+ // wait for the previous frame to finish
+ vkWaitForFences(device->logical_device, 1, &SYNC.fence_inflight, VK_TRUE, UINT64_MAX);
+ vkResetFences(device->logical_device, 1, &SYNC.fence_inflight);
+
+ // aquire the next image the form the swap chain
+ u32 image_index;
+ vkAcquireNextImageKHR(device->logical_device, SWCH.swap_chain, UINT64_MAX, SYNC.semph_image_available, VK_NULL_HANDLE, &image_index);
+
+ // reset the command buffer
+ vkResetCommandBuffer(CMND.buffer, 0);
+ command_buffer_record(device, image_index);
+
+ // prepare the queue submit info
+ VkSubmitInfo submit_info = {0};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+
+ VkSemaphore wait_semaphs[] = { SYNC.semph_image_available };
+ VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
+ submit_info.waitSemaphoreCount = ARR_SIZE(wait_semaphs);
+ submit_info.pWaitSemaphores = wait_semaphs;
+ submit_info.pWaitDstStageMask = wait_stages;
+
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = &CMND.buffer;
+
+ VkSemaphore signal_semphs[] = { SYNC.semph_image_available };
+ submit_info.signalSemaphoreCount = ARR_SIZE(signal_semphs);
+ submit_info.pSignalSemaphores = signal_semphs;
+
+ // submit the graphics work
+ VCHECK(vkQueueSubmit, device->graphics_queue, 1, &submit_info, SYNC.fence_inflight);
+
+ // prepare the graphics info
+ VkPresentInfoKHR present_info = {0};
+ present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+
+ present_info.waitSemaphoreCount = ARR_SIZE(signal_semphs);
+ present_info.pWaitSemaphores = signal_semphs;
+
+ VkSwapchainKHR swap_chains[] = { SWCH.swap_chain };
+ present_info.swapchainCount = ARR_SIZE(swap_chains);
+ present_info.pSwapchains = swap_chains;
+ present_info.pImageIndices = &image_index;
+ present_info.pResults = NULL; // Optional
+
+ vkQueuePresentKHR(device->present_queue, &present_info);
+
+ ret = 0;
+exit:
+ return ret;
+}
+
static int create_instance(device_t device, struct device_info *info)
{
int ret = 1;
@@ -177,8 +256,6 @@ static int create_instance(device_t device, struct device_info *info)
VkInstanceCreateInfo create_info = {0};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.pApplicationInfo = &app_info;
-
-
create_info.enabledLayerCount = 0;
@@ -503,18 +580,6 @@ static int create_pipeline(device_t device, struct device_info *info)
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_assembly.primitiveRestartEnable = VK_FALSE;
- // VkViewport viewport = {0};
- // viewport.x = 0.0f;
- // viewport.y = 0.0f;
- // viewport.width = (float) SWCH.extent.width;
- // viewport.height = (float) SWCH.extent.height;
- // viewport.minDepth = 0.0f;
- // viewport.maxDepth = 1.0f;
-
- // VkRect2D scissor = {0};
- // scissor.offset = {0, 0};
- // scissor.extent = SWCH.extent;
-
VkPipelineViewportStateCreateInfo viewport_state = {0};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 1;
@@ -594,12 +659,22 @@ static int create_pipeline(device_t device, struct device_info *info)
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_attachment_ref;
+ VkSubpassDependency dependency = {0};
+ dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependency.dstSubpass = 0;
+ dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependency.srcAccessMask = 0;
+ dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
VkRenderPassCreateInfo render_pass_info = {0};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
render_pass_info.attachmentCount = 1;
render_pass_info.pAttachments = &color_attachment;
render_pass_info.subpassCount = 1;
render_pass_info.pSubpasses = &subpass;
+ render_pass_info.dependencyCount = 1;
+ render_pass_info.pDependencies = &dependency;
VCHECK(vkCreateRenderPass, device->logical_device, &render_pass_info, NULL, &PPLN.render_pass);
@@ -626,7 +701,25 @@ static int create_pipeline(device_t device, struct device_info *info)
pipeline_info.basePipelineIndex = -1; // Optional
VCHECK(vkCreateGraphicsPipelines, device->logical_device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &PPLN.pipeline);
-
+
+ PPLN.framebuffers = xcalloc(SWCH.nimages, sizeof(*PPLN.framebuffers));
+ for(u32 i = 0; i < SWCH.nimages; i++) {
+ VkImageView attachments[] = {
+ SWCH.image_views[i]
+ };
+
+ VkFramebufferCreateInfo framebuffer_info = {0};
+ framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ framebuffer_info.renderPass = PPLN.render_pass;
+ framebuffer_info.attachmentCount = 1;
+ framebuffer_info.pAttachments = attachments;
+ framebuffer_info.width = SWCH.extent.width;
+ framebuffer_info.height = SWCH.extent.height;
+ framebuffer_info.layers = 1;
+
+ VCHECK(vkCreateFramebuffer, device->logical_device, &framebuffer_info, NULL, &PPLN.framebuffers[i]);
+ }
+
ret = 0;
exit:
vkDestroyShaderModule(device->logical_device, frag_shader, NULL);
@@ -636,11 +729,73 @@ exit:
static void destroy_pipeline(device_t device)
{
+ for(u32 i = 0; i < SWCH.nimages; i++) {
+ vkDestroyFramebuffer(device->logical_device, PPLN.framebuffers[i], NULL);
+ }
+ if(SWCH.nimages > 0) free(PPLN.framebuffers);
+
vkDestroyPipeline(device->logical_device, PPLN.pipeline, NULL);
vkDestroyPipelineLayout(device->logical_device, PPLN.layout, NULL);
vkDestroyRenderPass(device->logical_device, PPLN.render_pass, NULL);
}
+static int create_command_pool(device_t device, struct device_info *info)
+{
+ (void)info;
+ int ret = 1;
+
+ struct queue_family_idx indices;
+ device_queue_families(device->physical_device, device->surface, &indices);
+
+ VkCommandPoolCreateInfo pool_info = {0};
+ pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ pool_info.queueFamilyIndex = indices.graphics_family;
+
+ VCHECK(vkCreateCommandPool, device->logical_device, &pool_info, NULL, &CMND.pool);
+
+ // allocate the command buffer(s)
+ VkCommandBufferAllocateInfo allocate_info = {0};
+ allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocate_info.commandPool = CMND.pool;
+ allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ allocate_info.commandBufferCount = 1;
+
+ VCHECK(vkAllocateCommandBuffers, device->logical_device, &allocate_info, &CMND.buffer);
+
+ ret = 0;
+exit:
+ return ret;
+}
+
+static int create_sync_objects(device_t device, struct device_info *info)
+{
+ (void)info;
+ int ret = 1;
+
+ VkSemaphoreCreateInfo semph_info = {0};
+ semph_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ VkFenceCreateInfo fence_info = {0};
+ fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ VCHECK(vkCreateSemaphore, device->logical_device, &semph_info, NULL, &SYNC.semph_image_available);
+ VCHECK(vkCreateSemaphore, device->logical_device, &semph_info, NULL, &SYNC.semph_render_finished);
+ VCHECK(vkCreateFence, device->logical_device, &fence_info, NULL, &SYNC.fence_inflight);
+
+ ret = 0;
+exit:
+ return ret;
+}
+
+static void destroy_sync_objects(device_t device)
+{
+ vkDestroySemaphore(device->logical_device, SYNC.semph_image_available, NULL);
+ vkDestroySemaphore(device->logical_device, SYNC.semph_render_finished, NULL);
+ vkDestroyFence(device->logical_device, SYNC.fence_inflight, NULL);
+}
+
static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family)
{
u32 count = 0;
@@ -800,6 +955,65 @@ exit:
return ret;
}
+static int command_buffer_record(device_t device, u32 image_index)
+{
+ int ret = 1;
+
+ // Begin the buffer
+ VkCommandBufferBeginInfo begin_info = {0};
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.flags = 0; // Optional
+ begin_info.pInheritanceInfo = NULL; // Optional
+
+ VCHECK(vkBeginCommandBuffer, CMND.buffer, &begin_info);
+
+ // Begin the render pass
+ VkRenderPassBeginInfo render_pass_info = {0};
+ render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ render_pass_info.renderPass = PPLN.render_pass;
+ render_pass_info.framebuffer = PPLN.framebuffers[image_index];
+
+ render_pass_info.renderArea.offset = (VkOffset2D){0, 0};
+ render_pass_info.renderArea.extent = SWCH.extent;
+
+ VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
+ render_pass_info.clearValueCount = 1;
+ render_pass_info.pClearValues = &clear_color;
+
+ vkCmdBeginRenderPass(CMND.buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
+
+ // Begin the drawing commands
+ vkCmdBindPipeline(CMND.buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PPLN.pipeline);
+
+ VkViewport viewport = {0};
+ viewport.x = 0.0f;
+ viewport.y = 0.0f;
+ viewport.width = (float)SWCH.extent.width;
+ viewport.height = (float)SWCH.extent.height;
+ viewport.minDepth = 0.0f;
+ viewport.maxDepth = 1.0f;
+
+ vkCmdSetViewport(CMND.buffer, 0, 1, &viewport);
+
+ VkRect2D scissor = {0};
+ scissor.offset = (VkOffset2D){0, 0};
+ scissor.extent = SWCH.extent;
+ vkCmdSetScissor(CMND.buffer, 0, 1, &scissor);
+
+ // 3 vertices, 1 instance (for instanced rendering)
+ // 0 is the first vertex, 0 is the fist instance
+ vkCmdDraw(CMND.buffer, 3, 1, 0, 0);
+
+ // Cleaning up
+ vkCmdEndRenderPass(CMND.buffer);
+
+ VCHECK(vkEndCommandBuffer, CMND.buffer);
+
+ ret = 0;
+exit:
+ return ret;
+}
+
#define X_VK_RESULT_TABLE(X) \
X(VK_SUCCESS) \
X(VK_NOT_READY) \
diff --git a/src/device.h b/src/device.h
index 05bdbc1..fac15b9 100644
--- a/src/device.h
+++ b/src/device.h
@@ -38,10 +38,24 @@ typedef struct device {
struct pipeline {
VkRenderPass render_pass;
+ VkFramebuffer *framebuffers;
+
VkPipelineLayout layout;
VkPipeline pipeline;
} pipeline;
+ struct command {
+ VkCommandPool pool;
+ VkCommandBuffer buffer;
+ // VkCommandBuffer *buffers;
+ } command;
+
+ struct sync {
+ VkSemaphore semph_image_available;
+ VkSemaphore semph_render_finished;
+ VkFence fence_inflight;
+ } sync;
+
} * device_t;
struct device_info {
@@ -56,5 +70,6 @@ struct device_info {
device_t device_create(struct device_info *info);
void device_destroy(device_t device);
+int device_draw_frame(device_t device);
#endif
diff --git a/src/main.c b/src/main.c
index 5309f09..678db3a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,6 +6,7 @@
#include "common.h"
// TODO: rename device.c/.h
+// to graphics.c/.h
window_t window;
device_t device;
@@ -24,8 +25,8 @@ int main(void)
// populate window info
struct window_info win_info = {0};
win_info.title = "Test App";
- win_info.w = 1200;
- win_info.h = 800;
+ win_info.w = 640;
+ win_info.h = 480;
// create window
window = window_create(&win_info);
@@ -69,6 +70,8 @@ int main(void)
running = 0;
break;
}
+
+ device_draw_frame(device);
}
ret = 0;