mirror of
https://github.com/SSimco/Cemu.git
synced 2024-11-23 05:19:40 +00:00
Pass c++ exception to java for renderer functions
This commit is contained in:
parent
80ea25b10f
commit
be23c47cac
@ -260,6 +260,8 @@ void VulkanRenderer::GetDeviceFeatures()
|
||||
physicalDeviceFeatures2.pNext = prevStruct;
|
||||
|
||||
vkGetPhysicalDeviceFeatures2(m_physicalDevice, &physicalDeviceFeatures2);
|
||||
m_featureControl.deviceFeatures.geometry_shader = physicalDeviceFeatures2.features.geometryShader;
|
||||
m_featureControl.deviceFeatures.logic_op = physicalDeviceFeatures2.features.logicOp;
|
||||
|
||||
/* Get Vulkan device properties and limits */
|
||||
VkPhysicalDeviceFloatControlsPropertiesKHR pfcp{};
|
||||
@ -451,10 +453,8 @@ VulkanRenderer::VulkanRenderer()
|
||||
deviceFeatures.independentBlend = VK_TRUE;
|
||||
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||
deviceFeatures.imageCubeArray = VK_TRUE;
|
||||
#if !BOOST_OS_MACOS
|
||||
deviceFeatures.geometryShader = VK_TRUE;
|
||||
// deviceFeatures.logicOp = VK_TRUE;
|
||||
#endif
|
||||
deviceFeatures.geometryShader = m_featureControl.deviceFeatures.geometry_shader;
|
||||
deviceFeatures.logicOp = m_featureControl.deviceFeatures.logic_op;
|
||||
deviceFeatures.occlusionQueryPrecise = VK_TRUE;
|
||||
deviceFeatures.depthClamp = VK_TRUE;
|
||||
deviceFeatures.depthBiasClamp = VK_TRUE;
|
||||
|
@ -457,6 +457,12 @@ private:
|
||||
bool shader_float_controls = false; // VK_KHR_shader_float_controls
|
||||
}deviceExtensions;
|
||||
|
||||
struct
|
||||
{
|
||||
bool geometry_shader;
|
||||
bool logic_op;
|
||||
} deviceFeatures;
|
||||
|
||||
struct
|
||||
{
|
||||
bool shaderRoundingModeRTEFloat32{ false };
|
||||
|
@ -6,6 +6,11 @@
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.vulkan.version"
|
||||
android:required="true"
|
||||
android:version="0x401000" />
|
||||
|
||||
<application
|
||||
android:name="info.cemu.Cemu.CemuApplication"
|
||||
android:allowBackup="true"
|
||||
|
@ -64,6 +64,22 @@ jobject JNIUtils::createJavaLongArrayList(JNIEnv* env, const std::vector<uint64_
|
||||
return JNIUtils::createArrayList(env, valuesJava);
|
||||
}
|
||||
|
||||
void JNIUtils::handleNativeException(JNIEnv* env, const std::function<void()>& fn)
|
||||
{
|
||||
try
|
||||
{
|
||||
fn();
|
||||
} catch (const std::exception& exception)
|
||||
{
|
||||
jclass exceptionClass = env->FindClass("info/cemu/Cemu/nativeinterface/NativeException");
|
||||
env->ThrowNew(exceptionClass, exception.what());
|
||||
} catch (...)
|
||||
{
|
||||
jclass exceptionClass = env->FindClass("info/cemu/Cemu/nativeinterface/NativeException");
|
||||
env->ThrowNew(exceptionClass, "Unknown native exception");
|
||||
}
|
||||
}
|
||||
|
||||
jobject JNIUtils::createJavaStringArrayList(JNIEnv* env, const std::vector<std::wstring>& strings)
|
||||
{
|
||||
jclass arrayListClass = env->FindClass("java/util/ArrayList");
|
||||
|
@ -13,6 +13,8 @@ namespace JNIUtils
|
||||
|
||||
jobject createJavaStringArrayList(JNIEnv* env, const std::vector<std::wstring>& stringList);
|
||||
|
||||
void handleNativeException(JNIEnv* env, const std::function<void()>& fn);
|
||||
|
||||
class ScopedJNIENV
|
||||
{
|
||||
public:
|
||||
|
@ -16,7 +16,9 @@ extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, [[mayb
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_setSurface(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject surface, jboolean is_main_canvas)
|
||||
{
|
||||
s_emulationState.setSurface(env, surface, is_main_canvas);
|
||||
JNIUtils::handleNativeException(env, [&]() {
|
||||
s_emulationState.setSurface(env, surface, is_main_canvas);
|
||||
});
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
@ -86,7 +88,9 @@ Java_info_cemu_Cemu_NativeLibrary_initializeEmulation([[maybe_unused]] JNIEnv* e
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_initializerRenderer(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject testSurface)
|
||||
{
|
||||
s_emulationState.initializeRenderer(env, testSurface);
|
||||
JNIUtils::handleNativeException(env, [&]() {
|
||||
s_emulationState.initializeRenderer(env, testSurface);
|
||||
});
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
|
@ -1,7 +1,5 @@
|
||||
package info.cemu.Cemu.emulation;
|
||||
|
||||
import static androidx.core.app.ActivityCompat.finishAffinity;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.SurfaceTexture;
|
||||
@ -24,14 +22,13 @@ import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import info.cemu.Cemu.NativeLibrary;
|
||||
import info.cemu.Cemu.R;
|
||||
import info.cemu.Cemu.databinding.FragmentEmulationBinding;
|
||||
import info.cemu.Cemu.input.SensorManager;
|
||||
import info.cemu.Cemu.inputoverlay.InputOverlaySettingsProvider;
|
||||
import info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView;
|
||||
import info.cemu.Cemu.nativeinterface.NativeException;
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemClickListener {
|
||||
@ -71,7 +68,7 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC
|
||||
}
|
||||
}
|
||||
|
||||
private static class SurfaceHolderCallback implements SurfaceHolder.Callback {
|
||||
private class SurfaceHolderCallback implements SurfaceHolder.Callback {
|
||||
final boolean isMainCanvas;
|
||||
boolean surfaceSet;
|
||||
|
||||
@ -85,12 +82,16 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
|
||||
NativeLibrary.setSurfaceSize(width, height, isMainCanvas);
|
||||
if (surfaceSet) {
|
||||
return;
|
||||
try {
|
||||
NativeLibrary.setSurfaceSize(width, height, isMainCanvas);
|
||||
if (surfaceSet) {
|
||||
return;
|
||||
}
|
||||
NativeLibrary.setSurface(surfaceHolder.getSurface(), isMainCanvas);
|
||||
surfaceSet = true;
|
||||
} catch (NativeException exception) {
|
||||
onEmulationError(getString(R.string.failed_create_surface_error, exception.getMessage()));
|
||||
}
|
||||
surfaceSet = true;
|
||||
NativeLibrary.setSurface(surfaceHolder.getSurface(), isMainCanvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -112,6 +113,7 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC
|
||||
private InputOverlaySurfaceView inputOverlaySurfaceView;
|
||||
private SensorManager sensorManager;
|
||||
private EmulationViewModel viewModel;
|
||||
private boolean hasEmulationError;
|
||||
|
||||
public EmulationFragment(String launchPath) {
|
||||
this.launchPath = launchPath;
|
||||
@ -229,14 +231,10 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
viewModel = new ViewModelProvider(requireActivity()).get(EmulationViewModel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
viewModel = new ViewModelProvider(requireActivity()).get(EmulationViewModel.class);
|
||||
|
||||
binding = FragmentEmulationBinding.inflate(inflater, container, false);
|
||||
inputOverlaySurfaceView = binding.inputOverlay;
|
||||
|
||||
@ -271,8 +269,12 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC
|
||||
inputOverlaySurfaceView.setVisibility(View.GONE);
|
||||
}
|
||||
SurfaceView mainCanvas = binding.mainCanvas;
|
||||
|
||||
NativeLibrary.initializerRenderer(testSurface);
|
||||
try {
|
||||
NativeLibrary.initializerRenderer(testSurface);
|
||||
} catch (NativeException exception) {
|
||||
onEmulationError(getString(R.string.failed_initialize_renderer_error, exception.getMessage()));
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
var mainCanvasHolder = mainCanvas.getHolder();
|
||||
mainCanvasHolder.addCallback(new SurfaceHolderCallback(true));
|
||||
@ -283,6 +285,8 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
|
||||
if (hasEmulationError)
|
||||
return;
|
||||
if (!isGameRunning) {
|
||||
isGameRunning = true;
|
||||
startGame();
|
||||
@ -312,6 +316,7 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC
|
||||
}
|
||||
|
||||
private void onEmulationError(String errorMessage) {
|
||||
hasEmulationError = true;
|
||||
if (viewModel == null)
|
||||
return;
|
||||
viewModel.setEmulationError(new EmulationError(errorMessage));
|
||||
|
@ -0,0 +1,8 @@
|
||||
package info.cemu.Cemu.nativeinterface;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class NativeException extends RuntimeException {
|
||||
public NativeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -174,4 +174,6 @@
|
||||
<string name="no_disk_key">Could not decrypt title. Make sure that keys.txt contains the correct disc key for this title.</string>
|
||||
<string name="no_title_tik">Could not decrypt title because title.tik is missing.</string>
|
||||
<string name="game_not_found">Unable to launch game because the base files were not found.</string>
|
||||
<string name="failed_create_surface_error">Failed creating surface: %1$s</string>
|
||||
<string name="failed_initialize_renderer_error">Failed to initialize renderer: %1$s</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user