almost first rendering, fixing renderer issues

This commit is contained in:
Kbz-8
2022-12-19 00:59:45 +01:00
parent 4a67aab716
commit f1e0499564
417 changed files with 60861 additions and 298 deletions

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 22:40:58 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -66,122 +66,16 @@ namespace mlx
}
}
Render_Core::Render_Core() : _device(), _queues(), _surface(),
_cmd_pool(), _swapchain(), _instance()
{}
void Render_Core::init()
{
volkInitialize();
_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;
@@ -192,13 +86,7 @@ namespace mlx
vkDeviceWaitIdle(_device());
_swapchain.destroyFB();
_pass.destroy();
_swapchain.destroy();
_semaphore.destroy();
_cmd_pool.destroy();
_device.destroy();
_surface.destroy();
_instance.destroy();
_is_init = false;

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 17:51:47 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -14,19 +14,10 @@
#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>
@@ -43,51 +34,21 @@ namespace mlx
class Render_Core : public Singleton<Render_Core>
{
public:
Render_Core();
Render_Core() = default;
void init();
void destroyCommandBuffers();
void destroy();
bool beginFrame();
void endFrame();
inline Instance& getInstance() noexcept { return _instance; }
inline Device& getDevice() noexcept { return _device; }
inline Queues& getQueue() noexcept { return _queues; }
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; }
~Render_Core() = default;
private:
Device _device;
Queues _queues;
Surface _surface;
RenderPass _pass;
CmdPool _cmd_pool;
Device _device;
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;
};
}

View File

