mirror of
https://github.com/seekrs/MacroLibX.git
synced 2026-01-11 14:43:34 +00:00
yes
This commit is contained in:
@@ -26,7 +26,7 @@ namespace mlx
|
||||
|
||||
inline void SetFPSCap(std::uint32_t fps) noexcept;
|
||||
|
||||
inline Handle NewGraphicsSuport(std::size_t w, std::size_t h, const char* title);
|
||||
inline Handle NewGraphicsSuport(std::size_t w, std::size_t h, const char* title, bool is_resizable);
|
||||
inline void ClearGraphicsSupport(Handle win);
|
||||
inline void DestroyGraphicsSupport(Handle win);
|
||||
inline void SetGraphicsSupportPosition(Handle win, int x, int y);
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace mlx
|
||||
m_fps.SetMaxFPS(fps);
|
||||
}
|
||||
|
||||
void* Application::NewGraphicsSuport(std::size_t w, std::size_t h, const char* title)
|
||||
void* Application::NewGraphicsSuport(std::size_t w, std::size_t h, const char* title, bool is_resizable)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_image_registry.IsTextureKnown(reinterpret_cast<Texture*>(const_cast<char*>(title))))
|
||||
@@ -88,13 +88,13 @@ namespace mlx
|
||||
{
|
||||
for(std::size_t i = 0; i < 8; i++)
|
||||
{
|
||||
m_graphics.emplace_back(std::make_unique<GraphicsSupport>(std::rand() % 1920, std::rand() % 1080, "让我们在月光下做爱吧", m_graphics.size()));
|
||||
m_graphics.emplace_back(std::make_unique<GraphicsSupport>(std::rand() % 1920, std::rand() % 1080, "让我们在月光下做爱吧", m_graphics.size(), is_resizable));
|
||||
m_graphics.back()->GetWindow()->SetPosition(std::rand() % 1920, std::rand() % 1080);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, title, m_graphics.size()));
|
||||
m_graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, title, m_graphics.size(), is_resizable));
|
||||
m_in.RegisterWindow(m_graphics.back()->GetWindow());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace mlx
|
||||
{
|
||||
public:
|
||||
GraphicsSupport(std::size_t w, std::size_t h, NonOwningPtr<Texture> render_target, int id);
|
||||
GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id);
|
||||
GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id, bool is_resizable);
|
||||
|
||||
[[nodiscard]] MLX_FORCEINLINE int& GetID() noexcept { return m_id; }
|
||||
[[nodiscard]] inline std::shared_ptr<Window> GetWindow() { return p_window; }
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace mlx
|
||||
public:
|
||||
SDLManager();
|
||||
|
||||
Handle CreateWindow(const std::string& title, std::size_t w, std::size_t h, bool hidden, std::int32_t& id);
|
||||
Handle CreateWindow(const std::string& title, std::size_t w, std::size_t h, bool hidden, std::int32_t& id, bool is_resizable);
|
||||
void DestroyWindow(Handle window) noexcept;
|
||||
|
||||
void InputsFetcher(func::function<void(mlx_event_type, int, int)> functor);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace mlx
|
||||
class Window
|
||||
{
|
||||
public:
|
||||
Window(std::size_t w, std::size_t h, const std::string& title, bool hidden = false);
|
||||
Window(std::size_t w, std::size_t h, const std::string& title, bool is_resizable, bool hidden = false);
|
||||
|
||||
inline Handle GetWindowHandle() const noexcept { return p_window; }
|
||||
inline int GetWidth() const noexcept { return m_width; }
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Renderer/Image.h>
|
||||
#include <Core/EventBus.h>
|
||||
#include <Renderer/Swapchain.h>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
@@ -16,46 +17,33 @@ namespace mlx
|
||||
|
||||
void Init(NonOwningPtr<Window> window);
|
||||
|
||||
bool BeginFrame();
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
|
||||
[[nodiscard]] inline VkSwapchainKHR GetSwapchain() const noexcept { return m_swapchain; }
|
||||
[[nodiscard]] inline VkSurfaceKHR GetSurface() const noexcept { return m_surface; }
|
||||
[[nodiscard]] inline VkSemaphore GetImageAvailableSemaphore(int index) const noexcept { return m_image_available_semaphores[index]; }
|
||||
[[nodiscard]] inline VkSemaphore GetRenderFinishedSemaphore(int index) const noexcept { return m_render_finished_semaphores[index]; }
|
||||
[[nodiscard]] inline VkCommandBuffer GetCommandBuffer(int index) const noexcept { return m_cmd_buffers[index]; }
|
||||
[[nodiscard]] inline VkCommandBuffer GetActiveCommandBuffer() const noexcept { return m_cmd_buffers[m_current_frame_index]; }
|
||||
[[nodiscard]] inline const std::vector<Image>& GetSwapchainImages() const { return m_swapchain_images; }
|
||||
[[nodiscard]] inline std::size_t& GetDrawCallsCounterRef() noexcept { return m_drawcalls; }
|
||||
[[nodiscard]] inline std::size_t& GetPolygonDrawnCounterRef() noexcept { return m_polygons_drawn; }
|
||||
[[nodiscard]] inline std::size_t GetSwapchainImageIndex() const noexcept { return m_swapchain_image_index; }
|
||||
[[nodiscard]] inline std::size_t GetCurrentFrameIndex() const noexcept { return m_current_frame_index; }
|
||||
[[nodiscard]] inline NonOwningPtr<Window> GetWindow() const noexcept { return p_window; }
|
||||
|
||||
MLX_FORCEINLINE constexpr void RequireFramebufferResize() noexcept { m_framebuffers_resize = true; }
|
||||
[[nodiscard]] inline const Swapchain& GetSwapchain() const noexcept { return m_swapchain; }
|
||||
|
||||
void Destroy() noexcept;
|
||||
|
||||
~Renderer() = default;
|
||||
|
||||
private:
|
||||
void CreateSwapchain();
|
||||
void DestroySwapchain();
|
||||
|
||||
private:
|
||||
Swapchain m_swapchain;
|
||||
std::array<VkSemaphore, MAX_FRAMES_IN_FLIGHT> m_image_available_semaphores;
|
||||
std::array<VkSemaphore, MAX_FRAMES_IN_FLIGHT> m_render_finished_semaphores;
|
||||
std::array<VkCommandBuffer, MAX_FRAMES_IN_FLIGHT> m_cmd_buffers;
|
||||
std::array<VkFence, MAX_FRAMES_IN_FLIGHT> m_cmd_fences;
|
||||
std::vector<Image> m_swapchain_images;
|
||||
NonOwningPtr<Window> p_window;
|
||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||
std::uint32_t m_current_frame_index = 0;
|
||||
std::uint32_t m_swapchain_image_index = 0;
|
||||
std::size_t m_drawcalls = 0;
|
||||
std::size_t m_polygons_drawn = 0;
|
||||
bool m_framebuffers_resize = false;
|
||||
std::size_t m_drawcalls = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
43
runtime/Includes/Renderer/Swapchain.h
git.filemode.normal_file
43
runtime/Includes/Renderer/Swapchain.h
git.filemode.normal_file
@@ -0,0 +1,43 @@
|
||||
#ifndef __MLX_SWAPCHAIN__
|
||||
#define __MLX_SWAPCHAIN__
|
||||
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
#include <Renderer/Image.h>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
class Swapchain
|
||||
{
|
||||
public:
|
||||
Swapchain() = default;
|
||||
|
||||
void Init(NonOwningPtr<class Window> window);
|
||||
void AquireFrame(VkSemaphore signal);
|
||||
void Present(VkSemaphore wait) noexcept;
|
||||
void Destroy();
|
||||
|
||||
[[nodiscard]] inline VkSwapchainKHR Get() const noexcept { return m_swapchain; }
|
||||
[[nodiscard]] inline VkSurfaceKHR GetSurface() const noexcept { return m_surface; }
|
||||
[[nodiscard]] inline std::uint32_t GetImagesCount() const noexcept { return m_images_count; }
|
||||
[[nodiscard]] inline std::uint32_t GetMinImagesCount() const noexcept { return m_min_images_count; }
|
||||
[[nodiscard]] inline std::uint32_t GetImageIndex() const noexcept { return m_current_image_index; }
|
||||
[[nodiscard]] inline const std::vector<Image>& GetSwapchainImages() const { return m_swapchain_images; }
|
||||
|
||||
~Swapchain() = default;
|
||||
|
||||
private:
|
||||
void CreateSwapchain();
|
||||
|
||||
private:
|
||||
std::vector<Image> m_swapchain_images;
|
||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||
NonOwningPtr<class Window> p_window;
|
||||
std::uint32_t m_images_count = 0;
|
||||
std::uint32_t m_min_images_count = 0;
|
||||
std::uint32_t m_current_image_index = 0;
|
||||
bool m_resize = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -42,7 +42,18 @@ extern "C"
|
||||
mlx::FatalError("invalid window size (%d x %d)", w, h);
|
||||
return NULL; // not nullptr for the C compatibility
|
||||
}
|
||||
return static_cast<mlx::Application*>(mlx)->NewGraphicsSuport(w, h, title);
|
||||
return static_cast<mlx::Application*>(mlx)->NewGraphicsSuport(w, h, title, false);
|
||||
}
|
||||
|
||||
void* mlx_new_resizable_window(void* mlx, int w, int h, const char* title)
|
||||
{
|
||||
MLX_CHECK_APPLICATION_POINTER(mlx);
|
||||
if(w <= 0 || h <= 0)
|
||||
{
|
||||
mlx::FatalError("invalid window size (%d x %d)", w, h);
|
||||
return NULL; // not nullptr for the C compatibility
|
||||
}
|
||||
return static_cast<mlx::Application*>(mlx)->NewGraphicsSuport(w, h, title, true);
|
||||
}
|
||||
|
||||
void mlx_set_window_position(void *mlx, void *win, int x, int y)
|
||||
@@ -51,7 +62,7 @@ extern "C"
|
||||
static_cast<mlx::Application*>(mlx)->SetGraphicsSupportPosition(win, x, y);
|
||||
}
|
||||
|
||||
int mlx_loop_hook(void* mlx, int (*f)(void*), void* param)
|
||||
void mlx_loop_hook(void* mlx, int (*f)(void*), void* param)
|
||||
{
|
||||
MLX_CHECK_APPLICATION_POINTER(mlx);
|
||||
static_cast<mlx::Application*>(mlx)->LoopHook(f, param);
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace mlx
|
||||
p_scene = std::make_unique<Scene>();
|
||||
}
|
||||
|
||||
GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id) :
|
||||
GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id, bool is_resizable) :
|
||||
m_put_pixel_manager(&m_renderer),
|
||||
p_window(std::make_shared<Window>(w, h, title)),
|
||||
p_window(std::make_shared<Window>(w, h, title, is_resizable)),
|
||||
m_id(id),
|
||||
m_has_window(true)
|
||||
{
|
||||
@@ -31,13 +31,10 @@ namespace mlx
|
||||
void GraphicsSupport::Render() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_renderer.BeginFrame())
|
||||
{
|
||||
m_renderer.BeginFrame();
|
||||
m_draw_layer = 0;
|
||||
m_scene_renderer.Render(*p_scene, m_renderer);
|
||||
m_renderer.EndFrame();
|
||||
}
|
||||
|
||||
m_renderer.EndFrame();
|
||||
#ifdef GRAPHICS_MEMORY_DUMP
|
||||
// dump memory to file every two seconds
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
@@ -47,12 +47,20 @@ namespace mlx
|
||||
DebugLog("SDL Manager initialized");
|
||||
}
|
||||
|
||||
Handle SDLManager::CreateWindow(const std::string& title, std::size_t w, std::size_t h, bool hidden, std::int32_t& id)
|
||||
Handle SDLManager::CreateWindow(const std::string& title, std::size_t w, std::size_t h, bool hidden, std::int32_t& id, bool is_resizable)
|
||||
{
|
||||
Internal::WindowInfos* infos = new Internal::WindowInfos;
|
||||
Verify(infos != nullptr, "SDL: window allocation failed");
|
||||
|
||||
infos->window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_VULKAN | (hidden ? SDL_WINDOW_HIDDEN : SDL_WINDOW_SHOWN));
|
||||
std::uint32_t flags = SDL_WINDOW_VULKAN;
|
||||
if(hidden)
|
||||
flags |= SDL_WINDOW_HIDDEN;
|
||||
else
|
||||
flags |= SDL_WINDOW_SHOWN;
|
||||
if(is_resizable)
|
||||
flags |= SDL_WINDOW_RESIZABLE;
|
||||
|
||||
infos->window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, flags);
|
||||
if(!infos->window)
|
||||
FatalError("SDL: unable to open a new window; %", SDL_GetError());
|
||||
infos->icon = SDL_CreateRGBSurfaceFrom(static_cast<void*>(logo_mlx), logo_mlx_width, logo_mlx_height, 32, 4 * logo_mlx_width, rmask, gmask, bmask, amask);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace mlx
|
||||
{
|
||||
Verify((bool)p_renderer, "invalid renderer pointer");
|
||||
|
||||
VkExtent2D swapchain_extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain());
|
||||
VkExtent2D swapchain_extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain().Get());
|
||||
#ifdef DEBUG
|
||||
auto res = m_textures.try_emplace(draw_layer, CPUBuffer{}, swapchain_extent.width, swapchain_extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_put_pixel_layer_" + std::to_string(draw_layer));
|
||||
#else
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
Window::Window(std::size_t w, std::size_t h, const std::string& title, bool hidden) : m_name(title), m_width(w), m_height(h)
|
||||
Window::Window(std::size_t w, std::size_t h, const std::string& title, bool is_resizable, bool hidden) : m_name(title), m_width(w), m_height(h)
|
||||
{
|
||||
p_window = SDLManager::Get().CreateWindow(title, w, h, hidden, m_id);
|
||||
p_window = SDLManager::Get().CreateWindow(title, w, h, hidden, m_id, is_resizable);
|
||||
}
|
||||
|
||||
void Window::Destroy() noexcept
|
||||
|
||||
@@ -153,8 +153,8 @@ namespace mlx
|
||||
std::vector<VkImageView> attachment_views;
|
||||
if(p_renderer)
|
||||
{
|
||||
attachments.push_back(kvfBuildSwapchainAttachmentDescription(p_renderer->GetSwapchain(), clear_attachments));
|
||||
attachment_views.push_back(p_renderer->GetSwapchainImages()[0].GetImageView());
|
||||
attachments.push_back(kvfBuildSwapchainAttachmentDescription(p_renderer->GetSwapchain().Get(), clear_attachments));
|
||||
attachment_views.push_back(p_renderer->GetSwapchain().GetSwapchainImages()[0].GetImageView());
|
||||
}
|
||||
|
||||
#pragma omp parallel for
|
||||
@@ -171,7 +171,7 @@ namespace mlx
|
||||
|
||||
if(p_renderer)
|
||||
{
|
||||
for(const Image& image : p_renderer->GetSwapchainImages())
|
||||
for(const Image& image : p_renderer->GetSwapchain().GetSwapchainImages())
|
||||
{
|
||||
attachment_views[0] = image.GetImageView();
|
||||
m_framebuffers.push_back(kvfCreateFramebuffer(RenderCore::Get().GetDevice(), m_renderpass, attachment_views.data(), attachment_views.size(), { .width = image.GetWidth(), .height = image.GetHeight() }));
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <mlx_profile.h>
|
||||
#include <PreCompiled.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
|
||||
@@ -7,6 +6,8 @@
|
||||
#define KVF_ENABLE_VALIDATION_LAYERS
|
||||
#endif
|
||||
|
||||
#define KVF_ASSERT(x) mlx::Assert(x, #x)
|
||||
|
||||
#if defined(MLX_COMPILER_GCC) || defined(MLX_COMPILER_CLANG)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
||||
@@ -60,8 +61,6 @@ namespace mlx
|
||||
kvfSetValidationErrorCallback(&ValidationErrorCallback);
|
||||
kvfSetValidationWarningCallback(&WarningCallback);
|
||||
|
||||
//kvfAddLayer("VK_LAYER_MESA_overlay");
|
||||
|
||||
Window window(1, 1, "", true);
|
||||
std::vector<const char*> instance_extensions = window.GetRequiredVulkanInstanceExtentions();
|
||||
#ifdef MLX_PLAT_MACOS
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace mlx
|
||||
p_set->SetImage(renderer.GetCurrentFrameIndex(), 0, render_target);
|
||||
p_set->Update(renderer.GetCurrentFrameIndex(), cmd);
|
||||
|
||||
m_pipeline.BindPipeline(cmd, renderer.GetSwapchainImageIndex(), { 0.0f, 0.0f, 0.0f, 1.0f });
|
||||
m_pipeline.BindPipeline(cmd, renderer.GetSwapchain().GetImageIndex(), { 0.0f, 0.0f, 0.0f, 1.0f });
|
||||
VkDescriptorSet set = p_set->GetSet(renderer.GetCurrentFrameIndex());
|
||||
RenderCore::Get().vkCmdBindDescriptorSets(cmd, m_pipeline.GetPipelineBindPoint(), m_pipeline.GetPipelineLayout(), 0, 1, &set, 0, nullptr);
|
||||
RenderCore::Get().vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace mlx
|
||||
if(event.What() == Event::ResizeEventCode)
|
||||
{
|
||||
m_main_render_texture.Destroy();
|
||||
auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain());
|
||||
auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain().Get());
|
||||
#ifdef DEBUG
|
||||
m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_renderpasses_target");
|
||||
#else
|
||||
@@ -24,7 +24,7 @@ namespace mlx
|
||||
}
|
||||
};
|
||||
EventBus::RegisterListener({ functor, "__MlxRenderPasses" });
|
||||
auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain());
|
||||
auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain().Get());
|
||||
|
||||
#ifdef DEBUG
|
||||
m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_renderpasses_target");
|
||||
|
||||
@@ -9,11 +9,6 @@ namespace mlx
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
struct ResizeEventBroadcast : public EventBase
|
||||
{
|
||||
Event What() const override { return Event::ResizeEventCode; }
|
||||
};
|
||||
|
||||
struct FrameBeginEventBroadcast : public EventBase
|
||||
{
|
||||
Event What() const override { return Event::FrameBeginEventCode; }
|
||||
@@ -23,20 +18,8 @@ namespace mlx
|
||||
void Renderer::Init(NonOwningPtr<Window> window)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
func::function<void(const EventBase&)> functor = [this](const EventBase& event)
|
||||
{
|
||||
if(event.What() == Event::ResizeEventCode)
|
||||
this->RequireFramebufferResize();
|
||||
};
|
||||
EventBus::RegisterListener({ functor, "__MlxRenderer" + std::to_string(reinterpret_cast<std::uintptr_t>(this)) });
|
||||
|
||||
p_window = window;
|
||||
|
||||
m_surface = p_window->CreateVulkanSurface(RenderCore::Get().GetInstance());
|
||||
DebugLog("Vulkan: surface created");
|
||||
|
||||
CreateSwapchain();
|
||||
|
||||
m_swapchain.Init(p_window);
|
||||
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
m_image_available_semaphores[i] = kvfCreateSemaphore(RenderCore::Get().GetDevice());
|
||||
@@ -50,27 +33,16 @@ namespace mlx
|
||||
}
|
||||
}
|
||||
|
||||
bool Renderer::BeginFrame()
|
||||
void Renderer::BeginFrame()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
kvfWaitForFence(RenderCore::Get().GetDevice(), m_cmd_fences[m_current_frame_index]);
|
||||
VkResult result = RenderCore::Get().vkAcquireNextImageKHR(RenderCore::Get().GetDevice(), m_swapchain, UINT64_MAX, m_image_available_semaphores[m_current_frame_index], VK_NULL_HANDLE, &m_swapchain_image_index);
|
||||
if(result == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
//DestroySwapchain();
|
||||
//CreateSwapchain();
|
||||
//EventBus::SendBroadcast(Internal::ResizeEventBroadcast{});
|
||||
//return false;
|
||||
}
|
||||
else if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
|
||||
FatalError("Vulkan error: failed to acquire swapchain image, %", kvfVerbaliseVkResult(result));
|
||||
|
||||
m_swapchain.AquireFrame(m_image_available_semaphores[m_current_frame_index]);
|
||||
RenderCore::Get().vkResetCommandBuffer(m_cmd_buffers[m_current_frame_index], 0);
|
||||
kvfBeginCommandBuffer(m_cmd_buffers[m_current_frame_index], 0);
|
||||
m_drawcalls = 0;
|
||||
m_polygons_drawn = 0;
|
||||
EventBus::SendBroadcast(Internal::FrameBeginEventBroadcast{});
|
||||
return true;
|
||||
}
|
||||
|
||||
void Renderer::EndFrame()
|
||||
@@ -79,55 +51,14 @@ namespace mlx
|
||||
VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
|
||||
kvfEndCommandBuffer(m_cmd_buffers[m_current_frame_index]);
|
||||
kvfSubmitCommandBuffer(RenderCore::Get().GetDevice(), m_cmd_buffers[m_current_frame_index], KVF_GRAPHICS_QUEUE, m_render_finished_semaphores[m_current_frame_index], m_image_available_semaphores[m_current_frame_index], m_cmd_fences[m_current_frame_index], wait_stages);
|
||||
if(!kvfQueuePresentKHR(RenderCore::Get().GetDevice(), m_render_finished_semaphores[m_current_frame_index], m_swapchain, m_swapchain_image_index) || m_framebuffers_resize)
|
||||
{
|
||||
m_framebuffers_resize = false;
|
||||
//DestroySwapchain();
|
||||
//CreateSwapchain();
|
||||
//EventBus::SendBroadcast(Internal::ResizeEventBroadcast{});
|
||||
}
|
||||
m_swapchain.Present(m_render_finished_semaphores[m_current_frame_index]);
|
||||
m_current_frame_index = (m_current_frame_index + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
void Renderer::CreateSwapchain()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
Vec2ui drawable_size = p_window->GetVulkanDrawableSize();
|
||||
VkExtent2D extent = { drawable_size.x, drawable_size.y };
|
||||
m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, false);
|
||||
|
||||
std::uint32_t images_count = kvfGetSwapchainImagesCount(m_swapchain);
|
||||
std::vector<VkImage> tmp(images_count);
|
||||
m_swapchain_images.resize(images_count);
|
||||
RenderCore::Get().vkGetSwapchainImagesKHR(RenderCore::Get().GetDevice(), m_swapchain, &images_count, tmp.data());
|
||||
for(std::size_t i = 0; i < images_count; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
m_swapchain_images[i].Init(tmp[i], kvfGetSwapchainImagesFormat(m_swapchain), extent.width, extent.height, VK_IMAGE_LAYOUT_UNDEFINED, "mlx_swapchain_image_" + std::to_string(i));
|
||||
#else
|
||||
m_swapchain_images[i].Init(tmp[i], kvfGetSwapchainImagesFormat(m_swapchain), extent.width, extent.height, VK_IMAGE_LAYOUT_UNDEFINED, {});
|
||||
#endif
|
||||
m_swapchain_images[i].TransitionLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
m_swapchain_images[i].CreateImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
DebugLog("Vulkan: swapchain created");
|
||||
}
|
||||
|
||||
void Renderer::DestroySwapchain()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
for(Image& img : m_swapchain_images)
|
||||
img.DestroyImageView();
|
||||
kvfDestroySwapchainKHR(RenderCore::Get().GetDevice(), m_swapchain);
|
||||
DebugLog("Vulkan: swapchain destroyed");
|
||||
}
|
||||
|
||||
void Renderer::Destroy() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
|
||||
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
kvfDestroySemaphore(RenderCore::Get().GetDevice(), m_image_available_semaphores[i]);
|
||||
@@ -137,10 +68,6 @@ namespace mlx
|
||||
kvfDestroyFence(RenderCore::Get().GetDevice(), m_cmd_fences[i]);
|
||||
DebugLog("Vulkan: fence destroyed");
|
||||
}
|
||||
|
||||
DestroySwapchain();
|
||||
RenderCore::Get().vkDestroySurfaceKHR(RenderCore::Get().GetInstance(), m_surface, nullptr);
|
||||
DebugLog("Vulkan: surface destroyed");
|
||||
m_surface = VK_NULL_HANDLE;
|
||||
m_swapchain.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
108
runtime/Sources/Renderer/Swapchain.cpp
git.filemode.normal_file
108
runtime/Sources/Renderer/Swapchain.cpp
git.filemode.normal_file
@@ -0,0 +1,108 @@
|
||||
#include <PreCompiled.h>
|
||||
|
||||
#include <Platform/Window.h>
|
||||
#include <Renderer/Swapchain.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Core/Logs.h>
|
||||
#include <Core/EventBus.h>
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
struct ResizeEventBroadcast : public EventBase
|
||||
{
|
||||
Event What() const override { return Event::ResizeEventCode; }
|
||||
};
|
||||
}
|
||||
|
||||
void Swapchain::Init(NonOwningPtr<Window> window)
|
||||
{
|
||||
p_window = window;
|
||||
m_surface = window->CreateVulkanSurface(RenderCore::Get().GetInstance());
|
||||
DebugLog("Vulkan: surface created");
|
||||
CreateSwapchain();
|
||||
}
|
||||
|
||||
void Swapchain::AquireFrame(VkSemaphore signal)
|
||||
{
|
||||
if(m_resize)
|
||||
{
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
CreateSwapchain();
|
||||
EventBus::SendBroadcast(Internal::ResizeEventBroadcast{});
|
||||
}
|
||||
|
||||
VkResult result = RenderCore::Get().vkAcquireNextImageKHR(RenderCore::Get().GetDevice(), m_swapchain, UINT64_MAX, signal, VK_NULL_HANDLE, &m_current_image_index);
|
||||
if(result == VK_SUBOPTIMAL_KHR)
|
||||
m_resize = true; // Recreate Swapchain next time
|
||||
else if(result == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
m_resize = true;
|
||||
AquireFrame(signal);
|
||||
}
|
||||
else if(result != VK_SUCCESS)
|
||||
FatalError("Vulkan: failed to acquire swapchain image, %", kvfVerbaliseVkResult(result));
|
||||
}
|
||||
|
||||
void Swapchain::Present(VkSemaphore wait) noexcept
|
||||
{
|
||||
if(!kvfQueuePresentKHR(RenderCore::Get().GetDevice(), wait, m_swapchain, m_current_image_index))
|
||||
m_resize = true;
|
||||
}
|
||||
|
||||
void Swapchain::Destroy()
|
||||
{
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
|
||||
for(Image& img : m_swapchain_images)
|
||||
img.DestroyImageView();
|
||||
// kvfDestroySwapchainKHR(RenderCore::Get().GetDevice(), m_swapchain);
|
||||
|
||||
RenderCore::Get().vkDestroySurfaceKHR(RenderCore::Get().GetInstance(), m_surface, nullptr);
|
||||
m_surface = VK_NULL_HANDLE;
|
||||
DebugLog("Vulkan: surface destroyed");
|
||||
}
|
||||
|
||||
void Swapchain::CreateSwapchain()
|
||||
{
|
||||
for(Image& img : m_swapchain_images)
|
||||
img.DestroyImageView();
|
||||
m_swapchain_images.clear();
|
||||
|
||||
VkExtent2D extent;
|
||||
do
|
||||
{
|
||||
Vec2ui size = p_window->GetVulkanDrawableSize();
|
||||
extent = { size.x, size.y };
|
||||
} while(extent.width == 0 || extent.height == 0);
|
||||
|
||||
VkSwapchainKHR old_swapchain = m_swapchain;
|
||||
m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, VK_NULL_HANDLE, true);
|
||||
// if(old_swapchain != VK_NULL_HANDLE)
|
||||
// kvfDestroySwapchainKHR(RenderCore::Get().GetDevice(), old_swapchain);
|
||||
|
||||
m_images_count = kvfGetSwapchainImagesCount(m_swapchain);
|
||||
m_min_images_count = kvfGetSwapchainMinImagesCount(m_swapchain);
|
||||
std::vector<VkImage> tmp(m_images_count);
|
||||
m_swapchain_images.resize(m_images_count);
|
||||
RenderCore::Get().vkGetSwapchainImagesKHR(RenderCore::Get().GetDevice(), m_swapchain, &m_images_count, tmp.data());
|
||||
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
|
||||
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
for(std::size_t i = 0; i < m_images_count; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
m_swapchain_images[i].Init(tmp[i], kvfGetSwapchainImagesFormat(m_swapchain), extent.width, extent.height, VK_IMAGE_LAYOUT_UNDEFINED, "mlx_swapchain_image_" + std::to_string(i));
|
||||
#else
|
||||
m_swapchain_images[i].Init(tmp[i], kvfGetSwapchainImagesFormat(m_swapchain), extent.width, extent.height, VK_IMAGE_LAYOUT_UNDEFINED, {});
|
||||
#endif
|
||||
m_swapchain_images[i].TransitionLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, cmd);
|
||||
m_swapchain_images[i].CreateImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
kvfEndCommandBuffer(cmd);
|
||||
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
|
||||
kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence);
|
||||
kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
|
||||
DebugLog("Vulkan: swapchain created");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user