diff options
| -rw-r--r-- | src/common.h | 2 | ||||
| -rw-r--r-- | src/device.c | 247 | ||||
| -rw-r--r-- | src/window.c | 8 | 
3 files changed, 144 insertions, 113 deletions
| diff --git a/src/common.h b/src/common.h index 27d8404..eaa0743 100644 --- a/src/common.h +++ b/src/common.h @@ -51,7 +51,7 @@ void *xrealloc(void *ptr, size_t size);          fseek(fp, 0, SEEK_SET);                             \          fread(buf, sizeof(u32), *size/sizeof(u32), fp);     \                                                              \ -        return 0;                                           \ +        ret =  0;                                           \      exit:                                                   \          fclose(fp);                                         \          return ret;                                         \ diff --git a/src/device.c b/src/device.c index a200e5e..f85b1a6 100644 --- a/src/device.c +++ b/src/device.c @@ -10,11 +10,21 @@  // 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" @@ -52,13 +62,14 @@ 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_swap_chain(device_t device, struct device_info *info); -static int create_render_pass(device_t device, struct device_info *info);  static int create_pipeline(device_t device, struct device_info *info);  static void destroy_swap_chain(device_t device);  static void destroy_pipeline(device_t device);  // --- Helper Function --- +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); @@ -107,12 +118,13 @@ 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;      SWCH.swap_chain = VK_NULL_HANDLE;      SWCH.nimages = 0; + +    PPLN.pipeline = VK_NULL_HANDLE; +    PPLN.layout = VK_NULL_HANDLE; +    PPLN.render_pass = VK_NULL_HANDLE;      CCHECK(create_instance);      CCHECK(create_surface); @@ -122,7 +134,6 @@ device_t device_create(struct device_info *info)      CCHECK(create_physical_device);      CCHECK(create_logical_device);      CCHECK(create_swap_chain); -    CCHECK(create_render_pass);      CCHECK(create_pipeline);      return device;     @@ -166,11 +177,14 @@ static int create_instance(device_t device, struct device_info *info)      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(char *)); +    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++) { @@ -196,18 +210,17 @@ static int create_instance(device_t device, struct device_info *info)      debug_messenger_populate_info(&msg_info);      create_info.pNext = &msg_info; -#endif  - -    if(vkCreateInstance(&create_info, NULL, &device->instance) != VK_SUCCESS) { -        err("vkCreateInstance: failed"); -        goto exit; -    } +#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 @@ -239,7 +252,7 @@ static int create_physical_device(device_t device, struct device_info *info)          goto exit;      } -    VkPhysicalDevice *devices = xcalloc(dev_count, sizeof(VkPhysicalDevice)); +    VkPhysicalDevice *devices = xcalloc(dev_count, sizeof(*devices));      vkEnumeratePhysicalDevices(device->instance, &dev_count, devices);      for(u32 i = 0; i < dev_count; i++) { @@ -270,20 +283,17 @@ static int create_logical_device(device_t device, struct device_info *info)      struct queue_family_idx indices = {0};      device_queue_families(device->physical_device, device->surface, &indices); -    // queue infos -    #define QUEUE_FAMILY_COUNT 2 -     -    VkDeviceQueueCreateInfo queue_infos[QUEUE_FAMILY_COUNT] = {0}; -    u32 queue_indices[QUEUE_FAMILY_COUNT] = { +    // queue infos     +    u32 unique_queue_family_count = 0; +    u32 queue_indices[] = {          indices.graphics_family, indices.present_family,      }; - -    u32 unique_queue_family_count = 0; +     +    VkDeviceQueueCreateInfo queue_infos[ARR_SIZE(queue_indices)] = {0};      float queue_priority = 1.0f; -     -    // basically get add only the unique queue families -    for(size_t i = 0; i < QUEUE_FAMILY_COUNT; i++) +    // 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++) { @@ -323,10 +333,7 @@ static int create_logical_device(device_t device, struct device_info *info)      // so i wont bother adding them      create_info.enabledLayerCount = 0; -    if(vkCreateDevice(device->physical_device, &create_info, NULL, &device->logical_device) != VK_SUCCESS) { -        err("vkCreateDevice: failed"); -        goto exit; -    } +    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); @@ -338,17 +345,16 @@ exit:  static int create_swap_chain(device_t device, struct device_info *info)  { -         (void)info;      int ret = 1; -    struct swap_chain_support_details details; +    struct swap_chain_support_details details = {0};      swap_chain_support(device->physical_device, device->surface, &details);      VkSurfaceFormatKHR surface_format;      VkPresentModeKHR   present_mode;      VkExtent2D         extent; -    u32                image_count = 3; +    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); @@ -370,15 +376,15 @@ static int create_swap_chain(device_t device, struct device_info *info)      create_info.imageArrayLayers = 1;      create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; -    struct queue_family_idx indices; +    struct queue_family_idx indices = {0};      device_queue_families(device->physical_device, device->surface, &indices); -    u32 queue_indices[2] = { indices.graphics_family, indices.present_family }; +    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 = 2; +        create_info.queueFamilyIndexCount = ARR_SIZE(queue_indices);          create_info.pQueueFamilyIndices = queue_indices;      } else {          create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -394,11 +400,9 @@ static int create_swap_chain(device_t device, struct device_info *info)      create_info.oldSwapchain = NULL; -    if (vkCreateSwapchainKHR(device->logical_device, &create_info, NULL, &SWCH.swap_chain) != VK_SUCCESS) { -        err("Couldn't create a Swapchain"); -        goto exit; -    } +    VCHECK(vkCreateSwapchainKHR, device->logical_device, &create_info, NULL, &SWCH.swap_chain); +    // Get the Images      SWCH.image_format = surface_format.format;      SWCH.extent = extent; @@ -429,10 +433,7 @@ static int create_swap_chain(device_t device, struct device_info *info)          create_info.subresourceRange.baseArrayLayer = 0;          create_info.subresourceRange.layerCount = 1; -        if(vkCreateImageView(device->logical_device, &create_info, NULL, &SWCH.image_views[i]) != VK_SUCCESS) { -            err("Couldn't create image view"); -            goto exit; -        } +        VCHECK(vkCreateImageView, device->logical_device, &create_info, NULL, &SWCH.image_views[i]);      }      ret = 0; @@ -446,6 +447,7 @@ 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);      } +          if(SWCH.nimages != 0) {          free(SWCH.images);          free(SWCH.image_views); @@ -454,52 +456,12 @@ static void destroy_swap_chain(device_t device)      vkDestroySwapchainKHR(device->logical_device, SWCH.swap_chain, NULL);  } -static int create_render_pass(device_t device, struct device_info *info) -{ -    (void)info; -    int ret = 1; - -    VkAttachmentDescription color_attachment = {0}; -    color_attachment.format = SWCH.image_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; - -    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; - -    if (vkCreateRenderPass(device->logical_device, &render_pass_info, NULL, &PPLN.render_pass) != VK_SUCCESS) { -        err("Couldnt create a render pass"); -        goto exit; -    } -     -    ret = 0; -exit: -    return ret; -} -  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; @@ -518,10 +480,11 @@ static int create_pipeline(device_t device, struct device_info *info)      frag_stage.module = frag_shader;      frag_stage.pName = "main"; -    VkPipelineShaderStageCreateInfo shader_stages[2] = { vert_stage, frag_stage }; +    VkPipelineShaderStageCreateInfo shader_stages[] = { vert_stage, frag_stage }; -    VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; -     +    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); @@ -601,6 +564,7 @@ static int create_pipeline(device_t device, struct device_info *info)      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 @@ -608,10 +572,38 @@ static int create_pipeline(device_t device, struct device_info *info)      pipeline_layout_info.pushConstantRangeCount = 0; // Optional      pipeline_layout_info.pPushConstantRanges = NULL; // Optional -    if(vkCreatePipelineLayout(device->logical_device, &pipeline_layout_info, NULL, &PPLN.layout) != VK_SUCCESS) { -        goto exit; -    } +    VCHECK(vkCreatePipelineLayout, device->logical_device, &pipeline_layout_info, NULL, &PPLN.layout); + +    // Create Render Pass +    VkAttachmentDescription color_attachment = {0}; +    color_attachment.format = SWCH.image_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; + +    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; + +    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; @@ -633,17 +625,12 @@ static int create_pipeline(device_t device, struct device_info *info)      pipeline_info.basePipelineHandle = VK_NULL_HANDLE; // Optional      pipeline_info.basePipelineIndex = -1; // Optional -    if(vkCreateGraphicsPipelines(device->logical_device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &PPLN.pipeline) != VK_SUCCESS) { -        err("Couldnt create a graphics pipeline"); -        goto exit; -    } +    VCHECK(vkCreateGraphicsPipelines, device->logical_device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &PPLN.pipeline);      ret = 0;  exit: -    if(frag_shader != VK_NULL_HANDLE) -        vkDestroyShaderModule(device->logical_device, frag_shader, NULL); -    if(vert_shader != VK_NULL_HANDLE) -        vkDestroyShaderModule(device->logical_device, vert_shader, NULL); +    vkDestroyShaderModule(device->logical_device, frag_shader, NULL); +    vkDestroyShaderModule(device->logical_device, vert_shader, NULL);      return ret;  } @@ -659,7 +646,7 @@ static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surfa      u32 count = 0;      vkGetPhysicalDeviceQueueFamilyProperties(phy_device, &count, NULL); -    VkQueueFamilyProperties *properties = xcalloc(count, sizeof(VkQueueFamilyProperties)); +    VkQueueFamilyProperties *properties = xcalloc(count, sizeof(*properties));      vkGetPhysicalDeviceQueueFamilyProperties(phy_device, &count, properties);      for(u32 i = 0; i < count; i++) { @@ -699,10 +686,12 @@ static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface  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(VkExtensionProperties)); +    VkExtensionProperties *properties = xcalloc(count, sizeof(*properties));      vkEnumerateDeviceExtensionProperties(phy_device, NULL, &count, properties);      for(size_t i = 0; i < ARR_SIZE(device_extensions); i++) @@ -711,16 +700,18 @@ static bool device_has_extension_support(VkPhysicalDevice phy_device)          for(u32 j = 0; j < count; j++)              if(strncmp(device_extensions[i], properties[j].extensionName, 256) == 0) {                  present = true; +                break;              }          if(!present) { -            free(properties); -            return false; +            goto exit;          }      } +    ret = true; +exit:      free(properties); -    return true; +    return ret;  }  static int swap_chain_support(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct swap_chain_support_details *details) @@ -801,10 +792,7 @@ static int pipeline_load_shader_module(VkDevice device, char *path, VkShaderModu      create_info.codeSize = size;      create_info.pCode = buf; -    if (vkCreateShaderModule(device, &create_info, NULL, module) != VK_SUCCESS) { -        err("Couldnt create shader module"); -        goto exit; -    } +    VCHECK(vkCreateShaderModule, device, &create_info, NULL, module);      ret = 0;  exit:     @@ -812,6 +800,43 @@ 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) @@ -830,16 +855,16 @@ static bool instance_has_validation_layers(const char * const *layers, u32 nlaye  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); -    if(CreateDebugUtilsMessengerEXT(device->instance, &cinfo, NULL, &device->debug_messenger) != VK_SUCCESS) { -        info("CreateDebugUtilMessengerEXT: failed"); -        return 1; -    } +    VCHECK(CreateDebugUtilsMessengerEXT, device->instance, &cinfo, NULL, &device->debug_messenger); -    return 0; +    ret = 0; +exit: +    return ret;  }  static void debug_messenger_populate_info(VkDebugUtilsMessengerCreateInfoEXT *info) diff --git a/src/window.c b/src/window.c index 4a498e6..9810a42 100644 --- a/src/window.c +++ b/src/window.c @@ -3,11 +3,15 @@  window_t window_create(struct window_info *info)  { -    info->flags |= SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN; +    info->flags |= SDL_WINDOW_VULKAN;      SDL_Vulkan_LoadLibrary(NULL);      window_t window = SDL_CreateWindow(info->title, info->x, info->y,                                         info->w, info->h, info->flags); +    if(window == NULL) { +        err("SDL_CreateWindow: failed"); +    } +          return window;  } @@ -20,6 +24,7 @@ void window_destroy(window_t window)  int window_extension_info(window_t window, unsigned int *ext_count, const char **extensions)  {      if(SDL_Vulkan_GetInstanceExtensions((SDL_Window *)window, ext_count, extensions) == SDL_FALSE) { +        err("SDL_Vulkan_GetInstanceExtensions: failed");          return 1;      } @@ -29,6 +34,7 @@ int window_extension_info(window_t window, unsigned int *ext_count, const char *  int window_create_surface(window_t window, VkInstance instance, VkSurfaceKHR *surface)  {      if(SDL_Vulkan_CreateSurface((SDL_Window *)window, instance, surface) == SDL_FALSE) { +        err("SDL_Vulkan_CreateSurface: failed");          return 1;      } | 
