Skip to content

Commit

Permalink
renderer_vulkan: Address vulkan surface recreation issues (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
PabloMK7 authored Jul 16, 2024
1 parent 55748d7 commit 959a66d
Show file tree
Hide file tree
Showing 9 changed files with 24 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ android {
namespace = "org.citra.citra_emu"

compileSdkVersion = "android-34"
ndkVersion = "26.1.10909125"
ndkVersion = "26.3.11579264"

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
import org.citra.citra_emu.fragments.MessageDialogFragment
import org.citra.citra_emu.utils.ControllerMappingHelper
import org.citra.citra_emu.utils.FileBrowserHelper
import org.citra.citra_emu.utils.ForegroundService
import org.citra.citra_emu.utils.EmulationLifecycleUtil
import org.citra.citra_emu.utils.EmulationMenuSettings
import org.citra.citra_emu.utils.ThemeUtil
Expand All @@ -47,7 +46,6 @@ import org.citra.citra_emu.viewmodel.EmulationViewModel
class EmulationActivity : AppCompatActivity() {
private val preferences: SharedPreferences
get() = PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
private var foregroundService: Intent? = null
var isActivityRecreated = false

private val settingsViewModel: SettingsViewModel by viewModels()
Expand Down Expand Up @@ -85,10 +83,6 @@ class EmulationActivity : AppCompatActivity() {
windowManager.defaultDisplay.rotation
)

// Start a foreground service to prevent the app from getting killed in the background
foregroundService = Intent(this, ForegroundService::class.java)
startForegroundService(foregroundService)

EmulationLifecycleUtil.addShutdownHook(hook = { this.finish() })
}

Expand All @@ -112,7 +106,6 @@ class EmulationActivity : AppCompatActivity() {

override fun onDestroy() {
EmulationLifecycleUtil.clear()
stopForegroundService(this)
super.onDestroy()
}

Expand Down Expand Up @@ -452,12 +445,4 @@ class EmulationActivity : AppCompatActivity() {

OnFilePickerResult(result.toString())
}

companion object {
fun stopForegroundService(activity: Activity) {
val startIntent = Intent(activity, ForegroundService::class.java)
startIntent.action = ForegroundService.ACTION_STOP
activity.startForegroundService(startIntent)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
}

// Dismiss previous notifications (should not happen unless a crash occurred)
EmulationActivity.stopForegroundService(this)

setInsets()
}

Expand All @@ -170,7 +167,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}

override fun onDestroy() {
EmulationActivity.stopForegroundService(this)
super.onDestroy()
}

Expand Down
8 changes: 6 additions & 2 deletions src/android/app/src/main/jni/emu_window/emu_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ static void UpdateLandscapeScreenLayout() {
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
}

void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
render_window = surface;
bool EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
if (render_window == surface) {
return false;
}

render_window = surface;
window_info.type = Frontend::WindowSystemType::Android;
window_info.render_surface = surface;

StopPresenting();
OnFramebufferSizeChanged();
return true;
}

bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {
Expand Down
2 changes: 1 addition & 1 deletion src/android/app/src/main/jni/emu_window/emu_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class EmuWindow_Android : public Frontend::EmuWindow {
~EmuWindow_Android();

/// Called by the onSurfaceChanges() method to change the surface
void OnSurfaceChanged(ANativeWindow* surface);
bool OnSurfaceChanged(ANativeWindow* surface);

/// Handles touch event that occur.(Touched or released)
bool OnTouchEvent(int x, int y, bool pressed);
Expand Down
5 changes: 3 additions & 2 deletions src/android/app/src/main/jni/native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,13 @@ void Java_org_citra_citra_1emu_NativeLibrary_surfaceChanged(JNIEnv* env,
jobject surf) {
s_surf = ANativeWindow_fromSurface(env, surf);

bool notify = false;
if (window) {
window->OnSurfaceChanged(s_surf);
notify = window->OnSurfaceChanged(s_surf);
}

auto& system = Core::System::GetInstance();
if (system.IsPoweredOn()) {
if (notify && system.IsPoweredOn()) {
system.GPU().Renderer().NotifySurfaceChanged();
}

Expand Down
2 changes: 1 addition & 1 deletion src/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
2 changes: 1 addition & 1 deletion src/video_core/renderer_vulkan/vk_present_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ void PresentWindow::CopyToSwapchain(Frame* frame) {
.pSignalSemaphores = &present_ready,
};

std::scoped_lock submit_lock{scheduler.submit_mutex};
std::scoped_lock submit_lock{scheduler.submit_mutex, recreate_surface_mutex};

try {
graphics_queue.submit(submit_info, frame->present_done);
Expand Down
18 changes: 11 additions & 7 deletions src/video_core/renderer_vulkan/vk_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,13 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) {
}

bool Swapchain::AcquireNextImage() {
if (needs_recreation) {
return false;
}

MICROPROFILE_SCOPE(Vulkan_Acquire);
vk::Device device = instance.GetDevice();
vk::Result result =
const vk::Device device = instance.GetDevice();
const vk::Result result =
device.acquireNextImageKHR(swapchain, std::numeric_limits<u64>::max(),
image_acquired[frame_index], VK_NULL_HANDLE, &image_index);

Expand All @@ -102,10 +106,6 @@ bool Swapchain::AcquireNextImage() {
}

void Swapchain::Present() {
if (needs_recreation) {
return;
}

const vk::PresentInfoKHR present_info = {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &present_ready[image_index],
Expand All @@ -119,6 +119,10 @@ void Swapchain::Present() {
[[maybe_unused]] vk::Result result = instance.GetPresentQueue().presentKHR(present_info);
} catch (vk::OutOfDateKHRError&) {
needs_recreation = true;
return;
} catch (vk::SurfaceLostKHRError&) {
needs_recreation = true;
return;
} catch (const vk::SystemError& err) {
LOG_CRITICAL(Render_Vulkan, "Swapchain presentation failed {}", err.what());
UNREACHABLE();
Expand Down Expand Up @@ -268,4 +272,4 @@ void Swapchain::SetupImages() {
}
}

} // namespace Vulkan
} // namespace Vulkan

0 comments on commit 959a66d

Please sign in to comment.