fixing window resizing

This commit is contained in:
2024-12-04 14:04:44 +01:00
parent 122f4e8403
commit b7183a1058
9 changed files with 90 additions and 61 deletions

View File

@@ -9,7 +9,7 @@
Error("invalid window ptr (NULL)"); \ Error("invalid window ptr (NULL)"); \
return; \ return; \
} \ } \
else if(std::find_if(m_graphics.begin(), m_graphics.end(), [win](const std::unique_ptr<GraphicsSupport>& gs){ return *static_cast<int*>(win) == gs->GetID(); }) == m_graphics.end()) \ else if(std::find_if(m_graphics.begin(), m_graphics.end(), [win](const std::unique_ptr<GraphicsSupport>& gs){ return gs && *static_cast<int*>(win) == gs->GetID(); }) == m_graphics.end()) \
{ \ { \
Error("invalid window ptr"); \ Error("invalid window ptr"); \
return; \ return; \

View File

@@ -24,8 +24,8 @@ namespace mlx
GraphicPipeline() = default; GraphicPipeline() = default;
void Init(const GraphicPipelineDescriptor& descriptor, std::string_view debug_name); void Init(const GraphicPipelineDescriptor& descriptor, std::string_view debug_name);
bool BindPipeline(VkCommandBuffer command_buffer, std::size_t framebuffer_index, std::array<float, 4> clear) noexcept; bool BindPipeline(VkCommandBuffer cmd, std::size_t framebuffer_index, std::array<float, 4> clear) noexcept;
void EndPipeline(VkCommandBuffer command_buffer) noexcept override; void EndPipeline(VkCommandBuffer cmd) noexcept override;
void Destroy() noexcept; void Destroy() noexcept;
[[nodiscard]] inline VkPipeline GetPipeline() const override { return m_pipeline; } [[nodiscard]] inline VkPipeline GetPipeline() const override { return m_pipeline; }

View File

@@ -38,14 +38,19 @@ namespace mlx
switch(type) switch(type)
{ {
case LogType::Debug: std::cout << Ansi::blue << "[MLX Debug] " << Ansi::def << code_infos << message << std::endl; break; case LogType::Debug: std::cout << Ansi::blue << "[MLX Debug] "; break;
case LogType::Message: std::cout << Ansi::blue << "[MLX Message] " << Ansi::def << code_infos << message << '\n'; break; case LogType::Message: std::cout << Ansi::blue << "[MLX Message] "; break;
case LogType::Warning: std::cout << Ansi::magenta << "[MLX Warning] " << Ansi::def << code_infos << message << '\n'; break; case LogType::Warning: std::cout << Ansi::magenta << "[MLX Warning] "; break;
case LogType::Error: std::cerr << Ansi::red << "[MLX Error] " << Ansi::def << code_infos << message << '\n'; break; case LogType::Error: std::cerr << Ansi::red << "[MLX Error] "; break;
case LogType::FatalError: std::cerr << Ansi::red << "[MLX Fatal Error] " << Ansi::def << code_infos << message << '\n'; break; case LogType::FatalError: std::cerr << Ansi::red << "[MLX Fatal Error] "; break;
default: break; default: break;
} }
const std::chrono::zoned_time current_time{ std::chrono::current_zone(), std::chrono::floor<std::chrono::milliseconds>(std::chrono::system_clock::now()) };
std::cout << Ansi::yellow << std::format("[{0:%H:%M:%S}] ", current_time) << Ansi::def << code_infos << message << std::endl;
if(type == LogType::FatalError) if(type == LogType::FatalError)
{ {
std::cout << Ansi::bg_red << "Fatal Error: emergency exit" << Ansi::bg_def << std::endl; std::cout << Ansi::bg_red << "Fatal Error: emergency exit" << Ansi::bg_def << std::endl;

View File

@@ -26,17 +26,9 @@ namespace mlx
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
VkDescriptorPoolSize pool_sizes[] = { VkDescriptorPoolSize pool_sizes[] = {
{ VK_DESCRIPTOR_TYPE_SAMPLER, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_SETS_PER_POOL }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, MAX_SETS_PER_POOL }, { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, MAX_SETS_PER_POOL }, { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, MAX_SETS_PER_POOL }
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, MAX_SETS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, MAX_SETS_PER_POOL }
}; };
VkDescriptorPoolCreateInfo pool_info{}; VkDescriptorPoolCreateInfo pool_info{};

View File

@@ -50,8 +50,10 @@ namespace mlx
kvfGPipelineBuilderSetVertexInputs(builder, binding_description, attributes_description.data(), attributes_description.size()); kvfGPipelineBuilderSetVertexInputs(builder, binding_description, attributes_description.data(), attributes_description.size());
} }
m_pipeline = kvfCreateGraphicsPipeline(RenderCore::Get().GetDevice(), m_pipeline_layout, builder, m_renderpass); m_pipeline = kvfCreateGraphicsPipeline(RenderCore::Get().GetDevice(), VK_NULL_HANDLE, m_pipeline_layout, builder, m_renderpass);
DebugLog("Vulkan: graphics pipeline created"); #ifdef DEBUG
DebugLog("Vulkan: graphics pipeline created %", m_debug_name);
#endif
kvfDestroyGPipelineBuilder(builder); kvfDestroyGPipelineBuilder(builder);
#ifdef MLX_HAS_DEBUG_UTILS_FUNCTIONS #ifdef MLX_HAS_DEBUG_UTILS_FUNCTIONS
@@ -82,10 +84,10 @@ namespace mlx
#endif #endif
} }
bool GraphicPipeline::BindPipeline(VkCommandBuffer command_buffer, std::size_t framebuffer_index, std::array<float, 4> clear) noexcept bool GraphicPipeline::BindPipeline(VkCommandBuffer cmd, std::size_t framebuffer_index, std::array<float, 4> clear) noexcept
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
TransitionAttachments(command_buffer); TransitionAttachments(cmd);
VkFramebuffer fb = m_framebuffers[framebuffer_index]; VkFramebuffer fb = m_framebuffers[framebuffer_index];
VkExtent2D fb_extent = kvfGetFramebufferSize(fb); VkExtent2D fb_extent = kvfGetFramebufferSize(fb);
@@ -96,12 +98,12 @@ namespace mlx
viewport.height = fb_extent.height; viewport.height = fb_extent.height;
viewport.minDepth = 0.0f; viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f; viewport.maxDepth = 1.0f;
RenderCore::Get().vkCmdSetViewport(command_buffer, 0, 1, &viewport); RenderCore::Get().vkCmdSetViewport(cmd, 0, 1, &viewport);
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = { 0, 0 }; scissor.offset = { 0, 0 };
scissor.extent = fb_extent; scissor.extent = fb_extent;
RenderCore::Get().vkCmdSetScissor(command_buffer, 0, 1, &scissor); RenderCore::Get().vkCmdSetScissor(cmd, 0, 1, &scissor);
for(std::size_t i = 0; i < m_clears.size(); i++) for(std::size_t i = 0; i < m_clears.size(); i++)
{ {
@@ -111,15 +113,15 @@ namespace mlx
m_clears[i].color.float32[3] = clear[3]; m_clears[i].color.float32[3] = clear[3];
} }
kvfBeginRenderPass(m_renderpass, command_buffer, fb, fb_extent, m_clears.data(), m_clears.size()); kvfBeginRenderPass(m_renderpass, cmd, fb, fb_extent, m_clears.data(), m_clears.size());
RenderCore::Get().vkCmdBindPipeline(command_buffer, GetPipelineBindPoint(), GetPipeline()); RenderCore::Get().vkCmdBindPipeline(cmd, GetPipelineBindPoint(), GetPipeline());
return true; return true;
} }
void GraphicPipeline::EndPipeline(VkCommandBuffer command_buffer) noexcept void GraphicPipeline::EndPipeline(VkCommandBuffer cmd) noexcept
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
RenderCore::Get().vkCmdEndRenderPass(command_buffer); RenderCore::Get().vkCmdEndRenderPass(cmd);
} }
void GraphicPipeline::Destroy() noexcept void GraphicPipeline::Destroy() noexcept
@@ -127,24 +129,32 @@ namespace mlx
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
p_vertex_shader.reset(); p_vertex_shader.reset();
p_fragment_shader.reset(); p_fragment_shader.reset();
for(auto& fb : m_framebuffers) for(auto fb : m_framebuffers)
{ {
kvfDestroyFramebuffer(RenderCore::Get().GetDevice(), fb); kvfDestroyFramebuffer(RenderCore::Get().GetDevice(), fb);
DebugLog("Vulkan: framebuffer destroyed"); #ifdef DEBUG
DebugLog("Vulkan: framebuffer destroyed in %", m_debug_name);
#endif
} }
m_framebuffers.clear(); 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;
DebugLog("Vulkan: graphics pipeline layout destroyed"); #ifdef DEBUG
DebugLog("Vulkan: graphics pipeline layout destroyed %", m_debug_name);
#endif
kvfDestroyRenderPass(RenderCore::Get().GetDevice(), m_renderpass); kvfDestroyRenderPass(RenderCore::Get().GetDevice(), m_renderpass);
m_renderpass = VK_NULL_HANDLE; m_renderpass = VK_NULL_HANDLE;
DebugLog("Vulkan: renderpass destroyed"); #ifdef DEBUG
DebugLog("Vulkan: renderpass destroyed for %", m_debug_name);
#endif
kvfDestroyPipeline(RenderCore::Get().GetDevice(), m_pipeline); kvfDestroyPipeline(RenderCore::Get().GetDevice(), m_pipeline);
m_pipeline = VK_NULL_HANDLE; m_pipeline = VK_NULL_HANDLE;
DebugLog("Vulkan: graphics pipeline destroyed"); #ifdef DEBUG
DebugLog("Vulkan: graphics pipeline destroyed %", m_debug_name);
#endif
p_renderer = nullptr; p_renderer = nullptr;
m_clears.clear(); m_clears.clear();
@@ -192,7 +202,9 @@ namespace mlx
m_renderpass = kvfCreateRenderPassWithSubpassDependencies(RenderCore::Get().GetDevice(), attachments.data(), attachments.size(), GetPipelineBindPoint(), dependencies.data(), dependencies.size()); 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"); #ifdef DEBUG
DebugLog("Vulkan: renderpass created for %", m_debug_name);
#endif
if(p_renderer) if(p_renderer)
{ {
@@ -200,13 +212,17 @@ namespace mlx
{ {
attachment_views[0] = image.GetImageView(); 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() })); m_framebuffers.push_back(kvfCreateFramebuffer(RenderCore::Get().GetDevice(), m_renderpass, attachment_views.data(), attachment_views.size(), { .width = image.GetWidth(), .height = image.GetHeight() }));
DebugLog("Vulkan: framebuffer created"); #ifdef DEBUG
DebugLog("Vulkan: framebuffer created for %", m_debug_name);
#endif
} }
} }
for(NonOwningPtr<Texture> image : render_targets) for(NonOwningPtr<Texture> image : render_targets)
{ {
m_framebuffers.push_back(kvfCreateFramebuffer(RenderCore::Get().GetDevice(), m_renderpass, attachment_views.data(), attachment_views.size(), { .width = image->GetWidth(), .height = image->GetHeight() })); m_framebuffers.push_back(kvfCreateFramebuffer(RenderCore::Get().GetDevice(), m_renderpass, attachment_views.data(), attachment_views.size(), { .width = image->GetWidth(), .height = image->GetHeight() }));
DebugLog("Vulkan: framebuffer created"); #ifdef DEBUG
DebugLog("Vulkan: framebuffer created for %", m_debug_name);
#endif
} }
} }

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, "mlx_2d_render_pass" }); EventBus::RegisterListener({ functor, "mlx_2d_render_pass_" + std::to_string(reinterpret_cast<std::uintptr_t>(this)) });
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);
@@ -76,6 +76,9 @@ namespace mlx
pipeline_descriptor.color_attachments = { &render_target }; pipeline_descriptor.color_attachments = { &render_target };
pipeline_descriptor.clear_color_attachments = false; pipeline_descriptor.clear_color_attachments = false;
#ifdef DEBUG #ifdef DEBUG
if(renderer.GetWindow())
m_pipeline.Init(pipeline_descriptor, "mlx_2D_pass_" + renderer.GetWindow()->GetName());
else
m_pipeline.Init(pipeline_descriptor, "mlx_2D_pass"); m_pipeline.Init(pipeline_descriptor, "mlx_2D_pass");
#else #else
m_pipeline.Init(pipeline_descriptor, {}); m_pipeline.Init(pipeline_descriptor, {});

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, "mlx_final_pass" }); EventBus::RegisterListener({ functor, "mlx_final_pass_" + std::to_string(reinterpret_cast<std::uintptr_t>(this)) });
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);
} }
@@ -55,7 +55,10 @@ namespace mlx
pipeline_descriptor.renderer = &renderer; pipeline_descriptor.renderer = &renderer;
pipeline_descriptor.no_vertex_inputs = true; pipeline_descriptor.no_vertex_inputs = true;
#ifdef DEBUG #ifdef DEBUG
if(final_target)
m_pipeline.Init(pipeline_descriptor, "mlx_final_pass"); m_pipeline.Init(pipeline_descriptor, "mlx_final_pass");
else
m_pipeline.Init(pipeline_descriptor, "mlx_final_pass_" + renderer.GetWindow()->GetName());
#else #else
m_pipeline.Init(pipeline_descriptor, {}); m_pipeline.Init(pipeline_descriptor, {});
#endif #endif

