Skip to content

Commit

Permalink
vulkan swapchain repaired
Browse files Browse the repository at this point in the history
  • Loading branch information
Agrael1 committed Apr 17, 2024
1 parent 241474c commit 785d923
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 49 deletions.
2 changes: 2 additions & 0 deletions examples/hello-triangle-win32-t/include/example/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class App

private:
Window wnd;
uint32_t width;
uint32_t height;

wis::DebugMessenger info;

Expand Down
27 changes: 15 additions & 12 deletions examples/hello-triangle-win32-t/src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void DebugCallback(wis::Severity severity, const char* message, void* user_data)
}

Test::App::App(uint32_t width, uint32_t height)
: wnd(width, height, "VTest")
: wnd(width, height, "VTest"), width(width), height(height)
{
wis::LibLogger::SetLogLayer(std::make_shared<LogProvider>());

Expand Down Expand Up @@ -364,6 +364,9 @@ void Test::App::ProcessEvent(Event e)

void Test::App::OnResize(uint32_t width, uint32_t height)
{
if (width == this->width && height == this->height)
return;

auto result = swap.Resize(width, height);
if (result.status != wis::Status::Ok)
throw std::runtime_error("Failed to resize swapchain");
Expand Down Expand Up @@ -405,7 +408,7 @@ void Test::App::Frame()
},
},
back_buffers[swap.GetCurrentIndex()]);

wis::RenderPassRenderTargetDesc targets{
.target = render_targets[swap.GetCurrentIndex()],
.load_op = wis::LoadOperation::Clear,
Expand All @@ -417,27 +420,27 @@ void Test::App::Frame()
.target_count = 1,
.flags = wis::RenderPassFlags::None,
};

cmd_list.BeginRenderPass(&rp);
cmd_list.SetRootSignature(root);

wis::DescriptorBufferView desc_buffers[] = { desc_buffer, sampler_buffer };

cmd_list.SetDescriptorBuffers(desc_buffers, 2);
cmd_list.SetDescriptorTableOffset(0, desc_buffer, 0);
cmd_list.SetDescriptorTableOffset(1, sampler_buffer, 0);

cmd_list.SetRootConstants(&rotation, 1, 0, wis::ShaderStages::Vertex);

cmd_list.IASetPrimitiveTopology(wis::PrimitiveTopology::TriangleList);

cmd_list.IASetVertexBuffers(&vertex_binding, 1);
cmd_list.RSSetViewport({ 0, 0, float(wnd.GetWidth()), float(wnd.GetHeight()), 0, 1 });
cmd_list.RSSetScissor({ 0, 0, wnd.GetWidth(), wnd.GetHeight() });

cmd_list.DrawInstanced(3);
cmd_list.EndRenderPass();

cmd_list.TextureBarrier({
.sync_before = wis::BarrierSync::Draw,
.sync_after = wis::BarrierSync::All,
Expand All @@ -454,10 +457,10 @@ void Test::App::Frame()
},
back_buffers[swap.GetCurrentIndex()]);
cmd_list.Close();

wis::CommandListView lists[] = { cmd_list };
queue.ExecuteCommandLists(lists, 1);

auto result = swap.Present();
if (result.status != wis::Status::Ok && result.status != wis::Status::Occluded)
throw std::runtime_error("Failed to present swapchain");
Expand Down
4 changes: 2 additions & 2 deletions examples/shaders/forward/example.ps.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ struct PSInput
float2 tc : TEXCOORD0;
};

Texture2D<float4> texture0 : register(t0);
SamplerState samLinear : register(s0);
[[vk::binding(0,0)]]Texture2D<float4> texture0 : register(t0);
[[vk::binding(0,1)]] SamplerState samLinear : register(s0);

