Pass c++ exception to java for renderer functions

This commit is contained in:
SSimco 2024-09-21 21:48:37 +03:00
parent 80ea25b10f
commit be23c47cac
9 changed files with 72 additions and 24 deletions

View File

@ -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;

View File

@ -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 };

View File

@ -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"

View File

@ -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");

View File

@ -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:

View File

@ -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

View File

@ -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));

View File

@ -0,0 +1,8 @@
package info.cemu.Cemu.nativeinterface;
@SuppressWarnings("unused")
public final class NativeException extends RuntimeException {
public NativeException(String message) {
super(message);
}
}

View File

@ -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>