This commit is contained in:
Emmanuel Hansen 2023-07-11 17:24:48 +00:00
parent 9b4d988d8c
commit 108fb2380a
14 changed files with 190 additions and 12 deletions

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "libadrenotools"]
path = src/RyujinxAndroid/app/src/main/cpp/libraries/adrenotools
url = https://github.com/bylaws/libadrenotools/
url = https://github.com/bylaws/libadrenotools.git

View File

@ -31,6 +31,8 @@ namespace LibRyujinx
private static ManualResetEvent _surfaceEvent;
private static long _surfacePtr;
public static VulkanLoader? VulkanLoader { get; private set; }
[DllImport("libryujinxjni")]
private extern static IntPtr getStringPointer(JEnvRef jEnv, JStringLocalRef s);
@ -213,7 +215,8 @@ namespace LibRyujinx
public unsafe static JBoolean JniInitializeGraphicsRendererNative(JEnvRef jEnv,
JObjectLocalRef jObj,
JArrayLocalRef extensionsArray,
JLong surfacePtr)
JLong surfacePtr,
JLong driverHandle)
{
if (Renderer != null)
{
@ -252,12 +255,17 @@ namespace LibRyujinx
_surfacePtr = surfacePtr;
if((long)driverHandle != 0)
{
VulkanLoader = new VulkanLoader((IntPtr)(long)driverHandle);
}
CreateSurface createSurfaceFunc = instance =>
{
_surfaceEvent.WaitOne();
_surfaceEvent.Reset();
var api = Vk.GetApi();
var api = VulkanLoader?.GetApi() ?? Vk.GetApi();
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))
{
var createInfo = new AndroidSurfaceCreateInfoKHR

View File

@ -91,7 +91,7 @@ namespace LibRyujinx
}
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,
null);
}

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

View File

@ -59,6 +59,9 @@ android {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
jniLibs {
keepDebugSymbols += '**/libryujinx.so'
}
}
externalNativeBuild {
cmake {

View File

@ -10,6 +10,11 @@ cmake_minimum_required(VERSION 3.22.1)
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
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
@ -52,4 +57,6 @@ target_link_libraries( # Specifies the target library.
oboe::oboe
${log-lib}
-lvulkan
-landroid)
-landroid
adrenotools
)

@ -0,0 +1 @@
Subproject commit deec5f75ee1a8ccbe32c8780b1d17284fc87b0f1

View File

@ -7,6 +7,7 @@
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <string>
#include <jni.h>
#include <exception>
#include <android/log.h>
@ -15,6 +16,8 @@
#include "vulkan_wrapper.h"
#include <vulkan/vulkan_android.h>
#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
#define CALL_VK(func) \

View File

@ -185,7 +185,46 @@ void onFrameEnd(double time){
_updateFrameTime = env->GetStaticMethodID(cl, "updateRenderSessionPerformance", "(J)V");
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,
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;
}

View File

@ -7,6 +7,8 @@ import android.view.SurfaceView
import org.ryujinx.android.viewmodels.GameModel
import org.ryujinx.android.viewmodels.MainViewModel
import org.ryujinx.android.viewmodels.QuickSettings
import org.ryujinx.android.viewmodels.VulkanDriverViewModel
import java.io.File
import kotlin.concurrent.thread
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!!.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(
nativeInterop!!.VkRequiredExtensions!!,
window
window,
driverHandle
)

View File

@ -25,8 +25,10 @@ import androidx.core.view.WindowInsetsControllerCompat
import com.anggrayudi.storage.SimpleStorageHelper
import org.ryujinx.android.ui.theme.RyujinxAndroidTheme
import org.ryujinx.android.viewmodels.MainViewModel
import org.ryujinx.android.viewmodels.VulkanDriverViewModel
import org.ryujinx.android.views.HomeViews
import org.ryujinx.android.views.MainView
import java.io.File
class MainActivity : ComponentActivity() {

View File

@ -15,4 +15,6 @@ class NativeHelpers {
external fun getNativeWindow(surface:Surface) : Long
external fun attachCurrentThread() : Unit
external fun detachCurrentThread() : Unit
external fun loadDriver(driverPath:String, nativeLibPath:String, privateAppsPath:String, publicAppsPath:String, driverName:String) : Long
}

View File

@ -25,7 +25,8 @@ class RyujinxNative {
external fun graphicsInitialize(configuration: GraphicsConfiguration): Boolean
external fun graphicsInitializeRenderer(
extensions: Array<String>,
surface: Long
surface: Long,
driver: Long
): Boolean
external fun deviceLoad(game: String): Boolean

View File

@ -279,7 +279,7 @@ class SettingViews {
enableTextureRecompression.value = !enableTextureRecompression.value
})
}
/*Row(
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
@ -423,7 +423,7 @@ class SettingViews {
Text(text = "Drivers")
}
}
*/
}
}
ExpandableView(onCardArrowClick = { }, title = "Input") {