diff options
author | kartofen <mladenovnasko0@gmail.com> | 2023-10-22 18:35:58 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2023-10-22 18:35:58 +0300 |
commit | 560f07e306da1906720ffc8a7de32069b8b7353e (patch) | |
tree | f2ec80f50bcac515515cb5d023b58d9dfdd7c6dc | |
parent | ff2497dc2c67d2b7df29b729c763b6e09c876d76 (diff) |
triangle!!!!!!!!!!
-rw-r--r-- | src/device.c | 244 | ||||
-rw-r--r-- | src/device.h | 15 | ||||
-rw-r--r-- | src/main.c | 7 |
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 @@ -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; |