summaryrefslogtreecommitdiff
path: root/src/device.c
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2023-10-22 21:18:13 +0300
committerkartofen <mladenovnasko0@gmail.com>2023-10-22 21:18:13 +0300
commite9bd321c8bd6bdb6aa7305c6da8b33e8cac462f7 (patch)
tree14d1e8993b68520dcfedfd6939b84c1af1330376 /src/device.c
parent7e555eeadd1f295db7700b8bde884fcb92bb2b8d (diff)
renamed device.c/.h to graphics
Diffstat (limited to 'src/device.c')
-rw-r--r--src/device.c1147
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