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 12
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 ReShadeUnregisterEvent(reshade::addon_event ev, void *callback);
39 
40 RESHADE_API_LIBRARY_DECL void ReShadeRegisterOverlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime));
41 RESHADE_API_LIBRARY_DECL void ReShadeUnregisterOverlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime));
42 
43 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);
44 RESHADE_API_LIBRARY_DECL void ReShadeDestroyEffectRuntime(reshade::api::effect_runtime *runtime);
45 RESHADE_API_LIBRARY_DECL void ReShadeUpdateAndPresentEffectRuntime(reshade::api::effect_runtime *runtime);
46 
47 #else
48 
49 // Use the kernel32 variant of module enumeration functions so it can be safely called from 'DllMain'
50 extern "C" BOOL WINAPI K32EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
51 
52 namespace reshade { namespace internal
53 {
57  inline HMODULE get_reshade_module_handle(HMODULE reshade_module = nullptr)
58  {
59  static HMODULE handle = reshade_module;
60  if (handle == nullptr)
61  {
62  HMODULE modules[1024]; DWORD num = 0;
63  if (K32EnumProcessModules(GetCurrentProcess(), modules, sizeof(modules), &num))
64  {
65  if (num > sizeof(modules))
66  num = sizeof(modules);
67 
68  for (DWORD i = 0; i < num / sizeof(HMODULE); ++i)
69  {
70  if (GetProcAddress(modules[i], "ReShadeRegisterAddon") &&
71  GetProcAddress(modules[i], "ReShadeUnregisterAddon"))
72  {
73  handle = modules[i];
74  break;
75  }
76  }
77  }
78  }
79  return handle;
80  }
81 
85  inline HMODULE get_current_module_handle(HMODULE addon_module = nullptr)
86  {
87  static HMODULE handle = addon_module;
88  return handle;
89  }
90 } }
91 
92 #endif
93 
94 namespace reshade
95 {
99  enum class log_level
100  {
104  error = 1,
108  warning = 2,
112  info = 3,
116  debug = 4
117  };
118 
124  inline void log_message(log_level level, const char *message)
125  {
126 #if defined(RESHADE_API_LIBRARY)
127  ReShadeLogMessage(nullptr, static_cast<int>(level), message);
128 #else
129  static const auto func = reinterpret_cast<void(*)(HMODULE, int, const char *)>(
130  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeLogMessage"));
131  func(internal::get_current_module_handle(), static_cast<int>(level), message);
132 #endif
133  }
134 
140  inline void get_reshade_base_path(char *path, size_t *path_size)
141  {
142 #if defined(RESHADE_API_LIBRARY)
143  ReShadeGetBasePath(path, path_size);
144 #else
145  static const auto func = reinterpret_cast<bool(*)(char *, size_t *)>(
146  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeGetBasePath"));
147  func(path, path_size);
148 #endif
149  }
150 
161  inline bool get_config_value(api::effect_runtime *runtime, const char *section, const char *key, char *value, size_t *value_size)
162  {
163 #if defined(RESHADE_API_LIBRARY)
164  return ReShadeGetConfigValue(nullptr, runtime, section, key, value, value_size);
165 #else
166  static const auto func = reinterpret_cast<bool(*)(HMODULE, api::effect_runtime *, const char *, const char *, char *, size_t *)>(
167  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeGetConfigValue"));
168  return func(internal::get_current_module_handle(), runtime, section, key, value, value_size);
169 #endif
170  }
171 #if _HAS_CXX17
172  template <typename T>
173  inline bool get_config_value(api::effect_runtime *runtime, const char *section, const char *key, T &value)
174  {
175  char value_string[32]; size_t value_length = sizeof(value_string) - 1;
176  if (!get_config_value(runtime, section, key, value_string, &value_length))
177  return false;
178  return std::from_chars(value_string, value_string + value_length, value).ec == std::errc {};
179  }
180  template <>
181  inline bool get_config_value<bool>(api::effect_runtime *runtime, const char *section, const char *key, bool &value)
182  {
183  int value_int = 0;
184  if (!get_config_value<int>(runtime, section, key, value_int))
185  return false;
186  value = (value_int != 0);
187  return true;
188  }
189 #endif
190 
199  inline void set_config_value(api::effect_runtime *runtime, const char *section, const char *key, const char *value)
200  {
201 #if defined(RESHADE_API_LIBRARY)
202  ReShadeSetConfigValue(nullptr, runtime, section, key, value);
203 #else
204  static const auto func = reinterpret_cast<void(*)(HMODULE, api::effect_runtime *, const char *, const char *, const char *)>(
205  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeSetConfigValue"));
206  func(internal::get_current_module_handle(), runtime, section, key, value);
207 #endif
208  }
209 #if _HAS_CXX17
210  template <typename T>
211  inline void set_config_value(api::effect_runtime *runtime, const char *section, const char *key, const T &value)
212  {
213  char value_string[32] = "";
214  std::to_chars(value_string, value_string + sizeof(value_string) - 1, value);
215  set_config_value(runtime, section, key, static_cast<const char *>(value_string));
216  }
217  template <>
218  inline void set_config_value<bool>(api::effect_runtime *runtime, const char *section, const char *key, const bool &value)
219  {
220  set_config_value<int>(runtime, section, key, value ? 1 : 0);
221  }
222 #endif
223  inline void set_config_value(api::effect_runtime *runtime, const char *section, const char *key, const char *value, size_t value_size)
224  {
225 #if defined(RESHADE_API_LIBRARY)
226  ReShadeSetConfigArray(nullptr, runtime, section, key, value, value_size);
227 #else
228  static const auto func = reinterpret_cast<void(*)(HMODULE, api::effect_runtime *, const char *, const char *, const char *, size_t)>(
229  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeSetConfigArray"));
230  func(internal::get_current_module_handle(), runtime, section, key, value, value_size);
231 #endif
232  }
233 
240  inline bool register_addon(HMODULE addon_module, [[maybe_unused]] HMODULE reshade_module = nullptr)
241  {
242 #if defined(RESHADE_API_LIBRARY)
243  return ReShadeRegisterAddon(addon_module, RESHADE_API_VERSION);
244 #else
245  addon_module = internal::get_current_module_handle(addon_module);
246  reshade_module = internal::get_reshade_module_handle(reshade_module);
247 
248  if (reshade_module == nullptr)
249  return false;
250 
251  const auto func = reinterpret_cast<bool(*)(HMODULE, uint32_t)>(
252  GetProcAddress(reshade_module, "ReShadeRegisterAddon"));
253  // Check that the ReShade module supports the used API
254  if (func == nullptr || !func(addon_module, RESHADE_API_VERSION))
255  return false;
256 
257 #if defined(IMGUI_VERSION_NUM)
258  const auto imgui_func = reinterpret_cast<const imgui_function_table *(*)(uint32_t)>(
259  GetProcAddress(reshade_module, "ReShadeGetImGuiFunctionTable"));
260  // Check that the ReShade module was built with Dear ImGui support and supports the used version
261  if (imgui_func == nullptr || !(imgui_function_table_instance() = imgui_func(IMGUI_VERSION_NUM)))
262  return false;
263 #endif
264 
265  return true;
266 #endif
267  }
274  inline void unregister_addon(HMODULE addon_module, [[maybe_unused]] HMODULE reshade_module = nullptr)
275  {
276 #if defined(RESHADE_API_LIBRARY)
277  ReShadeUnregisterAddon(addon_module);
278 #else
279  addon_module = internal::get_current_module_handle(addon_module);
280  reshade_module = internal::get_reshade_module_handle(reshade_module);
281 
282  if (reshade_module == nullptr)
283  return;
284 
285  const auto func = reinterpret_cast<bool(*)(HMODULE)>(
286  GetProcAddress(reshade_module, "ReShadeUnregisterAddon"));
287  if (func != nullptr)
288  func(addon_module);
289 #endif
290  }
291 
298  template <addon_event ev>
299  inline void register_event(typename addon_event_traits<ev>::decl callback)
300  {
301 #if defined(RESHADE_API_LIBRARY)
302  ReShadeRegisterEvent(ev, static_cast<void *>(callback));
303 #else
304  static const auto func = reinterpret_cast<void(*)(addon_event, void *)>(
305  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeRegisterEvent"));
306  if (func != nullptr)
307  func(ev, static_cast<void *>(callback));
308 #endif
309  }
315  template <addon_event ev>
316  inline void unregister_event(typename addon_event_traits<ev>::decl callback)
317  {
318 #if defined(RESHADE_API_LIBRARY)
319  ReShadeUnregisterEvent(ev, static_cast<void *>(callback));
320 #else
321  static const auto func = reinterpret_cast<void(*)(addon_event, void *)>(
322  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUnregisterEvent"));
323  if (func != nullptr)
324  func(ev, static_cast<void *>(callback));
325 #endif
326  }
327 
334  inline void register_overlay(const char *title, void(*callback)(api::effect_runtime *runtime))
335  {
336 #if defined(RESHADE_API_LIBRARY)
337  ReShadeRegisterOverlay(title, callback);
338 #else
339  static const auto func = reinterpret_cast<void(*)(const char *, void(*)(api::effect_runtime *))>(
340  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeRegisterOverlay"));
341  if (func != nullptr)
342  func(title, callback);
343 #endif
344  }
350  inline void unregister_overlay(const char *title, void(*callback)(api::effect_runtime *runtime))
351  {
352 #if defined(RESHADE_API_LIBRARY)
353  ReShadeUnregisterOverlay(title, callback);
354 #else
355  static const auto func = reinterpret_cast<void(*)(const char *, void(*)(api::effect_runtime *))>(
356  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUnregisterOverlay"));
357  if (func != nullptr)
358  func(title, callback);
359 #endif
360  }
361 
372  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)
373  {
374 #if defined(RESHADE_API_LIBRARY)
375  return ReShadeCreateEffectRuntime(api, device, command_queue, swapchain, config_path, out_runtime);
376 #else
377  static const auto func = reinterpret_cast<bool(*)(reshade::api::device_api, void *, void *, void *, const char *, reshade::api::effect_runtime **)>(
378  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeCreateEffectRuntime"));
379  if (func == nullptr)
380  {
381  *out_runtime = nullptr;
382  return false;
383  }
384  return func(api, device, command_queue, swapchain, config_path, out_runtime);
385 #endif
386  }
392  {
393 #if defined(RESHADE_API_LIBRARY)
394  ReShadeDestroyEffectRuntime(runtime);
395 #else
396  static const auto func = reinterpret_cast<void(*)(reshade::api::effect_runtime *)>(
397  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeDestroyEffectRuntime"));
398  if (func != nullptr)
399  func(runtime);
400 #endif
401  }
407  {
408 #if defined(RESHADE_API_LIBRARY)
409  ReShadeUpdateAndPresentEffectRuntime(runtime);
410 #else
411  static const auto func = reinterpret_cast<void(*)(reshade::api::effect_runtime *)>(
412  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUpdateAndPresentEffectRuntime"));
413  if (func != nullptr)
414  func(runtime);
415 #endif
416  }
417 }
device_api
The underlying render API a device is using, as returned by device::get_api.
Definition: reshade_api_device.hpp:16
HMODULE get_reshade_module_handle(HMODULE reshade_module=nullptr)
Gets the handle to the ReShade module.
Definition: reshade.hpp:57
HMODULE get_current_module_handle(HMODULE addon_module=nullptr)
Gets the handle to the current add-on module.
Definition: reshade.hpp:85
Definition: reshade.hpp:52
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:316
void register_event(typename addon_event_traits< ev >::decl callback)
Registers a callback for the specified event with ReShade.
Definition: reshade.hpp:299
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:161
void get_reshade_base_path(char *path, size_t *path_size)
Gets the base path ReShade uses to resolve relative paths.
Definition: reshade.hpp:140
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:372
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:274
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:406
log_level
Available log severity levels.
Definition: reshade.hpp:100
@ warning
| [WARN] | ...
@ debug
| [DEBUG] | ...
@ info
| [INFO] | ...
@ error
| [ERROR] | ...
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:199
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:240
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:350
void log_message(log_level level, const char *message)
Writes a message to ReShade's log.
Definition: reshade.hpp:124
void destroy_effect_runtime(api::effect_runtime *runtime)
Instantly destroys an effect runtime that was previously created via create_effect_runtime....
Definition: reshade.hpp:391
void register_overlay(const char *title, void(*callback)(api::effect_runtime *runtime))
Registers an overlay with ReShade.
Definition: reshade.hpp:334
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