@@ -6,13 +6,16 @@
/* 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 */
/* Updated: 2022/12/18 22:56:47 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include "render_core.h"
#include <vector>
#include <set>
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
#include <iostream>
namespace mlx
{
@@ -22,7 +25,7 @@ namespace mlx
{
pickPhysicalDevice();
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(_physicalDevice);
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().getFamilies();
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
@@ -67,33 +70,42 @@ namespace mlx
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(Render_Core::get().getInstance().get(), &deviceCount, devices.data());
SDL_Window* window = SDL_CreateWindow("", 0, 0, 1, 1, SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN);
if(!window)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a window to pick physical device");
VkSurfaceKHR surface = VK_NULL_HANDLE;
if(SDL_Vulkan_CreateSurface(window, Render_Core::get().getInstance().get(), &surface) != SDL_TRUE)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a surface to pick physical device");
for(const auto& device : devices)
{
if(isDeviceSuitable(device))
if(isDeviceSuitable(device, surface))
{
_physicalDevice = device;
break;
}
}
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), surface, nullptr);
SDL_DestroyWindow(window);
if(_physicalDevice == VK_NULL_HANDLE)
core::error::report(e_kind::fatal_error, "Vulkan : failed to find a suitable GPU");
}
bool Device::isDeviceSuitable(VkPhysicalDevice device)
bool Device::isDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface)
{
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(device);
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(device, surface);
bool extensionsSupported = checkDeviceExtensionSupport(device);
bool swapChainAdequate = false;
uint32_t formatCount = 0;
if(extensionsSupported)
{
SwapChain::SwapChainSupportDetails swapChainSupport = Render_Core::get().getSwapChain().querySwapChainSupport(device);
swapChainAdequate = !swapChainSupport.formats.empty();
}
return indices.isComplete() && extensionsSupported && swapChainAdequate;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
return indices.isComplete() && extensionsSupported && formatCount != 0;
}
bool Device::checkDeviceExtensionSupport(VkPhysicalDevice device)
{
uint32_t extensionCount;

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 22:55:30 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -14,6 +14,7 @@
#define __MLX_VK_DEVICE__
#include <volk.h>
#include "vk_queues.h"
namespace mlx
{
@@ -30,7 +31,7 @@ namespace mlx
private:
void pickPhysicalDevice();
bool isDeviceSuitable(VkPhysicalDevice device);
bool isDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface);
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
VkPhysicalDevice _physicalDevice = VK_NULL_HANDLE;

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 22:37:00 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -23,9 +23,9 @@ namespace mlx
{
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "MicroLibX";
appInfo.pApplicationName = "MacroLibX";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "MicroLibX";
appInfo.pEngineName = "MacroLibX";
appInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1);
appInfo.apiVersion = VK_API_VERSION_1_2;
@@ -44,20 +44,27 @@ namespace mlx
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);
}
std::vector<const char*> Instance::getRequiredExtensions()
{
unsigned int count = 0;
if(!SDL_Vulkan_GetInstanceExtensions(Render_Core::get().getWindow()->getNativeWindow(), &count, nullptr))
SDL_Window* window = SDL_CreateWindow("", 0, 0, 1, 1, SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN);
if(!window)
core::error::report(e_kind::fatal_error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError());
if(!SDL_Vulkan_GetInstanceExtensions(window, &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))
if(!SDL_Vulkan_GetInstanceExtensions(window, &count, extensions.data() + additional_extension_count))
core::error::report(e_kind::error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError());
SDL_DestroyWindow(window);
return extensions;
}

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 17:42:08 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -21,7 +21,6 @@ namespace mlx
class Instance
{
public:
void init();
void destroy() noexcept;

View File

@@ -6,15 +6,17 @@
/* 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 */
/* Updated: 2022/12/18 22:52:04 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include "render_core.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
namespace mlx
{
Queues::QueueFamilyIndices Queues::findQueueFamilies(VkPhysicalDevice device)
Queues::QueueFamilyIndices Queues::findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface)
{
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
@@ -23,7 +25,6 @@ namespace mlx
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
_families = Queues::QueueFamilyIndices{};
int i = 0;
for(const auto& queueFamily : queueFamilies)
{
@@ -31,7 +32,7 @@ namespace mlx
_families->graphicsFamily = i;
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, Render_Core::get().getSurface().get(), &presentSupport);
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
if(presentSupport)
_families->presentFamily = i;
@@ -40,13 +41,27 @@ namespace mlx
break;
i++;
}
return *_families;
}
void Queues::init()
{
if(!_families.has_value())
findQueueFamilies(Render_Core::get().getDevice().getPhysicalDevice());
{
SDL_Window* window = SDL_CreateWindow("", 0, 0, 1, 1, SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN);
if(!window)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a window to init queues");
VkSurfaceKHR surface = VK_NULL_HANDLE;
if(SDL_Vulkan_CreateSurface(window, Render_Core::get().getInstance().get(), &surface) != SDL_TRUE)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a surface to init queues");
findQueueFamilies(Render_Core::get().getDevice().getPhysicalDevice(), surface);
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), surface, nullptr);
SDL_DestroyWindow(window);
}
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->graphicsFamily.value(), 0, &_graphicsQueue);
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->presentFamily.value(), 0, &_presentQueue);
}

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 22:44:37 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -30,7 +30,7 @@ namespace mlx
inline bool isComplete() { return graphicsFamily.has_value() && presentFamily.has_value(); }
};
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface);
void init();

View File

@@ -6,21 +6,22 @@
/* 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 */
/* Updated: 2022/12/18 20:12:40 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include "vk_semaphore.h"
#include "render_core.h"
#include <renderer/renderer.h>
namespace mlx
{
void Semaphore::init()
void Semaphore::init(Renderer& renderer)
{
_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);
_imagesInFlight.resize(renderer.getSwapChain().getImagesNumber(), VK_NULL_HANDLE);
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 19:50:10 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -21,7 +21,7 @@ namespace mlx
class Semaphore
{
public:
void init();
void init(class Renderer& renderer);
void destroy() noexcept;
inline VkSemaphore& getImageSemaphore(int i) noexcept { return _imageAvailableSemaphores[i]; }

View File

@@ -6,20 +6,22 @@
/* 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 */
/* Updated: 2022/12/18 22:20:57 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include "render_core.h"
#include <platform/window.h>
#include <renderer/renderer.h>
#include <SDL2/SDL_vulkan.h>
#include <SDL2/SDL.h>
namespace mlx
{
void Surface::create()
void Surface::create(Renderer& renderer)
{
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");
if(SDL_Vulkan_CreateSurface(renderer.getWindow()->getNativeWindow(), Render_Core::get().getInstance().get(), &_surface) != SDL_TRUE)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a surface : %s", SDL_GetError());
}
VkSurfaceFormatKHR Surface::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)

View File

@@ -6,7 +6,7 @@
/* 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 */
/* Updated: 2022/12/18 19:34:04 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -21,7 +21,7 @@ namespace mlx
class Surface
{
public:
void create();
void create(class Renderer& renderer);
void destroy() noexcept;
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);