Fix trying to acquire image when the surface is lost

This commit is contained in:
SSimco
2023-06-15 06:53:59 +03:00
parent 479e7c427a
commit 3c8fe805b8
5 changed files with 69 additions and 26 deletions
@@ -2631,7 +2631,13 @@ bool VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow)
m_padCloseReadySemaphore.notify();
return false;
}
#if __ANDROID__
std::unique_lock lock(m_surfaceMutex);
m_surfaceCondVar.wait(lock,[&](){
auto& chainInfo = GetChainInfoPtr(mainWindow);
return chainInfo && chainInfo->surface;
});
#endif // __ANDROID__
auto& chainInfo = GetChainInfo(mainWindow);
if (chainInfo.swapchainImageIndex != -1)
@@ -3770,7 +3776,29 @@ void VulkanRenderer::AppendOverlayDebugInfo()
ImGui::Text("--- Tex heaps ---");
memoryManager->appendOverlayHeapDebugInfo();
}
#if __ANDROID__
void VulkanRenderer::ClearSurface(bool mainWindow)
{
std::lock_guard lock(m_surfaceMutex);
auto& chainInfo = GetChainInfoPtr(mainWindow);
if(!chainInfo || !chainInfo->surface)
return;
vkDestroySurfaceKHR(m_instance, chainInfo->surface, nullptr);
chainInfo->surface = nullptr;
}
void VulkanRenderer::NotifySurfaceChanged(bool mainWindow)
{
std::lock_guard lock(m_surfaceMutex);
auto& chainInfo = GetChainInfoPtr(mainWindow);
if(!chainInfo)
return;
if(mainWindow)
chainInfo->surface = CreateFramebufferSurface(m_instance, gui_getWindowInfo().canvas_main);
else
chainInfo->surface = CreateFramebufferSurface(m_instance, gui_getWindowInfo().canvas_pad);
m_surfaceCondVar.notify_one();
}
#endif // __ANDROID__
void VKRDestructibleObject::flagForCurrentCommandBuffer()
{
m_lastCmdBufferId = VulkanRenderer::GetInstance()->GetCurrentCommandBufferId();
@@ -183,7 +183,10 @@ public:
void GetDeviceFeatures();
void DetermineVendor();
void InitializeSurface(const Vector2i& size, bool mainWindow);
#if __ANDROID__
void ClearSurface(bool mainWindow);
void NotifySurfaceChanged(bool mainWindow);
#endif // __ANDROID
const std::unique_ptr<SwapchainInfoVk>& GetChainInfoPtr(bool mainWindow) const;
SwapchainInfoVk& GetChainInfo(bool mainWindow) const;
@@ -610,6 +613,11 @@ private:
VkPipelineLayout m_pipelineLayout{nullptr};
VkCommandPool m_commandPool{ nullptr };
#if __ANDROID__
std::mutex m_surfaceMutex;
std::condition_variable m_surfaceCondVar;
#endif // __ANDROID__
// buffer to cache uniform vars
VkBuffer m_uniformVarBuffer = VK_NULL_HANDLE;
VkDeviceMemory m_uniformVarBufferMemory = VK_NULL_HANDLE;
+14 -1
View File
@@ -180,10 +180,23 @@ Java_info_cemu_Cemu_NativeLibrary_initializeRendererSurface(JNIEnv *env, jclass
VulkanRenderer::GetInstance()->InitializeSurface(
{width, height},
is_main_canvas);
}
extern "C"
JNIEXPORT void JNICALL
Java_info_cemu_Cemu_NativeLibrary_setDPI(JNIEnv *env, jclass clazz, jfloat dpi) {
auto& windowInfo = gui_getWindowInfo();
auto &windowInfo = gui_getWindowInfo();
windowInfo.dpi_scale = windowInfo.pad_dpi_scale = dpi;
}
extern "C"
JNIEXPORT void JNICALL
Java_info_cemu_Cemu_NativeLibrary_clearSurface(JNIEnv *env, jclass clazz, jboolean is_main_canvas) {
VulkanRenderer::GetInstance()->ClearSurface(is_main_canvas);
}
extern "C"
JNIEXPORT void JNICALL
Java_info_cemu_Cemu_NativeLibrary_recreateRenderSurface(JNIEnv *env, jclass clazz,
jboolean is_main_canvas) {
VulkanRenderer::GetInstance()->NotifySurfaceChanged(is_main_canvas);
}
@@ -1,24 +1,16 @@
package info.cemu.Cemu;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import info.cemu.Cemu.databinding.FragmentEmulationBinding;
import info.cemu.Cemu.databinding.FragmentGamesBinding;
public class EmulationFragment extends Fragment implements SurfaceHolder.Callback {
FragmentEmulationBinding binding;
@@ -35,7 +27,7 @@ public class EmulationFragment extends Fragment implements SurfaceHolder.Callbac
}
long gameTitleId;
boolean isRunning;
boolean isGameRunning;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -55,15 +47,6 @@ public class EmulationFragment extends Fragment implements SurfaceHolder.Callbac
return binding.getRoot();
}
private void startGame() {
if (!isRunning) {
isRunning = true;
NativeLibrary.initializerRenderer();
NativeLibrary.initializeRendererSurface(true);
NativeLibrary.startGame(gameTitleId);
}
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
@@ -73,11 +56,18 @@ public class EmulationFragment extends Fragment implements SurfaceHolder.Callbac
public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
NativeLibrary.setSurface(surfaceHolder.getSurface(), true);
NativeLibrary.setSurfaceSize(width, height, true);
startGame();
if (!isGameRunning) {
isGameRunning = true;
NativeLibrary.initializerRenderer();
NativeLibrary.initializeRendererSurface(true);
NativeLibrary.startGame(gameTitleId);
}else{
NativeLibrary.recreateRenderSurface(true);
}
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
NativeLibrary.clearSurface(true);
}
}
@@ -11,6 +11,8 @@ public class NativeLibrary {
public static native void setSurface(Surface surface, boolean isMainCanvas);
public static native void clearSurface(boolean isMainCanvas);
public static native void setSurfaceSize(int width, int height, boolean isMainCanvas);
public static native void initializerRenderer();
@@ -19,6 +21,8 @@ public class NativeLibrary {
public static native void startGame(long titleId);
public static native void recreateRenderSurface(boolean isMainCanvas);
public interface GameTitleLoadedCallback {
void onGameTitleLoaded(long titleId, String title);