From 9148ff7614b1dc22fd5d1dcf6d74e2fb4ff13706 Mon Sep 17 00:00:00 2001 From: Eleni Maria Stea Date: Wed, 4 Oct 2017 08:51:46 +0300 Subject: [PATCH] added a vulkan util (vkutil.h/.cc) surface, window, swapchain, command buffer, command pool --- src/gfxapi.cc | 2 +- src/gfxapi.h | 1 + src/main.cc | 5 +- src/opengl/opengl.cc | 4 +- src/vulkan/vk.cc | 368 ++-------------------- src/vulkan/vk.h | 2 - src/vulkan/vkutil.cc | 852 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/vulkan/vkutil.h | 59 ++++ 8 files changed, 947 insertions(+), 346 deletions(-) create mode 100644 src/vulkan/vkutil.cc create mode 100644 src/vulkan/vkutil.h diff --git a/src/gfxapi.cc b/src/gfxapi.cc index 2987a59..5296677 100644 --- a/src/gfxapi.cc +++ b/src/gfxapi.cc @@ -16,7 +16,7 @@ void (*gfx_clear)(float r, float g, float b); void (*gfx_viewport)(int x, int y, int width, int height); void (*gfx_zbuffer)(bool enable); void (*gfx_cull_face)(Gfx_cull_face cf); - +void (*gfx_reshape)(int width, int height); bool gfx_init(Gfx_API api) { diff --git a/src/gfxapi.h b/src/gfxapi.h index 1e6cd2b..62a8a3a 100644 --- a/src/gfxapi.h +++ b/src/gfxapi.h @@ -21,6 +21,7 @@ extern void (*gfx_clear)(float r, float g, float b); extern void (*gfx_viewport)(int x, int y, int width, int height); extern void (*gfx_zbuffer)(bool enable); extern void (*gfx_cull_face)(Gfx_cull_face cf); +extern void (*gfx_reshape)(int width, int height); bool gfx_init(Gfx_API api); void gfx_cleanup(); diff --git a/src/main.cc b/src/main.cc index 6b1050b..4e2c72f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -102,7 +102,7 @@ int main(int argc, char **argv) } //TODO - return 0; + //return 0; glfwSetKeyCallback(win, clbk_key); glfwSetCursorPosCallback(win, clbk_motion); @@ -318,6 +318,7 @@ static void clbk_mouse(GLFWwindow *win, int bn, int action, int mods) static void clbk_reshape(GLFWwindow *win, int width, int height) { + gfx_reshape(width, height); gfx_viewport(0, 0, width, height); aspect = (float)width / (float)height; mprojection = calc_projection_matrix(45, aspect, 0.5, 1000.0); @@ -388,4 +389,4 @@ static bool gen_poisson(std::vector &points, float min_dist, float radius) } } return false; -} \ No newline at end of file +} diff --git a/src/opengl/opengl.cc b/src/opengl/opengl.cc index 9b220ab..f6a7cef 100644 --- a/src/opengl/opengl.cc +++ b/src/opengl/opengl.cc @@ -13,6 +13,7 @@ static void clear(float r, float g, float b); static void viewport(int x, int y, int width, int height); static void zbuffer(bool enable); static void cull_face(Gfx_cull_face cf); +static void reshape(int width, int height) {}; bool init_opengl() { @@ -41,6 +42,7 @@ bool init_opengl() gfx_viewport = viewport; gfx_zbuffer = zbuffer; gfx_cull_face = cull_face; + gfx_reshape = reshape; // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); return true; @@ -88,4 +90,4 @@ static void cull_face(Gfx_cull_face cf) glCullFace(GL_BACK); break; } -} \ No newline at end of file +} diff --git a/src/vulkan/vk.cc b/src/vulkan/vk.cc index 105caba..871824f 100644 --- a/src/vulkan/vk.cc +++ b/src/vulkan/vk.cc @@ -4,36 +4,20 @@ #include #include #include - #include #include #include "gfxapi.h" +#include "vkutil.h" /* global variables */ extern GLFWwindow *win; extern int win_w; extern int win_h; -/* static variables */ -static std::vector enabled_extension_names; -static VkInstance inst; -static VkDevice device; -static VkPhysicalDevice pdev; -static VkSurfaceKHR surface; -static uint32_t device_mem_idx; -static uint32_t num_queues; -static uint32_t qfamily_idx; - -static const char *print_vulkan_error(VkResult error); -static const char *dev_type_str(VkPhysicalDeviceType type); -static const char *heap_flags_str(VkMemoryHeapFlags flags); -static const char *memtype_flags_str(VkMemoryPropertyFlags flags); -static const char *queue_flags_str(VkQueueFlags flags); - -/* static fumctions */ -static bool create_instance(); -static bool create_device(); +/* static functions */ +static void error_callback(int error, const char *descr); +static void reshape(int width, int height); bool init_vulkan() { @@ -47,12 +31,14 @@ bool init_vulkan() return false; } - if(!create_instance()) { - fprintf(stderr, "Failed to enable validation.\n"); + glfwSetErrorCallback(error_callback); + + if(!vku_create_device()) { + fprintf(stderr, "Failed to initialize vulkan.\n"); return false; } - if(!glfwGetPhysicalDevicePresentationSupport(inst, pdev, qfamily_idx)) { + if(!glfwGetPhysicalDevicePresentationSupport(vkinst, vkpdev, vkqfamily)) { fprintf(stderr, "Presentation support not found.\n"); return false; } @@ -63,11 +49,13 @@ bool init_vulkan() return false; } - if(VkResult err = glfwCreateWindowSurface(inst, win, 0, &surface)) { - fprintf(stderr, "Failed to create KHR surface: %s\n", print_vulkan_error(err)); + if(VkResult err = glfwCreateWindowSurface(vkinst, win, 0, &vksurface)) { + fprintf(stderr, "Failed to create KHR surface: %s\n", vku_get_vulkan_error_str(err)); return false; } + gfx_reshape = reshape; + return true; } @@ -75,329 +63,29 @@ void cleanup_vulkan() { //TODOs according to the book: // 1- make sure all threads have been terminated (when I add threads) - // 2- destroy objects in *reverse* order - - vkDestroySurfaceKHR(inst, surface, 0); - - if(vkDeviceWaitIdle(device) == VK_SUCCESS) { - vkDestroyDevice(device, 0); - vkDestroyInstance(inst, 0); - } -} - -static bool create_instance() -{ - /* enable layers */ - uint32_t layer_count = 0; - std::vector enabled_layers; - - if(vkEnumerateInstanceLayerProperties(&layer_count, 0) != VK_SUCCESS) { - fprintf(stderr, "Failed to query layer properties.\n"); - return false; - } - - if(layer_count > 0) { - VkLayerProperties *layers = (VkLayerProperties *)alloca(layer_count * sizeof *layers); - vkEnumerateInstanceLayerProperties(&layer_count, layers); - for(uint32_t i=0; i enabled_extensions; - - if(vkEnumerateInstanceExtensionProperties(0, &extensions_count, 0) != VK_SUCCESS) { - fprintf(stderr, "Failed to enumerate instance extension properties\n"); - return false; - } - - if(extensions_count > 0) { - VkExtensionProperties *extensions = (VkExtensionProperties *)alloca(extensions_count * sizeof *extensions); - vkEnumerateInstanceExtensionProperties(0, &extensions_count, extensions); - - for(uint32_t i=0; i 0) { - VkLayerProperties *layers = (VkLayerProperties*)alloca(layer_count * sizeof *layers); - vkEnumerateDeviceLayerProperties(pdev, &layer_count, layers); - printf("%u layers found.\n", layer_count); - for(uint32_t i=0; i - bool init_vulkan(); void cleanup_vulkan(); diff --git a/src/vulkan/vkutil.cc b/src/vulkan/vkutil.cc new file mode 100644 index 0000000..051ee4d --- /dev/null +++ b/src/vulkan/vkutil.cc @@ -0,0 +1,852 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "vkutil.h" + +/* global variables */ + +VkSwapchainKHR vkswapchain; +VkImage *vkswapchain_images; +int vknext_swapchain_image; +VkSurfaceKHR vksurface; +VkInstance vkinst; +VkPhysicalDevice vkpdev; +VkDevice vkdev; +VkQueue vkq; +VkCommandPool vkcmdpool; +VkCommandBuffer vkcmdbuf; /* primary command buffer */ +int vkqfamily; + +/* static functions */ +static const char *get_device_name_str(VkPhysicalDeviceType type); +static const char *get_memtype_flags_str(VkMemoryPropertyFlags flags); +static const char *get_queue_flags_str(VkQueueFlags flags); +static const char *get_mem_size_str(long sz); +static int ver_major(uint32_t ver); +static int ver_minor(uint32_t ver); +static int ver_patch(uint32_t ver); + +/* static variables */ +static VkPhysicalDevice *phys_devices; + +static int sel_dev; +static int sel_qfamily; + +static VkExtensionProperties *vkext, *vkdevext; +static uint32_t vkext_count, vkdevext_count; + +bool vku_have_extension(const char *name) +{ + if(!vkext) { + vkext_count = 0; + vkEnumerateInstanceExtensionProperties(0, &vkext_count, 0); + if(vkext_count) { + if(!(vkext = (VkExtensionProperties *)malloc(vkext_count * sizeof *vkext))) { + perror("failed to allocate instance extension list"); + return false; + } + vkEnumerateInstanceExtensionProperties(0, &vkext_count, vkext); + + printf("instance extensions:\n"); + for(int i=0; i<(int)vkext_count; i++) { + printf(" %s (ver: %u)\n", vkext[i].extensionName, (unsigned int)vkext[i].specVersion); + } + } + } + + for(int i=0; i<(int)vkext_count; i++) { + if(strcmp(vkext[i].extensionName, name) == 0) { + return true; + } + } + return false; +} + +bool vku_have_device_extension(const char *name) +{ + if(sel_dev < 0) return false; + + if(!vkdevext) { + vkdevext_count = 0; + vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, 0); + if(vkdevext_count) { + if(!(vkdevext = (VkExtensionProperties *)malloc(vkdevext_count * sizeof *vkdevext))) { + perror("failed to allocate device extension list"); + return false; + } + vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, vkdevext); + + printf("selected device extensions:\n"); + for(int i=0; i<(int)vkdevext_count; i++) { + printf(" %s (ver: %u)\n", vkdevext[i].extensionName, (unsigned int)vkdevext[i].specVersion); + } + } + } + + for(int i=0; i<(int)vkdevext_count; i++) { + if(strcmp(vkdevext[i].extensionName, name) == 0) { + return true; + } + } + return false; +} + +bool vku_create_device() +{ + VkInstanceCreateInfo inst_info; + VkDeviceCreateInfo dev_info; + VkDeviceQueueCreateInfo queue_info; + VkCommandPoolCreateInfo cmdpool_info; + uint32_t num_devices; + float qprio = 0.0f; + + static const char *ext_names[] = { + "VK_KHR_xcb_surface", + "VK_KHR_surface" + }; + + static const char *devext_names[] = { + "VK_KHR_swapchain" + }; + + sel_dev = -1; + sel_qfamily = -1; + + for(unsigned int i=0; ibuf) != 0) { + fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage); + return 0; + } + // TODO back with memory + return buf; +} + +void vku_destroy_buffer(struct vku_buffer *buf) +{ + if(buf) { + vkDestroyBuffer(vkdev, buf->buf, 0); + free(buf); + } +} + +void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs, + VkBuffer src, int soffs, int size) +{ + VkBufferCopy copy; + copy.size = size; + copy.srcOffset = soffs; + copy.dstOffset = doffs; + + vkCmdCopyBuffer(cmdbuf, src, dest, 1, ©); +} + +/* paste + +static bool create_instance() +{ + uint32_t layer_count = 0; + std::vector enabled_layers; + + if(vkEnumerateInstanceLayerProperties(&layer_count, 0) != VK_SUCCESS) { + fprintf(stderr, "Failed to query layer properties.\n"); + return false; + } + + if(layer_count > 0) { + VkLayerProperties *layers = (VkLayerProperties *)alloca(layer_count * sizeof *layers); + vkEnumerateInstanceLayerProperties(&layer_count, layers); + for(uint32_t i=0; i enabled_extensions; + + if(vkEnumerateInstanceExtensionProperties(0, &extensions_count, 0) != VK_SUCCESS) { + fprintf(stderr, "Failed to enumerate instance extension properties\n"); + return false; + } + + if(extensions_count > 0) { + VkExtensionProperties *extensions = (VkExtensionProperties *)alloca(extensions_count * sizeof *extensions); + vkEnumerateInstanceExtensionProperties(0, &extensions_count, extensions); + + for(uint32_t i=0; i 0) { + VkLayerProperties *layers = (VkLayerProperties*)alloca(layer_count * sizeof *layers); + vkEnumerateDeviceLayerProperties(pdev, &layer_count, layers); + printf("%u layers found.\n", layer_count); + for(uint32_t i=0; i> 22) & 0x3ff; +} + +static int ver_minor(uint32_t ver) +{ + return (ver >> 12) & 0x3ff; +} + +static int ver_patch(uint32_t ver) +{ + return ver & 0xfff; +} + +static const char *get_mem_size_str(long sz) +{ + static char str[64]; + static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 }; + int uidx = 0; + sz *= 10; + + while(sz >= 10240 && unitstr[uidx + 1]) { + sz /= 1024; + ++uidx; + } + sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]); + return str; +} diff --git a/src/vulkan/vkutil.h b/src/vulkan/vkutil.h new file mode 100644 index 0000000..f9cbf94 --- /dev/null +++ b/src/vulkan/vkutil.h @@ -0,0 +1,59 @@ +#ifndef VKUTIL_H_ +#define VKUTIL_H_ + +#include + +extern VkSwapchainKHR vkswapchain; +extern VkImage *vkswapchain_images; +extern VkSurfaceKHR vksurface; +extern VkInstance vkinst; +extern VkPhysicalDevice vkpdev; +extern VkDevice vkdev; +extern VkQueue vkq; +extern VkCommandPool vkcmdpool; +extern VkCommandBuffer vkcmdbuf; /* primary command buffer */ +extern int vkqfamily; +extern int vknext_swapchain_image; + +struct vku_buffer { + VkBuffer buf; + VkDeviceMemory mem_pool; + int mem_start, mem_size; +}; + +/* extensions */ +bool vku_have_extension(const char *name); +bool vku_have_device_extension(const char *name); + +/* device */ +bool vku_create_device(); +void vku_cleanup(); + +/* command buffers */ +VkCommandBuffer vku_alloc_cmdbuf(VkCommandPool pool, VkCommandBufferLevel level); +void vku_free_cmdbuf(VkCommandPool pool, VkCommandBuffer buf); + +void vku_begin_cmdbuf(VkCommandBuffer buf, unsigned int flags); +void vku_end_cmdbuf(VkCommandBuffer buf); +void vku_reset_cmdbuf(VkCommandBuffer buf); + +void vku_submit_cmdbuf(VkQueue q, VkCommandBuffer buf, VkFence done_fence); + +/* swapchain */ +VkSwapchainKHR vku_create_swapchain(VkSurfaceKHR surf, int xsz, int ysz, int n, + VkPresentModeKHR pmode, VkSwapchainKHR prev); +VkImage *vku_get_swapchain_images(VkSwapchainKHR sc, int *count); +int vku_get_next_image(VkSwapchainKHR sc); +void vku_present(VkSwapchainKHR sc, int img_idx); + +/* buffers */ +vku_buffer *vku_create_buffer(int sz, unsigned int usage); +void vku_destroy_buffer(vku_buffer *buf); + +void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs, + VkBuffer src, int soffs, int size); + +/* other */ +const char *vku_get_vulkan_error_str(VkResult error); + +#endif // VKUTIL_H_ \ No newline at end of file -- 1.7.10.4