Compare commits

...

6 commits

Author SHA1 Message Date
BearOso
a9e64edf73 Vulkan/Win32: Fix compile error. 2024-06-13 16:50:12 -05:00
BearOso
008cbcd1a1 Vulkan: Simplify set_vsync. Remove relaxed fifo.
It looks like relaxed fifo tears when refresh rate doesn't
match because it always misses a refresh interval.
2024-06-13 16:17:36 -05:00
BearOso
3980a9d6d4 Vulkan: Fix inverted logic. 2024-06-13 15:56:04 -05:00
BearOso
5c78493f4e Vulkan: Add device wait back to swapchain recreation. 2024-06-13 14:39:36 -05:00
BearOso
33e40a8f16 Vulkan: Refactor present modes. Add relaxed. 2024-06-13 11:37:00 -05:00
BearOso
2e25b70cf0 Vulkan: Associate new fence with swapchain image, not frame resources. 2024-06-13 11:16:36 -05:00
4 changed files with 56 additions and 59 deletions

View file

@ -233,7 +233,7 @@ bool Context::init_device(int preferred_device)
physical_device = device_list[preferred_device]; physical_device = device_list[preferred_device];
} }
if (physical_device != nullptr) if (physical_device == nullptr)
{ {
for (auto &device : device_list) for (auto &device : device_list)
{ {

View file

@ -18,13 +18,9 @@ Swapchain::~Swapchain()
{ {
} }
bool Swapchain::set_vsync(bool new_setting) void Swapchain::set_vsync(bool new_setting)
{ {
if (new_setting == vsync)
return false;
vsync = new_setting; vsync = new_setting;
return true;
} }
void Swapchain::on_render_pass_end(std::function<void ()> function) void Swapchain::on_render_pass_end(std::function<void ()> function)
@ -80,14 +76,39 @@ void Swapchain::create_render_pass()
bool Swapchain::recreate(int new_width, int new_height) bool Swapchain::recreate(int new_width, int new_height)
{ {
if (swapchain_object) if (swapchain_object)
{
device.waitIdle();
wait_on_frames(); wait_on_frames();
}
return create(num_swapchain_images, new_width, new_height); return create(num_swapchain_images, new_width, new_height);
} }
vk::Image Swapchain::get_image() vk::Image Swapchain::get_image()
{ {
return imageviewfbs[current_swapchain_image].image; return image_data[current_swapchain_image].image;
}
template<typename T>
static bool vector_find(std::vector<T> haystack, T&& needle)
{
for (auto &elem : haystack)
if (elem == needle)
return true;
return false;
}
vk::PresentModeKHR Swapchain::get_present_mode() {
auto present_mode = vk::PresentModeKHR::eFifo;
if (!vsync) {
if (supports_mailbox)
present_mode = vk::PresentModeKHR::eMailbox;
if (supports_immediate)
present_mode = vk::PresentModeKHR::eImmediate;
}
return present_mode;
} }
bool Swapchain::check_and_resize(int width, int height) bool Swapchain::check_and_resize(int width, int height)
@ -116,7 +137,7 @@ bool Swapchain::check_and_resize(int width, int height)
bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width, int new_height) bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width, int new_height)
{ {
frames.clear(); frames.clear();
imageviewfbs.clear(); image_data.clear();
auto surface_capabilities = physical_device.getSurfaceCapabilitiesKHR(surface).value; auto surface_capabilities = physical_device.getSurfaceCapabilitiesKHR(surface).value;
@ -165,21 +186,9 @@ bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width,
extents.height = surface_capabilities.minImageExtent.height; extents.height = surface_capabilities.minImageExtent.height;
auto present_modes = physical_device.getSurfacePresentModesKHR(surface).value; auto present_modes = physical_device.getSurfacePresentModesKHR(surface).value;
supports_mailbox = supports_mailbox = vector_find(present_modes, vk::PresentModeKHR::eMailbox);
std::find(present_modes.begin(), present_modes.end(), supports_immediate = vector_find(present_modes, vk::PresentModeKHR::eImmediate);
vk::PresentModeKHR::eMailbox) != present_modes.end(); supports_relaxed = vector_find(present_modes, vk::PresentModeKHR::eFifoRelaxed);
supports_immediate =
std::find(present_modes.begin(), present_modes.end(),
vk::PresentModeKHR::eImmediate) != present_modes.end();
auto present_mode = vk::PresentModeKHR::eFifo;
if (!vsync)
{
if (supports_mailbox)
present_mode = vk::PresentModeKHR::eMailbox;
if (supports_immediate)
present_mode = vk::PresentModeKHR::eImmediate;
}
auto swapchain_maintenance_info = vk::SwapchainPresentModesCreateInfoEXT{} auto swapchain_maintenance_info = vk::SwapchainPresentModesCreateInfoEXT{}
.setPresentModes(present_modes); .setPresentModes(present_modes);
@ -193,7 +202,7 @@ bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width,
.setImageUsage(vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc) .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc)
.setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque) .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
.setClipped(true) .setClipped(true)
.setPresentMode(present_mode) .setPresentMode(get_present_mode())
.setSurface(surface) .setSurface(surface)
.setPreTransform(vk::SurfaceTransformFlagBitsKHR::eIdentity) .setPreTransform(vk::SurfaceTransformFlagBitsKHR::eIdentity)
.setImageArrayLayers(1) .setImageArrayLayers(1)
@ -224,7 +233,7 @@ bool Swapchain::create_resources()
auto command_buffers = device.allocateCommandBuffersUnique(command_buffer_allocate_info).value; auto command_buffers = device.allocateCommandBuffersUnique(command_buffer_allocate_info).value;
frames.resize(num_swapchain_images); frames.resize(num_swapchain_images);
imageviewfbs.resize(num_swapchain_images); image_data.resize(num_swapchain_images);
vk::FenceCreateInfo fence_create_info(vk::FenceCreateFlagBits::eSignaled); vk::FenceCreateInfo fence_create_info(vk::FenceCreateFlagBits::eSignaled);
@ -234,7 +243,6 @@ bool Swapchain::create_resources()
auto &frame = frames[i]; auto &frame = frames[i];
frame.command_buffer = std::move(command_buffers[i]); frame.command_buffer = std::move(command_buffers[i]);
frame.fence = device.createFenceUnique(fence_create_info).value; frame.fence = device.createFenceUnique(fence_create_info).value;
frame.freeable = device.createFenceUnique(fence_create_info).value;
frame.acquire = device.createSemaphoreUnique({}).value; frame.acquire = device.createSemaphoreUnique({}).value;
frame.complete = device.createSemaphoreUnique({}).value; frame.complete = device.createSemaphoreUnique({}).value;
} }
@ -242,7 +250,7 @@ bool Swapchain::create_resources()
for (unsigned int i = 0; i < num_swapchain_images; i++) for (unsigned int i = 0; i < num_swapchain_images; i++)
{ {
// Create resources associated with swapchain images // Create resources associated with swapchain images
auto &image = imageviewfbs[i]; auto &image = image_data[i];
image.image = swapchain_images[i]; image.image = swapchain_images[i];
auto image_view_create_info = vk::ImageViewCreateInfo{} auto image_view_create_info = vk::ImageViewCreateInfo{}
.setImage(swapchain_images[i]) .setImage(swapchain_images[i])
@ -259,6 +267,8 @@ bool Swapchain::create_resources()
.setLayers(1) .setLayers(1)
.setRenderPass(render_pass.get()); .setRenderPass(render_pass.get());
image.framebuffer = device.createFramebufferUnique(framebuffer_create_info).value; image.framebuffer = device.createFramebufferUnique(framebuffer_create_info).value;
image.fence = device.createFenceUnique(fence_create_info).value;
} }
current_swapchain_image = 0; current_swapchain_image = 0;
@ -277,7 +287,7 @@ bool Swapchain::begin_frame()
auto &frame = frames[current_frame]; auto &frame = frames[current_frame];
auto result = device.waitForFences({ frame.fence.get(), frame.freeable.get() }, true, 33333333); auto result = device.waitForFences({ frame.fence.get() }, true, 33333333);
if (result != vk::Result::eSuccess) if (result != vk::Result::eSuccess)
{ {
printf("Timed out waiting for fence.\n"); printf("Timed out waiting for fence.\n");
@ -339,19 +349,13 @@ bool Swapchain::swap()
.setImageIndices(current_swapchain_image); .setImageIndices(current_swapchain_image);
vk::SwapchainPresentModeInfoEXT present_mode_info; vk::SwapchainPresentModeInfoEXT present_mode_info;
vk::PresentModeKHR present_mode = vk::PresentModeKHR::eFifo; auto present_mode = get_present_mode();
if (!vsync)
{
if (supports_mailbox)
present_mode = vk::PresentModeKHR::eMailbox;
if (supports_immediate)
present_mode = vk::PresentModeKHR::eImmediate;
}
present_mode_info.setPresentModes(present_mode); present_mode_info.setPresentModes(present_mode);
present_info.setPNext(&present_mode_info); present_info.setPNext(&present_mode_info);
device.resetFences(frames[current_frame].freeable.get()); auto &present_fence = image_data[current_swapchain_image].fence.get();
vk::SwapchainPresentFenceInfoEXT present_fence_info(frames[current_frame].freeable.get()); device.resetFences(present_fence);
vk::SwapchainPresentFenceInfoEXT present_fence_info(present_fence);
present_mode_info.setPNext(&present_fence_info); present_mode_info.setPNext(&present_fence_info);
vk::Result result = queue.presentKHR(present_info); vk::Result result = queue.presentKHR(present_info);
@ -376,7 +380,7 @@ bool Swapchain::end_frame()
vk::Framebuffer Swapchain::get_framebuffer() vk::Framebuffer Swapchain::get_framebuffer()
{ {
return imageviewfbs[current_swapchain_image].framebuffer.get(); return image_data[current_swapchain_image].framebuffer.get();
} }
vk::CommandBuffer &Swapchain::get_cmd() vk::CommandBuffer &Swapchain::get_cmd()
@ -393,7 +397,7 @@ void Swapchain::begin_render_pass()
auto render_pass_begin_info = vk::RenderPassBeginInfo{} auto render_pass_begin_info = vk::RenderPassBeginInfo{}
.setRenderPass(render_pass.get()) .setRenderPass(render_pass.get())
.setFramebuffer(imageviewfbs[current_swapchain_image].framebuffer.get()) .setFramebuffer(image_data[current_swapchain_image].framebuffer.get())
.setRenderArea(vk::Rect2D({}, extents)) .setRenderArea(vk::Rect2D({}, extents))
.setClearValues(value); .setClearValues(value);
get_cmd().beginRenderPass(render_pass_begin_info, vk::SubpassContents::eInline); get_cmd().beginRenderPass(render_pass_begin_info, vk::SubpassContents::eInline);
@ -412,13 +416,13 @@ void Swapchain::end_render_pass()
bool Swapchain::wait_on_frame(int frame_num) bool Swapchain::wait_on_frame(int frame_num)
{ {
auto result = device.waitForFences({ frames[frame_num].fence.get(), frames[frame_num].freeable.get() }, true, 133000000); auto result = device.waitForFences({ image_data[frame_num].fence.get() }, true, 33000000);
return (result == vk::Result::eSuccess); return (result == vk::Result::eSuccess);
} }
void Swapchain::wait_on_frames() void Swapchain::wait_on_frames()
{ {
for (auto i = 0; i < frames.size(); i++) for (auto i = 0; i < image_data.size(); i++)
wait_on_frame(i); wait_on_frame(i);
} }

View file

@ -27,10 +27,10 @@ class Swapchain
void end_frame_without_swap(); void end_frame_without_swap();
bool swap(); bool swap();
void wait_on_frames(); void wait_on_frames();
// Returns true if vsync setting was changed, false if it was the same void set_vsync(bool on);
bool set_vsync(bool on);
void on_render_pass_end(std::function<void()> function); void on_render_pass_end(std::function<void()> function);
int get_num_frames() { return num_swapchain_images; } int get_num_frames() { return num_swapchain_images; }
vk::PresentModeKHR get_present_mode();
vk::Image get_image(); vk::Image get_image();
vk::Framebuffer get_framebuffer(); vk::Framebuffer get_framebuffer();
@ -45,15 +45,15 @@ class Swapchain
struct Frame struct Frame
{ {
vk::UniqueFence fence; vk::UniqueFence fence;
vk::UniqueFence freeable;
vk::UniqueSemaphore acquire; vk::UniqueSemaphore acquire;
vk::UniqueSemaphore complete; vk::UniqueSemaphore complete;
vk::UniqueCommandBuffer command_buffer; vk::UniqueCommandBuffer command_buffer;
}; };
struct ImageViewFB struct ImageData
{ {
vk::Image image; vk::Image image;
vk::UniqueFence fence;
vk::UniqueImageView image_view; vk::UniqueImageView image_view;
vk::UniqueFramebuffer framebuffer; vk::UniqueFramebuffer framebuffer;
}; };
@ -69,8 +69,9 @@ class Swapchain
bool vsync = true; bool vsync = true;
bool supports_immediate = false; bool supports_immediate = false;
bool supports_mailbox = false; bool supports_mailbox = false;
bool supports_relaxed = false;
std::vector<Frame> frames; std::vector<Frame> frames;
std::vector<ImageViewFB> imageviewfbs; std::vector<ImageData> image_data;
vk::Device device; vk::Device device;
vk::SurfaceKHR surface; vk::SurfaceKHR surface;

View file

@ -70,6 +70,8 @@ bool CVulkan::Initialize(HWND hWnd)
return false; return false;
} }
context->swapchain->set_vsync(GUI.Vsync);
if (!Settings.AutoDisplayMessages) if (!Settings.AutoDisplayMessages)
{ {
Settings.DisplayIndicators = true; Settings.DisplayIndicators = true;
@ -91,11 +93,6 @@ bool CVulkan::Initialize(HWND hWnd)
} }
} }
if (context->swapchain->set_vsync(GUI.Vsync))
{
context->recreate_swapchain();
}
simple_output = std::make_unique<Vulkan::SimpleOutput>(context.get(), vk::Format::eR5G6B5UnormPack16); simple_output = std::make_unique<Vulkan::SimpleOutput>(context.get(), vk::Format::eR5G6B5UnormPack16);
return true; return true;
@ -181,9 +178,7 @@ bool CVulkan::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight)
if (!context) if (!context)
return false; return false;
bool vsync_changed = context->swapchain->set_vsync(GUI.Vsync); if (newWidth != current_width || newHeight != current_height)
if (newWidth != current_width || newHeight != current_height || vsync_changed)
{ {
context->recreate_swapchain(newWidth, newHeight); context->recreate_swapchain(newWidth, newHeight);
context->wait_idle(); context->wait_idle();
@ -218,10 +213,7 @@ bool CVulkan::ApplyDisplayChanges(void)
current_shadername = shadername; current_shadername = shadername;
} }
if (context->swapchain->set_vsync(GUI.Vsync)) context->swapchain->set_vsync(GUI.Vsync);
{
context->recreate_swapchain();
}
return true; return true;
} }