android: vulkan: Recreate surface after suspension & adapt to async. presentation.
This commit is contained in:
parent
65dc35a1a5
commit
117bc2ae6c
8 changed files with 39 additions and 26 deletions
|
@ -217,6 +217,7 @@ void Config::ReadValues() {
|
||||||
ReadSetting("Renderer", Settings::values.accelerate_astc);
|
ReadSetting("Renderer", Settings::values.accelerate_astc);
|
||||||
ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
|
ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
|
||||||
ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
|
ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
|
||||||
|
ReadSetting("Renderer", Settings::values.async_presentation);
|
||||||
|
|
||||||
// Use GPU accuracy normal by default on Android
|
// Use GPU accuracy normal by default on Android
|
||||||
Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger(
|
Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger(
|
||||||
|
@ -230,10 +231,6 @@ void Config::ReadValues() {
|
||||||
Settings::values.renderer_force_max_clock =
|
Settings::values.renderer_force_max_clock =
|
||||||
config->GetBoolean("Renderer", "force_max_clock", true);
|
config->GetBoolean("Renderer", "force_max_clock", true);
|
||||||
|
|
||||||
// Enable asynchronous presentation by default on Android
|
|
||||||
Settings::values.async_presentation =
|
|
||||||
config->GetBoolean("Renderer", "async_presentation", true);
|
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
ReadSetting("Audio", Settings::values.sink_id);
|
ReadSetting("Audio", Settings::values.sink_id);
|
||||||
ReadSetting("Audio", Settings::values.audio_output_device_id);
|
ReadSetting("Audio", Settings::values.audio_output_device_id);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "jni/emu_window/emu_window.h"
|
#include "jni/emu_window/emu_window.h"
|
||||||
|
|
||||||
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
m_render_window = surface;
|
window_info.render_surface = reinterpret_cast<void*>(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
|
void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
|
||||||
|
@ -37,7 +37,7 @@ void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timesta
|
||||||
float gyro_y, float gyro_z, float accel_x,
|
float gyro_y, float gyro_z, float accel_x,
|
||||||
float accel_y, float accel_z) {
|
float accel_y, float accel_z) {
|
||||||
m_input_subsystem->GetVirtualGamepad()->SetMotionState(
|
m_input_subsystem->GetVirtualGamepad()->SetMotionState(
|
||||||
player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z);
|
player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnReadNfcTag(std::span<u8> data) {
|
void EmuWindow_Android::OnReadNfcTag(std::span<u8> data) {
|
||||||
|
@ -65,9 +65,8 @@ EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsyste
|
||||||
// Ensures that we emulate with the correct aspect ratio.
|
// Ensures that we emulate with the correct aspect ratio.
|
||||||
UpdateCurrentFramebufferLayout(m_window_width, m_window_height);
|
UpdateCurrentFramebufferLayout(m_window_width, m_window_height);
|
||||||
|
|
||||||
m_host_window = surface;
|
|
||||||
window_info.type = Core::Frontend::WindowSystemType::Android;
|
window_info.type = Core::Frontend::WindowSystemType::Android;
|
||||||
window_info.render_surface = reinterpret_cast<void*>(m_host_window);
|
window_info.render_surface = reinterpret_cast<void*>(surface);
|
||||||
|
|
||||||
m_input_subsystem->Initialize();
|
m_input_subsystem->Initialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,6 @@ public:
|
||||||
private:
|
private:
|
||||||
InputCommon::InputSubsystem* m_input_subsystem{};
|
InputCommon::InputSubsystem* m_input_subsystem{};
|
||||||
|
|
||||||
ANativeWindow* m_render_window{};
|
|
||||||
ANativeWindow* m_host_window{};
|
|
||||||
|
|
||||||
float m_window_width{};
|
float m_window_width{};
|
||||||
float m_window_height{};
|
float m_window_height{};
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
|
||||||
state_tracker(), scheduler(device, state_tracker),
|
state_tracker(), scheduler(device, state_tracker),
|
||||||
swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
|
swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
|
||||||
render_window.GetFramebufferLayout().height, false),
|
render_window.GetFramebufferLayout().height, false),
|
||||||
present_manager(render_window, device, memory_allocator, scheduler, swapchain),
|
present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
|
||||||
|
surface),
|
||||||
blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager,
|
blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager,
|
||||||
scheduler, screen_info),
|
scheduler, screen_info),
|
||||||
rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator,
|
rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator,
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
|
#include "core/frontend/emu_window.h"
|
||||||
#include "video_core/renderer_vulkan/vk_present_manager.h"
|
#include "video_core/renderer_vulkan/vk_present_manager.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_surface.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_,
|
PresentManager::PresentManager(const vk::Instance& instance_,
|
||||||
|
Core::Frontend::EmuWindow& render_window_, const Device& device_,
|
||||||
MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
|
MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
|
||||||
Swapchain& swapchain_)
|
Swapchain& swapchain_, vk::SurfaceKHR& surface_)
|
||||||
: render_window{render_window_}, device{device_},
|
: instance{instance_}, render_window{render_window_}, device{device_},
|
||||||
memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_},
|
memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_},
|
||||||
blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())},
|
surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(),
|
||||||
|
swapchain.GetImageViewFormat())},
|
||||||
use_present_thread{Settings::values.async_presentation.GetValue()},
|
use_present_thread{Settings::values.async_presentation.GetValue()},
|
||||||
image_count{swapchain.GetImageCount()} {
|
image_count{swapchain.GetImageCount()}, last_render_surface{
|
||||||
|
render_window_.GetWindowInfo().render_surface} {
|
||||||
|
|
||||||
auto& dld = device.GetLogical();
|
auto& dld = device.GetLogical();
|
||||||
cmdpool = dld.CreateCommandPool({
|
cmdpool = dld.CreateCommandPool({
|
||||||
|
@ -290,10 +295,19 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
|
||||||
MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
|
MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
|
||||||
|
|
||||||
const auto recreate_swapchain = [&] {
|
const auto recreate_swapchain = [&] {
|
||||||
swapchain.Create(frame->width, frame->height, frame->is_srgb);
|
swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb);
|
||||||
image_count = swapchain.GetImageCount();
|
image_count = swapchain.GetImageCount();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
// If the frontend recreated the surface, recreate the renderer surface and swapchain.
|
||||||
|
if (last_render_surface != render_window.GetWindowInfo().render_surface) {
|
||||||
|
last_render_surface = render_window.GetWindowInfo().render_surface;
|
||||||
|
surface = CreateSurface(instance, render_window.GetWindowInfo());
|
||||||
|
recreate_swapchain();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the size or colorspace of the incoming frames has changed, recreate the swapchain
|
// If the size or colorspace of the incoming frames has changed, recreate the swapchain
|
||||||
// to account for that.
|
// to account for that.
|
||||||
const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb);
|
const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb);
|
||||||
|
@ -454,4 +468,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
|
||||||
swapchain.Present(render_semaphore);
|
swapchain.Present(render_semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
|
@ -37,8 +37,9 @@ struct Frame {
|
||||||
|
|
||||||
class PresentManager {
|
class PresentManager {
|
||||||
public:
|
public:
|
||||||
PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device,
|
PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window,
|
||||||
MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain);
|
const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler,
|
||||||
|
Swapchain& swapchain, vk::SurfaceKHR& surface);
|
||||||
~PresentManager();
|
~PresentManager();
|
||||||
|
|
||||||
/// Returns the last used presentation frame
|
/// Returns the last used presentation frame
|
||||||
|
@ -60,11 +61,13 @@ private:
|
||||||
void CopyToSwapchain(Frame* frame);
|
void CopyToSwapchain(Frame* frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const vk::Instance& instance;
|
||||||
Core::Frontend::EmuWindow& render_window;
|
Core::Frontend::EmuWindow& render_window;
|
||||||
const Device& device;
|
const Device& device;
|
||||||
MemoryAllocator& memory_allocator;
|
MemoryAllocator& memory_allocator;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
Swapchain& swapchain;
|
Swapchain& swapchain;
|
||||||
|
vk::SurfaceKHR& surface;
|
||||||
vk::CommandPool cmdpool;
|
vk::CommandPool cmdpool;
|
||||||
std::vector<Frame> frames;
|
std::vector<Frame> frames;
|
||||||
std::queue<Frame*> present_queue;
|
std::queue<Frame*> present_queue;
|
||||||
|
@ -77,7 +80,8 @@ private:
|
||||||
std::jthread present_thread;
|
std::jthread present_thread;
|
||||||
bool blit_supported;
|
bool blit_supported;
|
||||||
bool use_present_thread;
|
bool use_present_thread;
|
||||||
std::size_t image_count;
|
std::size_t image_count{};
|
||||||
|
void* last_render_surface{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -107,16 +107,17 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap
|
||||||
Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
|
Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
|
||||||
u32 width_, u32 height_, bool srgb)
|
u32 width_, u32 height_, bool srgb)
|
||||||
: surface{surface_}, device{device_}, scheduler{scheduler_} {
|
: surface{surface_}, device{device_}, scheduler{scheduler_} {
|
||||||
Create(width_, height_, srgb);
|
Create(surface_, width_, height_, srgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
Swapchain::~Swapchain() = default;
|
Swapchain::~Swapchain() = default;
|
||||||
|
|
||||||
void Swapchain::Create(u32 width_, u32 height_, bool srgb) {
|
void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) {
|
||||||
is_outdated = false;
|
is_outdated = false;
|
||||||
is_suboptimal = false;
|
is_suboptimal = false;
|
||||||
width = width_;
|
width = width_;
|
||||||
height = height_;
|
height = height_;
|
||||||
|
surface = surface_;
|
||||||
|
|
||||||
const auto physical_device = device.GetPhysical();
|
const auto physical_device = device.GetPhysical();
|
||||||
const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
|
const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
~Swapchain();
|
~Swapchain();
|
||||||
|
|
||||||
/// Creates (or recreates) the swapchain with a given size.
|
/// Creates (or recreates) the swapchain with a given size.
|
||||||
void Create(u32 width, u32 height, bool srgb);
|
void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb);
|
||||||
|
|
||||||
/// Acquires the next image in the swapchain, waits as needed.
|
/// Acquires the next image in the swapchain, waits as needed.
|
||||||
bool AcquireNextImage();
|
bool AcquireNextImage();
|
||||||
|
@ -118,7 +118,7 @@ private:
|
||||||
|
|
||||||
bool NeedsPresentModeUpdate() const;
|
bool NeedsPresentModeUpdate() const;
|
||||||
|
|
||||||
const VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
const Device& device;
|
const Device& device;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue