<commit_before>#include "lib.h"

#define VMA_IMPLEMENTATION
#include "vk.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define GLFW_EXPOSE_NATIVE_WIN32
#include "glfw/glfw3.h"
#include "glfw/glfw3native.h"

static const VkDescriptorPoolSize descriptor_pool_sizes[] = {
    {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,             16},
    {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,              16},
    {VK_DESCRIPTOR_TYPE_SAMPLER,                    16},
    {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,              16},
};

constexpr uint32_t max_descriptor_sets = 64;
constexpr uint32_t max_timestamp_queries = 64;

//
// Vk_Instance is a container that stores common Vulkan resources like vulkan instance,
// device, command pool, swapchain, etc.
//
Vk_Instance vk;

#ifdef _WIN32
VkSurfaceKHR platform_create_surface(VkInstance instance, GLFWwindow* window) {
    VkWin32SurfaceCreateInfoKHR desc{ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
    desc.hinstance = ::GetModuleHandle(nullptr);
    desc.hwnd = glfwGetWin32Window(window);
    VkSurfaceKHR surface;
    VK_CHECK(vkCreateWin32SurfaceKHR(instance, &desc, nullptr, &surface));
    return surface;
}
#else
#error platform_create_surface() is not implemented on this platform
#endif

static void create_instance(bool enable_validation_layers) {
    const char* instance_extensions[] = {
        VK_KHR_SURFACE_EXTENSION_NAME,
        VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
        VK_EXT_DEBUG_UTILS_EXTENSION_NAME
    };

    uint32_t count = 0;
    VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr));
    std::vector<VkExtensionProperties> extension_properties(count);
    VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, extension_properties.data()));

    for (auto name : instance_extensions) {
        bool supported = false;
        for (const auto& property : extension_properties) {
            if (!strcmp(property.extensionName, name)) {
                supported = true;
                break;
            }
        }
        if (!supported)
            error("Vulkan: required instance extension is not available: " + std::string(name));
    }

    VkApplicationInfo app_info { VK_STRUCTURE_TYPE_APPLICATION_INFO };
    // The highest version of instance-level, physical-device-level or
    // device-level functionality we are going to use.
    app_info.apiVersion = VK_API_VERSION_1_2;

    VkInstanceCreateInfo desc { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
    desc.pApplicationInfo        = &app_info;
    desc.enabledExtensionCount   = sizeof(instance_extensions)/sizeof(instance_extensions[0]);
    desc.ppEnabledExtensionNames = instance_extensions;

    if (enable_validation_layers) {
        static const char* layer_names[] = {
            "VK_LAYER_KHRONOS_validation"
        };
        desc.enabledLayerCount = (uint32_t)std::size(layer_names);
        desc.ppEnabledLayerNames = layer_names;
    }    

    VK_CHECK(vkCreateInstance(&desc, nullptr, &vk.instance));
}

