X-Git-Url: https://eleni.mutantstargoat.com/git/?p=vkrt;a=blobdiff_plain;f=src%2Fmain.cc;fp=src%2Fmain.cc;h=0000000000000000000000000000000000000000;hp=5ec96d4cc7c9ccaf78ea34dd50d34c1c531eedb8;hb=638b86fbbdb0307faf21c04532d8f5ceb3b29884;hpb=c7de7f04077b07757ffef63ce6771a9d561945d5 diff --git a/src/main.cc b/src/main.cc deleted file mode 100644 index 5ec96d4..0000000 --- a/src/main.cc +++ /dev/null @@ -1,548 +0,0 @@ -#include - -#define GLFW_INCLUDE_VULKAN -#include - -#include -#include -#include - -#include - -#include - -/* extern "C": vulkan framework */ -#include "vk.h" -#include "util.h" - -/* C++ */ -#include "camera.h" - -/* defines */ -#define FENCE_TIMEOUT UINT64_MAX - -/**************************/ -/* static glfw callbacks */ -/**************************/ - -static void -clb_key(GLFWwindow *win, int key, int scancode, int action, int mods); - -static void -clb_reshape(GLFWwindow *win, int width, int height); - -static void -clb_motion(GLFWwindow *win, double x, double y); - -static void -clb_mouse(GLFWwindow *win, int button, int action, int mods); - -/**************************/ -/* static functions */ -/**************************/ - -/* init, cleanup, display */ - -static bool -init(); - -static void -cleanup(); - -static void -display(); - -/* vulkan, glfw */ - -static bool -vk_init(); - -static bool -vk_create_sync_objects(); - -static void -vk_cleanup(); - -/***************************/ -/* static/global variables */ -/***************************/ - -static GLFWwindow *win; -/* static bool redraw_pending; */ -static bool move_camera; - -/* camera */ -static float cam_phi = 25; -static float cam_theta = 0; -static float cam_dist = 16; -static Vec3 cam_pos; - -static OrbitCamera *camera; - -static float aspect; -static Mat4 mproj; - -/* win etc */ -static int win_w = 800; -static int win_h = 600; - -/* vulkan */ -static bool vk_enable_layers = true; -static struct vk_ctx vk_core; -static VkSurfaceKHR vk_surf; - -static struct vk_swapchain vk_chain; -static uint32_t vk_current_image; -static int vk_frame_idx; -static std::vectorvk_framebuffers; - -/* for the moment: one cmd buffer per swapchain image */ -static std::vectorvk_cmd_buffers; -static std::vectorvk_fences; -static struct vk_semaphores *vk_semas; - -/* FIXME make them part of each object's functions/params */ -static struct vk_renderer vk_rnd; -static struct vk_attachment vk_depth_att; -static float vk_fb_color[4] = { 0.0, 0.0, 0.5, 1.0 }; - -/* empty for as long as we hardcode the vertices in the vertex shader */ -#if 0 -static struct vk_vertex_info vk_vert_info; -#endif - -int main(int argc, char** argv) -{ - atexit(cleanup); - - /*********************************************************** - * GLFW - ***********************************************************/ - - if (!glfwInit()) { - fprintf(stderr, "Failed to initialize GLFW.\n"); - return 1; - } - - if (glfwVulkanSupported() != GLFW_TRUE) { - fprintf(stderr, "Vulkan is not supported on this device.\n"); - return 1; - } - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - if (!(win = glfwCreateWindow(win_w, win_h, "helloworld rt", 0, 0))) { - fprintf(stderr, "Failed to create GLFW window\n"); - return 1; - } - - glfwSetKeyCallback(win, clb_key); - glfwSetWindowSizeCallback(win, clb_reshape); - glfwSetCursorPosCallback(win, clb_motion); - glfwSetMouseButtonCallback(win, clb_mouse); - - /*********************************************************** - * VULKAN context - ***********************************************************/ - - if (!vk_init_ctx_for_rendering(&vk_core, true, vk_enable_layers)) { - fprintf(stderr, "Failed to initialize Vulkan context.\n"); - return 1; - } - - /*********************************************************** - * XCB/GLFW surface - ***********************************************************/ - - glfwGetFramebufferSize(win, &win_h, &win_h); - if (glfwCreateWindowSurface(vk_core.inst, win, 0, &vk_surf) - != VK_SUCCESS) { - fprintf(stderr, "Failed to create XCB surface.\n"); - return 1; - } - - /*********************************************************** - * Initialize Vulkan structs - ***********************************************************/ - - if (!vk_init()) { - return 1; - } - - /*********************************************************** - * Initialize program objects, classes etc - ***********************************************************/ - - if (!init()) { - return 1; - } - - /*********************************************************** - * Rendering loop - ***********************************************************/ - - while(!glfwWindowShouldClose(win)) { - glfwPollEvents(); - display(); - } - - vkDeviceWaitIdle(vk_core.dev); - return 0; -} - -/* static functions */ - -static bool -vk_init() -{ - /* create swapchain */ - if (!vk_create_swapchain(&vk_core, win_w, win_h, false, vk_surf, 0, &vk_chain)) { - fprintf(stderr, "No swapchain was created.\n"); - return false; - } - - if (vk_chain.swapchain == VK_NULL_HANDLE) { - fprintf(stderr, "Invalid swapchain handle.\n"); - return false; - } - - if (!vk_create_sync_objects()) { - fprintf(stderr, "Failed to create sync objects.\n"); - return false; - } - - /* FIXME for the moment one cmd buf. - * But most probably I need to change this later. */ - VkCommandBuffer cmd_buf; - if (!(cmd_buf = vk_create_cmd_buffer(&vk_core))) { - fprintf(stderr, "Failed to create command buffer: %d.\n", 0); - return false; - } - vk_cmd_buffers.push_back(cmd_buf); - - /* FIXME: this part is going to be part of each object's - * renderpass and pipeline */ - - /* create depth attachment (for the moment we are going to use this - * for all images */ - if (!vk_fill_image_props(&vk_core, - win_w, win_h, 1, - 1, 1, 1, - VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - false, true, false, - &vk_depth_att.props)) { - fprintf(stderr, "Unsupported depth image properties\n"); - return false; - } - if (!vk_create_image(&vk_core, &vk_depth_att.props, &vk_depth_att.obj)) { - fprintf(stderr, "Failed to create depth attachment.\n"); - return false; - } - if(!vk_create_image_view(&vk_core, vk_depth_att.obj.img, VK_IMAGE_VIEW_TYPE_2D, - vk_depth_att.props.format, false, - &vk_depth_att.obj.img_view)) { - fprintf(stderr, "Failed to create image view for depth attachment.\n"); - return false; - } - - /* load shaders */ - int vsz, fsz; - char *vsdr = sdr_load("data/main.vert.spv", &vsz); - char *fsdr = sdr_load("data/main.frag.spv", &fsz); - - /* create renderer */ - if (!vk_create_renderer(&vk_core, - vsdr, vsz, fsdr, fsz, - win_w, win_h, 1, - true, false, - 1, &vk_chain.img_props, &vk_depth_att.props, - 0, &vk_rnd)) { - goto fail; - } - - vk_framebuffers.resize(vk_chain.num_images, VK_NULL_HANDLE); - for (uint32_t i = 0; i < vk_chain.num_images; i++) { - if (!vk_create_framebuffer(&vk_core, - win_w, win_h, 1, - &vk_chain.views[i], - &vk_depth_att.obj.img_view, - vk_rnd.renderpass, - &vk_framebuffers[i])) - goto fail; - } - - /* record cmd buffer FIXME: - * should move this and make it part of each renderer - * also add all other stuff needed like uniforms - * descriptor sets spec constants push constants etc - * renderer - */ - - free(vsdr); - free(fsdr); - - return true; - -fail: - free(vsdr); - free(fsdr); - - return false; -} - -static bool -init() -{ - camera = new OrbitCamera; - return true; -} - -static void -cleanup() -{ - delete camera; - - vk_cleanup(); -} - -/* FIXME */ -static int count; -static void -display() -{ - vkWaitForFences(vk_core.dev, 1, &vk_fences[vk_frame_idx], VK_TRUE, UINT64_MAX); - vkResetFences(vk_core.dev, 1, &vk_fences[vk_frame_idx]); - - VkResult err; - do { - err = vkAcquireNextImageKHR(vk_core.dev, vk_chain.swapchain, - UINT64_MAX, - vk_semas[vk_frame_idx].frame_ready, - 0, &vk_current_image); - switch(err) { - case VK_ERROR_OUT_OF_DATE_KHR: - fprintf(stderr, "acquire next image error: VK_ERROR_OUT_OF_DATE_KHR.\n"); - abort(); - break; - case VK_SUBOPTIMAL_KHR: - fprintf(stderr, "AcquireNextImageKHR returned VK_SUBOPTIMAL_KHR, ignored.\n"); - abort(); - break; - case VK_ERROR_SURFACE_LOST_KHR: - vkDestroySurfaceKHR(vk_core.inst, vk_surf, 0); - if (glfwCreateWindowSurface(vk_core.inst, win, 0, &vk_surf) != - VK_SUCCESS) { - fprintf(stderr, "Failed to recreate GLFW/XCB surface.\n"); - } - abort(); - break; - default: - assert(!err); - break; - } - } while (err != VK_SUCCESS); - - /* FIXME update buffer data */ - if (!vk_record_cmd_buffer(&vk_core, - vk_cmd_buffers[0], - &vk_rnd, - 4, vk_fb_color, - vk_framebuffers[vk_current_image], - 2, 0, - 0, 0, win_w, win_h)) { - fprintf(stderr, "Failed to record command buffer.\n"); - abort(); - } - - /* each object should have a command buffer renderpass etc? */ - VkSubmitInfo sinfo; - VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - - memset(&sinfo, 0, sizeof sinfo); - sinfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - sinfo.waitSemaphoreCount = 1; - sinfo.pWaitSemaphores = &vk_semas[vk_frame_idx].frame_ready; - sinfo.pWaitDstStageMask = &wait_stages; - sinfo.commandBufferCount = 1; - sinfo.pCommandBuffers = &vk_cmd_buffers[0]; - sinfo.signalSemaphoreCount = 1; - sinfo.pSignalSemaphores = &vk_semas[vk_frame_idx].frame_done; - - if (vkQueueSubmit(vk_core.queue, 1, &sinfo, vk_fences[vk_frame_idx]) != 0) { - fprintf(stderr, "Failed to submit draw commands.\n"); - abort(); - } - - if (vkQueueWaitIdle(vk_core.queue) != VK_SUCCESS) { - fprintf(stderr, "Failed to wait idle.\n"); - abort(); - } - - if (!vk_queue_present(&vk_chain, vk_core.queue, vk_current_image, - vk_semas[vk_frame_idx].frame_done)) { - abort(); - } - - vk_frame_idx = (vk_frame_idx + 1) % (vk_chain.num_images - 1); - - printf("display %d\n", count++); - printf("current image %u\n", vk_current_image); - printf("frame idx %d\n", vk_frame_idx); -} - -static void -vk_cleanup() -{ - int num_images = vk_chain.num_images - 1; - - vk_destroy_image(&vk_core, &vk_depth_att.obj); - vk_destroy_renderer(&vk_core, &vk_rnd); - - for (size_t i = 0; i < vk_framebuffers.size(); i++) { - vkDestroyFramebuffer(vk_core.dev, vk_framebuffers[i], 0); - } - vk_framebuffers.clear(); - - glfwDestroyWindow(win); - - if (vk_chain.swapchain) { - vk_destroy_swapchain(&vk_core, &vk_chain); - vkDestroySurfaceKHR(vk_core.inst, vk_surf, 0); - } - - if (vk_enable_layers) - return; - - vk_destroy_cmd_buffers(&vk_core, vk_cmd_buffers.size(), vk_cmd_buffers.data()); - vk_cmd_buffers.clear(); - - vk_destroy_fences(&vk_core, vk_fences.size(), vk_fences.data()); - vk_fences.clear(); - - for (int i = 0; i < num_images; i++) - vk_destroy_semaphores(&vk_core, &vk_semas[i]); - free(vk_semas); - - for (size_t i = 0; i < vk_cmd_buffers.size(); i++) - vk_destroy_cmd_buffers(&vk_core, vk_cmd_buffers.size(), vk_cmd_buffers.data()); - vk_cmd_buffers.clear(); - - glfwTerminate(); - - vk_cleanup_ctx(&vk_core); -} - -static bool -vk_create_sync_objects() -{ - VkFenceCreateInfo finfo; - memset(&finfo, 0, sizeof finfo); - finfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - finfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - VkSemaphoreCreateInfo sinfo; - memset(&sinfo, 0, sizeof sinfo); - sinfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - vk_fences.resize(vk_chain.num_images - 1, VK_NULL_HANDLE); - - vk_semas = (vk_semaphores *)malloc(sizeof(vk_semaphores) * (vk_chain.num_images - 1)); - for (uint32_t i = 0; i < (vk_chain.num_images - 1); i++) { - if (vkCreateFence(vk_core.dev, &finfo, 0, &vk_fences[i]) != VK_SUCCESS) { - fprintf(stderr, "Failed to create fence: %d\n", i); - return false; - } - - if (vkCreateSemaphore(vk_core.dev, &sinfo, 0, &vk_semas[i].frame_ready) != VK_SUCCESS) { - fprintf(stderr, "Failed to create frame_ready semaphore: %d\n", i); - return false; - } - - if (vkCreateSemaphore(vk_core.dev, &sinfo, 0, &vk_semas[i].frame_done) != VK_SUCCESS) { - fprintf(stderr, "Failed to create frame_done semaphore: %d\n", i); - return false; - } - } - - return true; -} - -/* glfw callbacks */ - -static void -clb_reshape(GLFWwindow *win, - int width, - int height) -{ - aspect = (float)width / (float)height; - mproj = calc_projection_matrix(45, aspect, 0.5, 1000.0f); - - /* FIXME near and far clipping planes */ - vk_set_viewport(&vk_core, vk_cmd_buffers[0], - 0, 0, win_w, win_h, 0.0f, 1.0f); - win_w = width; - win_h = height; -} - -static void -clb_key(GLFWwindow *win, int key, int scancode, - int action, int mods) -{ - if (action == GLFW_REPEAT) return; - - if (action == GLFW_PRESS) { - switch(key) { - case GLFW_KEY_ESCAPE: - glfwSetWindowShouldClose(win, GLFW_TRUE); - exit(0); - case ' ': - move_camera = !move_camera; - break; - default: - break; - } - } -} - -static double prev_x, prev_y; -static bool button[8]; - -static void -clb_motion(GLFWwindow *win, - double x, - double y) -{ - double dx = x - prev_x; - double dy = y - prev_y; - - prev_x = x; - prev_y = y; - - if(button[0]) { - cam_theta += dx * 0.5; - cam_phi += dy * 0.5; - - if(cam_phi < 0) - cam_phi = 0; - if(cam_phi > 90) - cam_phi = 90; - } - - if(button[1]) { - cam_dist += dy * 0.1; - if(cam_dist < 0.0) { - cam_dist = 0.0; - } - } -} - -static void -clb_mouse(GLFWwindow *win, - int button, - int action, - int mods) -{ -}