working on code refactor

This commit is contained in:
2024-04-23 20:59:50 +02:00
parent 215a0dc2c3
commit ace4c98945
53 changed files with 1378 additions and 1403 deletions

View File

@@ -1,105 +1,100 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_device.cpp :+: :+: :+: */
/* Device.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:14:29 by maldavid #+# #+# */
/* Updated: 2024/03/25 22:31:54 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:10:08 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <pre_compiled.h>
#include <PreCmpiled.h>
#include "render_core.h"
#include <Renderer/Core/RenderCore.h>
namespace mlx
{
const std::vector<const char*> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
const std::vector<const char*> device_extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
void Device::init()
void Device::Init()
{
pickPhysicalDevice();
PickPhysicalDevice();
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().getFamilies();
Queues::QueueFamilyIndices indices = RenderCore::Get().GetQueue().GetFamilies();
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<std::uint32_t> uniqueQueueFamilies = { indices.graphics_family.value(), indices.present_family.value() };
std::vector<VkDeviceQueueCreateInfo> queue_create_infos;
std::set<std::uint32_t> unique_queue_families = { indices.graphics_family.value(), indices.present_family.value() };
float queuePriority = 1.0f;
for(std::uint32_t queueFamily : uniqueQueueFamilies)
float queue_priority = 1.0f;
for(std::uint32_t queue_family : unique_queue_families)
{
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.push_back(queueCreateInfo);
VkDeviceQueueCreateInfo queue_create_info{};
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info.queueFamilyIndex = queue_family;
queue_create_info.queueCount = 1;
queue_create_info.pQueuePriorities = &queue_priority;
queue_create_infos.push_back(queue_create_info);
}
VkPhysicalDeviceFeatures deviceFeatures{};
VkPhysicalDeviceFeatures device_features{};
VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.queueCreateInfoCount = static_cast<std::uint32_t>(queueCreateInfos.size());
createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = static_cast<std::uint32_t>(deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
createInfo.enabledLayerCount = 0;
VkDeviceCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.queueCreateInfoCount = static_cast<std::uint32_t>(queue_create_infos.size());
create_info.pQueueCreateInfos = queue_create_infos.data();
create_info.pEnabledFeatures = &device_features;
create_info.enabledExtensionCount = static_cast<std::uint32_t>(device_extensions.size());
create_info.ppEnabledExtensionNames = device_extensions.data();
create_info.enabledLayerCount = 0;
VkResult res;
if((res = vkCreateDevice(_physical_device, &createInfo, nullptr, &_device)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create logcal device, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new logical device");
#endif
if((res = vkCreateDevice(m_physical_device, &create_info, nullptr, &m_device)) != VK_SUCCESS)
FatalError("Vulkan : failed to create logcal device, %", VerbaliseVkResult(res));
DebugLog("Vulkan : created new logical device");
}
void Device::pickPhysicalDevice()
void Device::PickPhysicalDevice()
{
std::uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(Render_Core::get().getInstance().get(), &deviceCount, nullptr);
std::uint32_t device_count = 0;
vkEnumeratePhysicalDevices(RenderCore::Get().GetInstance().Get(), &device_count, nullptr);
if(deviceCount == 0)
core::error::report(e_kind::fatal_error, "Vulkan : failed to find GPUs with Vulkan support");
if(device_count == 0)
FatalError("Vulkan : failed to find GPUs with Vulkan support");
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(Render_Core::get().getInstance().get(), &deviceCount, devices.data());
std::vector<VkPhysicalDevice> devices(device_count);
vkEnumeratePhysicalDevices(RenderCore::Get().GetInstance().Get(), &device_count, devices.data());
std::multimap<int, VkPhysicalDevice> devices_score;
for(const auto& device : devices)
{
int score = deviceScore(device);
int score = DeviceScore(device);
devices_score.insert(std::make_pair(score, device));
}
if(devices_score.rbegin()->first > 0)
_physical_device = devices_score.rbegin()->second;
m_physical_device = devices_score.rbegin()->second;
else
core::error::report(e_kind::fatal_error, "Vulkan : failed to find a suitable GPU");
FatalError("Vulkan : failed to find a suitable GPU");
#ifdef DEBUG
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(_physical_device, &props);
core::error::report(e_kind::message, "Vulkan : picked a physical device, %s", props.deviceName);
vkGetPhysicalDeviceProperties(m_physical_device, &props);
DebugLog("Vulkan : picked a physical device, %s", props.deviceName);
#endif
Render_Core::get().getQueue().findQueueFamilies(_physical_device); // update queue indicies to current physical device
RenderCore::Get().GetQueue().FindQueueFamilies(m_physical_device); // update queue indicies to current physical device
}
int Device::deviceScore(VkPhysicalDevice device)
int Device::DeviceScore(VkPhysicalDevice device)
{
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(device);
bool extensionsSupported = checkDeviceExtensionSupport(device);
Queues::QueueFamilyIndices indices = RenderCore::Get().GetQueue().FindQueueFamilies(device);
bool extensions_supported = CheckDeviceExtensionSupport(device);
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(device, &props);
if(!indices.isComplete() || !extensionsSupported)
if(!indices.IsComplete() || !extensions_supported)
return -1;
VkPhysicalDeviceFeatures features;
@@ -122,28 +117,26 @@ namespace mlx
return score;
}
bool Device::checkDeviceExtensionSupport(VkPhysicalDevice device)
bool Device::CheckDeviceExtensionSupport(VkPhysicalDevice device)
{
std::uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
std::uint32_t extension_count;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
std::vector<VkExtensionProperties> available_extensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data());
std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
std::set<std::string> required_extensions(device_extensions.begin(), device_extensions.end());
for(const auto& extension : availableExtensions)
requiredExtensions.erase(extension.extensionName);
for(const auto& extension : available_extensions)
required_extensions.erase(extension.extensionName);
return requiredExtensions.empty();
return required_extensions.empty();
}
void Device::destroy() noexcept
void Device::Destroy() noexcept
{
vkDestroyDevice(_device, nullptr);
_device = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a logical device");
#endif
vkDestroyDevice(m_device, nullptr);
m_device = VK_NULL_HANDLE;
DebugLog("Vulkan : destroyed a logical device");
}
}

View File

@@ -1,58 +1,54 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_fence.cpp :+: :+: :+: */
/* Fence.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 17:53:06 by maldavid #+# #+# */
/* Updated: 2024/03/25 19:02:14 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:13:09 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <pre_compiled.h>
#include <Precompiled.h>
#include <renderer/core/vk_fence.h>
#include <renderer/core/render_core.h>
#include <Renderer/Core/Fence.h>
#include <Renderer/Core/RenderCore.h>
namespace mlx
{
void Fence::init()
void Fence::Init()
{
VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkFenceCreateInfo fence_info{};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkResult res;
if((res = vkCreateFence(Render_Core::get().getDevice().get(), &fenceInfo, nullptr, &_fence)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a synchronization object (fence), %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new fence");
#endif
if((res = vkCreateFence(RenderCore::Get().GetDevice().Get(), &fence_info, nullptr, &m_fence)) != VK_SUCCESS)
FatalError("Vulkan : failed to create a synchronization object (fence), %", VerbaliseVkResult(res));
DebugLog("Vulkan : created new fence");
}
void Fence::wait() noexcept
void Fence::Wait() noexcept
{
vkWaitForFences(Render_Core::get().getDevice().get(), 1, &_fence, VK_TRUE, UINT64_MAX);
vkWaitForFences(RenderCore::Get().GetDevice().Get(), 1, &m_fence, VK_TRUE, UINT64_MAX);
}
void Fence::reset() noexcept
void Fence::Reset() noexcept
{
vkResetFences(Render_Core::get().getDevice().get(), 1, &_fence);
vkResetFences(RenderCore::Get().GetDevice().Get(), 1, &m_fence);
}
bool Fence::isReady() const noexcept
bool Fence::IsReady() const noexcept
{
return vkGetFenceStatus(Render_Core::get().getDevice().get(), _fence) == VK_SUCCESS;
return vkGetFenceStatus(RenderCore::Get().GetDevice().Get(), m_fence) == VK_SUCCESS;
}
void Fence::destroy() noexcept
{
if(_fence != VK_NULL_HANDLE)
vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr);
_fence = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed fence");
#endif
if(m_fence != VK_NULL_HANDLE)
vkDestroyFence(RenderCore::Get().GetDevice().Get(), m_fence, nullptr);
m_fence = VK_NULL_HANDLE;
DebugLog("Vulkan : destroyed fence");
}
}

View File

@@ -1,63 +1,67 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_instance.cpp :+: :+: :+: */
/* Instance.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:04:21 by maldavid #+# #+# */
/* Updated: 2024/03/25 23:10:37 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:43:47 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <pre_compiled.h>
#include <PreCompiled.h>
#include "vk_instance.h"
#include "render_core.h"
#include <platform/window.h>
#include <Renderer/Core/Instance.h>
#include <Renderer/Core/RenderCore.h>
namespace mlx
{
void Instance::init()
void Instance::Init()
{
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pEngineName = "MacroLibX";
appInfo.engineVersion = VK_MAKE_VERSION(1, 3, 1);
appInfo.apiVersion = VK_API_VERSION_1_2;
std::uint32_t api_version = std::min(volkGetInstanceVersion(), MLX_TARGET_VULKAN_API_VERSION);
auto extensions = getRequiredExtensions();
if(api_version == 0)
FatalError("Vulkan API is not supported by this driver");
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledExtensionCount = static_cast<std::uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
createInfo.enabledLayerCount = 0; // will be replaced if validation layers are enabled
createInfo.pNext = nullptr;
m_instance_version = api_version;
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
if constexpr(enableValidationLayers)
VkApplicationInfo app_info{};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pEngineName = "MacroLibX";
app_info.engineVersion = MLX_VERSION;
app_info.apiVersion = api_version;
auto extensions = GetRequiredExtensions();
VkInstanceCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.pApplicationInfo = &app_info;
create_info.enabledExtensionCount = static_cast<std::uint32_t>(extensions.size());
create_info.ppEnabledExtensionNames = extensions.data();
create_info.enabledLayerCount = 0; // will be replaced if validation layers are enabled
create_info.pNext = nullptr;
VkDebugUtilsMessengerCreateInfoEXT debug_create_info;
if constexpr(enable_validation_layers)
{
if(Render_Core::get().getLayers().checkValidationLayerSupport())
if(RenderCore::Get().GetLayers().CheckValidationLayerSupport())
{
createInfo.enabledLayerCount = static_cast<std::uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
Render_Core::get().getLayers().populateDebugMessengerCreateInfo(debugCreateInfo);
createInfo.pNext = static_cast<VkDebugUtilsMessengerCreateInfoEXT*>(&debugCreateInfo);
create_info.enabledLayerCount = static_cast<std::uint32_t>(validation_layers.size());
create_info.ppEnabledLayerNames = validation_layers.data();
RenderCore::Get().GetLayers().PopulateDebugMessengerCreateInfo(debug_create_info);
create_info.pNext = static_cast<VkDebugUtilsMessengerCreateInfoEXT*>(&debug_create_info);
}
}
VkResult res;
if((res = vkCreateInstance(&createInfo, nullptr, &_instance)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create Vulkan instance, %s", RCore::verbaliseResultVk(res));
volkLoadInstance(_instance);
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new instance");
#endif
if((res = vkCreateInstance(&create_info, nullptr, &m_instance)) != VK_SUCCESS)
FatalError("Vulkan : failed to create Vulkan instance, %", VerbaliseVkResult(res));
volkLoadInstance(m_instance);
DebugLog("Vulkan : created new instance");
}
std::vector<const char*> Instance::getRequiredExtensions()
std::vector<const char*> Instance::GetRequiredExtensions()
{
std::uint32_t glfw_extension_count = 0;
const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count);
@@ -75,12 +79,10 @@ namespace mlx
return extensions;
}
void Instance::destroy() noexcept
void Instance::Destroy() noexcept
{
vkDestroyInstance(_instance, nullptr);
_instance = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed an instance");
#endif
vkDestroyInstance(m_instance, nullptr);
m_instance = VK_NULL_HANDLE;
DebugLog("Vulkan : destroyed an instance");
}
}

View File

@@ -1,12 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* memory.cpp :+: :+: :+: */
/* Memory.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: kbz_8 <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/20 22:02:37 by kbz_8 #+# #+# */
/* Updated: 2024/03/25 19:27:44 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:49:10 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -17,7 +17,6 @@
#define VK_NO_PROTOTYPES
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
#define VMA_VULKAN_VERSION 1002000
#define VMA_ASSERT(expr) ((void)0)
#define VMA_IMPLEMENTATION
@@ -39,11 +38,8 @@
#include <vma.h>
#endif
#include <pre_compiled.h>
#include <core/errors.h>
#include <core/profiler.h>
#include <renderer/core/render_core.h>
#include <PreCompiled.h>
#include <Renderer/Core/RenderCore.h>
namespace mlx
{
@@ -67,99 +63,99 @@ namespace mlx
vma_vulkan_func.vkMapMemory = vkMapMemory;
vma_vulkan_func.vkUnmapMemory = vkUnmapMemory;
vma_vulkan_func.vkCmdCopyBuffer = vkCmdCopyBuffer;
vma_vulkan_func.vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2;
vma_vulkan_func.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2;
vma_vulkan_func.vkBindBufferMemory2KHR = vkBindBufferMemory2;
vma_vulkan_func.vkBindImageMemory2KHR = vkBindImageMemory2;
vma_vulkan_func.vkGetPhysicalDeviceMemoryProperties2KHR = vkGetPhysicalDeviceMemoryProperties2;
#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
vma_vulkan_func.vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2,
vma_vulkan_func.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2,
#endif
#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
vma_vulkan_func.vkBindBufferMemory2KHR = vkBindBufferMemory2,
vma_vulkan_func.vkBindImageMemory2KHR = vkBindImageMemory2,
#endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
vma_vulkan_func.vkGetPhysicalDeviceMemoryProperties2KHR = vkGetPhysicalDeviceMemoryProperties2,
#endif
#if VMA_VULKAN_VERSION >= 1003000
vma_vulkan_func.vkGetDeviceBufferMemoryRequirements = vkGetDeviceBufferMemoryRequirements,
vma_vulkan_func.vkGetDeviceImageMemoryRequirements = vkGetDeviceImageMemoryRequirements,
#endif
VmaAllocatorCreateInfo allocatorCreateInfo{};
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
allocatorCreateInfo.physicalDevice = Render_Core::get().getDevice().getPhysicalDevice();
allocatorCreateInfo.device = Render_Core::get().getDevice().get();
allocatorCreateInfo.instance = Render_Core::get().getInstance().get();
allocatorCreateInfo.pVulkanFunctions = &vma_vulkan_func;
VmaAllocatorCreateInfo allocator_create_info{};
allocator_create_info.vulkanApiVersion = RenderCore::Get().GetInstance().GetInstanceVersion();
allocator_create_info.physicalDevice = RenderCore::Get().GetDevice().GetPhysicalDevice();
allocator_create_info.device = RenderCore::Get().GetDevice().Get();
allocator_create_info.instance = RenderCore::Get().GetInstance().Get();
allocator_create_info.pVulkanFunctions = &vma_vulkan_func;
VkResult res = vmaCreateAllocator(&allocatorCreateInfo, &_allocator);
VkResult res = vmaCreateAllocator(&allocator_create_info, &m_allocator);
if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : failed to create graphics memory allocator, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG
core::error::report(e_kind::message, "Graphics allocator : created new allocator");
#endif
FatalError("Graphics allocator : failed to create graphics memory allocator, %", VerbaliseVkResult(res));
DebugLog("Graphics allocator : created new allocator");
}
VmaAllocation GPUallocator::createBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, const char* name) noexcept
VmaAllocation GPUallocator::CreateBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, const char* name) noexcept
{
MLX_PROFILE_FUNCTION();
VmaAllocation allocation;
VkResult res = vmaCreateBuffer(_allocator, binfo, vinfo, &buffer, &allocation, nullptr);
VkResult res = vmaCreateBuffer(m_allocator, binfo, vinfo, &buffer, &allocation, nullptr);
if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : failed to allocate a buffer, %s", RCore::verbaliseResultVk(res));
FatalError("Graphics allocator : failed to allocate a buffer, %s", RCore::verbaliseResultVk(res));
if(name != nullptr)
{
Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_BUFFER, (std::uint64_t)buffer, name);
vmaSetAllocationName(_allocator, allocation, name);
RenderCore::Get().GetLayers().SetDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_BUFFER, (std::uint64_t)buffer, name);
vmaSetAllocationName(m_allocator, allocation, name);
}
#ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : created new buffer '%s'", name);
#endif
_active_buffers_allocations++;
DebugLog("Graphics Allocator : created new buffer '%s'", name);
m_active_buffers_allocations++;
return allocation;
}
void GPUallocator::destroyBuffer(VmaAllocation allocation, VkBuffer buffer) noexcept
void GPUallocator::DestroyBuffer(VmaAllocation allocation, VkBuffer buffer) noexcept
{
MLX_PROFILE_FUNCTION();
vkDeviceWaitIdle(Render_Core::get().getDevice().get());
vmaDestroyBuffer(_allocator, buffer, allocation);
#ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : destroyed buffer");
#endif
_active_buffers_allocations--;
vkDeviceWaitIdle(RenderCore::Get().GetDevice().Get());
vmaDestroyBuffer(m_allocator, buffer, allocation);
DebugLog("Graphics Allocator : destroyed buffer");
m_active_buffers_allocations--;
}
VmaAllocation GPUallocator::createImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, const char* name) noexcept
VmaAllocation GPUallocator::CreateImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, const char* name) noexcept
{
MLX_PROFILE_FUNCTION();
VmaAllocation allocation;
VkResult res = vmaCreateImage(_allocator, iminfo, vinfo, &image, &allocation, nullptr);
VkResult res = vmaCreateImage(m_allocator, iminfo, vinfo, &image, &allocation, nullptr);
if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : failed to allocate an image, %s", RCore::verbaliseResultVk(res));
FatalError("Graphics allocator : failed to allocate an image, %", VerbaliseVkResult(res));
if(name != nullptr)
{
Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_IMAGE, (std::uint64_t)image, name);
vmaSetAllocationName(_allocator, allocation, name);
RenderCore::Get().GetLayers().SetDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_IMAGE, (std::uint64_t)image, name);
vmaSetAllocationName(m_allocator, allocation, name);
}
#ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : created new image '%s'", name);
#endif
_active_images_allocations++;
DebugLog("Graphics Allocator : created new image '%s'", name);
m_active_images_allocations++;
return allocation;
}
void GPUallocator::destroyImage(VmaAllocation allocation, VkImage image) noexcept
void GPUallocator::DestroyImage(VmaAllocation allocation, VkImage image) noexcept
{
MLX_PROFILE_FUNCTION();
vkDeviceWaitIdle(Render_Core::get().getDevice().get());
vmaDestroyImage(_allocator, image, allocation);
#ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : destroyed image");
#endif
_active_images_allocations--;
vkDeviceWaitIdle(RenderCore::Get().GetDevice().Get());
vmaDestroyImage(m_allocator, image, allocation);
DebugLog("Graphics Allocator : destroyed image");
m_active_images_allocations--;
}
void GPUallocator::mapMemory(VmaAllocation allocation, void** data) noexcept
void GPUallocator::MapMemory(VmaAllocation allocation, void** data) noexcept
{
MLX_PROFILE_FUNCTION();
VkResult res = vmaMapMemory(_allocator, allocation, data);
VkResult res = vmaMapMemory(m_allocator, allocation, data);
if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : unable to map GPU memory to CPU memory, %s", RCore::verbaliseResultVk(res));
FatalError("Graphics allocator : unable to map GPU memory to CPU memory, %", VerbaliseVkResult(res));
}
void GPUallocator::unmapMemory(VmaAllocation allocation) noexcept
{
MLX_PROFILE_FUNCTION();
vmaUnmapMemory(_allocator, allocation);
vmaUnmapMemory(m_allocator, allocation);
}
void GPUallocator::dumpMemoryToJson()
@@ -170,36 +166,34 @@ namespace mlx
std::ofstream file(name);
if(!file.is_open())
{
core::error::report(e_kind::error, "Graphics allocator : unable to dump memory to a json file");
Error("Graphics allocator : unable to dump memory to a json file");
return;
}
char* str = nullptr;
vmaBuildStatsString(_allocator, &str, true);
vmaBuildStatsString(m_allocator, &str, true);
file << str;
vmaFreeStatsString(_allocator, str);
vmaFreeStatsString(m_allocator, str);
file.close();
id++;
}
void GPUallocator::flush(VmaAllocation allocation, VkDeviceSize size, VkDeviceSize offset) noexcept
void GPUallocator::Flush(VmaAllocation allocation, VkDeviceSize size, VkDeviceSize offset) noexcept
{
MLX_PROFILE_FUNCTION();
vmaFlushAllocation(_allocator, allocation, offset, size);
vmaFlushAllocation(m_allocator, allocation, offset, size);
}
void GPUallocator::destroy() noexcept
void GPUallocator::Destroy() noexcept
{
if(_active_images_allocations != 0)
core::error::report(e_kind::error, "Graphics allocator : some user-dependant allocations were not freed before destroying the display (%d active allocations). You may have not destroyed all the MLX resources you've created", _active_images_allocations);
else if(_active_buffers_allocations != 0)
core::error::report(e_kind::error, "Graphics allocator : some MLX-dependant allocations were not freed before destroying the display (%d active allocations). This is an error in the MLX, please report this should not happen", _active_buffers_allocations);
if(_active_images_allocations < 0 || _active_buffers_allocations < 0)
core::error::report(e_kind::warning, "Graphics allocator : the impossible happened, the MLX has freed more allocations than it has made (wtf)");
vmaDestroyAllocator(_allocator);
_active_buffers_allocations = 0;
_active_images_allocations = 0;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a graphics allocator");
#endif
if(m_active_images_allocations != 0)
Error("Graphics allocator : some user-dependant allocations were not freed before destroying the display (% active allocations). You may have not destroyed all the MLX resources you've created", m_active_images_allocations);
else if(m_active_buffers_allocations != 0)
Error("Graphics allocator : some MLX-dependant allocations were not freed before destroying the display (% active allocations). This is an error in the MLX, please report this should not happen", m_active_buffers_allocations);
if(m_active_images_allocations < 0 || m_active_buffers_allocations < 0)
Warning("Graphics allocator : the impossible happened, the MLX has freed more allocations than it has made (wtf)");
vmaDestroyAllocator(m_allocator);
m_active_buffers_allocations = 0;
m_active_images_allocations = 0;
DebugLog("Vulkan : destroyed a graphics allocator");
}
}

View File

@@ -1,55 +1,53 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_queues.cpp :+: :+: :+: */
/* Queues.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:02:42 by maldavid #+# #+# */
/* Updated: 2024/03/25 22:29:19 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:51:21 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <pre_compiled.h>
#include <PreCompiled.h>
#include "render_core.h"
#include <Renderer/Core/RenderCore.h>
namespace mlx
{
Queues::QueueFamilyIndices Queues::findQueueFamilies(VkPhysicalDevice device)
{
std::uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
std::vector<VkQueueFamilyProperties> queue_families(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.data());
_families = Queues::QueueFamilyIndices{};
n_families = Queues::QueueFamilyIndices{};
int i = 0;
for(const auto& queueFamily : queueFamilies)
for(const auto& queue_family : queue_families)
{
if(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
_families->graphics_family = i;
if(queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT)
m_families->graphics_family = i;
if(glfwGetPhysicalDevicePresentationSupport(Render_Core::get().getInstance().get(), device, i))
_families->present_family = i;
if(glfwGetPhysicalDevicePresentationSupport(RenderCore::Get().GetInstance().Get(), device, i))
m_families->present_family = i;
if(_families->isComplete())
return *_families;
if(m_families->IsComplete())
return *m_families;
i++;
}
return *_families;
return *m_families;
}
void Queues::init()
void Queues::Init()
{
if(!_families.has_value())
findQueueFamilies(Render_Core::get().getDevice().getPhysicalDevice());
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->graphics_family.value(), 0, &_graphics_queue);
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->present_family.value(), 0, &_present_queue);
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : got graphics and present queues");
#endif
if(!m_families.has_value())
FindQueueFamilies(RenderCore::Get().GetDevice().GetPhysicalDevice());
vkGetDeviceQueue(RenderCore::Get().GetDevice().Get(), m_families->graphics_family.value(), 0, &m_graphics_queue);
vkGetDeviceQueue(RenderCore::Get().GetDevice().Get(), m_families->present_family.value(), 0, &m_present_queue);
DebugLog("Vulkan : got graphics and present queues");
}
}

View File

@@ -1,12 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render_core.cpp :+: :+: :+: */
/* RenderCore.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/17 23:33:34 by maldavid #+# #+# */
/* Updated: 2024/03/25 19:02:06 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:54:26 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -14,10 +14,10 @@
#define VOLK_IMPLEMENTATION
#include <volk.h>
#include <pre_compiled.h>
#include <PreCompiled.h>
#include <renderer/core/render_core.h>
#include <renderer/command/vk_cmd_buffer.h>
#include <Renderer/Core/RenderCore.h>
#include <Renderer/Command/CommandBuffer.h>
#ifdef DEBUG
#ifdef MLX_COMPILER_MSVC
@@ -29,124 +29,106 @@
namespace mlx
{
namespace RCore
const char* VerbaliseVkResult(VkResult result)
{
std::optional<std::uint32_t> findMemoryType(std::uint32_t typeFilter, VkMemoryPropertyFlags properties, bool error)
switch(result)
{
VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(Render_Core::get().getDevice().getPhysicalDevice(), &memProperties);
case VK_SUCCESS: return "Success";
case VK_NOT_READY: return "A fence or query has not yet completed";
case VK_TIMEOUT: return "A wait operation has not completed in the specified time";
case VK_EVENT_SET: return "An event is signaled";
case VK_EVENT_RESET: return "An event is unsignaled";
case VK_INCOMPLETE: return "A return array was too small for the result";
case VK_ERROR_OUT_OF_HOST_MEMORY: return "A host memory allocation has failed";
case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "A device memory allocation has failed";
case VK_ERROR_INITIALIZATION_FAILED: return "Initialization of an object could not be completed for implementation-specific reasons";
case VK_ERROR_DEVICE_LOST: return "The logical or physical device has been lost";
case VK_ERROR_MEMORY_MAP_FAILED: return "Mapping of a memory object has failed";
case VK_ERROR_LAYER_NOT_PRESENT: return "A requested layer is not present or could not be loaded";
case VK_ERROR_EXTENSION_NOT_PRESENT: return "A requested extension is not supported";
case VK_ERROR_FEATURE_NOT_PRESENT: return "A requested feature is not supported";
case VK_ERROR_INCOMPATIBLE_DRIVER: return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
case VK_ERROR_TOO_MANY_OBJECTS: return "Too many objects of the type have already been created";
case VK_ERROR_FORMAT_NOT_SUPPORTED: return "A requested format is not supported on this device";
case VK_ERROR_SURFACE_LOST_KHR: return "A surface is no longer available";
case VK_SUBOPTIMAL_KHR: return "A swapchain no longer matches the surface properties exactly, but can still be used";
case VK_ERROR_OUT_OF_DATE_KHR: return "A surface has changed in such a way that it is no longer compatible with the swapchain";
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "The display used by a swapchain does not use the same presentable image layout";
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
case VK_ERROR_VALIDATION_FAILED_EXT: return "A validation layer found an error";
for(std::uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
{
if((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
return i;
}
if(error)
core::error::report(e_kind::fatal_error, "Vulkan : failed to find suitable memory type");
return std::nullopt;
}
const char* verbaliseResultVk(VkResult result)
{
switch(result)
{
case VK_SUCCESS: return "Success";
case VK_NOT_READY: return "A fence or query has not yet completed";
case VK_TIMEOUT: return "A wait operation has not completed in the specified time";
case VK_EVENT_SET: return "An event is signaled";
case VK_EVENT_RESET: return "An event is unsignaled";
case VK_INCOMPLETE: return "A return array was too small for the result";
case VK_ERROR_OUT_OF_HOST_MEMORY: return "A host memory allocation has failed";
case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "A device memory allocation has failed";
case VK_ERROR_INITIALIZATION_FAILED: return "Initialization of an object could not be completed for implementation-specific reasons";
case VK_ERROR_DEVICE_LOST: return "The logical or physical device has been lost";
case VK_ERROR_MEMORY_MAP_FAILED: return "Mapping of a memory object has failed";
case VK_ERROR_LAYER_NOT_PRESENT: return "A requested layer is not present or could not be loaded";
case VK_ERROR_EXTENSION_NOT_PRESENT: return "A requested extension is not supported";
case VK_ERROR_FEATURE_NOT_PRESENT: return "A requested feature is not supported";
case VK_ERROR_INCOMPATIBLE_DRIVER: return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
case VK_ERROR_TOO_MANY_OBJECTS: return "Too many objects of the type have already been created";
case VK_ERROR_FORMAT_NOT_SUPPORTED: return "A requested format is not supported on this device";
case VK_ERROR_SURFACE_LOST_KHR: return "A surface is no longer available";
case VK_SUBOPTIMAL_KHR: return "A swapchain no longer matches the surface properties exactly, but can still be used";
case VK_ERROR_OUT_OF_DATE_KHR: return "A surface has changed in such a way that it is no longer compatible with the swapchain";
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "The display used by a swapchain does not use the same presentable image layout";
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
case VK_ERROR_VALIDATION_FAILED_EXT: return "A validation layer found an error";
default: return "Unknown Vulkan error";
}
return nullptr;
}
VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags)
{
VkPipelineStageFlags stages = 0;
while(accessFlags != 0)
{
VkAccessFlagBits AccessFlag = static_cast<VkAccessFlagBits>(accessFlags & (~(accessFlags - 1)));
if(AccessFlag == 0 || (AccessFlag & (AccessFlag - 1)) != 0)
core::error::report(e_kind::fatal_error, "Vulkan : an error has been caught during access flag to pipeline stage operation");
accessFlags &= ~AccessFlag;
switch(AccessFlag)
{
case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; break;
case VK_ACCESS_INDEX_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_UNIFORM_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break;
case VK_ACCESS_SHADER_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_SHADER_WRITE_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_TRANSFER_READ_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_TRANSFER_WRITE_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_HOST_READ_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_HOST_WRITE_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_MEMORY_READ_BIT: break;
case VK_ACCESS_MEMORY_WRITE_BIT: break;
default: core::error::report(e_kind::error, "Vulkan : unknown access flag"); break;
}
}
return stages;
default: return "Unknown Vulkan error";
}
return nullptr;
}
void Render_Core::init()
VkPipelineStageFlags AccessFlagsToPipelineStage(VkAccessFlags access_flags, VkPipelineStageFlags stage_flags)
{
VkPipelineStageFlags stages = 0;
while(access_flags != 0)
{
VkAccessFlagBits Access_flag = static_cast<VkAccessFlagBits>(access_flags & (~(access_flags - 1)));
if(Access_flag == 0 || (Access_flag & (Access_flag - 1)) != 0)
FatalError("Vulkan : an error has been caught during access flag to pipeline stage operation");
access_flags &= ~Access_flag;
switch(Access_flag)
{
case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; break;
case VK_ACCESS_INDEX_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_UNIFORM_READ_BIT: stages |= stage_flags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break;
case VK_ACCESS_SHADER_READ_BIT: stages |= stage_flags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_SHADER_WRITE_BIT: stages |= stage_flags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_TRANSFER_READ_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_TRANSFER_WRITE_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_HOST_READ_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_HOST_WRITE_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_MEMORY_READ_BIT: break;
case VK_ACCESS_MEMORY_WRITE_BIT: break;
default: Error("Vulkan : unknown access flag"); break;
}
}
return stages;
}
void RenderCore::Init()
{
if(volkInitialize() != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan loader : cannot load %s, are you sure Vulkan is installed on your system ?", VULKAN_LIB_NAME);
FatalError("Vulkan loader : cannot load %, are you sure Vulkan is installed on your system ?", VULKAN_LIB_NAME);
_instance.init();
volkLoadInstance(_instance.get());
_layers.init();
_device.init();
volkLoadDevice(_device.get());
_queues.init();
_allocator.init();
_cmd_manager.init();
_is_init = true;
m_instance.Init();
volkLoadInstance(m_instance.Get());
m_layers.Init();
m_device.Init();
volkLoadDevice(m_device.Get());
m_queues.Init();
m_allocator.Init();
m_cmd_manager.Init();
m_is_init = true;
}
void Render_Core::destroy()
void RenderCore::Destroy()
{
if(!_is_init)
if(!m_is_init)
return;
vkDeviceWaitIdle(_device());
vkDeviceWaitIdle(m_device.Get());
_pool_manager.destroyAllPools();
_cmd_manager.destroy();
_allocator.destroy();
_device.destroy();
_layers.destroy();
_instance.destroy();
m_pool_manager.DestroyAllPools();
m_cmd_manager.Destroy();
m_allocator.Destroy();
m_device.Destroy();
m_layers.Destroy();
m_instance.Destroy();
_is_init = false;
m_is_init = false;
}
}

View File

@@ -1,45 +1,36 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_semaphore.cpp :+: :+: :+: */
/* Semaphore.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:01:08 by maldavid #+# #+# */
/* Updated: 2024/03/25 19:02:25 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:55:42 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <pre_compiled.h>
#include "vk_semaphore.h"
#include "render_core.h"
#include <renderer/renderer.h>
#include <PreCompiled.h>
#include <Renderer/Core/RenderCore.h>
#include <Renderer/Core/Semaphore.h>
namespace mlx
{
void Semaphore::init()
void Semaphore::Init()
{
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkSemaphoreCreateInfo semaphore_info{};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkResult res;
if( (res = vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_image_available_semaphore)) != VK_SUCCESS ||
(res = vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_render_finished_semaphore)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a synchronization object (semaphore), %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new semaphores");
#endif
if((res = vkCreateSemaphore(RenderCore::Get().GetDevice().Get(), &semaphore_info, nullptr, &m_semaphore)) != VK_SUCCESS)
FatalError("Vulkan : failed to create a synchronization object (semaphore), %", VerbaliseVkResult(res));
DebugLog("Vulkan : created new semaphores");
}
void Semaphore::destroy() noexcept
void Semaphore::Destroy() noexcept
{
vkDestroySemaphore(Render_Core::get().getDevice().get(), _render_finished_semaphore, nullptr);
_render_finished_semaphore = VK_NULL_HANDLE;
vkDestroySemaphore(Render_Core::get().getDevice().get(), _image_available_semaphore, nullptr);
_image_available_semaphore = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed semaphores");
#endif
vkDestroySemaphore(RenderCore::Get().GetDevice().Get(), m_semaphore, nullptr);
m_semaphore = VK_NULL_HANDLE;
DebugLog("Vulkan : destroyed semaphore");
}
}

View File

@@ -1,12 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_surface.cpp :+: :+: :+: */
/* Surface.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:58:49 by maldavid #+# #+# */
/* Updated: 2024/03/25 22:25:55 by maldavid ### ########.fr */
/* Updated: 2024/04/23 18:56:56 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -17,31 +17,27 @@
namespace mlx
{
void Surface::create(Renderer& renderer)
void Surface::Create(Renderer& renderer)
{
if(glfwCreateWindowSurface(Render_Core::get().getInstance().get(), renderer.getWindow()->getNativeWindow(), NULL, &_surface) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a surface");
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new surface");
#endif
if(glfwCreateWindowSurface(RenderCore::Get().GetInstance().Get(), renderer.GetWindow()->GetNativeWindow(), NULL, &m_surface) != VK_SUCCESS)
FatalError("Vulkan : failed to create a surface");
DebugLog("Vulkan : created new surface");
}
VkSurfaceFormatKHR Surface::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
VkSurfaceFormatKHR Surface::ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& available_formats)
{
auto it = std::find_if(availableFormats.begin(), availableFormats.end(), [](VkSurfaceFormatKHR format)
auto it = std::find_if(available_formats.begin(), available_formats.end(), [](VkSurfaceFormatKHR format)
{
return format.format == VK_FORMAT_R8G8B8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
});
return (it == availableFormats.end() ? availableFormats[0] : *it);
return (it == available_formats.end() ? available_formats[0] : *it);
}
void Surface::destroy() noexcept
void Surface::Destroy() noexcept
{
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), _surface, nullptr);
_surface = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a surface");
#endif
vkDestroySurfaceKHR(RenderCore::Get().GetInstance().Get(), m_surface, nullptr);
m_surface = VK_NULL_HANDLE;
DebugLog("Vulkan : destroyed a surface");
}
}

View File

@@ -1,79 +1,72 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_validation_layers.cpp :+: :+: :+: */
/* ValidationLayers.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/19 14:05:25 by maldavid #+# #+# */
/* Updated: 2024/03/25 19:00:06 by maldavid ### ########.fr */
/* Updated: 2024/04/23 19:20:21 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <pre_compiled.h>
#include "render_core.h"
#include "vulkan/vulkan_core.h"
#include <core/errors.h>
#include <PreCompiled.h>
#include <Renderer/Core/RenderCore.h>
namespace mlx
{
void ValidationLayers::init()
void ValidationLayers::Init()
{
if constexpr(!enableValidationLayers)
if constexpr(!enable_validation_layers)
return;
std::uint32_t extensionCount;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> extensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
std::uint32_t extension_count;
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr);
std::vector<VkExtensionProperties> extensions(extension_count);
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data());
if(!std::any_of(extensions.begin(), extensions.end(), [=](VkExtensionProperties ext) { return std::strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; }))
{
core::error::report(e_kind::warning , "Vulkan : %s not present, debug utils are disabled", VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
Warning("Vulkan : %s not present, debug utils are disabled", VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
return;
}
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
populateDebugMessengerCreateInfo(createInfo);
VkResult res = createDebugUtilsMessengerEXT(&createInfo, nullptr);
VkDebugUtilsMessengerCreateInfoEXT create_info{};
populateDebugMessengerCreateInfo(create_info);
VkResult res = createDebugUtilsMessengerEXT(&create_info, nullptr);
if(res != VK_SUCCESS)
core::error::report(e_kind::warning, "Vulkan : failed to set up debug messenger, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG
Warning("Vulkan : failed to set up debug messenger, %", VerbaliseVkResult(res));
else
core::error::report(e_kind::message, "Vulkan : enabled validation layers");
#endif
DebugLog("Vulkan : enabled validation layers");
_vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkSetDebugUtilsObjectNameEXT");
if(!_vkSetDebugUtilsObjectNameEXT)
core::error::report(e_kind::warning, "Vulkan : failed to set up debug object names, %s", RCore::verbaliseResultVk(VK_ERROR_EXTENSION_NOT_PRESENT));
#ifdef DEBUG
f_vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(RenderCore::Get().GetInstance().Get(), "vkSetDebugUtilsObjectNameEXT");
if(!f_vkSetDebugUtilsObjectNameEXT)
Warning("Vulkan : failed to set up debug object names, %", VerbaliseVkResult(VK_ERROR_EXTENSION_NOT_PRESENT));
else
core::error::report(e_kind::message, "Vulkan : enabled debug object names");
#endif
DebugLog("Vulkan : enabled debug object names");
}
bool ValidationLayers::checkValidationLayerSupport()
bool ValidationLayers::CheckValidationLayerSupport()
{
std::uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::uint32_t layer_count;
vkEnumerateInstanceLayerProperties(&layer_count, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
std::vector<VkLayerProperties> available_layers(layer_count);
vkEnumerateInstanceLayerProperties(&layer_count, available_layers.data());
return std::all_of(validationLayers.begin(), validationLayers.end(), [&](const char* layerName)
return std::all_of(validation_layers.begin(), validation_layers.end(), [&](const char* layer_name)
{
if(!std::any_of(availableLayers.begin(), availableLayers.end(), [=](VkLayerProperties props) { return std::strcmp(layerName, props.layerName) == 0; }))
if(!std::any_of(available_layers.begin(), available_layers.end(), [=](VkLayerProperties props) { return std::strcmp(layer_name, props.layer_name) == 0; }))
{
core::error::report(e_kind::error, "Vulkan : a validation layer was requested but was not found ('%s')", layerName);
Error("Vulkan : a validation layer was requested but was not found ('%')", layer_name);
return false;
}
return true;
});
}
VkResult ValidationLayers::setDebugUtilsObjectNameEXT(VkObjectType object_type, std::uint64_t object_handle, const char* object_name)
VkResult ValidationLayers::SetDebugUtilsObjectNameEXT(VkObjectType object_type, std::uint64_t object_handle, const char* object_name)
{
if(!_vkSetDebugUtilsObjectNameEXT)
if(!f_vkSetDebugUtilsObjectNameEXT)
return VK_ERROR_EXTENSION_NOT_PRESENT;
VkDebugUtilsObjectNameInfoEXT name_info{};
@@ -81,49 +74,49 @@ namespace mlx
name_info.objectType = object_type;
name_info.objectHandle = object_handle;
name_info.pObjectName = object_name;
return _vkSetDebugUtilsObjectNameEXT(Render_Core::get().getDevice().get(), &name_info);
return f_vkSetDebugUtilsObjectNameEXT(RenderCore::Get().GetDevice().Get(), &name_info);
}
void ValidationLayers::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo)
void ValidationLayers::PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& create_info)
{
createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.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;
createInfo.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;
createInfo.pfnUserCallback = ValidationLayers::debugCallback;
create_info = {};
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 = ValidationLayers::DebugCallback;
}
void ValidationLayers::destroy()
void ValidationLayers::Destroy()
{
if constexpr(enableValidationLayers)
if constexpr(enable_validation_layers)
{
destroyDebugUtilsMessengerEXT(nullptr);
DestroyDebugUtilsMessengerEXT(nullptr);
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed validation layers");
DebugLog("Vulkan : destroyed validation layers");
#endif
}
}
VkResult ValidationLayers::createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator)
VkResult ValidationLayers::CreateDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator)
{
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkCreateDebugUtilsMessengerEXT");
return func != nullptr ? func(Render_Core::get().getInstance().get(), pCreateInfo, pAllocator, &_debug_messenger) : VK_ERROR_EXTENSION_NOT_PRESENT;
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(RenderCore::Get().GetInstance().Get(), "vkCreateDebugUtilsMessengerEXT");
return func != nullptr ? func(RenderCore::Get().GetInstance().Get(), pCreateInfo, pAllocator, &m_debug_messenger) : VK_ERROR_EXTENSION_NOT_PRESENT;
}
VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayers::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, [[maybe_unused]] void* pUserData)
VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayers::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, [[maybe_unused]] void* pUserData)
{
if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
core::error::report(e_kind::error, pCallbackData->pMessage);
Error(pCallbackData->pMessage);
else if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
core::error::report(e_kind::warning, pCallbackData->pMessage);
Warning(pCallbackData->pMessage);
return VK_FALSE;
}
void ValidationLayers::destroyDebugUtilsMessengerEXT(const VkAllocationCallbacks* pAllocator)
{
auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkDestroyDebugUtilsMessengerEXT");
auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(RenderCore::Get().GetInstance().Get(), "vkDestroyDebugUtilsMessengerEXT");
if(func != nullptr)
func(Render_Core::get().getInstance().get(), _debug_messenger, pAllocator);
func(RenderCore::Get().GetInstance().Get(), m_debug_messenger, pAllocator);
}
}