kiba-engine
poc.c
1 
2 #include <kiba/renderer/poc.h>
3 
4 #include <kiba/core/log.h>
5 #include <kiba/renderer/vulkan/command_buffer.h>
6 #include <kiba/renderer/vulkan/context.h>
7 #include <kiba/renderer/vulkan/depth.h>
8 #include <kiba/renderer/vulkan/device.h>
9 #include <kiba/renderer/vulkan/framebuffers.h>
10 #include <kiba/renderer/vulkan/image.h>
11 #include <kiba/renderer/vulkan/index_buffer.h>
12 #include <kiba/renderer/vulkan/instance.h>
13 #include <kiba/renderer/vulkan/logging.h>
14 #include <kiba/renderer/vulkan/pipeline.h>
15 #include <kiba/renderer/vulkan/renderpass.h>
16 #include <kiba/renderer/vulkan/surface.h>
17 #include <kiba/renderer/vulkan/swap_chain.h>
18 #include <kiba/renderer/vulkan/sync.h>
19 #include <kiba/renderer/vulkan/texture.h>
20 #include <kiba/renderer/vulkan/uniform.h>
21 #include <kiba/renderer/vulkan/vertex_buffer.h>
22 
23 vulkan_context context;
24 
25 b8 vulkan_init(platform_window *window) {
26  if (!vulkan_default_context_create(&context, window)) {
27  return false;
28  }
29 
30  if (!vulkan_instance_create(&context)) {
31  return false;
32  }
33 
34 #ifdef KB_DEBUG_BUILD
35  if (!vulkan_debug_messenger_create(&context)) {
36  return false;
37  }
38 #endif
39 
40  if (!vulkan_surface_create(&context)) {
41  return false;
42  }
43 
44  if (!vulkan_device_create(&context)) {
45  return false;
46  }
47 
48  if (!vulkan_renderpass_create(&context)) {
49  return false;
50  }
51 
52  if (!vulkan_swap_chain_create(&context)) {
53  return false;
54  }
55 
56  if (!vulkan_descriptor_set_layout_create(&context)) {
57  return false;
58  }
59 
60  if (!vulkan_pipeline_create(&context)) {
61  return false;
62  }
63 
64  if (!vulkan_depth_create(&context)) {
65  return false;
66  }
67 
68  if (!vulkan_framebuffers_create(&context)) {
69  return false;
70  }
71 
72  if (!vulkan_texture_create(&context)) {
73  return false;
74  }
75 
76  if (!vulkan_vertex_buffer_create(&context)) {
77  return false;
78  }
79 
80  if (!vulkan_index_buffer_create(&context)) {
81  return false;
82  }
83 
84  if (!vulkan_uniform_buffers_create(&context)) {
85  return false;
86  }
87 
88  if (!vulkan_descriptor_pool_create(&context)) {
89  return false;
90  }
91 
92  if (!vulkan_descriptor_sets_create(&context)) {
93  return false;
94  }
95 
96  if (!vulkan_sync_create(&context)) {
97  return false;
98  }
99 
100  return true;
101 }
102 
103 void vulkan_shutdown(void) {
104  // wait until async stuff done
105  vkDeviceWaitIdle(context.device.logical);
106 
107  vulkan_framebuffers_destroy(&context);
108 
109  vulkan_depth_destroy(&context);
110 
111  vulkan_swap_chain_destroy(&context);
112 
113  vulkan_texture_destroy(&context);
114 
115  vulkan_pipeline_destroy(&context);
116 
117  vulkan_renderpass_destroy(&context);
118 
119  vulkan_uniform_buffers_destroy(&context);
120 
121  vulkan_descriptor_pool_destroy(&context);
122 
123  vulkan_descriptor_set_layout_destroy(&context);
124 
125  vulkan_index_buffer_destroy(&context);
126 
127  vulkan_vertex_buffer_destroy(&context);
128 
129  vulkan_sync_destroy(&context);
130 
131  vulkan_device_destroy(&context);
132 
133  vulkan_surface_destroy(&context);
134 
135 #ifdef KB_DEBUG_BUILD
136  vulkan_debug_messenger_destroy(&context);
137 #endif
138 
139  vulkan_instance_destroy(&context);
140 
141  vulkan_context_destroy(&context);
142 }
143 
144 void vulkan_draw_frame(void) {
145  VK_CALL_ASSERT(vkWaitForFences(context.device.logical, 1, &context.sync.fc_in_flight, VK_TRUE, UINT64_MAX));
146  u32 image_index = 0;
147 
148  VkResult res = vkAcquireNextImageKHR(context.device.logical,
149  context.swap_chain.swap_chain,
150  UINT64_MAX,
151  context.sync.sp_image_available,
152  VK_NULL_HANDLE,
153  &image_index);
154  if (res == VK_ERROR_OUT_OF_DATE_KHR) {
155  vulkan_swap_chain_recreate(&context);
156  return;
157  } // TODO handle not VK_SUCCESS or VK_SUBOPTIMAL_KHR
158 
159  // only reset fence when not returning early -> avoids deadlock
160  VK_CALL_ASSERT(vkResetFences(context.device.logical, 1, &context.sync.fc_in_flight));
161 
162  static u32 init_counter = 0;
163  if (init_counter < 3) {
164  if (!vulkan_image_transition_layout_tmp(&context,
165  context.swap_chain.images[image_index],
166  VK_FORMAT_R8G8B8A8_SRGB,
167  VK_IMAGE_LAYOUT_UNDEFINED,
168  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)) {
169  KB_ERROR("failed to transition vulkan_image layout before rendering");
170  }
171  init_counter += (init_counter == image_index);
172  } else {
173  if (!vulkan_image_transition_layout_tmp(&context,
174  context.swap_chain.images[image_index],
175  VK_FORMAT_R8G8B8A8_SRGB,
176  VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
177  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)) {
178  KB_ERROR("failed to transition vulkan_image layout before rendering");
179  }
180  }
181 
182  VK_CALL_ASSERT(vkResetCommandBuffer(context.device.graphics_queue.command_buffer, 0));
183  vulkan_command_buffer_record(&context, context.device.graphics_queue.command_buffer, image_index);
184 
185  VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
186 
187  // handle uniforms
188  vulkan_uniform_buffers_update(&context, image_index);
189 
190  VkSubmitInfo submit_info = {
191  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
192  .waitSemaphoreCount = 1,
193  .pWaitSemaphores = &context.sync.sp_image_available,
194  .pWaitDstStageMask = wait_stages,
195  .commandBufferCount = 1,
196  .pCommandBuffers = &context.device.graphics_queue.command_buffer,
197  .signalSemaphoreCount = 1,
198  .pSignalSemaphores = &context.sync.sp_render_finished,
199  };
200  VK_CALL_ASSERT(vkQueueSubmit(context.device.graphics_queue.queue, 1, &submit_info, context.sync.fc_in_flight));
201 
202  if (!vulkan_image_transition_layout_tmp(&context,
203  context.swap_chain.images[image_index],
204  VK_FORMAT_R8G8B8A8_SRGB,
205  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
206  VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
207  KB_ERROR("failed to transition vulkan_image layout after rendering");
208  }
209 
210  VkPresentInfoKHR present_info = {
211  .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
212  .waitSemaphoreCount = 1,
213  .pWaitSemaphores = &context.sync.sp_render_finished,
214  .swapchainCount = 1,
215  .pSwapchains = &context.swap_chain.swap_chain,
216  .pImageIndices = &image_index,
217  .pResults = NULL,
218  };
219  res = vkQueuePresentKHR(context.device.present_queue.queue, &present_info);
220  if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR || context.swap_chain.recreate) {
221  context.swap_chain.recreate = false;
222  vulkan_swap_chain_recreate(&context);
223  } // TODO handle not VK_SUCCESS
224 }
Logging system.
#define KB_ERROR(...)
Log entry with error log level.
Definition: log.h:142
Structure holding information about a window.
Definition: window.h:13