diff options
author | kartofen <mladenovnasko0@gmail.com> | 2023-10-22 21:18:13 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2023-10-22 21:18:13 +0300 |
commit | e9bd321c8bd6bdb6aa7305c6da8b33e8cac462f7 (patch) | |
tree | 14d1e8993b68520dcfedfd6939b84c1af1330376 /src/device.c | |
parent | 7e555eeadd1f295db7700b8bde884fcb92bb2b8d (diff) |
renamed device.c/.h to graphics
Diffstat (limited to 'src/device.c')
-rw-r--r-- | src/device.c | 1147 |
1 files changed, 0 insertions, 1147 deletions
diff --git a/src/device.c b/src/device.c deleted file mode 100644 index 5934270..0000000 --- a/src/device.c +++ /dev/null @@ -1,1147 +0,0 @@ -#include <string.h> -#include <errno.h> -#include <vulkan/vulkan.h> - -#include "device.h" -#include "common.h" - -// TODO: rename device.c/.h -// TODO: add more error checking -// TODO: add log output -// TODO: check for memory leaks - -#define SWAP_CHAIN_IMAGES 3 - -#define CLAMP(val, min, max) (((val) < (min)) ? (min) : ((val) > (max) ? (max) : (val))) - -#define ECHECK(f, ...) if(f(__VA_ARGS__) != 0) { err(#f ": failed"); goto exit; } -#define FCHECK(f, ...) if(f(__VA_ARGS__) != 0) { err(#f ": failed"); goto fail; } - -#define VCHECK(f, ...) \ - do { \ - VkResult res; \ - if((res = f(__VA_ARGS__)) != VK_SUCCESS) { \ - err(#f ": %s", str_VkResult(res)); \ - goto exit; } \ - } while(0) - -#ifdef DEBUG -char *validation_layers[] = { - "VK_LAYER_KHRONOS_validation" -}; -#endif - -char *device_extensions[] = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME -}; - -struct queue_family_idx { - u32 graphics_family; - bool has_graphics_family; - - u32 present_family; - bool has_present_family; -}; - -struct swap_chain_support_details { - VkSurfaceCapabilitiesKHR capabilities; - - VkSurfaceFormatKHR *formats; - u32 nformats; - - VkPresentModeKHR *present_modes; - u32 npresent_modes; -}; - -// most function that return an int follow this scheme: -// 0 - success; 1 - error; (sometimes -1 - fatal error) - -// -- Major Functions --- -static int create_instance(device_t device, struct device_info *info); -static int create_surface(device_t device, struct device_info *info); -static int create_physical_device(device_t device, struct device_info *info); -static int create_logical_device(device_t device, struct device_info *info); -static int create_pipeline(device_t device, struct device_info *info); -static int create_swap_chain(device_t device, struct device_info *info); -static int create_command_pool(device_t device, struct device_info *info); -static int create_sync_objects(device_t device, struct device_info *info); - -static void destroy_swap_chain(device_t device); -static void destroy_pipeline(device_t device); -// static void destroy_command_pool(device_t device); -static void destroy_sync_objects(device_t device); - -// --- Helper Functions --- -static char *str_VkResult(VkResult result); - -static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface); -static bool device_has_extension_support(VkPhysicalDevice phy_device); -static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family); - -#define PPLN device->pipeline -static int pipeline_load_shader_module(VkDevice device, char *path, VkShaderModule *module); - -#define SWCH device->swap_chain -static int swap_chain_support(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct swap_chain_support_details *details); -static void swap_chain_free_support_details(struct swap_chain_support_details *details); -static int swap_chain_choose_format(VkSurfaceFormatKHR* formats, u32 nformats, VkSurfaceFormatKHR *format); -static int swap_chain_choose_present_mode(VkPresentModeKHR *modes, u32 nmodes, VkPresentModeKHR *mode); -static int swap_chain_get_extent(VkSurfaceCapabilitiesKHR capabilities, VkExtent2D *extent); - -#define CMND device->command -static int command_buffer_record(device_t device, u32 image_index); - -#define SYNC device->sync - -F_LOAD_FILE_ALIGNED(u32) // from config.h - -// --- Debug Functions --- -#ifdef DEBUG -static bool instance_has_validation_layers(const char * const *layers, u32 nlayers); - -static int create_debug_messenger(device_t device, struct device_info* info); -static void debug_messenger_populate_info(VkDebugUtilsMessengerCreateInfoEXT *info); - -static VKAPI_ATTR VkBool32 VKAPI_CALL debug_messenger_callback( - VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData); - -// Vulkan Wrappers -VkResult CreateDebugUtilsMessengerEXT( - VkInstance instance, - const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDebugUtilsMessengerEXT* pDebugMessenger); -void DestroyDebugUtilsMessengerEXT( - VkInstance instance, - VkDebugUtilsMessengerEXT debugMessenger, - const VkAllocationCallbacks* pAllocator); -#endif - -#define CCHECK(f) FCHECK(f, device, info) - -device_t device_create(struct device_info *info) -{ - device_t device = xmalloc(sizeof(struct device)); - device->instance = VK_NULL_HANDLE; - device->logical_device = VK_NULL_HANDLE; - - - PPLN.pipeline = VK_NULL_HANDLE; - PPLN.layout = VK_NULL_HANDLE; - PPLN.render_pass = VK_NULL_HANDLE; - - SWCH.swap_chain = VK_NULL_HANDLE; - SWCH.nimages = 0; - - CMND.pool = VK_NULL_HANDLE; - - SYNC.semph_image_available = VK_NULL_HANDLE; - SYNC.semph_render_finished = VK_NULL_HANDLE; - SYNC.fence_inflight = VK_NULL_HANDLE; - - CCHECK(create_instance); - CCHECK(create_surface); -#ifdef DEBUG - CCHECK(create_debug_messenger); -#endif - CCHECK(create_physical_device); - CCHECK(create_logical_device); - CCHECK(create_pipeline); - CCHECK(create_swap_chain); - CCHECK(create_command_pool); - CCHECK(create_sync_objects); - - return device; -fail: - device_destroy(device); - return NULL; -} - -void device_destroy(device_t device) -{ - if(!device) return; - - vkDeviceWaitIdle(device->logical_device); - - destroy_sync_objects(device); - - vkDestroyCommandPool(device->logical_device, CMND.pool, NULL); - - destroy_swap_chain(device); - destroy_pipeline(device); - - vkDestroyDevice(device->logical_device, NULL); - - #ifdef DEBUG - DestroyDebugUtilsMessengerEXT(device->instance, device->debug_messenger, NULL); - #endif - - vkDestroySurfaceKHR(device->instance, device->surface, NULL); - vkDestroyInstance(device->instance, NULL); - - free(device); -} - -int device_draw_frame(device_t device) -{ - int ret = 1; - - // wait for the previous frame to finish - vkWaitForFences(device->logical_device, 1, &SYNC.fence_inflight, VK_TRUE, UINT64_MAX); - - // aquire the next image the form the swap chain - u32 image_index; - VkResult res = vkAcquireNextImageKHR(device->logical_device, SWCH.swap_chain, UINT64_MAX, SYNC.semph_image_available, VK_NULL_HANDLE, &image_index); - - // recreate the swap chain on resize - if(res == VK_ERROR_OUT_OF_DATE_KHR) { - destroy_swap_chain(device); - create_swap_chain(device, NULL); - - ret = 0; goto exit; - } - - vkResetFences(device->logical_device, 1, &SYNC.fence_inflight); - - // reset the command buffer - vkResetCommandBuffer(CMND.buffer, 0); - command_buffer_record(device, image_index); - - // prepare the queue submit info - VkSubmitInfo submit_info = {0}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - - VkSemaphore wait_semaphs[] = { SYNC.semph_image_available }; - VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - submit_info.waitSemaphoreCount = ARR_SIZE(wait_semaphs); - submit_info.pWaitSemaphores = wait_semaphs; - submit_info.pWaitDstStageMask = wait_stages; - - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &CMND.buffer; - - VkSemaphore signal_semphs[] = { SYNC.semph_image_available }; - submit_info.signalSemaphoreCount = ARR_SIZE(signal_semphs); - submit_info.pSignalSemaphores = signal_semphs; - - // submit the graphics work - VCHECK(vkQueueSubmit, device->graphics_queue, 1, &submit_info, SYNC.fence_inflight); - - // prepare the graphics info - VkPresentInfoKHR present_info = {0}; - present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - - present_info.waitSemaphoreCount = ARR_SIZE(signal_semphs); - present_info.pWaitSemaphores = signal_semphs; - - VkSwapchainKHR swap_chains[] = { SWCH.swap_chain }; - present_info.swapchainCount = ARR_SIZE(swap_chains); - present_info.pSwapchains = swap_chains; - present_info.pImageIndices = &image_index; - present_info.pResults = NULL; // Optional - - - vkQueuePresentKHR(device->present_queue, &present_info); - - - ret = 0; -exit: - return ret; -} - -static int create_instance(device_t device, struct device_info *info) -{ - int ret = 1; - - VkApplicationInfo app_info = {0}; - app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - app_info.pEngineName = "Engine"; - app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); - app_info.apiVersion = VK_API_VERSION_1_0; - - app_info.pApplicationName = info->name; - app_info.applicationVersion = info->version; - - VkInstanceCreateInfo create_info = {0}; - create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - create_info.pApplicationInfo = &app_info; - - create_info.enabledLayerCount = 0; - -#ifdef DEBUG - // add debug utils extensions for debug callback - char **extensions = xcalloc(info->ext_count+1, sizeof(*extensions)); - extensions[info->ext_count] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; - - for(u32 i = 0; i < info->ext_count; i++) { - extensions[i] = (char *)info->extensions[i]; - } - - create_info.enabledExtensionCount = info->ext_count+1; - create_info.ppEnabledExtensionNames = (const char * const *)extensions; - - // validation layer support - u32 nlayers = ARR_SIZE(validation_layers); - - if(!instance_has_validation_layers((const char * const *)validation_layers, nlayers)) { - err("validation_layer_support: failed"); - goto exit; - } - - create_info.ppEnabledLayerNames = (const char * const *)validation_layers; - create_info.enabledLayerCount = nlayers; - - // add the debug messenger for instance creation and destruction - VkDebugUtilsMessengerCreateInfoEXT msg_info = {0}; - debug_messenger_populate_info(&msg_info); - - create_info.pNext = &msg_info; -#else - create_info.enabledExtensionCount = info->ext_count; - create_info.ppEnabledExtensionNames = (const char * const *)info->extensions; - - create_info.enabledLayerCount = 0; -#endif - - VCHECK(vkCreateInstance, &create_info, NULL, &device->instance); - - ret = 0; -exit: -#ifdef DEBUG - free(extensions); -#endif - return ret; -} - -static int create_surface(device_t device, struct device_info *info) -{ - if(info->surface_func(device->instance, &device->surface)) { - err("Couldn't create a VkSurfaceKHR"); - return 1; - } - - return 0; -} - -static int create_physical_device(device_t device, struct device_info *info) -{ - (void)info; - int ret = 1; - - device->physical_device = VK_NULL_HANDLE; - - u32 dev_count = 0; - vkEnumeratePhysicalDevices(device->instance, &dev_count, NULL); - - if(dev_count == 0) { - err("No physical devices could be found!"); - goto exit; - } - - VkPhysicalDevice *devices = xcalloc(dev_count, sizeof(*devices)); - vkEnumeratePhysicalDevices(device->instance, &dev_count, devices); - - for(u32 i = 0; i < dev_count; i++) { - if(device_is_suitable(devices[i], device->surface)) { - device->physical_device = devices[i]; - break; - } - } - - free(devices); - - if(device->physical_device == VK_NULL_HANDLE) { - err("No suitable physical device could be found"); - goto exit; - } - - ret = 0; -exit: - return ret; -} - -static int create_logical_device(device_t device, struct device_info *info) -{ - (void)info; - int ret = 1; - - // queue family data - struct queue_family_idx indices = {0}; - device_queue_families(device->physical_device, device->surface, &indices); - - // queue infos - u32 unique_queue_family_count = 0; - u32 queue_indices[] = { - indices.graphics_family, indices.present_family, - }; - - VkDeviceQueueCreateInfo queue_infos[ARR_SIZE(queue_indices)] = {0}; - - float queue_priority = 1.0f; - // basically get only the unique queue families - for(size_t i = 0; i < ARR_SIZE(queue_indices); i++) - { - bool unique = true; - for(size_t j = 0; j < i; j++) { - if(queue_indices[i] == queue_indices[j]) { - unique = false; - break; - } - } - - if(!unique) continue; - - queue_infos[unique_queue_family_count].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_infos[unique_queue_family_count].queueFamilyIndex = queue_indices[i]; - queue_infos[unique_queue_family_count].queueCount = 1; - queue_infos[unique_queue_family_count].pQueuePriorities = &queue_priority; - - unique_queue_family_count++; - } - - // device features - VkPhysicalDeviceFeatures device_features = {0}; - - // logical device create info - VkDeviceCreateInfo create_info = {0}; - create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - - create_info.pQueueCreateInfos = queue_infos; - create_info.queueCreateInfoCount = unique_queue_family_count; - - create_info.pEnabledFeatures = &device_features; - - create_info.ppEnabledExtensionNames = (const char * const *)device_extensions; - create_info.enabledExtensionCount = ARR_SIZE(device_extensions); - - // validation layers can be set, but - // newer implementations will ignore them - // so i wont bother adding them - create_info.enabledLayerCount = 0; - - VCHECK(vkCreateDevice, device->physical_device, &create_info, NULL, &device->logical_device); - - vkGetDeviceQueue(device->logical_device, indices.graphics_family, 0, &device->graphics_queue); - vkGetDeviceQueue(device->logical_device, indices.present_family, 0, &device->present_queue); - - ret = 0; -exit: - return ret; -} - -static int create_swap_chain(device_t device, struct device_info *info) -{ - (void)info; - int ret = 1; - - struct swap_chain_support_details details; - swap_chain_support(device->physical_device, device->surface, &details); - - VkSurfaceFormatKHR surface_format; - VkPresentModeKHR present_mode; - VkExtent2D extent; - u32 image_count = SWAP_CHAIN_IMAGES; - - swap_chain_choose_format(details.formats, details.nformats, &surface_format); - swap_chain_choose_present_mode(details.present_modes, details.npresent_modes, &present_mode); - swap_chain_get_extent(details.capabilities, &extent); - - if(details.capabilities.maxImageCount > 0) { - image_count = CLAMP(image_count, details.capabilities.minImageCount, details.capabilities.maxImageCount); - } - - // start filling in the create info - VkSwapchainCreateInfoKHR create_info = {0}; - create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - - create_info.surface = device->surface; - create_info.minImageCount = image_count; - create_info.imageFormat = surface_format.format; - create_info.imageColorSpace = surface_format.colorSpace; - create_info.imageExtent = extent; - create_info.imageArrayLayers = 1; - create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - struct queue_family_idx indices = {0}; - device_queue_families(device->physical_device, device->surface, &indices); - - u32 queue_indices[] = { indices.graphics_family, indices.present_family }; - - // set the sharing mode of the images - if(indices.graphics_family != indices.present_family) { - create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - create_info.queueFamilyIndexCount = ARR_SIZE(queue_indices); - create_info.pQueueFamilyIndices = queue_indices; - } else { - create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - create_info.queueFamilyIndexCount = 0; - create_info.pQueueFamilyIndices = NULL; - } - - create_info.preTransform = details.capabilities.currentTransform; - create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - - create_info.presentMode = present_mode; - create_info.clipped = VK_TRUE; - - create_info.oldSwapchain = NULL; - - VCHECK(vkCreateSwapchainKHR, device->logical_device, &create_info, NULL, &SWCH.swap_chain); - - // Get the Images - SWCH.image_format = surface_format.format; - SWCH.extent = extent; - - vkGetSwapchainImagesKHR(device->logical_device, SWCH.swap_chain, &SWCH.nimages, NULL); - - SWCH.images = xcalloc(SWCH.nimages, sizeof(*SWCH.images)); - SWCH.image_views = xcalloc(SWCH.nimages, sizeof(SWCH.image_views)); - SWCH.framebuffers = xcalloc(SWCH.nimages, sizeof(*SWCH.framebuffers)); - - vkGetSwapchainImagesKHR(device->logical_device, SWCH.swap_chain, &SWCH.nimages, SWCH.images); - - for(u32 i = 0; i < SWCH.nimages; i++) - { - VkImageViewCreateInfo create_info = {0}; - create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - create_info.image = SWCH.images[i]; - - create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - create_info.format = surface_format.format; - - create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - - create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - create_info.subresourceRange.baseMipLevel = 0; - create_info.subresourceRange.levelCount = 1; - create_info.subresourceRange.baseArrayLayer = 0; - create_info.subresourceRange.layerCount = 1; - - VCHECK(vkCreateImageView, device->logical_device, &create_info, NULL, &SWCH.image_views[i]); - } - - for(u32 i = 0; i < SWCH.nimages; i++) - { - VkImageView attachments[] = { - SWCH.image_views[i] - }; - - VkFramebufferCreateInfo framebuffer_info = {0}; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.renderPass = PPLN.render_pass; - framebuffer_info.attachmentCount = 1; - framebuffer_info.pAttachments = attachments; - framebuffer_info.width = SWCH.extent.width; - framebuffer_info.height = SWCH.extent.height; - framebuffer_info.layers = 1; - - VCHECK(vkCreateFramebuffer, device->logical_device, &framebuffer_info, NULL, &SWCH.framebuffers[i]); - } - - ret = 0; -exit: - swap_chain_free_support_details(&details); - return ret; -} - -static void destroy_swap_chain(device_t device) -{ - for(u32 i = 0; i < SWCH.nimages; i++) { - vkDestroyImageView(device->logical_device, SWCH.image_views[i], NULL); - vkDestroyFramebuffer(device->logical_device, SWCH.framebuffers[i], NULL); - } - - if(SWCH.nimages != 0) { - free(SWCH.images); - free(SWCH.image_views); - free(SWCH.framebuffers); - } - - vkDestroySwapchainKHR(device->logical_device, SWCH.swap_chain, NULL); -} - -static int create_pipeline(device_t device, struct device_info *info) -{ - (void)info; - int ret = 1; - - // Shader Things - VkShaderModule vert_shader = VK_NULL_HANDLE; - VkShaderModule frag_shader = VK_NULL_HANDLE; - - pipeline_load_shader_module(device->logical_device, "shaders/shader1.vert.spv", &vert_shader); - pipeline_load_shader_module(device->logical_device, "shaders/shader1.frag.spv", &frag_shader); - - VkPipelineShaderStageCreateInfo vert_stage = {0}; - vert_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vert_stage.stage = VK_SHADER_STAGE_VERTEX_BIT; - vert_stage.module = vert_shader; - vert_stage.pName = "main"; - - VkPipelineShaderStageCreateInfo frag_stage = {0}; - frag_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - frag_stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - frag_stage.module = frag_shader; - frag_stage.pName = "main"; - - VkPipelineShaderStageCreateInfo shader_stages[] = { vert_stage, frag_stage }; - - VkDynamicState dynamic_states[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - - // A Bunch of other things for the pipeline - VkPipelineDynamicStateCreateInfo dynamic_state = {0}; - dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state.dynamicStateCount = ARR_SIZE(dynamic_states); - dynamic_state.pDynamicStates = dynamic_states; - - // vertex things - hard coded (for now) - VkPipelineVertexInputStateCreateInfo vertex_input = {0}; - vertex_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input.vertexBindingDescriptionCount = 0; - vertex_input.pVertexBindingDescriptions = NULL; - vertex_input.vertexAttributeDescriptionCount = 0; - vertex_input.pVertexAttributeDescriptions = NULL; - - VkPipelineInputAssemblyStateCreateInfo input_assembly = {0}; - input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - input_assembly.primitiveRestartEnable = VK_FALSE; - - VkPipelineViewportStateCreateInfo viewport_state = {0}; - viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state.viewportCount = 1; - viewport_state.scissorCount = 1; - - VkPipelineRasterizationStateCreateInfo rasterizer = {0}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - - rasterizer.depthBiasEnable = VK_FALSE; - rasterizer.depthBiasConstantFactor = 0.0f; // Optional - rasterizer.depthBiasClamp = 0.0f; // Optional - rasterizer.depthBiasSlopeFactor = 0.0f; // Optional - - VkPipelineMultisampleStateCreateInfo multisampling = {0}; - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisampling.minSampleShading = 1.0f; // Optional - multisampling.pSampleMask = NULL; // Optional - multisampling.alphaToCoverageEnable = VK_FALSE; // Optional - multisampling.alphaToOneEnable = VK_FALSE; // Optional - - VkPipelineColorBlendAttachmentState color_blend_attachment = {0}; - color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - color_blend_attachment.blendEnable = VK_FALSE; - color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional - color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional - color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD; // Optional - color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional - color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional - color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD; // Optional - - VkPipelineColorBlendStateCreateInfo color_blend = {0}; - color_blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - color_blend.logicOpEnable = VK_FALSE; - color_blend.logicOp = VK_LOGIC_OP_COPY; // Optional - color_blend.attachmentCount = 1; - color_blend.pAttachments = &color_blend_attachment; - color_blend.blendConstants[0] = 0.0f; // Optional - color_blend.blendConstants[1] = 0.0f; // Optional - color_blend.blendConstants[2] = 0.0f; // Optional - color_blend.blendConstants[3] = 0.0f; // Optional - - // Create Pipeline Layout - VkPipelineLayoutCreateInfo pipeline_layout_info = {0}; - pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_info.setLayoutCount = 0; // Optional - pipeline_layout_info.pSetLayouts = NULL; // Optional - pipeline_layout_info.pushConstantRangeCount = 0; // Optional - pipeline_layout_info.pPushConstantRanges = NULL; // Optional - - VCHECK(vkCreatePipelineLayout, device->logical_device, &pipeline_layout_info, NULL, &PPLN.layout); - - // get the required format - // currently the only to do that - // TOOD: fix this - VkSurfaceFormatKHR surface_format; - struct swap_chain_support_details details; - swap_chain_support(device->physical_device, device->surface, &details); - swap_chain_choose_format(details.formats, details.nformats, &surface_format); - swap_chain_free_support_details(&details); - - // Create Render Pass - VkAttachmentDescription color_attachment = {0}; - color_attachment.format = surface_format.format; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference color_attachment_ref = {0}; - color_attachment_ref.attachment = 0; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {0}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_ref; - - VkSubpassDependency dependency = {0}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo render_pass_info = {0}; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; - render_pass_info.subpassCount = 1; - render_pass_info.pSubpasses = &subpass; - render_pass_info.dependencyCount = 1; - render_pass_info.pDependencies = &dependency; - - VCHECK(vkCreateRenderPass, device->logical_device, &render_pass_info, NULL, &PPLN.render_pass); - - // Finally Create the Pipeline - VkGraphicsPipelineCreateInfo pipeline_info = {0}; - pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipeline_info.stageCount = 2; - pipeline_info.pStages = shader_stages; - - pipeline_info.pVertexInputState = &vertex_input; - pipeline_info.pInputAssemblyState = &input_assembly; - pipeline_info.pViewportState = &viewport_state; - pipeline_info.pRasterizationState = &rasterizer; - pipeline_info.pMultisampleState = &multisampling; - pipeline_info.pDepthStencilState = NULL; - pipeline_info.pColorBlendState = &color_blend; - pipeline_info.pDynamicState = &dynamic_state; - - pipeline_info.layout = PPLN.layout; - pipeline_info.renderPass = PPLN.render_pass; - pipeline_info.subpass = 0; - - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; // Optional - pipeline_info.basePipelineIndex = -1; // Optional - - VCHECK(vkCreateGraphicsPipelines, device->logical_device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &PPLN.pipeline); - - ret = 0; -exit: - vkDestroyShaderModule(device->logical_device, frag_shader, NULL); - vkDestroyShaderModule(device->logical_device, vert_shader, NULL); - return ret; -} - -static void destroy_pipeline(device_t device) -{ - vkDestroyPipeline(device->logical_device, PPLN.pipeline, NULL); - vkDestroyPipelineLayout(device->logical_device, PPLN.layout, NULL); - vkDestroyRenderPass(device->logical_device, PPLN.render_pass, NULL); -} - -static int create_command_pool(device_t device, struct device_info *info) -{ - (void)info; - int ret = 1; - - struct queue_family_idx indices; - device_queue_families(device->physical_device, device->surface, &indices); - - VkCommandPoolCreateInfo pool_info = {0}; - pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - pool_info.queueFamilyIndex = indices.graphics_family; - - VCHECK(vkCreateCommandPool, device->logical_device, &pool_info, NULL, &CMND.pool); - - // allocate the command buffer(s) - VkCommandBufferAllocateInfo allocate_info = {0}; - allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocate_info.commandPool = CMND.pool; - allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocate_info.commandBufferCount = 1; - - VCHECK(vkAllocateCommandBuffers, device->logical_device, &allocate_info, &CMND.buffer); - - ret = 0; -exit: - return ret; -} - -static int create_sync_objects(device_t device, struct device_info *info) -{ - (void)info; - int ret = 1; - - VkSemaphoreCreateInfo semph_info = {0}; - semph_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fence_info = {0}; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - VCHECK(vkCreateSemaphore, device->logical_device, &semph_info, NULL, &SYNC.semph_image_available); - VCHECK(vkCreateSemaphore, device->logical_device, &semph_info, NULL, &SYNC.semph_render_finished); - VCHECK(vkCreateFence, device->logical_device, &fence_info, NULL, &SYNC.fence_inflight); - - ret = 0; -exit: - return ret; -} - -static void destroy_sync_objects(device_t device) -{ - vkDestroySemaphore(device->logical_device, SYNC.semph_image_available, NULL); - vkDestroySemaphore(device->logical_device, SYNC.semph_render_finished, NULL); - vkDestroyFence(device->logical_device, SYNC.fence_inflight, NULL); -} - -static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family) -{ - u32 count = 0; - vkGetPhysicalDeviceQueueFamilyProperties(phy_device, &count, NULL); - - VkQueueFamilyProperties *properties = xcalloc(count, sizeof(*properties)); - vkGetPhysicalDeviceQueueFamilyProperties(phy_device, &count, properties); - - for(u32 i = 0; i < count; i++) { - if(properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) { - queue_family->graphics_family = i; - queue_family->has_graphics_family = true; - } - - VkBool32 present_support = false; - vkGetPhysicalDeviceSurfaceSupportKHR(phy_device, i, surface, &present_support); - - if(present_support) { - queue_family->present_family = i; - queue_family->has_present_family = true; - } - } - - free(properties); - return 0; -} - -static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface) -{ - struct queue_family_idx indices; - struct swap_chain_support_details details; - - return - (device_queue_families(phy_device, surface, &indices), - indices.has_graphics_family && indices.has_present_family) - && - (device_has_extension_support(phy_device)) - && - (swap_chain_support(phy_device, surface, &details), - swap_chain_free_support_details(&details), - (details.nformats > 0) && (details.npresent_modes > 0)); -} - -static bool device_has_extension_support(VkPhysicalDevice phy_device) -{ - bool ret = false; - - u32 count = 0; - vkEnumerateDeviceExtensionProperties(phy_device, NULL, &count, NULL); - - VkExtensionProperties *properties = xcalloc(count, sizeof(*properties)); - vkEnumerateDeviceExtensionProperties(phy_device, NULL, &count, properties); - - for(size_t i = 0; i < ARR_SIZE(device_extensions); i++) - { - bool present = false; - for(u32 j = 0; j < count; j++) - if(strncmp(device_extensions[i], properties[j].extensionName, 256) == 0) { - present = true; - break; - } - - if(!present) { - goto exit; - } - } - - ret = true; -exit: - free(properties); - return ret; -} - -static int swap_chain_support(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct swap_chain_support_details *details) -{ - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phy_device, surface, &details->capabilities); - - vkGetPhysicalDeviceSurfaceFormatsKHR(phy_device, surface, &details->nformats, NULL); - if(details->nformats > 0) { - details->formats = xcalloc(details->nformats, sizeof(*details->formats)); - vkGetPhysicalDeviceSurfaceFormatsKHR(phy_device, surface, &details->nformats, details->formats); - } - - vkGetPhysicalDeviceSurfacePresentModesKHR(phy_device, surface, &details->npresent_modes, NULL); - if(details->npresent_modes > 0) { - details->present_modes = xcalloc(details->npresent_modes, sizeof(*details->present_modes)); - vkGetPhysicalDeviceSurfacePresentModesKHR(phy_device, surface, &details->npresent_modes, details->present_modes); - } - - return 0; -} - -static void swap_chain_free_support_details(struct swap_chain_support_details *details) -{ - if(details->nformats > 0) free(details->formats); - if(details->npresent_modes > 0) free(details->present_modes); -} - -static int swap_chain_choose_format(VkSurfaceFormatKHR* formats, u32 nformats, VkSurfaceFormatKHR *format) -{ - for(u32 i = 0; i < nformats; i++) - if(formats[i].format == VK_FORMAT_B8G8R8A8_SRGB && - formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - *format = formats[i]; - return 0; - } - - *format = formats[0]; - return 0; -} - -static int swap_chain_choose_present_mode(VkPresentModeKHR *modes, u32 nmodes, VkPresentModeKHR *mode) -{ - for(u32 i = 0; i < nmodes; i++) - if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { - *mode = modes[i]; - return 0; - } - - *mode = VK_PRESENT_MODE_FIFO_KHR; - return 0; -} - -static int swap_chain_get_extent(VkSurfaceCapabilitiesKHR capabilities, VkExtent2D *extent) -{ - if(capabilities.currentExtent.width != UINT32_MAX) { - *extent = capabilities.currentExtent; - return 0; - } - - // TODO implement - err("Not Implemented"); - return 1; -} - -static int pipeline_load_shader_module(VkDevice device, char *path, VkShaderModule *module) -{ - int ret = 1; - - size_t size = 0; - u32 *buf = NULL; - - ECHECK(load_file_u32_aligned, path, &size, NULL); - buf = xmalloc(size); - ECHECK(load_file_u32_aligned, path, &size, buf); - - VkShaderModuleCreateInfo create_info = {0}; - create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - create_info.codeSize = size; - create_info.pCode = buf; - - VCHECK(vkCreateShaderModule, device, &create_info, NULL, module); - - ret = 0; -exit: - if(buf) free(buf); - return ret; -} - -static int command_buffer_record(device_t device, u32 image_index) -{ - int ret = 1; - - // Begin the buffer - VkCommandBufferBeginInfo begin_info = {0}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.flags = 0; // Optional - begin_info.pInheritanceInfo = NULL; // Optional - - VCHECK(vkBeginCommandBuffer, CMND.buffer, &begin_info); - - // Begin the render pass - VkRenderPassBeginInfo render_pass_info = {0}; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_info.renderPass = PPLN.render_pass; - render_pass_info.framebuffer = SWCH.framebuffers[image_index]; - - render_pass_info.renderArea.offset = (VkOffset2D){0, 0}; - render_pass_info.renderArea.extent = SWCH.extent; - - VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; - render_pass_info.clearValueCount = 1; - render_pass_info.pClearValues = &clear_color; - - vkCmdBeginRenderPass(CMND.buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); - - // Begin the drawing commands - vkCmdBindPipeline(CMND.buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PPLN.pipeline); - - VkViewport viewport = {0}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = (float)SWCH.extent.width; - viewport.height = (float)SWCH.extent.height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - vkCmdSetViewport(CMND.buffer, 0, 1, &viewport); - - VkRect2D scissor = {0}; - scissor.offset = (VkOffset2D){0, 0}; - scissor.extent = SWCH.extent; - vkCmdSetScissor(CMND.buffer, 0, 1, &scissor); - - // 3 vertices, 1 instance (for instanced rendering) - // 0 is the first vertex, 0 is the fist instance - vkCmdDraw(CMND.buffer, 3, 1, 0, 0); - - // Cleaning up - vkCmdEndRenderPass(CMND.buffer); - - VCHECK(vkEndCommandBuffer, CMND.buffer); - - ret = 0; -exit: - return ret; -} - -#define X_VK_RESULT_TABLE(X) \ - X(VK_SUCCESS) \ - X(VK_NOT_READY) \ - X(VK_TIMEOUT) \ - X(VK_EVENT_SET) \ - X(VK_EVENT_RESET) \ - X(VK_INCOMPLETE) \ - X(VK_ERROR_OUT_OF_HOST_MEMORY) \ - X(VK_ERROR_OUT_OF_DEVICE_MEMORY) \ - X(VK_ERROR_INITIALIZATION_FAILED) \ - X(VK_ERROR_DEVICE_LOST) \ - X(VK_ERROR_MEMORY_MAP_FAILED) \ - X(VK_ERROR_LAYER_NOT_PRESENT) \ - X(VK_ERROR_EXTENSION_NOT_PRESENT) \ - X(VK_ERROR_FEATURE_NOT_PRESENT) \ - X(VK_ERROR_INCOMPATIBLE_DRIVER) \ - X(VK_ERROR_TOO_MANY_OBJECTS) \ - X(VK_ERROR_FORMAT_NOT_SUPPORTED) \ - X(VK_ERROR_FRAGMENTED_POOL) \ - X(VK_ERROR_UNKNOWN) \ - X(VK_ERROR_OUT_OF_POOL_MEMORY) \ - X(VK_ERROR_INVALID_EXTERNAL_HANDLE) \ - X(VK_ERROR_FRAGMENTATION) \ - X(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS) \ - -#define X_VK_RESULT_CASE(error) \ - case error: return #error; - -static char *str_VkResult(VkResult result) -{ - switch(result) { - X_VK_RESULT_TABLE(X_VK_RESULT_CASE) - default: - return "VK_ERROR_OTHER"; - } -} - -#ifdef DEBUG - -static bool instance_has_validation_layers(const char * const *layers, u32 nlayers) -{ - (void)layers; - (void)nlayers; - - // u32 navaliable = 0; - // vkEnumerateInstanceLayerProperties(&navaliable, NULL); - - // VkLayerProperties *available_layers = xcalloc(navaliable, sizeof(VkLayerProperties)); - // vkEnumerateInstanceLayerProperties(&navaliable, available_layers); - return true; -} - -static int create_debug_messenger(device_t device, struct device_info *info) -{ - (void)info; - int ret = 1; - - VkDebugUtilsMessengerCreateInfoEXT cinfo = {0}; - debug_messenger_populate_info(&cinfo); - - VCHECK(CreateDebugUtilsMessengerEXT, device->instance, &cinfo, NULL, &device->debug_messenger); - - ret = 0; -exit: - return ret; -} - -static void debug_messenger_populate_info(VkDebugUtilsMessengerCreateInfoEXT *info) -{ - info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - info->messageSeverity = - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - info->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; - info->pfnUserCallback = debug_messenger_callback; -} - -static VKAPI_ATTR VkBool32 VKAPI_CALL debug_messenger_callback( - VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData) -{ - (void)messageSeverity; - (void)messageType; - (void)pUserData; - - warn("Validation Layer: %s", pCallbackData->pMessage); - return VK_FALSE; -} - -VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { - PFN_vkCreateDebugUtilsMessengerEXT f = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); - if (f != NULL) { - return f(instance, pCreateInfo, pAllocator, pDebugMessenger); - } else { - return VK_ERROR_EXTENSION_NOT_PRESENT; - } -} - -void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { - PFN_vkDestroyDebugUtilsMessengerEXT f = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); - if (f != NULL) { - f(instance, debugMessenger, pAllocator); - } -} - -#endif |