af4277c20421d870a7884a345fc76f55f0a78a69
[vkrt] / src / main.cc
1 #include <stdio.h>
2
3 #define GLFW_INCLUDE_VULKAN
4 #include <GLFW/glfw3.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "vk.h"
9 #include "util.h"
10
11
12 /* static glfw callbacks */
13
14 static void
15 clb_key(GLFWwindow *win, int key, int scancode, int action, int mods);
16
17 static void
18 clb_reshape(GLFWwindow *win, int width, int height);
19
20 /* static functions */
21
22 static bool
23 init(void);
24
25 static void
26 cleanup(void);
27
28 static void
29 display(void);
30
31 /* static variables */
32
33 static GLFWwindow *win;
34 static bool redraw_pending;
35
36 static bool vk_enable_layers = true;
37
38 static int win_w = 800;
39 static int win_h = 600;
40
41 static struct vk_ctx vk_core;
42 static VkSurfaceKHR vk_surf;
43 static struct vk_renderer vk_rnd;
44 static struct vk_swapchain vk_chain;
45 static struct vk_semaphores vk_sema;
46 static struct vk_attachment vk_depth_att;
47 static float vk_fb_color[4] = { 0.0, 0.0, 0.5, 1.0 };
48
49 /* make array later if many cmd buffers */
50 static VkCommandBuffer vk_cmd_buf;
51
52 /* empty for as long as we hardcode the vertices in the vertex shader */
53 static struct vk_vertex_info vk_vert_info;
54
55 int main(int argc, char** argv)
56 {
57     atexit(cleanup);
58
59     if (!init()) {
60         return 1;
61     }
62
63     /* reshape window once just in case */
64
65     glfwGetWindowSize(win, &win_w, &win_h);
66     clb_reshape(win, win_w, win_h);
67
68     /* event loop */
69     redraw_pending = true;
70
71     while(!glfwWindowShouldClose(win)) {
72         glfwWaitEvents();
73         if (redraw_pending) {
74             redraw_pending = false;
75             display();
76         }
77     }
78
79     return 0;
80 }
81
82 /* static functions */
83
84 static bool
85 init(void)
86 {
87     char *vsdr = 0;
88     char *fsdr = 0;
89     int vsz, fsz;
90
91     /* initialize GLFW */
92
93     if (!glfwInit()) {
94         fprintf(stderr, "Failed to initialize GLFW.\n");
95         return false;
96     }
97
98     if (glfwVulkanSupported() != GLFW_TRUE) {
99         fprintf(stderr, "Vulkan is not supported on this device.\n");
100         return false;
101     }
102
103     /* create window */
104
105     glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
106     win = glfwCreateWindow(win_w, win_h, "helloworld rt", 0, 0);
107
108     if (!win) {
109         fprintf(stderr, "Failed to create GLFW window\n");
110         return false;
111     }
112
113     glfwSetKeyCallback(win, clb_key);
114
115     /* initialize Vulkan context (instance) */
116
117     if (!vk_init_ctx_for_rendering(&vk_core, true, vk_enable_layers)) {
118         fprintf(stderr, "Failed to initialize Vulkan context.\n");
119         return false;
120     }
121
122     /* create (Xcb) surface */
123
124     glfwGetFramebufferSize(win, &win_h, &win_h);
125     if (glfwCreateWindowSurface(vk_core.inst, win, 0, &vk_surf)
126             != VK_SUCCESS) {
127         fprintf(stderr, "Failed to create XCB surface.\n");
128         return false;
129     }
130
131     /* create semaphores */
132     if (!vk_create_semaphores(&vk_core, false, &vk_sema)) {
133         fprintf(stderr, "No semaphores were created.\n");
134         goto fail;
135     }
136
137     /* create swapchain */
138     if (!vk_create_swapchain(&vk_core, win_w, win_h, false, vk_surf, 0, &vk_chain)) {
139         fprintf(stderr, "No swapchain was created.\n");
140         goto fail;
141     }
142
143     if (vk_chain.swapchain == VK_NULL_HANDLE) {
144         fprintf(stderr, "Invalid swapchain handle.\n");
145         goto fail;
146     }
147
148     /* create shaders */
149     vsdr = sdr_load("data/main.vert.spv", &vsz);
150     fsdr = sdr_load("data/main.frag.spv", &fsz);
151
152     /* create depth attachment (for the moment we are going to use this
153      * for all images */
154     if (!vk_fill_image_props(&vk_core,
155                              win_w, win_h, 1,
156                              1, 1, 1,
157                              VK_FORMAT_D32_SFLOAT_S8_UINT,
158                              VK_IMAGE_TILING_OPTIMAL,
159                              VK_IMAGE_LAYOUT_UNDEFINED,
160                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
161                              false, true, false,
162                              &vk_depth_att.props)) {
163         fprintf(stderr, "Unsupported depth image properties\n");
164         return false;
165     }
166     if (!vk_create_image(&vk_core, &vk_depth_att.props, &vk_depth_att.obj)) {
167         fprintf(stderr, "Failed to create depth attachment.\n");
168         goto fail;
169     }
170
171     /* create renderer */
172     if (!vk_create_renderer(&vk_core,
173                             vsdr, vsz, fsdr, fsz,
174                             win_w, win_h, 1,
175                             false, false,
176                             vk_chain.num_atts, vk_chain.atts, &vk_depth_att,
177                             &vk_vert_info, &vk_rnd)) {
178         goto fail;
179     }
180
181     /* create cmd buffer */
182     if ((vk_cmd_buf = vk_create_cmd_buffer(&vk_core)) == VK_NULL_HANDLE) {
183         fprintf(stderr, "Failed to create command buffer.\n");
184         goto fail;
185     }
186
187     /* record cmd buffer */
188     if (!vk_record_cmd_buffer(&vk_core, vk_cmd_buf,
189                               &vk_rnd, 0,
190                               4, vk_fb_color,
191                               vk_chain.num_atts + 1, 0,
192                               0, 0, win_w, win_h)) {
193         fprintf(stderr, "Failed to record command buffer.\n");
194         goto fail;
195     }
196
197     free(vsdr);
198     free(fsdr);
199
200     /* set GLFW callbacks */
201
202     /* glfwSetWindowSizeCallback(win, clb_reshape); */
203
204     /*
205     glfwSetCursorPosCallback(win, clb_motion);
206     glfwSetMouseButtonCallback(win, clb_mouse);
207     */
208
209     return true;
210
211 fail:
212     free(vsdr);
213     free(fsdr);
214
215     return false;
216 }
217
218 static void
219 display(void)
220 {
221     uint32_t img_idx;
222     VkSubmitInfo sinfo;
223     VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
224         VkPresentInfoKHR pinfo;
225
226     vkAcquireNextImageKHR(vk_core.dev, vk_chain.swapchain,
227                           UINT64_MAX, vk_sema.frame_ready, 0, &img_idx);
228
229     memset(&sinfo, 0, sizeof sinfo);
230     sinfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
231     sinfo.waitSemaphoreCount = 1;
232     sinfo.pWaitSemaphores = &vk_sema.frame_ready;
233     sinfo.pWaitDstStageMask = &wait_stages;
234     sinfo.commandBufferCount = 1;
235     sinfo.pCommandBuffers = &vk_cmd_buf;
236     sinfo.signalSemaphoreCount = 1;
237         sinfo.pSignalSemaphores = &vk_sema.frame_done;
238
239     if (vkQueueSubmit(vk_core.queue, 1, &sinfo, 0) != 0) {
240         fprintf(stderr, "Failed to submit draw commands.\n");
241         abort();
242     }
243
244     memset(&pinfo, 0, sizeof pinfo);
245     pinfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
246     pinfo.waitSemaphoreCount = 1;
247     pinfo.pWaitSemaphores = &vk_sema.frame_done;
248     pinfo.swapchainCount = 1;
249     pinfo.pSwapchains = &vk_chain.swapchain;
250     pinfo.pImageIndices = &img_idx;
251
252     vkQueuePresentKHR(vk_core.queue, &pinfo);
253 }
254
255 static void
256 cleanup(void)
257 {
258     vkQueueWaitIdle(vk_core.queue);
259
260     if (vk_cmd_buf != VK_NULL_HANDLE) {
261         vkResetCommandBuffer(vk_cmd_buf, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
262     }
263
264     vk_destroy_image(&vk_core, &vk_depth_att.obj);
265     vk_destroy_semaphores(&vk_core, &vk_sema);
266     vk_destroy_renderer(&vk_core, &vk_rnd);
267
268     if (vk_chain.swapchain) {
269         vk_destroy_swapchain(&vk_core, &vk_chain);
270         vkDestroySurfaceKHR(vk_core.inst, vk_surf, 0);
271     }
272
273     glfwDestroyWindow(win);
274
275     if (!vk_enable_layers)
276         vkFreeCommandBuffers(vk_core.dev, vk_core.cmd_pool, 1, &vk_cmd_buf);
277
278     vk_cleanup_ctx(&vk_core, vk_enable_layers);
279
280     glfwTerminate();
281 }
282
283 /* glfw callbacks */
284
285 static void
286 clb_key(GLFWwindow *win, int key, int scancode,
287         int action, int mods)
288 {
289     if (action == GLFW_PRESS) {
290         switch(key) {
291         case GLFW_KEY_ESCAPE:
292             glfwSetWindowShouldClose(win, GLFW_TRUE);
293             return;
294         }
295     }
296 }
297
298 static void
299 clb_reshape(GLFWwindow *win, int width, int height)
300 {
301 }