working on swapchains

This commit is contained in:
2024-11-26 23:11:03 +01:00
parent 32b6053cfb
commit 122f4e8403
12 changed files with 84 additions and 29 deletions

View File

@@ -47,7 +47,7 @@ ifeq ($(OS), Darwin)
endif endif
ifeq ($(DEBUG), true) ifeq ($(DEBUG), true)
CXXFLAGS += -g3 -D DEBUG CXXFLAGS += -g3 -O0 -D DEBUG
LDFLAGS += -rdynamic LDFLAGS += -rdynamic
else else
CXXFLAGS += -O3 CXXFLAGS += -O3

View File

@@ -56,7 +56,14 @@ int update(void* param)
mlx_transform_put_image_to_window(mlx->mlx, mlx->render_target_win, mlx->logo_bmp, 100, 40, 0.5f, 75.0f); mlx_transform_put_image_to_window(mlx->mlx, mlx->render_target_win, mlx->logo_bmp, 100, 40, 0.5f, 75.0f);
mlx_put_image_to_window(mlx->mlx, mlx->render_target_win, mlx->img, 40, 60); mlx_put_image_to_window(mlx->mlx, mlx->render_target_win, mlx->img, 40, 60);
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->render_target_win, 40, 60); for(int j = 0, color = 0; j < 200; j++)
{
mlx_pixel_put(mlx->mlx, mlx->render_target_win, j, j, 0xFFFF0000 + color);
mlx_pixel_put(mlx->mlx, mlx->render_target_win, 199 - j, j, 0xFF0000FF);
color += (color < 255);
}
mlx_transform_put_image_to_window(mlx->mlx, mlx->win, mlx->render_target, 5, 250, 0.5f, 33.0f);
i++; i++;
return 0; return 0;
@@ -139,10 +146,14 @@ int main(void)
int dummy; int dummy;
mlx.mlx = mlx_init(); mlx.mlx = mlx_init();
mlx.win = mlx_new_window(mlx.mlx, 400, 400, "My window"); mlx.win = mlx_new_resizable_window(mlx.mlx, 400, 400, "My window");
mlx_get_screens_size(mlx.mlx, mlx.win, &w, &h);
printf("screen size : %dx%d\n", w, h);
mlx.render_target = mlx_new_image(mlx.mlx, 200, 200); mlx.render_target = mlx_new_image(mlx.mlx, 200, 200);
mlx.render_target_win = mlx_new_window(mlx.mlx, 200, 200, (char*)mlx.render_target); mlx.render_target_win = mlx_new_window(mlx.mlx, 200, 200, (char*)mlx.render_target);
mlx_clear_window(mlx.mlx, mlx.render_target_win, 0xFFC16868);
mlx_set_fps_goal(mlx.mlx, 60); mlx_set_fps_goal(mlx.mlx, 60);
@@ -164,9 +175,6 @@ int main(void)
mlx_loop_hook(mlx.mlx, update, &mlx); mlx_loop_hook(mlx.mlx, update, &mlx);
mlx_loop(mlx.mlx); mlx_loop(mlx.mlx);
mlx_get_screens_size(mlx.mlx, mlx.win, &w, &h);
printf("screen size : %dx%d\n", w, h);
mlx_destroy_image(mlx.mlx, mlx.logo_png); mlx_destroy_image(mlx.mlx, mlx.logo_png);
mlx_destroy_image(mlx.mlx, mlx.logo_jpg); mlx_destroy_image(mlx.mlx, mlx.logo_jpg);
mlx_destroy_image(mlx.mlx, mlx.logo_bmp); mlx_destroy_image(mlx.mlx, mlx.logo_bmp);

View File

@@ -1,7 +1,7 @@
#ifndef __MLX_RENDER_CORE__ #ifndef __MLX_RENDER_CORE__
#define __MLX_RENDER_CORE__ #define __MLX_RENDER_CORE__
constexpr const int MAX_FRAMES_IN_FLIGHT = 3; constexpr const int MAX_FRAMES_IN_FLIGHT = 2;
#include <Renderer/Memory.h> #include <Renderer/Memory.h>
#include <Renderer/Descriptor.h> #include <Renderer/Descriptor.h>

View File

