3 #define GLFW_INCLUDE_VULKAN
4 #include <GLFW/glfw3.h>
8 #include <gmath/gmath.h>
10 /* extern "C": vulkan framework */
17 /**************************/
18 /* static glfw callbacks */
19 /**************************/
22 clb_key(GLFWwindow *win, int key, int scancode, int action, int mods);
25 clb_reshape(GLFWwindow *win, int width, int height);
28 clb_motion(GLFWwindow *win, double x, double y);
31 clb_mouse(GLFWwindow *win, int button, int action, int mods);
33 /**************************/
34 /* static functions */
35 /**************************/
37 /* init, cleanup, display */
56 /**************************/
57 /* static variables */
58 /**************************/
60 static GLFWwindow *win;
61 static bool redraw_pending;
62 static bool move_camera;
65 static float cam_phi = 25;
66 static float cam_theta = 0;
67 static float cam_dist = 16;
71 static OrbitCamera *camera;
73 static bool vk_enable_layers = true;
75 static int win_w = 800;
76 static int win_h = 600;
78 static struct vk_ctx vk_core;
79 static VkSurfaceKHR vk_surf;
80 static struct vk_renderer vk_rnd;
81 static struct vk_swapchain vk_chain;
82 static struct vk_semaphores vk_sema;
83 static struct vk_attachment vk_depth_att;
84 static float vk_fb_color[4] = { 0.0, 0.0, 0.5, 1.0 };
86 /* make array later if many cmd buffers */
87 static VkCommandBuffer vk_cmd_buf;
89 /* empty for as long as we hardcode the vertices in the vertex shader */
90 static struct vk_vertex_info vk_vert_info;
92 int main(int argc, char** argv)
97 fprintf(stderr, "Failed to initialize GLFW.\n");
105 /* reshape window once just in case */
107 glfwGetWindowSize(win, &win_w, &win_h);
108 clb_reshape(win, win_w, win_h);
111 redraw_pending = true;
113 while(!glfwWindowShouldClose(win)) {
115 if (redraw_pending) {
116 redraw_pending = false;
122 while(!glfwWindowShouldClose(win)) {
125 glfwSwapBuffers(win);
133 /* static functions */
142 if (glfwVulkanSupported() != GLFW_TRUE) {
143 fprintf(stderr, "Vulkan is not supported on this device.\n");
149 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
150 win = glfwCreateWindow(win_w, win_h, "helloworld rt", 0, 0);
153 fprintf(stderr, "Failed to create GLFW window\n");
157 glfwSetKeyCallback(win, clb_key);
159 /* initialize Vulkan context (instance) */
161 if (!vk_init_ctx_for_rendering(&vk_core, true, vk_enable_layers)) {
162 fprintf(stderr, "Failed to initialize Vulkan context.\n");
166 /* create (Xcb) surface */
168 glfwGetFramebufferSize(win, &win_h, &win_h);
169 if (glfwCreateWindowSurface(vk_core.inst, win, 0, &vk_surf)
171 fprintf(stderr, "Failed to create XCB surface.\n");
175 /* create semaphores */
176 if (!vk_create_semaphores(&vk_core, false, &vk_sema)) {
177 fprintf(stderr, "No semaphores were created.\n");
181 /* create swapchain */
182 if (!vk_create_swapchain(&vk_core, win_w, win_h, false, vk_surf, 0, &vk_chain)) {
183 fprintf(stderr, "No swapchain was created.\n");
187 if (vk_chain.swapchain == VK_NULL_HANDLE) {
188 fprintf(stderr, "Invalid swapchain handle.\n");
193 vsdr = sdr_load("data/main.vert.spv", &vsz);
194 fsdr = sdr_load("data/main.frag.spv", &fsz);
196 /* create depth attachment (for the moment we are going to use this
198 if (!vk_fill_image_props(&vk_core,
201 VK_FORMAT_D32_SFLOAT_S8_UINT,
202 VK_IMAGE_TILING_OPTIMAL,
203 VK_IMAGE_LAYOUT_UNDEFINED,
204 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
206 &vk_depth_att.props)) {
207 fprintf(stderr, "Unsupported depth image properties\n");
210 if (!vk_create_image(&vk_core, &vk_depth_att.props, &vk_depth_att.obj)) {
211 fprintf(stderr, "Failed to create depth attachment.\n");
215 /* create renderer */
216 if (!vk_create_renderer(&vk_core,
217 vsdr, vsz, fsdr, fsz,
220 vk_chain.num_atts, vk_chain.atts, &vk_depth_att,
221 &vk_vert_info, &vk_rnd)) {
225 /* create cmd buffer */
226 if ((vk_cmd_buf = vk_create_cmd_buffer(&vk_core)) == VK_NULL_HANDLE) {
227 fprintf(stderr, "Failed to create command buffer.\n");
231 /* record cmd buffer */
232 if (!vk_record_cmd_buffer(&vk_core, vk_cmd_buf,
235 vk_chain.num_atts + 1, 0,
236 0, 0, win_w, win_h)) {
237 fprintf(stderr, "Failed to record command buffer.\n");
244 /* set GLFW callbacks */
246 glfwSetWindowSizeCallback(win, clb_reshape);
248 glfwSetCursorPosCallback(win, clb_motion);
249 glfwSetMouseButtonCallback(win, clb_mouse);
264 fprintf(stderr, "Failed to initialize Vulkan structs.\n");
268 camera = new OrbitCamera;
283 VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
284 VkPresentInfoKHR pinfo;
286 vkAcquireNextImageKHR(vk_core.dev, vk_chain.swapchain,
287 UINT64_MAX, vk_sema.frame_ready, 0, &img_idx);
289 memset(&sinfo, 0, sizeof sinfo);
290 sinfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
291 sinfo.waitSemaphoreCount = 1;
292 sinfo.pWaitSemaphores = &vk_sema.frame_ready;
293 sinfo.pWaitDstStageMask = &wait_stages;
294 sinfo.commandBufferCount = 1;
295 sinfo.pCommandBuffers = &vk_cmd_buf;
296 sinfo.signalSemaphoreCount = 1;
297 sinfo.pSignalSemaphores = &vk_sema.frame_done;
299 if (vkQueueSubmit(vk_core.queue, 1, &sinfo, 0) != 0) {
300 fprintf(stderr, "Failed to submit draw commands.\n");
304 memset(&pinfo, 0, sizeof pinfo);
305 pinfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
306 pinfo.waitSemaphoreCount = 1;
307 pinfo.pWaitSemaphores = &vk_sema.frame_done;
308 pinfo.swapchainCount = 1;
309 pinfo.pSwapchains = &vk_chain.swapchain;
310 pinfo.pImageIndices = &img_idx;
312 vkQueuePresentKHR(vk_core.queue, &pinfo);
318 vkQueueWaitIdle(vk_core.queue);
320 if (vk_cmd_buf != VK_NULL_HANDLE) {
321 vkResetCommandBuffer(vk_cmd_buf, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
324 vk_destroy_image(&vk_core, &vk_depth_att.obj);
325 vk_destroy_semaphores(&vk_core, &vk_sema);
326 vk_destroy_renderer(&vk_core, &vk_rnd);
328 if (vk_chain.swapchain) {
329 vk_destroy_swapchain(&vk_core, &vk_chain);
330 vkDestroySurfaceKHR(vk_core.inst, vk_surf, 0);
333 glfwDestroyWindow(win);
335 if (!vk_enable_layers)
336 vkFreeCommandBuffers(vk_core.dev, vk_core.cmd_pool, 1, &vk_cmd_buf);
338 vk_cleanup_ctx(&vk_core, vk_enable_layers);
346 clb_key(GLFWwindow *win, int key, int scancode,
347 int action, int mods)
349 if (action == GLFW_PRESS) {
351 case GLFW_KEY_ESCAPE:
352 glfwSetWindowShouldClose(win, GLFW_TRUE);
355 move_camera = !move_camera;
364 clb_reshape(GLFWwindow *win,
370 static double prev_x, prev_y;
371 static bool button[8];
374 clb_motion(GLFWwindow *win,
378 double dx = x - prev_x;
379 double dy = y - prev_y;
385 cam_theta += dx * 0.5;
395 cam_dist += dy * 0.1;
403 clb_mouse(GLFWwindow *win,