mirror of https://github.com/snes9xgit/snes9x.git
Vulkan: Separate context, surface, and swapchain.
This commit is contained in:
parent
72e4946410
commit
febcf27482
|
@ -1,6 +1,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
#include "vulkan_context.hpp"
|
#include "vulkan_context.hpp"
|
||||||
|
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
|
@ -93,45 +94,61 @@ std::vector<std::string> Vulkan::Context::get_device_list()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
||||||
bool Context::init_win32(HINSTANCE hinstance, HWND hwnd, int preferred_device)
|
bool Context::init_win32()
|
||||||
{
|
{
|
||||||
instance = create_instance_preamble(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
instance = create_instance_preamble(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||||
if (!instance)
|
if (!instance)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
return init(preferred_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Context::create_win32_surface(HINSTANCE hinstance, HWND hwnd)
|
||||||
|
{
|
||||||
auto win32_surface_create_info = vk::Win32SurfaceCreateInfoKHR{}
|
auto win32_surface_create_info = vk::Win32SurfaceCreateInfoKHR{}
|
||||||
.setHinstance(hinstance)
|
.setHinstance(hinstance)
|
||||||
.setHwnd(hwnd);
|
.setHwnd(hwnd);
|
||||||
surface = instance->createWin32SurfaceKHRUnique(win32_surface_create_info).value;
|
auto retval = instance->createWin32SurfaceKHRUnique(win32_surface_create_info);
|
||||||
if (!surface)
|
if (retval.result != vk::Result::eSuccess)
|
||||||
return false;
|
return false;
|
||||||
return init(preferred_device);
|
surface = std::move(retval.value);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||||
bool Context::init_Xlib(Display *dpy, Window xid, int preferred_device)
|
bool Context::init_Xlib()
|
||||||
{
|
{
|
||||||
instance = create_instance_preamble(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
instance = create_instance_preamble(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||||
if (!instance)
|
if (!instance)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
return init();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Context::create_Xlib_surface(Display *dpy, Window xid)
|
||||||
|
{
|
||||||
auto retval = instance->createXlibSurfaceKHRUnique({ {}, dpy, xid });
|
auto retval = instance->createXlibSurfaceKHRUnique({ {}, dpy, xid });
|
||||||
if (retval.result != vk::Result::eSuccess)
|
if (retval.result != vk::Result::eSuccess)
|
||||||
return false;
|
return false;
|
||||||
surface = std::move(retval.value);
|
surface = std::move(retval.value);
|
||||||
|
|
||||||
return init(preferred_device);
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||||
bool Context::init_wayland(wl_display *dpy, wl_surface *parent, int initial_width, int initial_height, int preferred_device)
|
bool Context::init_wayland()
|
||||||
{
|
{
|
||||||
instance = create_instance_preamble(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
|
instance = create_instance_preamble(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
|
||||||
if (!instance)
|
if (!instance)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
return init();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Context::create_wayland_surface(wl_display *dpy, wl_surface *parent)
|
||||||
|
{
|
||||||
auto wayland_surface_create_info = vk::WaylandSurfaceCreateInfoKHR{}
|
auto wayland_surface_create_info = vk::WaylandSurfaceCreateInfoKHR{}
|
||||||
.setSurface(parent)
|
.setSurface(parent)
|
||||||
.setDisplay(dpy);
|
.setDisplay(dpy);
|
||||||
|
@ -141,18 +158,29 @@ bool Context::init_wayland(wl_display *dpy, wl_surface *parent, int initial_widt
|
||||||
return false;
|
return false;
|
||||||
surface = std::move(new_surface);
|
surface = std::move(new_surface);
|
||||||
|
|
||||||
return init(preferred_device, initial_width, initial_height);
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Context::init(int preferred_device, int initial_width, int initial_height)
|
bool Context::destroy_surface()
|
||||||
{
|
{
|
||||||
init_device(preferred_device);
|
wait_idle();
|
||||||
|
if (swapchain)
|
||||||
|
swapchain->uncreate();
|
||||||
|
|
||||||
|
surface.reset();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Context::init()
|
||||||
|
{
|
||||||
|
init_device();
|
||||||
init_vma();
|
init_vma();
|
||||||
init_command_pool();
|
init_command_pool();
|
||||||
init_descriptor_pool();
|
init_descriptor_pool();
|
||||||
|
|
||||||
create_swapchain(initial_width, initial_height);
|
swapchain = std::make_unique<Swapchain>(*this);
|
||||||
wait_idle();
|
wait_idle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +220,7 @@ static bool find_extension(std::vector<vk::ExtensionProperties> &props, const ch
|
||||||
}) != props.end();
|
}) != props.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t find_graphics_queue(vk::PhysicalDevice &device)
|
static std::optional<uint32_t> find_graphics_queue(vk::PhysicalDevice &device)
|
||||||
{
|
{
|
||||||
auto queue_props = device.getQueueFamilyProperties();
|
auto queue_props = device.getQueueFamilyProperties();
|
||||||
for (size_t i = 0; i < queue_props.size(); i++)
|
for (size_t i = 0; i < queue_props.size(); i++)
|
||||||
|
@ -203,7 +231,7 @@ static uint32_t find_graphics_queue(vk::PhysicalDevice &device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return UINT32_MAX;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_extensions(std::vector<const char *> &required_extensions, vk::PhysicalDevice &device)
|
static bool check_extensions(std::vector<const char *> &required_extensions, vk::PhysicalDevice &device)
|
||||||
|
@ -217,7 +245,7 @@ static bool check_extensions(std::vector<const char *> &required_extensions, vk:
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Context::init_device(int preferred_device)
|
bool Context::init_device()
|
||||||
{
|
{
|
||||||
std::vector<const char *> required_extensions = {
|
std::vector<const char *> required_extensions = {
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||||
|
@ -251,8 +279,9 @@ bool Context::init_device(int preferred_device)
|
||||||
if (!device_chosen)
|
if (!device_chosen)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
graphics_queue_family_index = find_graphics_queue(physical_device);
|
if (auto index = find_graphics_queue(physical_device))
|
||||||
if (graphics_queue_family_index == UINT32_MAX)
|
graphics_queue_family_index = *index;
|
||||||
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::vector<float> priorities = { 1.0f };
|
std::vector<float> priorities = { 1.0f };
|
||||||
|
@ -262,14 +291,6 @@ bool Context::init_device(int preferred_device)
|
||||||
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);
|
||||||
|
|
||||||
auto surface_formats = physical_device.getSurfaceFormatsKHR(surface.get()).value;
|
|
||||||
if (std::find_if(surface_formats.begin(),
|
|
||||||
surface_formats.end(),
|
|
||||||
[](vk::SurfaceFormatKHR &f) {
|
|
||||||
return (f.format == vk::Format::eB8G8R8A8Unorm);
|
|
||||||
}) == surface_formats.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,16 +310,15 @@ bool Context::init_vma()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Context::create_swapchain(int width, int height)
|
bool Context::create_swapchain()
|
||||||
{
|
{
|
||||||
wait_idle();
|
wait_idle();
|
||||||
swapchain = std::make_unique<Swapchain>(*this);
|
return swapchain->create();
|
||||||
return swapchain->create(2, width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Context::recreate_swapchain(int width, int height)
|
bool Context::recreate_swapchain()
|
||||||
{
|
{
|
||||||
return swapchain->recreate(width, height);
|
return swapchain->recreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::wait_idle()
|
void Context::wait_idle()
|
||||||
|
|
|
@ -22,22 +22,28 @@ class Context
|
||||||
Context();
|
Context();
|
||||||
~Context();
|
~Context();
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||||
bool init_Xlib(Display *dpy, Window xid, int preferred_device = -1);
|
bool init_Xlib();
|
||||||
|
bool create_Xlib_surface(Display *dpy, Window xid);
|
||||||
#endif
|
#endif
|
||||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||||
bool init_wayland(wl_display *dpy, wl_surface *parent, int width, int height, int preferred_device = -1);
|
bool init_wayland();
|
||||||
|
bool create_wayland_surface(wl_display *dpy, wl_surface *parent);
|
||||||
#endif
|
#endif
|
||||||
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
||||||
bool init_win32(HINSTANCE hinstance, HWND hwnd, int preferred_device = -1);
|
bool init_win32();
|
||||||
|
bool create_win32_surface(HINSTANCE hinstance, HWND hwnd);
|
||||||
#endif
|
#endif
|
||||||
bool init(int preferred_device = -1, int initial_width = -1, int initial_height = -1);
|
bool init();
|
||||||
bool create_swapchain(int width = -1, int height = -1);
|
bool create_swapchain();
|
||||||
bool recreate_swapchain(int width = -1, int height = -1);
|
bool recreate_swapchain();
|
||||||
|
bool destroy_surface();
|
||||||
void wait_idle();
|
void wait_idle();
|
||||||
vk::CommandBuffer begin_cmd_buffer();
|
vk::CommandBuffer begin_cmd_buffer();
|
||||||
void end_cmd_buffer();
|
void end_cmd_buffer();
|
||||||
void hard_barrier(vk::CommandBuffer cmd);
|
void hard_barrier(vk::CommandBuffer cmd);
|
||||||
static std::vector<std::string> get_device_list();
|
static std::vector<std::string> get_device_list();
|
||||||
|
void set_preferred_device(int device) { preferred_device = device; };
|
||||||
|
void unset_preferred_device() { preferred_device = -1; };
|
||||||
|
|
||||||
vma::Allocator allocator;
|
vma::Allocator allocator;
|
||||||
vk::Device device;
|
vk::Device device;
|
||||||
|
@ -53,9 +59,10 @@ class Context
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init_vma();
|
bool init_vma();
|
||||||
bool init_device(int preferred_device = 0);
|
bool init_device();
|
||||||
bool init_command_pool();
|
bool init_command_pool();
|
||||||
bool init_descriptor_pool();
|
bool init_descriptor_pool();
|
||||||
|
int preferred_device;
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||||
Display *xlib_display;
|
Display *xlib_display;
|
||||||
|
|
|
@ -9,7 +9,6 @@ Swapchain::Swapchain(Context &context_)
|
||||||
{
|
{
|
||||||
device = context.device;
|
device = context.device;
|
||||||
queue = context.queue;
|
queue = context.queue;
|
||||||
surface = context.surface.get();
|
|
||||||
physical_device = context.physical_device;
|
physical_device = context.physical_device;
|
||||||
command_pool = context.command_pool.get();
|
command_pool = context.command_pool.get();
|
||||||
create_render_pass();
|
create_render_pass();
|
||||||
|
@ -77,17 +76,17 @@ void Swapchain::create_render_pass()
|
||||||
.setDependencies(subpass_dependency)
|
.setDependencies(subpass_dependency)
|
||||||
.setAttachments(attachment_description);
|
.setAttachments(attachment_description);
|
||||||
|
|
||||||
render_pass = device.createRenderPassUnique(render_pass_create_info).value;
|
render_pass = context.device.createRenderPassUnique(render_pass_create_info).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Swapchain::recreate(int new_width, int new_height)
|
bool Swapchain::recreate()
|
||||||
{
|
{
|
||||||
if (swapchain_object)
|
if (swapchain_object)
|
||||||
{
|
{
|
||||||
device.waitIdle();
|
device.waitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
return create(num_swapchain_images, new_width, new_height);
|
return create();
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::Image Swapchain::get_image()
|
vk::Image Swapchain::get_image()
|
||||||
|
@ -123,7 +122,7 @@ bool Swapchain::check_and_resize(int width, int height)
|
||||||
|
|
||||||
if (width == -1 && height == -1)
|
if (width == -1 && height == -1)
|
||||||
{
|
{
|
||||||
surface_capabilities = physical_device.getSurfaceCapabilitiesKHR(surface).value;
|
surface_capabilities = physical_device.getSurfaceCapabilitiesKHR(context.surface.get()).value;
|
||||||
width = surface_capabilities.currentExtent.width;
|
width = surface_capabilities.currentExtent.width;
|
||||||
height = surface_capabilities.currentExtent.height;
|
height = surface_capabilities.currentExtent.height;
|
||||||
}
|
}
|
||||||
|
@ -133,24 +132,34 @@ bool Swapchain::check_and_resize(int width, int height)
|
||||||
|
|
||||||
if (extents.width != (uint32_t)width || extents.height != (uint32_t)height)
|
if (extents.width != (uint32_t)width || extents.height != (uint32_t)height)
|
||||||
{
|
{
|
||||||
recreate(width, height);
|
set_desired_size(width, height);
|
||||||
|
recreate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width, int new_height)
|
bool Swapchain::uncreate()
|
||||||
|
{
|
||||||
|
frames.clear();
|
||||||
|
image_data.clear();
|
||||||
|
swapchain_object.reset();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Swapchain::create()
|
||||||
{
|
{
|
||||||
frames.clear();
|
frames.clear();
|
||||||
image_data.clear();
|
image_data.clear();
|
||||||
|
|
||||||
auto surface_capabilities = physical_device.getSurfaceCapabilitiesKHR(surface).value;
|
auto surface_capabilities = physical_device.getSurfaceCapabilitiesKHR(context.surface.get()).value;
|
||||||
|
|
||||||
if (surface_capabilities.minImageCount > desired_num_swapchain_images)
|
if (desired_latency == - 1 || (int)surface_capabilities.minImageCount > desired_latency)
|
||||||
num_swapchain_images = surface_capabilities.minImageCount;
|
num_swapchain_images = surface_capabilities.minImageCount;
|
||||||
else
|
else
|
||||||
num_swapchain_images = desired_num_swapchain_images;
|
num_swapchain_images = desired_latency;
|
||||||
|
|
||||||
// If extents aren't reported (Wayland), we have to rely on Wayland to report
|
// If extents aren't reported (Wayland), we have to rely on Wayland to report
|
||||||
// the size, so keep current extent.
|
// the size, so keep current extent.
|
||||||
|
@ -168,11 +177,11 @@ bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_width > 0 && new_height > 0)
|
if (desired_width > 0 && desired_height > 0)
|
||||||
{
|
{
|
||||||
// No buffer is allocated for surface yet
|
// No buffer is allocated for surface yet
|
||||||
extents.width = new_width;
|
extents.width = desired_width;
|
||||||
extents.height = new_height;
|
extents.height = desired_height;
|
||||||
}
|
}
|
||||||
else if (extents.width < 1 || extents.height < 1)
|
else if (extents.width < 1 || extents.height < 1)
|
||||||
{
|
{
|
||||||
|
@ -191,14 +200,6 @@ bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width,
|
||||||
if (extents.height < surface_capabilities.minImageExtent.height)
|
if (extents.height < surface_capabilities.minImageExtent.height)
|
||||||
extents.height = surface_capabilities.minImageExtent.height;
|
extents.height = surface_capabilities.minImageExtent.height;
|
||||||
|
|
||||||
auto present_modes = physical_device.getSurfacePresentModesKHR(surface).value;
|
|
||||||
supports_mailbox = vector_find(present_modes, vk::PresentModeKHR::eMailbox);
|
|
||||||
supports_immediate = vector_find(present_modes, vk::PresentModeKHR::eImmediate);
|
|
||||||
supports_relaxed = vector_find(present_modes, vk::PresentModeKHR::eFifoRelaxed);
|
|
||||||
|
|
||||||
auto swapchain_maintenance_info = vk::SwapchainPresentModesCreateInfoEXT{}
|
|
||||||
.setPresentModes(present_modes);
|
|
||||||
|
|
||||||
auto swapchain_create_info = vk::SwapchainCreateInfoKHR{}
|
auto swapchain_create_info = vk::SwapchainCreateInfoKHR{}
|
||||||
.setMinImageCount(num_swapchain_images)
|
.setMinImageCount(num_swapchain_images)
|
||||||
.setImageFormat(vk::Format::eB8G8R8A8Unorm)
|
.setImageFormat(vk::Format::eB8G8R8A8Unorm)
|
||||||
|
@ -209,11 +210,10 @@ bool Swapchain::create(unsigned int desired_num_swapchain_images, int new_width,
|
||||||
.setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
|
.setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
|
||||||
.setClipped(true)
|
.setClipped(true)
|
||||||
.setPresentMode(get_present_mode())
|
.setPresentMode(get_present_mode())
|
||||||
.setSurface(surface)
|
.setSurface(context.surface.get())
|
||||||
.setPreTransform(vk::SurfaceTransformFlagBitsKHR::eIdentity)
|
.setPreTransform(vk::SurfaceTransformFlagBitsKHR::eIdentity)
|
||||||
.setImageArrayLayers(1)
|
.setImageArrayLayers(1)
|
||||||
.setQueueFamilyIndices(graphics_queue_index)
|
.setQueueFamilyIndices(graphics_queue_index);
|
||||||
.setPNext(&swapchain_maintenance_info);
|
|
||||||
|
|
||||||
swapchain_object.reset();
|
swapchain_object.reset();
|
||||||
auto resval = device.createSwapchainKHRUnique(swapchain_create_info);
|
auto resval = device.createSwapchainKHRUnique(swapchain_create_info);
|
||||||
|
@ -299,7 +299,7 @@ bool Swapchain::begin_frame()
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::ResultValue<uint32_t> result_value(vk::Result::eSuccess, 0);
|
vk::ResultValue<uint32_t> result_value(vk::Result::eSuccess, 0);
|
||||||
result_value = device.acquireNextImageKHR(swapchain_object.get(), UINT64_MAX, frame.acquire.get());
|
result_value = device.acquireNextImageKHR(swapchain_object.get(), 33333333, frame.acquire.get());
|
||||||
|
|
||||||
if (result_value.result == vk::Result::eErrorOutOfDateKHR ||
|
if (result_value.result == vk::Result::eErrorOutOfDateKHR ||
|
||||||
result_value.result == vk::Result::eSuboptimalKHR)
|
result_value.result == vk::Result::eSuboptimalKHR)
|
||||||
|
|
|
@ -13,10 +13,16 @@ class Swapchain
|
||||||
public:
|
public:
|
||||||
Swapchain(Context &);
|
Swapchain(Context &);
|
||||||
~Swapchain();
|
~Swapchain();
|
||||||
bool create(unsigned int num_frames, int width = -1, int height = -1);
|
bool create();
|
||||||
bool recreate(int width = -1, int height = -1);
|
bool uncreate();
|
||||||
|
bool recreate();
|
||||||
bool create_resources();
|
bool create_resources();
|
||||||
bool check_and_resize(int width = -1, int height = -1);
|
bool check_and_resize(int width = -1, int height = -1);
|
||||||
|
Swapchain &set_desired_size(int width, int height) { desired_width = width; desired_height = height; return *this; }
|
||||||
|
void unset_desired_size() { desired_width = -1; desired_height = -1; }
|
||||||
|
Swapchain &set_desired_latency(int latency) { desired_latency = latency; return *this; }
|
||||||
|
void unset_desired_latency() { desired_latency = -1; }
|
||||||
|
|
||||||
bool begin_frame();
|
bool begin_frame();
|
||||||
void begin_render_pass();
|
void begin_render_pass();
|
||||||
void end_render_pass();
|
void end_render_pass();
|
||||||
|
@ -61,6 +67,9 @@ 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;
|
||||||
|
int desired_width = -1;
|
||||||
|
int desired_height = -1;
|
||||||
|
int desired_latency = -1;
|
||||||
uint64_t presentation_id = 0;
|
uint64_t presentation_id = 0;
|
||||||
bool vsync = true;
|
bool vsync = true;
|
||||||
bool supports_immediate = false;
|
bool supports_immediate = false;
|
||||||
|
@ -71,7 +80,6 @@ class Swapchain
|
||||||
|
|
||||||
Vulkan::Context &context;
|
Vulkan::Context &context;
|
||||||
vk::Device device;
|
vk::Device device;
|
||||||
vk::SurfaceKHR surface;
|
|
||||||
vk::CommandPool command_pool;
|
vk::CommandPool command_pool;
|
||||||
vk::PhysicalDevice physical_device;
|
vk::PhysicalDevice physical_device;
|
||||||
vk::Queue queue;
|
vk::Queue queue;
|
||||||
|
|
|
@ -91,7 +91,10 @@ void S9xVulkanDisplayDriver::refresh()
|
||||||
|
|
||||||
#ifdef GDK_WINDOWING_WAYLAND
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
||||||
|
{
|
||||||
std::tie(new_width, new_height) = wayland_surface->get_size_for_metrics(get_metrics(*drawing_area));
|
std::tie(new_width, new_height) = wayland_surface->get_size_for_metrics(get_metrics(*drawing_area));
|
||||||
|
context->swapchain->set_desired_size(new_width, new_height);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
@ -101,7 +104,7 @@ void S9xVulkanDisplayDriver::refresh()
|
||||||
|
|
||||||
if (new_width != current_width || new_height != current_height)
|
if (new_width != current_width || new_height != current_height)
|
||||||
{
|
{
|
||||||
context->recreate_swapchain(new_width, new_height);
|
context->recreate_swapchain();
|
||||||
context->wait_idle();
|
context->wait_idle();
|
||||||
current_width = new_width;
|
current_width = new_width;
|
||||||
current_height = new_height;
|
current_height = new_height;
|
||||||
|
@ -128,10 +131,14 @@ int S9xVulkanDisplayDriver::init()
|
||||||
wl_display *display = gdk_wayland_display_get_wl_display(drawing_area->get_display()->gobj());
|
wl_display *display = gdk_wayland_display_get_wl_display(drawing_area->get_display()->gobj());
|
||||||
|
|
||||||
if (!wayland_surface->attach(display, surface, get_metrics(*drawing_area)))
|
if (!wayland_surface->attach(display, surface, get_metrics(*drawing_area)))
|
||||||
return -1;
|
goto abort;
|
||||||
|
if (!context->init_wayland())
|
||||||
if (!context->init_wayland(wayland_surface->display, wayland_surface->child, current_width, current_height))
|
goto abort;
|
||||||
return -1;
|
if (!context->create_wayland_surface(wayland_surface->display, wayland_surface->child))
|
||||||
|
goto abort;
|
||||||
|
context->swapchain->set_desired_size(current_width, current_height);
|
||||||
|
if (!context->create_swapchain())
|
||||||
|
goto abort;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (GDK_IS_X11_WINDOW(drawing_area->get_window()->gobj()))
|
if (GDK_IS_X11_WINDOW(drawing_area->get_window()->gobj()))
|
||||||
|
@ -139,8 +146,12 @@ int S9xVulkanDisplayDriver::init()
|
||||||
display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
|
display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
|
||||||
xid = gdk_x11_window_get_xid(drawing_area->get_window()->gobj());
|
xid = gdk_x11_window_get_xid(drawing_area->get_window()->gobj());
|
||||||
|
|
||||||
if (!context->init_Xlib(display, xid))
|
if (!context->init_Xlib())
|
||||||
return -1;
|
goto abort;
|
||||||
|
if (!context->create_Xlib_surface(display, xid))
|
||||||
|
goto abort;
|
||||||
|
if (!context->create_swapchain())
|
||||||
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
device = context->device;
|
device = context->device;
|
||||||
|
@ -168,6 +179,10 @@ int S9xVulkanDisplayDriver::init()
|
||||||
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 0;
|
return 0;
|
||||||
|
|
||||||
|
abort:
|
||||||
|
context.reset();
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xVulkanDisplayDriver::deinit()
|
void S9xVulkanDisplayDriver::deinit()
|
||||||
|
|
|
@ -28,7 +28,7 @@ EmuCanvasVulkan::EmuCanvasVulkan(EmuConfig *config, QWidget *parent, QWidget *ma
|
||||||
|
|
||||||
EmuCanvasVulkan::~EmuCanvasVulkan()
|
EmuCanvasVulkan::~EmuCanvasVulkan()
|
||||||
{
|
{
|
||||||
deinit();
|
assert(!context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuCanvasVulkan::initImGui()
|
bool EmuCanvasVulkan::initImGui()
|
||||||
|
@ -85,14 +85,16 @@ bool EmuCanvasVulkan::createContext()
|
||||||
QGuiApplication::sync();
|
QGuiApplication::sync();
|
||||||
|
|
||||||
context = std::make_unique<Vulkan::Context>();
|
context = std::make_unique<Vulkan::Context>();
|
||||||
|
context->set_preferred_device(config->display_device_index);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
auto hwnd = (HWND)winId();
|
auto hwnd = (HWND)winId();
|
||||||
if (!context->init_win32(nullptr, hwnd, config->display_device_index))
|
if (!context->init_win32(nullptr, hwnd, config->display_device_index))
|
||||||
{
|
goto fail;
|
||||||
context.reset();
|
if (!context->create_win32_surface(nullptr, hwnd))
|
||||||
return false;
|
goto fail;
|
||||||
}
|
if (!context->swapchain->create())
|
||||||
|
goto fail;
|
||||||
#else
|
#else
|
||||||
if (platform == "wayland")
|
if (platform == "wayland")
|
||||||
{
|
{
|
||||||
|
@ -101,21 +103,31 @@ bool EmuCanvasVulkan::createContext()
|
||||||
auto surface = (wl_surface *)pni->nativeResourceForWindow("surface", main_window->windowHandle());
|
auto surface = (wl_surface *)pni->nativeResourceForWindow("surface", main_window->windowHandle());
|
||||||
wayland_surface->attach(display, surface, { parent->x() - main_window->x(), parent->y() - main_window->y(), width(), height(), static_cast<int>(devicePixelRatio()) });
|
wayland_surface->attach(display, surface, { parent->x() - main_window->x(), parent->y() - main_window->y(), width(), height(), static_cast<int>(devicePixelRatio()) });
|
||||||
auto [scaled_width, scaled_height] = wayland_surface->get_size();
|
auto [scaled_width, scaled_height] = wayland_surface->get_size();
|
||||||
if (!context->init_wayland(display, wayland_surface->child, scaled_width, scaled_height, config->display_device_index))
|
|
||||||
{
|
if (!context->init_wayland())
|
||||||
context.reset();
|
goto fail;
|
||||||
return false;
|
|
||||||
}
|
if (!context->create_wayland_surface(display, wayland_surface->child))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
context->swapchain->set_desired_size(scaled_width, scaled_height);
|
||||||
|
if (!context->swapchain->create())
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
else if (platform == "xcb")
|
else if (platform == "xcb")
|
||||||
{
|
{
|
||||||
auto display = (Display *)pni->nativeResourceForWindow("display", window);
|
auto display = (Display *)pni->nativeResourceForWindow("display", window);
|
||||||
auto xid = (Window)winId();
|
auto xid = (Window)winId();
|
||||||
if (!context->init_Xlib(display, xid, config->display_device_index))
|
|
||||||
{
|
if (!context->init_Xlib())
|
||||||
context.reset();
|
goto fail;
|
||||||
return false;
|
|
||||||
}
|
if (!context->create_Xlib_surface(display, xid))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
context->wait_idle();
|
||||||
|
if (!context->swapchain->create())
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -130,6 +142,10 @@ bool EmuCanvasVulkan::createContext()
|
||||||
paintEvent(nullptr);
|
paintEvent(nullptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
context.reset();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuCanvasVulkan::tryLoadShader()
|
void EmuCanvasVulkan::tryLoadShader()
|
||||||
|
|
Loading…
Reference in New Issue