@@ -16,6 +16,7 @@ namespace mlx
Renderer() = default; Renderer() = default;
void Init(NonOwningPtr<Window> window); void Init(NonOwningPtr<Window> window);
void Init(NonOwningPtr<Texture> render_target);
void BeginFrame(); void BeginFrame();
void EndFrame(); void EndFrame();
@@ -28,6 +29,7 @@ namespace mlx
[[nodiscard]] inline std::size_t& GetPolygonDrawnCounterRef() noexcept { return m_polygons_drawn; } [[nodiscard]] inline std::size_t& GetPolygonDrawnCounterRef() noexcept { return m_polygons_drawn; }
[[nodiscard]] inline std::size_t GetCurrentFrameIndex() const noexcept { return m_current_frame_index; } [[nodiscard]] inline std::size_t GetCurrentFrameIndex() const noexcept { return m_current_frame_index; }
[[nodiscard]] inline NonOwningPtr<Window> GetWindow() const noexcept { return p_window; } [[nodiscard]] inline NonOwningPtr<Window> GetWindow() const noexcept { return p_window; }
[[nodiscard]] inline NonOwningPtr<Texture> GetRenderTarget() const noexcept { return p_render_target; }
[[nodiscard]] inline const Swapchain& GetSwapchain() const noexcept { return m_swapchain; } [[nodiscard]] inline const Swapchain& GetSwapchain() const noexcept { return m_swapchain; }
void Destroy() noexcept; void Destroy() noexcept;
@@ -41,6 +43,7 @@ namespace mlx
std::array<VkCommandBuffer, MAX_FRAMES_IN_FLIGHT> m_cmd_buffers; std::array<VkCommandBuffer, MAX_FRAMES_IN_FLIGHT> m_cmd_buffers;
std::array<VkFence, MAX_FRAMES_IN_FLIGHT> m_cmd_fences; std::array<VkFence, MAX_FRAMES_IN_FLIGHT> m_cmd_fences;
NonOwningPtr<Window> p_window; NonOwningPtr<Window> p_window;
NonOwningPtr<Texture> p_render_target;
std::uint32_t m_current_frame_index = 0; std::uint32_t m_current_frame_index = 0;
std::size_t m_polygons_drawn = 0; std::size_t m_polygons_drawn = 0;
std::size_t m_drawcalls = 0; std::size_t m_drawcalls = 0;

View File

@@ -10,7 +10,7 @@ namespace mlx
m_has_window(false) m_has_window(false)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
m_renderer.Init(nullptr); m_renderer.Init(render_target);
m_scene_renderer.Init(render_target); m_scene_renderer.Init(render_target);
p_scene = std::make_unique<Scene>(); p_scene = std::make_unique<Scene>();
} }

View File

@@ -9,11 +9,18 @@ namespace mlx
{ {
Verify((bool)p_renderer, "invalid renderer pointer"); Verify((bool)p_renderer, "invalid renderer pointer");
VkExtent2D swapchain_extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain().Get()); VkExtent2D extent;
if(p_renderer->GetWindow())
extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain().Get());
else if(p_renderer->GetRenderTarget())
extent = VkExtent2D{ .width = p_renderer->GetRenderTarget()->GetWidth(), .height = p_renderer->GetRenderTarget()->GetHeight() };
else
FatalError("a renderer was created without window nor render target attached (wtf)");
#ifdef DEBUG #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)); auto res = m_textures.try_emplace(draw_layer, CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_put_pixel_layer_" + std::to_string(draw_layer));
#else #else
auto res = m_textures.try_emplace(draw_layer, CPUBuffer{}, swapchain_extent.width, swapchain_extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, std::string_view{}); auto res = m_textures.try_emplace(draw_layer, CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, std::string_view{});
#endif #endif
if(res.second) if(res.second)
res.first->second.Clear(VK_NULL_HANDLE, Vec4f{ 0.0f }); res.first->second.Clear(VK_NULL_HANDLE, Vec4f{ 0.0f });

View File

@@ -132,6 +132,7 @@ namespace mlx
kvfDestroyFramebuffer(RenderCore::Get().GetDevice(), fb); kvfDestroyFramebuffer(RenderCore::Get().GetDevice(), fb);
DebugLog("Vulkan: framebuffer destroyed"); DebugLog("Vulkan: framebuffer destroyed");
} }
m_framebuffers.clear();
kvfDestroyPipelineLayout(RenderCore::Get().GetDevice(), m_pipeline_layout); kvfDestroyPipelineLayout(RenderCore::Get().GetDevice(), m_pipeline_layout);
m_pipeline_layout = VK_NULL_HANDLE; m_pipeline_layout = VK_NULL_HANDLE;
@@ -148,7 +149,6 @@ namespace mlx
p_renderer = nullptr; p_renderer = nullptr;
m_clears.clear(); m_clears.clear();
m_attachments.clear(); m_attachments.clear();
m_framebuffers.clear();
} }
void GraphicPipeline::CreateFramebuffers(const std::vector<NonOwningPtr<Texture>>& render_targets, bool clear_attachments) void GraphicPipeline::CreateFramebuffers(const std::vector<NonOwningPtr<Texture>>& render_targets, bool clear_attachments)
@@ -156,6 +156,8 @@ namespace mlx
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
std::vector<VkAttachmentDescription> attachments; std::vector<VkAttachmentDescription> attachments;
std::vector<VkImageView> attachment_views; std::vector<VkImageView> attachment_views;
std::vector<VkSubpassDependency> dependencies;
if(p_renderer) if(p_renderer)
{ {
attachments.push_back(kvfBuildSwapchainAttachmentDescription(p_renderer->GetSwapchain().Get(), clear_attachments)); attachments.push_back(kvfBuildSwapchainAttachmentDescription(p_renderer->GetSwapchain().Get(), clear_attachments));
@@ -164,11 +166,30 @@ namespace mlx
for(NonOwningPtr<Texture> image : render_targets) for(NonOwningPtr<Texture> image : render_targets)
{ {
attachments.push_back(kvfBuildAttachmentDescription((kvfIsDepthFormat(image->GetFormat()) ? KVF_IMAGE_DEPTH : KVF_IMAGE_COLOR), image->GetFormat(), image->GetLayout(), image->GetLayout(), clear_attachments, VK_SAMPLE_COUNT_1_BIT)); attachments.push_back(kvfBuildAttachmentDescription(KVF_IMAGE_COLOR, image->GetFormat(), image->GetLayout(), image->GetLayout(), clear_attachments, VK_SAMPLE_COUNT_1_BIT));
attachment_views.push_back(image->GetImageView()); attachment_views.push_back(image->GetImageView());
#if 0
VkSubpassDependency& first_dependency = dependencies.emplace_back();
first_dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
first_dependency.dstSubpass = 0;
first_dependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
first_dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
first_dependency.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
first_dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
first_dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
VkSubpassDependency& second_dependency = dependencies.emplace_back();
second_dependency.srcSubpass = 0;
second_dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
second_dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
second_dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
second_dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
second_dependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
second_dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
#endif
} }
m_renderpass = kvfCreateRenderPass(RenderCore::Get().GetDevice(), attachments.data(), attachments.size(), GetPipelineBindPoint()); m_renderpass = kvfCreateRenderPassWithSubpassDependencies(RenderCore::Get().GetDevice(), attachments.data(), attachments.size(), GetPipelineBindPoint(), dependencies.data(), dependencies.size());
m_clears.clear(); m_clears.clear();
m_clears.resize(attachments.size()); m_clears.resize(attachments.size());
DebugLog("Vulkan: renderpass created"); DebugLog("Vulkan: renderpass created");

View File

@@ -50,7 +50,7 @@ namespace mlx
if(event.What() == Event::ResizeEventCode) if(event.What() == Event::ResizeEventCode)
m_pipeline.Destroy(); m_pipeline.Destroy();
}; };
EventBus::RegisterListener({ functor, "__MlxRender2DPass" }); EventBus::RegisterListener({ functor, "mlx_2d_render_pass" });
p_viewer_data_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_vertex_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Vertex); p_viewer_data_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_vertex_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Vertex);
p_texture_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); p_texture_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment);

View File

@@ -36,7 +36,7 @@ namespace mlx
if(event.What() == Event::ResizeEventCode) if(event.What() == Event::ResizeEventCode)
m_pipeline.Destroy(); m_pipeline.Destroy();
}; };
EventBus::RegisterListener({ functor, "__MlxFinalPass" }); EventBus::RegisterListener({ functor, "mlx_final_pass" });
p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment);
} }

View File

