Skip to content

Commit

Permalink
UI Compat: Add debug UI for selecting custom return addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Feb 24, 2024
1 parent 52aca1a commit 022bc29
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/CommitHash.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#define UEVR_COMMIT_HASH "54ef72d539578f581bc30358cab337f332868404"
#define UEVR_COMMIT_HASH "52aca1a46d889a2fa3c4cab2af2964b0e8ec0e1c"
#define UEVR_BUILD_DATE "24.02.2024"
#define UEVR_BUILD_TIME "00:00"
88 changes: 72 additions & 16 deletions src/mods/vr/FFakeStereoRenderingHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,65 @@ void FFakeStereoRenderingHook::on_draw_ui() {
m_tracking_system_hook->on_draw_ui();
}

auto& data = m_viewport_rt_hook_data;
std::scoped_lock _{data.retaddr_mutex};

std::vector<uintptr_t> retaddrs{};
std::vector<std::string> items{};
for (auto& addr : data.seen_retaddrs) {
items.push_back(fmt::format("{:x}", addr));
retaddrs.push_back(addr);
}

std::vector<const char*> citems{};
for (auto& item : items) {
citems.push_back(item.c_str());
}

if (!items.empty()) {
if (ImGui::BeginCombo("GetRenderTargetTexture Retaddrs", items[data.selected_retaddr].c_str())) {
for (int n = 0; n < items.size(); n++) {
ImGui::PushID(n);
auto retaddr = retaddrs[n];
const bool is_selected = (data.selected_retaddr == n);

// Calculate the text size for the current item
const auto text_size = ImGui::CalcTextSize(items[n].c_str(), NULL, true);
const auto padding = ImGui::GetStyle().ItemSpacing.x;
const auto selectable_size = ImVec2{text_size.x + padding, text_size.y};

if (ImGui::Selectable(items[n].c_str(), is_selected, ImGuiSelectableFlags_None, selectable_size)) {
data.selected_retaddr = n;
}

ImGui::SameLine();
if (ImGui::Button("Call Original")) {
data.call_original_retaddrs.insert(retaddr);
data.redirected_retaddrs.erase(retaddr);
}

ImGui::SameLine();
if (ImGui::Button("Redirect")) {
data.redirected_retaddrs.insert(retaddr);
data.call_original_retaddrs.erase(retaddr);
}

ImGui::SameLine();
if (data.call_original_retaddrs.contains(retaddr)) {
ImGui::Text("[Calling Original]");
} else if (data.redirected_retaddrs.contains(retaddr)) {
ImGui::Text("[Redirected]");
} else {
ImGui::Text("[Default]");
}

ImGui::PopID();
}
ImGui::EndCombo();
}

}

ImGui::TreePop();
}

