From 8fb0cca684e078cd2537070c53ad970ebbc2e9a7 Mon Sep 17 00:00:00 2001 From: Eleni Maria Stea Date: Tue, 23 Jan 2018 12:07:48 +0200 Subject: [PATCH] rewriting swapchain/image/allocation parts atm doing the simplest thing, will optimize allocator etc later --- src/vulkan/allocator.cc | 23 ++ src/vulkan/allocator.h | 9 + src/vulkan/image.cc | 36 +++ src/vulkan/image.h | 10 + src/vulkan/vk.cc | 577 +++++++++++++++++++++++++++++++++++------------ src/vulkan/vkutil.cc | 111 +++++---- src/vulkan/vkutil.h | 13 +- 7 files changed, 588 insertions(+), 191 deletions(-) create mode 100644 src/vulkan/allocator.cc create mode 100644 src/vulkan/allocator.h create mode 100644 src/vulkan/image.cc create mode 100644 src/vulkan/image.h diff --git a/src/vulkan/allocator.cc b/src/vulkan/allocator.cc new file mode 100644 index 0000000..5228a72 --- /dev/null +++ b/src/vulkan/allocator.cc @@ -0,0 +1,23 @@ +#include +#include + +#include "allocator.h" +#include "vk.h" +#include "vkutil.h" + +VkDeviceMemory vk_allocate(int size) +{ + VkDeviceMemory gpu_mem; + + VkMemoryAllocateInfo gpu_alloc_inf; + memset(&gpu_alloc_inf, 0, sizeof gpu_alloc_inf); + gpu_alloc_inf.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + gpu_alloc_inf.allocationSize = size; + + if(vkAllocateMemory(vk_device, &gpu_alloc_inf, 0, &gpu_mem) != VK_SUCCESS) { + fprintf(stderr, "Failed to allocate device memory, mem size: %d\n"); + return 0; + } + + return gpu_mem; +} diff --git a/src/vulkan/allocator.h b/src/vulkan/allocator.h new file mode 100644 index 0000000..dd730e3 --- /dev/null +++ b/src/vulkan/allocator.h @@ -0,0 +1,9 @@ +#ifndef ALLOCATOR_H_ +#define ALLOCATOR_H_ + +#include + +VkDeviceMemory vk_allocate(int size); +void vk_free(VkDeviceMemory gpu_memory); + +#endif // ALLOCATOR_H_ diff --git a/src/vulkan/image.cc b/src/vulkan/image.cc new file mode 100644 index 0000000..780bfa0 --- /dev/null +++ b/src/vulkan/image.cc @@ -0,0 +1,36 @@ +#include +#include + +#include "allocator.h" +#include "image.h" +#include "vk.h" +#include "vkutil.h" + +bool vk_image_set_layout(VkCommandBuffer cmd_buf, VkImage img, VkImageAspectFlags aspect_flags, + VkImageLayout old_layout, VkImageLayout new_layout, VkAccessFlagBits access_mask) +{ + VkImageMemoryBarrier imb; + memset(&imb, 0, sizeof imb); + imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imb.srcAccessMask = access_mask; + imb.oldLayout = old_layout; + imb.newLayout = new_layout; + imb.image = img; + imb.subresourceRange = {aspect_flags, 0, 1, 0, 1}; + + if(new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + imb.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + } else if (new_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } else if (new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + imb.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } else if (new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + imb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + } + + VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + VkPipelineStageFlags dst_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + + vkCmdPipelineBarrier(cmd_buf, src_stages, dst_stages, 0, 0, 0, 0, 0, 1, &imb); + return true; +} diff --git a/src/vulkan/image.h b/src/vulkan/image.h new file mode 100644 index 0000000..7427c6a --- /dev/null +++ b/src/vulkan/image.h @@ -0,0 +1,10 @@ +#ifndef IMAGE_H_ +#define IMAGE_H_ + +#include + +bool vk_image_set_layout(VkCommandBuffer cmd_buf, VkImage img, VkImageAspectFlags aspect_flags, + VkImageLayout old_layout, VkImageLayout new_layout, VkAccessFlagBits access_mask); + + +#endif diff --git a/src/vulkan/vk.cc b/src/vulkan/vk.cc index 0e3725b..f5829ab 100644 --- a/src/vulkan/vk.cc +++ b/src/vulkan/vk.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -9,14 +10,30 @@ #include +#include "allocator.h" #include "gfxapi.h" +#include "image.h" #include "vkutil.h" +#include "vk.h" /* global variables */ extern GLFWwindow *win; extern int win_w; extern int win_h; +static VkCommandBuffer cmd_buf; // command buffer used at zbuffer creation +//depth buffer +static VkImage dimg; +static VkImageView dview; +//swapchain +static VkImage *images; +static VkImageView *iviews; +static uint32_t num_images; + +/* static variables */ +static VkDeviceMemory gpu_mem; // to be replaced when I fix the allocator +// zbuffer image, view: + VkCommandBuffer *swapchain_cmd_bufs; /* static functions */ @@ -30,20 +47,16 @@ static void swapbuffers(); static void begin_drawing(); static void end_drawing(); -static bool create_swapchain_cmd_bufs(VkCommandPool vkcmdpool); +static bool create_swapchain(); +static bool begin_command_buffer(); +static bool create_swapchain_image_views(VkFormat format); +static bool create_zbuffer(); + +static bool create_swapchain_cmd_bufs(VkCommandPool vk_pool); static bool record_cmd_clear(float r, float g, float b); bool init_vulkan() { - gfx_clear = clear; - gfx_viewport = viewport; - gfx_zbuffer = zbuffer; - gfx_cull_face = cull_face; - gfx_reshape = reshape; - gfx_swapbuffers = swapbuffers; - gfx_begin_drawing = begin_drawing; - gfx_end_drawing = end_drawing; - if(!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW.\n"); return false; @@ -54,14 +67,16 @@ bool init_vulkan() return false; } + //TODO: remove later glfwSetErrorCallback(error_callback); + /* create device and command pool! */ if(!vku_create_device()) { fprintf(stderr, "Failed to initialize vulkan.\n"); return false; } - if(!glfwGetPhysicalDevicePresentationSupport(vkinst, vkpdev, vkqfamily)) { + if(!glfwGetPhysicalDevicePresentationSupport(vkinst, vk_physical, vkqfamily)) { fprintf(stderr, "Presentation support not found.\n"); return false; } @@ -72,46 +87,326 @@ bool init_vulkan() return false; } - if(VkResult err = glfwCreateWindowSurface(vkinst, win, 0, &vksurface)) { - fprintf(stderr, "Failed to create KHR surface: %s\n", vku_get_vulkan_error_str(err)); + VkResult res = glfwCreateWindowSurface(vkinst, win, 0, &vk_surface); + if(res != VK_SUCCESS) { + fprintf(stderr, "Failed to create KHR surface: %s\n", vku_get_vulkan_error_str(res)); return false; } + if(!create_swapchain()) { + fprintf(stderr, "Failed to create swapchain.\n"); + return false; + } + + cmd_buf = VK_NULL_HANDLE; + if(!begin_command_buffer()) { + fprintf(stderr, "Failed to start VK_NULL_HANDLE command buffer.\n"); + return false; + } + + if(!create_zbuffer()) { + fprintf(stderr, "Failed to create depth buffer.\n"); + return false; + } + + gfx_clear = clear; + gfx_viewport = viewport; + gfx_zbuffer = zbuffer; + gfx_cull_face = cull_face; + gfx_reshape = reshape; + gfx_swapbuffers = swapbuffers; + gfx_begin_drawing = begin_drawing; + gfx_end_drawing = end_drawing; + + +/* if(!vku_create_semaphores()) return false; - if(!(vkswapchain = vku_create_swapchain(vksurface, win_w, win_h, 2, - VK_PRESENT_MODE_FIFO_KHR, 0))) { + if(!(vk_swapchain = vku_create_swapchain(vk_surface, win_w, win_h, 2, + VK_PRESENT_MODE_IMMEDIATE_KHR, 0))) { fprintf(stderr, "Failed to create swapchain.\n"); return false; } - vkswapchain_images = vku_get_swapchain_images(vkswapchain, &vknum_swapchain_images); + vkswapchain_images = vku_get_swapchain_images(vk_swapchain, &vknum_swapchain_images); if(!vkswapchain_images) { fprintf(stderr, "Failed to get swapchain images.\n"); return false; } - /* vkswapchain_views = vku_create_image_views(vkswapchain_images, vknum_swapchain_images); - if(!vkswapchain_views) { - fprintf(stderr, "Failed to create swapchain image views.\n"); - delete [] vkswapchain_images; +// vkswapchain_views = vku_create_image_views(vkswapchain_images, vknum_swapchain_images); +// if(!vkswapchain_views) { +// fprintf(stderr, "Failed to create swapchain image views.\n"); +// delete [] vkswapchain_images; +// return false; +// } + + if(!create_swapchain_cmd_bufs(vk_pool)) { + return false; + } + + if(!record_cmd_clear(1.0, 0.1, 0.1)) + return false; + */ + + return true; +} + +static bool create_swapchain() +{ + /* surface capabilities */ + VkSurfaceCapabilitiesKHR scap; + if(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical, vk_surface, &scap) != VK_SUCCESS) { + fprintf(stderr, "Failed to get physical device surface capabilities\n"); + return false; + } + + /* presentation modes */ + uint32_t prmode_cnt; + if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, 0) != VK_SUCCESS) { + fprintf(stderr, "Failed to get physical device surface presentation modes count.\n"); + return false; + } + + if(prmode_cnt == 0) { + fprintf(stderr, "Presentation modes not found.\n"); + return false; + } + + VkPresentModeKHR scmode = VK_PRESENT_MODE_FIFO_KHR; + VkPresentModeKHR *modes = new VkPresentModeKHR[prmode_cnt]; + + if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, modes) != VK_SUCCESS) { + fprintf(stderr, "Failed to get physical device presentation modes.\n"); + return false; + } + + for(uint32_t i=0; i 0 && num_images > scap.maxImageCount) + num_images = scap.maxImageCount; + + printf("num_images : %u\n", num_images); + assert(num_images > 0); + + /* transform flags */ + VkSurfaceTransformFlagBitsKHR pre_transf = scap.currentTransform; + if(scap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + pre_transf = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + + /* find suitable colorspace, format */ + uint32_t fcount; + if(vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical, vk_surface, &fcount, 0) != VK_SUCCESS) { + fprintf(stderr, "Failed to get format count for physical device.\n"); + return false; + } + if(fcount == 0) { + fprintf(stderr, "No color formats were found.\n"); + return false; + } + + VkFormat format; + VkColorSpaceKHR colorspace; + + VkSurfaceFormatKHR *formats = new VkSurfaceFormatKHR[fcount]; + if(vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical, vk_surface, &fcount, formats) != VK_SUCCESS) { + fprintf(stderr, "Failed to get surface formats.\n"); + return false; + } + if((fcount == 1) && (formats[0].format == VK_FORMAT_UNDEFINED)) { + format = VK_FORMAT_B8G8R8_UNORM; + } else { + format = formats[0].format; + } + colorspace = formats[0].colorSpace; + + /* creating the swapchain */ + VkSwapchainCreateInfoKHR sinfo; + memset(&sinfo, 0, sizeof sinfo); + + sinfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + sinfo.surface = vk_surface; + sinfo.minImageCount = num_images; + sinfo.imageFormat = format; + sinfo.imageColorSpace = colorspace; + sinfo.imageExtent = scextent; + sinfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + sinfo.preTransform = pre_transf; + sinfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + sinfo.imageArrayLayers = 1; + sinfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + sinfo.presentMode = scmode; + sinfo.oldSwapchain = VK_NULL_HANDLE; //TODO + sinfo.clipped = VK_TRUE; //TODO + + if(vkCreateSwapchainKHR(vk_device, &sinfo, 0, &vk_swapchain) != VK_SUCCESS) { + fprintf(stderr, "Failed to create swapchain.\n"); + return false; + } + + if(vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &num_images, 0) != VK_SUCCESS) { + fprintf(stderr, "Failed to get the number of the swapchain images.\n"); + return false; + } + + images = new VkImage[num_images]; + if(vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &num_images, images) != VK_SUCCESS) { + fprintf(stderr, "Failed to get the swapchain images.\n"); + return false; + } + assert(images); + + if(!create_swapchain_image_views(format)) { + fprintf(stderr, "Failed to create image views for the swapchain images.\n"); + return false; + } + + // create renderpass + + + return true; +} + +static bool create_swapchain_image_views(VkFormat format) +{ + VkImageViewCreateInfo ivinf; + memset(&ivinf, 0, sizeof ivinf); + + ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + ivinf.format = format; + ivinf.components = { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }; + ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + ivinf.subresourceRange.levelCount = 1; + ivinf.subresourceRange.layerCount = 1; + ivinf.viewType = VK_IMAGE_VIEW_TYPE_2D; + + iviews = new VkImageView[num_images]; + for(uint32_t i=0; ibuf) != 0) { + if(vkCreateBuffer(vk_device, &binfo, 0, &buf->buf) != 0) { fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage); return 0; } @@ -554,7 +577,7 @@ struct vku_buffer *vku_create_buffer(int sz, unsigned int usage) void vku_destroy_buffer(struct vku_buffer *buf) { if(buf) { - vkDestroyBuffer(vkdev, buf->buf, 0); + vkDestroyBuffer(vk_device, buf->buf, 0); delete buf; } } @@ -679,13 +702,13 @@ bool vku_create_graphics_pipeline(VkPipelineLayout *layout) vs.scissorCount = 1; /* dynamic states: that can be changed later */ - std::vector ds_enabled; - ds_enabled.push_back(VK_DYNAMIC_STATE_VIEWPORT); +// std::vector ds_enabled; +// ds_enabled.push_back(VK_DYNAMIC_STATE_VIEWPORT); //ds_enabled.push_back(VK_DYNAMIC_STATE_SCISSOR); - VkPipelineDynamicStateCreateInfo ds; - ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - ds.pDynamicStates = ds_enabled.data(); - ds.dynamicStateCount = static_cast(ds_enabled.size()); +// VkPipelineDynamicStateCreateInfo ds; +// ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; +// ds.pDynamicStates = ds_enabled.data(); +// ds.dynamicStateCount = static_cast(ds_enabled.size()); /* depth tests */ VkPipelineDepthStencilStateCreateInfo dsi; diff --git a/src/vulkan/vkutil.h b/src/vulkan/vkutil.h index eda0e71..396209f 100644 --- a/src/vulkan/vkutil.h +++ b/src/vulkan/vkutil.h @@ -4,21 +4,22 @@ #include #include +extern VkPhysicalDevice vk_physical; +extern VkDevice vk_device; +extern VkCommandPool vk_pool; +extern VkQueue vk_queue; +extern VkSwapchainKHR vk_swapchain; +extern VkSurfaceKHR vk_surface; + extern VkPipeline *vkgparent_pipeline; extern VkDescriptorSet *vkdescset; extern VkFramebuffer *vkfbufs; extern VkRenderPass vkrpass; extern VkInstance vkinst; -extern VkPhysicalDevice vkpdev; -extern VkDevice vkdev; -extern VkQueue vkq; -extern VkCommandPool vkcmdpool; extern VkCommandBuffer vkcmdbuf; /* primary command buffer */ extern int vkqfamily; /* presentation */ -extern VkSurfaceKHR vksurface; -extern VkSwapchainKHR vkswapchain; extern int vknum_swapchain_images; extern VkImage *vkswapchain_images; extern VkImageView *vkswapchain_views; -- 1.7.10.4