mirror of https://github.com/snes9xgit/snes9x.git
Wayland compatibility with Vulkan.
This commit is contained in:
parent
fa03a2c5b2
commit
e4768f9b80
|
@ -125,6 +125,8 @@ if(USE_WAYLAND)
|
|||
list(APPEND DEFINES "USE_WAYLAND")
|
||||
list(APPEND SOURCES src/gtk_wayland_egl_context.cpp
|
||||
src/gtk_wayland_egl_context.h
|
||||
src/gtk_wayland_surface.cpp
|
||||
src/gtk_wayland_surface.h
|
||||
src/wayland-idle-inhibit-unstable-v1.c)
|
||||
list(APPEND ARGS ${WAYLAND_CFLAGS})
|
||||
list(APPEND LIBS ${WAYLAND_LIBRARIES})
|
||||
|
@ -365,21 +367,6 @@ add_executable(slang_test ../vulkan/slang_helpers.cpp
|
|||
../vulkan/slang_preset_test.cpp
|
||||
../conffile.cpp
|
||||
../stream.cpp)
|
||||
#add_executable(vulkan_test ../vulkan/slang_helpers.cpp
|
||||
# ../vulkan/slang_helpers.hpp
|
||||
# ../vulkan/slang_shader.cpp
|
||||
# ../vulkan/slang_shader.hpp
|
||||
# ../vulkan/slang_preset.cpp
|
||||
# ../vulkan/slang_preset.hpp
|
||||
# ../vulkan/vulkan_hpp_storage.cpp
|
||||
# ../vulkan/test.cpp
|
||||
# ../vulkan/vk2d.cpp
|
||||
# ../conffile.cpp
|
||||
# ../stream.cpp)
|
||||
#target_include_directories(vulkan_test PRIVATE ${INCLUDES})
|
||||
#target_compile_options(vulkan_test PRIVATE ${ARGS})
|
||||
#target_compile_definitions(vulkan_test PRIVATE ${DEFINES} "VULKAN_HPP_NO_EXCEPTIONS" "VULKAN_HPP_ASSERT_ON_RESULT=")
|
||||
#target_link_libraries(vulkan_test PRIVATE ${LIBS})
|
||||
|
||||
target_include_directories(slang_test PRIVATE ${INCLUDES})
|
||||
target_compile_options(slang_test PRIVATE ${ARGS})
|
||||
|
|
|
@ -900,7 +900,8 @@ static void S9xInitDriver()
|
|||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
|
||||
{
|
||||
gui_config->display_driver = "opengl";
|
||||
if (gui_config->display_driver != "vulkan")
|
||||
gui_config->display_driver = "opengl";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void S9xVulkanDisplayDriver::create_pipeline()
|
|||
auto [result, pipeline] = device.createGraphicsPipelineUnique(nullptr, pipeline_create_info);
|
||||
this->pipeline = std::move(pipeline);
|
||||
}
|
||||
|
||||
|
||||
S9xVulkanDisplayDriver::S9xVulkanDisplayDriver(Snes9xWindow *_window, Snes9xConfig *_config)
|
||||
{
|
||||
window = _window;
|
||||
|
@ -187,7 +187,13 @@ void S9xVulkanDisplayDriver::refresh(int width, int height)
|
|||
|
||||
if (new_width != current_width || new_height != current_height || vsync_changed)
|
||||
{
|
||||
context->recreate_swapchain();
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
||||
{
|
||||
wayland_surface->resize();
|
||||
}
|
||||
#endif
|
||||
context->recreate_swapchain(new_width, new_height);
|
||||
context->wait_idle();
|
||||
current_width = new_width;
|
||||
current_height = new_height;
|
||||
|
@ -200,11 +206,27 @@ int S9xVulkanDisplayDriver::init()
|
|||
{
|
||||
current_width = drawing_area->get_width() * drawing_area->get_scale_factor();
|
||||
current_height = drawing_area->get_height() * drawing_area->get_scale_factor();
|
||||
display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
|
||||
xid = gdk_x11_window_get_xid(drawing_area->get_window()->gobj());
|
||||
|
||||
context = std::make_unique<Vulkan::Context>();
|
||||
context->init(display, xid);
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
|
||||
{
|
||||
wayland_surface = std::make_unique<WaylandSurface>();
|
||||
if (!wayland_surface->attach(GTK_WIDGET(drawing_area->gobj())))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
context->init_wayland(wayland_surface->display, wayland_surface->child, current_width, current_height);
|
||||
}
|
||||
#endif
|
||||
if (GDK_IS_X11_WINDOW(drawing_area->get_window()->gobj()))
|
||||
{
|
||||
display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
|
||||
xid = gdk_x11_window_get_xid(drawing_area->get_window()->gobj());
|
||||
|
||||
context->init_Xlib(display, xid);
|
||||
}
|
||||
swapchain = context->swapchain.get();
|
||||
device = context->device;
|
||||
|
||||
|
@ -236,7 +258,7 @@ int S9xVulkanDisplayDriver::init()
|
|||
auto descriptor = device.allocateDescriptorSetsUnique(dsai);
|
||||
descriptors.push_back(std::move(descriptor[0]));
|
||||
}
|
||||
|
||||
|
||||
textures.clear();
|
||||
textures.resize(swapchain->get_num_frames());
|
||||
for (auto &t : textures)
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#include "../../vulkan/slang_preset.hpp"
|
||||
#include "../../vulkan/vulkan_shader_chain.hpp"
|
||||
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include "gtk_wayland_surface.h"
|
||||
#endif
|
||||
|
||||
class S9xVulkanDisplayDriver : public S9xDisplayDriver
|
||||
{
|
||||
public:
|
||||
|
@ -40,6 +44,10 @@ class S9xVulkanDisplayDriver : public S9xDisplayDriver
|
|||
int current_width;
|
||||
int current_height;
|
||||
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
std::unique_ptr<WaylandSurface> wayland_surface;
|
||||
#endif
|
||||
|
||||
void create_pipeline();
|
||||
vk::UniqueDescriptorSetLayout descriptor_set_layout;
|
||||
vk::UniquePipelineLayout pipeline_layout;
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gtk_s9x.h"
|
||||
#include "gtk_wayland_surface.h"
|
||||
#include "wayland-idle-inhibit-unstable-v1.h"
|
||||
|
||||
static void wl_global(void *data,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t name,
|
||||
const char *interface,
|
||||
uint32_t version)
|
||||
{
|
||||
auto wl = (WaylandSurface *)data;
|
||||
|
||||
if (!strcmp(interface, "wl_compositor"))
|
||||
wl->compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3);
|
||||
else if (!strcmp(interface, "wl_subcompositor"))
|
||||
wl->subcompositor = (struct wl_subcompositor *)wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, 1);
|
||||
else if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name))
|
||||
wl->idle_inhibit_manager = (struct zwp_idle_inhibit_manager_v1 *)wl_registry_bind(wl_registry, name, &zwp_idle_inhibit_manager_v1_interface, 1);
|
||||
}
|
||||
|
||||
static void wl_global_remove(void *data,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t name)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener wl_registry_listener = {
|
||||
wl_global,
|
||||
wl_global_remove
|
||||
};
|
||||
|
||||
WaylandSurface::WaylandSurface()
|
||||
{
|
||||
display = nullptr;
|
||||
registry = nullptr;
|
||||
compositor = nullptr;
|
||||
subcompositor = nullptr;
|
||||
parent = nullptr;
|
||||
child = nullptr;
|
||||
region = nullptr;
|
||||
subsurface = nullptr;
|
||||
idle_inhibit_manager = nullptr;
|
||||
idle_inhibitor = nullptr;
|
||||
}
|
||||
|
||||
WaylandSurface::~WaylandSurface()
|
||||
{
|
||||
if (idle_inhibitor)
|
||||
zwp_idle_inhibitor_v1_destroy(idle_inhibitor);
|
||||
|
||||
if (idle_inhibit_manager)
|
||||
zwp_idle_inhibit_manager_v1_destroy(idle_inhibit_manager);
|
||||
|
||||
if (subsurface)
|
||||
wl_subsurface_destroy(subsurface);
|
||||
|
||||
if (region)
|
||||
wl_region_destroy(region);
|
||||
|
||||
if (child)
|
||||
wl_surface_destroy(child);
|
||||
}
|
||||
|
||||
bool WaylandSurface::attach(GtkWidget *widget)
|
||||
{
|
||||
GdkWindow *window = gtk_widget_get_window(widget);
|
||||
|
||||
if (!GDK_IS_WAYLAND_WINDOW(window))
|
||||
return false;
|
||||
|
||||
gdk_window = window;
|
||||
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
|
||||
|
||||
display = gdk_wayland_display_get_wl_display(gdk_window_get_display(gdk_window));
|
||||
parent = gdk_wayland_window_get_wl_surface(gdk_window);
|
||||
registry = wl_display_get_registry(display);
|
||||
|
||||
wl_registry_add_listener(registry, &wl_registry_listener, this);
|
||||
wl_display_roundtrip(display);
|
||||
|
||||
if (!compositor || !subcompositor)
|
||||
return false;
|
||||
|
||||
child = wl_compositor_create_surface(compositor);
|
||||
region = wl_compositor_create_region(compositor);
|
||||
subsurface = wl_subcompositor_get_subsurface(subcompositor, child, parent);
|
||||
|
||||
wl_surface_set_input_region(child, region);
|
||||
wl_subsurface_set_desync(subsurface);
|
||||
wl_subsurface_set_position(subsurface, x, y);
|
||||
|
||||
if (idle_inhibit_manager && gui_config->prevent_screensaver)
|
||||
{
|
||||
printf("Inhibiting screensaver.\n");
|
||||
zwp_idle_inhibit_manager_v1_create_inhibitor(idle_inhibit_manager, child);
|
||||
}
|
||||
|
||||
auto scale = gdk_window_get_scale_factor(window);
|
||||
wl_surface_set_buffer_scale(child, scale);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaylandSurface::resize()
|
||||
{
|
||||
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
|
||||
auto scale = gdk_window_get_scale_factor(gdk_window);
|
||||
wl_subsurface_set_position(subsurface, x, y);
|
||||
wl_surface_set_buffer_scale(child, scale);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtk_compat.h"
|
||||
|
||||
class WaylandSurface
|
||||
{
|
||||
public:
|
||||
WaylandSurface();
|
||||
~WaylandSurface();
|
||||
bool attach(GtkWidget *widget);
|
||||
void resize();
|
||||
|
||||
GdkWindow *gdk_window;
|
||||
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
|
||||
struct wl_surface *parent;
|
||||
struct wl_surface *child;
|
||||
struct wl_subsurface *subsurface;
|
||||
struct wl_region *region;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
||||
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
|
||||
};
|
|
@ -37,22 +37,52 @@ Context::~Context()
|
|||
device.destroy();
|
||||
}
|
||||
|
||||
bool Context::init(Display *dpy, Window xid, int preferred_device)
|
||||
static vk::UniqueInstance create_instance_preamble(const char *wsi_extension)
|
||||
{
|
||||
if (instance)
|
||||
return false;
|
||||
|
||||
xlib_display = dpy;
|
||||
xlib_window = xid;
|
||||
|
||||
std::vector<const char *> extensions = { VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_EXTENSION_NAME };
|
||||
std::vector<const char *> extensions = { wsi_extension, VK_KHR_SURFACE_EXTENSION_NAME };
|
||||
vk::ApplicationInfo application_info({}, {}, {}, {}, VK_API_VERSION_1_0);
|
||||
vk::InstanceCreateInfo instance_create_info({}, &application_info, {}, extensions);
|
||||
|
||||
instance = vk::createInstanceUnique(instance_create_info);
|
||||
auto instance = vk::createInstanceUnique(instance_create_info);
|
||||
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance.get());
|
||||
surface = instance->createXlibSurfaceKHRUnique({ {}, xlib_display, xlib_window });
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||
bool Context::init_Xlib(Display *dpy, Window xid, int preferred_device)
|
||||
{
|
||||
if (instance)
|
||||
return false;
|
||||
instance = create_instance_preamble(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
surface = instance->createXlibSurfaceKHRUnique({ {}, dpy, xid });
|
||||
return init(preferred_device);
|
||||
}
|
||||
#endif
|
||||
|
||||
#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)
|
||||
{
|
||||
if (instance)
|
||||
return false;
|
||||
instance = create_instance_preamble(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
|
||||
auto wayland_surface_create_info = vk::WaylandSurfaceCreateInfoKHR{}
|
||||
.setSurface(parent)
|
||||
.setDisplay(dpy);
|
||||
surface = instance->createWaylandSurfaceKHRUnique(wayland_surface_create_info);
|
||||
init_device(preferred_device);
|
||||
init_vma();
|
||||
init_command_pool();
|
||||
init_descriptor_pool();
|
||||
create_swapchain(initial_width, initial_height);
|
||||
device.waitIdle();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Context::init(int preferred_device)
|
||||
{
|
||||
|
||||
init_device(preferred_device);
|
||||
init_vma();
|
||||
|
@ -159,16 +189,16 @@ bool Context::init_vma()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Context::create_swapchain()
|
||||
bool Context::create_swapchain(int width, int height)
|
||||
{
|
||||
wait_idle();
|
||||
swapchain = std::make_unique<Swapchain>(device, physical_device, queue, surface.get(), command_pool.get());
|
||||
return swapchain->create(3);
|
||||
return swapchain->create(3, width, height);
|
||||
}
|
||||
|
||||
bool Context::recreate_swapchain()
|
||||
bool Context::recreate_swapchain(int width, int height)
|
||||
{
|
||||
return swapchain->recreate();
|
||||
return swapchain->recreate(width, height);
|
||||
}
|
||||
|
||||
void Context::wait_idle()
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "X11/Xlib.h"
|
||||
//"VK_USE_PLATFORM_WAYLAND_KHR"
|
||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
#include "vk_mem_alloc.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "vulkan_swapchain.hpp"
|
||||
|
@ -15,9 +18,15 @@ class Context
|
|||
public:
|
||||
Context();
|
||||
~Context();
|
||||
bool init(Display *dpy, Window xid, int preferred_device = 0);
|
||||
bool create_swapchain();
|
||||
bool recreate_swapchain();
|
||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||
bool init_Xlib(Display *dpy, Window xid, int preferred_device = 0);
|
||||
#endif
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
bool init_wayland(wl_display *dpy, wl_surface *parent, int width, int height, int preferred_device = 0);
|
||||
#endif
|
||||
bool init(int preferred_device = 0);
|
||||
bool create_swapchain(int width = -1, int height = -1);
|
||||
bool recreate_swapchain(int width = -1, int height = -1);
|
||||
void wait_idle();
|
||||
vk::CommandBuffer begin_cmd_buffer();
|
||||
void end_cmd_buffer();
|
||||
|
@ -38,8 +47,10 @@ class Context
|
|||
|
||||
vk::UniquePipeline create_generic_pipeline();
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||
Display *xlib_display;
|
||||
Window xlib_window;
|
||||
#endif
|
||||
|
||||
vk::UniqueInstance instance;
|
||||
vk::PhysicalDevice physical_device;
|
||||
|
|
|
@ -235,17 +235,18 @@ bool ShaderChain::load_shader_preset(std::string filename)
|
|||
if (p.samplers.size() > 0)
|
||||
num_samplers += p.samplers.size();
|
||||
}
|
||||
|
||||
std::array<vk::DescriptorPoolSize, 2> descriptor_pool_sizes;
|
||||
descriptor_pool_sizes[0]
|
||||
.setType(vk::DescriptorType::eUniformBuffer)
|
||||
.setDescriptorCount(num_ubos * 3);
|
||||
.setDescriptorCount(num_ubos * context->swapchain->get_num_frames());
|
||||
descriptor_pool_sizes[1]
|
||||
.setType(vk::DescriptorType::eCombinedImageSampler)
|
||||
.setDescriptorCount(num_samplers * 3);
|
||||
.setDescriptorCount(num_samplers * context->swapchain->get_num_frames());
|
||||
|
||||
auto descriptor_pool_create_info = vk::DescriptorPoolCreateInfo{}
|
||||
.setPoolSizes(descriptor_pool_sizes)
|
||||
.setMaxSets(pipelines.size() * 3)
|
||||
.setMaxSets(pipelines.size() * context->swapchain->get_num_frames())
|
||||
.setFlags(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet);
|
||||
|
||||
descriptor_pool = context->device.createDescriptorPoolUnique(descriptor_pool_create_info);
|
||||
|
@ -393,7 +394,6 @@ void ShaderChain::do_frame(uint8_t *data, int width, int height, int stride, vk:
|
|||
auto cmd = context->swapchain->get_cmd();
|
||||
|
||||
current_frame_index = context->swapchain->get_current_frame();
|
||||
|
||||
update_and_propagate_sizes(width, height, viewport_width, viewport_height);
|
||||
|
||||
update_framebuffers(cmd, current_frame_index);
|
||||
|
|
|
@ -33,7 +33,8 @@ class SlangPipeline
|
|||
{
|
||||
vk::UniqueDescriptorSet descriptor_set;
|
||||
PipelineImage image;
|
||||
} frame[3];
|
||||
vk::UniqueFence fence;
|
||||
} frame[4];
|
||||
|
||||
vk::Buffer uniform_buffer;
|
||||
vma::Allocation uniform_buffer_allocation;
|
||||
|
|
|
@ -72,11 +72,11 @@ void Swapchain::create_render_pass()
|
|||
render_pass = device.createRenderPassUnique(render_pass_create_info);
|
||||
}
|
||||
|
||||
bool Swapchain::recreate()
|
||||
bool Swapchain::recreate(int new_width, int new_height)
|
||||
{
|
||||
device.waitIdle();
|
||||
|
||||
return create(num_frames);
|
||||
return create(num_frames, new_width, new_height);
|
||||
}
|
||||
|
||||
vk::Image Swapchain::get_image()
|
||||
|
@ -84,7 +84,7 @@ vk::Image Swapchain::get_image()
|
|||
return imageviewfbs[current_swapchain_image].image;
|
||||
}
|
||||
|
||||
bool Swapchain::create(unsigned int desired_num_frames)
|
||||
bool Swapchain::create(unsigned int desired_num_frames, int new_width, int new_height)
|
||||
{
|
||||
frames.clear();
|
||||
imageviewfbs.clear();
|
||||
|
@ -98,10 +98,17 @@ bool Swapchain::create(unsigned int desired_num_frames)
|
|||
|
||||
extents = surface_capabilities.currentExtent;
|
||||
|
||||
if (extents.width <= 1 || extents.height <= 1)
|
||||
if (new_width > 0 && new_height > 0)
|
||||
{
|
||||
// No buffer is allocated for surface yet
|
||||
extents.width = new_width;
|
||||
extents.height = new_height;
|
||||
}
|
||||
else if (extents.width < 1 || extents.height < 1)
|
||||
{
|
||||
// Surface is likely hidden
|
||||
printf("Extents too small.\n");
|
||||
swapchain_object.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -118,12 +125,14 @@ bool Swapchain::create(unsigned int desired_num_frames)
|
|||
.setSurface(surface)
|
||||
.setImageArrayLayers(1);
|
||||
|
||||
if (swapchain)
|
||||
swapchain_create_info.setOldSwapchain(swapchain.get());
|
||||
if (swapchain_object)
|
||||
swapchain_create_info.setOldSwapchain(swapchain_object.get());
|
||||
|
||||
swapchain = device.createSwapchainKHRUnique(swapchain_create_info);
|
||||
swapchain_object = device.createSwapchainKHRUnique(swapchain_create_info);
|
||||
if (!swapchain_object)
|
||||
return false;
|
||||
|
||||
auto swapchain_images = device.getSwapchainImagesKHR(swapchain.get());
|
||||
auto swapchain_images = device.getSwapchainImagesKHR(swapchain_object.get());
|
||||
vk::CommandBufferAllocateInfo command_buffer_allocate_info(command_pool, vk::CommandBufferLevel::ePrimary, num_frames);
|
||||
auto command_buffers = device.allocateCommandBuffersUnique(command_buffer_allocate_info);
|
||||
|
||||
|
@ -168,6 +177,8 @@ bool Swapchain::create(unsigned int desired_num_frames)
|
|||
image.framebuffer = device.createFramebufferUnique(framebuffer_create_info);
|
||||
}
|
||||
|
||||
device.waitIdle();
|
||||
|
||||
current_swapchain_image = 0;
|
||||
|
||||
return true;
|
||||
|
@ -175,7 +186,7 @@ bool Swapchain::create(unsigned int desired_num_frames)
|
|||
|
||||
bool Swapchain::begin_frame()
|
||||
{
|
||||
if (extents.width < 1 || extents.height < 1)
|
||||
if (!swapchain_object || extents.width < 1 || extents.height < 1)
|
||||
{
|
||||
printf ("Extents too small\n");
|
||||
return false;
|
||||
|
@ -190,17 +201,18 @@ bool Swapchain::begin_frame()
|
|||
return false;
|
||||
}
|
||||
|
||||
auto result_value = device.acquireNextImageKHR(swapchain.get(), 33000000, frame.acquire.get());
|
||||
auto result_value = device.acquireNextImageKHR(swapchain_object.get(), 33000000, frame.acquire.get());
|
||||
if (result_value.result == vk::Result::eErrorOutOfDateKHR ||
|
||||
result_value.result == vk::Result::eSuboptimalKHR)
|
||||
{
|
||||
printf("Out of date\n");
|
||||
recreate();
|
||||
return begin_frame();
|
||||
}
|
||||
|
||||
if (result_value.result != vk::Result::eSuccess)
|
||||
{
|
||||
printf ("Random failure %d\n", result_value.result);
|
||||
printf("Timeout waiting for frame. Running too slow.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -213,7 +225,7 @@ bool Swapchain::begin_frame()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Swapchain::end_frame()
|
||||
bool Swapchain::end_frame(vk::Fence extra_fence)
|
||||
{
|
||||
auto &frame = frames[current_frame];
|
||||
frame.command_buffer->end();
|
||||
|
@ -225,11 +237,13 @@ bool Swapchain::end_frame()
|
|||
frame.command_buffer.get(),
|
||||
frame.complete.get());
|
||||
|
||||
if (extra_fence)
|
||||
queue.submit(submit_info, extra_fence);
|
||||
queue.submit(submit_info, frame.fence.get());
|
||||
|
||||
auto present_info = vk::PresentInfoKHR{}
|
||||
.setWaitSemaphores(frames[current_frame].complete.get())
|
||||
.setSwapchains(swapchain.get())
|
||||
.setSwapchains(swapchain_object.get())
|
||||
.setImageIndices(current_swapchain_image);
|
||||
|
||||
auto result = queue.presentKHR(present_info);
|
||||
|
|
|
@ -16,13 +16,13 @@ class Swapchain
|
|||
vk::SurfaceKHR surface,
|
||||
vk::CommandPool command_pool);
|
||||
~Swapchain();
|
||||
bool create(unsigned int num_frames);
|
||||
bool recreate();
|
||||
bool create(unsigned int num_frames, int width = -1, int height = -1);
|
||||
bool recreate(int width = -1, int height = -1);
|
||||
bool begin_frame();
|
||||
void begin_render_pass();
|
||||
void end_render_pass();
|
||||
bool wait_on_frame(int frame_num);
|
||||
bool end_frame();
|
||||
bool end_frame(vk::Fence extra_fence = nullptr);
|
||||
// Returns true if vsync setting was changed, false if it was the same
|
||||
bool set_vsync(bool on);
|
||||
|
||||
|
@ -53,7 +53,7 @@ class Swapchain
|
|||
vk::UniqueFramebuffer framebuffer;
|
||||
};
|
||||
|
||||
vk::UniqueSwapchainKHR swapchain;
|
||||
vk::UniqueSwapchainKHR swapchain_object;
|
||||
vk::Extent2D extents;
|
||||
|
||||
vk::UniqueRenderPass render_pass;
|
||||
|
|
|
@ -214,7 +214,6 @@ void Texture::from_buffer(uint8_t *buffer, int width, int height, int byte_strid
|
|||
vk::SubmitInfo si{};
|
||||
si.setCommandBuffers(cmd.get());
|
||||
queue.submit(si);
|
||||
queue.waitIdle();
|
||||
}
|
||||
|
||||
void Texture::create(int width, int height, vk::Format fmt, vk::SamplerAddressMode wrap_mode, bool linear, bool mipmap)
|
||||
|
|
Loading…
Reference in New Issue