diff options
| author | swurl <swurl@swurl.xyz> | 2025-05-11 23:58:25 +0000 |
|---|---|---|
| committer | crueter <crueter@noreply.localhost> | 2025-05-11 23:58:25 +0000 |
| commit | 7e943732bf025bb7ead5ee3e104b88c020f9f422 (patch) | |
| tree | 0f1a403b8f44190c90f9b4fab0a8de188237f735 /src/video_core | |
| parent | 5bbb9eba32734219cd9b57dfeefaa028b1e8ab02 (diff) | |
fix a large variety of issues (#101)
- GLASM/SPIR-V mixup on Android
- potential greenscreen fix (thx suyu)
- save memory layout and add 10gb/12gb options
- potential samsung gaming hub fix
- fix layout of controller UI
- fix default settings to sensible defaults.
- note to TotK that you should increase memory layout
- Error checking for Windows linking
- fix an IDE error
- improved migration system w/threading and busy indicator
- disabled citron migration for now
- replaced some user-facing legacy strings with eden
- Added 10GB and 12GB DRAM layouts
- Fix Android black screen issues
- add discord link & update FAQ/Quickstart
- update links in about page
- add back rich presence
- add Don't show again for desktop pre alpha banner
- add citron warning to android and polaris to desktop
Signed-off-by: swurl <swurl@swurl.xyz>
Co-authored-by: Pavel Barabanov <pavelbarabanov94@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/101
Co-authored-by: swurl <swurl@swurl.xyz>
Co-committed-by: swurl <swurl@swurl.xyz>
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/host1x/ffmpeg/ffmpeg.cpp | 182 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 114 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_present_manager.cpp | 41 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_present_manager.h | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_query_cache.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.cpp | 62 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.h | 26 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.h | 4 |
8 files changed, 387 insertions, 62 deletions
diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.cpp b/src/video_core/host1x/ffmpeg/ffmpeg.cpp index 7e955223db..fe85efaab3 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp +++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// SPDX-FileCopyrightText: Copyright 2025 eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + #include "common/assert.h" #include "common/logging/log.h" #include "common/scope_exit.h" @@ -49,7 +55,8 @@ AVPixelFormat GetGpuFormat(AVCodecContext* codec_context, const AVPixelFormat* p return codec_context->pix_fmt; } -std::string AVError(int errnum) { +std::string AVError(int errnum) +{ char errbuf[AV_ERROR_MAX_STRING_SIZE] = {}; av_make_error_string(errbuf, sizeof(errbuf) - 1, errnum); return errbuf; @@ -218,6 +225,167 @@ bool DecoderContext::OpenContext(const Decoder& decoder) { return true; } +// Nasty but allows linux builds to pass. +// Requires double checks when FFMPEG gets updated. +// Hopefully a future FFMPEG update will all and expose a solution in the public API. +namespace { + +typedef struct FFCodecDefault { + const char* key; + const char* value; +} FFCodecDefault; + +typedef struct FFCodec { + /** + * The public AVCodec. See codec.h for it. + */ + AVCodec p; + + /** + * Internal codec capabilities FF_CODEC_CAP_*. + */ + unsigned caps_internal : 29; + + /** + * This field determines the type of the codec (decoder/encoder) + * and also the exact callback cb implemented by the codec. + * cb_type uses enum FFCodecType values. + */ + unsigned cb_type : 3; + + int priv_data_size; + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(struct AVCodecContext* dst, const struct AVCodecContext* src); + + /** + * Copy variables back to the user-facing context + */ + int (*update_thread_context_for_user)(struct AVCodecContext* dst, + const struct AVCodecContext* src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const FFCodecDefault* defaults; + + /** + * Initialize codec static data, called from av_codec_iterate(). + * + * This is not intended for time consuming operations as it is + * run for every codec regardless of that codec being used. + */ + void (*init_static_data)(struct FFCodec* codec); + + int (*init)(struct AVCodecContext*); + + union { + /** + * Decode to an AVFrame. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE. + * + * @param avctx codec context + * @param[out] frame AVFrame for output + * @param[out] got_frame_ptr decoder sets to 0 or 1 to indicate that + * a non-empty frame was returned in frame. + * @param[in] avpkt AVPacket containing the data to be decoded + * @return amount of bytes read from the packet on success, + * negative error code on failure + */ + int (*decode)(struct AVCodecContext* avctx, struct AVFrame* frame, int* got_frame_ptr, + struct AVPacket* avpkt); + /** + * Decode subtitle data to an AVSubtitle. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE_SUB. + * + * Apart from that this is like the decode callback. + */ + int (*decode_sub)(struct AVCodecContext* avctx, struct AVSubtitle* sub, int* got_frame_ptr, + const struct AVPacket* avpkt); + /** + * Decode API with decoupled packet/frame dataflow. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_FRAME. + * + * This function is called to get one output frame. It should call + * ff_decode_get_packet() to obtain input data. + */ + int (*receive_frame)(struct AVCodecContext* avctx, struct AVFrame* frame); + /** + * Encode data to an AVPacket. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE + * + * @param avctx codec context + * @param[out] avpkt output AVPacket + * @param[in] frame AVFrame containing the input to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode)(struct AVCodecContext* avctx, struct AVPacket* avpkt, + const struct AVFrame* frame, int* got_packet_ptr); + /** + * Encode subtitles to a raw buffer. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE_SUB. + */ + int (*encode_sub)(struct AVCodecContext* avctx, uint8_t* buf, int buf_size, + const struct AVSubtitle* sub); + /** + * Encode API with decoupled frame/packet dataflow. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_PACKET. + * + * This function is called to get one output packet. + * It should call ff_encode_get_frame() to obtain input data. + */ + int (*receive_packet)(struct AVCodecContext* avctx, struct AVPacket* avpkt); + } cb; + + int (*close)(struct AVCodecContext*); + + /** + * Flush buffers. + * Will be called when seeking + */ + void (*flush)(struct AVCodecContext*); + + /** + * Decoding only, a comma-separated list of bitstream filters to apply to + * packets before decoding. + */ + const char* bsfs; + + /** + * Array of pointers to hardware configurations supported by the codec, + * or NULL if no hardware supported. The array is terminated by a NULL + * pointer. + * + * The user can only access this field via avcodec_get_hw_config(). + */ + const struct AVCodecHWConfigInternal* const* hw_configs; + + /** + * List of supported codec_tags, terminated by FF_CODEC_TAGS_END. + */ + const uint32_t* codec_tags; +} FFCodec; + +#ifndef ANDROID +static av_always_inline const FFCodec* ffcodec(const AVCodec* codec) { + return (const FFCodec*)codec; +} +#endif +} // namespace + + bool DecoderContext::SendPacket(const Packet& packet) { m_temp_frame = std::make_shared<Frame>(); m_got_frame = 0; @@ -227,8 +395,12 @@ bool DecoderContext::SendPacket(const Packet& packet) { #ifndef ANDROID if (!m_codec_context->hw_device_ctx && m_codec_context->codec_id == AV_CODEC_ID_H264) { m_decode_order = true; - const int ret = avcodec_send_frame(m_codec_context, m_temp_frame->GetFrame()); - if (ret < 0) { + auto* codec{ffcodec(m_decoder.GetCodec())}; + if (const int ret = codec->cb.decode(m_codec_context, + m_temp_frame->GetFrame(), + &m_got_frame, + packet.GetPacket()); + ret < 0) { LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", AVError(ret)); return false; } @@ -247,9 +419,11 @@ bool DecoderContext::SendPacket(const Packet& packet) { std::shared_ptr<Frame> DecoderContext::ReceiveFrame() { // Android can randomly crash when calling decode directly, so skip. // TODO update ffmpeg and hope that fixes it. +// TODO: This is causing issues on linux, need to bisect #ifndef ANDROID if (!m_codec_context->hw_device_ctx && m_codec_context->codec_id == AV_CODEC_ID_H264) { m_decode_order = true; + auto* codec{ffcodec(m_decoder.GetCodec())}; int ret{0}; if (m_got_frame == 0) { @@ -257,7 +431,7 @@ std::shared_ptr<Frame> DecoderContext::ReceiveFrame() { auto* pkt = packet.GetPacket(); pkt->data = nullptr; pkt->size = 0; - ret = avcodec_receive_packet(m_codec_context, pkt); + ret = codec->cb.decode(m_codec_context, m_temp_frame->GetFrame(), &m_got_frame, pkt); m_codec_context->has_b_frames = 0; } diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 3260ef8cc2..30f5ff7a75 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Copyright 2025 eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + #include <algorithm> #include <array> #include <cstring> @@ -99,52 +102,91 @@ Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dl } RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window, - Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_, - std::unique_ptr<Core::Frontend::GraphicsContext> context_) try - : RendererBase(emu_window, std::move(context_)), device_memory(device_memory_), gpu(gpu_), - library(OpenLibrary(context.get())), - // Create raw Vulkan instance first - instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, - Settings::values.renderer_debug.GetValue())), - // Now create RAII wrappers for the resources in the correct order - managed_instance(MakeManagedInstance(instance, dld)), - // Create debug messenger if debug is enabled - debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance) - : vk::DebugUtilsMessenger{}), - managed_debug_messenger(Settings::values.renderer_debug - ? MakeManagedDebugUtilsMessenger(debug_messenger, instance, dld) - : ManagedDebugUtilsMessenger{}), - // Create surface - surface(CreateSurface(instance, render_window.GetWindowInfo())), - managed_surface(MakeManagedSurface(surface, instance, dld)), - device(CreateDevice(instance, dld, *surface)), - memory_allocator(device), state_tracker(), - scheduler(device, state_tracker), - swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, - render_window.GetFramebufferLayout().height), - present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, - *surface), - blit_swapchain(device_memory, device, memory_allocator, present_manager, scheduler, - PresentFiltersForDisplay), - blit_capture(device_memory, device, memory_allocator, present_manager, scheduler, - PresentFiltersForDisplay), - blit_applet(device_memory, device, memory_allocator, present_manager, scheduler, - PresentFiltersForAppletCapture), - rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, - scheduler), - applet_frame() { - - if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { + Tegra::MaxwellDeviceMemoryManager& device_memory_, + Tegra::GPU& gpu_, + std::unique_ptr<Core::Frontend::GraphicsContext> context_) +try + : RendererBase(emu_window, std::move(context_)) + , device_memory(device_memory_) + , gpu(gpu_) + , library(OpenLibrary(context.get())) + , + // Create raw Vulkan instance first + instance(CreateInstance(*library, + dld, + VK_API_VERSION_1_1, + render_window.GetWindowInfo().type, + Settings::values.renderer_debug.GetValue())) + , + // Now create RAII wrappers for the resources in the correct order + managed_instance(MakeManagedInstance(instance, dld)) + , + // Create debug messenger if debug is enabled + debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance) + : vk::DebugUtilsMessenger{}) + , managed_debug_messenger(Settings::values.renderer_debug + ? MakeManagedDebugUtilsMessenger(debug_messenger, instance, dld) + : ManagedDebugUtilsMessenger{}) + , + // Create surface + surface(CreateSurface(instance, render_window.GetWindowInfo())) + , managed_surface(MakeManagedSurface(surface, instance, dld)) + , device(CreateDevice(instance, dld, *surface)) + , memory_allocator(device) + , state_tracker() + , scheduler(device, state_tracker) + , swapchain(*surface, + device, + scheduler, + render_window.GetFramebufferLayout().width, + render_window.GetFramebufferLayout().height) + , present_manager(instance, + render_window, + device, + memory_allocator, + scheduler, + swapchain, +#ifdef ANDROID + surface) + , +#else + *surface) + , +#endif + blit_swapchain(device_memory, + device, + memory_allocator, + present_manager, + scheduler, + PresentFiltersForDisplay) + , blit_capture(device_memory, + device, + memory_allocator, + present_manager, + scheduler, + PresentFiltersForDisplay) + , blit_applet(device_memory, + device, + memory_allocator, + present_manager, + scheduler, + PresentFiltersForAppletCapture) + , rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, scheduler) + , applet_frame() { + + if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { turbo_mode.emplace(instance, dld); scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); }); } +#ifndef ANDROID // Release ownership from the old instance and surface instance.release(); surface.release(); if (Settings::values.renderer_debug) { debug_messenger.release(); } +#endif Report(); } catch (const vk::Exception& exception) { diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 8f5edeae24..a448dc5288 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -95,15 +95,31 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form } // Anonymous namespace -PresentManager::PresentManager(const vk::Instance& instance_, Core::Frontend::EmuWindow& render_window_, - const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, - Swapchain& swapchain_, VkSurfaceKHR_T* surface_handle_) - : instance{instance_}, render_window{render_window_}, device{device_}, - memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, - surface_handle{surface_handle_}, - blit_supported{CanBlitToSwapchain(device.GetPhysical(), - swapchain.GetImageViewFormat())}, - use_present_thread{Settings::values.async_presentation.GetValue()} { +PresentManager::PresentManager(const vk::Instance& instance_, + Core::Frontend::EmuWindow& render_window_, + const Device& device_, + MemoryAllocator& memory_allocator_, + Scheduler& scheduler_, + Swapchain& swapchain_, +#ifdef ANDROID + vk::SurfaceKHR& surface_) +#else + VkSurfaceKHR_T* surface_handle_) +#endif + : instance{instance_} + , render_window{render_window_} + , device{device_} + , memory_allocator{memory_allocator_} + , scheduler{scheduler_} + , swapchain{swapchain_} +#ifdef ANDROID + , surface{surface_} +#else + , surface_handle{surface_handle_} +#endif + , blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())} + , use_present_thread{Settings::values.async_presentation.GetValue()} +{ SetImageCount(); auto& dld = device.GetLogical(); @@ -289,7 +305,11 @@ void PresentManager::PresentThread(std::stop_token token) { } void PresentManager::RecreateSwapchain(Frame* frame) { +#ifndef ANDROID swapchain.Create(surface_handle, frame->width, frame->height); // Pass raw pointer +#else + swapchain.Create(*surface, frame->width, frame->height); // Pass raw pointer +#endif SetImageCount(); } @@ -307,6 +327,9 @@ void PresentManager::CopyToSwapchain(Frame* frame) { try { // Recreate surface and swapchain if needed. if (requires_recreation) { +#ifdef ANDROID + surface = CreateSurface(instance, render_window.GetWindowInfo()); +#endif RecreateSwapchain(frame); } diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 96850ed56f..5820280602 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h @@ -37,9 +37,17 @@ struct Frame { class PresentManager { public: - PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window, - const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler, - Swapchain& swapchain, VkSurfaceKHR_T* surface_handle); + PresentManager(const vk::Instance& instance, + Core::Frontend::EmuWindow& render_window, + const Device& device, + MemoryAllocator& memory_allocator, + Scheduler& scheduler, + Swapchain& swapchain, +#ifdef ANDROID + vk::SurfaceKHR& surface); +#else + VkSurfaceKHR_T* surface_handle); +#endif ~PresentManager(); /// Returns the last used presentation frame @@ -73,7 +81,11 @@ private: MemoryAllocator& memory_allocator; Scheduler& scheduler; Swapchain& swapchain; +#ifdef ANDROID + vk::SurfaceKHR& surface; +#else VkSurfaceKHR_T* surface_handle; +#endif vk::CommandPool cmdpool; std::vector<Frame> frames; std::queue<Frame*> present_queue; diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index a28296bdaf..44c06eddf3 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -176,7 +176,7 @@ public: PauseCounter(); } AbandonCurrentQuery(); - std::function<void()> func([this, counts = pending_flush_queries.size()] { + std::function<void()> func([this] { amend_value = 0; accumulation_value = 0; }); diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index ec96b75036..a002ca83a0 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -105,23 +105,58 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap } // Anonymous namespace -Swapchain::Swapchain(VkSurfaceKHR_T* surface_handle_, const Device& device_, Scheduler& scheduler_, - u32 width_, u32 height_) - : surface_handle{surface_handle_}, device{device_}, scheduler{scheduler_} { +Swapchain::Swapchain( +#ifdef ANDROID + VkSurfaceKHR surface_, +#else + VkSurfaceKHR_T* surface_handle_, +#endif + const Device& device_, + Scheduler& scheduler_, + u32 width_, + u32 height_) +#ifdef ANDROID + : surface(surface_) +#else + : surface_handle{surface_handle_} +#endif + , device{device_} + , scheduler{scheduler_} +{ +#ifdef ANDROID + Create(surface, width_, height_); +#else Create(surface_handle, width_, height_); +#endif } Swapchain::~Swapchain() = default; -void Swapchain::Create(VkSurfaceKHR_T* surface_handle_, u32 width_, u32 height_) { +void Swapchain::Create( +#ifdef ANDROID + VkSurfaceKHR surface_, +#else + VkSurfaceKHR_T* surface_handle_, +#endif + u32 width_, + u32 height_) +{ is_outdated = false; is_suboptimal = false; width = width_; height = height_; +#ifdef ANDROID + surface = surface_; +#else surface_handle = surface_handle_; +#endif const auto physical_device = device.GetPhysical(); +#ifdef ANDROID + const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; +#else const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface_handle)}; +#endif if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) { return; } @@ -199,10 +234,17 @@ void Swapchain::Present(VkSemaphore render_semaphore) { void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) { const auto physical_device{device.GetPhysical()}; + +#ifdef ANDROID + const auto formats{physical_device.GetSurfaceFormatsKHR(surface)}; + const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface); +#else const auto formats{physical_device.GetSurfaceFormatsKHR(surface_handle)}; const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface_handle); - has_mailbox = std::find(present_modes.begin(), present_modes.end(), - VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.end(); +#endif + + has_mailbox = std::find(present_modes.begin(), present_modes.end(), VK_PRESENT_MODE_MAILBOX_KHR) + != present_modes.end(); has_imm = std::find(present_modes.begin(), present_modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != present_modes.end(); has_fifo_relaxed = std::find(present_modes.begin(), present_modes.end(), @@ -228,7 +270,11 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .pNext = nullptr, .flags = 0, +#ifdef ANDROID + .surface = surface, +#else .surface = surface_handle, +#endif .minImageCount = requested_image_count, .imageFormat = surface_format.format, .imageColorSpace = surface_format.colorSpace, @@ -269,7 +315,11 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) { swapchain_ci.flags |= VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR; } // Request the size again to reduce the possibility of a TOCTOU race condition. +#ifdef ANDROID + const auto updated_capabilities = physical_device.GetSurfaceCapabilitiesKHR(surface); +#else const auto updated_capabilities = physical_device.GetSurfaceCapabilitiesKHR(surface_handle); +#endif swapchain_ci.imageExtent = ChooseSwapExtent(updated_capabilities, width, height); // Don't add code within this and the swapchain creation. swapchain = device.GetLogical().CreateSwapchainKHR(swapchain_ci); diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index f5090c27f4..b3e1c4f025 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -21,12 +21,27 @@ class Scheduler; class Swapchain { public: - explicit Swapchain(VkSurfaceKHR_T* surface_handle, const Device& device, Scheduler& scheduler, u32 width, - u32 height); + explicit Swapchain( +#ifdef ANDROID + VkSurfaceKHR surface, +#else + VkSurfaceKHR_T* surface_handle, +#endif + const Device& device, + Scheduler& scheduler, + u32 width, + u32 height); ~Swapchain(); /// Creates (or recreates) the swapchain with a given size. - void Create(VkSurfaceKHR_T* surface_handle, u32 width, u32 height); + void Create( +#ifdef ANDROID + VkSurfaceKHR surface, +#else + VkSurfaceKHR_T* surface_handle, +#endif + u32 width, + u32 height); /// Acquires the next image in the swapchain, waits as needed. bool AcquireNextImage(); @@ -110,7 +125,12 @@ private: bool NeedsPresentModeUpdate() const; +#ifdef ANDROID + VkSurfaceKHR surface; +#else VkSurfaceKHR_T* surface_handle; +#endif + const Device& device; Scheduler& scheduler; diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index aa9fb8e17b..4607bf516c 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -430,6 +430,7 @@ public: return handle != nullptr; } +#ifndef ANDROID /** * Releases ownership of the managed handle. * The caller is responsible for managing the lifetime of the returned handle. @@ -438,6 +439,7 @@ public: Type release() noexcept { return std::exchange(handle, nullptr); } +#endif protected: Type handle = nullptr; @@ -510,6 +512,7 @@ public: return handle != nullptr; } +#ifndef ANDROID /** * Releases ownership of the managed handle. * The caller is responsible for managing the lifetime of the returned handle. @@ -518,6 +521,7 @@ public: Type release() noexcept { return std::exchange(handle, nullptr); } +#endif protected: Type handle = nullptr; |
