From d5a2b6bca9f9cc57dcca19962d5ba9b83d26da3e Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Thu, 16 May 2024 14:22:35 -0300 Subject: refa Move BluCan initialization to BluCat folder --- src/blucat/core.cpp | 503 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 503 insertions(+) create mode 100644 src/blucat/core.cpp (limited to 'src/blucat/core.cpp') diff --git a/src/blucat/core.cpp b/src/blucat/core.cpp new file mode 100644 index 0000000..8478f86 --- /dev/null +++ b/src/blucat/core.cpp @@ -0,0 +1,503 @@ +/* + * Copyright 2022-2024 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core.hpp" + +namespace +{ + +#ifdef DEBUG +VKAPI_ATTR VkBool32 VKAPI_CALL +vk_debug_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_type, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* _obj) +{ + // Set level. + Log::Level log_level; + switch(message_severity) + { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + log_level = Log::Level::Trace; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + log_level = Log::Level::Information; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + log_level = Log::Level::Warning; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + default: + log_level = Log::Level::Error; + break; + } + + // Log message. + BluCat::core.log.message(log_level, callback_data->pMessage); + + return VK_FALSE; +} +#endif + +void +load_threads(void *obj) +{ + auto num_threads{std::thread::hardware_concurrency() - 1}; + for(auto i{0}; i < num_threads; i++) + BluCat::core.threads.emplace_back( + BluCat::core.workers.emplace_back(&BluCat::core.job_queue)); +} + +void +unload_threads(void *obj) +{ + BluCat::core.job_queue.stop(); + for(auto &t: BluCat::core.threads) t.join(); +} + +void +load_fps(void *obj) +{ + using namespace std::chrono; + + BluCat::core.max_frame_duration = + duration(1000 / BluCat::core.fps); + // FIXME: actually calculates the real delta time. + BluCat::core.delta_time = 1.0f / BluCat::core.fps; +} + +void +load_font_library(void *obj) +{ + FT_Error error{FT_Init_FreeType(&BluCat::core.font_library)}; + if(error) throw CommandError{"Failed to open the FreeType library."}; +} + +void +unload_font_library(void *obj) +{ + FT_Done_FreeType(BluCat::core.font_library); +} + +#ifdef DEBUG +void +load_vk_debug_callback(void *obj) +{ + PFN_vkCreateDebugUtilsMessengerEXT debug_messenger; + + // A Vulkan instance extension named VK_EXT_debug_utils and a Vulkan instance + // layer named VK_LAYER_LUNARG_standard_validation are required to enable + // this callback. These instance extension and instance layer are loaded at + // Instance::load_blucat_instance. + VkDebugUtilsMessengerCreateInfoEXT create_info; + create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + create_info.pNext = nullptr; + create_info.messageSeverity = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_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 = vk_debug_callback; + create_info.pUserData = nullptr; + create_info.flags = 0; + + debug_messenger = (PFN_vkCreateDebugUtilsMessengerEXT) + vkGetInstanceProcAddr(BluCat::core.vk_instance, + "vkCreateDebugUtilsMessengerEXT"); + + if(debug_messenger(BluCat::core.vk_instance, &create_info, nullptr, + &BluCat::core.vk_callback) != VK_SUCCESS) + CommandError{"Failed to setup debug callback for Vulkan."}; +} + +void +unload_vk_debug_callback(void *obj) +{ + PFN_vkDestroyDebugUtilsMessengerEXT debug_messenger; + + debug_messenger = (PFN_vkDestroyDebugUtilsMessengerEXT) + vkGetInstanceProcAddr(BluCat::core.vk_instance, + "vkDestroyDebugUtilsMessengerEXT"); + + debug_messenger(BluCat::core.vk_instance, BluCat::core.vk_callback, nullptr); +} +#endif + +void +load_devices(void *obj) +{ + uint32_t devices_count; + std::vector vk_physical_devices; + + // Enumerate physical devices + { + vkEnumeratePhysicalDevices( + BluCat::core.vk_instance, &devices_count, nullptr); + if(devices_count < 1) + CommandError{"Failed to find GPUs with Vulkan support."}; + vk_physical_devices.resize(devices_count); + vkEnumeratePhysicalDevices( + BluCat::core.vk_instance, &devices_count, vk_physical_devices.data()); + } + +#ifdef DEBUG + BluCat::core.log.message(Log::Level::Trace, "Physical devices properties"); +#endif + + BluCat::core.vk_devices.reserve(devices_count); + for(auto i = 0; i < devices_count; i++) + { + // Use swapchain on first device. + if(i == 0) + { + BluCat::core.vk_devices.emplace_back(vk_physical_devices[i], true); + BluCat::core.vk_device_with_swapchain = &BluCat::core.vk_devices[i]; + } + else + BluCat::core.vk_devices.emplace_back(vk_physical_devices[i], false); + } +} + +void +unload_devices(void *obj) +{ + BluCat::core.vk_devices.clear(); +} + +static void +load_swapchain(void *obj) +{ + try { BluCat::core.vk_swapchain = new BluCat::Swapchain(); } + catch(const CommandError &error) + { + std::string error_message{"Failed to create swapchain → "}; + error_message += error.what(); + throw CommandError{error_message}; + } +} + +void +unload_swapchain(void *obj) +{ + delete BluCat::core.vk_swapchain; +} + +void +load_framebuffer(void *obj) +{ + try + { + BluCat::core.vk_framebuffer = new BluCat::Framebuffer(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create framebuffer."}; + } +} + +void +unload_framebuffer(void *obj) +{ + delete BluCat::core.vk_framebuffer; +} + +void +load_render_pass(void *obj) +{ + try + { + BluCat::core.vk_render_pass = new BluCat::RenderPass(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create render pass."}; + } +} + +void +unload_render_pass(void *obj) +{ + delete BluCat::core.vk_render_pass; +} + +void +load_descriptor_set_layout(void *obj) +{ + try + { + BluCat::core.vk_descriptor_set_layout = new BluCat::DescriptorSetLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create descriptor set layouts."}; + } +} + +void +unload_descriptor_set_layout(void *obj) +{ + delete BluCat::core.vk_descriptor_set_layout; +} + +void +load_graphics_pipeline_3d_layout(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_3d_layout = + new BluCat::GraphicsPipeline3DLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 3d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_3d_layout(void *obj) +{ + delete BluCat::core.vk_graphics_pipeline_3d_layout; +} + +void +load_graphics_pipeline_2d_solid_layout(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_2d_solid_layout = + new BluCat::GraphicsPipeline2DSolidLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_solid_layout(void *obj) +{ + delete BluCat::core.vk_graphics_pipeline_2d_solid_layout; +} + +void +load_graphics_pipeline_2d_wired_layout(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_2d_wired_layout = + new BluCat::GraphicsPipeline2DWiredLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_wired_layout(void *obj) +{ + delete BluCat::core.vk_graphics_pipeline_2d_wired_layout; +} + +void +load_light(void *obj) +{ + try + { + BluCat::core.vk_light = new BluCat::Light(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to descriptor sets for light."}; + } +} + +void +unload_light(void *obj) +{ + delete BluCat::core.vk_light; +} + +void +load_graphics_pipeline_3d(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_3d = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 3d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_3d(void *obj) +{ + BluCat::core.vk_graphics_pipeline_3d = nullptr; +} + +void +load_graphics_pipeline_3d_skeletal(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_3d_skeletal = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 3d skeletal graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_3d_skeletal(void *obj) +{ + BluCat::core.vk_graphics_pipeline_3d_skeletal = nullptr; +} + +void +load_graphics_pipeline_sprite_3d(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_sprite_3d = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create sprite 3d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_sprite_3d(void *obj) +{ + BluCat::core.vk_graphics_pipeline_sprite_3d = nullptr; +} + +void +load_graphics_pipeline_2d_solid(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_2d_solid = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_solid(void *obj) +{ + BluCat::core.vk_graphics_pipeline_2d_solid = nullptr; +} + +void +load_graphics_pipeline_2d_wired(void *obj) +{ + try + { + BluCat::core.vk_graphics_pipeline_2d_wired = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_wired(void *obj) +{ + BluCat::core.vk_graphics_pipeline_2d_wired = nullptr; +} + +void +load_renderer(void *obj) +{ + try + { + glm::vec4 region( + 0.f, 0.f, + static_cast(BluCat::core.display_width), + static_cast(BluCat::core.display_height)); + BluCat::core.vk_renderer = new BluCat::Renderer( + {}, + {std::make_shared(region, region.z, region.w)}); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create renderer."}; + } +} + +void +unload_renderer(void *obj) +{ + delete BluCat::core.vk_renderer; +} + +} + +namespace BluCat +{ + +std::random_device random_seed; +std::mt19937 random_number_generator; + +const CommandChain Core::loader{ + {&load_threads, &unload_threads}, + {&load_fps, nullptr}, + {&load_font_library, &unload_font_library}, +#ifdef DEBUG + {&load_vk_debug_callback, &unload_vk_debug_callback}, +#endif + {&load_devices, &unload_devices}, + {&load_swapchain, &unload_swapchain}, + + {&load_render_pass, &unload_render_pass}, + {&load_framebuffer, &unload_framebuffer}, + {&load_descriptor_set_layout, &unload_descriptor_set_layout}, + {&load_graphics_pipeline_3d_layout, + &unload_graphics_pipeline_3d_layout}, + {&load_graphics_pipeline_2d_solid_layout, + &unload_graphics_pipeline_2d_solid_layout}, + {&load_graphics_pipeline_2d_wired_layout, + &unload_graphics_pipeline_2d_wired_layout}, + {&load_light, &unload_light}, + {&load_graphics_pipeline_3d_skeletal, + &unload_graphics_pipeline_3d_skeletal}, + {&load_graphics_pipeline_3d, &unload_graphics_pipeline_3d}, + {&load_graphics_pipeline_sprite_3d, + &unload_graphics_pipeline_sprite_3d}, + {&load_graphics_pipeline_2d_solid, &unload_graphics_pipeline_2d_solid}, + {&load_graphics_pipeline_2d_wired, &unload_graphics_pipeline_2d_wired}, + {&load_renderer, &unload_renderer}, +}; + +Core core; + +} -- cgit v1.2.3