diff options
Diffstat (limited to 'src/renderer.c')
| -rw-r--r-- | src/renderer.c | 1470 |
1 files changed, 0 insertions, 1470 deletions
diff --git a/src/renderer.c b/src/renderer.c deleted file mode 100644 index 7022af6..0000000 --- a/src/renderer.c +++ /dev/null @@ -1,1470 +0,0 @@ -#include "log.h" -#include "renderer.h" -#include "src/platform.h" -#include "vulkan/vulkan_core.h" -#include <assert.h> - -static const char *VALIDATION_LAYERS[] = {"VK_LAYER_KHRONOS_validation"}; -static constexpr int VALIDATION_LAYER_COUNT = - sizeof(VALIDATION_LAYERS) / sizeof(VALIDATION_LAYERS[0]); - -#ifdef VGLTF_DEBUG -static constexpr bool enable_validation_layers = true; -#else -static constexpr bool enable_validation_layers = false; -#endif - -static VKAPI_ATTR VkBool32 VKAPI_CALL -debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, - VkDebugUtilsMessageTypeFlagBitsEXT message_type, - const VkDebugUtilsMessengerCallbackDataEXT *callback_data, - void *user_data) { - (void)message_severity; - (void)message_type; - (void)user_data; - VGLTF_LOG_DBG("validation layer: %s", callback_data->pMessage); - return VK_FALSE; -} - -static constexpr int REQUIRED_INSTANCE_EXTENSIONS_ARRAY_CAPACITY = 10; -struct required_instance_extensions { - const char *extensions[REQUIRED_INSTANCE_EXTENSIONS_ARRAY_CAPACITY]; - uint32_t count; -}; -void required_instance_extensions_push( - struct required_instance_extensions *required_instance_extensions, - const char *required_instance_extension) { - if (required_instance_extensions->count == - REQUIRED_INSTANCE_EXTENSIONS_ARRAY_CAPACITY) { - VGLTF_PANIC("required instance extensions array is full"); - } - required_instance_extensions - ->extensions[required_instance_extensions->count++] = - required_instance_extension; -} - -static constexpr int SUPPORTED_INSTANCE_EXTENSIONS_ARRAY_CAPACITY = 128; -struct supported_instance_extensions { - VkExtensionProperties - properties[SUPPORTED_INSTANCE_EXTENSIONS_ARRAY_CAPACITY]; - uint32_t count; -}; -bool supported_instance_extensions_init( - struct supported_instance_extensions *supported_instance_extensions) { - if (vkEnumerateInstanceExtensionProperties( - nullptr, &supported_instance_extensions->count, nullptr) != - VK_SUCCESS) { - goto err; - } - - if (supported_instance_extensions->count > - SUPPORTED_INSTANCE_EXTENSIONS_ARRAY_CAPACITY) { - VGLTF_LOG_ERR("supported instance extensions array cannot fit all the " - "VkExtensionProperties"); - goto err; - } - - if (vkEnumerateInstanceExtensionProperties( - nullptr, &supported_instance_extensions->count, - supported_instance_extensions->properties) != VK_SUCCESS) { - goto err; - } - return true; -err: - return false; -} -void supported_instance_extensions_debug_print( - const struct supported_instance_extensions *supported_instance_extensions) { - VGLTF_LOG_DBG("Supported instance extensions:"); - for (uint32_t i = 0; i < supported_instance_extensions->count; i++) { - VGLTF_LOG_DBG("\t- %s", - supported_instance_extensions->properties[i].extensionName); - } -} -bool supported_instance_extensions_includes( - const struct supported_instance_extensions *supported_instance_extensions, - const char *extension_name) { - for (uint32_t supported_instance_extension_index = 0; - supported_instance_extension_index < - supported_instance_extensions->count; - supported_instance_extension_index++) { - const VkExtensionProperties *extension_properties = - &supported_instance_extensions - ->properties[supported_instance_extension_index]; - if (strcmp(extension_properties->extensionName, extension_name) == 0) { - return true; - } - } - - return false; -} - -static constexpr uint32_t SUPPORTED_VALIDATION_LAYERS_ARRAY_CAPACITY = 64; -struct supported_validation_layers { - VkLayerProperties properties[SUPPORTED_VALIDATION_LAYERS_ARRAY_CAPACITY]; - uint32_t count; -}; -bool supported_validation_layers_init( - struct supported_validation_layers *supported_validation_layers) { - if (vkEnumerateInstanceLayerProperties(&supported_validation_layers->count, - nullptr) != VK_SUCCESS) { - goto err; - } - - if (supported_validation_layers->count > - SUPPORTED_VALIDATION_LAYERS_ARRAY_CAPACITY) { - VGLTF_LOG_ERR("supported validation layers array cannot fit all the " - "VkLayerProperties"); - goto err; - } - - if (vkEnumerateInstanceLayerProperties( - &supported_validation_layers->count, - supported_validation_layers->properties) != VK_SUCCESS) { - goto err; - } - - return true; -err: - return false; -} - -static bool are_validation_layer_supported() { - struct supported_validation_layers supported_layers = {}; - if (!supported_validation_layers_init(&supported_layers)) { - goto err; - } - - for (int requested_layer_index = 0; - requested_layer_index < VALIDATION_LAYER_COUNT; - requested_layer_index++) { - const char *requested_layer_name = VALIDATION_LAYERS[requested_layer_index]; - bool requested_layer_found = false; - for (uint32_t supported_layer_index = 0; - supported_layer_index < supported_layers.count; - supported_layer_index++) { - VkLayerProperties *supported_layer = - &supported_layers.properties[supported_layer_index]; - if (strcmp(requested_layer_name, supported_layer->layerName) == 0) { - requested_layer_found = true; - break; - } - } - - if (!requested_layer_found) { - goto err; - } - } - - return true; -err: - return false; -} - -static bool fetch_required_instance_extensions( - struct required_instance_extensions *required_extensions, - struct vgltf_platform *platform) { - struct supported_instance_extensions supported_extensions = {}; - if (!supported_instance_extensions_init(&supported_extensions)) { - VGLTF_LOG_ERR( - "Couldn't fetch supported instance extensions details (OOM?)"); - goto err; - } - supported_instance_extensions_debug_print(&supported_extensions); - - uint32_t platform_required_extension_count = 0; - const char *const *platform_required_extensions = - vgltf_platform_get_vulkan_instance_extensions( - platform, &platform_required_extension_count); - for (uint32_t platform_required_extension_index = 0; - platform_required_extension_index < platform_required_extension_count; - platform_required_extension_index++) { - required_instance_extensions_push( - required_extensions, - platform_required_extensions[platform_required_extension_index]); - } - required_instance_extensions_push( - required_extensions, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - - if (enable_validation_layers) { - required_instance_extensions_push(required_extensions, - VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - } - - bool all_extensions_supported = true; - for (uint32_t required_extension_index = 0; - required_extension_index < required_extensions->count; - required_extension_index++) { - const char *required_extension_name = - required_extensions->extensions[required_extension_index]; - if (!supported_instance_extensions_includes(&supported_extensions, - required_extension_name)) { - VGLTF_LOG_ERR("Unsupported instance extension: %s", - required_extension_name); - all_extensions_supported = false; - } - } - - if (!all_extensions_supported) { - VGLTF_LOG_ERR("Some required extensions are unsupported."); - goto err; - } - - return true; -err: - return false; -} - -static void populate_debug_messenger_create_info( - VkDebugUtilsMessengerCreateInfoEXT *create_info) { - *create_info = (VkDebugUtilsMessengerCreateInfoEXT){}; - create_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - create_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; - create_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; - create_info->pfnUserCallback = debug_callback; -} - -static bool vgltf_renderer_create_instance(struct vgltf_renderer *renderer, - struct vgltf_platform *platform) { - VGLTF_LOG_INFO("Creating vulkan instance..."); - if (enable_validation_layers && !are_validation_layer_supported()) { - VGLTF_LOG_ERR("Requested validation layers aren't supported"); - goto err; - } - - VkApplicationInfo application_info = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pApplicationName = "Visible GLTF", - .applicationVersion = VK_MAKE_VERSION(0, 1, 0), - .pEngineName = "No Engine", - .engineVersion = VK_MAKE_VERSION(1, 0, 0), - .apiVersion = VK_API_VERSION_1_2}; - - struct required_instance_extensions required_extensions = {}; - fetch_required_instance_extensions(&required_extensions, platform); - - VkInstanceCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pApplicationInfo = &application_info, - .enabledExtensionCount = required_extensions.count, - .ppEnabledExtensionNames = required_extensions.extensions, - .flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR}; - - VkDebugUtilsMessengerCreateInfoEXT debug_create_info; - if (enable_validation_layers) { - create_info.enabledLayerCount = VALIDATION_LAYER_COUNT; - create_info.ppEnabledLayerNames = VALIDATION_LAYERS; - populate_debug_messenger_create_info(&debug_create_info); - create_info.pNext = &debug_create_info; - } - - if (vkCreateInstance(&create_info, nullptr, &renderer->instance) != - VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to create VkInstance"); - goto err; - } - - return true; -err: - return false; -} - -static VkResult create_debug_utils_messenger_ext( - VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *create_info, - const VkAllocationCallbacks *allocator, - VkDebugUtilsMessengerEXT *debug_messenger) { - auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( - instance, "vkCreateDebugUtilsMessengerEXT"); - if (func != nullptr) { - return func(instance, create_info, allocator, debug_messenger); - } - - return VK_ERROR_EXTENSION_NOT_PRESENT; -} - -static void -destroy_debug_utils_messenger_ext(VkInstance instance, - VkDebugUtilsMessengerEXT debug_messenger, - const VkAllocationCallbacks *allocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( - instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != nullptr) { - func(instance, debug_messenger, allocator); - } -} - -static void -vgltf_renderer_setup_debug_messenger(struct vgltf_renderer *renderer) { - if (!enable_validation_layers) - return; - VkDebugUtilsMessengerCreateInfoEXT create_info; - populate_debug_messenger_create_info(&create_info); - create_debug_utils_messenger_ext(renderer->instance, &create_info, nullptr, - &renderer->debug_messenger); -} - -static constexpr int AVAILABLE_PHYSICAL_DEVICE_ARRAY_CAPACITY = 128; -struct available_physical_devices { - VkPhysicalDevice devices[AVAILABLE_PHYSICAL_DEVICE_ARRAY_CAPACITY]; - uint32_t count; -}; -static bool -available_physical_devices_init(VkInstance instance, - struct available_physical_devices *devices) { - - if (vkEnumeratePhysicalDevices(instance, &devices->count, nullptr) != - VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't enumerate physical devices"); - goto err; - } - - if (devices->count == 0) { - VGLTF_LOG_ERR("Failed to find any GPU with Vulkan support"); - goto err; - } - - if (devices->count > AVAILABLE_PHYSICAL_DEVICE_ARRAY_CAPACITY) { - VGLTF_LOG_ERR("available physical devices array cannot fit all available " - "physical devices"); - goto err; - } - - if (vkEnumeratePhysicalDevices(instance, &devices->count, devices->devices) != - VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't enumerate physical devices"); - goto err; - } - - return true; -err: - return false; -} - -struct queue_family_indices { - uint32_t graphics_family; - uint32_t present_family; - bool has_graphics_family; - bool has_present_family; -}; -bool queue_family_indices_is_complete( - const struct queue_family_indices *indices) { - return indices->has_graphics_family && indices->has_present_family; -} -bool queue_family_indices_for_device(struct queue_family_indices *indices, - VkPhysicalDevice device, - VkSurfaceKHR surface) { - static constexpr uint32_t QUEUE_FAMILY_PROPERTIES_ARRAY_CAPACITY = 64; - uint32_t queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, - nullptr); - - if (queue_family_count > QUEUE_FAMILY_PROPERTIES_ARRAY_CAPACITY) { - VGLTF_LOG_ERR( - "Queue family properties array cannot fit all queue family properties"); - goto err; - } - - VkQueueFamilyProperties - queue_family_properties[QUEUE_FAMILY_PROPERTIES_ARRAY_CAPACITY] = {}; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, - queue_family_properties); - - for (uint32_t queue_family_index = 0; queue_family_index < queue_family_count; - queue_family_index++) { - VkQueueFamilyProperties *queue_family = - &queue_family_properties[queue_family_index]; - - VkBool32 present_support; - vkGetPhysicalDeviceSurfaceSupportKHR(device, queue_family_index, surface, - &present_support); - - if (queue_family->queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices->graphics_family = queue_family_index; - indices->has_graphics_family = true; - } - - if (present_support) { - indices->present_family = queue_family_index; - indices->has_present_family = true; - } - - if (queue_family_indices_is_complete(indices)) { - break; - } - } - - return true; -err: - return false; -} - -static bool is_in_array(uint32_t *array, int length, uint32_t value) { - for (int i = 0; i < length; i++) { - if (array[i] == value) { - return true; - } - } - - return false; -} - -static constexpr uint32_t SUPPORTED_EXTENSIONS_ARRAY_CAPACITY = 128; -struct supported_extensions { - VkExtensionProperties properties[SUPPORTED_EXTENSIONS_ARRAY_CAPACITY]; - uint32_t count; -}; -bool supported_extensions_init( - struct supported_extensions *supported_extensions, - VkPhysicalDevice device) { - if (vkEnumerateDeviceExtensionProperties(device, nullptr, - &supported_extensions->count, - nullptr) != VK_SUCCESS) { - goto err; - } - - if (supported_extensions->count > SUPPORTED_EXTENSIONS_ARRAY_CAPACITY) { - VGLTF_LOG_ERR( - "supported extensions aarray cannot fit all the VkExtensionProperties"); - goto err; - } - - if (vkEnumerateDeviceExtensionProperties( - device, nullptr, &supported_extensions->count, - supported_extensions->properties) != VK_SUCCESS) { - goto err; - } - - return true; -err: - return false; -} - -static bool supported_extensions_includes_extension( - struct supported_extensions *supported_extensions, - const char *extension_name) { - for (uint32_t supported_extension_index = 0; - supported_extension_index < supported_extensions->count; - supported_extension_index++) { - if (strcmp(supported_extensions->properties[supported_extension_index] - .extensionName, - extension_name) == 0) { - return true; - } - } - return false; -} - -static const char *DEVICE_EXTENSIONS[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset"}; -static constexpr int DEVICE_EXTENSION_COUNT = - sizeof(DEVICE_EXTENSIONS) / sizeof(DEVICE_EXTENSIONS[0]); -static bool are_device_extensions_supported(VkPhysicalDevice device) { - struct supported_extensions supported_extensions = {}; - if (!supported_extensions_init(&supported_extensions, device)) { - goto err; - } - - for (uint32_t required_extension_index = 0; - required_extension_index < DEVICE_EXTENSION_COUNT; - required_extension_index++) { - if (!supported_extensions_includes_extension( - &supported_extensions, - DEVICE_EXTENSIONS[required_extension_index])) { - VGLTF_LOG_DBG("Unsupported: %s", - DEVICE_EXTENSIONS[required_extension_index]); - goto err; - } - } - - return true; - -err: - return false; -} - -static constexpr int SWAPCHAIN_SUPPORT_DETAILS_MAX_SURFACE_FORMAT_COUNT = 256; -static constexpr int SWAPCHAIN_SUPPORT_DETAILS_MAX_PRESENT_MODE_COUNT = 256; -struct swapchain_support_details { - VkSurfaceCapabilitiesKHR capabilities; - VkSurfaceFormatKHR - formats[SWAPCHAIN_SUPPORT_DETAILS_MAX_SURFACE_FORMAT_COUNT]; - VkPresentModeKHR - present_modes[SWAPCHAIN_SUPPORT_DETAILS_MAX_PRESENT_MODE_COUNT]; - uint32_t format_count; - uint32_t present_mode_count; -}; -bool swapchain_support_details_query_from_device( - struct swapchain_support_details *swapchain_support_details, - VkPhysicalDevice device, VkSurfaceKHR surface) { - if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - device, surface, &swapchain_support_details->capabilities) != - VK_SUCCESS) { - goto err; - } - - if (vkGetPhysicalDeviceSurfaceFormatsKHR( - device, surface, &swapchain_support_details->format_count, nullptr) != - VK_SUCCESS) { - goto err; - } - - if (swapchain_support_details->format_count != 0 && - swapchain_support_details->format_count < - SWAPCHAIN_SUPPORT_DETAILS_MAX_SURFACE_FORMAT_COUNT) { - if (vkGetPhysicalDeviceSurfaceFormatsKHR( - device, surface, &swapchain_support_details->format_count, - swapchain_support_details->formats) != VK_SUCCESS) { - goto err; - } - } - - if (vkGetPhysicalDeviceSurfacePresentModesKHR( - device, surface, &swapchain_support_details->present_mode_count, - nullptr) != VK_SUCCESS) { - goto err; - } - - if (swapchain_support_details->present_mode_count != 0 && - swapchain_support_details->present_mode_count < - SWAPCHAIN_SUPPORT_DETAILS_MAX_PRESENT_MODE_COUNT) { - if (vkGetPhysicalDeviceSurfacePresentModesKHR( - device, surface, &swapchain_support_details->present_mode_count, - swapchain_support_details->present_modes) != VK_SUCCESS) { - goto err; - } - } - - return true; -err: - return false; -} - -static bool is_physical_device_suitable(VkPhysicalDevice device, - VkSurfaceKHR surface) { - struct queue_family_indices indices = {}; - queue_family_indices_for_device(&indices, device, surface); - - VGLTF_LOG_DBG("Checking for physical device extension support"); - bool extensions_supported = are_device_extensions_supported(device); - VGLTF_LOG_DBG("Supported: %d", extensions_supported); - - bool swapchain_adequate = false; - if (extensions_supported) { - - VGLTF_LOG_DBG("Checking for swapchain support details"); - struct swapchain_support_details swapchain_support_details = {}; - if (!swapchain_support_details_query_from_device(&swapchain_support_details, - device, surface)) { - VGLTF_LOG_ERR("Couldn't query swapchain support details from device"); - goto err; - } - - swapchain_adequate = swapchain_support_details.format_count > 0 && - swapchain_support_details.present_mode_count > 0; - } - - return queue_family_indices_is_complete(&indices) && extensions_supported && - swapchain_adequate; -err: - return false; -} - -static bool -vgltf_renderer_pick_physical_device(struct vgltf_renderer *renderer) { - VkPhysicalDevice physical_device = VK_NULL_HANDLE; - - struct available_physical_devices available_physical_devices = {}; - if (!available_physical_devices_init(renderer->instance, - &available_physical_devices)) { - VGLTF_LOG_ERR("Couldn't fetch available physical devices"); - goto err; - } - - for (uint32_t available_physical_device_index = 0; - available_physical_device_index < available_physical_devices.count; - available_physical_device_index++) { - VkPhysicalDevice available_physical_device = - available_physical_devices.devices[available_physical_device_index]; - if (is_physical_device_suitable(available_physical_device, - renderer->surface)) { - physical_device = available_physical_device; - break; - } - } - - if (physical_device == VK_NULL_HANDLE) { - VGLTF_LOG_ERR("Failed to find a suitable GPU"); - goto err; - } - - renderer->physical_device = physical_device; - - return true; -err: - return false; -} - -static bool -vgltf_renderer_create_logical_device(struct vgltf_renderer *renderer) { - struct queue_family_indices queue_family_indices = {}; - queue_family_indices_for_device(&queue_family_indices, - renderer->physical_device, renderer->surface); - static constexpr int MAX_QUEUE_FAMILY_COUNT = 2; - - uint32_t unique_queue_families[MAX_QUEUE_FAMILY_COUNT] = {}; - int unique_queue_family_count = 0; - - if (!is_in_array(unique_queue_families, unique_queue_family_count, - queue_family_indices.graphics_family)) { - assert(unique_queue_family_count < MAX_QUEUE_FAMILY_COUNT); - unique_queue_families[unique_queue_family_count++] = - queue_family_indices.graphics_family; - } - if (!is_in_array(unique_queue_families, unique_queue_family_count, - queue_family_indices.present_family)) { - assert(unique_queue_family_count < MAX_QUEUE_FAMILY_COUNT); - unique_queue_families[unique_queue_family_count++] = - queue_family_indices.present_family; - } - - float queue_priority = 1.f; - VkDeviceQueueCreateInfo queue_create_infos[MAX_QUEUE_FAMILY_COUNT] = {}; - int queue_create_info_count = 0; - for (int unique_queue_family_index = 0; - unique_queue_family_index < unique_queue_family_count; - unique_queue_family_index++) { - queue_create_infos[queue_create_info_count++] = (VkDeviceQueueCreateInfo){ - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .queueFamilyIndex = unique_queue_families[unique_queue_family_index], - .queueCount = 1, - .pQueuePriorities = &queue_priority}; - } - - VkPhysicalDeviceFeatures device_features = {}; - VkDeviceCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pQueueCreateInfos = queue_create_infos, - .queueCreateInfoCount = queue_create_info_count, - .pEnabledFeatures = &device_features, - .ppEnabledExtensionNames = DEVICE_EXTENSIONS, - .enabledExtensionCount = DEVICE_EXTENSION_COUNT}; - if (vkCreateDevice(renderer->physical_device, &create_info, nullptr, - &renderer->device) != VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to create logical device"); - goto err; - } - - vkGetDeviceQueue(renderer->device, queue_family_indices.graphics_family, 0, - &renderer->graphics_queue); - vkGetDeviceQueue(renderer->device, queue_family_indices.present_family, 0, - &renderer->present_queue); - - return true; -err: - return false; -} - -static bool vgltf_renderer_create_surface(struct vgltf_renderer *renderer, - struct vgltf_platform *platform) { - if (!vgltf_platform_create_vulkan_surface(platform, renderer->instance, - &renderer->surface)) { - VGLTF_LOG_ERR("Couldn't create surface"); - goto err; - } - - return true; -err: - return false; -} - -static VkSurfaceFormatKHR -choose_swapchain_surface_format(VkSurfaceFormatKHR *available_formats, - uint32_t available_format_count) { - for (uint32_t available_format_index = 0; - available_format_index < available_format_count; - available_format_index++) { - VkSurfaceFormatKHR *available_format = - &available_formats[available_format_index]; - if (available_format->format == VK_FORMAT_B8G8R8A8_SRGB && - available_format->colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - return *available_format; - } - } - - return available_formats[0]; -} - -static VkPresentModeKHR -choose_swapchain_present_mode(VkPresentModeKHR *available_modes, - uint32_t available_mode_count) { - for (uint32_t available_mode_index = 0; - available_mode_index < available_mode_count; available_mode_index++) { - VkPresentModeKHR available_mode = available_modes[available_mode_index]; - if (available_mode == VK_PRESENT_MODE_MAILBOX_KHR) { - return available_mode; - } - } - - return VK_PRESENT_MODE_FIFO_KHR; -} - -static uint32_t clamp_uint32(uint32_t min, uint32_t max, uint32_t value) { - return value < min ? min : value > max ? max : value; -} - -static VkExtent2D -choose_swapchain_extent(const VkSurfaceCapabilitiesKHR *capabilities, int width, - int height) { - if (capabilities->currentExtent.width != UINT32_MAX) { - return capabilities->currentExtent; - } else { - VkExtent2D actual_extent = {width, height}; - actual_extent.width = - clamp_uint32(capabilities->minImageExtent.width, - capabilities->maxImageExtent.width, actual_extent.width); - actual_extent.height = - clamp_uint32(capabilities->minImageExtent.height, - capabilities->maxImageExtent.height, actual_extent.height); - return actual_extent; - } -} - -static bool vgltf_renderer_create_swapchain(struct vgltf_renderer *renderer) { - struct swapchain_support_details swapchain_support_details = {}; - swapchain_support_details_query_from_device( - &swapchain_support_details, renderer->physical_device, renderer->surface); - - VkSurfaceFormatKHR surface_format = - choose_swapchain_surface_format(swapchain_support_details.formats, - swapchain_support_details.format_count); - VkPresentModeKHR present_mode = choose_swapchain_present_mode( - swapchain_support_details.present_modes, - swapchain_support_details.present_mode_count); - - VkExtent2D extent = choose_swapchain_extent( - &swapchain_support_details.capabilities, renderer->window_size.width, - renderer->window_size.height); - uint32_t image_count = - swapchain_support_details.capabilities.minImageCount + 1; - if (swapchain_support_details.capabilities.maxImageCount > 0 && - image_count > swapchain_support_details.capabilities.maxImageCount) { - image_count = swapchain_support_details.capabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR create_info = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = renderer->surface, - .minImageCount = image_count, - .imageFormat = surface_format.format, - .imageColorSpace = surface_format.colorSpace, - .imageExtent = extent, - .imageArrayLayers = 1, - .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT}; - struct queue_family_indices indices = {}; - queue_family_indices_for_device(&indices, renderer->physical_device, - renderer->surface); - uint32_t queue_family_indices[] = {indices.graphics_family, - indices.present_family}; - if (indices.graphics_family != indices.present_family) { - create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - create_info.queueFamilyIndexCount = 2; - create_info.pQueueFamilyIndices = queue_family_indices; - } else { - create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - } - - create_info.preTransform = - swapchain_support_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 = VK_NULL_HANDLE; - - if (vkCreateSwapchainKHR(renderer->device, &create_info, nullptr, - &renderer->swapchain) != VK_SUCCESS) { - VGLTF_LOG_ERR("Swapchain creation failed!"); - goto err; - } - - if (vkGetSwapchainImagesKHR(renderer->device, renderer->swapchain, - &renderer->swapchain_image_count, - nullptr) != VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't get swapchain image count"); - goto destroy_swapchain; - } - - if (renderer->swapchain_image_count > - VGLTF_RENDERER_MAX_SWAPCHAIN_IMAGE_COUNT) { - VGLTF_LOG_ERR("Swapchain image array cannot fit all %d swapchain images", - renderer->swapchain_image_count); - goto destroy_swapchain; - } - - if (vkGetSwapchainImagesKHR(renderer->device, renderer->swapchain, - &renderer->swapchain_image_count, - renderer->swapchain_images) != VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't get swapchain images"); - goto destroy_swapchain; - } - - renderer->swapchain_image_format = surface_format.format; - renderer->swapchain_extent = extent; - - return true; -destroy_swapchain: - vkDestroySwapchainKHR(renderer->device, renderer->swapchain, nullptr); -err: - return false; -} - -static bool vgltf_renderer_create_image_views(struct vgltf_renderer *renderer) { - uint32_t swapchain_image_index; - for (swapchain_image_index = 0; - swapchain_image_index < renderer->swapchain_image_count; - swapchain_image_index++) { - VkImage swapchain_image = renderer->swapchain_images[swapchain_image_index]; - - VkImageViewCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = swapchain_image, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = renderer->swapchain_image_format, - .components = {VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY}, - .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .levelCount = 1, - .layerCount = 1}}; - - if (vkCreateImageView( - renderer->device, &create_info, nullptr, - &renderer->swapchain_image_views[swapchain_image_index]) != - VK_SUCCESS) { - goto err; - } - } - return true; -err: - for (uint32_t to_remove_index = 0; to_remove_index < swapchain_image_index; - to_remove_index++) { - vkDestroyImageView(renderer->device, - renderer->swapchain_image_views[to_remove_index], - nullptr); - } - return false; -} - -static bool create_shader_module(VkDevice device, const unsigned char *code, - int size, VkShaderModule *out) { - VkShaderModuleCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .codeSize = size, - .pCode = (const uint32_t *)code, - }; - if (vkCreateShaderModule(device, &create_info, nullptr, out) != VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't create shader module"); - goto err; - } - return true; -err: - return false; -} - -static bool vgltf_renderer_create_render_pass(struct vgltf_renderer *renderer) { - VkAttachmentDescription color_attachment = { - .format = renderer->swapchain_image_format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR}; - VkAttachmentReference color_attachment_ref = { - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }; - VkSubpassDescription subpass = {.pipelineBindPoint = - VK_PIPELINE_BIND_POINT_GRAPHICS, - .pColorAttachments = &color_attachment_ref, - .colorAttachmentCount = 1}; - VkSubpassDependency dependency = { - .srcSubpass = VK_SUBPASS_EXTERNAL, - .dstSubpass = 0, - .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccessMask = 0, - .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT}; - - VkRenderPassCreateInfo render_pass_info = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = &color_attachment, - .subpassCount = 1, - .pSubpasses = &subpass, - .dependencyCount = 1, - .pDependencies = &dependency}; - - if (vkCreateRenderPass(renderer->device, &render_pass_info, nullptr, - &renderer->render_pass) != VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to create render pass"); - goto err; - } - - return true; -err: - return false; -} - -static bool -vgltf_renderer_create_graphics_pipeline(struct vgltf_renderer *renderer) { - static constexpr unsigned char triangle_shader_vert_code[] = { -#embed "../compiled_shaders/triangle.vert.spv" - }; - static constexpr unsigned char triangle_shader_frag_code[] = { -#embed "../compiled_shaders/triangle.frag.spv" - }; - - VkShaderModule triangle_shader_vert_module; - if (!create_shader_module(renderer->device, triangle_shader_vert_code, - sizeof(triangle_shader_vert_code), - &triangle_shader_vert_module)) { - VGLTF_LOG_ERR("Couldn't create triangle vert shader module"); - goto err; - } - - VkShaderModule triangle_shader_frag_module; - if (!create_shader_module(renderer->device, triangle_shader_frag_code, - sizeof(triangle_shader_frag_code), - &triangle_shader_frag_module)) { - VGLTF_LOG_ERR("Couldn't create triangle frag shader module"); - goto destroy_vert_shader_module; - } - - VkPipelineShaderStageCreateInfo triangle_shader_vert_stage_create_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_VERTEX_BIT, - .module = triangle_shader_vert_module, - .pName = "main"}; - VkPipelineShaderStageCreateInfo triangle_shader_frag_stage_create_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = triangle_shader_frag_module, - .pName = "main"}; - VkPipelineShaderStageCreateInfo shader_stages[] = { - triangle_shader_vert_stage_create_info, - triangle_shader_frag_stage_create_info}; - - VkDynamicState dynamic_states[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - - VkPipelineDynamicStateCreateInfo dynamic_state = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .dynamicStateCount = sizeof(dynamic_states) / sizeof(dynamic_states[0]), - .pDynamicStates = dynamic_states}; - - VkPipelineVertexInputStateCreateInfo vertex_input_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = 0, - .vertexAttributeDescriptionCount = 0, - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - .primitiveRestartEnable = VK_FALSE, - }; - - VkPipelineViewportStateCreateInfo viewport_state = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .viewportCount = 1, - .scissorCount = 1}; - - VkPipelineRasterizationStateCreateInfo rasterizer = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .depthClampEnable = VK_FALSE, - .rasterizerDiscardEnable = VK_FALSE, - .polygonMode = VK_POLYGON_MODE_FILL, - .lineWidth = 1.f, - .cullMode = VK_CULL_MODE_BACK_BIT, - .frontFace = VK_FRONT_FACE_CLOCKWISE, - .depthBiasEnable = VK_FALSE}; - - VkPipelineMultisampleStateCreateInfo multisampling = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .sampleShadingEnable = VK_FALSE, - .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, - }; - - VkPipelineColorBlendAttachmentState color_blend_attachment = { - .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - .blendEnable = VK_FALSE, - }; - - VkPipelineColorBlendStateCreateInfo color_blending = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .logicOpEnable = VK_FALSE, - .attachmentCount = 1, - .pAttachments = &color_blend_attachment}; - - VkPipelineLayoutCreateInfo pipeline_layout_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - }; - - if (vkCreatePipelineLayout(renderer->device, &pipeline_layout_info, nullptr, - &renderer->pipeline_layout) != VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't create pipeline layout"); - goto destroy_frag_shader_module; - } - - VkGraphicsPipelineCreateInfo pipeline_info = { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .stageCount = 2, - .pStages = shader_stages, - .pVertexInputState = &vertex_input_info, - .pInputAssemblyState = &input_assembly, - .pViewportState = &viewport_state, - .pRasterizationState = &rasterizer, - .pMultisampleState = &multisampling, - .pColorBlendState = &color_blending, - .pDynamicState = &dynamic_state, - .layout = renderer->pipeline_layout, - .renderPass = renderer->render_pass, - .subpass = 0, - }; - - if (vkCreateGraphicsPipelines(renderer->device, VK_NULL_HANDLE, 1, - &pipeline_info, nullptr, - &renderer->graphics_pipeline) != VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't create pipeline"); - goto destroy_pipeline_layout; - } - - vkDestroyShaderModule(renderer->device, triangle_shader_frag_module, nullptr); - vkDestroyShaderModule(renderer->device, triangle_shader_vert_module, nullptr); - return true; -destroy_pipeline_layout: - vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr); -destroy_frag_shader_module: - vkDestroyShaderModule(renderer->device, triangle_shader_frag_module, nullptr); -destroy_vert_shader_module: - vkDestroyShaderModule(renderer->device, triangle_shader_vert_module, nullptr); -err: - return false; -} - -static bool -vgltf_renderer_create_framebuffers(struct vgltf_renderer *renderer) { - for (uint32_t i = 0; i < renderer->swapchain_image_count; i++) { - VkImageView attachments[] = {renderer->swapchain_image_views[i]}; - - VkFramebufferCreateInfo framebuffer_info = { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = renderer->render_pass, - .attachmentCount = 1, - .pAttachments = attachments, - .width = renderer->swapchain_extent.width, - .height = renderer->swapchain_extent.height, - .layers = 1}; - - if (vkCreateFramebuffer(renderer->device, &framebuffer_info, nullptr, - &renderer->swapchain_framebuffers[i]) != - VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to create framebuffer"); - goto err; - } - } - - return true; -err: - return false; -} - -static bool -vgltf_renderer_create_command_pool(struct vgltf_renderer *renderer) { - struct queue_family_indices queue_family_indices = {}; - if (!queue_family_indices_for_device(&queue_family_indices, - renderer->physical_device, - renderer->surface)) { - VGLTF_LOG_ERR("Couldn't fetch queue family indices"); - goto err; - } - - VkCommandPoolCreateInfo pool_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = queue_family_indices.graphics_family}; - - if (vkCreateCommandPool(renderer->device, &pool_info, nullptr, - &renderer->command_pool) != VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't create command pool"); - goto err; - } - - return true; -err: - return false; -} - -static bool -vgltf_renderer_create_command_buffer(struct vgltf_renderer *renderer) { - VkCommandBufferAllocateInfo allocate_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .commandPool = renderer->command_pool, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT}; - - if (vkAllocateCommandBuffers(renderer->device, &allocate_info, - renderer->command_buffer) != VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't allocate command buffers"); - goto err; - } - - return true; -err: - return false; -} - -static bool -vgltf_renderer_create_sync_objects(struct vgltf_renderer *renderer) { - VkSemaphoreCreateInfo semaphore_info = { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - }; - - VkFenceCreateInfo fence_info = {.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - .flags = VK_FENCE_CREATE_SIGNALED_BIT}; - - int frame_in_flight_index = 0; - for (; frame_in_flight_index < VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT; - frame_in_flight_index++) { - if (vkCreateSemaphore( - renderer->device, &semaphore_info, nullptr, - &renderer->image_available_semaphores[frame_in_flight_index]) != - VK_SUCCESS || - vkCreateSemaphore( - renderer->device, &semaphore_info, nullptr, - &renderer->render_finished_semaphores[frame_in_flight_index]) != - VK_SUCCESS || - vkCreateFence(renderer->device, &fence_info, nullptr, - &renderer->in_flight_fences[frame_in_flight_index]) != - VK_SUCCESS) { - VGLTF_LOG_ERR("Couldn't create sync objects"); - goto err; - } - } - - return true; -err: - for (int frame_in_flight_to_delete_index = 0; - frame_in_flight_to_delete_index < frame_in_flight_index; - frame_in_flight_to_delete_index++) { - vkDestroyFence(renderer->device, - renderer->in_flight_fences[frame_in_flight_index], nullptr); - vkDestroySemaphore( - renderer->device, - renderer->render_finished_semaphores[frame_in_flight_index], nullptr); - vkDestroySemaphore( - renderer->device, - renderer->image_available_semaphores[frame_in_flight_index], nullptr); - } - return false; -} - -static void vgltf_renderer_cleanup_swapchain(struct vgltf_renderer *renderer) { - for (uint32_t framebuffer_index = 0; - framebuffer_index < renderer->swapchain_image_count; - framebuffer_index++) { - vkDestroyFramebuffer(renderer->device, - renderer->swapchain_framebuffers[framebuffer_index], - nullptr); - } - - for (uint32_t image_view_index = 0; - image_view_index < renderer->swapchain_image_count; image_view_index++) { - vkDestroyImageView(renderer->device, - renderer->swapchain_image_views[image_view_index], - nullptr); - } - - vkDestroySwapchainKHR(renderer->device, renderer->swapchain, nullptr); -} - -static bool vgltf_renderer_recreate_swapchain(struct vgltf_renderer *renderer) { - vkDeviceWaitIdle(renderer->device); - vgltf_renderer_cleanup_swapchain(renderer); - - // TODO add error handling - vgltf_renderer_create_swapchain(renderer); - vgltf_renderer_create_image_views(renderer); - vgltf_renderer_create_framebuffers(renderer); - return true; -} - -bool vgltf_renderer_triangle_pass(struct vgltf_renderer *renderer) { - vkWaitForFences(renderer->device, 1, - &renderer->in_flight_fences[renderer->current_frame], VK_TRUE, - UINT64_MAX); - - uint32_t image_index; - VkResult acquire_swapchain_image_result = vkAcquireNextImageKHR( - renderer->device, renderer->swapchain, UINT64_MAX, - renderer->image_available_semaphores[renderer->current_frame], - VK_NULL_HANDLE, &image_index); - if (acquire_swapchain_image_result == VK_ERROR_OUT_OF_DATE_KHR || - acquire_swapchain_image_result == VK_SUBOPTIMAL_KHR || - renderer->framebuffer_resized) { - renderer->framebuffer_resized = false; - vgltf_renderer_recreate_swapchain(renderer); - return true; - } else if (acquire_swapchain_image_result != VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to acquire a swapchain image"); - goto err; - } - - vkResetFences(renderer->device, 1, - &renderer->in_flight_fences[renderer->current_frame]); - - vkResetCommandBuffer(renderer->command_buffer[renderer->current_frame], 0); - VkCommandBufferBeginInfo begin_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - }; - - if (vkBeginCommandBuffer(renderer->command_buffer[renderer->current_frame], - &begin_info) != VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to begin recording command buffer"); - goto err; - } - - VkRenderPassBeginInfo render_pass_info = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = renderer->render_pass, - .framebuffer = renderer->swapchain_framebuffers[image_index], - .renderArea = {.offset = {}, .extent = renderer->swapchain_extent}, - .clearValueCount = 1, - .pClearValues = - &(const VkClearValue){.color = {.float32 = {0.f, 0.f, 0.f, 1.f}}}, - - }; - - vkCmdBeginRenderPass(renderer->command_buffer[renderer->current_frame], - &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(renderer->command_buffer[renderer->current_frame], - VK_PIPELINE_BIND_POINT_GRAPHICS, - renderer->graphics_pipeline); - VkViewport viewport = {.x = 0.f, - .y = 0.f, - .width = (float)renderer->swapchain_extent.width, - .height = (float)renderer->swapchain_extent.height, - .minDepth = 0.f, - .maxDepth = 1.f}; - vkCmdSetViewport(renderer->command_buffer[renderer->current_frame], 0, 1, - &viewport); - VkRect2D scissor = {.offset = {}, .extent = renderer->swapchain_extent}; - vkCmdSetScissor(renderer->command_buffer[renderer->current_frame], 0, 1, - &scissor); - - vkCmdDraw(renderer->command_buffer[renderer->current_frame], 3, 1, 0, 0); - - vkCmdEndRenderPass(renderer->command_buffer[renderer->current_frame]); - - if (vkEndCommandBuffer(renderer->command_buffer[renderer->current_frame]) != - VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to record command buffer"); - goto err; - } - - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - }; - - VkSemaphore wait_semaphores[] = { - renderer->image_available_semaphores[renderer->current_frame]}; - VkPipelineStageFlags wait_stages[] = { - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = wait_semaphores; - submit_info.pWaitDstStageMask = wait_stages; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = - &renderer->command_buffer[renderer->current_frame]; - - VkSemaphore signal_semaphores[] = { - renderer->render_finished_semaphores[renderer->current_frame]}; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = signal_semaphores; - if (vkQueueSubmit(renderer->graphics_queue, 1, &submit_info, - renderer->in_flight_fences[renderer->current_frame]) != - VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to submit draw command buffer"); - goto err; - } - - VkPresentInfoKHR present_info = {.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .waitSemaphoreCount = 1, - .pWaitSemaphores = signal_semaphores}; - - VkSwapchainKHR swapchains[] = {renderer->swapchain}; - present_info.swapchainCount = 1; - present_info.pSwapchains = swapchains; - present_info.pImageIndices = &image_index; - VkResult result = vkQueuePresentKHR(renderer->present_queue, &present_info); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { - vgltf_renderer_recreate_swapchain(renderer); - } else if (acquire_swapchain_image_result != VK_SUCCESS) { - VGLTF_LOG_ERR("Failed to acquire a swapchain image"); - goto err; - } - renderer->current_frame = - (renderer->current_frame + 1) % VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT; - return true; -err: - return false; -} - -bool vgltf_renderer_init(struct vgltf_renderer *renderer, - struct vgltf_platform *platform) { - if (!vgltf_renderer_create_instance(renderer, platform)) { - VGLTF_LOG_ERR("instance creation failed"); - goto err; - } - vgltf_renderer_setup_debug_messenger(renderer); - if (!vgltf_renderer_create_surface(renderer, platform)) { - goto destroy_instance; - } - - if (!vgltf_renderer_pick_physical_device(renderer)) { - VGLTF_LOG_ERR("Couldn't pick physical device"); - goto destroy_surface; - } - if (!vgltf_renderer_create_logical_device(renderer)) { - VGLTF_LOG_ERR("Couldn't create logical device"); - goto destroy_device; - } - - struct vgltf_window_size window_size = {800, 600}; - if (!vgltf_platform_get_window_size(platform, &window_size)) { - VGLTF_LOG_ERR("Couldn't get window size"); - goto destroy_device; - } - renderer->window_size = window_size; - - if (!vgltf_renderer_create_swapchain(renderer)) { - VGLTF_LOG_ERR("Couldn't create swapchain"); - goto destroy_device; - } - - if (!vgltf_renderer_create_image_views(renderer)) { - VGLTF_LOG_ERR("Couldn't create image views"); - goto destroy_swapchain; - } - - if (!vgltf_renderer_create_render_pass(renderer)) { - VGLTF_LOG_ERR("Couldn't create render pass"); - goto destroy_image_views; - } - - if (!vgltf_renderer_create_graphics_pipeline(renderer)) { - VGLTF_LOG_ERR("Couldn't create graphics pipeline"); - goto destroy_render_pass; - } - - if (!vgltf_renderer_create_framebuffers(renderer)) { - VGLTF_LOG_ERR("Couldn't create framebuffers"); - goto destroy_graphics_pipeline; - } - - if (!vgltf_renderer_create_command_pool(renderer)) { - VGLTF_LOG_ERR("Couldn't create command pool"); - goto destroy_frame_buffers; - } - - if (!vgltf_renderer_create_command_buffer(renderer)) { - VGLTF_LOG_ERR("Couldn't create command buffer"); - goto destroy_command_pool; - } - - if (!vgltf_renderer_create_sync_objects(renderer)) { - VGLTF_LOG_ERR("Couldn't create sync objects"); - goto destroy_command_pool; - } - - return true; - -destroy_command_pool: - vkDestroyCommandPool(renderer->device, renderer->command_pool, nullptr); -destroy_frame_buffers: - for (uint32_t swapchain_framebuffer_index = 0; - swapchain_framebuffer_index < renderer->swapchain_image_count; - swapchain_framebuffer_index++) { - vkDestroyFramebuffer( - renderer->device, - renderer->swapchain_framebuffers[swapchain_framebuffer_index], nullptr); - } -destroy_graphics_pipeline: - vkDestroyPipeline(renderer->device, renderer->graphics_pipeline, nullptr); - vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr); -destroy_render_pass: - vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr); -destroy_image_views: - for (uint32_t swapchain_image_view_index = 0; - swapchain_image_view_index < renderer->swapchain_image_count; - swapchain_image_view_index++) { - vkDestroyImageView( - renderer->device, - renderer->swapchain_image_views[swapchain_image_view_index], nullptr); - } -destroy_swapchain: - vkDestroySwapchainKHR(renderer->device, renderer->swapchain, nullptr); -destroy_device: - vkDestroyDevice(renderer->device, nullptr); -destroy_surface: - vkDestroySurfaceKHR(renderer->instance, renderer->surface, nullptr); -destroy_instance: - if (enable_validation_layers) { - destroy_debug_utils_messenger_ext(renderer->instance, - renderer->debug_messenger, nullptr); - } - vkDestroyInstance(renderer->instance, nullptr); -err: - return false; -} -void vgltf_renderer_deinit(struct vgltf_renderer *renderer) { - vkDeviceWaitIdle(renderer->device); - vgltf_renderer_cleanup_swapchain(renderer); - vkDestroyPipeline(renderer->device, renderer->graphics_pipeline, nullptr); - vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr); - vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr); - for (int i = 0; i < VGLTF_RENDERER_MAX_FRAME_IN_FLIGHT_COUNT; i++) { - vkDestroySemaphore(renderer->device, - renderer->image_available_semaphores[i], nullptr); - vkDestroySemaphore(renderer->device, - renderer->render_finished_semaphores[i], nullptr); - vkDestroyFence(renderer->device, renderer->in_flight_fences[i], nullptr); - } - vkDestroyCommandPool(renderer->device, renderer->command_pool, nullptr); - vkDestroyDevice(renderer->device, nullptr); - if (enable_validation_layers) { - destroy_debug_utils_messenger_ext(renderer->instance, - renderer->debug_messenger, nullptr); - } - vkDestroySurfaceKHR(renderer->instance, renderer->surface, nullptr); - vkDestroyInstance(renderer->instance, nullptr); -} -void vgltf_renderer_on_window_resized(struct vgltf_renderer *renderer, - struct vgltf_window_size size) { - if (size.width > 0 && size.height > 0 && - size.width != renderer->window_size.width && - size.height != renderer->window_size.height) { - renderer->window_size = size; - renderer->framebuffer_resized = true; - } -} |
