removed copying

This commit is contained in:
2026-05-06 20:10:34 +03:00
parent d90164cab8
commit 6ced4acdb6
2 changed files with 47 additions and 40 deletions

View File

@@ -3,6 +3,7 @@
#ifdef OMATH_ENABLE_HOOKING #ifdef OMATH_ENABLE_HOOKING
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <memory>
#include <optional> #include <optional>
#include <shared_mutex> #include <shared_mutex>
@@ -43,6 +44,9 @@ namespace omath::hooks
// Return nullopt to pass the message to the original WndProc; return a value to intercept it. // Return nullopt to pass the message to the original WndProc; return a value to intercept it.
using wnd_proc_callback = std::function<std::optional<LRESULT>(HWND, UINT, WPARAM, LPARAM)>; using wnd_proc_callback = std::function<std::optional<LRESULT>(HWND, UINT, WPARAM, LPARAM)>;
template<typename Callback>
using callback_ptr = std::shared_ptr<const Callback>;
[[nodiscard]] static HooksManager& get(); [[nodiscard]] static HooksManager& get();
HooksManager(const HooksManager&) = delete; HooksManager(const HooksManager&) = delete;
HooksManager& operator=(const HooksManager&) = delete; HooksManager& operator=(const HooksManager&) = delete;
@@ -142,15 +146,15 @@ namespace omath::hooks
safetyhook::InlineHook m_opengl_wgl_swap_buffers_hook; safetyhook::InlineHook m_opengl_wgl_swap_buffers_hook;
safetyhook::InlineHook m_opengl_swap_buffers_hook; safetyhook::InlineHook m_opengl_swap_buffers_hook;
dx9_present_callback m_dx9_present_cb; callback_ptr<dx9_present_callback> m_dx9_present_cb;
dx9_reset_callback m_dx9_reset_cb; callback_ptr<dx9_reset_callback> m_dx9_reset_cb;
dx9_end_scene_callback m_dx9_end_scene_cb; callback_ptr<dx9_end_scene_callback> m_dx9_end_scene_cb;
present_callback m_present_cb; callback_ptr<present_callback> m_present_cb;
resize_buffers_callback m_resize_buffers_cb; callback_ptr<resize_buffers_callback> m_resize_buffers_cb;
execute_command_lists_callback m_execute_command_lists_cb; callback_ptr<execute_command_lists_callback> m_execute_command_lists_cb;
opengl_swap_buffers_callback m_opengl_swap_buffers_cb; callback_ptr<opengl_swap_buffers_callback> m_opengl_swap_buffers_cb;
wnd_proc_callback m_wnd_proc_cb; callback_ptr<wnd_proc_callback> m_wnd_proc_cb;
}; };
} // namespace omath::hooks } // namespace omath::hooks

View File

