ReShade
A generic post-processing injector for games and video software.
reshade.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2021 Patrick Mours
3  * SPDX-License-Identifier: BSD-3-Clause OR MIT
4  */
5 
6 #pragma once
7 
8 #include "reshade_events.hpp"
9 #include "reshade_overlay.hpp"
10 #include <charconv>
11 
12 // Current version of the ReShade API
13 #define RESHADE_API_VERSION 20
14 
15 // Optionally import ReShade API functions when 'RESHADE_API_LIBRARY' is defined instead of using header-only mode
16 #if defined(RESHADE_API_LIBRARY) || defined(RESHADE_API_LIBRARY_EXPORT)
17 
18 #if defined(RESHADE_API_LIBRARY_EXPORT)
19  #define RESHADE_API_LIBRARY 1
20  #define RESHADE_API_LIBRARY_DECL extern "C" __declspec(dllexport)
21 #else
22  #define RESHADE_API_LIBRARY_DECL extern "C" __declspec(dllimport)
23 #endif
24 
25 RESHADE_API_LIBRARY_DECL void ReShadeLogMessage(void *module, int level, const char *message);
26 
27 RESHADE_API_LIBRARY_DECL void ReShadeGetBasePath(char *path, size_t *path_size);
28 
29 RESHADE_API_LIBRARY_DECL bool ReShadeGetConfigValue(void *module, reshade::api::effect_runtime *runtime, const char *section, const char *key, char *value, size_t *value_size);
30 RESHADE_API_LIBRARY_DECL void ReShadeSetConfigValue(void *module, reshade::api::effect_runtime *runtime, const char *section, const char *key, const char *value);
31 RESHADE_API_LIBRARY_DECL void ReShadeSetConfigArray(void *module, reshade::api::effect_runtime *runtime, const char *section, const char *key, const char *value, size_t value_size);
32 
33 RESHADE_API_LIBRARY_DECL bool ReShadeRegisterAddon(void *module, uint32_t api_version);
34 RESHADE_API_LIBRARY_DECL void ReShadeUnregisterAddon(void *module);
35 
36 RESHADE_API_LIBRARY_DECL void ReShadeRegisterEvent(reshade::addon_event ev, void *callback);
37 RESHADE_API_LIBRARY_DECL void ReShadeRegisterEventForAddon(void *module, reshade::addon_event ev, void *callback);
38 RESHADE_API_LIBRARY_DECL void ReShadeUnregisterEvent(reshade::addon_event ev, void *callback);
39 RESHADE_API_LIBRARY_DECL void ReShadeUnregisterEventForAddon(void *module, reshade::addon_event ev, void *callback);
40 
41 RESHADE_API_LIBRARY_DECL void ReShadeRegisterOverlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime));
42 RESHADE_API_LIBRARY_DECL void ReShadeRegisterOverlayForAddon(void *module, const char *title, void(*callback)(reshade::api::effect_runtime *runtime));
43 RESHADE_API_LIBRARY_DECL void ReShadeUnregisterOverlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime));
44 RESHADE_API_LIBRARY_DECL void ReShadeUnregisterOverlayForAddon(void *module, const char *title, void(*callback)(reshade::api::effect_runtime *runtime));
45 
46 RESHADE_API_LIBRARY_DECL bool ReShadeCreateEffectRuntime(reshade::api::device_api api, void *opaque_device, void *opaque_command_queue, void *opaque_swapchain, const char *config_path, reshade::api::effect_runtime **out_runtime);
47 RESHADE_API_LIBRARY_DECL void ReShadeDestroyEffectRuntime(reshade::api::effect_runtime *runtime);
48 RESHADE_API_LIBRARY_DECL void ReShadeUpdateAndPresentEffectRuntime(reshade::api::effect_runtime *runtime);
49 
50 #else
51 
52 #include <Windows.h>
53 
54 // Use the kernel32 variant of module enumeration functions so it can be safely called from 'DllMain'
55 extern "C" BOOL WINAPI K32EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
56 
57 namespace reshade::internal
58 {
62  inline HMODULE get_reshade_module_handle(HMODULE initial_handle = nullptr)
63  {
64  static HMODULE handle = initial_handle;
65  if (handle == nullptr)
66  {
67  HMODULE modules[1024]; DWORD num = 0;
68  if (K32EnumProcessModules(GetCurrentProcess(), modules, sizeof(modules), &num))
69  {
70  if (num > sizeof(modules))
71  num = sizeof(modules);
72 
73  for (DWORD i = 0; i < num / sizeof(HMODULE); ++i)
74  {
75  if (GetProcAddress(modules[i], "ReShadeRegisterAddon") &&
76  GetProcAddress(modules[i], "ReShadeUnregisterAddon"))
77  {
78  handle = modules[i];
79  break;
80  }
81  }
82  }
83  }
84  return handle;
85  }
86 
90  inline HMODULE get_current_module_handle(HMODULE initial_handle = nullptr)
91  {
92  static HMODULE handle = initial_handle;
93  return handle;
94  }
95 }
96 
97 #endif
98 
99 namespace reshade
100 {
101 #if !defined(RESHADE_API_LIBRARY_EXPORT) || defined(BUILTIN_ADDON)
102  namespace log
103  {
107  enum class level
108  {
112  error = 1,
116  warning = 2,
120  info = 3,
124  debug = 4,
125  };
126 
132  inline void message(level level, const char *message)
133  {
134 #if defined(RESHADE_API_LIBRARY)
135  ReShadeLogMessage(nullptr, static_cast<int>(level), message);
136 #else
137  static const auto func = reinterpret_cast<void(*)(void *, int, const char *)>(
138  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeLogMessage"));
139  func(internal::get_current_module_handle(), static_cast<int>(level), message);
140 #endif
141  }
142  }
143 #endif
144 
150  inline void get_reshade_base_path(char *path, size_t *path_size)
151  {
152 #if defined(RESHADE_API_LIBRARY)
153  ReShadeGetBasePath(path, path_size);
154 #else
155  static const auto func = reinterpret_cast<bool(*)(char *, size_t *)>(
156  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeGetBasePath"));
157  func(path, path_size);
158 #endif
159  }
160 
171  inline bool get_config_value(api::effect_runtime *runtime, const char *section, const char *key, char *value, size_t *value_size)
172  {
173 #if defined(RESHADE_API_LIBRARY)
174  return ReShadeGetConfigValue(nullptr, runtime, section, key, value, value_size);
175 #else
176  static const auto func = reinterpret_cast<bool(*)(void *, api::effect_runtime *, const char *, const char *, char *, size_t *)>(
177  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeGetConfigValue"));
178  return func(internal::get_current_module_handle(), runtime, section, key, value, value_size);
179 #endif
180  }
181 #if _HAS_CXX17 || __cplusplus >= 201703L
182  template <typename T>
183  inline bool get_config_value(api::effect_runtime *runtime, const char *section, const char *key, T &value)
184  {
185  char value_string[32]; size_t value_length = sizeof(value_string) - 1;
186  if (!get_config_value(runtime, section, key, value_string, &value_length))
187  return false;
188  return std::from_chars(value_string, value_string + value_length, value).ec == std::errc {};
189  }
190  template <>
191  inline bool get_config_value<bool>(api::effect_runtime *runtime, const char *section, const char *key, bool &value)
192  {
193  int value_int = 0;
194  if (!get_config_value<int>(runtime, section, key, value_int))
195  return false;
196  value = (value_int != 0);
197  return true;
198  }
199 #endif
200 
209  inline void set_config_value(api::effect_runtime *runtime, const char *section, const char *key, const char *value)
210  {
211 #if defined(RESHADE_API_LIBRARY)
212  ReShadeSetConfigValue(nullptr, runtime, section, key, value);
213 #else
214  static const auto func = reinterpret_cast<void(*)(void *, api::effect_runtime *, const char *, const char *, const char *)>(
215  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeSetConfigValue"));
216  func(internal::get_current_module_handle(), runtime, section, key, value);
217 #endif
218  }
219 #if _HAS_CXX17 || __cplusplus >= 201703L
220  template <typename T>
221  inline void set_config_value(api::effect_runtime *runtime, const char *section, const char *key, const T &value)
222  {
223  char value_string[32] = "";
224  std::to_chars(value_string, value_string + sizeof(value_string) - 1, value);
225  set_config_value(runtime, section, key, static_cast<const char *>(value_string));
226  }
227  template <>
228  inline void set_config_value<bool>(api::effect_runtime *runtime, const char *section, const char *key, const bool &value)
229  {
230  set_config_value<int>(runtime, section, key, value ? 1 : 0);
231  }
232 #endif
233  inline void set_config_value(api::effect_runtime *runtime, const char *section, const char *key, const char *value, size_t value_size)
234  {
235 #if defined(RESHADE_API_LIBRARY)
236  ReShadeSetConfigArray(nullptr, runtime, section, key, value, value_size);
237 #else
238  static const auto func = reinterpret_cast<void(*)(void *, api::effect_runtime *, const char *, const char *, const char *, size_t)>(
239  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeSetConfigArray"));
240  func(internal::get_current_module_handle(), runtime, section, key, value, value_size);
241 #endif
242  }
243 
250  inline bool register_addon(void *addon_module, [[maybe_unused]] void *reshade_module = nullptr)
251  {
252 #if defined(RESHADE_API_LIBRARY)
253  return ReShadeRegisterAddon(addon_module, RESHADE_API_VERSION);
254 #else
255  addon_module = internal::get_current_module_handle(static_cast<HMODULE>(addon_module));
256  reshade_module = internal::get_reshade_module_handle(static_cast<HMODULE>(reshade_module));
257 
258  if (reshade_module == nullptr)
259  return false;
260 
261  const auto func = reinterpret_cast<bool(*)(void *, uint32_t)>(
262  GetProcAddress(static_cast<HMODULE>(reshade_module), "ReShadeRegisterAddon"));
263  // Check that the ReShade module supports the used API
264  if (func == nullptr || !func(addon_module, RESHADE_API_VERSION))
265  return false;
266 
267 #if defined(IMGUI_VERSION_NUM)
268  const auto imgui_func = reinterpret_cast<const imgui_function_table *(*)(uint32_t)>(
269  GetProcAddress(static_cast<HMODULE>(reshade_module), "ReShadeGetImGuiFunctionTable"));
270  // Check that the ReShade module was built with Dear ImGui support and supports the used version
271  if (imgui_func == nullptr || !(imgui_function_table_instance() = imgui_func(IMGUI_VERSION_NUM)))
272  return false;
273 #endif
274 
275  return true;
276 #endif
277  }
284  inline void unregister_addon(void *addon_module, [[maybe_unused]] void *reshade_module = nullptr)
285  {
286 #if defined(RESHADE_API_LIBRARY)
287  ReShadeUnregisterAddon(addon_module);
288 #else
289  addon_module = internal::get_current_module_handle(static_cast<HMODULE>(addon_module));
290  reshade_module = internal::get_reshade_module_handle(static_cast<HMODULE>(reshade_module));
291 
292  if (reshade_module == nullptr)
293  return;
294 
295  const auto func = reinterpret_cast<bool(*)(void *)>(
296  GetProcAddress(static_cast<HMODULE>(reshade_module), "ReShadeUnregisterAddon"));
297  if (func != nullptr)
298  func(addon_module);
299 #endif
300  }
301 
308  template <addon_event ev>
309  inline void register_event(typename addon_event_traits<ev>::decl callback)
310  {
311 #if defined(RESHADE_API_LIBRARY)
312  ReShadeRegisterEvent(ev, reinterpret_cast<void *>(callback));
313 #else
314  static const auto func = reinterpret_cast<void(*)(addon_event, void *)>(
315  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeRegisterEvent"));
316  if (func != nullptr)
317  func(ev, reinterpret_cast<void *>(callback));
318 #endif
319  }
325  template <addon_event ev>
326  inline void unregister_event(typename addon_event_traits<ev>::decl callback)
327  {
328 #if defined(RESHADE_API_LIBRARY)
329  ReShadeUnregisterEvent(ev, reinterpret_cast<void *>(callback));
330 #else
331  static const auto func = reinterpret_cast<void(*)(addon_event, void *)>(
332  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUnregisterEvent"));
333  if (func != nullptr)
334  func(ev, reinterpret_cast<void *>(callback));
335 #endif
336  }
337 
344  inline void register_overlay(const char *title, void(*callback)(api::effect_runtime *runtime))
345  {
346 #if defined(RESHADE_API_LIBRARY)
347  ReShadeRegisterOverlay(title, callback);
348 #else
349  static const auto func = reinterpret_cast<void(*)(const char *, void(*)(api::effect_runtime *))>(
350  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeRegisterOverlay"));
351  if (func != nullptr)
352  func(title, callback);
353 #endif
354  }
360  inline void unregister_overlay(const char *title, void(*callback)(api::effect_runtime *runtime))
361  {
362 #if defined(RESHADE_API_LIBRARY)
363  ReShadeUnregisterOverlay(title, callback);
364 #else
365  static const auto func = reinterpret_cast<void(*)(const char *, void(*)(api::effect_runtime *))>(
366  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUnregisterOverlay"));
367  if (func != nullptr)
368  func(title, callback);
369 #endif
370  }
371 
382  inline bool create_effect_runtime(reshade::api::device_api api, void *device, void *command_queue, void *swapchain, const char *config_path, reshade::api::effect_runtime **out_runtime)
383  {
384 #if defined(RESHADE_API_LIBRARY)
385  return ReShadeCreateEffectRuntime(api, device, command_queue, swapchain, config_path, out_runtime);
386 #else
387  static const auto func = reinterpret_cast<bool(*)(reshade::api::device_api, void *, void *, void *, const char *, reshade::api::effect_runtime **)>(
388  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeCreateEffectRuntime"));
389  if (func == nullptr)
390  {
391  *out_runtime = nullptr;
392  return false;
393  }
394  return func(api, device, command_queue, swapchain, config_path, out_runtime);
395 #endif
396  }
402  {
403 #if defined(RESHADE_API_LIBRARY)
404  ReShadeDestroyEffectRuntime(runtime);
405 #else
406  static const auto func = reinterpret_cast<void(*)(reshade::api::effect_runtime *)>(
407  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeDestroyEffectRuntime"));
408  if (func != nullptr)
409  func(runtime);
410 #endif
411  }
417  {
418 #if defined(RESHADE_API_LIBRARY)
419  ReShadeUpdateAndPresentEffectRuntime(runtime);
420 #else
421  static const auto func = reinterpret_cast<void(*)(reshade::api::effect_runtime *)>(
422  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUpdateAndPresentEffectRuntime"));
423  if (func != nullptr)
424  func(runtime);
425 #endif
426  }
427 }
device_api
Underlying graphics API a device is using.
Definition: reshade_api_device.hpp:17
level
Severity levels for logging.
Definition: reshade.hpp:108
@ warning
| WARN | ...
@ debug
| DEBUG | ...
@ info
| INFO | ...
@ error
| ERROR | ...
void message(level level, const char *message)
Writes a message to ReShade's log.
Definition: reshade.hpp:132
Definition: reshade.hpp:58
void unregister_event(typename addon_event_traits< ev >::decl callback)
Unregisters a callback from the specified event that was previously registered via register_event.
Definition: reshade.hpp:326
void register_event(typename addon_event_traits< ev >::decl callback)
Registers a callback for the specified event with ReShade.
Definition: reshade.hpp:309
addon_event
Definition: reshade_events.hpp:13
void unregister_addon(void *addon_module, [[maybe_unused]] void *reshade_module=nullptr)
Unregisters this module as an add-on. Call this in 'AddonUninit' or 'DllMain' during process detach,...
Definition: reshade.hpp:284
bool get_config_value(api::effect_runtime *runtime, const char *section, const char *key, char *value, size_t *value_size)
Gets a value from one of ReShade's config files. This can use either the global config file (ReShade....
Definition: reshade.hpp:171
void get_reshade_base_path(char *path, size_t *path_size)
Gets the base path ReShade uses to resolve relative paths.
Definition: reshade.hpp:150
bool create_effect_runtime(reshade::api::device_api api, void *device, void *command_queue, void *swapchain, const char *config_path, reshade::api::effect_runtime **out_runtime)
Creates a new effect runtime for an existing swap chain, for when it was not already hooked by ReShad...
Definition: reshade.hpp:382
void update_and_present_effect_runtime(api::effect_runtime *runtime)
Updates and renders an effect runtime onto the current back buffer of the swap chain it was created w...
Definition: reshade.hpp:416
void set_config_value(api::effect_runtime *runtime, const char *section, const char *key, const char *value)
Sets and saves a value in one of ReShade's config files. This can use either the global config file (...
Definition: reshade.hpp:209
bool register_addon(void *addon_module, [[maybe_unused]] void *reshade_module=nullptr)
Registers this module as an add-on with ReShade. Call this in 'AddonInit' or 'DllMain' during process...
Definition: reshade.hpp:250
void unregister_overlay(const char *title, void(*callback)(api::effect_runtime *runtime))
Unregisters an overlay that was previously registered via register_overlay.
Definition: reshade.hpp:360
void destroy_effect_runtime(api::effect_runtime *runtime)
Instantly destroys an effect runtime that was previously created via create_effect_runtime....
Definition: reshade.hpp:401
void register_overlay(const char *title, void(*callback)(api::effect_runtime *runtime))
Registers an overlay with ReShade.
Definition: reshade.hpp:344
BOOL WINAPI K32EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded)
#define RESHADE_API_VERSION
Definition: reshade.hpp:13
A post-processing effect runtime, used to control effects.
Definition: reshade_api.hpp:51