3 #define GLFW_INCLUDE_VULKAN
4 #include <GLFW/glfw3.h>
12 /* static glfw callbacks */
15 clb_key(GLFWwindow *win, int key, int scancode, int action, int mods);
18 clb_reshape(GLFWwindow *win, int width, int height);
20 /* static functions */
31 /* static variables */
33 static GLFWwindow *win;
34 static bool redraw_pending;
36 static bool vk_enable_layers;
38 static int win_w = 800;
39 static int win_h = 600;
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 };
49 /* make array later if many cmd buffers */
50 static VkCommandBuffer vk_cmd_buf;
52 /* empty for as long as we hardcode the vertices in the vertex shader */
53 static struct vk_vertex_info vk_vert_info;
55 int main(int argc, char** argv)
63 /* reshape window once just in case */
65 glfwGetWindowSize(win, &win_w, &win_h);
66 clb_reshape(win, win_w, win_h);
69 redraw_pending = true;
71 while(!glfwWindowShouldClose(win)) {
74 redraw_pending = false;
82 /* static functions */
94 fprintf(stderr, "Failed to initialize GLFW.\n");
98 if (glfwVulkanSupported() != GLFW_TRUE) {
99 fprintf(stderr, "Vulkan is not supported on this device.\n");
105 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
106 win = glfwCreateWindow(win_w, win_h, "helloworld rt", 0, 0);
109 fprintf(stderr, "Failed to create GLFW window\n");
113 glfwSetKeyCallback(win, clb_key);
115 /* initialize Vulkan context (instance) */
117 if (!vk_init_ctx_for_rendering(&vk_core, true, vk_enable_layers)) {
118 fprintf(stderr, "Failed to initialize Vulkan context.\n");
122 /* create (Xcb) surface */
124 glfwGetFramebufferSize(win, &win_h, &win_h);
125 if (glfwCreateWindowSurface(vk_core.inst, win, 0, &vk_surf)
127 fprintf(stderr, "Failed to create XCB surface.\n");
131 /* create semaphores */
132 if (!vk_create_semaphores(&vk_core, false, &vk_sema)) {
133 fprintf(stderr, "No semaphores were created.\n");
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");
143 if (vk_chain.swapchain == VK_NULL_HANDLE) {
144 fprintf(stderr, "Invalid swapchain handle.\n");
149 vsdr = sdr_load("data/main.vert.spv", &vsz);
150 fsdr = sdr_load("data/main.frag.spv", &fsz);
152 /* create depth attachment (for the moment we are going to use this
154 if (!vk_fill_image_props(&vk_core,
157 VK_FORMAT_D24_UNORM_S8_UINT,
158 VK_IMAGE_TILING_OPTIMAL,
159 VK_IMAGE_LAYOUT_UNDEFINED,
160 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
162 &vk_depth_att.props)) {
163 fprintf(stderr, "Unsupported depth image properties\n");
166 if (!vk_create_image(&vk_core, &vk_depth_att.props, &vk_depth_att.obj)) {
167 fprintf(stderr, "Failed to create depth attachment.\n");
171 /* create renderer */
172 if (!vk_create_renderer(&vk_core,
173 vsdr, vsz, fsdr, fsz,
176 vk_chain.num_atts, vk_chain.atts, &vk_depth_att,
177 &vk_vert_info, &vk_rnd)) {
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");
187 /* record cmd buffer */
188 if (!vk_record_cmd_buffer(&vk_core, vk_cmd_buf,
191 vk_chain.num_atts + 1, 0,
192 0, 0, win_w, win_h)) {
193 fprintf(stderr, "Failed to record command buffer.\n");
200 /* set GLFW callbacks */
202 /* glfwSetWindowSizeCallback(win, clb_reshape); */
205 glfwSetCursorPosCallback(win, clb_motion);
206 glfwSetMouseButtonCallback(win, clb_mouse);
223 VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
224 VkPresentInfoKHR pinfo;
226 vkAcquireNextImageKHR(vk_core.dev, vk_chain.swapchain,
227 UINT64_MAX, vk_sema.frame_ready, 0, &img_idx);
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;
239 if (vkQueueSubmit(vk_core.queue, 1, &sinfo, 0) != 0) {
240 fprintf(stderr, "Failed to submit draw commands.\n");
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;
252 vkQueuePresentKHR(vk_core.queue, &pinfo);
258 vkQueueWaitIdle(vk_core.queue);
260 if (vk_cmd_buf != VK_NULL_HANDLE) {
261 vkResetCommandBuffer(vk_cmd_buf, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
264 vk_destroy_image(&vk_core, &vk_depth_att.obj);
265 vk_destroy_renderer(&vk_core, &vk_rnd);
266 vk_destroy_semaphores(&vk_core, &vk_sema);
268 if (vk_chain.swapchain) {
269 vk_destroy_swapchain(&vk_core, &vk_chain);
270 vkDestroySurfaceKHR(vk_core.inst, vk_surf, 0);
273 glfwDestroyWindow(win);
275 if (!vk_enable_layers)
276 vkFreeCommandBuffers(vk_core.dev, vk_core.cmd_pool, 1, &vk_cmd_buf);
278 vk_cleanup_ctx(&vk_core, vk_enable_layers);
286 clb_key(GLFWwindow *win, int key, int scancode,
287 int action, int mods)
289 if (action == GLFW_PRESS) {
291 case GLFW_KEY_ESCAPE:
292 glfwSetWindowShouldClose(win, GLFW_TRUE);
299 clb_reshape(GLFWwindow *win, int width, int height)