vulkan: Add support for VK_KHR_present_wait

May have a tighter CPU-GPU sync for lower latency.
This commit is contained in:
BearOso 2024-09-02 13:15:37 -05:00
parent 8559143576
commit c8895c8cdb
4 changed files with 60 additions and 13 deletions

View File

@ -245,6 +245,23 @@ bool Context::init_device(int preferred_device)
}
}
std::vector<const char *> present_wait_extensions =
{
VK_KHR_PRESENT_ID_EXTENSION_NAME,
VK_KHR_PRESENT_WAIT_EXTENSION_NAME
};
if (check_extensions(present_wait_extensions, physical_device))
{
for (auto &ext : present_wait_extensions)
required_extensions.push_back(ext);
have_VK_KHR_present_wait = true;
}
else
{
have_VK_KHR_present_wait = false;
}
auto extension_properties = physical_device.enumerateDeviceExtensionProperties().value;
physical_device.getProperties(&physical_device_props);
@ -256,6 +273,14 @@ bool Context::init_device(int preferred_device)
vk::DeviceQueueCreateInfo dqci({}, graphics_queue_family_index, priorities);
vk::DeviceCreateInfo dci({}, dqci, {}, required_extensions);
vk::PhysicalDevicePresentWaitFeaturesKHR physical_device_present_wait_feature(true);
vk::PhysicalDevicePresentIdFeaturesKHR physical_device_present_id_feature(true);
if (have_VK_KHR_present_wait)
{
dci.setPNext(&physical_device_present_wait_feature);
physical_device_present_wait_feature.setPNext(&physical_device_present_id_feature);
}
device = physical_device.createDevice(dci).value;
queue = device.getQueue(graphics_queue_family_index, 0);
@ -289,7 +314,7 @@ bool Context::init_vma()
bool Context::create_swapchain(int width, int height)
{
wait_idle();
swapchain = std::make_unique<Swapchain>(device, physical_device, queue, surface.get(), command_pool.get());
swapchain = std::make_unique<Swapchain>(*this);
return swapchain->create(2, width, height);
}

View File

@ -51,6 +51,8 @@ class Context
vk::PhysicalDeviceProperties physical_device_props;
vk::UniqueSurfaceKHR surface;
bool have_VK_KHR_present_wait = false;
private:
bool init_vma();
bool init_device(int preferred_device = 0);

View File

@ -1,15 +1,17 @@
#include "vulkan_swapchain.hpp"
#include "vulkan_context.hpp"
namespace Vulkan
{
Swapchain::Swapchain(vk::Device device_, vk::PhysicalDevice physical_device_, vk::Queue queue_, vk::SurfaceKHR surface_, vk::CommandPool command_pool_)
: surface(surface_),
command_pool(command_pool_),
physical_device(physical_device_),
queue(queue_)
Swapchain::Swapchain(Context &context_)
: context(context_)
{
device = device_;
device = context.device;
queue = context.queue;
surface = context.surface.get();
physical_device = context.physical_device;
command_pool = context.command_pool.get();
create_render_pass();
end_render_pass_function = nullptr;
}
@ -351,13 +353,22 @@ bool Swapchain::swap()
vk::SwapchainPresentModeInfoEXT present_mode_info;
auto present_mode = get_present_mode();
present_mode_info.setPresentModes(present_mode);
present_info.setPNext(&present_mode_info);
auto &present_fence = image_data[current_swapchain_image].fence.get();
device.resetFences(present_fence);
vk::SwapchainPresentFenceInfoEXT present_fence_info(present_fence);
present_info.setPNext(&present_mode_info);
present_mode_info.setPNext(&present_fence_info);
vk::PresentIdKHR present_id;
if (context.have_VK_KHR_present_wait)
{
presentation_id++;
present_id.setPresentIds(presentation_id);
present_fence_info.setPNext(&present_id);
}
vk::Result result = queue.presentKHR(present_info);
if (result == vk::Result::eErrorOutOfDateKHR)
{
@ -424,6 +435,15 @@ void Swapchain::wait_on_frames()
{
for (auto i = 0; i < image_data.size(); i++)
wait_on_frame(i);
if (context.have_VK_KHR_present_wait)
{
auto result = device.waitForPresentKHR(swapchain_object.get(), presentation_id, 16666666);
if (result != vk::Result::eSuccess)
{
printf("Error waiting on present: %s\n", vk::to_string(result).c_str());
}
}
}
vk::Extent2D Swapchain::get_extents()

View File

@ -6,14 +6,12 @@
namespace Vulkan
{
class Context;
class Swapchain
{
public:
Swapchain(vk::Device device,
vk::PhysicalDevice physical_device,
vk::Queue queue,
vk::SurfaceKHR surface,
vk::CommandPool command_pool);
Swapchain(Context &);
~Swapchain();
bool create(unsigned int num_frames, int width = -1, int height = -1);
bool recreate(int width = -1, int height = -1);
@ -66,6 +64,7 @@ class Swapchain
unsigned int current_frame = 0;
unsigned int current_swapchain_image = 0;
unsigned int num_swapchain_images = 0;
uint64_t presentation_id = 0;
bool vsync = true;
bool supports_immediate = false;
bool supports_mailbox = false;
@ -73,6 +72,7 @@ class Swapchain
std::vector<Frame> frames;
std::vector<ImageData> image_data;
Vulkan::Context &context;
vk::Device device;
vk::SurfaceKHR surface;
vk::CommandPool command_pool;