From 638b86fbbdb0307faf21c04532d8f5ceb3b29884 Mon Sep 17 00:00:00 2001 From: Eleni Maria Stea Date: Wed, 2 Feb 2022 17:39:55 +0200 Subject: [PATCH] removed all c++ --- Makefile | 7 +- src/camera.cc | 60 ------- src/camera.h | 34 ---- src/main.c | 546 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cc | 548 --------------------------------------------------------- 5 files changed, 549 insertions(+), 646 deletions(-) delete mode 100644 src/camera.cc delete mode 100644 src/camera.h create mode 100644 src/main.c delete mode 100644 src/main.cc diff --git a/Makefile b/Makefile index 63fe0e1..bc47b29 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ src = $(wildcard src/*.c) -ccsrc = $(wildcard src/*.cc) -obj = $(src:.c=.o) $(ccsrc:.cc=.o) +obj = $(src:.c=.o) dep = $(obj:.o=.d) vsdr = $(wildcard data/*.vert) fsdr = $(wildcard data/*.frag) @@ -9,13 +8,13 @@ spv = $(subst .vert,.vert.spv,$(vsdr)) \ bin = rt dbg = -g -inc = -Isubmodule/gmath/src -I/usr/include -Isubmodule/libimago/src -I/usr/local/include +inc = -I/usr/include -Isubmodule/libimago/src -I/usr/local/include CC = gcc CXX = g++ CFLAGS = -pedantic -Wall $(dbg) -MMD CXXFLAGS = -pedantic -Wall $(dbg) -MMD $(opt) $(inc) -LDFLAGS = -lvulkan -lglfw -lassimp -limago -lgmath +LDFLAGS = -lvulkan -lglfw -lassimp -limago .PHONY: all all: $(bin) $(spv) diff --git a/src/camera.cc b/src/camera.cc deleted file mode 100644 index 620bec4..0000000 --- a/src/camera.cc +++ /dev/null @@ -1,60 +0,0 @@ -#include - -#include - -#include "camera.h" - -Camera::Camera() {} -Camera::~Camera() {} - -OrbitCamera::OrbitCamera() -{ - phi = theta = distance = 0; -} - -OrbitCamera::~OrbitCamera() {} - -void OrbitCamera::set_orbit_params(float theta, float phi, float distance) -{ - this->phi = phi; - this->theta = theta; - this->distance = distance; -} - -Mat4 OrbitCamera::get_view_matrix() const -{ - Mat4 view_matrix; - view_matrix.translation(-position); - view_matrix.rotate_y(theta * (float)M_PI / 180); - view_matrix.rotate_x(phi * (float)M_PI / 180); - view_matrix.translate(Vec3(0, 0, -distance)); - - return view_matrix; -} - -Mat4 calc_projection_matrix(float fov_deg, float aspect, float n, float f) -{ - float fov = fov_deg / 180 * M_PI; - - float tmp; - tmp = 1 / tan(fov / 2.0); - - /* near - far clipping planes */ - float range = n - f; - - Mat4 pmat = Mat4( - tmp/aspect, 0, 0, 0, - 0, tmp, 0, 0, - 0, 0, (f + n) / range, -1, - 0, 0, 2 * n * f / range, 0 - ); - - return pmat; -} - -void OrbitCamera::set_position(float x, float y, float z) -{ - position.x = x; - position.y = y; - position.z = z; -} diff --git a/src/camera.h b/src/camera.h deleted file mode 100644 index 0f70040..0000000 --- a/src/camera.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef CAMERA_H_ -#define CAMERA_H_ - -#include - -class Camera { -public: - Camera(); - virtual ~Camera(); - - virtual Mat4 get_view_matrix() const = 0; -}; - -class OrbitCamera : public Camera { -protected: - float theta; - float phi; - float distance; - - Vec3 position; - -public: - OrbitCamera(); - virtual ~OrbitCamera(); - - virtual Mat4 get_view_matrix() const override; - - void set_orbit_params(float theta, float phi, float distance); - void set_position(float x, float y, float z); -}; - -Mat4 calc_projection_matrix(float fov_deg, float aspect, float n, float f); - -#endif // CAMERA_H_ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c275372 --- /dev/null +++ b/src/main.c @@ -0,0 +1,546 @@ +#include + +#define GLFW_INCLUDE_VULKAN +#include + +#include +#include +#include + +/* extern "C": vulkan framework */ +#include "vk.h" +#include "util.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; + +#if 0 +static Vec3 cam_pos; +static OrbitCamera *camera; +static Mat4 mproj; +#endif + +static float aspect; + +/* 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 VkFramebuffer *vk_framebuffers; + +/* for the moment: one cmd buffer per swapchain image */ +static VkCommandBuffer *vk_cmd_buffers; +static VkFence *vk_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() +{ + uint32_t i; + + /* 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 = (VkCommandBuffer*)malloc(vk_chain.num_images * sizeof *vk_cmd_buffers); + memset(vk_cmd_buffers, 0, vk_chain.num_images * sizeof *vk_cmd_buffers); + vk_cmd_buffers[0] = 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 = (VkFramebuffer*)malloc(vk_chain.num_images * sizeof vk_framebuffers[0]); + memset(vk_framebuffers, VK_NULL_HANDLE, vk_chain.num_images * sizeof vk_framebuffers[0]); + + for (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() +{ + return true; +} + +static void +cleanup() +{ + 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() +{ + uint32_t i; + 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 (i = 0; i < vk_chain.num_images; i++) { + vkDestroyFramebuffer(vk_core.dev, vk_framebuffers[i], 0); + } + + 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_chain.num_images, vk_cmd_buffers); + + vk_destroy_fences(&vk_core, vk_chain.num_images, vk_fences); + + for (int i = 0; i < num_images; i++) + vk_destroy_semaphores(&vk_core, &vk_semas[i]); + free(vk_semas); + + 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 = (VkFence*)malloc((vk_chain.num_images - 1) * sizeof *vk_fences); + memset(vk_fences, VK_NULL_HANDLE, (vk_chain.num_images - 1) * sizeof *vk_fences); + + vk_semas = (struct vk_semaphores *)malloc(sizeof(struct vk_semaphores) * (vk_chain.num_images - 1)); + memset(vk_semas, VK_NULL_HANDLE, (vk_chain.num_images - 1) * sizeof *vk_fences); + + 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; +#if 0 + mproj = calc_projection_matrix(45, aspect, 0.5, 1000.0f); +#endif + + /* 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) +{ +} 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) -{ -} -- 1.7.10.4