From e4768f9b8091bdbb1a4f4c7e8843d3383cd301fd Mon Sep 17 00:00:00 2001 From: BearOso Date: Tue, 24 Jan 2023 17:33:46 -0600 Subject: [PATCH] Wayland compatibility with Vulkan. --- gtk/CMakeLists.txt | 17 +--- gtk/src/gtk_display.cpp | 3 +- gtk/src/gtk_display_driver_vulkan.cpp | 34 ++++++-- gtk/src/gtk_display_driver_vulkan.h | 8 ++ gtk/src/gtk_wayland_surface.cpp | 119 ++++++++++++++++++++++++++ gtk/src/gtk_wayland_surface.h | 38 ++++++++ vulkan/vulkan_context.cpp | 58 ++++++++++--- vulkan/vulkan_context.hpp | 19 +++- vulkan/vulkan_shader_chain.cpp | 8 +- vulkan/vulkan_slang_pipeline.hpp | 3 +- vulkan/vulkan_swapchain.cpp | 40 ++++++--- vulkan/vulkan_swapchain.hpp | 8 +- vulkan/vulkan_texture.cpp | 1 - 13 files changed, 293 insertions(+), 63 deletions(-) create mode 100644 gtk/src/gtk_wayland_surface.cpp create mode 100644 gtk/src/gtk_wayland_surface.h diff --git a/gtk/CMakeLists.txt b/gtk/CMakeLists.txt index 3af9f44b..6b3c34fb 100644 --- a/gtk/CMakeLists.txt +++ b/gtk/CMakeLists.txt @@ -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}) diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp index a3aeb571..689d2c2f 100644 --- a/gtk/src/gtk_display.cpp +++ b/gtk/src/gtk_display.cpp @@ -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 diff --git a/gtk/src/gtk_display_driver_vulkan.cpp b/gtk/src/gtk_display_driver_vulkan.cpp index 1c806e93..1f8a021a 100644 --- a/gtk/src/gtk_display_driver_vulkan.cpp +++ b/gtk/src/gtk_display_driver_vulkan.cpp @@ -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(); - context->init(display, xid); + +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj())) + { + wayland_surface = std::make_unique(); + 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) diff --git a/gtk/src/gtk_display_driver_vulkan.h b/gtk/src/gtk_display_driver_vulkan.h index d24f852e..c3386105 100644 --- a/gtk/src/gtk_display_driver_vulkan.h +++ b/gtk/src/gtk_display_driver_vulkan.h @@ -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 wayland_surface; +#endif + void create_pipeline(); vk::UniqueDescriptorSetLayout descriptor_set_layout; vk::UniquePipelineLayout pipeline_layout; diff --git a/gtk/src/gtk_wayland_surface.cpp b/gtk/src/gtk_wayland_surface.cpp new file mode 100644 index 00000000..a6d79282 --- /dev/null +++ b/gtk/src/gtk_wayland_surface.cpp @@ -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 +#include + +#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); +} \ No newline at end of file diff --git a/gtk/src/gtk_wayland_surface.h b/gtk/src/gtk_wayland_surface.h new file mode 100644 index 00000000..05a354c5 --- /dev/null +++ b/gtk/src/gtk_wayland_surface.h @@ -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; +}; diff --git a/vulkan/vulkan_context.cpp b/vulkan/vulkan_context.cpp index 7fcc16a5..b0d9264c 100644 --- a/vulkan/vulkan_context.cpp +++ b/vulkan/vulkan_context.cpp @@ -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 extensions = { VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_EXTENSION_NAME }; + std::vector 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(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() diff --git a/vulkan/vulkan_context.hpp b/vulkan/vulkan_context.hpp index 1946b3e1..ce64f991 100644 --- a/vulkan/vulkan_context.hpp +++ b/vulkan/vulkan_context.hpp @@ -1,6 +1,9 @@ #pragma once -#include "X11/Xlib.h" +//"VK_USE_PLATFORM_WAYLAND_KHR" +#ifdef VK_USE_PLATFORM_XLIB_KHR +#include +#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; diff --git a/vulkan/vulkan_shader_chain.cpp b/vulkan/vulkan_shader_chain.cpp index 89418856..b7907532 100644 --- a/vulkan/vulkan_shader_chain.cpp +++ b/vulkan/vulkan_shader_chain.cpp @@ -235,17 +235,18 @@ bool ShaderChain::load_shader_preset(std::string filename) if (p.samplers.size() > 0) num_samplers += p.samplers.size(); } + std::array 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); diff --git a/vulkan/vulkan_slang_pipeline.hpp b/vulkan/vulkan_slang_pipeline.hpp index 3467eb0d..7dfd89e9 100644 --- a/vulkan/vulkan_slang_pipeline.hpp +++ b/vulkan/vulkan_slang_pipeline.hpp @@ -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; diff --git a/vulkan/vulkan_swapchain.cpp b/vulkan/vulkan_swapchain.cpp index 0d15ac38..5658b728 100644 --- a/vulkan/vulkan_swapchain.cpp +++ b/vulkan/vulkan_swapchain.cpp @@ -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); diff --git a/vulkan/vulkan_swapchain.hpp b/vulkan/vulkan_swapchain.hpp index 05727776..4a9b1362 100644 --- a/vulkan/vulkan_swapchain.hpp +++ b/vulkan/vulkan_swapchain.hpp @@ -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; diff --git a/vulkan/vulkan_texture.cpp b/vulkan/vulkan_texture.cpp index 13d2bdf7..c9dc491b 100644 --- a/vulkan/vulkan_texture.cpp +++ b/vulkan/vulkan_texture.cpp @@ -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)