forked from MeloNX/MeloNX
test
This commit is contained in:
parent
9b4d988d8c
commit
108fb2380a
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
|||||||
[submodule "libadrenotools"]
|
[submodule "libadrenotools"]
|
||||||
path = src/RyujinxAndroid/app/src/main/cpp/libraries/adrenotools
|
path = src/RyujinxAndroid/app/src/main/cpp/libraries/adrenotools
|
||||||
url = https://github.com/bylaws/libadrenotools/
|
url = https://github.com/bylaws/libadrenotools.git
|
||||||
|
@ -31,6 +31,8 @@ namespace LibRyujinx
|
|||||||
private static ManualResetEvent _surfaceEvent;
|
private static ManualResetEvent _surfaceEvent;
|
||||||
private static long _surfacePtr;
|
private static long _surfacePtr;
|
||||||
|
|
||||||
|
public static VulkanLoader? VulkanLoader { get; private set; }
|
||||||
|
|
||||||
[DllImport("libryujinxjni")]
|
[DllImport("libryujinxjni")]
|
||||||
private extern static IntPtr getStringPointer(JEnvRef jEnv, JStringLocalRef s);
|
private extern static IntPtr getStringPointer(JEnvRef jEnv, JStringLocalRef s);
|
||||||
|
|
||||||
@ -213,7 +215,8 @@ namespace LibRyujinx
|
|||||||
public unsafe static JBoolean JniInitializeGraphicsRendererNative(JEnvRef jEnv,
|
public unsafe static JBoolean JniInitializeGraphicsRendererNative(JEnvRef jEnv,
|
||||||
JObjectLocalRef jObj,
|
JObjectLocalRef jObj,
|
||||||
JArrayLocalRef extensionsArray,
|
JArrayLocalRef extensionsArray,
|
||||||
JLong surfacePtr)
|
JLong surfacePtr,
|
||||||
|
JLong driverHandle)
|
||||||
{
|
{
|
||||||
if (Renderer != null)
|
if (Renderer != null)
|
||||||
{
|
{
|
||||||
@ -252,12 +255,17 @@ namespace LibRyujinx
|
|||||||
|
|
||||||
_surfacePtr = surfacePtr;
|
_surfacePtr = surfacePtr;
|
||||||
|
|
||||||
|
if((long)driverHandle != 0)
|
||||||
|
{
|
||||||
|
VulkanLoader = new VulkanLoader((IntPtr)(long)driverHandle);
|
||||||
|
}
|
||||||
|
|
||||||
CreateSurface createSurfaceFunc = instance =>
|
CreateSurface createSurfaceFunc = instance =>
|
||||||
{
|
{
|
||||||
_surfaceEvent.WaitOne();
|
_surfaceEvent.WaitOne();
|
||||||
_surfaceEvent.Reset();
|
_surfaceEvent.Reset();
|
||||||
|
|
||||||
var api = Vk.GetApi();
|
var api = VulkanLoader?.GetApi() ?? Vk.GetApi();
|
||||||
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))
|
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))
|
||||||
{
|
{
|
||||||
var createInfo = new AndroidSurfaceCreateInfoKHR
|
var createInfo = new AndroidSurfaceCreateInfoKHR
|
||||||
|
@ -91,7 +91,7 @@ namespace LibRyujinx
|
|||||||
}
|
}
|
||||||
else if (graphicsBackend == GraphicsBackend.Vulkan)
|
else if (graphicsBackend == GraphicsBackend.Vulkan)
|
||||||
{
|
{
|
||||||
Renderer = new VulkanRenderer(Vk.GetApi(), (instance, vk) => new SurfaceKHR((ulong?)createSurfaceFunc(instance.Handle)),
|
Renderer = new VulkanRenderer(VulkanLoader?.GetApi() ?? Vk.GetApi(), (instance, vk) => new SurfaceKHR((ulong?)createSurfaceFunc(instance.Handle)),
|
||||||
() => requiredExtensions,
|
() => requiredExtensions,
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
96
src/LibRyujinx/VulkanLoader.cs
Normal file
96
src/LibRyujinx/VulkanLoader.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Silk.NET.Core.Contexts;
|
||||||
|
using Silk.NET.Vulkan;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LibRyujinx
|
||||||
|
{
|
||||||
|
public class VulkanLoader : IDisposable
|
||||||
|
{
|
||||||
|
private delegate IntPtr GetInstanceProcAddress(IntPtr instance, IntPtr name);
|
||||||
|
private delegate IntPtr GetDeviceProcAddress(IntPtr device, IntPtr name);
|
||||||
|
|
||||||
|
private IntPtr _loadedLibrary = IntPtr.Zero;
|
||||||
|
private GetInstanceProcAddress _getInstanceProcAddr;
|
||||||
|
private GetDeviceProcAddress _getDeviceProcAddr;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_loadedLibrary != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
NativeLibrary.Free(_loadedLibrary);
|
||||||
|
_loadedLibrary = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public VulkanLoader(IntPtr driver)
|
||||||
|
{
|
||||||
|
_loadedLibrary = driver;
|
||||||
|
|
||||||
|
if(_loadedLibrary != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
var instanceGetProc = NativeLibrary.GetExport(_loadedLibrary, "vkGetInstanceProcAddr");
|
||||||
|
var deviceProc = NativeLibrary.GetExport(_loadedLibrary, "vkGetDeviceProcAddr");
|
||||||
|
|
||||||
|
_getInstanceProcAddr = Marshal.GetDelegateForFunctionPointer<GetInstanceProcAddress>(instanceGetProc);
|
||||||
|
_getDeviceProcAddr = Marshal.GetDelegateForFunctionPointer<GetDeviceProcAddress>(deviceProc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vk GetApi()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (_loadedLibrary == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return Vk.GetApi();
|
||||||
|
}
|
||||||
|
var ctx = new MultiNativeContext(new INativeContext[1]);
|
||||||
|
var ret = new Vk(ctx);
|
||||||
|
ctx.Contexts[0] = new LamdaNativeContext
|
||||||
|
(
|
||||||
|
x =>
|
||||||
|
{
|
||||||
|
var xPtr = Marshal.StringToHGlobalAnsi(x);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nint ptr = default;
|
||||||
|
ptr = _getInstanceProcAddr(ret.CurrentInstance.GetValueOrDefault().Handle, xPtr);
|
||||||
|
|
||||||
|
if (ptr == default)
|
||||||
|
{
|
||||||
|
ptr = _getInstanceProcAddr(IntPtr.Zero, xPtr);
|
||||||
|
|
||||||
|
if (ptr == default)
|
||||||
|
{
|
||||||
|
var currentDevice = ret.CurrentDevice.GetValueOrDefault().Handle;
|
||||||
|
if (currentDevice != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
ptr = _getDeviceProcAddr(currentDevice, xPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == default)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Gpu, $"Failed to get function pointer: {x}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(xPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -59,6 +59,9 @@ android {
|
|||||||
resources {
|
resources {
|
||||||
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
||||||
}
|
}
|
||||||
|
jniLibs {
|
||||||
|
keepDebugSymbols += '**/libryujinx.so'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
|
@ -10,6 +10,11 @@ cmake_minimum_required(VERSION 3.22.1)
|
|||||||
|
|
||||||
project("ryujinxjni")
|
project("ryujinxjni")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||||
|
|
||||||
|
add_subdirectory("libraries/adrenotools")
|
||||||
|
|
||||||
# Creates and names a library, sets it as either STATIC
|
# Creates and names a library, sets it as either STATIC
|
||||||
# or SHARED, and provides the relative paths to its source code.
|
# or SHARED, and provides the relative paths to its source code.
|
||||||
# You can define multiple libraries, and CMake builds them for you.
|
# You can define multiple libraries, and CMake builds them for you.
|
||||||
@ -52,4 +57,6 @@ target_link_libraries( # Specifies the target library.
|
|||||||
oboe::oboe
|
oboe::oboe
|
||||||
${log-lib}
|
${log-lib}
|
||||||
-lvulkan
|
-lvulkan
|
||||||
-landroid)
|
-landroid
|
||||||
|
adrenotools
|
||||||
|
)
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Subproject commit deec5f75ee1a8ccbe32c8780b1d17284fc87b0f1
|
@ -7,6 +7,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
@ -15,6 +16,8 @@
|
|||||||
#include "vulkan_wrapper.h"
|
#include "vulkan_wrapper.h"
|
||||||
#include <vulkan/vulkan_android.h>
|
#include <vulkan/vulkan_android.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "libraries/adrenotools/include/adrenotools/driver.h"
|
||||||
|
|
||||||
// A macro to pass call to Vulkan and check for return value for success
|
// A macro to pass call to Vulkan and check for return value for success
|
||||||
#define CALL_VK(func) \
|
#define CALL_VK(func) \
|
||||||
|
@ -179,13 +179,52 @@ Java_org_ryujinx_android_MainActivity_initVm(JNIEnv *env, jobject thiz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
void onFrameEnd(double time){
|
void onFrameEnd(double time) {
|
||||||
auto env = getEnv(true);
|
auto env = getEnv(true);
|
||||||
auto cl = env->FindClass("org/ryujinx/android/MainActivity");
|
auto cl = env->FindClass("org/ryujinx/android/MainActivity");
|
||||||
_updateFrameTime = env->GetStaticMethodID( cl , "updateRenderSessionPerformance", "(J)V");
|
_updateFrameTime = env->GetStaticMethodID(cl, "updateRenderSessionPerformance", "(J)V");
|
||||||
|
|
||||||
auto now = std::chrono::high_resolution_clock::now();
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
auto nano = std::chrono::duration_cast<std::chrono::nanoseconds>(now-_currentTimePoint).count();
|
auto nano = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||||
|
now - _currentTimePoint).count();
|
||||||
env->CallStaticVoidMethod(cl, _updateFrameTime,
|
env->CallStaticVoidMethod(cl, _updateFrameTime,
|
||||||
nano);
|
nano);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
Java_org_ryujinx_android_NativeHelpers_loadDriver(JNIEnv *env, jobject thiz,
|
||||||
|
jstring driver_path,
|
||||||
|
jstring native_lib_path,
|
||||||
|
jstring private_apps_path,
|
||||||
|
jstring public_apps_path,
|
||||||
|
jstring driver_name) {
|
||||||
|
auto driverPath = getStringPointer(env, driver_path);
|
||||||
|
auto libPath = getStringPointer(env, native_lib_path);
|
||||||
|
auto privateAppsPath = getStringPointer(env, private_apps_path);
|
||||||
|
auto driverName = getStringPointer(env, driver_name);
|
||||||
|
auto publicPath = getStringPointer(env, public_apps_path);
|
||||||
|
|
||||||
|
std::string redirectPath = publicPath;
|
||||||
|
|
||||||
|
redirectPath += "gpu/vk_file_redirect/";
|
||||||
|
|
||||||
|
auto handle = adrenotools_open_libvulkan(
|
||||||
|
RTLD_NOW,
|
||||||
|
ADRENOTOOLS_DRIVER_CUSTOM,
|
||||||
|
nullptr,
|
||||||
|
libPath,
|
||||||
|
privateAppsPath,
|
||||||
|
driverName,
|
||||||
|
nullptr,//redirectPath.c_str(),
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
delete driverPath;
|
||||||
|
delete libPath;
|
||||||
|
delete privateAppsPath;
|
||||||
|
delete driverName;
|
||||||
|
delete publicPath;
|
||||||
|
|
||||||
|
return (jlong)handle;
|
||||||
}
|
}
|
@ -7,6 +7,8 @@ import android.view.SurfaceView
|
|||||||
import org.ryujinx.android.viewmodels.GameModel
|
import org.ryujinx.android.viewmodels.GameModel
|
||||||
import org.ryujinx.android.viewmodels.MainViewModel
|
import org.ryujinx.android.viewmodels.MainViewModel
|
||||||
import org.ryujinx.android.viewmodels.QuickSettings
|
import org.ryujinx.android.viewmodels.QuickSettings
|
||||||
|
import org.ryujinx.android.viewmodels.VulkanDriverViewModel
|
||||||
|
import java.io.File
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class GameHost(context: Context?, val controller: GameController, val mainViewModel: MainViewModel) : SurfaceView(context), SurfaceHolder.Callback {
|
class GameHost(context: Context?, val controller: GameController, val mainViewModel: MainViewModel) : SurfaceView(context), SurfaceHolder.Callback {
|
||||||
@ -85,9 +87,23 @@ class GameHost(context: Context?, val controller: GameController, val mainViewMo
|
|||||||
nativeInterop!!.VkCreateSurface = nativeHelpers.getCreateSurfacePtr()
|
nativeInterop!!.VkCreateSurface = nativeHelpers.getCreateSurfacePtr()
|
||||||
nativeInterop!!.SurfaceHandle = window
|
nativeInterop!!.SurfaceHandle = window
|
||||||
|
|
||||||
|
var driverViewModel = VulkanDriverViewModel(mainViewModel.activity);
|
||||||
|
driverViewModel.getAvailableDrivers()
|
||||||
|
|
||||||
|
var driverHandle = 0L;
|
||||||
|
|
||||||
|
if(driverViewModel.selected.isNotEmpty()) {
|
||||||
|
var privatePath = mainViewModel.activity.filesDir;
|
||||||
|
var privateDriverPath = privatePath.absolutePath + "/driver/"
|
||||||
|
var driver = File(driverViewModel.selected)
|
||||||
|
driver.copyTo(File(privateDriverPath + driver.name), true)
|
||||||
|
driverHandle = NativeHelpers().loadDriver(driverViewModel.selected, mainViewModel.activity.applicationInfo.nativeLibraryDir!!, privateDriverPath, mainViewModel.activity.getExternalFilesDir(null)!!.absolutePath, driver.name)
|
||||||
|
}
|
||||||
|
|
||||||
success = _nativeRyujinx.graphicsInitializeRenderer(
|
success = _nativeRyujinx.graphicsInitializeRenderer(
|
||||||
nativeInterop!!.VkRequiredExtensions!!,
|
nativeInterop!!.VkRequiredExtensions!!,
|
||||||
window
|
window,
|
||||||
|
driverHandle
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,8 +25,10 @@ import androidx.core.view.WindowInsetsControllerCompat
|
|||||||
import com.anggrayudi.storage.SimpleStorageHelper
|
import com.anggrayudi.storage.SimpleStorageHelper
|
||||||
import org.ryujinx.android.ui.theme.RyujinxAndroidTheme
|
import org.ryujinx.android.ui.theme.RyujinxAndroidTheme
|
||||||
import org.ryujinx.android.viewmodels.MainViewModel
|
import org.ryujinx.android.viewmodels.MainViewModel
|
||||||
|
import org.ryujinx.android.viewmodels.VulkanDriverViewModel
|
||||||
import org.ryujinx.android.views.HomeViews
|
import org.ryujinx.android.views.HomeViews
|
||||||
import org.ryujinx.android.views.MainView
|
import org.ryujinx.android.views.MainView
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
@ -15,4 +15,6 @@ class NativeHelpers {
|
|||||||
external fun getNativeWindow(surface:Surface) : Long
|
external fun getNativeWindow(surface:Surface) : Long
|
||||||
external fun attachCurrentThread() : Unit
|
external fun attachCurrentThread() : Unit
|
||||||
external fun detachCurrentThread() : Unit
|
external fun detachCurrentThread() : Unit
|
||||||
|
|
||||||
|
external fun loadDriver(driverPath:String, nativeLibPath:String, privateAppsPath:String, publicAppsPath:String, driverName:String) : Long
|
||||||
}
|
}
|
@ -25,7 +25,8 @@ class RyujinxNative {
|
|||||||
external fun graphicsInitialize(configuration: GraphicsConfiguration): Boolean
|
external fun graphicsInitialize(configuration: GraphicsConfiguration): Boolean
|
||||||
external fun graphicsInitializeRenderer(
|
external fun graphicsInitializeRenderer(
|
||||||
extensions: Array<String>,
|
extensions: Array<String>,
|
||||||
surface: Long
|
surface: Long,
|
||||||
|
driver: Long
|
||||||
): Boolean
|
): Boolean
|
||||||
|
|
||||||
external fun deviceLoad(game: String): Boolean
|
external fun deviceLoad(game: String): Boolean
|
||||||
|
@ -279,7 +279,7 @@ class SettingViews {
|
|||||||
enableTextureRecompression.value = !enableTextureRecompression.value
|
enableTextureRecompression.value = !enableTextureRecompression.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/*Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(8.dp),
|
.padding(8.dp),
|
||||||
@ -423,7 +423,7 @@ class SettingViews {
|
|||||||
Text(text = "Drivers")
|
Text(text = "Drivers")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExpandableView(onCardArrowClick = { }, title = "Input") {
|
ExpandableView(onCardArrowClick = { }, title = "Input") {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user