2025-07-16 18:26:28 +02:00
/*
* Copyright ( C ) 2021 Patrick Mours
* SPDX - License - Identifier : BSD - 3 - Clause OR MIT
*/
# pragma once
# include "reshade_events.hpp"
# include "reshade_overlay.hpp"
# include <charconv>
// Current version of the ReShade API
2025-12-31 14:27:34 +01:00
# define RESHADE_API_VERSION 18
2025-07-16 18:26:28 +02:00
// Optionally import ReShade API functions when 'RESHADE_API_LIBRARY' is defined instead of using header-only mode
# if defined(RESHADE_API_LIBRARY) || defined(RESHADE_API_LIBRARY_EXPORT)
# if defined(RESHADE_API_LIBRARY_EXPORT)
# define RESHADE_API_LIBRARY 1
# define RESHADE_API_LIBRARY_DECL extern "C" __declspec(dllexport)
# else
# define RESHADE_API_LIBRARY_DECL extern "C" __declspec(dllimport)
# endif
2025-12-31 14:27:34 +01:00
RESHADE_API_LIBRARY_DECL void ReShadeLogMessage ( void * module , int level , const char * message ) ;
2025-07-16 18:26:28 +02:00
RESHADE_API_LIBRARY_DECL void ReShadeGetBasePath ( char * path , size_t * path_size ) ;
2025-12-31 14:27:34 +01:00
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 ) ;
RESHADE_API_LIBRARY_DECL void ReShadeSetConfigValue ( void * module , reshade : : api : : effect_runtime * runtime , const char * section , const char * key , const char * value ) ;
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 ) ;
2025-07-16 18:26:28 +02:00
2025-12-31 14:27:34 +01:00
RESHADE_API_LIBRARY_DECL bool ReShadeRegisterAddon ( void * module , uint32_t api_version ) ;
RESHADE_API_LIBRARY_DECL void ReShadeUnregisterAddon ( void * module ) ;
2025-07-16 18:26:28 +02:00
RESHADE_API_LIBRARY_DECL void ReShadeRegisterEvent ( reshade : : addon_event ev , void * callback ) ;
2025-12-31 14:27:34 +01:00
RESHADE_API_LIBRARY_DECL void ReShadeRegisterEventForAddon ( void * module , reshade : : addon_event ev , void * callback ) ;
2025-07-16 18:26:28 +02:00
RESHADE_API_LIBRARY_DECL void ReShadeUnregisterEvent ( reshade : : addon_event ev , void * callback ) ;
2025-12-31 14:27:34 +01:00
RESHADE_API_LIBRARY_DECL void ReShadeUnregisterEventForAddon ( void * module , reshade : : addon_event ev , void * callback ) ;
2025-07-16 18:26:28 +02:00
RESHADE_API_LIBRARY_DECL void ReShadeRegisterOverlay ( const char * title , void ( * callback ) ( reshade : : api : : effect_runtime * runtime ) ) ;
2025-12-31 14:27:34 +01:00
RESHADE_API_LIBRARY_DECL void ReShadeRegisterOverlayForAddon ( void * module , const char * title , void ( * callback ) ( reshade : : api : : effect_runtime * runtime ) ) ;
2025-07-16 18:26:28 +02:00
RESHADE_API_LIBRARY_DECL void ReShadeUnregisterOverlay ( const char * title , void ( * callback ) ( reshade : : api : : effect_runtime * runtime ) ) ;
2025-12-31 14:27:34 +01:00
RESHADE_API_LIBRARY_DECL void ReShadeUnregisterOverlayForAddon ( void * module , const char * title , void ( * callback ) ( reshade : : api : : effect_runtime * runtime ) ) ;
2025-07-16 18:26:28 +02:00
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 ) ;
RESHADE_API_LIBRARY_DECL void ReShadeDestroyEffectRuntime ( reshade : : api : : effect_runtime * runtime ) ;
RESHADE_API_LIBRARY_DECL void ReShadeUpdateAndPresentEffectRuntime ( reshade : : api : : effect_runtime * runtime ) ;
# else
2025-12-31 14:27:34 +01:00
# include <Windows.h>
2025-07-16 18:26:28 +02:00
// Use the kernel32 variant of module enumeration functions so it can be safely called from 'DllMain'
extern " C " BOOL WINAPI K32EnumProcessModules ( HANDLE hProcess , HMODULE * lphModule , DWORD cb , LPDWORD lpcbNeeded ) ;
namespace reshade { namespace internal
{
/// <summary>
/// Gets the handle to the ReShade module.
/// </summary>
inline HMODULE get_reshade_module_handle ( HMODULE initial_handle = nullptr )
{
static HMODULE handle = initial_handle ;
if ( handle = = nullptr )
{
HMODULE modules [ 1024 ] ; DWORD num = 0 ;
if ( K32EnumProcessModules ( GetCurrentProcess ( ) , modules , sizeof ( modules ) , & num ) )
{
if ( num > sizeof ( modules ) )
num = sizeof ( modules ) ;
for ( DWORD i = 0 ; i < num / sizeof ( HMODULE ) ; + + i )
{
if ( GetProcAddress ( modules [ i ] , " ReShadeRegisterAddon " ) & &
GetProcAddress ( modules [ i ] , " ReShadeUnregisterAddon " ) )
{
handle = modules [ i ] ;
break ;
}
}
}
}
return handle ;
}
/// <summary>
/// Gets the handle to the current add-on module.
/// </summary>
inline HMODULE get_current_module_handle ( HMODULE initial_handle = nullptr )
{
static HMODULE handle = initial_handle ;
return handle ;
}
} }
# endif
namespace reshade
{
# if !defined(RESHADE_API_LIBRARY_EXPORT) || defined(BUILTIN_ADDON)
namespace log
{
/// <summary>
/// Severity levels for logging.
/// </summary>
enum class level
{
/// <summary>
/// | ERROR | ...
/// </summary>
error = 1 ,
/// <summary>
/// | WARN | ...
/// </summary>
warning = 2 ,
/// <summary>
/// | INFO | ...
/// </summary>
info = 3 ,
/// <summary>
/// | DEBUG | ...
/// </summary>
debug = 4 ,
} ;
/// <summary>
/// Writes a message to ReShade's log.
/// </summary>
/// <param name="level">Severity level.</param>
/// <param name="message">A null-terminated message string.</param>
inline void message ( level level , const char * message )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeLogMessage ( nullptr , static_cast < int > ( level ) , message ) ;
# else
2025-12-31 14:27:34 +01:00
static const auto func = reinterpret_cast < void ( * ) ( void * , int , const char * ) > (
2025-07-16 18:26:28 +02:00
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeLogMessage " ) ) ;
func ( internal : : get_current_module_handle ( ) , static_cast < int > ( level ) , message ) ;
# endif
}
}
# endif
/// <summary>
/// Gets the base path ReShade uses to resolve relative paths.
/// </summary>
/// <param name="path">Pointer to a string buffer that is filled with the base path, or <see langword="nullptr"/> to query the necessary size.</param>
/// <param name="path_size">Pointer to an integer that contains the size of the string buffer and is set to the actual length of the string, including the null-terminator.</param>
inline void get_reshade_base_path ( char * path , size_t * path_size )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeGetBasePath ( path , path_size ) ;
# else
static const auto func = reinterpret_cast < bool ( * ) ( char * , size_t * ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeGetBasePath " ) ) ;
func ( path , path_size ) ;
# endif
}
/// <summary>
/// Gets a value from one of ReShade's config files.
/// This can use either the global config file (ReShade.ini next to the application executable), or one local to an effect runtime (ReShade[index].ini in the base path).
/// </summary>
/// <param name="runtime">Optional effect runtime to use the config file from, or <see langword="nullptr"/> to use the global config file.</param>
/// <param name="section">Name of the config section.</param>
/// <param name="key">Name of the config value.</param>
/// <param name="value">Pointer to a string buffer that is filled with the config value, or <see langword="nullptr"/> to query the necessary size.</param>
/// <param name="value_size">Pointer to an integer that contains the size of the string buffer and is set to the actual length of the string, including the null-terminator.</param>
/// <returns><see langword="true"/> if the specified config value exists, <see cref="false"/> otherwise.</returns>
inline bool get_config_value ( api : : effect_runtime * runtime , const char * section , const char * key , char * value , size_t * value_size )
{
# if defined(RESHADE_API_LIBRARY)
return ReShadeGetConfigValue ( nullptr , runtime , section , key , value , value_size ) ;
# else
2025-12-31 14:27:34 +01:00
static const auto func = reinterpret_cast < bool ( * ) ( void * , api : : effect_runtime * , const char * , const char * , char * , size_t * ) > (
2025-07-16 18:26:28 +02:00
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeGetConfigValue " ) ) ;
return func ( internal : : get_current_module_handle ( ) , runtime , section , key , value , value_size ) ;
# endif
}
# if _HAS_CXX17 || __cplusplus >= 201703L
template < typename T >
inline bool get_config_value ( api : : effect_runtime * runtime , const char * section , const char * key , T & value )
{
char value_string [ 32 ] ; size_t value_length = sizeof ( value_string ) - 1 ;
if ( ! get_config_value ( runtime , section , key , value_string , & value_length ) )
return false ;
return std : : from_chars ( value_string , value_string + value_length , value ) . ec = = std : : errc { } ;
}
template < >
inline bool get_config_value < bool > ( api : : effect_runtime * runtime , const char * section , const char * key , bool & value )
{
int value_int = 0 ;
if ( ! get_config_value < int > ( runtime , section , key , value_int ) )
return false ;
value = ( value_int ! = 0 ) ;
return true ;
}
# endif
/// <summary>
/// Sets and saves a value in one of ReShade's config files.
/// This can use either the global config file (ReShade.ini next to the application executable), or one local to an effect runtime (ReShade[index].ini in the base path).
/// </summary>
/// <param name="runtime">Optional effect runtime to use the config file from, or <see langword="nullptr"/> to use the global config file.</param>
/// <param name="section">Name of the config section.</param>
/// <param name="key">Name of the config value.</param>
/// <param name="value">Config value to set.</param>
inline void set_config_value ( api : : effect_runtime * runtime , const char * section , const char * key , const char * value )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeSetConfigValue ( nullptr , runtime , section , key , value ) ;
# else
2025-12-31 14:27:34 +01:00
static const auto func = reinterpret_cast < void ( * ) ( void * , api : : effect_runtime * , const char * , const char * , const char * ) > (
2025-07-16 18:26:28 +02:00
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeSetConfigValue " ) ) ;
func ( internal : : get_current_module_handle ( ) , runtime , section , key , value ) ;
# endif
}
# if _HAS_CXX17 || __cplusplus >= 201703L
template < typename T >
inline void set_config_value ( api : : effect_runtime * runtime , const char * section , const char * key , const T & value )
{
char value_string [ 32 ] = " " ;
std : : to_chars ( value_string , value_string + sizeof ( value_string ) - 1 , value ) ;
set_config_value ( runtime , section , key , static_cast < const char * > ( value_string ) ) ;
}
template < >
inline void set_config_value < bool > ( api : : effect_runtime * runtime , const char * section , const char * key , const bool & value )
{
set_config_value < int > ( runtime , section , key , value ? 1 : 0 ) ;
}
# endif
inline void set_config_value ( api : : effect_runtime * runtime , const char * section , const char * key , const char * value , size_t value_size )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeSetConfigArray ( nullptr , runtime , section , key , value , value_size ) ;
# else
2025-12-31 14:27:34 +01:00
static const auto func = reinterpret_cast < void ( * ) ( void * , api : : effect_runtime * , const char * , const char * , const char * , size_t ) > (
2025-07-16 18:26:28 +02:00
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeSetConfigArray " ) ) ;
func ( internal : : get_current_module_handle ( ) , runtime , section , key , value , value_size ) ;
# endif
}
/// <summary>
/// Registers this module as an add-on with ReShade.
/// Call this in 'AddonInit' or 'DllMain' during process attach, before any of the other API functions!
/// </summary>
/// <param name="addon_module">Handle of the current module.</param>
/// <param name="reshade_module">Handle of the ReShade module in the process, or <see langword="nullptr"/> to find it automatically.</param>
2025-12-31 14:27:34 +01:00
inline bool register_addon ( void * addon_module , [[maybe_unused]] void * reshade_module = nullptr )
2025-07-16 18:26:28 +02:00
{
# if defined(RESHADE_API_LIBRARY)
return ReShadeRegisterAddon ( addon_module , RESHADE_API_VERSION ) ;
# else
2025-12-31 14:27:34 +01:00
addon_module = internal : : get_current_module_handle ( static_cast < HMODULE > ( addon_module ) ) ;
reshade_module = internal : : get_reshade_module_handle ( static_cast < HMODULE > ( reshade_module ) ) ;
2025-07-16 18:26:28 +02:00
if ( reshade_module = = nullptr )
return false ;
2025-12-31 14:27:34 +01:00
const auto func = reinterpret_cast < bool ( * ) ( void * , uint32_t ) > (
GetProcAddress ( static_cast < HMODULE > ( reshade_module ) , " ReShadeRegisterAddon " ) ) ;
2025-07-16 18:26:28 +02:00
// Check that the ReShade module supports the used API
if ( func = = nullptr | | ! func ( addon_module , RESHADE_API_VERSION ) )
return false ;
# if defined(IMGUI_VERSION_NUM)
const auto imgui_func = reinterpret_cast < const imgui_function_table * ( * ) ( uint32_t ) > (
2025-12-31 14:27:34 +01:00
GetProcAddress ( static_cast < HMODULE > ( reshade_module ) , " ReShadeGetImGuiFunctionTable " ) ) ;
2025-07-16 18:26:28 +02:00
// Check that the ReShade module was built with Dear ImGui support and supports the used version
if ( imgui_func = = nullptr | | ! ( imgui_function_table_instance ( ) = imgui_func ( IMGUI_VERSION_NUM ) ) )
return false ;
# endif
return true ;
# endif
}
/// <summary>
/// Unregisters this module as an add-on.
/// Call this in 'AddonUninit' or 'DllMain' during process detach, after any of the other API functions.
/// </summary>
/// <param name="addon_module">Handle of the current module.</param>
/// <param name="reshade_module">Handle of the ReShade module in the process, or <see langword="nullptr"/> to find it automatically.</param>
2025-12-31 14:27:34 +01:00
inline void unregister_addon ( void * addon_module , [[maybe_unused]] void * reshade_module = nullptr )
2025-07-16 18:26:28 +02:00
{
# if defined(RESHADE_API_LIBRARY)
ReShadeUnregisterAddon ( addon_module ) ;
# else
2025-12-31 14:27:34 +01:00
addon_module = internal : : get_current_module_handle ( static_cast < HMODULE > ( addon_module ) ) ;
reshade_module = internal : : get_reshade_module_handle ( static_cast < HMODULE > ( reshade_module ) ) ;
2025-07-16 18:26:28 +02:00
if ( reshade_module = = nullptr )
return ;
2025-12-31 14:27:34 +01:00
const auto func = reinterpret_cast < bool ( * ) ( void * ) > (
GetProcAddress ( static_cast < HMODULE > ( reshade_module ) , " ReShadeUnregisterAddon " ) ) ;
2025-07-16 18:26:28 +02:00
if ( func ! = nullptr )
func ( addon_module ) ;
# endif
}
/// <summary>
/// Registers a callback for the specified event with ReShade.
/// <para>The callback function is then called whenever the application performs a task associated with this event (see also the <see cref="addon_event"/> enumeration).</para>
/// </summary>
/// <param name="callback">Pointer to the callback function.</param>
/// <typeparam name="ev">Event to register the callback for.</typeparam>
template < addon_event ev >
inline void register_event ( typename addon_event_traits < ev > : : decl callback )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeRegisterEvent ( ev , static_cast < void * > ( callback ) ) ;
# else
static const auto func = reinterpret_cast < void ( * ) ( addon_event , void * ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeRegisterEvent " ) ) ;
if ( func ! = nullptr )
func ( ev , reinterpret_cast < void * > ( callback ) ) ;
# endif
}
/// <summary>
/// Unregisters a callback from the specified event that was previously registered via <see cref="register_event"/>.
/// </summary>
/// <param name="callback">Pointer to the callback function.</param>
/// <typeparam name="ev">Event to unregister the callback from.</typeparam>
template < addon_event ev >
inline void unregister_event ( typename addon_event_traits < ev > : : decl callback )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeUnregisterEvent ( ev , static_cast < void * > ( callback ) ) ;
# else
static const auto func = reinterpret_cast < void ( * ) ( addon_event , void * ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeUnregisterEvent " ) ) ;
if ( func ! = nullptr )
func ( ev , reinterpret_cast < void * > ( callback ) ) ;
# endif
}
/// <summary>
/// Registers an overlay with ReShade.
/// <para>The callback function is then called when the overlay is visible and allows adding Dear ImGui widgets for user interaction.</para>
/// </summary>
/// <param name="title">Null-terminated title string, or <see langword="nullptr"/> to register a settings overlay for this add-on.</param>
/// <param name="callback">Pointer to the callback function.</param>
inline void register_overlay ( const char * title , void ( * callback ) ( api : : effect_runtime * runtime ) )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeRegisterOverlay ( title , callback ) ;
# else
static const auto func = reinterpret_cast < void ( * ) ( const char * , void ( * ) ( api : : effect_runtime * ) ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeRegisterOverlay " ) ) ;
if ( func ! = nullptr )
func ( title , callback ) ;
# endif
}
/// <summary>
/// Unregisters an overlay that was previously registered via <see cref="register_overlay"/>.
/// </summary>
/// <param name="title">Null-terminated title string.</param>
/// <param name="callback">Pointer to the callback function.</param>
inline void unregister_overlay ( const char * title , void ( * callback ) ( api : : effect_runtime * runtime ) )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeUnregisterOverlay ( title , callback ) ;
# else
static const auto func = reinterpret_cast < void ( * ) ( const char * , void ( * ) ( api : : effect_runtime * ) ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeUnregisterOverlay " ) ) ;
if ( func ! = nullptr )
func ( title , callback ) ;
# endif
}
/// <summary>
/// Creates a new effect runtime for an existing swapchain, for when it was not already hooked by ReShade (e.g. because the RESHADE_DISABLE_GRAPHICS_HOOK environment variable is set).
/// </summary>
/// <param name="api">Underlying graphics API used.</param>
/// <param name="device">'IDirect3DDevice9', 'ID3D10Device', 'ID3D11Device', 'ID3D12Device', 'HGLRC' or 'VkDevice', depending on the graphics API.</param>
/// <param name="command_queue">'ID3D11DeviceContext', 'ID3D12CommandQueue', or 'VkQueue', depending on the graphics API.</param>
/// <param name="swapchain">'IDirect3DSwapChain9', 'IDXGISwapChain', 'HDC' or 'VkSwapchainKHR', depending on the graphics API.</param>
/// <param name="config_path">Path to the configuration file the effect runtime should use.</param>
/// <param name="out_runtime">Pointer to a variable that is set to the pointer of the created effect runtime.</param>
/// <returns><see langword="true"/> if the effect_runtime was successfully created, <see langword="false"/> otherwise (in this case <paramref name="out_runtime"/> is set to <see langword="nullptr"/>).</returns>
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 )
{
# if defined(RESHADE_API_LIBRARY)
return ReShadeCreateEffectRuntime ( api , device , command_queue , swapchain , config_path , out_runtime ) ;
# else
static const auto func = reinterpret_cast < bool ( * ) ( reshade : : api : : device_api , void * , void * , void * , const char * , reshade : : api : : effect_runtime * * ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeCreateEffectRuntime " ) ) ;
if ( func = = nullptr )
{
* out_runtime = nullptr ;
return false ;
}
return func ( api , device , command_queue , swapchain , config_path , out_runtime ) ;
# endif
}
/// <summary>
/// Instantly destroys an effect runtime that was previously created via <see cref="create_effect_runtime"/>.
/// Do not call this with effect runtimes that were automatically created by ReShade!
/// </summary>
inline void destroy_effect_runtime ( api : : effect_runtime * runtime )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeDestroyEffectRuntime ( runtime ) ;
# else
static const auto func = reinterpret_cast < void ( * ) ( reshade : : api : : effect_runtime * ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeDestroyEffectRuntime " ) ) ;
if ( func ! = nullptr )
func ( runtime ) ;
# endif
}
/// <summary>
/// Updates and renders an effect runtime onto the current back buffer of the swap chain it was created with.
/// Do not call this with effect runtimes that were automatically created by ReShade!
/// </summary>
inline void update_and_present_effect_runtime ( api : : effect_runtime * runtime )
{
# if defined(RESHADE_API_LIBRARY)
ReShadeUpdateAndPresentEffectRuntime ( runtime ) ;
# else
static const auto func = reinterpret_cast < void ( * ) ( reshade : : api : : effect_runtime * ) > (
GetProcAddress ( internal : : get_reshade_module_handle ( ) , " ReShadeUpdateAndPresentEffectRuntime " ) ) ;
if ( func ! = nullptr )
func ( runtime ) ;
# endif
}
}