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