summaryrefslogtreecommitdiffstats
path: root/src/renderer.c
diff options
context:
space:
mode:
authorClement Sibille <clements@lisible.xyz>2025-05-05 08:32:33 +0200
committerClement Sibille <clements@lisible.xyz>2025-05-05 12:24:27 +0200
commitb71eac2069a30349435c192d682e865718c86a15 (patch)
tree33754245a23533e31e6a83390bf190c11dfe2bb9 /src/renderer.c
parent6017db0069977ae85e698a1234f4a2b7632ee495 (diff)
Add a vulkan renderer that renders an OBJ
Diffstat (limited to 'src/renderer.c')
-rw-r--r--src/renderer.c1470
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;
- }
-}
Go back to lisible.xyz