| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- #include "core/VulkanBase.hpp"
- #include <cstring>
- #include "GLFW.hpp"
- import Core.List;
- import Core.Logger;
- import Core.Types;
- import Core.Array;
- using Core::Vulkan::Base;
- #define GET_FUNCTION(name) (reinterpret_cast<PFN_##name>(getFunction(#name)))
- Base::Base() :
- instance(VK_NULL_HANDLE),
- #ifdef DEBUG_VULKAN
- debugMessenger(VK_NULL_HANDLE), debugReportCallback(VK_NULL_HANDLE),
- #endif
- surface(VK_NULL_HANDLE), physicalDevice(VK_NULL_HANDLE),
- device(VK_NULL_HANDLE) {
- }
- Base::~Base() {
- destroy();
- }
- bool Base::initInstance() {
- u32 baseCount = 0;
- const char** baseExtensions = glfwGetRequiredInstanceExtensions(&baseCount);
- if(baseExtensions == nullptr) {
- VK_REPORT_ERROR("Could not get required extensions from GLFW");
- return true;
- }
- Core::List<const char*> extensions;
- for(u32 i = 0; i < baseCount; i++) {
- extensions.add(baseExtensions[i]);
- }
- Core::List<const char*> layers;
- #ifdef DEBUG_VULKAN
- extensions.add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- extensions.add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
- layers.add("VK_LAYER_KHRONOS_validation");
- #endif
- VkApplicationInfo appInfo = {
- .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
- .pApplicationName = "Vulkan",
- .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
- .pEngineName = "Kajetan",
- .engineVersion = VK_MAKE_VERSION(0, 0, 1),
- .apiVersion = VK_API_VERSION_1_1};
- VkInstanceCreateInfo info = {
- .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
- .pApplicationInfo = &appInfo,
- .enabledLayerCount = static_cast<u32>(layers.getLength()),
- .ppEnabledLayerNames = &layers[0],
- .enabledExtensionCount = static_cast<u32>(extensions.getLength()),
- .ppEnabledExtensionNames = &extensions[0]};
- VK_CHECK_TRUE(vkCreateInstance(&info, nullptr, &instance));
- return false;
- }
- #ifdef DEBUG_VULKAN
- static VKAPI_ATTR VkBool32 onVulkanDebugMessenger VKAPI_CALL(
- VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT,
- const VkDebugUtilsMessengerCallbackDataEXT* data, void*) {
- VK_REPORT_WARNING("Vulkan validation layer message: {}", data->pMessage);
- return false;
- }
- bool Base::initDebugMessenger() {
- VkDebugUtilsMessengerCreateInfoEXT info = {
- .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
- .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
- .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,
- .pfnUserCallback = onVulkanDebugMessenger};
- auto f = GET_FUNCTION(vkCreateDebugUtilsMessengerEXT);
- if(f == nullptr) {
- VK_REPORT_WARNING("Could not find debug util messenger function");
- return false;
- }
- VK_CHECK_TRUE(f(instance, &info, nullptr, &debugMessenger));
- return false;
- }
- static VKAPI_ATTR VkBool32 onVulkanDebugReport VKAPI_CALL(
- VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t,
- int32_t, const char* pLayerPrefix, const char* pMessage, void*) {
- VK_REPORT_WARNING("Vulkan debug message '{}': {}", pLayerPrefix, pMessage);
- return false;
- }
- bool Base::initDebugReportCallback() {
- VkDebugReportCallbackCreateInfoEXT info = {
- .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
- .flags = VK_DEBUG_REPORT_WARNING_BIT_EXT |
- VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
- VK_DEBUG_REPORT_ERROR_BIT_EXT,
- .pfnCallback = onVulkanDebugReport};
- auto f = GET_FUNCTION(vkCreateDebugReportCallbackEXT);
- if(f == nullptr) {
- VK_REPORT_WARNING("Could not find debug report function");
- return false;
- }
- VK_CHECK_TRUE(f(instance, &info, nullptr, &debugReportCallback));
- return false;
- }
- void Base::destroyDebugMessenger() {
- if(debugMessenger == VK_NULL_HANDLE) {
- return;
- }
- auto f = GET_FUNCTION(vkDestroyDebugUtilsMessengerEXT);
- if(f == nullptr) {
- VK_REPORT_WARNING(
- "Could not find debug util messenger destroy function");
- return;
- }
- f(instance, debugMessenger, nullptr);
- debugMessenger = VK_NULL_HANDLE;
- }
- void Base::destroyDebugReportCallback() {
- if(debugReportCallback == VK_NULL_HANDLE) {
- return;
- }
- auto f = GET_FUNCTION(vkDestroyDebugReportCallbackEXT);
- if(f == nullptr) {
- VK_REPORT_WARNING("Could not find debug report destroy function");
- return;
- }
- f(instance, debugReportCallback, nullptr);
- debugReportCallback = VK_NULL_HANDLE;
- }
- #endif
- bool Base::initSurface() {
- GLFWwindow* w = Window::get();
- if(w == nullptr) {
- VK_REPORT_ERROR("Init a window before Vulkan");
- return true;
- }
- VK_CHECK_TRUE(glfwCreateWindowSurface(instance, w, nullptr, &surface));
- return false;
- }
- bool Base::init() {
- if(initInstance()) {
- return true;
- }
- #ifdef DEBUG_VULKAN
- if(initDebugMessenger() || initDebugReportCallback()) {
- return true;
- }
- #endif
- return initSurface();
- }
- void Base::destroy() {
- #ifdef DEBUG_VULKAN
- destroyDebugMessenger();
- destroyDebugReportCallback();
- #endif
- if(instance != VK_NULL_HANDLE) {
- vkDestroySurfaceKHR(instance, surface, nullptr);
- surface = VK_NULL_HANDLE;
- vkDestroyDevice(device, nullptr);
- device = VK_NULL_HANDLE;
- }
- vkDestroyInstance(instance, nullptr);
- instance = VK_NULL_HANDLE;
- }
- PFN_vkVoidFunction Base::getFunction(const char* name) {
- return vkGetInstanceProcAddr(instance, name);
- }
- void Base::getPhysicalDeviceProperties(VkPhysicalDeviceProperties& p) {
- vkGetPhysicalDeviceProperties(physicalDevice, &p);
- }
- u32 Base::findQueueFamily(VkQueueFlags flags) {
- Core::Array<VkQueueFamilyProperties, 32> p;
- u32 c = p.getLength();
- vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &c, p.begin());
- for(u32 i = 0; i < c; i++) {
- if((p[i].queueFlags & flags) == flags) {
- return i;
- }
- }
- return INVALID_QUEUE_FAMILY;
- }
- static bool hasPresentationSupport(
- VkPhysicalDevice pd, VkSurfaceKHR s, u32 index) {
- VkBool32 b = false;
- VK_CHECK(false, vkGetPhysicalDeviceSurfaceSupportKHR(pd, index, s, &b));
- return b;
- }
- u32 Base::findSurfaceQueueFamily() {
- u32 c = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &c, nullptr);
- for(u32 i = 0; i < c; i++) {
- if(hasPresentationSupport(physicalDevice, surface, i)) {
- return i;
- }
- }
- return INVALID_QUEUE_FAMILY;
- }
- bool Base::hasExtension(const char* extension) {
- Core::Array<VkExtensionProperties, 1024> e;
- u32 c = e.getLength();
- VK_CHECK(
- false, vkEnumerateDeviceExtensionProperties(
- physicalDevice, nullptr, &c, &e[0]));
- for(u32 i = 0; i < c; i++) {
- if(strcmp(e[i].extensionName, extension) == 0) {
- return true;
- }
- }
- return false;
- }
- bool Base::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR& c) {
- VK_CHECK_TRUE(
- vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &c));
- return false;
- }
- bool Base::findSurfaceFormat(
- VkSurfaceFormatKHR& sf, SurfaceFormatSelector sfs) {
- Core::Array<VkSurfaceFormatKHR, 128> formats;
- u32 c = formats.getLength();
- VK_CHECK_TRUE(vkGetPhysicalDeviceSurfaceFormatsKHR(
- physicalDevice, surface, &c, formats.begin()));
- int bestPoints = 0;
- for(u32 i = 0; i < c; i++) {
- int points = sfs(formats[i]);
- if(points > bestPoints) {
- bestPoints = points;
- sf = formats[i];
- }
- }
- return bestPoints == 0;
- }
- bool Base::findSurfacePresentMode(
- VkPresentModeKHR& m, SurfacePresentModeSelector spms) {
- Core::Array<VkPresentModeKHR, 64> modes;
- u32 c = modes.getLength();
- VK_CHECK_TRUE(vkGetPhysicalDeviceSurfacePresentModesKHR(
- physicalDevice, surface, &c, modes.begin()));
- int bestPoints = 0;
- for(u32 i = 0; i < c; i++) {
- int points = spms(modes[i]);
- if(points > bestPoints) {
- bestPoints = points;
- m = modes[i];
- }
- }
- return bestPoints == 0;
- }
- bool Base::initDevice(
- const List<DeviceQueueData> data, const List<const char*>& extensions) {
- Core::List<VkDeviceQueueCreateInfo> qInfo;
- for(const DeviceQueueData& d : data) {
- VkDeviceQueueCreateInfo& i = qInfo.put();
- i.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- i.queueFamilyIndex = d.queueFamilyIndex;
- i.queueCount = 1;
- i.pQueuePriorities = &d.priority;
- }
- VkPhysicalDeviceFeatures deviceFeatures = {};
- vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
- VkDeviceCreateInfo info = {
- .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .queueCreateInfoCount = static_cast<u32>(qInfo.getLength()),
- .pQueueCreateInfos = &qInfo[0],
- .enabledExtensionCount = static_cast<u32>(extensions.getLength()),
- .ppEnabledExtensionNames = &extensions[0],
- .pEnabledFeatures = &deviceFeatures};
- VK_CHECK_TRUE(vkCreateDevice(physicalDevice, &info, nullptr, &device));
- return false;
- }
- void Base::waitForIdle() {
- if(device != VK_NULL_HANDLE) {
- vkDeviceWaitIdle(device);
- }
- }
- u32 Base::findMemoryType(u32 typeFilter, VkMemoryPropertyFlags flags) {
- VkPhysicalDeviceMemoryProperties m;
- vkGetPhysicalDeviceMemoryProperties(physicalDevice, &m);
- for(u32 i = 0; i < m.memoryTypeCount; i++) {
- if(typeFilter & (1u << i) &&
- (m.memoryTypes[i].propertyFlags & flags) == flags) {
- return i;
- }
- }
- return INVALID_MEMORY_TYPE;
- }
|