@@ -259,19 +259,19 @@ namespace omath::hooks
void HooksManager::set_on_dx9_present(dx9_present_callback callback) void HooksManager::set_on_dx9_present(dx9_present_callback callback)
{ {
std::unique_lock lock(m_dx9_present_mutex); std::unique_lock lock(m_dx9_present_mutex);
m_dx9_present_cb = std::move(callback); m_dx9_present_cb = callback ? std::make_shared<dx9_present_callback>(std::move(callback)) : nullptr;
} }
void HooksManager::set_on_dx9_reset(dx9_reset_callback callback) void HooksManager::set_on_dx9_reset(dx9_reset_callback callback)
{ {
std::unique_lock lock(m_dx9_reset_mutex); std::unique_lock lock(m_dx9_reset_mutex);
m_dx9_reset_cb = std::move(callback); m_dx9_reset_cb = callback ? std::make_shared<dx9_reset_callback>(std::move(callback)) : nullptr;
} }
void HooksManager::set_on_dx9_end_scene(dx9_end_scene_callback callback) void HooksManager::set_on_dx9_end_scene(dx9_end_scene_callback callback)
{ {
std::unique_lock lock(m_dx9_end_scene_mutex); std::unique_lock lock(m_dx9_end_scene_mutex);
m_dx9_end_scene_cb = std::move(callback); m_dx9_end_scene_cb = callback ? std::make_shared<dx9_end_scene_callback>(std::move(callback)) : nullptr;
} }
bool HooksManager::hook_dx11() bool HooksManager::hook_dx11()
@@ -433,25 +433,27 @@ namespace omath::hooks
void HooksManager::set_on_opengl_swap_buffers(opengl_swap_buffers_callback callback) void HooksManager::set_on_opengl_swap_buffers(opengl_swap_buffers_callback callback)
{ {
std::unique_lock lock(m_opengl_swap_buffers_mutex); std::unique_lock lock(m_opengl_swap_buffers_mutex);
m_opengl_swap_buffers_cb = std::move(callback); m_opengl_swap_buffers_cb =
callback ? std::make_shared<opengl_swap_buffers_callback>(std::move(callback)) : nullptr;
} }
void HooksManager::set_on_present(present_callback callback) void HooksManager::set_on_present(present_callback callback)
{ {
std::unique_lock lock(m_present_mutex); std::unique_lock lock(m_present_mutex);
m_present_cb = std::move(callback); m_present_cb = callback ? std::make_shared<present_callback>(std::move(callback)) : nullptr;
} }
void HooksManager::set_on_resize_buffers(resize_buffers_callback callback) void HooksManager::set_on_resize_buffers(resize_buffers_callback callback)
{ {
std::unique_lock lock(m_resize_buffers_mutex); std::unique_lock lock(m_resize_buffers_mutex);
m_resize_buffers_cb = std::move(callback); m_resize_buffers_cb = callback ? std::make_shared<resize_buffers_callback>(std::move(callback)) : nullptr;
} }
void HooksManager::set_on_execute_command_lists(execute_command_lists_callback callback) void HooksManager::set_on_execute_command_lists(execute_command_lists_callback callback)
{ {
std::unique_lock lock(m_execute_command_lists_mutex); std::unique_lock lock(m_execute_command_lists_mutex);
m_execute_command_lists_cb = std::move(callback); m_execute_command_lists_cb =
callback ? std::make_shared<execute_command_lists_callback>(std::move(callback)) : nullptr;
} }
bool HooksManager::hook_wnd_proc(HWND hwnd) bool HooksManager::hook_wnd_proc(HWND hwnd)
@@ -486,24 +488,25 @@ namespace omath::hooks
void HooksManager::set_on_wnd_proc(wnd_proc_callback callback) void HooksManager::set_on_wnd_proc(wnd_proc_callback callback)
{ {
std::unique_lock lock(m_wnd_proc_mutex); std::unique_lock lock(m_wnd_proc_mutex);
m_wnd_proc_cb = std::move(callback); m_wnd_proc_cb = callback ? std::make_shared<wnd_proc_callback>(std::move(callback)) : nullptr;
} }
// Detour implementations: copy callback under shared lock, call it unlocked, // Detour implementations: copy a shared_ptr to the callback under shared lock, call it unlocked,
// then call original. This avoids a deadlock if the callback itself calls set_on_*(). // then call original. This avoids copying captured lambda state every frame and still avoids
// a deadlock if the callback itself calls set_on_*().
HRESULT __stdcall HooksManager::dx9_present_detour(IDirect3DDevice9* p_device, const RECT* p_source_rect, HRESULT __stdcall HooksManager::dx9_present_detour(IDirect3DDevice9* p_device, const RECT* p_source_rect,
const RECT* p_dest_rect, HWND h_dest_window_override, const RECT* p_dest_rect, HWND h_dest_window_override,
const RGNDATA* p_dirty_region) const RGNDATA* p_dirty_region)
{ {
auto& mgr = get(); auto& mgr = get();
dx9_present_callback cb; callback_ptr<dx9_present_callback> cb;
{ {
std::shared_lock lock(mgr.m_dx9_present_mutex); std::shared_lock lock(mgr.m_dx9_present_mutex);
cb = mgr.m_dx9_present_cb; cb = mgr.m_dx9_present_cb;
} }
if (cb) if (cb)
cb(p_device, p_source_rect, p_dest_rect, h_dest_window_override, p_dirty_region); (*cb)(p_device, p_source_rect, p_dest_rect, h_dest_window_override, p_dirty_region);
return mgr.m_dx9_present_hook.call<HRESULT>(p_device, p_source_rect, p_dest_rect, h_dest_window_override, return mgr.m_dx9_present_hook.call<HRESULT>(p_device, p_source_rect, p_dest_rect, h_dest_window_override,
p_dirty_region); p_dirty_region);
} }
@@ -512,39 +515,39 @@ namespace omath::hooks
D3DPRESENT_PARAMETERS* p_presentation_parameters) D3DPRESENT_PARAMETERS* p_presentation_parameters)
{ {
auto& mgr = get(); auto& mgr = get();
dx9_reset_callback cb; callback_ptr<dx9_reset_callback> cb;
{ {
std::shared_lock lock(mgr.m_dx9_reset_mutex); std::shared_lock lock(mgr.m_dx9_reset_mutex);
cb = mgr.m_dx9_reset_cb; cb = mgr.m_dx9_reset_cb;
} }
if (cb) if (cb)
cb(p_device, p_presentation_parameters); (*cb)(p_device, p_presentation_parameters);
return mgr.m_dx9_reset_hook.call<HRESULT>(p_device, p_presentation_parameters); return mgr.m_dx9_reset_hook.call<HRESULT>(p_device, p_presentation_parameters);
} }
HRESULT __stdcall HooksManager::dx9_end_scene_detour(IDirect3DDevice9* p_device) HRESULT __stdcall HooksManager::dx9_end_scene_detour(IDirect3DDevice9* p_device)
{ {
auto& mgr = get(); auto& mgr = get();
dx9_end_scene_callback cb; callback_ptr<dx9_end_scene_callback> cb;
{ {
std::shared_lock lock(mgr.m_dx9_end_scene_mutex); std::shared_lock lock(mgr.m_dx9_end_scene_mutex);
cb = mgr.m_dx9_end_scene_cb; cb = mgr.m_dx9_end_scene_cb;
} }
if (cb) if (cb)
cb(p_device); (*cb)(p_device);
return mgr.m_dx9_end_scene_hook.call<HRESULT>(p_device); return mgr.m_dx9_end_scene_hook.call<HRESULT>(p_device);
} }
HRESULT __stdcall HooksManager::dx11_present_detour(IDXGISwapChain* p_swap_chain, UINT sync_interval, UINT flags) HRESULT __stdcall HooksManager::dx11_present_detour(IDXGISwapChain* p_swap_chain, UINT sync_interval, UINT flags)
{ {
auto& mgr = get(); auto& mgr = get();
present_callback cb; callback_ptr<present_callback> cb;
{ {
std::shared_lock lock(mgr.m_present_mutex); std::shared_lock lock(mgr.m_present_mutex);
cb = mgr.m_present_cb; cb = mgr.m_present_cb;
} }
if (cb) if (cb)
cb(p_swap_chain, sync_interval, flags); (*cb)(p_swap_chain, sync_interval, flags);
return mgr.m_dx11_present_hook.call<HRESULT>(p_swap_chain, sync_interval, flags); return mgr.m_dx11_present_hook.call<HRESULT>(p_swap_chain, sync_interval, flags);
} }
@@ -553,13 +556,13 @@ namespace omath::hooks
UINT swap_chain_flags) UINT swap_chain_flags)
{ {
auto& mgr = get(); auto& mgr = get();
resize_buffers_callback cb; callback_ptr<resize_buffers_callback> cb;
{ {
std::shared_lock lock(mgr.m_resize_buffers_mutex); std::shared_lock lock(mgr.m_resize_buffers_mutex);
cb = mgr.m_resize_buffers_cb; cb = mgr.m_resize_buffers_cb;
} }
if (cb) if (cb)
cb(p_swap_chain, buffer_count, width, height, new_format, swap_chain_flags); (*cb)(p_swap_chain, buffer_count, width, height, new_format, swap_chain_flags);
return mgr.m_dx11_resize_buffers_hook.call<HRESULT>(p_swap_chain, buffer_count, width, height, new_format, return mgr.m_dx11_resize_buffers_hook.call<HRESULT>(p_swap_chain, buffer_count, width, height, new_format,
swap_chain_flags); swap_chain_flags);
} }
@@ -567,13 +570,13 @@ namespace omath::hooks
HRESULT __stdcall HooksManager::dx12_present_detour(IDXGISwapChain* p_swap_chain, UINT sync_interval, UINT flags) HRESULT __stdcall HooksManager::dx12_present_detour(IDXGISwapChain* p_swap_chain, UINT sync_interval, UINT flags)
{ {
auto& mgr = get(); auto& mgr = get();
present_callback cb; callback_ptr<present_callback> cb;
{ {
std::shared_lock lock(mgr.m_present_mutex); std::shared_lock lock(mgr.m_present_mutex);
cb = mgr.m_present_cb; cb = mgr.m_present_cb;
} }
if (cb) if (cb)
cb(p_swap_chain, sync_interval, flags); (*cb)(p_swap_chain, sync_interval, flags);
return mgr.m_dx12_present_hook.call<HRESULT>(p_swap_chain, sync_interval, flags); return mgr.m_dx12_present_hook.call<HRESULT>(p_swap_chain, sync_interval, flags);
} }
@@ -582,13 +585,13 @@ namespace omath::hooks
UINT swap_chain_flags) UINT swap_chain_flags)
{ {
auto& mgr = get(); auto& mgr = get();
resize_buffers_callback cb; callback_ptr<resize_buffers_callback> cb;
{ {
std::shared_lock lock(mgr.m_resize_buffers_mutex); std::shared_lock lock(mgr.m_resize_buffers_mutex);
cb = mgr.m_resize_buffers_cb; cb = mgr.m_resize_buffers_cb;
} }
if (cb) if (cb)
cb(p_swap_chain, buffer_count, width, height, new_format, swap_chain_flags); (*cb)(p_swap_chain, buffer_count, width, height, new_format, swap_chain_flags);
return mgr.m_dx12_resize_buffers_hook.call<HRESULT>(p_swap_chain, buffer_count, width, height, new_format, return mgr.m_dx12_resize_buffers_hook.call<HRESULT>(p_swap_chain, buffer_count, width, height, new_format,
swap_chain_flags); swap_chain_flags);
} }
@@ -598,13 +601,13 @@ namespace omath::hooks
ID3D12CommandList* const* pp_command_lists) ID3D12CommandList* const* pp_command_lists)
{ {
auto& mgr = get(); auto& mgr = get();
execute_command_lists_callback cb; callback_ptr<execute_command_lists_callback> cb;
{ {
std::shared_lock lock(mgr.m_execute_command_lists_mutex); std::shared_lock lock(mgr.m_execute_command_lists_mutex);
cb = mgr.m_execute_command_lists_cb; cb = mgr.m_execute_command_lists_cb;
} }
if (cb) if (cb)
cb(p_command_queue, num_command_lists, pp_command_lists); (*cb)(p_command_queue, num_command_lists, pp_command_lists);
mgr.m_dx12_execute_command_lists_hook.call<void>(p_command_queue, num_command_lists, pp_command_lists); mgr.m_dx12_execute_command_lists_hook.call<void>(p_command_queue, num_command_lists, pp_command_lists);
} }
@@ -616,13 +619,13 @@ namespace omath::hooks
{ {
g_is_inside_opengl_swap_buffers = true; g_is_inside_opengl_swap_buffers = true;
opengl_swap_buffers_callback cb; callback_ptr<opengl_swap_buffers_callback> cb;
{ {
std::shared_lock lock(mgr.m_opengl_swap_buffers_mutex); std::shared_lock lock(mgr.m_opengl_swap_buffers_mutex);
cb = mgr.m_opengl_swap_buffers_cb; cb = mgr.m_opengl_swap_buffers_cb;
} }
if (cb) if (cb)
cb(hdc); (*cb)(hdc);
const BOOL result = mgr.m_opengl_wgl_swap_buffers_hook.call<BOOL>(hdc); const BOOL result = mgr.m_opengl_wgl_swap_buffers_hook.call<BOOL>(hdc);
g_is_inside_opengl_swap_buffers = false; g_is_inside_opengl_swap_buffers = false;
@@ -640,13 +643,13 @@ namespace omath::hooks
{ {
g_is_inside_opengl_swap_buffers = true; g_is_inside_opengl_swap_buffers = true;
opengl_swap_buffers_callback cb; callback_ptr<opengl_swap_buffers_callback> cb;
{ {
std::shared_lock lock(mgr.m_opengl_swap_buffers_mutex); std::shared_lock lock(mgr.m_opengl_swap_buffers_mutex);
cb = mgr.m_opengl_swap_buffers_cb; cb = mgr.m_opengl_swap_buffers_cb;
} }
if (cb) if (cb)
cb(hdc); (*cb)(hdc);
const BOOL result = mgr.m_opengl_swap_buffers_hook.call<BOOL>(hdc); const BOOL result = mgr.m_opengl_swap_buffers_hook.call<BOOL>(hdc);
g_is_inside_opengl_swap_buffers = false; g_is_inside_opengl_swap_buffers = false;
@@ -659,7 +662,7 @@ namespace omath::hooks
LRESULT __stdcall HooksManager::wnd_proc_detour(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) LRESULT __stdcall HooksManager::wnd_proc_detour(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
{ {
auto& mgr = get(); auto& mgr = get();
wnd_proc_callback cb; callback_ptr<wnd_proc_callback> cb;
WNDPROC original; WNDPROC original;
{ {
std::shared_lock lock(mgr.m_wnd_proc_mutex); std::shared_lock lock(mgr.m_wnd_proc_mutex);
@@ -668,7 +671,7 @@ namespace omath::hooks
} }
if (cb) if (cb)
{ {
if (const auto result = cb(hwnd, msg, w_param, l_param)) if (const auto result = (*cb)(hwnd, msg, w_param, l_param))
return *result; return *result;
} }
return CallWindowProc(original, hwnd, msg, w_param, l_param); return CallWindowProc(original, hwnd, msg, w_param, l_param);