static void create_device(GLFWwindow* window) {
    // select physical device
    {
        uint32_t count;
        VK_CHECK(vkEnumeratePhysicalDevices(vk.instance, &count, nullptr));

        if (count == 0)
            error("There are no Vulkan physical devices available");

        std::vector<VkPhysicalDevice> physical_devices(count);
        VK_CHECK(vkEnumeratePhysicalDevices(vk.instance, &count, physical_devices.data()));

        for (const auto& physical_device : physical_devices)
        {
            VkPhysicalDeviceProperties props;
            vkGetPhysicalDeviceProperties(physical_device, &props);

            // Check for device-level Vulkan 1.2 compatibility.
            if (VK_VERSION_MAJOR(props.apiVersion) == 1 && VK_VERSION_MINOR(props.apiVersion) >= 2)
            {
                vk.physical_device = physical_device;
                vk.timestamp_period_ms = (double)props.limits.timestampPeriod * 1e-6;
                break;
            }
        }

        if (vk.physical_device == nullptr)
            error("Failed to find physical device that supports requested Vulkan API version");
    }

    vk.surface = platform_create_surface(vk.instance, window);

    // select queue family
    {
        uint32_t queue_family_count;
        vkGetPhysicalDeviceQueueFamilyProperties(vk.physical_device, &queue_family_count, nullptr);

        std::vector<VkQueueFamilyProperties> queue_families(queue_family_count);
        vkGetPhysicalDeviceQueueFamilyProperties(vk.physical_device, &queue_family_count, queue_families.data());

        // select queue family with presentation and graphics support
        vk.queue_family_index = -1;
        for (uint32_t i = 0; i < queue_family_count; i++) {
            VkBool32 presentation_supported;
            VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(vk.physical_device, i, vk.surface, &presentation_supported));

            if (presentation_supported && (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
                vk.queue_family_index = i;
                break;
            }
        }
        if (vk.queue_family_index == -1)
            error("Vulkan: failed to find queue family");
    }

    // create VkDevice
    {
        std::vector<const char*> device_extensions = {
            VK_KHR_SWAPCHAIN_EXTENSION_NAME
        };

        uint32_t count = 0;
        VK_CHECK(vkEnumerateDeviceExtensionProperties(vk.physical_device, nullptr, &count, nullptr));
        std::vector<VkExtensionProperties> extension_properties(count);
        VK_CHECK(vkEnumerateDeviceExtensionProperties(vk.physical_device, nullptr, &count, extension_properties.data()));

        auto is_extension_supported = [&extension_properties](const char* extension_name) {
            for (const auto& property : extension_properties) {
                if (!strcmp(property.extensionName, extension_name)) {
                    return true;
                }
            }
            return false;
        };
        for (auto required_extension : device_extensions) {
            if (!is_extension_supported(required_extension))
                error("Vulkan: required device extension is not available: " + std::string(required_extension));
        }

        const float priority = 1.0;
        VkDeviceQueueCreateInfo queue_create_info { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
        queue_create_info.queueFamilyIndex = vk.queue_family_index;
        queue_create_info.queueCount = 1;
        queue_create_info.pQueuePriorities = &priority;

        VkPhysicalDeviceVulkan12Features vulkan12_features { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES };
        vulkan12_features.bufferDeviceAddress = VK_TRUE;

        VkPhysicalDeviceFeatures2 features2 { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
        features2.pNext = &vulkan12_features;

        VkDeviceCreateInfo device_create_info { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
        device_create_info.pNext = &features2;
        device_create_info.queueCreateInfoCount = 1;
        device_create_info.pQueueCreateInfos = &queue_create_info;
        device_create_info.enabledExtensionCount = (uint32_t)device_extensions.size();
        device_create_info.ppEnabledExtensionNames = device_extensions.data();

        VK_CHECK(vkCreateDevice(vk.physical_device, &device_create_info, nullptr, &vk.device));
    }
}

static VKAPI_ATTR VkBool32 VKAPI_CALL debug_utils_messenger_callback(
    VkDebugUtilsMessageSeverityFlagBitsEXT          message_severity,
    VkDebugUtilsMessageTypeFlagsEXT                 message_type,
    const VkDebugUtilsMessengerCallbackDataEXT*     callback_data,
    void*                                           user_data)
{
#ifdef _WIN32
    printf("%s\n", callback_data->pMessage);
    OutputDebugStringA(callback_data->pMessage);
    OutputDebugStringA("\n");
    DebugBreak();
#endif
    return VK_FALSE;
}

void Vk_Image::destroy() {
    vkDestroyImage(vk.device, handle, nullptr);
    vkDestroyImageView(vk.device, view, nullptr);
    vmaFreeMemory(vk.allocator, allocation);
    *this = Vk_Image{};
}

void Vk_Buffer::destroy() {
    vkDestroyBuffer(vk.device, handle, nullptr);
    vmaFreeMemory(vk.allocator, allocation);
    *this = Vk_Buffer{};
}

void vk_initialize(GLFWwindow* window, bool enable_validation_layers) {
    VK_CHECK(volkInitialize());
    uint32_t instance_version = volkGetInstanceVersion();

    // Require version 1.1 or higher of instance-level functionality.
    // "As long as the instance supports at least Vulkan 1.1, an application can use different 
    // versions of Vulkan with an instance than it does with a device or physical device."
    bool loader_supports_version_higher_than_or_equal_to_1_1 =
        VK_VERSION_MAJOR(instance_version) > 1 || VK_VERSION_MINOR(instance_version) >= 1;
    if (!loader_supports_version_higher_than_or_equal_to_1_1)
        error("Old Vulkan loader detected which supports only Vulkan 1.0, please update your driver");

    create_instance(enable_validation_layers);
    volkLoadInstance(vk.instance);<commit_msg>Switch to Vulkan 1.3<commit_after>#include "lib.h"

#define VMA_IMPLEMENTATION
#include "vk.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define GLFW_EXPOSE_NATIVE_WIN32
#include "glfw/glfw3.h"
#include "glfw/glfw3native.h"

static const VkDescriptorPoolSize descriptor_pool_sizes[] = {
    {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,             16},
    {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,              16},
    {VK_DESCRIPTOR_TYPE_SAMPLER,                    16},
    {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,              16},
};

constexpr uint32_t max_descriptor_sets = 64;
constexpr uint32_t max_timestamp_queries = 64;

//
// Vk_Instance is a container that stores common Vulkan resources like vulkan instance,
// device, command pool, swapchain, etc.
//
Vk_Instance vk;

#ifdef _WIN32
VkSurfaceKHR platform_create_surface(VkInstance instance, GLFWwindow* window) {
    VkWin32SurfaceCreateInfoKHR desc{ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
    desc.hinstance = ::GetModuleHandle(nullptr);
    desc.hwnd = glfwGetWin32Window(window);
    VkSurfaceKHR surface;
    VK_CHECK(vkCreateWin32SurfaceKHR(instance, &desc, nullptr, &surface));
    return surface;
}
#else
#error platform_create_surface() is not implemented on this platform
#endif

static void create_instance(bool enable_validation_layers) {
    const char* instance_extensions[] = {
        VK_KHR_SURFACE_EXTENSION_NAME,
        VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
        VK_EXT_DEBUG_UTILS_EXTENSION_NAME
    };

    uint32_t count = 0;
    VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr));
    std::vector<VkExtensionProperties> extension_properties(count);
    VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, extension_properties.data()));

    for (auto name : instance_extensions) {
        bool supported = false;
        for (const auto& property : extension_properties) {
            if (!strcmp(property.extensionName, name)) {
                supported = true;
                break;
            }
        }
        if (!supported)
            error("Required instance extension is not available: " + std::string(name));
    }

    VkApplicationInfo app_info { VK_STRUCTURE_TYPE_APPLICATION_INFO };
    app_info.apiVersion = VK_API_VERSION_1_3;

    VkInstanceCreateInfo instance_create_info { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
    instance_create_info.pApplicationInfo = &app_info;
    instance_create_info.enabledExtensionCount = sizeof(instance_extensions)/sizeof(instance_extensions[0]);
    instance_create_info.ppEnabledExtensionNames = instance_extensions;

    if (enable_validation_layers) {
        static const char* layer_names[] = {
            "VK_LAYER_KHRONOS_validation"
        };
		instance_create_info.enabledLayerCount = (uint32_t)std::size(layer_names);
		instance_create_info.ppEnabledLayerNames = layer_names;
    }    

    VK_CHECK(vkCreateInstance(&instance_create_info, nullptr, &vk.instance));
}

static void create_device(GLFWwindow* window) {
    // select physical device
    {
        uint32_t count;
        VK_CHECK(vkEnumeratePhysicalDevices(vk.instance, &count, nullptr));

        if (count == 0)
            error("There are no Vulkan physical devices available");

        std::vector<VkPhysicalDevice> physical_devices(count);
        VK_CHECK(vkEnumeratePhysicalDevices(vk.instance, &count, physical_devices.data()));

        for (const auto& physical_device : physical_devices)
        {
            VkPhysicalDeviceProperties props;
            vkGetPhysicalDeviceProperties(physical_device, &props);

            // Check for device-level Vulkan 1.3 compatibility.
            if (VK_VERSION_MAJOR(props.apiVersion) == 1 && VK_VERSION_MINOR(props.apiVersion) >= 3)
            {
                vk.physical_device = physical_device;
                vk.timestamp_period_ms = (double)props.limits.timestampPeriod * 1e-6;
                break;
            }
        }

        if (vk.physical_device == nullptr)
            error("Failed to find physical device that supports requested Vulkan API version");
    }

    vk.surface = platform_create_surface(vk.instance, window);

    // select queue family
    {
        uint32_t queue_family_count;
        vkGetPhysicalDeviceQueueFamilyProperties(vk.physical_device, &queue_family_count, nullptr);

        std::vector<VkQueueFamilyProperties> queue_families(queue_family_count);
        vkGetPhysicalDeviceQueueFamilyProperties(vk.physical_device, &queue_family_count, queue_families.data());

        // select queue family with presentation and graphics support
        vk.queue_family_index = -1;
        for (uint32_t i = 0; i < queue_family_count; i++) {
            VkBool32 presentation_supported;
            VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(vk.physical_device, i, vk.surface, &presentation_supported));

            if (presentation_supported && (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
                vk.queue_family_index = i;
                break;
            }
        }
        if (vk.queue_family_index == -1)
            error("Vulkan: failed to find queue family");
    }

    // create VkDevice
    {
        std::vector<const char*> device_extensions = {
            VK_KHR_SWAPCHAIN_EXTENSION_NAME
        };

        uint32_t count = 0;
        VK_CHECK(vkEnumerateDeviceExtensionProperties(vk.physical_device, nullptr, &count, nullptr));
        std::vector<VkExtensionProperties> extension_properties(count);
        VK_CHECK(vkEnumerateDeviceExtensionProperties(vk.physical_device, nullptr, &count, extension_properties.data()));

        auto is_extension_supported = [&extension_properties](const char* extension_name) {
            for (const auto& property : extension_properties) {
                if (!strcmp(property.extensionName, extension_name)) {
                    return true;
                }
            }
            return false;
        };
        for (auto required_extension : device_extensions) {
            if (!is_extension_supported(required_extension))
                error("Vulkan: required device extension is not available: " + std::string(required_extension));
        }

        const float priority = 1.0;
        VkDeviceQueueCreateInfo queue_create_info { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
        queue_create_info.queueFamilyIndex = vk.queue_family_index;
        queue_create_info.queueCount = 1;
        queue_create_info.pQueuePriorities = &priority;

		VkPhysicalDeviceBufferDeviceAddressFeatures buffer_device_address_features{
			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES };
		buffer_device_address_features.bufferDeviceAddress = VK_TRUE;

        VkPhysicalDeviceFeatures2 features2 { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
        features2.pNext = &buffer_device_address_features;

        VkDeviceCreateInfo device_create_info { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
        device_create_info.pNext = &features2;
        device_create_info.queueCreateInfoCount = 1;
        device_create_info.pQueueCreateInfos = &queue_create_info;
        device_create_info.enabledExtensionCount = (uint32_t)device_extensions.size();
        device_create_info.ppEnabledExtensionNames = device_extensions.data();

        VK_CHECK(vkCreateDevice(vk.physical_device, &device_create_info, nullptr, &vk.device));
    }
}

static VKAPI_ATTR VkBool32 VKAPI_CALL debug_utils_messenger_callback(
    VkDebugUtilsMessageSeverityFlagBitsEXT          message_severity,
    VkDebugUtilsMessageTypeFlagsEXT                 message_type,
    const VkDebugUtilsMessengerCallbackDataEXT*     callback_data,
    void*                                           user_data)
{
#ifdef _WIN32
    printf("%s\n", callback_data->pMessage);
    OutputDebugStringA(callback_data->pMessage);
    OutputDebugStringA("\n");
    DebugBreak();
#endif
    return VK_FALSE;
}

void Vk_Image::destroy() {
    vkDestroyImage(vk.device, handle, nullptr);
    vkDestroyImageView(vk.device, view, nullptr);
    vmaFreeMemory(vk.allocator, allocation);
    *this = Vk_Image{};
}

void Vk_Buffer::destroy() {
    vkDestroyBuffer(vk.device, handle, nullptr);
    vmaFreeMemory(vk.allocator, allocation);
    *this = Vk_Buffer{};
}

void vk_initialize(GLFWwindow* window, bool enable_validation_layers) {
    VK_CHECK(volkInitialize());
    uint32_t instance_version = volkGetInstanceVersion();

    // Require version 1.1 or higher of instance-level functionality.
    // "As long as the instance supports at least Vulkan 1.1, an application can use different 
    // versions of Vulkan with an instance than it does with a device or physical device."
    bool instance_version_higher_than_or_equal_to_1_1 =
        VK_VERSION_MAJOR(instance_version) > 1 || VK_VERSION_MINOR(instance_version) >= 1;
    if (!instance_version_higher_than_or_equal_to_1_1)
        error("The supported instance version is Vulkan 1.1 or higher, but Vulkan 1.0 loader is detected");

    create_instance(enable_validation_layers);
    volkLoadInstance(vk.instance);
{'fraction_non_alphanumeric': 0.08337919647771051, 'fraction_numerical': 0.010787011557512383, 'mean_word_length': 3.38807051436851, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1937757', 'n_tokens_mistral': 5647, 'n_tokens_neox': 5324, 'n_words': 1001}