123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755 |
- #pragma once
- #ifdef __APPLE__
- const bool isApplePlatform = true;
- #else
- const bool isApplePlatform = false;
- #endif
- typedef struct VulkanDevice {
- VkPhysicalDevice gpu;
- VkPhysicalDeviceProperties gpuProperties;
- VkPhysicalDeviceMemoryProperties memoryProperties;
- VkQueueFamilyProperties *queueFamilyProperties;
- uint32_t queueFamilyPropertiesCount;
- uint32_t graphicsQueueFamilyIndex;
- VkDevice device;
- VkCommandPool commandPool;
- } VulkanDevice;
- VulkanDevice *createVulkanDevice(VkPhysicalDevice gpu) {
- VulkanDevice *device = (VulkanDevice *)malloc(sizeof(VulkanDevice));
- memset(device, 0, sizeof(VulkanDevice));
- device->gpu = gpu;
- vkGetPhysicalDeviceMemoryProperties(gpu, &device->memoryProperties);
- vkGetPhysicalDeviceProperties(gpu, &device->gpuProperties);
- vkGetPhysicalDeviceQueueFamilyProperties(gpu, &device->queueFamilyPropertiesCount, NULL);
- assert(device->queueFamilyPropertiesCount >= 1);
- device->queueFamilyProperties = (VkQueueFamilyProperties *)malloc(device->queueFamilyPropertiesCount * sizeof(VkQueueFamilyProperties));
- vkGetPhysicalDeviceQueueFamilyProperties(gpu, &device->queueFamilyPropertiesCount, device->queueFamilyProperties);
- assert(device->queueFamilyPropertiesCount >= 1);
- device->graphicsQueueFamilyIndex = UINT32_MAX;
- for (uint32_t i = 0; i < device->queueFamilyPropertiesCount; ++i) {
- if ((device->queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
- device->graphicsQueueFamilyIndex = i;
- }
- }
- float queuePriorities[1] = {0.0};
- VkDeviceQueueCreateInfo queue_info = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
- queue_info.queueCount = 1;
- queue_info.pQueuePriorities = queuePriorities;
- queue_info.queueFamilyIndex = device->graphicsQueueFamilyIndex;
- const char *deviceExtensions[] = {
- VK_KHR_SWAPCHAIN_EXTENSION_NAME,
- };
- VkDeviceCreateInfo deviceInfo = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
- deviceInfo.queueCreateInfoCount = 1;
- deviceInfo.pQueueCreateInfos = &queue_info;
- deviceInfo.enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0]);
- deviceInfo.ppEnabledExtensionNames = deviceExtensions;
- VkResult res = vkCreateDevice(gpu, &deviceInfo, NULL, &device->device);
- assert(res == VK_SUCCESS);
- /* Create a command pool to allocate our command buffer from */
- VkCommandPoolCreateInfo cmd_pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
- cmd_pool_info.queueFamilyIndex = device->graphicsQueueFamilyIndex;
- cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- res = vkCreateCommandPool(device->device, &cmd_pool_info, NULL, &device->commandPool);
- assert(res == VK_SUCCESS);
- return device;
- }
- void destroyVulkanDevice(VulkanDevice *device) {
- free(device->queueFamilyProperties);
- if (device->commandPool) {
- vkDestroyCommandPool(device->device, device->commandPool, 0);
- }
- if (device->device) {
- vkDestroyDevice(device->device, 0);
- }
- free(device);
- }
- typedef struct SwapchainBuffers {
- VkImage image;
- VkImageView view;
- } SwapchainBuffers;
- typedef struct DepthBuffer {
- VkFormat format;
- VkImage image;
- VkDeviceMemory mem;
- VkImageView view;
- } DepthBuffer;
- typedef struct FrameBuffers {
- VkSwapchainKHR swap_chain;
- SwapchainBuffers *swap_chain_buffers;
- uint32_t swapchain_image_count;
- VkFramebuffer *framebuffers;
- uint32_t current_buffer;
- uint32_t current_frame;
- uint64_t num_swaps;
- VkExtent2D buffer_size;
- VkRenderPass render_pass;
- VkFormat format;
- DepthBuffer depth;
- VkSemaphore *present_complete_semaphore;
- VkSemaphore *render_complete_semaphore;
- VkFence *flight_fence;
- } FrameBuffers;
- static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
- printf("%s\n", pCallbackData->pMessage);
- return VK_FALSE;
- }
- static VkDebugUtilsMessengerEXT debugMessenger = NULL;
- #ifdef GLFW_INCLUDE_VULKAN
- static VkInstance createVkInstance(bool enable_debug_layer) {
- // initialize the VkApplicationInfo structure
- VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
- app_info.pApplicationName = "NanoVG";
- app_info.applicationVersion = 1;
- app_info.pEngineName = "NanoVG";
- app_info.engineVersion = 1;
- app_info.apiVersion = VK_API_VERSION_1_0;
- static const char *append_extensions[] = {
- VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
- };
- uint32_t append_extensions_count = sizeof(append_extensions) / sizeof(append_extensions[0]);
- if (!enable_debug_layer) {
- append_extensions_count = 0;
- }
- static const char *apple_extensions[] = {
- VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
- };
- uint32_t apple_extensions_count = sizeof(apple_extensions) / sizeof(apple_extensions[0]);
- if (!isApplePlatform) {
- apple_extensions_count = 0;
- }
- uint32_t extensions_count = 0;
- const char **glfw_extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
- const char **extensions = (const char **)calloc(extensions_count + append_extensions_count + apple_extensions_count, sizeof(char *));
- for (uint32_t i = 0; i < extensions_count; ++i) {
- extensions[i] = glfw_extensions[i];
- }
- for (uint32_t i = 0; i < append_extensions_count; ++i) {
- extensions[extensions_count++] = append_extensions[i];
- }
- for (uint32_t i = 0; i < apple_extensions_count; ++i) {
- extensions[extensions_count++] = apple_extensions[i];
- }
- // initialize the VkInstanceCreateInfo structure
- VkInstanceCreateInfo inst_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
- inst_info.pApplicationInfo = &app_info;
- inst_info.enabledExtensionCount = extensions_count;
- inst_info.ppEnabledExtensionNames = extensions;
- if (isApplePlatform) {
- inst_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
- }
- static const char *instance_validation_layers[] = {
- "VK_LAYER_KHRONOS_validation"
- };
- if (enable_debug_layer) {
- inst_info.enabledLayerCount = sizeof(instance_validation_layers) / sizeof(instance_validation_layers[0]);
- inst_info.ppEnabledLayerNames = instance_validation_layers;
- uint32_t layerCount = 0;
- vkEnumerateInstanceLayerProperties(&layerCount, 0);
- VkLayerProperties *layerprop = (VkLayerProperties *)malloc(sizeof(VkLayerProperties) * layerCount);
- vkEnumerateInstanceLayerProperties(&layerCount, layerprop);
- printf("vkEnumerateInstanceLayerProperties:");
- for (uint32_t i = 0; i < layerCount; ++i) {
- printf("%s\n", layerprop[i].layerName);
- }
- free(layerprop);
- }
- VkInstance inst;
- VkResult res;
- res = vkCreateInstance(&inst_info, NULL, &inst);
- free((void*) extensions);
- if (res == VK_ERROR_INCOMPATIBLE_DRIVER) {
- printf("cannot find a compatible Vulkan ICD\n");
- exit(-1);
- } else if (res) {
- switch(res){
- case(VK_ERROR_OUT_OF_HOST_MEMORY):printf("VK_ERROR_OUT_OF_HOST_MEMORY\n");break;
- case(VK_ERROR_OUT_OF_DEVICE_MEMORY):printf("VK_ERROR_OUT_OF_DEVICE_MEMORY\n");break;
- case(VK_ERROR_INITIALIZATION_FAILED):printf("VK_ERROR_INITIALIZATION_FAILED\n");break;
- case(VK_ERROR_LAYER_NOT_PRESENT):printf("VK_ERROR_LAYER_NOT_PRESENT\n");break;
- case(VK_ERROR_EXTENSION_NOT_PRESENT):printf("VK_ERROR_EXTENSION_NOT_PRESENT\n");break;
- default:printf("unknown error %d\n", res);break;
- }
- exit(-1);
- }
- if (enable_debug_layer) {
- VkDebugUtilsMessengerCreateInfoEXT createInfo = {0};
- createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
- createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
- createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
- createInfo.pfnUserCallback = debugCallback;
- PFN_vkCreateDebugUtilsMessengerEXT fn_vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT");
- if (!fn_vkCreateDebugUtilsMessengerEXT) {
- printf("vkCreateDebugUtilsMessengerEXT not found\n");
- } else {
- VkResult res = fn_vkCreateDebugUtilsMessengerEXT(inst, &createInfo, NULL, &debugMessenger);
- if (res != VK_SUCCESS)
- {
- debugMessenger = NULL;
- printf("CreateDebugUtilsMessengerEXT failed (%d)\n", res);
- }
- }
- }
- return inst;
- }
- #endif
- static void destroyDebugCallback(VkInstance instance) {
- if (!debugMessenger)
- return;
- PFN_vkDestroyDebugUtilsMessengerEXT fn_vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
- if (fn_vkDestroyDebugUtilsMessengerEXT)
- {
- fn_vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, NULL);
- }
- }
- VkCommandPool createCmdPool(VulkanDevice *device) {
- VkResult res;
- /* Create a command pool to allocate our command buffer from */
- VkCommandPoolCreateInfo cmd_pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
- cmd_pool_info.queueFamilyIndex = device->graphicsQueueFamilyIndex;
- cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- VkCommandPool cmd_pool;
- res = vkCreateCommandPool(device->device, &cmd_pool_info, NULL, &cmd_pool);
- assert(res == VK_SUCCESS);
- return cmd_pool;
- }
- VkCommandBuffer* createCmdBuffer(VkDevice device, VkCommandPool cmd_pool, uint32_t command_buffer_count) {
- VkResult res;
- VkCommandBufferAllocateInfo cmd = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
- cmd.commandPool = cmd_pool;
- cmd.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- cmd.commandBufferCount = command_buffer_count;
- VkCommandBuffer *cmd_buffer = calloc(command_buffer_count, sizeof (VkCommandBuffer));
- res = vkAllocateCommandBuffers(device, &cmd, cmd_buffer);
- assert(res == VK_SUCCESS);
- return cmd_buffer;
- }
- bool memory_type_from_properties(VkPhysicalDeviceMemoryProperties memoryProps, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex) {
- // Search memtypes to find first index with those properties
- for (uint32_t i = 0; i < memoryProps.memoryTypeCount; i++) {
- if ((typeBits & 1) == 1) {
- // Type is available, does it match user properties?
- if ((memoryProps.memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) {
- *typeIndex = i;
- return true;
- }
- }
- typeBits >>= 1;
- }
- // No memory types matched, return failure
- return false;
- }
- DepthBuffer createDepthBuffer(const VulkanDevice *device, int width, int height) {
- VkResult res;
- DepthBuffer depth;
- depth.format = VK_FORMAT_D24_UNORM_S8_UINT;
- #define dformats 3
- const VkFormat depth_formats[dformats] = {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT};
- VkImageTiling image_tilling;
- for (int i=0;i<dformats;i++){
- VkFormatProperties fprops;
- vkGetPhysicalDeviceFormatProperties(device->gpu, depth_formats[i], &fprops);
- if (fprops.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- depth.format=depth_formats[i];
- image_tilling = VK_IMAGE_TILING_LINEAR;
- break;
- } else if (fprops.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- depth.format=depth_formats[i];
- image_tilling = VK_IMAGE_TILING_OPTIMAL;
- break;
- }
- if(i==dformats-1){
- printf("Failed to find supported depth format!\n");
- exit(-1);
- }
- }
- const VkFormat depth_format = depth.format;
- VkImageCreateInfo image_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
- image_info.imageType = VK_IMAGE_TYPE_2D;
- image_info.format = depth_format;
- image_info.tiling = image_tilling;
- image_info.extent.width = width;
- image_info.extent.height = height;
- image_info.extent.depth = 1;
- image_info.mipLevels = 1;
- image_info.arrayLayers = 1;
- image_info.samples = VK_SAMPLE_COUNT_1_BIT;
- image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- image_info.queueFamilyIndexCount = 0;
- image_info.pQueueFamilyIndices = NULL;
- image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- VkMemoryAllocateInfo mem_alloc = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
- VkImageViewCreateInfo view_info = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
- view_info.format = depth_format;
- view_info.components.r = VK_COMPONENT_SWIZZLE_R;
- view_info.components.g = VK_COMPONENT_SWIZZLE_G;
- view_info.components.b = VK_COMPONENT_SWIZZLE_B;
- view_info.components.a = VK_COMPONENT_SWIZZLE_A;
- view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- view_info.subresourceRange.baseMipLevel = 0;
- view_info.subresourceRange.levelCount = 1;
- view_info.subresourceRange.baseArrayLayer = 0;
- view_info.subresourceRange.layerCount = 1;
- view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- if (depth_format == VK_FORMAT_D16_UNORM_S8_UINT || depth_format == VK_FORMAT_D24_UNORM_S8_UINT ||
- depth_format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
- view_info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
- }
- VkMemoryRequirements mem_reqs;
- /* Create image */
- res = vkCreateImage(device->device, &image_info, NULL, &depth.image);
- assert(res == VK_SUCCESS);
- vkGetImageMemoryRequirements(device->device, depth.image, &mem_reqs);
- mem_alloc.allocationSize = mem_reqs.size;
- /* Use the memory properties to determine the type of memory required */
- bool pass =
- memory_type_from_properties(device->memoryProperties, mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex);
- assert(pass);
- /* Allocate memory */
- res = vkAllocateMemory(device->device, &mem_alloc, NULL, &depth.mem);
- assert(res == VK_SUCCESS);
- /* Bind memory */
- res = vkBindImageMemory(device->device, depth.image, depth.mem, 0);
- assert(res == VK_SUCCESS);
- /* Create image view */
- view_info.image = depth.image;
- res = vkCreateImageView(device->device, &view_info, NULL, &depth.view);
- assert(res == VK_SUCCESS);
- return depth;
- }
- static void setupImageLayout(VkCommandBuffer cmdbuffer, VkImage image,
- VkImageAspectFlags aspectMask,
- VkImageLayout old_image_layout,
- VkImageLayout new_image_layout) {
- VkImageMemoryBarrier image_memory_barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
- image_memory_barrier.oldLayout = old_image_layout;
- image_memory_barrier.newLayout = new_image_layout;
- image_memory_barrier.image = image;
- VkImageSubresourceRange subresourceRange = {aspectMask, 0, 1, 0, 1};
- image_memory_barrier.subresourceRange = subresourceRange;
- if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
- /* Make sure anything that was copying from this image has completed */
- image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- }
- if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
- image_memory_barrier.dstAccessMask =
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- }
- if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
- image_memory_barrier.dstAccessMask =
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- }
- if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- /* Make sure any Copy or CPU writes to image are flushed */
- image_memory_barrier.dstAccessMask =
- VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
- }
- VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
- VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- vkCmdPipelineBarrier(cmdbuffer, src_stages, dest_stages, 0, 0, NULL,
- 0, NULL, 1, pmemory_barrier);
- }
- SwapchainBuffers createSwapchainBuffers(const VulkanDevice *device, VkFormat format, VkCommandBuffer cmdbuffer, VkImage image) {
- VkResult res;
- SwapchainBuffers buffer;
- VkImageViewCreateInfo color_attachment_view = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
- color_attachment_view.format = format;
- color_attachment_view.components.r = VK_COMPONENT_SWIZZLE_R;
- color_attachment_view.components.g = VK_COMPONENT_SWIZZLE_G;
- color_attachment_view.components.b = VK_COMPONENT_SWIZZLE_B;
- color_attachment_view.components.a = VK_COMPONENT_SWIZZLE_A;
- VkImageSubresourceRange subresourceRange = {0};
- subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- subresourceRange.baseMipLevel = 0;
- subresourceRange.levelCount = 1;
- subresourceRange.baseArrayLayer = 0;
- subresourceRange.layerCount = 1;
- color_attachment_view.subresourceRange = subresourceRange;
- color_attachment_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
- buffer.image = image;
- setupImageLayout(
- cmdbuffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
- color_attachment_view.image = buffer.image;
- res = vkCreateImageView(device->device, &color_attachment_view, NULL,
- &buffer.view);
- assert(res == VK_SUCCESS);
- return buffer;
- }
- VkRenderPass createRenderPass(VkDevice device, VkFormat color_format, VkFormat depth_format) {
- VkAttachmentDescription attachments[2] = {{0}};
- attachments[0].format = color_format;
- attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
- attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachments[1].format = depth_format;
- attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
- attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- VkAttachmentReference color_reference = {0};
- color_reference.attachment = 0;
- color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- VkAttachmentReference depth_reference = {0};
- depth_reference.attachment = 1;
- depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- VkSubpassDescription subpass = {0};
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.flags = 0;
- subpass.inputAttachmentCount = 0;
- subpass.pInputAttachments = NULL;
- subpass.colorAttachmentCount = 1;
- subpass.pColorAttachments = &color_reference;
- subpass.pResolveAttachments = NULL;
- subpass.pDepthStencilAttachment = &depth_reference;
- subpass.preserveAttachmentCount = 0;
- subpass.pPreserveAttachments = NULL;
- VkRenderPassCreateInfo rp_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
- rp_info.attachmentCount = 2;
- rp_info.pAttachments = attachments;
- rp_info.subpassCount = 1;
- rp_info.pSubpasses = &subpass;
- VkRenderPass render_pass;
- VkResult res;
- res = vkCreateRenderPass(device, &rp_info, NULL, &render_pass);
- assert(res == VK_SUCCESS);
- return render_pass;
- }
- FrameBuffers createFrameBuffers(const VulkanDevice *device, VkSurfaceKHR surface, VkQueue queue, int winWidth, int winHeight, VkSwapchainKHR oldSwapchain) {
- VkResult res;
- VkBool32 supportsPresent;
- vkGetPhysicalDeviceSurfaceSupportKHR(device->gpu, device->graphicsQueueFamilyIndex, surface, &supportsPresent);
- if (!supportsPresent) {
- exit(-1); //does not supported.
- }
- VkCommandBuffer *setup_cmd_buffer = createCmdBuffer(device->device, device->commandPool, 1);
- const VkCommandBufferBeginInfo cmd_buf_info = {
- VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- };
- vkBeginCommandBuffer(setup_cmd_buffer[0], &cmd_buf_info);
- VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
- VkColorSpaceKHR colorSpace;
- {
- // Get the list of VkFormats that are supported:
- uint32_t formatCount;
- res = vkGetPhysicalDeviceSurfaceFormatsKHR(device->gpu, surface, &formatCount, NULL);
- assert(res == VK_SUCCESS);
- VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
- res = vkGetPhysicalDeviceSurfaceFormatsKHR(device->gpu, surface, &formatCount, surfFormats);
- assert(res == VK_SUCCESS);
- // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
- // the surface has no preferred format. Otherwise, at least one
- // supported format will be returned.
- if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) {
- colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
- } else {
- assert(formatCount >= 1);
- colorFormat = surfFormats[0].format;
- }
- colorSpace = surfFormats[0].colorSpace;
- free(surfFormats);
- }
- colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
- // Check the surface capabilities and formats
- VkSurfaceCapabilitiesKHR surfCapabilities;
- res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
- device->gpu, surface, &surfCapabilities);
- assert(res == VK_SUCCESS);
- VkExtent2D buffer_size;
- // width and height are either both -1, or both not -1.
- if (surfCapabilities.currentExtent.width == (uint32_t)-1) {
- buffer_size.width = winWidth;
- buffer_size.height = winHeight;
- } else {
- // If the surface size is defined, the swap chain size must match
- buffer_size = surfCapabilities.currentExtent;
- }
- DepthBuffer depth = createDepthBuffer(device, buffer_size.width, buffer_size.height);
- VkRenderPass render_pass = createRenderPass(device->device, colorFormat, depth.format);
- VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
- uint32_t presentModeCount;
- vkGetPhysicalDeviceSurfacePresentModesKHR(device->gpu, surface, &presentModeCount, NULL);
- assert(presentModeCount > 0);
- VkPresentModeKHR *presentModes = (VkPresentModeKHR *)malloc(sizeof(VkPresentModeKHR) * presentModeCount);
- vkGetPhysicalDeviceSurfacePresentModesKHR(device->gpu, surface, &presentModeCount, presentModes);
- for (size_t i = 0; i < presentModeCount; i++) {
- if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
- swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
- break;
- }
- if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
- swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
- }
- }
- free(presentModes);
- VkSurfaceTransformFlagBitsKHR preTransform;
- if (surfCapabilities.supportedTransforms &
- VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
- preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- } else {
- preTransform = surfCapabilities.currentTransform;
- }
- // Determine the number of VkImage's to use in the swap chain (we desire to
- // own only 1 image at a time, besides the images being displayed and
- // queued for display):
- uint32_t desiredNumberOfSwapchainImages =
- fmax(surfCapabilities.minImageCount+1, 3);
- if ((surfCapabilities.maxImageCount > 0) &&
- (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount)) {
- // Application must settle for fewer images than desired:
- desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
- }
- VkSwapchainCreateInfoKHR swapchainInfo = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
- swapchainInfo.surface = surface;
- swapchainInfo.minImageCount = desiredNumberOfSwapchainImages;
- swapchainInfo.imageFormat = colorFormat;
- swapchainInfo.imageColorSpace = colorSpace;
- swapchainInfo.imageExtent = buffer_size;
- swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- swapchainInfo.preTransform = preTransform;
- swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- swapchainInfo.imageArrayLayers = 1;
- swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchainInfo.presentMode = swapchainPresentMode;
- swapchainInfo.oldSwapchain = oldSwapchain;
- swapchainInfo.clipped = true;
- VkSwapchainKHR swap_chain;
- res = vkCreateSwapchainKHR(device->device, &swapchainInfo, NULL,
- &swap_chain);
- assert(res == VK_SUCCESS);
- if (oldSwapchain != VK_NULL_HANDLE) {
- vkDestroySwapchainKHR(device->device, oldSwapchain, NULL);
- }
- uint32_t swapchain_image_count;
- res = vkGetSwapchainImagesKHR(device->device, swap_chain,
- &swapchain_image_count, NULL);
- assert(res == VK_SUCCESS);
- VkImage *swapchainImages =
- (VkImage *)malloc(swapchain_image_count * sizeof(VkImage));
- assert(swapchainImages);
- res = vkGetSwapchainImagesKHR(device->device, swap_chain,
- &swapchain_image_count,
- swapchainImages);
- assert(res == VK_SUCCESS);
- SwapchainBuffers *swap_chain_buffers = (SwapchainBuffers *)malloc(swapchain_image_count * sizeof(SwapchainBuffers));
- for (uint32_t i = 0; i < swapchain_image_count; i++) {
- swap_chain_buffers[i] = createSwapchainBuffers(device, colorFormat, setup_cmd_buffer[0], swapchainImages[i]);
- }
- free(swapchainImages);
- VkImageView attachments[2];
- attachments[1] = depth.view;
- VkFramebufferCreateInfo fb_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
- fb_info.renderPass = render_pass;
- fb_info.attachmentCount = 2;
- fb_info.pAttachments = attachments;
- fb_info.width = buffer_size.width;
- fb_info.height = buffer_size.height;
- fb_info.layers = 1;
- uint32_t i;
- VkFramebuffer *framebuffers = (VkFramebuffer *)malloc(swapchain_image_count *
- sizeof(VkFramebuffer));
- assert(framebuffers);
- for (i = 0; i < swapchain_image_count; i++) {
- attachments[0] = swap_chain_buffers[i].view;
- res = vkCreateFramebuffer(device->device, &fb_info, NULL,
- &framebuffers[i]);
- assert(res == VK_SUCCESS);
- }
- vkEndCommandBuffer(setup_cmd_buffer[0]);
- VkSubmitInfo submitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO};
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = setup_cmd_buffer;
- vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
- vkQueueWaitIdle(queue);
- vkFreeCommandBuffers(device->device, device->commandPool, 1, setup_cmd_buffer);
- free(setup_cmd_buffer);
- FrameBuffers buffer = {0};
- buffer.swap_chain = swap_chain;
- buffer.swap_chain_buffers = swap_chain_buffers;
- buffer.swapchain_image_count = swapchain_image_count;
- buffer.framebuffers = framebuffers;
- buffer.current_buffer = 0;
- buffer.format = colorFormat;
- buffer.buffer_size = buffer_size;
- buffer.render_pass = render_pass;
- buffer.depth = depth;
- buffer.present_complete_semaphore = (VkSemaphore *)calloc(swapchain_image_count, sizeof(VkSemaphore));
- buffer.render_complete_semaphore = (VkSemaphore *)calloc(swapchain_image_count, sizeof(VkSemaphore));
- buffer.flight_fence = (VkFence *)calloc(swapchain_image_count, sizeof(VkFence));
- VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
- VkFenceCreateInfo fenceCreateInfo = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
- for (i = 0; i < swapchain_image_count; i++) {
- res = vkCreateSemaphore(device->device, &presentCompleteSemaphoreCreateInfo, NULL, &buffer.present_complete_semaphore[i]);
- assert(res == VK_SUCCESS);
- res = vkCreateSemaphore(device->device, &presentCompleteSemaphoreCreateInfo, NULL, &buffer.render_complete_semaphore[i]);
- assert(res == VK_SUCCESS);
- res = vkCreateFence(device->device, &fenceCreateInfo, NULL, &buffer.flight_fence[i]);
- assert(res == VK_SUCCESS);
- }
- return buffer;
- }
- void destroyFrameBuffers(const VulkanDevice *device, FrameBuffers *buffer, VkQueue queue) {
- VkResult res = vkQueueWaitIdle(queue);
- assert(res == VK_SUCCESS);
- for (uint32_t i = 0; i < buffer->swapchain_image_count; ++i) {
- if (buffer->present_complete_semaphore[i] != VK_NULL_HANDLE) {
- vkDestroySemaphore(device->device, buffer->present_complete_semaphore[i], NULL);
- }
- if (buffer->render_complete_semaphore[i] != VK_NULL_HANDLE) {
- vkDestroySemaphore(device->device, buffer->render_complete_semaphore[i], NULL);
- }
- if (buffer->flight_fence[i] != VK_NULL_HANDLE) {
- vkDestroyFence(device->device, buffer->flight_fence[i], NULL);
- }
- }
- for (uint32_t i = 0; i < buffer->swapchain_image_count; ++i) {
- vkDestroyImageView(device->device, buffer->swap_chain_buffers[i].view, 0);
- vkDestroyFramebuffer(device->device, buffer->framebuffers[i], 0);
- }
- vkDestroyImageView(device->device, buffer->depth.view, 0);
- vkDestroyImage(device->device, buffer->depth.image, 0);
- vkFreeMemory(device->device, buffer->depth.mem, 0);
- vkDestroyRenderPass(device->device, buffer->render_pass, 0);
- vkDestroySwapchainKHR(device->device, buffer->swap_chain, 0);
- free(buffer->framebuffers);
- free(buffer->swap_chain_buffers);
- free(buffer->present_complete_semaphore);
- free(buffer->render_complete_semaphore);
- free(buffer->flight_fence);
- }
|