diff --git a/include/adrenotools/driver.h b/include/adrenotools/driver.h index 1749b2f..b09b4db 100644 --- a/include/adrenotools/driver.h +++ b/include/adrenotools/driver.h @@ -24,7 +24,7 @@ extern "C" { 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 + * @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 @@ -32,6 +32,22 @@ void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *t */ 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) diff --git a/src/driver.cpp b/src/driver.cpp index 435b787..4ddee4a 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +136,58 @@ err: return false; } +bool adrenotools_mem_gpu_allocate(void *handle, uint64_t *size) { + auto mapping{reinterpret_cast(handle)}; + + kgsl_gpuobj_alloc gpuobjAlloc{ + .size = *size, + .flags = KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT | KGSL_MEMFLAGS_IOCOHERENT, + }; + + kgsl_gpuobj_info info{}; + + int kgslFd{open("/dev/kgsl-3d0", O_RDWR)}; + if (kgslFd < 0) + return false; + + int ret{ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_ALLOC, &gpuobjAlloc)}; + if (ret) + goto err; + + *size = gpuobjAlloc.mmapsize; + + info.id = gpuobjAlloc.id; + + ret = ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_INFO, &info); + if (ret) + goto err; + + mapping->host_ptr = nullptr; + mapping->gpu_addr = info.gpuaddr; + mapping->size = *size; + mapping->flags = 0xc2600; //!< Unknown flags, but they are required for the mapping to work + + close(kgslFd); + return true; + +err: + close(kgslFd); + return false; +} + + +bool adrenotools_mem_cpu_map(void *handle, void *hostPtr, uint64_t size) { + auto mapping{reinterpret_cast(handle)}; + + int kgslFd{open("/dev/kgsl-3d0", O_RDWR)}; + if (kgslFd < 0) + return false; + + mapping->host_ptr = mmap(hostPtr, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kgslFd, mapping->gpu_addr); + close(kgslFd); + return mapping->host_ptr != nullptr; +} + bool adrenotools_validate_gpu_mapping(void *handle) { auto importMapping{reinterpret_cast(handle)}; return importMapping->gpu_addr == ADRENOTOOLS_GPU_MAPPING_SUCCEEDED_MAGIC; diff --git a/src/hook/hook_impl.h b/src/hook/hook_impl.h index fd0e3ca..2ce2471 100644 --- a/src/hook/hook_impl.h +++ b/src/hook/hook_impl.h @@ -12,7 +12,7 @@ extern "C" { void init_hook_param(const void *param); -void init_gsl(void *alloc, void *free); +void init_gsl(void *alloc, void *alloc64, void *free); void *hook_android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo);