diff --git a/.idea/misc.xml b/.idea/misc.xml index b52e1b28..ecdd43db 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index bd3bf03c..942f8c86 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -4,10 +4,10 @@ plugins { } android { - ndkVersion = "25.2.9519653" - compileSdkVersion = "android-31" + ndkVersion = "26.1.10909125" + compileSdkVersion = "android-32" defaultConfig { - minSdkVersion(31) + minSdkVersion(32) } buildTypes { diff --git a/lib/src/main/AndroidManifest.xml b/lib/src/main/AndroidManifest.xml index c1181f99..48eed878 100644 --- a/lib/src/main/AndroidManifest.xml +++ b/lib/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - - + \ No newline at end of file diff --git a/lib/src/main/assets/JRE-17.zip b/lib/src/main/assets/JRE-17.zip index d2f881f9..4b8f269a 100644 Binary files a/lib/src/main/assets/JRE-17.zip and b/lib/src/main/assets/JRE-17.zip differ diff --git a/lib/src/main/assets/options.txt b/lib/src/main/assets/options.txt index 0ff89a94..f4d55021 100644 --- a/lib/src/main/assets/options.txt +++ b/lib/src/main/assets/options.txt @@ -189,4 +189,4 @@ modelPart_right_sleeve:true modelPart_left_pants_leg:true modelPart_right_pants_leg:true modelPart_hat:true -fullscreenResolution:2960x1440@60:24 +fullscreenResolution:1920x1080@90:24 diff --git a/lib/src/main/java/pojlib/account/MinecraftAccount.java b/lib/src/main/java/pojlib/account/MinecraftAccount.java index 655accfb..9da30475 100644 --- a/lib/src/main/java/pojlib/account/MinecraftAccount.java +++ b/lib/src/main/java/pojlib/account/MinecraftAccount.java @@ -3,6 +3,7 @@ import static pojlib.account.Msa.checkMcProfile; import android.app.Activity; +import android.util.Log; import com.google.gson.Gson; import com.google.gson.JsonObject; @@ -70,7 +71,11 @@ public static MinecraftAccount load(String path, @Nullable String newToken, @Nul } public static String getSkinFaceUrl(MinecraftAccount account) { - return Constants.CRAFATAR_URL + "/avatars/" + account.uuid; + try { + return Constants.CRAFATAR_URL + "/avatars/" + account.uuid; + } catch (NullPointerException e) { + System.out.println("Username not set! Please sign in on PC/Pojav first then try again."); + return null; + } } - } \ No newline at end of file diff --git a/lib/src/main/java/pojlib/api/API_V1.java b/lib/src/main/java/pojlib/api/API_V1.java index 814800af..1d650ec7 100644 --- a/lib/src/main/java/pojlib/api/API_V1.java +++ b/lib/src/main/java/pojlib/api/API_V1.java @@ -41,6 +41,7 @@ public class API_V1 { public static String msaMessage = ""; + public static String model = "Quest"; private static boolean hasQueried = false; private static JsonObject initialResponse; public static boolean finishedDownloading = false; diff --git a/lib/src/main/java/pojlib/instance/MinecraftInstance.java b/lib/src/main/java/pojlib/instance/MinecraftInstance.java index 07d00936..c7cad982 100644 --- a/lib/src/main/java/pojlib/instance/MinecraftInstance.java +++ b/lib/src/main/java/pojlib/instance/MinecraftInstance.java @@ -314,6 +314,7 @@ public void launchInstance(Activity activity, MinecraftAccount account) { JREUtils.redirectAndPrintJRELog(); VLoader.setAndroidInitInfo(activity); VLoader.setEGLGlobal(JREUtils.getEGLContextPtr(), JREUtils.getEGLDisplayPtr(), JREUtils.getEGLConfigPtr()); + while(!API_V1.finishedDownloading); JREUtils.launchJavaVM(activity, generateLaunchArgs(account), versionName); } catch (Throwable e) { e.printStackTrace(); diff --git a/lib/src/main/java/pojlib/util/JREUtils.java b/lib/src/main/java/pojlib/util/JREUtils.java index 11f7d23c..a0913e18 100644 --- a/lib/src/main/java/pojlib/util/JREUtils.java +++ b/lib/src/main/java/pojlib/util/JREUtils.java @@ -142,20 +142,20 @@ public static void setJavaEnvironment(Activity activity) throws Throwable { envMap.put("JAVA_HOME", activity.getFilesDir() + "/runtimes/JRE-17"); envMap.put("HOME", Constants.MC_DIR); envMap.put("TMPDIR", activity.getCacheDir().getAbsolutePath()); - envMap.put("LIBGL_MIPMAP", "3"); - envMap.put("LIBGL_NOINTOVLHACK", "1"); + envMap.put("VR_MODEL", API_V1.model); envMap.put("MESA_GL_VERSION_OVERRIDE", "4.6"); envMap.put("MESA_GLSL_VERSION_OVERRIDE", "460"); envMap.put("MESA_LOADER_DRIVER_OVERRIDE", "zink"); + envMap.put("GALLIUM_DRIVER", "zink"); + envMap.put("LIBGL_DEBUG", "verbose"); + envMap.put("LIBGL_DRIVERS_PATH", sNativeLibDir); envMap.put("GALLIUM_THREAD", "0"); + envMap.put("MESA_LOG_FILE", Constants.MC_DIR + "/mesa-log.txt"); envMap.put("POJAV_RENDERER", "vulkan_zink"); envMap.put("LD_LIBRARY_PATH", LD_LIBRARY_PATH); envMap.put("PATH", activity.getFilesDir() + "/runtimes/JRE-17/bin:" + Os.getenv("PATH")); - envMap.put("LIBGL_GLES", "/system/lib64/libGLESv2.so"); - envMap.put("LIBGL_EGL", "/system/lib64/libEGL.so"); - File customEnvFile = new File(Constants.USER_HOME, "custom_env.txt"); if (customEnvFile.exists() && customEnvFile.isFile()) { BufferedReader reader = new BufferedReader(new FileReader(customEnvFile)); @@ -201,7 +201,7 @@ public static int launchJavaVM(final Activity activity, final List JVMAr userArgs.add("-Dorg.lwjgl.opengl.libname=" + graphicsLib); userArgs.add("-Dorg.lwjgl.opengles.libname=" + "/system/lib64/libGLESv3.so"); - userArgs.add("-Dorg.lwjgl.egl.libname=" + "/system/lib64/libEGL.so"); + userArgs.add("-Dorg.lwjgl.egl.libname=" + "/system/lib64/libEGL_dri.so"); userArgs.add("-Dfabric.addMods=" + Constants.MC_DIR + "/mods/" + versionName); userArgs.addAll(JVMArgs); diff --git a/lib/src/main/java/pojlib/util/LoginHelper.java b/lib/src/main/java/pojlib/util/LoginHelper.java index c6ab5b81..d7009676 100644 --- a/lib/src/main/java/pojlib/util/LoginHelper.java +++ b/lib/src/main/java/pojlib/util/LoginHelper.java @@ -89,6 +89,8 @@ public static void beginLogin(Activity activity) { API_V1.profileImage = MinecraftAccount.getSkinFaceUrl(API_V1.currentAcc); API_V1.profileName = API_V1.currentAcc.username; } catch (ExecutionException | InterruptedException e) { + API_V1.msaMessage = "Something went wrong! Couldn't reach the Microsoft Auth servers.\n" + + e.getMessage(); throw new RuntimeException(e); } }); diff --git a/lib/src/main/jni/OpenOVR/OCOVR.a b/lib/src/main/jni/OpenOVR/OCOVR.a index ca3fe74e..dc1578fd 100644 Binary files a/lib/src/main/jni/OpenOVR/OCOVR.a and b/lib/src/main/jni/OpenOVR/OCOVR.a differ diff --git a/lib/src/main/jni/OpenOVR/libDrvOpenXR.a b/lib/src/main/jni/OpenOVR/libDrvOpenXR.a index 3c91fc59..45d6902a 100644 Binary files a/lib/src/main/jni/OpenOVR/libDrvOpenXR.a and b/lib/src/main/jni/OpenOVR/libDrvOpenXR.a differ diff --git a/lib/src/main/jni/OpenOVR/libOCCore.a b/lib/src/main/jni/OpenOVR/libOCCore.a index 50d51323..3862f4a9 100644 Binary files a/lib/src/main/jni/OpenOVR/libOCCore.a and b/lib/src/main/jni/OpenOVR/libOCCore.a differ diff --git a/lib/src/main/jni/OpenOVR/libOpenXR.a b/lib/src/main/jni/OpenOVR/libOpenXR.a index 62966e2c..c1b3e6b0 100644 Binary files a/lib/src/main/jni/OpenOVR/libOpenXR.a and b/lib/src/main/jni/OpenOVR/libOpenXR.a differ diff --git a/lib/src/main/jni/adrenotools/driver.h b/lib/src/main/jni/adrenotools/driver.h index 2578836f..b09b4db8 100644 --- a/lib/src/main/jni/adrenotools/driver.h +++ b/lib/src/main/jni/adrenotools/driver.h @@ -7,6 +7,7 @@ extern "C" { #endif +#include #include "priv.h" /** @@ -18,23 +19,40 @@ extern "C" { * @param customDriverDir The directory to load a custom GPU driver named according to `customDriverName` from. Only used if ADRENOTOOLS_DRIVER_CUSTOM is set in `featureFlags` * @param customDriverName The soname of the custom driver to load. Only used if ADRENOTOOLS_DRIVER_CUSTOM is set in `featureFlags` * @param fileRedirectDir The directory which to redirect all file accesses performed by the driver to. Only used if ADRENOTOOLS_DRIVER_FILE_REDIRECT is set in `featureFlags` + * @param userMappingHandle A pointer to a void* which will be set to the mapping handle if ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT is set in `featureFlags` */ -void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir, struct adrenotools_gpu_mapping *nextGpuMapping); +void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir, void **userMappingHandle); /** - * @brief Imports the given CPU mapped memory range into the GSL allocator. The out_mapping should have been passed to adrenotools_open_libvulkan with ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT set in `featureFlags`. This should then be followed by a call to vkAllocateMemory with a matching size which will return a VkDeviceMemory view over the input region - * @param outMapping Output mapping pointer, the same as was passed to adrenotools_open_libvulkan + * @brief Imports the given CPU mapped memory range into the GSL allocator. This should then be followed by a call to vkAllocateMemory with a matching size which will return a VkDeviceMemory view over the input region + * @param handle Mapping handle that was returned by adrenotools_open_libvulkan * @param hostPtr The host pointer to import * @param size The size of the region to import * @return True on success */ -bool adrenotools_import_user_mem(struct adrenotools_gpu_mapping *outMapping, void *hostPtr, uint64_t size); +bool adrenotools_import_user_mem(void *handle, void *hostPtr, uint64_t size); + +/** + * @brief Maps GPU memory and imports it into the GSL allocator. This should then be followed by a call to adrenotools_mem_cpu_map to map the memory on the CPU, then finally vkAllocateMemory with a matching size + * @param handle Mapping handle that was returned by adrenotools_open_libvulkan + * @param size Pointer to a variable containing the size of the region to import, will be updated to contain the required size of the region to allocate CPU side + * @return true on success + */ +bool adrenotools_mem_gpu_allocate(void *handle, uint64_t *size); + +/** + * @brief Maps the last mapping allocated using adrenotools_mem_gpu_allocate into the given host memory region, such that vkAllocateMemory can then be called + * @param handle Mapping handle that was returned by adrenotools_open_libvulkan + * @param hostPtr A pointer to where the mapping should be mapped + * @param size The size of the mapping. MUST be equal to the size returned by adrenotools_mem_gpu_allocate + */ +bool adrenotools_mem_cpu_map(void *handle, void *hostPtr, uint64_t size); /** * @note This function should be called after adrenotools_open_libvulkan and Vulkan driver init to check if the mapping import hook loaded successfully * @return True if the mapping was successfully imported (or initialization succeeded) */ -bool adrenotools_validate_gpu_mapping(struct adrenotools_gpu_mapping *mapping); +bool adrenotools_validate_gpu_mapping(void *handle); /** * @brief Provides a way to force the GPU to run at the maximum possible clocks (thermal constraints will still be applied) diff --git a/lib/src/main/jni/adrenotools/libadrenotools.so b/lib/src/main/jni/adrenotools/libadrenotools.so index 562c6e46..c841ff97 100644 Binary files a/lib/src/main/jni/adrenotools/libadrenotools.so and b/lib/src/main/jni/adrenotools/libadrenotools.so differ diff --git a/lib/src/main/jni/egl_bridge.c b/lib/src/main/jni/egl_bridge.c index f8db66dd..e2f00510 100644 --- a/lib/src/main/jni/egl_bridge.c +++ b/lib/src/main/jni/egl_bridge.c @@ -591,7 +591,7 @@ typedef struct osmesa_context GLboolean (*OSMesaMakeCurrent_p) (OSMesaContext ctx, void *buffer, GLenum type, GLsizei width, GLsizei height); OSMesaContext (*OSMesaGetCurrentContext_p) (void); -OSMesaContext (*OSMesaCreateContext_p) (GLenum format, OSMesaContext sharelist); +OSMesaContext (*OSMesaCreateContextAttribs_p) ( const int *attribList, OSMesaContext sharelist ); GLubyte* (*glGetString_p) (GLenum name); void* gbuffer; @@ -711,36 +711,40 @@ void dlsym_OSMesa() { void* dl_handle; dl_handle = dlopen(alt_path, RTLD_NOW); if(dl_handle == NULL) dl_handle = dlopen(main_path, RTLD_NOW); - if(dl_handle == NULL) abort(); + if(dl_handle == NULL) { + printf("Error opening OSMesa! %s\n", dlerror()); + abort(); + } OSMesaMakeCurrent_p = dlsym(dl_handle, "OSMesaMakeCurrent"); OSMesaGetCurrentContext_p = dlsym(dl_handle,"OSMesaGetCurrentContext"); - OSMesaCreateContext_p = dlsym(dl_handle, "OSMesaCreateContext"); + OSMesaCreateContextAttribs_p = dlsym(dl_handle, "OSMesaCreateContextAttribs"); glGetString_p = dlsym(dl_handle,"glGetString"); } int pojavInit() { - savedWidth = 1080; - savedHeight = 720; + savedWidth = 1920; + savedHeight = 1080; - xrEglInit(); + // xrEglInit(); - char *natives = getenv("POJAV_NATIVEDIR"); - char *gpuStuff = getenv("HOME"); - strcat(natives, "/"); + char *gpuStuff; + char *nativeDir; + asprintf(&nativeDir, "%s/", getenv("POJAV_NATIVEDIR")); + asprintf(&gpuStuff, "%s/gpustuff", getenv("HOME")); void *libvulkan = adrenotools_open_libvulkan(RTLD_NOW, ADRENOTOOLS_DRIVER_CUSTOM, NULL, - gpuStuff, natives, - "libvulkan_freedreno.so", NULL, NULL); + gpuStuff, nativeDir, + "libvulkan_freedreno.so", NULL, NULL); adrenotools_set_turbo(true); printf("libvulkan: %p\n", libvulkan); char *vulkanPtrString; + asprintf(&vulkanPtrString, "%p", libvulkan); printf("%s\n", vulkanPtrString); setenv("VULKAN_PTR", vulkanPtrString, 1); - setenv("GALLIUM_DRIVER", "zink", 1); dlsym_OSMesa(); - if (OSMesaCreateContext_p == NULL) { + if (OSMesaCreateContextAttribs_p == NULL) { printf("OSMDroid: %s\n", dlerror()); return 0; } @@ -748,7 +752,7 @@ int pojavInit() { printf("OSMDroid: width=%i;height=%i, reserving %i bytes for frame buffer\n", savedWidth, savedHeight, savedWidth * 4 * savedHeight); - gbuffer = malloc(savedWidth * 4 * savedHeight + 1); + gbuffer = malloc(savedWidth * 4 * savedHeight); if (gbuffer) { printf("OSMDroid: created frame buffer\n"); return 1; @@ -809,7 +813,22 @@ Java_org_lwjgl_glfw_GLFW_nativeEglDetachOnCurrentThread(JNIEnv *env, jclass claz void* pojavCreateContext(void* contextSrc) { printf("OSMDroid: generating context\n"); - void *ctx = OSMesaCreateContext_p(OSMESA_RGBA, contextSrc); + + int attribs[100], n = 0; + + attribs[n++] = OSMESA_FORMAT; + attribs[n++] = OSMESA_RGBA; + attribs[n++] = OSMESA_DEPTH_BITS; + attribs[n++] = 24; + attribs[n++] = OSMESA_STENCIL_BITS; + attribs[n++] = 8; + attribs[n++] = OSMESA_ACCUM_BITS; + attribs[n++] = 0; + attribs[n++] = OSMESA_PROFILE; + attribs[n++] = OSMESA_CORE_PROFILE; + attribs[n++] = 0; + + void *ctx = OSMesaCreateContextAttribs_p(attribs, contextSrc); printf("OSMDroid: context=%p\n", ctx); return ctx; } @@ -825,7 +844,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL_nativeRegalMakeCurrent(JNIEnv *e } JNIEXPORT JNICALL jlong Java_org_lwjgl_opengl_GL_getGraphicsBufferAddr(JNIEnv *env, jobject thiz) { - return &gbuffer; + return (jlong) &gbuffer; } JNIEXPORT JNICALL jintArray Java_org_lwjgl_opengl_GL_getNativeWidthHeight(JNIEnv *env, jobject thiz) { diff --git a/lib/src/main/jni/vloader.cpp b/lib/src/main/jni/vloader.cpp index b652f8d6..9b66a31b 100644 --- a/lib/src/main/jni/vloader.cpp +++ b/lib/src/main/jni/vloader.cpp @@ -4,10 +4,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include "log.h" #include @@ -17,7 +20,50 @@ XrGraphicsBindingOpenGLESAndroidKHR* OpenComposite_Android_GLES_Binding_Info; std::string (*OpenComposite_Android_Load_Input_File)(const char *path); -static std::string load_file(const char *path); +static bool hasInitVulkan = false; + +static VkInstance instance; +static VkPhysicalDevice pDev; +static VkDevice dev; +static VkQueue queue; +static int queueFamilyIndex; + +static VkImage leftImage; +static VkImage rightImage; + +static VkDeviceMemory leftMem; +static VkDeviceMemory rightMem; + +static AHardwareBuffer* leftBuffer; +static AHardwareBuffer* rightBuffer; + +static const char* instExtensions[] = { VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, + VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, + VK_KHR_SURFACE_EXTENSION_NAME }; +static const char* devExtensions[] = { VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, + VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, + VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_KHR_MAINTENANCE1_EXTENSION_NAME}; + +typedef struct native_handle +{ + int version; /* sizeof(native_handle_t) */ + int numFds; /* number of file-descriptors at &data[0] */ + int numInts; /* number of ints at &data[numFds] */ +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wzero-length-array" +#endif + int data[0]; /* numFds + numInts ints */ +#if defined(__clang__) +#pragma clang diagnostic pop +#endif +} native_handle_t; + +extern "C" +const native_handle_t* _Nullable AHardwareBuffer_getNativeHandle( + const AHardwareBuffer* _Nonnull buffer); extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { @@ -27,6 +73,33 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { return JNI_VERSION_1_4; } +static std::string load_file(const char *path) { + // Just read the file from the filesystem, we changed the working directory earlier so + // Vivecraft can extract it's manifest files. + + printf("Path: %s\n", path); + int fd = open(path, O_RDONLY); + if (!fd) { + LOGE("Failed to load manifest file %s: %d %s\n", path, errno, strerror(errno)); + } + + int length = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + + std::string data; + data.resize(length); + if (!read(fd, (void *) data.data(), data.size())) { + LOGE("Failed to load manifest file %s failed to read: %d %s\n", path, errno, strerror(errno)); + } + + if (close(fd)) { + LOGE("Failed to load manifest file %s failed to close: %d %s\n", path, errno, + strerror(errno)); + } + + return std::move(data); +} + extern "C" JNIEXPORT void JNICALL Java_pojlib_util_VLoader_setAndroidInitInfo(JNIEnv *env, jclass clazz, jobject ctx) { @@ -73,60 +146,212 @@ Java_pojlib_util_VLoader_setEGLGlobal(JNIEnv* env, jclass clazz, jlong ctx, jlon }; } -extern "C" -JNIEXPORT jint JNICALL -Java_org_vivecraft_utils_VLoader_createGLImage(JNIEnv* env, jclass clazz, jint width, jint height) { - GLint image; - glGenTextures(1, reinterpret_cast(&image)); - glBindTexture(GL_TEXTURE_2D, image); - glTexParameterf(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER, 9729.0F); - glTexParameterf(GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER, 9729.0F); - glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - - GLenum error = glGetError(); - if(error != GL_NO_ERROR) { - printf("OpenGLES error! %d.", error); +void checkVkResult(VkResult res, const char* func) { + if(res != VK_SUCCESS) { + printf("%s returned %d!\n", func, res); + abort(); } +} + +void createInstance() { + VkApplicationInfo appInfo = { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pApplicationName = "QCXR VK Helper", + .applicationVersion = VK_MAKE_VERSION(4, 1, 0), + .pEngineName = "No Engine", + .engineVersion = 1, + .apiVersion = VK_VERSION_1_1 + }; - return image; + VkInstanceCreateInfo vkInstanceInfo = { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .flags = 0, + .pApplicationInfo = &appInfo, + .enabledLayerCount = 0, + .enabledExtensionCount = 3, + .ppEnabledExtensionNames = instExtensions + }; + + checkVkResult(vkCreateInstance(&vkInstanceInfo, nullptr, &instance), "vkCreateInstance"); } -extern "C" -JNIEXPORT void JNICALL -Java_org_vivecraft_utils_VLoader_writeImage(JNIEnv* env, jclass clazz, jint tex, jint width, jint height, jlong byteBuf) { - void* pixels = reinterpret_cast(byteBuf); - glBindTexture(GL_TEXTURE_2D, tex); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - GLenum error = glGetError(); - if(error != GL_NO_ERROR) { - printf("OpenGLES error! %d.", error); +void pickPhysicalDevice() { + uint32_t deviceCount = 0; + checkVkResult(vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr), "vkEnumeratePhysicalDevices"); + VkPhysicalDevice devices[deviceCount]; + checkVkResult(vkEnumeratePhysicalDevices(instance, &deviceCount, devices), "vkEnumeratePhysicalDevices"); + + pDev = devices[0]; + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(pDev, &queueFamilyCount, nullptr); + VkQueueFamilyProperties queueFamilies[queueFamilyCount]; + vkGetPhysicalDeviceQueueFamilyProperties(pDev, &queueFamilyCount, queueFamilies); + + int i = 0; + for (const auto& queueFamily : queueFamilies) { + if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { + queueFamilyIndex = i; + break; + } + + i++; } } -static std::string load_file(const char *path) { - // Just read the file from the filesystem, we changed the working directory earlier so - // Vivecraft can extract it's manifest files. +void createLogicalDevice() { + VkDeviceQueueCreateInfo queueCreateInfo{}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamilyIndex; + queueCreateInfo.queueCount = 1; - printf("Path: %s", path); - int fd = open(path, O_RDONLY); - if (!fd) { - LOGE("Failed to load manifest file %s: %d %s", path, errno, strerror(errno)); - } + float queuePriority = 1.0f; + queueCreateInfo.pQueuePriorities = &queuePriority; + VkPhysicalDeviceFeatures deviceFeatures{}; - int length = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); + VkDeviceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.pQueueCreateInfos = &queueCreateInfo; + createInfo.queueCreateInfoCount = 1; + createInfo.pEnabledFeatures = &deviceFeatures; - std::string data; - data.resize(length); - if (!read(fd, (void *) data.data(), data.size())) { - LOGE("Failed to load manifest file %s failed to read: %d %s", path, errno, strerror(errno)); + createInfo.enabledExtensionCount = 5; + createInfo.ppEnabledExtensionNames = devExtensions; + + checkVkResult(vkCreateDevice(pDev, &createInfo, nullptr, &dev), "vkCreateDevice"); + + vkGetDeviceQueue(dev, queueFamilyIndex, 0, &queue); +} + +uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { + VkPhysicalDeviceMemoryProperties memProperties; + vkGetPhysicalDeviceMemoryProperties(pDev, &memProperties); + + for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { + if (typeFilter & (1 << i)) { + return i; + } } - if (close(fd)) { - LOGE("Failed to load manifest file %s failed to close: %d %s", path, errno, - strerror(errno)); + printf("Error! Couldn't find suitable memory type!\n"); + abort(); +} + +void createVkImage(uint32_t width, uint32_t height, VkImage* img, VkDeviceMemory* memory, AHardwareBuffer** buffer) { + AHardwareBuffer_Desc desc = { + .width = width, + .height = height, + .layers = 1, + .format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + .usage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, + .rfu0 = 0, + .rfu1 = 0 + }; + AHardwareBuffer_allocate(&desc, buffer); + + VkExternalMemoryImageCreateInfo emai = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID + }; + + VkImageCreateInfo imgInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = &emai, + .imageType = VK_IMAGE_TYPE_2D, + .format = VK_FORMAT_R8G8B8A8_UNORM, + .extent = { + .width = width, + .height = height, + .depth = 1 + }, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_LINEAR, + .usage = VK_IMAGE_USAGE_SAMPLED_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + }; + + checkVkResult(vkCreateImage(dev, &imgInfo, nullptr, img), "vkCreateImage"); + + VkMemoryRequirements memoryRequirements; + vkGetImageMemoryRequirements(dev, *img, &memoryRequirements); + + VkAndroidHardwareBufferPropertiesANDROID hardwareBufferPropertiesAndroid = { + .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, + }; + checkVkResult(vkGetAndroidHardwareBufferPropertiesANDROID(dev, *buffer, &hardwareBufferPropertiesAndroid), "vkGetAndroidHardwareBufferPropertiesANDROID"); + + VkImportAndroidHardwareBufferInfoANDROID importAndroidHardwareBufferInfoAndroid = { + .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, + .buffer = *buffer + }; + + VkMemoryDedicatedAllocateInfo dedAllocInfo = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = &importAndroidHardwareBufferInfoAndroid, + .image = *img + }; + + VkMemoryAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocInfo.pNext = &dedAllocInfo; + allocInfo.allocationSize = hardwareBufferPropertiesAndroid.allocationSize; + allocInfo.memoryTypeIndex = findMemoryType(hardwareBufferPropertiesAndroid.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + checkVkResult(vkAllocateMemory(dev, &allocInfo, nullptr, memory), "vkAllocateMemory"); + vkBindImageMemory(dev, *img, *memory, 0); +} + +extern "C" +JNIEXPORT jint JNICALL +Java_org_vivecraft_utils_VLoader_getDMABuf(JNIEnv* env, jclass clazz, jboolean isLeft) { + const native_handle_t* handle = AHardwareBuffer_getNativeHandle(isLeft ? leftBuffer : rightBuffer); + int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1; + return dma_buf; +} + +extern "C" +JNIEXPORT jlong JNICALL +Java_org_vivecraft_utils_VLoader_getInstance(JNIEnv* env, jclass clazz) { + return reinterpret_cast(instance); +} + +extern "C" +JNIEXPORT jlong JNICALL +Java_org_vivecraft_utils_VLoader_getDevice(JNIEnv* env, jclass clazz) { + return reinterpret_cast(dev); +} + +extern "C" +JNIEXPORT jlong JNICALL +Java_org_vivecraft_utils_VLoader_getPhysicalDevice(JNIEnv* env, jclass clazz) { + return reinterpret_cast(pDev); +} + +extern "C" +JNIEXPORT jlong JNICALL +Java_org_vivecraft_utils_VLoader_getQueue(JNIEnv* env, jclass clazz) { + return reinterpret_cast(queue); +} + +extern "C" +JNIEXPORT jint JNICALL +Java_org_vivecraft_utils_VLoader_getQueueIndex(JNIEnv* env, jclass clazz) { + return queueFamilyIndex; +} + +extern "C" +JNIEXPORT jlong JNICALL +Java_org_vivecraft_utils_VLoader_createVKImage(JNIEnv* env, jclass clazz, jint width, jint height, jboolean isLeft) { + if(!hasInitVulkan) { + hasInitVulkan = true; + createInstance(); + pickPhysicalDevice(); + createLogicalDevice(); } - return std::move(data); + createVkImage(width, height, isLeft ? &leftImage : &rightImage, isLeft ? &leftMem : &rightMem, isLeft ? &leftBuffer : &rightBuffer); + return reinterpret_cast((uint64_t) isLeft ? leftImage : rightImage); } diff --git a/lib/src/main/jniLibs/arm64-v8a/libOSMesa_8.so b/lib/src/main/jniLibs/arm64-v8a/libOSMesa_8.so index 56693717..d0e862b2 100644 Binary files a/lib/src/main/jniLibs/arm64-v8a/libOSMesa_8.so and b/lib/src/main/jniLibs/arm64-v8a/libOSMesa_8.so differ diff --git a/lib/src/main/jniLibs/arm64-v8a/libdrm.so b/lib/src/main/jniLibs/arm64-v8a/libdrm.so new file mode 100644 index 00000000..b6d6c565 Binary files /dev/null and b/lib/src/main/jniLibs/arm64-v8a/libdrm.so differ diff --git a/lib/src/main/jniLibs/arm64-v8a/libfile_redirect_hook.so b/lib/src/main/jniLibs/arm64-v8a/libfile_redirect_hook.so index fb58a2ad..d89e6d56 100644 Binary files a/lib/src/main/jniLibs/arm64-v8a/libfile_redirect_hook.so and b/lib/src/main/jniLibs/arm64-v8a/libfile_redirect_hook.so differ diff --git a/lib/src/main/jniLibs/arm64-v8a/libgsl_alloc_hook.so b/lib/src/main/jniLibs/arm64-v8a/libgsl_alloc_hook.so index 3979c8dc..9e9c162f 100644 Binary files a/lib/src/main/jniLibs/arm64-v8a/libgsl_alloc_hook.so and b/lib/src/main/jniLibs/arm64-v8a/libgsl_alloc_hook.so differ diff --git a/lib/src/main/jniLibs/arm64-v8a/libhook_impl.so b/lib/src/main/jniLibs/arm64-v8a/libhook_impl.so index 2ba21922..1bdfe700 100644 Binary files a/lib/src/main/jniLibs/arm64-v8a/libhook_impl.so and b/lib/src/main/jniLibs/arm64-v8a/libhook_impl.so differ diff --git a/lib/src/main/jniLibs/arm64-v8a/libmain_hook.so b/lib/src/main/jniLibs/arm64-v8a/libmain_hook.so index 6ec9d17c..59698ee4 100644 Binary files a/lib/src/main/jniLibs/arm64-v8a/libmain_hook.so and b/lib/src/main/jniLibs/arm64-v8a/libmain_hook.so differ diff --git a/lib/src/main/jniLibs/arm64-v8a/libvulkan_freedreno.so b/lib/src/main/jniLibs/arm64-v8a/libvulkan_freedreno.so index 33f8e9a1..f3bbe663 100644 Binary files a/lib/src/main/jniLibs/arm64-v8a/libvulkan_freedreno.so and b/lib/src/main/jniLibs/arm64-v8a/libvulkan_freedreno.so differ