Skip to content

Commit

Permalink
RenderTargetPoolHook: Initial work for UE5
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Nov 30, 2024
1 parent 2a65a2a commit 522ff8a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 19 deletions.
69 changes: 51 additions & 18 deletions src/mods/vr/RenderTargetPoolHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,26 @@ void RenderTargetPoolHook::on_pre_engine_tick(sdk::UGameEngine* engine, float de
bool RenderTargetPoolHook::hook() {
SPDLOG_INFO("Attempting to hook RenderTargetPool::FindFreeElement");

const auto find_free_element = sdk::FRenderTargetPool::get_find_free_element_fn();
const auto is_ue5 = VR::get()->get_fake_stereo_hook()->has_double_precision();
const auto find_free_element = sdk::FRenderTargetPool::get_find_free_element_fn(is_ue5);

if (!find_free_element) {
SPDLOG_ERROR("Failed to find FRenderTargetPool::FindFreeElement, cannot hook");
return false;
}

if (VR::get()->get_fake_stereo_hook()->has_double_precision()) {
/*if (VR::get()->get_fake_stereo_hook()->has_double_precision()) {
spdlog::error("Render target pool hook is temporarily disabled on UE5, sorry :(");
return false;
}
}*/

SPDLOG_INFO("Performing hook...");

m_find_free_element_hook = safetyhook::create_inline((void*)*find_free_element, find_free_element_hook);
if (is_ue5) {
m_find_free_element_hook = safetyhook::create_inline((void*)*find_free_element, find_free_element_hook_ue5);
} else {
m_find_free_element_hook = safetyhook::create_inline((void*)*find_free_element, find_free_element_hook);
}

if (m_find_free_element_hook) {
SPDLOG_INFO("Successfully hooked RenderTargetPool::FindFreeElement");
Expand All @@ -56,25 +61,19 @@ bool RenderTargetPoolHook::hook() {
return true;
}

bool RenderTargetPoolHook::find_free_element_hook(
sdk::FRenderTargetPool* pool, sdk::FRHICommandListBase* cmd_list,
sdk::FPooledRenderTargetDesc* desc, TRefCountPtr<IPooledRenderTarget>* out,
const wchar_t* name,
uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10)
void RenderTargetPoolHook::on_post_find_free_element(
sdk::FRenderTargetPool* pool,
sdk::FPooledRenderTargetDesc* desc,
TRefCountPtr<IPooledRenderTarget>* out,
const wchar_t* name)
{
SPDLOG_INFO_ONCE("FRenderTargetPool::FindFreeElement called for the first time!");

const auto result = g_hook->m_find_free_element_hook.call<bool>(pool, cmd_list, desc, out, name, a6, a7, a8, a9, a10);

SPDLOG_INFO_ONCE("Finished calling FRenderTargetPool::FindFreeElement!");

// 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 (!g_hook->m_wants_activate) {
if (!m_wants_activate) {
std::scoped_lock _{g_hook->m_mutex};
g_hook->m_render_targets.clear();
return result;
m_render_targets.clear();
return;
}

if (name != nullptr) {
Expand All @@ -93,6 +92,40 @@ bool RenderTargetPoolHook::find_free_element_hook(
SPDLOG_INFO("FRenderTargetPool::FindFreeElement called with name {}", utility::narrow(name));
}
}
}

bool RenderTargetPoolHook::find_free_element_hook(
sdk::FRenderTargetPool* pool, sdk::FRHICommandListBase* cmd_list,
sdk::FPooledRenderTargetDesc* desc, TRefCountPtr<IPooledRenderTarget>* out,
const wchar_t* name,
uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10)
{
SPDLOG_INFO_ONCE("FRenderTargetPool::FindFreeElement (UE4) called for the first time!");

const auto result = g_hook->m_find_free_element_hook.call<bool>(pool, cmd_list, desc, out, name, a6, a7, a8, a9, a10);

SPDLOG_INFO_ONCE("Finished calling FRenderTargetPool::FindFreeElement!");

g_hook->on_post_find_free_element(pool, desc, out, name);

return result;
}

bool RenderTargetPoolHook::find_free_element_hook_ue5(
sdk::FRenderTargetPool* pool,
sdk::FPooledRenderTargetDesc* desc,
TRefCountPtr<IPooledRenderTarget>* out,
const wchar_t* name,
// these arent uintptrs, just defending against future changes to the size of the params
uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10)
{
SPDLOG_INFO_ONCE("FRenderTargetPool::FindFreeElement (UE5) called for the first time!");

const auto result = g_hook->m_find_free_element_hook.call<bool>(pool, desc, out, name, a6, a7, a8, a9, a10);

SPDLOG_INFO_ONCE("Finished calling FRenderTargetPool::FindFreeElement! (UE5)");

g_hook->on_post_find_free_element(pool, desc, out, name);

return result;
}
17 changes: 16 additions & 1 deletion src/mods/vr/RenderTargetPoolHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,22 @@ class RenderTargetPoolHook : public ModComponent {
TRefCountPtr<IPooledRenderTarget>* out,
const wchar_t* name,
// these arent uintptrs, just defending against future changes to the size of the params
uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10);
uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10);

static bool find_free_element_hook_ue5(
sdk::FRenderTargetPool* pool,
sdk::FPooledRenderTargetDesc* desc,
TRefCountPtr<IPooledRenderTarget>* out,
const wchar_t* name,
// these arent uintptrs, just defending against future changes to the size of the params
uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10
);

void on_post_find_free_element(sdk::FRenderTargetPool* pool,
sdk::FPooledRenderTargetDesc* desc,
TRefCountPtr<IPooledRenderTarget>* out,
const wchar_t* name
);

bool m_attempted_hook{false};
bool m_hooked{false};
Expand Down

0 comments on commit 522ff8a

Please sign in to comment.