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; auto extension_properties = physical_device.enumerateDeviceExtensionProperties().value;
physical_device.getProperties(&physical_device_props); 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::DeviceQueueCreateInfo dqci({}, graphics_queue_family_index, priorities);
vk::DeviceCreateInfo dci({}, dqci, {}, required_extensions); 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; device = physical_device.createDevice(dci).value;
queue = device.getQueue(graphics_queue_family_index, 0); queue = device.getQueue(graphics_queue_family_index, 0);
@ -289,7 +314,7 @@ bool Context::init_vma()
bool Context::create_swapchain(int width, int height) bool Context::create_swapchain(int width, int height)
{ {
wait_idle(); 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); return swapchain->create(2, width, height);
} }

View File

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

View File

@ -1,15 +1,17 @@
#include "vulkan_swapchain.hpp" #include "vulkan_swapchain.hpp"
#include "vulkan_context.hpp"
namespace Vulkan namespace Vulkan
{ {
Swapchain::Swapchain(vk::Device device_, vk::PhysicalDevice physical_device_, vk::Queue queue_, vk::SurfaceKHR surface_, vk::CommandPool command_pool_) Swapchain::Swapchain(Context &context_)
: surface(surface_), : context(context_)
command_pool(command_pool_),
physical_device(physical_device_),
queue(queue_)
{ {
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(); create_render_pass();
end_render_pass_function = nullptr; end_render_pass_function = nullptr;
} }
@ -351,13 +353,22 @@ bool Swapchain::swap()
vk::SwapchainPresentModeInfoEXT present_mode_info; vk::SwapchainPresentModeInfoEXT present_mode_info;
auto present_mode = get_present_mode(); auto present_mode = get_present_mode();
present_mode_info.setPresentModes(present_mode); present_mode_info.setPresentModes(present_mode);
present_info.setPNext(&present_mode_info);
auto &present_fence = image_data[current_swapchain_image].fence.get(); auto &present_fence = image_data[current_swapchain_image].fence.get();
device.resetFences(present_fence); device.resetFences(present_fence);
vk::SwapchainPresentFenceInfoEXT present_fence_info(present_fence); vk::SwapchainPresentFenceInfoEXT present_fence_info(present_fence);
present_info.setPNext(&present_mode_info);
present_mode_info.setPNext(&present_fence_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); vk::Result result = queue.presentKHR(present_info);
if (result == vk::Result::eErrorOutOfDateKHR) if (result == vk::Result::eErrorOutOfDateKHR)
{ {
@ -424,6 +435,15 @@ void Swapchain::wait_on_frames()
{ {
for (auto i = 0; i < image_data.size(); i++) for (auto i = 0; i < image_data.size(); i++)
wait_on_frame(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() vk::Extent2D Swapchain::get_extents()

View File

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