From aab171b1cb6f342c8da01aebda285917bb3bdd84 Mon Sep 17 00:00:00 2001 From: praydog Date: Thu, 22 Feb 2024 09:26:31 -0800 Subject: [PATCH] Plugins: Add various render target functions --- CMakeLists.txt | 6 ++ include/uevr/API.h | 22 ++++++- include/uevr/API.hpp | 66 +++++++++++++++++++ src/CommitHash.hpp | 4 +- src/mods/PluginLoader.cpp | 9 ++- src/mods/VR.hpp | 10 ++- .../FFakeStereoRenderingFunctions.cpp | 35 ++++++++++ .../FFakeStereoRenderingFunctions.hpp | 12 ++++ .../pluginloader/FRHITexture2DFunctions.cpp | 21 ++++++ .../pluginloader/FRHITexture2DFunctions.hpp | 11 ++++ .../pluginloader/FRenderTargetPoolHook.cpp | 25 +++++++ .../pluginloader/FRenderTargetPoolHook.hpp | 11 ++++ src/mods/vr/D3D11Component.cpp | 6 ++ src/mods/vr/D3D11Component.hpp | 1 + src/mods/vr/RenderTargetPoolHook.cpp | 16 +++-- src/mods/vr/RenderTargetPoolHook.hpp | 5 ++ 16 files changed, 250 insertions(+), 10 deletions(-) create mode 100644 src/mods/pluginloader/FFakeStereoRenderingFunctions.cpp create mode 100644 src/mods/pluginloader/FFakeStereoRenderingFunctions.hpp create mode 100644 src/mods/pluginloader/FRHITexture2DFunctions.cpp create mode 100644 src/mods/pluginloader/FRHITexture2DFunctions.hpp create mode 100644 src/mods/pluginloader/FRenderTargetPoolHook.cpp create mode 100644 src/mods/pluginloader/FRenderTargetPoolHook.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c04637a3..855b1a5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -666,6 +666,9 @@ list(APPEND uevr_SOURCES "src/mods/PluginLoader.cpp" "src/mods/UObjectHook.cpp" "src/mods/VR.cpp" + "src/mods/pluginloader/FFakeStereoRenderingFunctions.cpp" + "src/mods/pluginloader/FRHITexture2DFunctions.cpp" + "src/mods/pluginloader/FRenderTargetPoolHook.cpp" "src/mods/uobjecthook/SDKDumper.cpp" "src/mods/vr/Bindings.cpp" "src/mods/vr/CVarManager.cpp" @@ -701,6 +704,9 @@ list(APPEND uevr_SOURCES "src/mods/PluginLoader.hpp" "src/mods/UObjectHook.hpp" "src/mods/VR.hpp" + "src/mods/pluginloader/FFakeStereoRenderingFunctions.hpp" + "src/mods/pluginloader/FRHITexture2DFunctions.hpp" + "src/mods/pluginloader/FRenderTargetPoolHook.hpp" "src/mods/uobjecthook/SDKDumper.hpp" "src/mods/vr/CVarManager.hpp" "src/mods/vr/D3D11Component.hpp" diff --git a/include/uevr/API.h b/include/uevr/API.h index a6f3595c..2f08c709 100644 --- a/include/uevr/API.h +++ b/include/uevr/API.h @@ -36,7 +36,7 @@ SOFTWARE. #define UEVR_OUT #define UEVR_PLUGIN_VERSION_MAJOR 2 -#define UEVR_PLUGIN_VERSION_MINOR 13 +#define UEVR_PLUGIN_VERSION_MINOR 14 #define UEVR_PLUGIN_VERSION_PATCH 0 #define UEVR_RENDERER_D3D11 0 @@ -74,6 +74,7 @@ DECLARE_UEVR_HANDLE(UEVR_IConsoleCommandHandle); DECLARE_UEVR_HANDLE(UEVR_IConsoleVariableHandle); DECLARE_UEVR_HANDLE(UEVR_TArrayHandle); DECLARE_UEVR_HANDLE(UEVR_FMallocHandle); +DECLARE_UEVR_HANDLE(UEVR_FRHITexture2DHandle); /* OpenXR stuff */ DECLARE_UEVR_HANDLE(UEVR_XrInstance); @@ -342,6 +343,22 @@ typedef struct { void (*free)(UEVR_FMallocHandle instance, void* ptr); } UEVR_FMallocFunctions; +DECLARE_UEVR_HANDLE(UEVR_IPooledRenderTargetHandle); + +typedef struct { + void (*activate)(); + UEVR_IPooledRenderTargetHandle (*get_render_target)(const wchar_t* name); +} UEVR_FRenderTargetPoolHookFunctions; + +typedef struct { + UEVR_FRHITexture2DHandle (*get_scene_render_target)(); + UEVR_FRHITexture2DHandle (*get_ui_render_target)(); +} UEVR_FFakeStereoRenderingHookFunctions; + +typedef struct { + void* (*get_native_resource)(UEVR_FRHITexture2DHandle texture); +} UEVR_FRHITexture2DFunctions; + typedef struct { const UEVR_SDKFunctions* functions; const UEVR_SDKCallbacks* callbacks; @@ -357,6 +374,9 @@ typedef struct { const UEVR_FNameFunctions* fname; const UEVR_ConsoleFunctions* console; const UEVR_FMallocFunctions* malloc; + const UEVR_FRenderTargetPoolHookFunctions* render_target_pool_hook; + const UEVR_FFakeStereoRenderingHookFunctions* stereo_hook; + const UEVR_FRHITexture2DFunctions* frhitexture2d; } UEVR_SDKData; DECLARE_UEVR_HANDLE(UEVR_IVRSystem); diff --git a/include/uevr/API.hpp b/include/uevr/API.hpp index 24fb4345..26c1cb1c 100644 --- a/include/uevr/API.hpp +++ b/include/uevr/API.hpp @@ -129,6 +129,8 @@ class API { struct IConsoleCommand; struct ConsoleObjectElement; struct UObjectHook; + struct FRHITexture2D; + struct IPooledRenderTarget; template struct TArray; @@ -741,6 +743,26 @@ class API { } }; + struct FRHITexture2D { + inline UEVR_FRHITexture2DHandle to_handle() { return (UEVR_FRHITexture2DHandle)this; } + inline UEVR_FRHITexture2DHandle to_handle() const { return (UEVR_FRHITexture2DHandle)this; } + + void* get_native_resource() const { + static const auto fn = initialize()->get_native_resource; + return fn(to_handle()); + } + + private: + static inline const UEVR_FRHITexture2DFunctions* s_functions{nullptr}; + static inline const UEVR_FRHITexture2DFunctions* initialize() { + if (s_functions == nullptr) { + s_functions = API::get()->sdk()->frhitexture2d; + } + + return s_functions; + } + }; + public: // UEVR specific stuff struct UObjectHook { @@ -831,6 +853,50 @@ class API { } }; + struct RenderTargetPoolHook { + static void activate() { + static const auto fn = initialize()->activate; + fn(); + } + + static IPooledRenderTarget* get_render_target(const wchar_t* name) { + static const auto fn = initialize()->get_render_target; + return (IPooledRenderTarget*)fn(name); + } + + private: + static inline const UEVR_FRenderTargetPoolHookFunctions* s_functions{nullptr}; + static inline const UEVR_FRenderTargetPoolHookFunctions* initialize() { + if (s_functions == nullptr) { + s_functions = API::get()->sdk()->render_target_pool_hook; + } + + return s_functions; + } + }; + + struct StereoHook { + static FRHITexture2D* get_scene_render_target() { + static const auto fn = initialize()->get_scene_render_target; + return (FRHITexture2D*)fn(); + } + + static FRHITexture2D* get_ui_render_target() { + static const auto fn = initialize()->get_ui_render_target; + return (FRHITexture2D*)fn(); + } + + private: + static inline const UEVR_FFakeStereoRenderingHookFunctions* s_functions{nullptr}; + static inline const UEVR_FFakeStereoRenderingHookFunctions* initialize() { + if (s_functions == nullptr) { + s_functions = API::get()->sdk()->stereo_hook; + } + + return s_functions; + } + }; + private: const UEVR_PluginInitializeParam* m_param; const UEVR_SDKData* m_sdk; diff --git a/src/CommitHash.hpp b/src/CommitHash.hpp index 41fa454c..7253ae36 100644 --- a/src/CommitHash.hpp +++ b/src/CommitHash.hpp @@ -1,4 +1,4 @@ #pragma once -#define UEVR_COMMIT_HASH "f48ed675e2c1f8730b2a7ebfb9a1981c9a6ebf3d" -#define UEVR_BUILD_DATE "20.02.2024" +#define UEVR_COMMIT_HASH "c25695a8c0ec35b556229046cc7011e27f4d42ee" +#define UEVR_BUILD_DATE "22.02.2024" #define UEVR_BUILD_TIME "00:00" diff --git a/src/mods/PluginLoader.cpp b/src/mods/PluginLoader.cpp index 6f4d1efd..9342a779 100644 --- a/src/mods/PluginLoader.cpp +++ b/src/mods/PluginLoader.cpp @@ -22,6 +22,10 @@ #include #include +#include "pluginloader/FFakeStereoRenderingFunctions.hpp" +#include "pluginloader/FRenderTargetPoolHook.hpp" +#include "pluginloader/FRHITexture2DFunctions.hpp" + #include "UObjectHook.hpp" #include "VR.hpp" @@ -775,7 +779,10 @@ UEVR_SDKData g_sdk_data { &g_ffield_class_functions, &g_fname_functions, &g_console_functions, - &g_malloc_functions + &g_malloc_functions, + &uevr::render_target_pool_hook::functions, + &uevr::stereo_hook::functions, + &uevr::frhitexture2d::functions }; namespace uevr { diff --git a/src/mods/VR.hpp b/src/mods/VR.hpp index 3d978724..7e118b6b 100644 --- a/src/mods/VR.hpp +++ b/src/mods/VR.hpp @@ -397,7 +397,7 @@ class VR : public Mod { return m_lowest_xinput_user_index; } - auto& get_render_target_pool_hook() { + auto& get_render_target_pool_hook() const { return m_render_target_pool_hook; } @@ -577,6 +577,14 @@ class VR : public Mod { return m_extreme_compat_mode->value(); } + vrmod::D3D11Component& d3d11() { + return m_d3d11; + } + + vrmod::D3D12Component& d3d12() { + return m_d3d12; + } + private: Vector4f get_position_unsafe(uint32_t index) const; Vector4f get_velocity_unsafe(uint32_t index) const; diff --git a/src/mods/pluginloader/FFakeStereoRenderingFunctions.cpp b/src/mods/pluginloader/FFakeStereoRenderingFunctions.cpp new file mode 100644 index 00000000..5828c7e5 --- /dev/null +++ b/src/mods/pluginloader/FFakeStereoRenderingFunctions.cpp @@ -0,0 +1,35 @@ +#include "uevr/API.h" + +#include "mods/VR.hpp" +#include "FFakeStereoRenderingFunctions.hpp" + +namespace uevr { +UEVR_FRHITexture2DHandle stereo_hook::get_scene_render_target() { + const auto& vr = VR::get(); + if (auto& hook = vr->get_fake_stereo_hook(); hook != nullptr) { + auto rtm = hook->get_render_target_manager(); + if (auto rtm = hook->get_render_target_manager(); rtm != nullptr) { + return (UEVR_FRHITexture2DHandle)rtm->get_render_target(); + } + } + + return nullptr; +} + +UEVR_FRHITexture2DHandle stereo_hook::get_ui_render_target() { + const auto& vr = VR::get(); + if (auto& hook = vr->get_fake_stereo_hook(); hook != nullptr) { + auto rtm = hook->get_render_target_manager(); + if (auto rtm = hook->get_render_target_manager(); rtm != nullptr) { + return (UEVR_FRHITexture2DHandle)rtm->get_ui_target(); + } + } + + return nullptr; +} + +UEVR_FFakeStereoRenderingHookFunctions stereo_hook::functions { + &stereo_hook::get_scene_render_target, + &stereo_hook::get_ui_render_target +}; +} \ No newline at end of file diff --git a/src/mods/pluginloader/FFakeStereoRenderingFunctions.hpp b/src/mods/pluginloader/FFakeStereoRenderingFunctions.hpp new file mode 100644 index 00000000..2b7e7ea6 --- /dev/null +++ b/src/mods/pluginloader/FFakeStereoRenderingFunctions.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "uevr/API.h" + +namespace uevr { +namespace stereo_hook { +UEVR_FRHITexture2DHandle get_scene_render_target(); +UEVR_FRHITexture2DHandle get_ui_render_target(); + +extern UEVR_FFakeStereoRenderingHookFunctions functions; +} +} \ No newline at end of file diff --git a/src/mods/pluginloader/FRHITexture2DFunctions.cpp b/src/mods/pluginloader/FRHITexture2DFunctions.cpp new file mode 100644 index 00000000..13093285 --- /dev/null +++ b/src/mods/pluginloader/FRHITexture2DFunctions.cpp @@ -0,0 +1,21 @@ +#include + +#include "FRHITexture2DFunctions.hpp" + +namespace uevr { +namespace frhitexture2d { +void* get_native_resource(UEVR_FRHITexture2DHandle handle) { + const auto texture = (::FRHITexture2D*)handle; + + if (texture == nullptr) { + return nullptr; + } + + return texture->get_native_resource(); +} + +UEVR_FRHITexture2DFunctions functions { + &uevr::frhitexture2d::get_native_resource +}; +} +} \ No newline at end of file diff --git a/src/mods/pluginloader/FRHITexture2DFunctions.hpp b/src/mods/pluginloader/FRHITexture2DFunctions.hpp new file mode 100644 index 00000000..a8eda93d --- /dev/null +++ b/src/mods/pluginloader/FRHITexture2DFunctions.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "uevr/API.h" + +namespace uevr { +namespace frhitexture2d { +void* get_native_resource(UEVR_FRHITexture2DHandle handle); + +extern UEVR_FRHITexture2DFunctions functions; +} +} \ No newline at end of file diff --git a/src/mods/pluginloader/FRenderTargetPoolHook.cpp b/src/mods/pluginloader/FRenderTargetPoolHook.cpp new file mode 100644 index 00000000..f1cc6a24 --- /dev/null +++ b/src/mods/pluginloader/FRenderTargetPoolHook.cpp @@ -0,0 +1,25 @@ +#include "../mods/VR.hpp" +#include "FRenderTargetPoolHook.hpp" + +namespace uevr { +void render_target_pool_hook::activate() { + const auto& vr = VR::get(); + if (auto& hook = vr->get_render_target_pool_hook(); hook != nullptr) { + hook->activate(); + } +} + +UEVR_IPooledRenderTargetHandle render_target_pool_hook::get_render_target(const wchar_t* name) { + const auto& vr = VR::get(); + if (auto& hook = vr->get_render_target_pool_hook(); hook != nullptr) { + return (UEVR_IPooledRenderTargetHandle)hook->get_render_target(name); + } + + return nullptr; +} + +UEVR_FRenderTargetPoolHookFunctions render_target_pool_hook::functions { + &render_target_pool_hook::activate, + &render_target_pool_hook::get_render_target +}; +} \ No newline at end of file diff --git a/src/mods/pluginloader/FRenderTargetPoolHook.hpp b/src/mods/pluginloader/FRenderTargetPoolHook.hpp new file mode 100644 index 00000000..ddb06b76 --- /dev/null +++ b/src/mods/pluginloader/FRenderTargetPoolHook.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "uevr/API.h" + +namespace uevr { +namespace render_target_pool_hook { +void activate(); +UEVR_IPooledRenderTargetHandle get_render_target(const wchar_t* name); +extern UEVR_FRenderTargetPoolHookFunctions functions; +} +} \ No newline at end of file diff --git a/src/mods/vr/D3D11Component.cpp b/src/mods/vr/D3D11Component.cpp index c8ddefae..f74e3b40 100644 --- a/src/mods/vr/D3D11Component.cpp +++ b/src/mods/vr/D3D11Component.cpp @@ -1005,6 +1005,12 @@ bool D3D11Component::clear_tex(ID3D11Resource* tex, std::optional f return ctx.clear_rtv(color); } +bool D3D11Component::clear_tex(ID3D11Resource* tex, float* color, std::optional format) { + auto ctx = TextureContext{tex, format}; + + return ctx.clear_rtv(color); +} + void D3D11Component::copy_tex(ID3D11Resource* src, ID3D11Resource* dst) { auto& hook = g_framework->get_d3d11_hook(); auto device = hook->get_device(); diff --git a/src/mods/vr/D3D11Component.hpp b/src/mods/vr/D3D11Component.hpp index 7f05ce50..bcc43495 100644 --- a/src/mods/vr/D3D11Component.hpp +++ b/src/mods/vr/D3D11Component.hpp @@ -34,6 +34,7 @@ class D3D11Component { auto& get_ui_tex() { return m_ui_tex; } bool clear_tex(ID3D11Resource* rsrc, std::optional format = std::nullopt); + bool clear_tex(ID3D11Resource* rsrc, float* color, std::optional format = std::nullopt); void copy_tex(ID3D11Resource* src, ID3D11Resource* dst); void force_reset() { m_force_reset = true; } diff --git a/src/mods/vr/RenderTargetPoolHook.cpp b/src/mods/vr/RenderTargetPoolHook.cpp index 6b8fb2fe..26abb394 100644 --- a/src/mods/vr/RenderTargetPoolHook.cpp +++ b/src/mods/vr/RenderTargetPoolHook.cpp @@ -18,6 +18,10 @@ RenderTargetPoolHook::RenderTargetPoolHook() { void RenderTargetPoolHook::on_pre_engine_tick(sdk::UGameEngine* engine, float delta) { if (!m_attempted_hook && VR::get()->is_depth_enabled()) { + m_wants_activate = true; + } + + if (!m_attempted_hook && m_wants_activate) { m_attempted_hook = true; m_hooked = hook(); } @@ -66,7 +70,7 @@ bool RenderTargetPoolHook::find_free_element_hook( // Right now we are only using this for depth // and on some games it will crash if we mess with anything // so, TODO: fix the games that crash with depth enabled - if (!VR::get()->is_depth_enabled()) { + if (!g_hook->m_wants_activate) { std::scoped_lock _{g_hook->m_mutex}; g_hook->m_render_targets.clear(); return result; @@ -77,11 +81,13 @@ bool RenderTargetPoolHook::find_free_element_hook( if (out != nullptr) { std::scoped_lock _{g_hook->m_mutex}; - g_hook->m_render_targets[name] = out->reference; - /*if (out->reference != nullptr && out->reference->item.texture.texture != nullptr) { - const auto resource = out->reference->item.texture.texture->get_native_resource(); - }*/ + if (!g_hook->m_seen_names.contains(name)) { + g_hook->m_seen_names.insert(name); + SPDLOG_INFO("FRenderTargetPool::FindFreeElement called with name {}", utility::narrow(name)); + } + + g_hook->m_render_targets[name] = out->reference; } } diff --git a/src/mods/vr/RenderTargetPoolHook.hpp b/src/mods/vr/RenderTargetPoolHook.hpp index 01cf02eb..fc6420fd 100644 --- a/src/mods/vr/RenderTargetPoolHook.hpp +++ b/src/mods/vr/RenderTargetPoolHook.hpp @@ -19,6 +19,9 @@ class RenderTargetPoolHook : public ModComponent { public: RenderTargetPoolHook(); void on_pre_engine_tick(sdk::UGameEngine* engine, float delta) override; + void activate() { + m_wants_activate = true; + } IPooledRenderTarget* get_render_target(const std::wstring& name) { std::scoped_lock _{m_mutex}; @@ -67,8 +70,10 @@ class RenderTargetPoolHook : public ModComponent { bool m_attempted_hook{false}; bool m_hooked{false}; + bool m_wants_activate{false}; std::recursive_mutex m_mutex{}; SafetyHookInline m_find_free_element_hook{}; std::unordered_map m_render_targets{}; + std::unordered_set m_seen_names{}; }; \ No newline at end of file