@@ -16,7 +16,7 @@ namespace mlx
if(event.What() == Event::ResizeEventCode) if(event.What() == Event::ResizeEventCode)
m_main_render_texture.Destroy(); m_main_render_texture.Destroy();
}; };
EventBus::RegisterListener({ functor, "__MlxRenderPasses" }); EventBus::RegisterListener({ functor, "mlx_render_passes" });
} }
void RenderPasses::Pass(Scene& scene, Renderer& renderer, const Vec4f& clear_color) void RenderPasses::Pass(Scene& scene, Renderer& renderer, const Vec4f& clear_color)

View File

@@ -19,7 +19,6 @@ namespace mlx
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
p_window = window; p_window = window;
if(p_window)
m_swapchain.Init(p_window); m_swapchain.Init(p_window);
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{ {
@@ -34,6 +33,23 @@ namespace mlx
} }
} }
void Renderer::Init(NonOwningPtr<Texture> render_target)
{
MLX_PROFILE_FUNCTION();
p_render_target = render_target;
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
m_image_available_semaphores[i] = kvfCreateSemaphore(RenderCore::Get().GetDevice());
DebugLog("Vulkan: image available semaphore created");
m_render_finished_semaphores[i] = kvfCreateSemaphore(RenderCore::Get().GetDevice());
DebugLog("Vulkan: render finished semaphore created");
m_cmd_buffers[i] = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
DebugLog("Vulkan: command buffer created");
m_cmd_fences[i] = kvfCreateFence(RenderCore::Get().GetDevice());
DebugLog("Vulkan: fence created");
}
}
void Renderer::BeginFrame() void Renderer::BeginFrame()
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();

View File

@@ -19,8 +19,6 @@ namespace mlx
void Swapchain::Init(NonOwningPtr<Window> window) void Swapchain::Init(NonOwningPtr<Window> window)
{ {
p_window = window; p_window = window;
m_surface = window->CreateVulkanSurface(RenderCore::Get().GetInstance());
DebugLog("Vulkan: surface created");
CreateSwapchain(); CreateSwapchain();
} }
@@ -53,11 +51,16 @@ namespace mlx
void Swapchain::Destroy() void Swapchain::Destroy()
{ {
if(m_swapchain == VK_NULL_HANDLE)
return;
RenderCore::Get().WaitDeviceIdle(); RenderCore::Get().WaitDeviceIdle();
for(Image& img : m_swapchain_images) for(Image& img : m_swapchain_images)
img.DestroyImageView(); img.DestroyImageView();
m_swapchain_images.clear();
kvfDestroySwapchainKHR(RenderCore::Get().GetDevice(), m_swapchain); kvfDestroySwapchainKHR(RenderCore::Get().GetDevice(), m_swapchain);
m_swapchain = VK_NULL_HANDLE;
DebugLog("Vulkan: swapchain destroyed");
RenderCore::Get().vkDestroySurfaceKHR(RenderCore::Get().GetInstance(), m_surface, nullptr); RenderCore::Get().vkDestroySurfaceKHR(RenderCore::Get().GetInstance(), m_surface, nullptr);
m_surface = VK_NULL_HANDLE; m_surface = VK_NULL_HANDLE;
@@ -66,10 +69,6 @@ namespace mlx
void Swapchain::CreateSwapchain() void Swapchain::CreateSwapchain()
{ {
for(Image& img : m_swapchain_images)
img.DestroyImageView();
m_swapchain_images.clear();
VkExtent2D extent; VkExtent2D extent;
do do
{ {
@@ -77,10 +76,11 @@ namespace mlx
extent = { size.x, size.y }; extent = { size.x, size.y };
} while(extent.width == 0 || extent.height == 0); } while(extent.width == 0 || extent.height == 0);
VkSwapchainKHR old_swapchain = m_swapchain; Destroy();
m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, VK_NULL_HANDLE, true);
if(old_swapchain != VK_NULL_HANDLE) m_surface = p_window->CreateVulkanSurface(RenderCore::Get().GetInstance());
kvfDestroySwapchainKHR(RenderCore::Get().GetDevice(), old_swapchain); DebugLog("Vulkan: surface created");
m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, VK_NULL_HANDLE, false);
m_images_count = kvfGetSwapchainImagesCount(m_swapchain); m_images_count = kvfGetSwapchainImagesCount(m_swapchain);
m_min_images_count = kvfGetSwapchainMinImagesCount(m_swapchain); m_min_images_count = kvfGetSwapchainMinImagesCount(m_swapchain);