View File

@@ -27,6 +27,7 @@ namespace mlx
if(m_resize) if(m_resize)
{ {
RenderCore::Get().WaitDeviceIdle(); RenderCore::Get().WaitDeviceIdle();
Destroy();
CreateSwapchain(); CreateSwapchain();
EventBus::SendBroadcast(Internal::ResizeEventBroadcast{}); EventBus::SendBroadcast(Internal::ResizeEventBroadcast{});
} }
@@ -76,8 +77,6 @@ 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);
Destroy();
m_surface = p_window->CreateVulkanSurface(RenderCore::Get().GetInstance()); m_surface = p_window->CreateVulkanSurface(RenderCore::Get().GetInstance());
DebugLog("Vulkan: surface created"); DebugLog("Vulkan: surface created");
m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, VK_NULL_HANDLE, false); m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, VK_NULL_HANDLE, false);

49
third_party/kvf.h vendored
View File

@@ -229,7 +229,7 @@ void kvfGPipelineBuilderSetVertexInputs(KvfGraphicsPipelineBuilder* builder, VkV
void kvfGPipelineBuilderAddShaderStage(KvfGraphicsPipelineBuilder* builder, VkShaderStageFlagBits stage, VkShaderModule module, const char* entry); void kvfGPipelineBuilderAddShaderStage(KvfGraphicsPipelineBuilder* builder, VkShaderStageFlagBits stage, VkShaderModule module, const char* entry);
void kvfGPipelineBuilderResetShaderStages(KvfGraphicsPipelineBuilder* builder); void kvfGPipelineBuilderResetShaderStages(KvfGraphicsPipelineBuilder* builder);
VkPipeline kvfCreateGraphicsPipeline(VkDevice device, VkPipelineLayout layout, KvfGraphicsPipelineBuilder* builder, VkRenderPass pass); VkPipeline kvfCreateGraphicsPipeline(VkDevice device, VkPipelineCache cache, VkPipelineLayout layout, KvfGraphicsPipelineBuilder* builder, VkRenderPass pass);
void kvfDestroyPipeline(VkDevice device, VkPipeline pipeline); void kvfDestroyPipeline(VkDevice device, VkPipeline pipeline);
void kvfCheckVk(VkResult result); void kvfCheckVk(VkResult result);
@@ -413,9 +413,9 @@ typedef struct __KvfDevice
{ {
VkSurfaceCapabilitiesKHR capabilities; VkSurfaceCapabilitiesKHR capabilities;
VkSurfaceFormatKHR* formats; VkSurfaceFormatKHR* formats;
VkPresentModeKHR* presentModes; VkPresentModeKHR* present_modes;
uint32_t formats_count; uint32_t formats_count;
uint32_t presentModes_count; uint32_t present_modes_count;
} __KvfSwapchainSupportInternal; } __KvfSwapchainSupportInternal;
typedef struct __KvfSwapchain typedef struct __KvfSwapchain
@@ -619,6 +619,7 @@ void __kvfDestroyDevice(VkDevice device)
if(__kvf_internal_devices_size == 0) if(__kvf_internal_devices_size == 0)
{ {
KVF_FREE(__kvf_internal_devices); KVF_FREE(__kvf_internal_devices);
__kvf_internal_devices = NULL;
__kvf_internal_devices_capacity = 0; __kvf_internal_devices_capacity = 0;
} }
return; return;
@@ -703,6 +704,7 @@ __KvfDevice* __kvfGetKvfDeviceFromVkCommandBuffer(VkCommandBuffer cmd)
if(__kvf_internal_swapchains_size == 0) if(__kvf_internal_swapchains_size == 0)
{ {
KVF_FREE(__kvf_internal_swapchains); KVF_FREE(__kvf_internal_swapchains);
__kvf_internal_swapchains = NULL;
__kvf_internal_swapchains_capacity = 0; __kvf_internal_swapchains_capacity = 0;
} }
return; return;
@@ -718,7 +720,6 @@ __KvfDevice* __kvfGetKvfDeviceFromVkCommandBuffer(VkCommandBuffer cmd)
if(__kvf_internal_swapchains[i].swapchain == swapchain) if(__kvf_internal_swapchains[i].swapchain == swapchain)
return &__kvf_internal_swapchains[i]; return &__kvf_internal_swapchains[i];
} }
puts("not found");
return NULL; return NULL;
} }
#endif #endif
@@ -729,7 +730,7 @@ void __kvfAddFramebufferToArray(VkFramebuffer framebuffer, VkExtent2D extent)
if(__kvf_internal_framebuffers_size == __kvf_internal_framebuffers_capacity) if(__kvf_internal_framebuffers_size == __kvf_internal_framebuffers_capacity)
{ {
// Resize the dynamic array if necessary // Resize the dynamic array if necessary
__kvf_internal_framebuffers_capacity += 2; __kvf_internal_framebuffers_capacity += 5;
__kvf_internal_framebuffers = (__KvfFramebuffer*)KVF_REALLOC(__kvf_internal_framebuffers, __kvf_internal_framebuffers_capacity * sizeof(__KvfFramebuffer)); __kvf_internal_framebuffers = (__KvfFramebuffer*)KVF_REALLOC(__kvf_internal_framebuffers, __kvf_internal_framebuffers_capacity * sizeof(__KvfFramebuffer));
} }
@@ -760,11 +761,13 @@ void __kvfDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer)
if(__kvf_internal_framebuffers_size == 0) if(__kvf_internal_framebuffers_size == 0)
{ {
KVF_FREE(__kvf_internal_framebuffers); KVF_FREE(__kvf_internal_framebuffers);
__kvf_internal_framebuffers = NULL;
__kvf_internal_framebuffers_capacity = 0; __kvf_internal_framebuffers_capacity = 0;
} }
return; return;
} }
} }
KVF_ASSERT(false && "could not find framebuffer");
} }
__KvfFramebuffer* __kvfGetKvfFramebufferFromVkFramebuffer(VkFramebuffer framebuffer) __KvfFramebuffer* __kvfGetKvfFramebufferFromVkFramebuffer(VkFramebuffer framebuffer)
@@ -1875,12 +1878,12 @@ void kvfDestroySemaphore(VkDevice device, VkSemaphore semaphore)
KVF_GET_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR)(physical, surface, &support.formats_count, support.formats); KVF_GET_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR)(physical, surface, &support.formats_count, support.formats);
} }
KVF_GET_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR)(physical, surface, &support.presentModes_count, NULL); KVF_GET_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR)(physical, surface, &support.present_modes_count, NULL);
if(support.presentModes_count != 0) if(support.present_modes_count != 0)
{ {
support.presentModes = (VkPresentModeKHR*)KVF_MALLOC(sizeof(VkPresentModeKHR) * support.presentModes_count); support.present_modes = (VkPresentModeKHR*)KVF_MALLOC(sizeof(VkPresentModeKHR) * support.present_modes_count);
KVF_ASSERT(support.presentModes != NULL && "allocation failed :("); KVF_ASSERT(support.present_modes != NULL && "allocation failed :(");
KVF_GET_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR)(physical, surface, &support.presentModes_count, support.presentModes); KVF_GET_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR)(physical, surface, &support.present_modes_count, support.present_modes);
} }
return support; return support;
} }
@@ -1897,13 +1900,21 @@ void kvfDestroySemaphore(VkDevice device, VkSemaphore semaphore)
VkPresentModeKHR __kvfChooseSwapPresentMode(__KvfSwapchainSupportInternal* support, bool try_vsync) VkPresentModeKHR __kvfChooseSwapPresentMode(__KvfSwapchainSupportInternal* support, bool try_vsync)
{ {
if(try_vsync == false) if(try_vsync)
return VK_PRESENT_MODE_IMMEDIATE_KHR; return VK_PRESENT_MODE_FIFO_KHR;
for(uint32_t i = 0; i < support->presentModes_count; i++) bool mailbox_supported = false;
bool immediate_supported = false;
for(uint32_t i = 0; i < support->present_modes_count; i++)
{ {
if(support->presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) if(support->present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
return support->presentModes[i]; mailbox_supported = true;
if(support->present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
immediate_supported = true;
} }
if(mailbox_supported)
return VK_PRESENT_MODE_MAILBOX_KHR;
if(immediate_supported)
return VK_PRESENT_MODE_IMMEDIATE_KHR; // Best mode for low latency
return VK_PRESENT_MODE_FIFO_KHR; return VK_PRESENT_MODE_FIFO_KHR;
} }
@@ -1920,7 +1931,7 @@ void kvfDestroySemaphore(VkDevice device, VkSemaphore semaphore)
__KvfSwapchainSupportInternal support = __kvfQuerySwapchainSupport(physical, surface); __KvfSwapchainSupportInternal support = __kvfQuerySwapchainSupport(physical, surface);
VkSurfaceFormatKHR surfaceFormat = __kvfChooseSwapSurfaceFormat(&support); VkSurfaceFormatKHR surfaceFormat = __kvfChooseSwapSurfaceFormat(&support);
VkPresentModeKHR presentMode = __kvfChooseSwapPresentMode(&support, try_vsync); VkPresentModeKHR present_mode = __kvfChooseSwapPresentMode(&support, try_vsync);
uint32_t image_count = support.capabilities.minImageCount + 1; uint32_t image_count = support.capabilities.minImageCount + 1;
if(support.capabilities.maxImageCount > 0 && image_count > support.capabilities.maxImageCount) if(support.capabilities.maxImageCount > 0 && image_count > support.capabilities.maxImageCount)
@@ -1950,7 +1961,7 @@ void kvfDestroySemaphore(VkDevice device, VkSemaphore semaphore)
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
createInfo.preTransform = support.capabilities.currentTransform; createInfo.preTransform = support.capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = presentMode; createInfo.presentMode = present_mode;
createInfo.clipped = VK_TRUE; createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = old_swapchain; createInfo.oldSwapchain = old_swapchain;
@@ -2968,7 +2979,7 @@ void kvfGPipelineBuilderResetShaderStages(KvfGraphicsPipelineBuilder* builder)
builder->shader_stages_count = 0; builder->shader_stages_count = 0;
} }
VkPipeline kvfCreateGraphicsPipeline(VkDevice device, VkPipelineLayout layout, KvfGraphicsPipelineBuilder* builder, VkRenderPass pass) VkPipeline kvfCreateGraphicsPipeline(VkDevice device, VkPipelineCache cache, VkPipelineLayout layout, KvfGraphicsPipelineBuilder* builder, VkRenderPass pass)
{ {
KVF_ASSERT(builder != NULL); KVF_ASSERT(builder != NULL);
KVF_ASSERT(device != VK_NULL_HANDLE); KVF_ASSERT(device != VK_NULL_HANDLE);
@@ -3020,7 +3031,7 @@ VkPipeline kvfCreateGraphicsPipeline(VkDevice device, VkPipelineLayout layout, K
KVF_ASSERT(kvf_device != NULL); KVF_ASSERT(kvf_device != NULL);
#endif #endif
VkPipeline pipeline; VkPipeline pipeline;
__kvfCheckVk(KVF_GET_DEVICE_FUNCTION(vkCreateGraphicsPipelines)(device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &pipeline)); __kvfCheckVk(KVF_GET_DEVICE_FUNCTION(vkCreateGraphicsPipelines)(device, cache, 1, &pipeline_info, NULL, &pipeline));
return pipeline; return pipeline;
} }