mirror of
https://github.com/seekrs/MacroLibX.git
synced 2026-01-12 07:03:34 +00:00
fixing compatibility, workign on renderer
This commit is contained in:
206
src/renderer/core/render_core.cpp
git.filemode.normal_file
206
src/renderer/core/render_core.cpp
git.filemode.normal_file
@@ -0,0 +1,206 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* render_core.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/12/17 23:33:34 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 01:25:02 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#define VOLK_IMPLEMENTATION
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
#define VK_USE_PLATFORM_MACOS_MVK
|
||||
#else
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#endif
|
||||
|
||||
#include "render_core.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
namespace RCore
|
||||
{
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
void checkVk(VkResult result)
|
||||
{
|
||||
if(result != 0)
|
||||
core::error::report(result < 0 ? e_kind::fatal_error : e_kind::error, "Vulkan error : %s", verbaliseResultVk(result));
|
||||
}
|
||||
}
|
||||
|
||||
Render_Core::Render_Core() : _device(), _queues(), _surface(),
|
||||
_cmd_pool(), _swapchain(), _instance()
|
||||
{}
|
||||
|
||||
void Render_Core::init()
|
||||
{
|
||||
_instance.init();
|
||||
_surface.create();
|
||||
_device.init();
|
||||
_queues.init();
|
||||
_swapchain.init();
|
||||
_pass.init();
|
||||
_swapchain.initFB();
|
||||
_cmd_pool.init();
|
||||
|
||||
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
_cmd_buffers[i].init();
|
||||
|
||||
_semaphore.init();
|
||||
|
||||
_framebufferResized = false;
|
||||
_is_init = true;
|
||||
}
|
||||
|
||||
bool Render_Core::beginFrame()
|
||||
{
|
||||
if(!_is_init)
|
||||
return false;
|
||||
|
||||
vkWaitForFences(_device(), 1, &_semaphore.getInFlightFence(_active_image_index), VK_TRUE, UINT64_MAX);
|
||||
|
||||
_image_index = 0;
|
||||
VkResult result = vkAcquireNextImageKHR(_device(), _swapchain(), UINT64_MAX, _semaphore.getImageSemaphore(_active_image_index), VK_NULL_HANDLE, &_image_index);
|
||||
|
||||
if(result == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
_swapchain.recreate();
|
||||
return false;
|
||||
}
|
||||
else if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan error : failed to acquire swapchain image");
|
||||
|
||||
vkResetFences(_device(), 1, &_semaphore.getInFlightFence(_active_image_index));
|
||||
|
||||
vkResetCommandBuffer(_cmd_buffers[_active_image_index].get(), 0);
|
||||
|
||||
_cmd_buffers[_active_image_index].beginRecord();
|
||||
_pass.begin();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Render_Core::endFrame()
|
||||
{
|
||||
if(!_is_init)
|
||||
return;
|
||||
_pass.end();
|
||||
_cmd_buffers[_active_image_index].endRecord();
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
VkSemaphore waitSemaphores[] = { _semaphore.getImageSemaphore(_active_image_index) };
|
||||
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||
submitInfo.pWaitDstStageMask = waitStages;
|
||||
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &_cmd_buffers[_active_image_index].get();
|
||||
|
||||
VkSemaphore signalSemaphores[] = { _semaphore.getRenderImageSemaphore(_active_image_index) };
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||
|
||||
if(vkQueueSubmit(_queues.getGraphic(), 1, &submitInfo, _semaphore.getInFlightFence(_active_image_index)) != VK_SUCCESS)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit draw command buffer");
|
||||
|
||||
VkPresentInfoKHR presentInfo{};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
|
||||
presentInfo.waitSemaphoreCount = 1;
|
||||
presentInfo.pWaitSemaphores = signalSemaphores;
|
||||
|
||||
presentInfo.swapchainCount = 1;
|
||||
presentInfo.pSwapchains = &_swapchain();
|
||||
|
||||
presentInfo.pImageIndices = &_image_index;
|
||||
|
||||
VkResult result = vkQueuePresentKHR(_queues.getPresent(), &presentInfo);
|
||||
|
||||
if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || _framebufferResized)
|
||||
{
|
||||
_framebufferResized = false;
|
||||
_swapchain.recreate();
|
||||
}
|
||||
else if(result != VK_SUCCESS)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan error : failed to present swap chain image");
|
||||
|
||||
_active_image_index = (_active_image_index + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
void Render_Core::destroyCommandBuffers()
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::unique_lock<std::mutex> watchdog(mutex, std::try_to_lock);
|
||||
|
||||
if(!_is_init)
|
||||
return;
|
||||
|
||||
vkDeviceWaitIdle(_device());
|
||||
|
||||
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
_cmd_buffers[i].destroy();
|
||||
}
|
||||
|
||||
void Render_Core::destroy()
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::unique_lock<std::mutex> watchdog(mutex, std::try_to_lock);
|
||||
|
||||
if(!_is_init)
|
||||
return;
|
||||
|
||||
vkDeviceWaitIdle(_device());
|
||||
|
||||
_swapchain.destroyFB();
|
||||
_pass.destroy();
|
||||
_swapchain.destroy();
|
||||
_semaphore.destroy();
|
||||
_cmd_pool.destroy();
|
||||
_device.destroy();
|
||||
_surface.destroy();
|
||||
_instance.destroy();
|
||||
|
||||
_is_init = false;
|
||||
}
|
||||
}
|
||||
95
src/renderer/core/render_core.h
git.filemode.normal_file
95
src/renderer/core/render_core.h
git.filemode.normal_file
@@ -0,0 +1,95 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* render_core.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:16:32 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 03:42:51 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef __MLX_RENDER_CORE__
|
||||
#define __MLX_RENDER_CORE__
|
||||
|
||||
#include <volk.h>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
#include "vk_queues.h"
|
||||
#include "vk_device.h"
|
||||
#include "vk_surface.h"
|
||||
#include "vk_instance.h"
|
||||
#include "vk_semaphore.h"
|
||||
|
||||
#include <renderer/command/vk_cmd_pool.h>
|
||||
#include <renderer/command/vk_cmd_buffer.h>
|
||||
#include <renderer/swapchain/vk_swapchain.h>
|
||||
#include <renderer/swapchain/vk_render_pass.h>
|
||||
|
||||
#include <utils/singleton.h>
|
||||
#include <core/errors.h>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
namespace RCore
|
||||
{
|
||||
void checkVk(VkResult result);
|
||||
}
|
||||
|
||||
constexpr const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
class Render_Core : public Singleton<Render_Core>
|
||||
{
|
||||
public:
|
||||
Render_Core();
|
||||
|
||||
void init();
|
||||
|
||||
void destroyCommandBuffers();
|
||||
void destroy();
|
||||
|
||||
bool beginFrame();
|
||||
void endFrame();
|
||||
|
||||
inline std::shared_ptr<class MLX_Window> getWindow() { return _window; }
|
||||
inline void setWindow(std::shared_ptr<class MLX_Window> window) { _window = window; }
|
||||
|
||||
inline Instance& getInstance() { return _instance; }
|
||||
inline Device& getDevice() { return _device; }
|
||||
inline Surface& getSurface() { return _surface; }
|
||||
inline Queues& getQueue() { return _queues; }
|
||||
inline CmdPool& getCmdPool() { return _cmd_pool; }
|
||||
inline SwapChain& getSwapChain() { return _swapchain; }
|
||||
inline Semaphore& getSemaphore() { return _semaphore; }
|
||||
inline RenderPass& getRenderPass() { return _pass; }
|
||||
inline CmdBuffer& getCmdBuffer(int i) { return _cmd_buffers[i]; }
|
||||
inline CmdBuffer& getActiveCmdBuffer() { return _cmd_buffers[_active_image_index]; }
|
||||
inline uint32_t getActiveImageIndex() { return _active_image_index; }
|
||||
inline uint32_t getImageIndex() { return _image_index; }
|
||||
|
||||
constexpr inline void requireFrameBufferResize(int index) noexcept { _framebufferResized = true; }
|
||||
|
||||
private:
|
||||
Device _device;
|
||||
Queues _queues;
|
||||
Surface _surface;
|
||||
RenderPass _pass;
|
||||
CmdPool _cmd_pool;
|
||||
Instance _instance;
|
||||
SwapChain _swapchain;
|
||||
Semaphore _semaphore;
|
||||
std::array<CmdBuffer, MAX_FRAMES_IN_FLIGHT> _cmd_buffers;
|
||||
|
||||
std::shared_ptr<class MLX_Window> _window;
|
||||
|
||||
bool _framebufferResized = false;
|
||||
|
||||
uint32_t _active_image_index = 0;
|
||||
uint32_t _image_index = 0;
|
||||
bool _is_init = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __MLX_RENDER_CORE__
|
||||
117
src/renderer/core/vk_device.cpp
git.filemode.normal_file
117
src/renderer/core/vk_device.cpp
git.filemode.normal_file
@@ -0,0 +1,117 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_device.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:14:29 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 01:10:42 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "render_core.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
const std::vector<const char*> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
|
||||
|
||||
void Device::init()
|
||||
{
|
||||
pickPhysicalDevice();
|
||||
|
||||
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(_physicalDevice);
|
||||
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
|
||||
|
||||
float queuePriority = 1.0f;
|
||||
for(uint32_t queueFamily : uniqueQueueFamilies)
|
||||
{
|
||||
VkDeviceQueueCreateInfo queueCreateInfo{};
|
||||
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queueCreateInfo.queueFamilyIndex = queueFamily;
|
||||
queueCreateInfo.queueCount = 1;
|
||||
queueCreateInfo.pQueuePriorities = &queuePriority;
|
||||
queueCreateInfos.push_back(queueCreateInfo);
|
||||
}
|
||||
|
||||
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||
|
||||
VkDeviceCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
|
||||
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
|
||||
createInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||
|
||||
createInfo.pEnabledFeatures = &deviceFeatures;
|
||||
|
||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
||||
createInfo.enabledLayerCount = 0;
|
||||
|
||||
if(vkCreateDevice(_physicalDevice, &createInfo, nullptr, &_device) != VK_SUCCESS)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan : failed to create logcal device");
|
||||
}
|
||||
|
||||
void Device::pickPhysicalDevice()
|
||||
{
|
||||
uint32_t deviceCount = 0;
|
||||
vkEnumeratePhysicalDevices(Render_Core::get().getInstance().get(), &deviceCount, nullptr);
|
||||
|
||||
if(deviceCount == 0)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan : failed to find GPUs with Vulkan support");
|
||||
|
||||
std::vector<VkPhysicalDevice> devices(deviceCount);
|
||||
vkEnumeratePhysicalDevices(Render_Core::get().getInstance().get(), &deviceCount, devices.data());
|
||||
|
||||
for(const auto& device : devices)
|
||||
{
|
||||
if(isDeviceSuitable(device))
|
||||
{
|
||||
_physicalDevice = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(_physicalDevice == VK_NULL_HANDLE)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan : failed to find a suitable GPU");
|
||||
}
|
||||
bool Device::isDeviceSuitable(VkPhysicalDevice device)
|
||||
{
|
||||
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(device);
|
||||
|
||||
bool extensionsSupported = checkDeviceExtensionSupport(device);
|
||||
|
||||
bool swapChainAdequate = false;
|
||||
if(extensionsSupported)
|
||||
{
|
||||
SwapChain::SwapChainSupportDetails swapChainSupport = Render_Core::get().getSwapChain().querySwapChainSupport(device);
|
||||
swapChainAdequate = !swapChainSupport.formats.empty();
|
||||
}
|
||||
|
||||
return indices.isComplete() && extensionsSupported && swapChainAdequate;
|
||||
}
|
||||
bool Device::checkDeviceExtensionSupport(VkPhysicalDevice device)
|
||||
{
|
||||
uint32_t extensionCount;
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
|
||||
|
||||
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
|
||||
|
||||
std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
|
||||
|
||||
for(const auto& extension : availableExtensions)
|
||||
requiredExtensions.erase(extension.extensionName);
|
||||
|
||||
return requiredExtensions.empty();
|
||||
}
|
||||
|
||||
void Device::destroy() noexcept
|
||||
{
|
||||
vkDestroyDevice(_device, nullptr);
|
||||
}
|
||||
}
|
||||
41
src/renderer/core/vk_device.h
git.filemode.normal_file
41
src/renderer/core/vk_device.h
git.filemode.normal_file
@@ -0,0 +1,41 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_device.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:13:42 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 01:08:11 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef __MLX_VK_DEVICE__
|
||||
#define __MLX_VK_DEVICE__
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy() noexcept;
|
||||
|
||||
inline VkDevice& operator()() noexcept { return _device; }
|
||||
inline VkDevice& get() noexcept { return _device; }
|
||||
|
||||
inline VkPhysicalDevice& getPhysicalDevice() noexcept { return _physicalDevice; }
|
||||
|
||||
private:
|
||||
void pickPhysicalDevice();
|
||||
bool isDeviceSuitable(VkPhysicalDevice device);
|
||||
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
|
||||
|
||||
VkPhysicalDevice _physicalDevice = VK_NULL_HANDLE;
|
||||
VkDevice _device = VK_NULL_HANDLE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __MLX_VK_DEVICE__
|
||||
68
src/renderer/core/vk_instance.cpp
git.filemode.normal_file
68
src/renderer/core/vk_instance.cpp
git.filemode.normal_file
@@ -0,0 +1,68 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_instance.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:04:21 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 00:34:58 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "vk_instance.h"
|
||||
#include "render_core.h"
|
||||
#include <platform/window.h>
|
||||
#include <SDL2/SDL_vulkan.h>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
namespace RCore { const char* verbaliseResultVk(VkResult result); }
|
||||
|
||||
void Instance::init()
|
||||
{
|
||||
VkApplicationInfo appInfo{};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "MicroLibX";
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||
appInfo.pEngineName = "MicroLibX";
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_2;
|
||||
|
||||
VkInstanceCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
|
||||
auto extensions = getRequiredExtensions();
|
||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
||||
createInfo.ppEnabledExtensionNames = extensions.data();
|
||||
|
||||
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
|
||||
createInfo.enabledLayerCount = 0;
|
||||
createInfo.pNext = nullptr;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
std::vector<const char*> Instance::getRequiredExtensions()
|
||||
{
|
||||
unsigned int count = 0;
|
||||
if(!SDL_Vulkan_GetInstanceExtensions(Render_Core::get().getWindow()->getNativeWindow(), &count, nullptr))
|
||||
core::error::report(e_kind::fatal_error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError());
|
||||
|
||||
std::vector<const char*> extensions = { VK_EXT_DEBUG_REPORT_EXTENSION_NAME };
|
||||
size_t additional_extension_count = extensions.size();
|
||||
extensions.resize(additional_extension_count + count);
|
||||
|
||||
if(!SDL_Vulkan_GetInstanceExtensions(Render_Core::get().getWindow()->getNativeWindow(), &count, extensions.data() + additional_extension_count))
|
||||
core::error::report(e_kind::error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError());
|
||||
return extensions;
|
||||
}
|
||||
|
||||
void Instance::destroy() noexcept
|
||||
{
|
||||
vkDestroyInstance(_instance, nullptr);
|
||||
}
|
||||
}
|
||||
37
src/renderer/core/vk_instance.h
git.filemode.normal_file
37
src/renderer/core/vk_instance.h
git.filemode.normal_file
@@ -0,0 +1,37 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_instance.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:03:04 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 01:08:07 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef __MLX_VK_INSTANCE__
|
||||
#define __MLX_VK_INSTANCE__
|
||||
|
||||
#include <volk.h>
|
||||
#include <vector>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
class Instance
|
||||
{
|
||||
public:
|
||||
|
||||
void init();
|
||||
void destroy() noexcept;
|
||||
|
||||
inline VkInstance& operator()() noexcept { return _instance; }
|
||||
inline VkInstance& get() noexcept { return _instance; }
|
||||
|
||||
private:
|
||||
std::vector<const char*> getRequiredExtensions();
|
||||
VkInstance _instance = VK_NULL_HANDLE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __MLX_VK_INSTANCE__
|
||||
53
src/renderer/core/vk_queues.cpp
git.filemode.normal_file
53
src/renderer/core/vk_queues.cpp
git.filemode.normal_file
@@ -0,0 +1,53 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_queues.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:02:42 by maldavid #+# #+# */
|
||||
/* Updated: 2022/10/08 19:02:52 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "render_core.h"
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
Queues::QueueFamilyIndices Queues::findQueueFamilies(VkPhysicalDevice device)
|
||||
{
|
||||
uint32_t queueFamilyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
|
||||
|
||||
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
||||
|
||||
_families = Queues::QueueFamilyIndices{};
|
||||
|
||||
int i = 0;
|
||||
for(const auto& queueFamily : queueFamilies)
|
||||
{
|
||||
if(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
_families->graphicsFamily = i;
|
||||
|
||||
VkBool32 presentSupport = false;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, Render_Core::get().getSurface().get(), &presentSupport);
|
||||
|
||||
if(presentSupport)
|
||||
_families->presentFamily = i;
|
||||
|
||||
if(_families->isComplete())
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return *_families;
|
||||
}
|
||||
|
||||
void Queues::init()
|
||||
{
|
||||
if(!_families.has_value())
|
||||
findQueueFamilies(Render_Core::get().getDevice().getPhysicalDevice());
|
||||
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->graphicsFamily.value(), 0, &_graphicsQueue);
|
||||
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->presentFamily.value(), 0, &_presentQueue);
|
||||
}
|
||||
}
|
||||
48
src/renderer/core/vk_queues.h
git.filemode.normal_file
48
src/renderer/core/vk_queues.h
git.filemode.normal_file
@@ -0,0 +1,48 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_queues.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:01:49 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 01:08:04 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef __MLX_VK_QUEUES__
|
||||
#define __MLX_VK_QUEUES__
|
||||
|
||||
#include <volk.h>
|
||||
#include <optional>
|
||||
#include <cstdint>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
class Queues
|
||||
{
|
||||
public:
|
||||
struct QueueFamilyIndices
|
||||
{
|
||||
std::optional<uint32_t> graphicsFamily;
|
||||
std::optional<uint32_t> presentFamily;
|
||||
|
||||
inline bool isComplete() { return graphicsFamily.has_value() && presentFamily.has_value(); }
|
||||
};
|
||||
|
||||
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
|
||||
|
||||
void init();
|
||||
|
||||
inline VkQueue& getGraphic() noexcept { return _graphicsQueue; }
|
||||
inline VkQueue& getPresent() noexcept { return _presentQueue; }
|
||||
inline QueueFamilyIndices getFamilies() noexcept { return *_families; }
|
||||
|
||||
private:
|
||||
VkQueue _graphicsQueue;
|
||||
VkQueue _presentQueue;
|
||||
std::optional<QueueFamilyIndices> _families;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __MLX_VK_QUEUES__
|
||||
50
src/renderer/core/vk_semaphore.cpp
git.filemode.normal_file
50
src/renderer/core/vk_semaphore.cpp
git.filemode.normal_file
@@ -0,0 +1,50 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_semaphore.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 19:01:08 by maldavid #+# #+# */
|
||||
/* Updated: 2022/10/08 19:01:44 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "vk_semaphore.h"
|
||||
#include "render_core.h"
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
void Semaphore::init()
|
||||
{
|
||||
_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
_imagesInFlight.resize(Render_Core::get().getSwapChain().getImagesNumber(), VK_NULL_HANDLE);
|
||||
|
||||
VkSemaphoreCreateInfo semaphoreInfo{};
|
||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
||||
VkFenceCreateInfo fenceInfo{};
|
||||
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||
|
||||
for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
if(vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_imageAvailableSemaphores[i]) != VK_SUCCESS ||
|
||||
vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_renderFinishedSemaphores[i]) != VK_SUCCESS ||
|
||||
vkCreateFence(Render_Core::get().getDevice().get(), &fenceInfo, nullptr, &_inFlightFences[i]) != VK_SUCCESS)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan : failed to create synchronization objects for a frame");
|
||||
}
|
||||
}
|
||||
|
||||
void Semaphore::destroy() noexcept
|
||||
{
|
||||
for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
vkDestroySemaphore(Render_Core::get().getDevice().get(), _renderFinishedSemaphores[i], nullptr);
|
||||
vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores[i], nullptr);
|
||||
vkDestroyFence(Render_Core::get().getDevice().get(), _inFlightFences[i], nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/renderer/core/vk_semaphore.h
git.filemode.normal_file
40
src/renderer/core/vk_semaphore.h
git.filemode.normal_file
@@ -0,0 +1,40 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_semaphore.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 18:59:38 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 01:08:00 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef __MLX_VK_SEMAPHORE__
|
||||
#define __MLX_VK_SEMAPHORE__
|
||||
|
||||
#include <volk.h>
|
||||
#include <vector>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
class Semaphore
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy() noexcept;
|
||||
|
||||
inline VkSemaphore& getImageSemaphore(int i) noexcept { return _imageAvailableSemaphores[i]; }
|
||||
inline VkSemaphore& getRenderImageSemaphore(int i) noexcept { return _renderFinishedSemaphores[i]; }
|
||||
inline VkFence& getInFlightFence(int i) noexcept { return _inFlightFences[i]; }
|
||||
inline VkFence& getInFlightImage(int i) noexcept { return _imagesInFlight[i]; }
|
||||
|
||||
private:
|
||||
std::vector<VkSemaphore> _imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> _renderFinishedSemaphores;
|
||||
std::vector<VkFence> _inFlightFences;
|
||||
std::vector<VkFence> _imagesInFlight;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __MLX_VK_SEMAPHORE__
|
||||
40
src/renderer/core/vk_surface.cpp
git.filemode.normal_file
40
src/renderer/core/vk_surface.cpp
git.filemode.normal_file
@@ -0,0 +1,40 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_surface.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 18:58:49 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 00:35:03 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "render_core.h"
|
||||
#include <platform/window.h>
|
||||
#include <SDL2/SDL_vulkan.h>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
void Surface::create()
|
||||
{
|
||||
if(SDL_Vulkan_CreateSurface(Render_Core::get().getWindow()->getNativeWindow(), Render_Core::get().getInstance().get(), &_surface) != SDL_TRUE)
|
||||
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a surface");
|
||||
}
|
||||
|
||||
VkSurfaceFormatKHR Surface::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
|
||||
{
|
||||
for(const auto& availableFormat : availableFormats)
|
||||
{
|
||||
if(availableFormat.format == VK_FORMAT_R8G8B8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||
return availableFormat;
|
||||
}
|
||||
|
||||
return availableFormats[0];
|
||||
}
|
||||
|
||||
void Surface::destroy() noexcept
|
||||
{
|
||||
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), _surface, nullptr);
|
||||
}
|
||||
}
|
||||
37
src/renderer/core/vk_surface.h
git.filemode.normal_file
37
src/renderer/core/vk_surface.h
git.filemode.normal_file
@@ -0,0 +1,37 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* vk_surface.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/10/08 18:57:55 by maldavid #+# #+# */
|
||||
/* Updated: 2022/12/18 01:07:57 by maldavid ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef __MLX_VK_SURFACE__
|
||||
#define __MLX_VK_SURFACE__
|
||||
|
||||
#include <volk.h>
|
||||
#include <vector>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
class Surface
|
||||
{
|
||||
public:
|
||||
void create();
|
||||
void destroy() noexcept;
|
||||
|
||||
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
|
||||
|
||||
inline VkSurfaceKHR& operator()() noexcept { return _surface; }
|
||||
inline VkSurfaceKHR& get() noexcept { return _surface; }
|
||||
|
||||
private:
|
||||
VkSurfaceKHR _surface = VK_NULL_HANDLE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __MLX_VK_SURFACE__
|
||||
Reference in New Issue
Block a user