Expand Down Expand Up @@ -1731,11 +1790,6 @@ void FFakeStereoRenderingHook::viewport_draw_hook(void* viewport, bool should_pr
// This is only used for the UI compatibility mode.
FRHITexture2D** FFakeStereoRenderingHook::viewport_get_render_target_texture_hook(sdk::FViewport* viewport) {
const auto retaddr = (uintptr_t)_ReturnAddress();
static std::unordered_set<uintptr_t> redirected_retaddrs{};
static std::unordered_set<uintptr_t> call_original_retaddrs{};
static std::unordered_set<uintptr_t> seen_retaddrs{};
static std::recursive_mutex retaddr_mutex{};
static bool has_view_family_tex{false};

SPDLOG_INFO_ONCE("FViewport::GetRenderTargetTexture called!");
const auto og = g_hook->m_viewport_get_render_target_texture_hook->get_original<decltype(&viewport_get_render_target_texture_hook)>();
Expand All @@ -1745,19 +1799,21 @@ FRHITexture2D** FFakeStereoRenderingHook::viewport_get_render_target_texture_hoo
return og(viewport);
}

auto& data = g_hook->m_viewport_rt_hook_data;

{
std::scoped_lock _{retaddr_mutex};
utility::ScopeGuard guard{[&](){ seen_retaddrs.insert(retaddr); }};
std::scoped_lock _{data.retaddr_mutex};
utility::ScopeGuard guard{[&](){ data.seen_retaddrs.insert(retaddr); }};

if (call_original_retaddrs.contains(retaddr)) {
if (data.call_original_retaddrs.contains(retaddr)) {
return og(viewport);
}

std::optional<size_t> func_start{};

// ALWAYS check the retaddr for ViewFamilyTexture first and never skip it
// This will fix the case where we run into some other texture initially.
if (!seen_retaddrs.contains(retaddr)) {
if (!data.seen_retaddrs.contains(retaddr)) {
SPDLOG_INFO("FViewport::GetRenderTargetTexture called from {:x}", retaddr);

func_start = utility::find_function_start(retaddr);
Expand All @@ -1771,19 +1827,19 @@ FRHITexture2D** FFakeStereoRenderingHook::viewport_get_render_target_texture_hoo
// Everything else we will redirect to the UI render target.
if (utility::find_string_reference_in_path(*func_start, L"ViewFamilyTexture", false)) {
SPDLOG_INFO("Found view family texture reference @ {:x}", retaddr);
call_original_retaddrs.insert(retaddr);
has_view_family_tex = true;
data.call_original_retaddrs.insert(retaddr);
data.has_view_family_tex = true;
return og(viewport);
}
}

// Hacky way to allow the first texture to go through
// For the games that are using something other than ViewFamilyTexture as the scene RT.
if (!call_original_retaddrs.empty() && !redirected_retaddrs.contains(retaddr) && !has_view_family_tex) {
if (!data.call_original_retaddrs.empty() && !data.redirected_retaddrs.contains(retaddr) && !data.has_view_family_tex) {
return og(viewport);
}

if (!redirected_retaddrs.contains(retaddr) && !call_original_retaddrs.contains(retaddr)) {
if (!data.redirected_retaddrs.contains(retaddr) && !data.call_original_retaddrs.contains(retaddr)) {
if (!func_start) {
func_start = utility::find_function_start(retaddr);

Expand All @@ -1801,20 +1857,20 @@ FRHITexture2D** FFakeStereoRenderingHook::viewport_get_render_target_texture_hoo

if (utility::find_string_reference_in_path(*func_start, L"FinalPostProcessColor", false)) {
SPDLOG_INFO("Found FinalPostProcessColor reference @ {:x}", retaddr);
call_original_retaddrs.insert(retaddr);
data.call_original_retaddrs.insert(retaddr);
return og(viewport);
}

// TODO? this needs some more rigorous filtering
// some games are insane and have multiple "UnknownTexture" references...
if (utility::find_string_reference_in_path(*func_start, L"UnknownTexture", false)) {
SPDLOG_INFO("Found unknown texture reference @ {:x}", retaddr);
call_original_retaddrs.insert(retaddr);
data.call_original_retaddrs.insert(retaddr);
return og(viewport);
}

SPDLOG_INFO("Redirecting FViewport::GetRenderTargetTexture call to UI render target @ {:x}", retaddr);
redirected_retaddrs.insert(retaddr);
data.redirected_retaddrs.insert(retaddr);
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/mods/vr/FFakeStereoRenderingHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,15 @@ class FFakeStereoRenderingHook : public ModComponent {

std::unique_ptr<IXRTrackingSystemHook> m_tracking_system_hook{};

struct {
std::unordered_set<uintptr_t> seen_retaddrs{};
std::unordered_set<uintptr_t> call_original_retaddrs{};
std::unordered_set<uintptr_t> redirected_retaddrs{};
std::recursive_mutex retaddr_mutex{};
bool has_view_family_tex{false};
int32_t selected_retaddr{0};
} m_viewport_rt_hook_data{};

VRRenderTargetManager m_rtm{};
VRRenderTargetManager_418 m_rtm_418{};
VRRenderTargetManager_Special m_rtm_special{};
Expand Down

0 comments on commit 022bc29

Please sign in to comment.