struct PSOutput
{
Expand Down
2 changes: 1 addition & 1 deletion wisdom/bindings/wisdom.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated by wisdom generator on 2024-04-03 14:55:55.0763695 GMT+2
// Generated by wisdom generator on 2024-04-04 00:00:18.1158629 GMT+2
#include "wisdom.h"
#include <wisdom/wisdom.hpp>

Expand Down
2 changes: 1 addition & 1 deletion wisdom/bindings/wisdom.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated by wisdom generator on 2024-04-03 14:55:55.0763695 GMT+2
// Generated by wisdom generator on 2024-04-04 00:00:18.1158629 GMT+2
#pragma once
#include <stdint.h>
#include <stdbool.h>
Expand Down
8 changes: 6 additions & 2 deletions wisdom/include/wisdom/vulkan/impl/vk_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,11 +1051,15 @@ wis::VKDevice::VKCreateSwapChain(wis::SharedSurface surface,
wis::detail::VKSwapChainCreateInfo sci{ std::move(surface), device, adapter.GetInternal().adapter, itable.vkGetPhysicalDeviceSurfaceCapabilitiesKHR, swapchain.release(),
cmd_buf, cmd_pool.release(), qpresent_queue, graphics_queue, *format, present_mode, stereo, desc->stereo };

auto rres = sci.InitSemaphores();
auto rres = sci.InitBackBuffers(swap_info.imageExtent);
if (rres.status != wis::Status::Ok)
return rres;

rres = sci.InitBackBuffers(swap_info.imageExtent);
rres = sci.InitSemaphores();
if (rres.status != wis::Status::Ok)
return rres;

rres = sci.AquireNextIndex();
if (rres.status != wis::Status::Ok)
return rres;

Expand Down
93 changes: 69 additions & 24 deletions wisdom/include/wisdom/vulkan/impl/vk_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
wis::Result wis::detail::VKSwapChainCreateInfo::InitBackBuffers(VkExtent2D image_size) noexcept
{
auto& table = device.table();
if (!fence) {
VkFenceCreateInfo fence_info{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
auto result = table.vkCreateFence(device.get(), &fence_info, nullptr, &fence);
if (!wis::succeeded(result))
return { wis::make_result<FUNC, "vkCreateFence failed">(result) };
}

uint32_t new_back_buffer_count = 0;
auto result = table.vkGetSwapchainImagesKHR(device.get(), swapchain, &new_back_buffer_count, nullptr);

Expand Down Expand Up @@ -91,58 +102,87 @@ wis::Result wis::detail::VKSwapChainCreateInfo::InitBackBuffers(VkExtent2D image
.signalSemaphoreCount = 0,
.pSignalSemaphores = nullptr,
};
table.vkQueueSubmit(present_queue, 1, &submit, nullptr);
table.vkQueueWaitIdle(present_queue);
table.vkQueueSubmit(present_queue, 1, &submit, fence);
table.vkWaitForFences(device.get(), 1, &fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
table.vkResetFences(device.get(), 1, &fence);

return AquireNextIndex();
return wis::success;
}

wis::Result wis::detail::VKSwapChainCreateInfo::AquireNextIndex() const noexcept
{
auto& table = device.table();
auto result = table.vkAcquireNextImageKHR(device.get(), swapchain, std::numeric_limits<uint64_t>::max(), present_semaphore, nullptr, &present_index);
auto& dtable = device.table();
auto result = dtable.vkAcquireNextImageKHR(device.get(), swapchain, std::numeric_limits<uint64_t>::max(), image_ready_semaphores[acquire_index], nullptr, &present_index);
return wis::succeeded(result) ? wis::success : wis::make_result<FUNC, "vkAcquireNextImageKHR failed">(result);
}
wis::Result wis::detail::VKSwapChainCreateInfo::InitSemaphores() noexcept
{
present_semaphores = wis::detail::make_unique_for_overwrite<VkSemaphore[]>(back_buffer_count);
if (!present_semaphores)
return { wis::make_result<FUNC, "failed to allocate present_semaphores array">(VK_ERROR_OUT_OF_HOST_MEMORY) };

image_ready_semaphores = wis::detail::make_unique_for_overwrite<VkSemaphore[]>(back_buffer_count);
if (!image_ready_semaphores)
return { wis::make_result<FUNC, "failed to allocate image_ready_semaphores array">(VK_ERROR_OUT_OF_HOST_MEMORY) };

auto& table = device.table();
VkSemaphoreCreateInfo semaphore_info{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
auto result = table.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &present_semaphore);
if (!wis::succeeded(result))
return { wis::make_result<FUNC, "vkCreateSemaphore failed for present_semaphore">(result) };

result = table.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &graphics_semaphore);
return wis::succeeded(result) ? wis::success : wis::make_result<FUNC, "vkCreateSemaphore failed for graphics_semaphore">(result);
for (uint32_t n = 0; n < back_buffer_count; n++) {
auto result = table.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &present_semaphores[n]);
if (!wis::succeeded(result))
return { wis::make_result<FUNC, "vkCreateSemaphore failed for present_semaphore">(result) };
}
for (uint32_t n = 0; n < back_buffer_count; n++) {
auto result = table.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &image_ready_semaphores[n]);
if (!wis::succeeded(result))
return { wis::make_result<FUNC, "vkCreateSemaphore failed for image_ready_semaphore">(result) };
}
return wis::success;
}

void wis::detail::VKSwapChainCreateInfo::ReleaseSemaphore() const noexcept
void wis::detail::VKSwapChainCreateInfo::ReleaseSemaphores() noexcept
{
auto& dtable = device.table();
dtable.vkQueueWaitIdle(present_queue);
dtable.vkQueueWaitIdle(graphics_queue);

dtable.vkQueueSubmit(graphics_queue, 0, nullptr, fence);
dtable.vkWaitForFences(device.get(), 1, &fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
dtable.vkResetFences(device.get(), 1, &fence);

dtable.vkQueueSubmit(present_queue, 0, nullptr, fence);
dtable.vkWaitForFences(device.get(), 1, &fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
dtable.vkResetFences(device.get(), 1, &fence);

if (fence) {
dtable.vkDestroyFence(device.get(), fence, nullptr);
fence = nullptr;
}
}

wis::Result wis::VKSwapChain::Resize(uint32_t width, uint32_t height) noexcept
{
auto& dtable = device.table();

VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

VkSubmitInfo wait{
VkSubmitInfo wait_desc{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &present_semaphore.handle,
.pWaitSemaphores = &image_ready_semaphores[acquire_index],
.pWaitDstStageMask = &wait_stages,
};
dtable.vkQueueSubmit(graphics_queue, 1, &wait, nullptr);
dtable.vkQueueSubmit(graphics_queue, 1, &wait_desc, fence);
dtable.vkWaitForFences(device.get(), 1, &fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
dtable.vkResetFences(device.get(), 1, &fence);

dtable.vkQueueWaitIdle(present_queue);
dtable.vkQueueWaitIdle(graphics_queue);
dtable.vkQueueSubmit(present_queue, 0, nullptr, fence);
dtable.vkWaitForFences(device.get(), 1, &fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
dtable.vkResetFences(device.get(), 1, &fence);

VkSurfaceCapabilitiesKHR caps{};
getCaps(adapter, surface.get(), &caps);
Expand Down Expand Up @@ -181,7 +221,10 @@ wis::Result wis::VKSwapChain::Resize(uint32_t width, uint32_t height) noexcept
dtable.vkDestroySwapchainKHR(device.get(), old_swapchain, nullptr);

auto rres = InitBackBuffers(desc.imageExtent);
return rres;
if (rres.status != wis::Status::Ok)
return rres;

return AquireNextIndex();
}

wis::Result wis::VKSwapChain::Present() const noexcept
Expand All @@ -194,18 +237,18 @@ wis::Result wis::VKSwapChain::Present() const noexcept
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &present_semaphore.handle,
.pWaitSemaphores = &image_ready_semaphores[acquire_index],
.pWaitDstStageMask = &wait_stages,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &graphics_semaphore.handle,
.pSignalSemaphores = &present_semaphores[present_index],
};
dtable.vkQueueSubmit(graphics_queue, 1, &desc, nullptr);

VkPresentInfoKHR present_info{
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = nullptr,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &graphics_semaphore.handle,
.pWaitSemaphores = &present_semaphores[present_index],
.swapchainCount = 1,
.pSwapchains = &swapchain.handle,
.pImageIndices = &present_index,
Expand All @@ -218,11 +261,13 @@ wis::Result wis::VKSwapChain::Present() const noexcept
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &present_semaphore.handle,
.pSignalSemaphores = &image_ready_semaphores[acquire_index],
};
dtable.vkQueueSubmit(present_queue, 1, &wait, nullptr);
return wis::make_result<FUNC, "vkQueuePresentKHR failed">(result);
}

acquire_index = (acquire_index + 1) % back_buffer_count;

return AquireNextIndex();
}
21 changes: 14 additions & 7 deletions wisdom/include/wisdom/vulkan/vk_swapchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ struct VKSwapChainCreateInfo {
h::VkCommandPool command_pool = nullptr;
h::VkQueue present_queue = nullptr;
h::VkQueue graphics_queue = nullptr;
h::VkSemaphore present_semaphore = nullptr; // if signalled, it means the presentation is done
h::VkSemaphore graphics_semaphore = nullptr; // if signalled, it means the rendering is done

std::unique_ptr<VkSemaphore[]> present_semaphores = nullptr; // if signalled, it means the presentation is required
std::unique_ptr<VkSemaphore[]> image_ready_semaphores = nullptr; // if signalled, it means the rendering is available
std::unique_ptr<VKTexture[]> back_buffers;
h::VkFence fence = nullptr; //only used for initialization and resizing

VkSurfaceFormatKHR format{};

uint32_t back_buffer_count = 0;
Expand All @@ -32,6 +33,7 @@ struct VKSwapChainCreateInfo {

bool stereo = false;
bool stereo_requested = false;
mutable uint8_t acquire_index = 0;

public:
VKSwapChainCreateInfo() = default;
Expand Down Expand Up @@ -75,9 +77,14 @@ struct VKSwapChainCreateInfo {
auto& table = device.table();
auto hdevice = device.get();

ReleaseSemaphore();
table.vkDestroySemaphore(hdevice, present_semaphore, nullptr);
table.vkDestroySemaphore(hdevice, graphics_semaphore, nullptr);
ReleaseSemaphores();

for (uint32_t n = 0; n < back_buffer_count; n++) {
table.vkDestroySemaphore(hdevice, present_semaphores[n], nullptr);
}
for (uint32_t n = 0; n < 2; n++) {
table.vkDestroySemaphore(hdevice, image_ready_semaphores[n], nullptr);
}
table.vkDestroyCommandPool(hdevice, command_pool, nullptr);
table.vkDestroySwapchainKHR(hdevice, swapchain, nullptr);
}
Expand All @@ -86,7 +93,7 @@ struct VKSwapChainCreateInfo {
[[nodiscard]] WIS_INLINE wis::Result InitSemaphores() noexcept;
[[nodiscard]] WIS_INLINE wis::Result InitBackBuffers(VkExtent2D image_size) noexcept;
[[nodiscard]] WIS_INLINE wis::Result AquireNextIndex() const noexcept;
WIS_INLINE void ReleaseSemaphore() const noexcept;
WIS_INLINE void ReleaseSemaphores() noexcept;
};
} // namespace detail

Expand Down

0 comments on commit 785d923

Please sign in to comment.