diff --git a/CHANGELOG.txt b/CHANGELOG.txt index af70aa053..a674d3a83 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,19 +1,112 @@ -24.11.17.3 +24.11.25 +======== + + Disable the option to clear Flip Model backbuffers on present by default, + because it prevents OBS Game Capture in some (D3D11) scenarios. + +24.11.24.2 +========== + + Allow moving windows to different monitors by dragging without triggering + SK's monitor-change message (causes games to maximize the game window). + +24.11.24.1 +========== + + Fixed accidentally using ImGuiKey_MouseLeft to index the ImGuiIO::MouseDown + array (which only has 5 buttons; the value of ImGuiKey_MouseLeft is 653!) + * It should have been ImGuiIO::AddMouseButtonEvent (ImGuiKey_MouseLeft,...). + >> This relatively new bug only affected games w/ (Low-Level) Mouse Hooks... + + + Ignore mouse button capture when the mouse cursor is over a non-client part + of a game window (i.e. title bar or resize grips). + + Disengage the "confine cursor" option temporarily while a game window has + been grabbed and is inside of the "size/move" modal loop, so that the + window can actually be resized or repositioned without interference. + +24.11.24 +======== + + Unload plug-in DLLs at game exit _before_ uninstalling all hooked functions. + + Add plug-in DLL names to the unload log entires during game shutdown. + + Run each plug-in unload attempt within its own exception handler and + continue unloading remaining plug-ins if there is an exception. + +24.11.23.2 +========== + + Fixed the issue in 24.11.23.1 the correct way :) The staging copy of the + backbuffer needs to be enqueued, the reference to the backbuffer released, + and the command queue flushed immediately and then there are no chances + for the swapchain backbuffers to have outstanding references. + +24.11.23.1 +========== + + Fixed D3D11 screenshots occasionally causing display mode changes to fail if + a (Blt Model) game requested a mode change within 500-ms of the last screen + capture. + +24.11.23 +======== + + Cleaned-up Mouse Cursor section of Input Control Panel and removed the old + "Low-Level Mouse Settings" section. + + + Auto-Bluetooth Compatibility now only powers off PlayStation controllers + that have advanced Bluetooth mode active if SK has seen the game attempt + to poll input using WinMM or DirectInput 7/8 at least one time first. + + # Controllers start in "simple" Bluetooth mode when initially powered on, + which is a mode compatible with DirectInput and WinMM. + + >> Prior to this change, it could cause an endless loop of the controller + powering off, Steam Input re-initializing the controller in advanced + Bluetooth mode when powered back on, and then SK turning it back off! + + * It is a niche feature that is more likely to be accidentally enabled by + users not completely familiar with its purpose than the chances of + playing a game that requires it. + +24.11.22 +======== + + Update ReShade Add-on API headers to include new events in the next release. + + Reduce unnecessary WM_NCHITTEST messages sent to games when the cursor is not + even moving. + +24.11.21 +======== + + Enable Fake Fullscreen mode by default in STALKER 2, because it uses that + crap (in D3D12) for HDR... yay! + +24.11.20 +======== + + Fixed only a single monitor being listed in the Display menu. + + Added measures to prevent various ATLUS ports from moving the game window + back to the primary monitor whenever HDR is enabled/disabled or resolution + changes (they handle WM_DISPLAYCHANGE and WM_MOVE weirdly). + +24.11.19 +======== + + Restored support for using D3D11 Render Mod Tools in games with multiple + deferred contexts to debug shaders when ReShade is active. + +24.11.18 +======== + + Disable SteamAPI file hash checks on Fallout 4 + + Handle window activation more explicitly in Metaphor Re:Fantazio so that + its Keyboard Hook does not capture input events when the window is not + focused. + +24.11.16.3 ========== + Fixed various problems indicated by static analysis... -24.11.17.2 +24.11.16.2 ========== + Fixed problems with SK not re-initializing D3D11 when the active SwapChain is destroyed and re-created. + Fixed potential issues with loading ReShade as a plug-in and config files not correctly being passed to create_effect_runtime (...). -24.11.17.1 +24.11.16.1 ========== + Implement Lossy scRGB->HDR10 Quantization the correct way :) -24.11.17 +24.11.16 ======== + Added texture sampling fixes for Metaphor: ReFantazio so that it actually can make use of anisotropic filtering, instead of setting MaxAnisotropy diff --git a/SpecialK.vcxproj b/SpecialK.vcxproj index 5122e639c..183b9172e 100644 --- a/SpecialK.vcxproj +++ b/SpecialK.vcxproj @@ -1587,6 +1587,15 @@ if exist "$(TargetDir)$(TargetName).exp" ( del "$(TargetDir)$(TargetName).exp" ) + + + + + + + + + diff --git a/depends/include/ReShade/reshade.hpp b/depends/include/ReShade/reshade.hpp index 251a2a03d..bf0704320 100644 --- a/depends/include/ReShade/reshade.hpp +++ b/depends/include/ReShade/reshade.hpp @@ -5,6 +5,8 @@ #pragma once +#define RESHADE_NO_IMGUI + #include "reshade_events.hpp" #include "reshade_overlay.hpp" #include @@ -29,15 +31,20 @@ RESHADE_API_LIBRARY_DECL void ReShadeGetBasePath(char *path, size_t *path_size); 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); RESHADE_API_LIBRARY_DECL void ReShadeSetConfigValue(HMODULE module, reshade::api::effect_runtime *runtime, const char *section, const char *key, const char *value); +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); RESHADE_API_LIBRARY_DECL bool ReShadeRegisterAddon(HMODULE module, uint32_t api_version); RESHADE_API_LIBRARY_DECL void ReShadeUnregisterAddon(HMODULE module); RESHADE_API_LIBRARY_DECL void ReShadeRegisterEvent(reshade::addon_event ev, void *callback); +RESHADE_API_LIBRARY_DECL void ReShadeRegisterEventForAddon(HMODULE module, reshade::addon_event ev, void *callback); RESHADE_API_LIBRARY_DECL void ReShadeUnregisterEvent(reshade::addon_event ev, void *callback); +RESHADE_API_LIBRARY_DECL void ReShadeUnregisterEventForAddon(HMODULE module, reshade::addon_event ev, void *callback); RESHADE_API_LIBRARY_DECL void ReShadeRegisterOverlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime)); +RESHADE_API_LIBRARY_DECL void ReShadeRegisterOverlayForAddon(HMODULE module, const char *title, void(*callback)(reshade::api::effect_runtime *runtime)); RESHADE_API_LIBRARY_DECL void ReShadeUnregisterOverlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime)); +RESHADE_API_LIBRARY_DECL void ReShadeUnregisterOverlayForAddon(HMODULE module, const char *title, void(*callback)(reshade::api::effect_runtime *runtime)); 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); @@ -53,9 +60,9 @@ namespace reshade { namespace internal /// /// Gets the handle to the ReShade module. /// - inline HMODULE get_reshade_module_handle(HMODULE reshade_module = nullptr) + inline HMODULE get_reshade_module_handle(HMODULE initial_handle = nullptr) { - static HMODULE handle = reshade_module; + static HMODULE handle = initial_handle; if (handle == nullptr) { HMODULE modules[1024]; DWORD num = 0; @@ -81,13 +88,12 @@ namespace reshade { namespace internal /// /// Gets the handle to the current add-on module. /// - inline HMODULE get_current_module_handle(HMODULE addon_module = nullptr) + inline HMODULE get_current_module_handle(HMODULE initial_handle = nullptr) { - static HMODULE handle = addon_module; + static HMODULE handle = initial_handle; return handle; } - - inline BOOL has_addon(const wchar_t* name) + inline BOOL has_addon(const wchar_t* name) { if (name == nullptr) return FALSE; @@ -118,44 +124,49 @@ namespace reshade { namespace internal namespace reshade { - /// - /// Available log severity levels. - /// - enum class log_level +#if !defined(RESHADE_API_LIBRARY_EXPORT) || defined(BUILTIN_ADDON) + namespace log { /// - /// | [ERROR] | ... - /// - error = 1, - /// - /// | [WARN] | ... + /// Severity levels for logging. /// - warning = 2, - /// - /// | [INFO] | ... - /// - info = 3, + enum class level + { + /// + /// | ERROR | ... + /// + error = 1, + /// + /// | WARN | ... + /// + warning = 2, + /// + /// | INFO | ... + /// + info = 3, + /// + /// | DEBUG | ... + /// + debug = 4, + }; + /// - /// | [DEBUG] | ... + /// Writes a message to ReShade's log. /// - debug = 4 - }; - - /// - /// Writes a message to ReShade's log. - /// - /// Severity level. - /// A null-terminated message string. - inline void log_message(log_level level, const char *message) - { + /// Severity level. + /// A null-terminated message string. + inline void message(level level, const char *message) + { #if defined(RESHADE_API_LIBRARY) - ReShadeLogMessage(nullptr, static_cast(level), message); + ReShadeLogMessage(nullptr, static_cast(level), message); #else - static const auto func = reinterpret_cast( - GetProcAddress(internal::get_reshade_module_handle(), "ReShadeLogMessage")); - func(internal::get_current_module_handle(), static_cast(level), message); + static const auto func = reinterpret_cast( + GetProcAddress(internal::get_reshade_module_handle(), "ReShadeLogMessage")); + func(internal::get_current_module_handle(), static_cast(level), message); #endif + } } +#endif /// /// Gets the base path ReShade uses to resolve relative paths. @@ -245,6 +256,16 @@ namespace reshade set_config_value(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 + static const auto func = reinterpret_cast( + GetProcAddress(internal::get_reshade_module_handle(), "ReShadeSetConfigArray")); + func(internal::get_current_module_handle(), runtime, section, key, value, value_size); +#endif + } /// /// Registers this module as an add-on with ReShade. @@ -268,14 +289,13 @@ namespace reshade // Check that the ReShade module supports the used API if (func == nullptr || !func(addon_module, RESHADE_API_VERSION)) return false; -#if 0 -#if defined(IMGUI_VERSION_NUM) + +#if defined(IMGUI_VERSION_NUM) && !defined(RESHADE_NO_IMGUI) const auto imgui_func = reinterpret_cast( GetProcAddress(reshade_module, "ReShadeGetImGuiFunctionTable")); // 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 #endif return true; diff --git a/depends/include/ReShade/reshade_api.hpp b/depends/include/ReShade/reshade_api.hpp index 7d3c7ece1..e1616005f 100644 --- a/depends/include/ReShade/reshade_api.hpp +++ b/depends/include/ReShade/reshade_api.hpp @@ -31,6 +31,8 @@ namespace reshade { namespace api /// RESHADE_DEFINE_HANDLE(effect_uniform_variable); + struct display; + /// /// Input source for events triggered by user input. /// @@ -65,6 +67,10 @@ namespace reshade { namespace api /// virtual uint32_t get_back_buffer_count() const = 0; + /// + /// Gets the current back buffer resource. + /// + resource get_current_back_buffer() { return get_back_buffer(get_current_back_buffer_index()); } /// /// Gets the index of the back buffer resource that can currently be rendered into. /// @@ -91,10 +97,10 @@ namespace reshade { namespace api virtual void render_effects(command_list *cmd_list, resource_view rtv, resource_view rtv_srgb) = 0; /// - /// Captures a screenshot of the current back buffer resource and returns its image data in 32 bits-per-pixel RGBA format. + /// Captures a screenshot of the current back buffer resource and returns its image data. /// - /// Pointer to an array of width * height * 4 bytes the image data is written to. - virtual bool capture_screenshot(uint8_t *pixels) = 0; + /// Pointer to an array of width * height * bpp bytes the image data is written to (where bpp is the number of bytes per pixel of the back buffer format). + virtual bool capture_screenshot(void *pixels) = 0; /// /// Gets the current buffer dimensions of the swap chain. @@ -159,7 +165,7 @@ namespace reshade { namespace api /// File name of the effect file to enumerate uniform variables from, or to enumerate those of all loaded effects. /// Function to call for every uniform variable. template - inline void enumerate_uniform_variables(const char *effect_name, F lambda) + void enumerate_uniform_variables(const char *effect_name, F lambda) { enumerate_uniform_variables(effect_name, [](effect_runtime *runtime, effect_uniform_variable variable, void *user_data) { static_cast(user_data)->operator()(runtime, variable); }, &lambda); } @@ -193,7 +199,7 @@ namespace reshade { namespace api /// 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. virtual void get_uniform_variable_name(effect_uniform_variable variable, char *name, size_t *name_size) const = 0; template - inline void get_uniform_variable_name(effect_uniform_variable variable, char(&name)[SIZE]) const + void get_uniform_variable_name(effect_uniform_variable variable, char(&name)[SIZE]) const { size_t name_size = SIZE; get_uniform_variable_name(variable, name, &name_size); @@ -249,7 +255,7 @@ namespace reshade { namespace api /// if the annotation exists on the uniform variable, otherwise. virtual bool get_annotation_string_from_uniform_variable(effect_uniform_variable variable, const char *name, char *value, size_t *value_size) const = 0; template - inline bool get_annotation_string_from_uniform_variable(effect_uniform_variable variable, const char *name, char(&value)[SIZE]) const + bool get_annotation_string_from_uniform_variable(effect_uniform_variable variable, const char *name, char(&value)[SIZE]) const { size_t value_size = SIZE; return get_annotation_string_from_uniform_variable(variable, name, value, &value_size); @@ -308,7 +314,7 @@ namespace reshade { namespace api /// Optional value of the second component in the vector that is used to update this uniform variable. /// Optional value of the third component in the vector that is used to update this uniform variable. /// Optional value of the fourth component in the vector that is used to update this uniform variable. - inline void set_uniform_value_bool(effect_uniform_variable variable, bool x, bool y = bool(0), bool z = bool(0), bool w = bool(0)) + void set_uniform_value_bool(effect_uniform_variable variable, bool x, bool y = bool(0), bool z = bool(0), bool w = bool(0)) { const bool values[4] = { x, y, z, w }; set_uniform_value_bool(variable, values, 4); @@ -333,7 +339,7 @@ namespace reshade { namespace api /// Optional value of the second component in the vector that is used to update this uniform variable. /// Optional value of the third component in the vector that is used to update this uniform variable. /// Optional value of the fourth component in the vector that is used to update this uniform variable. - inline void set_uniform_value_float(effect_uniform_variable variable, float x, float y = float(0), float z = float(0), float w = float(0)) + void set_uniform_value_float(effect_uniform_variable variable, float x, float y = float(0), float z = float(0), float w = float(0)) { const float values[4] = { x, y, z, w }; set_uniform_value_float(variable, values, 4); @@ -358,7 +364,7 @@ namespace reshade { namespace api /// Optional value of the second component in the vector that is used to update this uniform variable. /// Optional value of the third component in the vector that is used to update this uniform variable. /// Optional value of the fourth component in the vector that is used to update this uniform variable. - inline void set_uniform_value_int(effect_uniform_variable variable, int32_t x, int32_t y = int32_t(0), int32_t z = int32_t(0), int32_t w = int32_t(0)) + void set_uniform_value_int(effect_uniform_variable variable, int32_t x, int32_t y = int32_t(0), int32_t z = int32_t(0), int32_t w = int32_t(0)) { const int32_t values[4] = { x, y, z, w }; set_uniform_value_int(variable, values, 4); @@ -383,7 +389,7 @@ namespace reshade { namespace api /// Optional value of the second component in the vector that is used to update this uniform variable. /// Optional value of the third component in the vector that is used to update this uniform variable. /// Optional value of the fourth component in the vector that is used to update this uniform variable. - inline void set_uniform_value_uint(effect_uniform_variable variable, uint32_t x, uint32_t y = uint32_t(0), uint32_t z = uint32_t(0), uint32_t w = uint32_t(0)) + void set_uniform_value_uint(effect_uniform_variable variable, uint32_t x, uint32_t y = uint32_t(0), uint32_t z = uint32_t(0), uint32_t w = uint32_t(0)) { const uint32_t values[4] = { x, y, z, w }; set_uniform_value_uint(variable, values, 4); @@ -402,7 +408,7 @@ namespace reshade { namespace api /// File name of the effect file to enumerate texture variables from, or to enumerate those of all loaded effects. /// Function to call for every texture variable. template - inline void enumerate_texture_variables(const char *effect_name, F lambda) + void enumerate_texture_variables(const char *effect_name, F lambda) { enumerate_texture_variables(effect_name, [](effect_runtime *runtime, effect_texture_variable variable, void *user_data) { static_cast(user_data)->operator()(runtime, variable); }, &lambda); } @@ -423,7 +429,7 @@ namespace reshade { namespace api /// 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. virtual void get_texture_variable_name(effect_texture_variable variable, char *name, size_t *name_size) const = 0; template - inline void get_texture_variable_name(effect_texture_variable variable, char(&name)[SIZE]) const + void get_texture_variable_name(effect_texture_variable variable, char(&name)[SIZE]) const { size_t name_size = SIZE; get_texture_variable_name(variable, name, &name_size); @@ -479,20 +485,20 @@ namespace reshade { namespace api /// if the annotation exists on the texture variable, otherwise. virtual bool get_annotation_string_from_texture_variable(effect_texture_variable variable, const char *name, char *value, size_t *value_size) const = 0; template - inline bool get_annotation_string_from_texture_variable(effect_texture_variable variable, const char *name, char(&value)[SIZE]) const + bool get_annotation_string_from_texture_variable(effect_texture_variable variable, const char *name, char(&value)[SIZE]) const { size_t value_size = SIZE; return get_annotation_string_from_texture_variable(variable, name, value, &value_size); } /// - /// Uploads 32 bits-per-pixel RGBA image data to the specified texture . + /// Uploads image data to the specified texture . /// /// Opaque handle to the texture variable. /// Width of the image data. /// Height of the image data. - /// Pointer to an array of width * height * 4 bytes the image data is read from. - virtual void update_texture(effect_texture_variable variable, const uint32_t width, const uint32_t height, const uint8_t *pixels) = 0; + /// Pointer to an array of width * height * bpp bytes the image data is read from (where bpp is the number of bytes per pixel of the texture format). + virtual void update_texture(effect_texture_variable variable, const uint32_t width, const uint32_t height, const void *pixels) = 0; /// /// Gets the shader resource view that is bound to the specified texture . @@ -526,7 +532,7 @@ namespace reshade { namespace api /// File name of the effect file to enumerate techniques from, or to enumerate those of all loaded effects. /// Function to call for every technique. template - inline void enumerate_techniques(const char *effect_name, F lambda) + void enumerate_techniques(const char *effect_name, F lambda) { enumerate_techniques(effect_name, [](effect_runtime *runtime, effect_technique technique, void *user_data) { static_cast(user_data)->operator()(runtime, technique); }, &lambda); } @@ -547,7 +553,7 @@ namespace reshade { namespace api /// 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. virtual void get_technique_name(effect_technique technique, char *name, size_t *name_size) const = 0; template - inline void get_technique_name(effect_technique technique, char(&name)[SIZE]) const + void get_technique_name(effect_technique technique, char(&name)[SIZE]) const { size_t name_size = SIZE; get_technique_name(technique, name, &name_size); @@ -603,7 +609,7 @@ namespace reshade { namespace api /// if the annotation exists on the technique, otherwise. virtual bool get_annotation_string_from_technique(effect_technique technique, const char *name, char *value, size_t *value_size) const = 0; template - inline bool get_annotation_string_from_technique(effect_technique technique, const char *name, char(&value)[SIZE]) const + bool get_annotation_string_from_technique(effect_technique technique, const char *name, char(&value)[SIZE]) const { size_t value_size = SIZE; return get_annotation_string_from_technique(technique, name, value, &value_size); @@ -631,7 +637,7 @@ namespace reshade { namespace api /// if the preprocessor definition is defined, otherwise. virtual bool get_preprocessor_definition(const char *name, char *value, size_t *value_size) const = 0; template - inline bool get_preprocessor_definition(const char *name, char(&value)[SIZE]) const + bool get_preprocessor_definition(const char *name, char(&value)[SIZE]) const { size_t value_size = SIZE; return get_preprocessor_definition(name, value, &value_size); @@ -674,7 +680,7 @@ namespace reshade { namespace api /// 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. virtual void get_current_preset_path(char *path, size_t *path_size) const = 0; template - inline void get_current_preset_path(char(&path)[SIZE]) const + void get_current_preset_path(char(&path)[SIZE]) const { size_t path_size = SIZE; get_current_preset_path(path, &path_size); @@ -715,7 +721,7 @@ namespace reshade { namespace api /// 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. virtual void get_uniform_variable_effect_name(effect_uniform_variable variable, char *effect_name, size_t *effect_name_size) const = 0; template - inline void get_uniform_variable_effect_name(effect_uniform_variable variable, char(&effect_name)[SIZE]) const + void get_uniform_variable_effect_name(effect_uniform_variable variable, char(&effect_name)[SIZE]) const { size_t effect_name_size = SIZE; get_uniform_variable_effect_name(variable, effect_name, &effect_name_size); @@ -729,7 +735,7 @@ namespace reshade { namespace api /// 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. virtual void get_texture_variable_effect_name(effect_texture_variable variable, char *effect_name, size_t *effect_name_size) const = 0; template - inline void get_texture_variable_effect_name(effect_texture_variable variable, char(&effect_name)[SIZE]) const + void get_texture_variable_effect_name(effect_texture_variable variable, char(&effect_name)[SIZE]) const { size_t effect_name_size = SIZE; get_texture_variable_effect_name(variable, effect_name, &effect_name_size); @@ -743,7 +749,7 @@ namespace reshade { namespace api /// 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. virtual void get_technique_effect_name(effect_technique technique, char *effect_name, size_t *effect_name_size) const = 0; template - inline void get_technique_effect_name(effect_technique technique, char(&effect_name)[SIZE]) const + void get_technique_effect_name(effect_technique technique, char(&effect_name)[SIZE]) const { size_t effect_name_size = SIZE; get_technique_effect_name(technique, effect_name, &effect_name_size); @@ -764,7 +770,7 @@ namespace reshade { namespace api /// if the preprocessor definition is defined, otherwise. virtual bool get_preprocessor_definition_for_effect(const char *effect_name, const char *name, char *value, size_t *value_size) const = 0; template - inline bool get_preprocessor_definition_for_effect(const char *effect_name, const char *name, char(&value)[SIZE]) const + bool get_preprocessor_definition_for_effect(const char *effect_name, const char *name, char(&value)[SIZE]) const { size_t value_size = SIZE; return get_preprocessor_definition_for_effect(effect_name, name, value, &value_size); @@ -789,5 +795,23 @@ namespace reshade { namespace api /// Overrides the color space used for presentation. /// virtual void set_color_space(color_space color_space) = 0; + + /// + /// Resets the value of the specified uniform . + /// + /// Opaque handle to the uniform variable. + virtual void reset_uniform_value(effect_uniform_variable variable) = 0; + + /// + /// Queues up the specified effect for reloading in the next frame. + /// This can be called multiple times with different effects to append to the queue. + /// + /// File name of the effect file that should be reloaded. + virtual void reload_effect_next_frame(const char *effect_name) = 0; + + /// + /// Gets the active display, which may change between frames or return nullptr if the swapchain does not have a unique output device. + /// + virtual display* get_active_display() const = 0; }; } } diff --git a/depends/include/ReShade/reshade_api_device.hpp b/depends/include/ReShade/reshade_api_device.hpp index 87e39b9d0..3deed5332 100644 --- a/depends/include/ReShade/reshade_api_device.hpp +++ b/depends/include/ReShade/reshade_api_device.hpp @@ -10,8 +10,9 @@ namespace reshade { namespace api { /// - /// The underlying render API a device is using, as returned by . + /// Underlying graphics API a device is using. /// + /// enum class device_api { /// Direct3D 9 @@ -35,8 +36,9 @@ namespace reshade { namespace api }; /// - /// The available features a device may support. + /// Optional capabilities a device may support, depending on the underlying graphics API and hardware. /// + /// enum class device_caps { /// @@ -56,7 +58,7 @@ namespace reshade { namespace api hull_and_domain_shader, /// /// Specifies whether logic operations are available in the blend state. - /// If this feature is not present, the and fields are ignored. + /// If this feature is not present, and are ignored. /// logic_op, /// @@ -76,7 +78,7 @@ namespace reshade { namespace api fill_mode_non_solid, /// /// Specifies whether conservative rasterization is supported. - /// If this feature is not present, the field must be 0. + /// If this feature is not present, must be 0. /// conservative_rasterization, /// @@ -136,7 +138,7 @@ namespace reshade { namespace api copy_query_heap_results, /// /// Specifies whether comparison sampling is supported. - /// If this feature is not present, the field is ignored and the compare filter types have no effect. + /// If this feature is not present, is ignored and the compare filter types have no effect. /// sampler_compare, /// @@ -174,17 +176,64 @@ namespace reshade { namespace api /// If this feature is not present, must not be used. /// shared_fence_nt_handle, + /// + /// Specifies whether amplification and mesh shaders are supported. + /// If this feature is not present, the and stages and must not be used. + /// + amplification_and_mesh_shader, + /// + /// Specifies whether ray tracing is supported. + /// If this feature is not present, , , and must not be used. + /// + ray_tracing, }; /// - /// Describes an adapter/physical device. + /// Properties that may be queried from a device. /// - struct device_properties + /// + enum class device_properties { - unsigned int api_version = 0; - unsigned int driver_version = 0; - unsigned int vendor_id = 0, device_id = 0; - char description[256] = ""; + /// + /// Version of the underlying graphics API the device is using. + /// Data is a 32-bit unsigned integer value. + /// + api_version = 1, + /// + /// Version of the graphics driver that is being used. + /// Data is a 32-bit unsigned integer value. + /// + driver_version, + /// + /// PCI vendor ID of the hardware associated with the logical render device. + /// Data is a 32-bit unsigned integer value. + /// + vendor_id, + /// + /// PCI device ID of the hardware associated with the logical render device. + /// Data is a 32-bit unsigned integer value. + /// + device_id, + /// + /// Description text of the hardware associated with the logical render device. + /// Data is an array of 256 byte-sized characters representing a null-terminated string. + /// + description, + /// + /// Size of a handle as written by . + /// Data is a 32-bit unsigned integer value. + /// + shader_group_handle_size, + /// + /// Required alignment of the base handle in the buffers passed to . + /// Data is a 32-bit unsigned integer value. + /// + shader_group_alignment, + /// + /// Required alignment of each handle in the buffers passed to . + /// Data is a 32-bit unsigned integer value. + /// + shader_group_handle_alignment, }; /// @@ -219,7 +268,8 @@ namespace reshade { namespace api /// /// Gets a reference to user-defined data from the object that was previously allocated via . /// - template inline T &get_private_data() const + template + T &get_private_data() const { uint64_t res; get_private_data(reinterpret_cast(&__uuidof(T)), &res); @@ -228,16 +278,18 @@ namespace reshade { namespace api /// /// Allocates user-defined data and stores it in the object. /// - template inline T &create_private_data(Args... args) + template + T &create_private_data(Args &&... args) { - uint64_t res = reinterpret_cast(new T(std::forward(args)...)); + uint64_t res = reinterpret_cast(new T(static_cast(args)...)); set_private_data(reinterpret_cast(&__uuidof(T)), res); return *reinterpret_cast(static_cast(res)); } /// /// Frees user-defined data that was previously allocated via . /// - template inline void destroy_private_data() + template + void destroy_private_data() { uint64_t res; get_private_data(reinterpret_cast(&__uuidof(T)), &res); @@ -273,29 +325,29 @@ namespace reshade { namespace api /// Creates a new sampler state object. /// /// Description of the sampler to create. - /// Pointer to a variable that is set to the handle of the created sampler. - /// if the sampler was successfully created, otherwise (in this case is set to zero). - virtual bool create_sampler(const sampler_desc &desc, sampler *out_handle) = 0; + /// Pointer to a variable that is set to the handle of the created sampler. + /// if the sampler was successfully created, otherwise (in this case is set to zero). + virtual bool create_sampler(const sampler_desc &desc, sampler *out_sampler) = 0; /// /// Instantly destroys a sampler that was previously created via . /// - virtual void destroy_sampler(sampler handle) = 0; + virtual void destroy_sampler(sampler sampler) = 0; /// /// Allocates and creates a new resource. /// /// Description of the resource to create. /// Optional data to upload to the resource after creation. This should point to an array of , one for each subresource (mipmap levels and array layers). Can be to indicate no initial data to upload. - /// Initial state of the resource after creation. This can later be changed via . - /// Pointer to a variable that is set to the handle of the created resource. + /// Initial state of the resource after creation. This can later be changed via . It should also be part of the flags of the description. + /// Pointer to a variable that is set to the handle of the created resource. /// Optional pointer to a variable of type HANDLE used when contains . When that variable is a , it is set to the exported shared handle of the created resource. When that variable is a valid handle, the resource is imported from that shared handle. - /// if the resource was successfully created, otherwise (in this case is set to zero). - virtual bool create_resource(const resource_desc &desc, const subresource_data *initial_data, resource_usage initial_state, resource *out_handle, void **shared_handle = nullptr) = 0; + /// if the resource was successfully created, otherwise (in this case is set to zero). + virtual bool create_resource(const resource_desc &desc, const subresource_data *initial_data, resource_usage initial_state, resource *out_resource, void **shared_handle = nullptr) = 0; /// /// Instantly destroys a resource that was previously created via and frees its memory. - /// Make sure the resource is no longer in use on the GPU (via any command list that may reference it and is still being executed) before doing this and never try to destroy resources created by the application! + /// Make sure the resource is no longer in use on the GPU (via any command list that may reference it and is still being executed) before doing this (e.g. with ) and never try to destroy resources created by the application! /// - virtual void destroy_resource(resource handle) = 0; + virtual void destroy_resource(resource resource) = 0; /// /// Gets the description of the specified resource. @@ -308,13 +360,13 @@ namespace reshade { namespace api /// Resource to create the view to. /// Usage type of the resource view to create. Set to to create a shader resource view, for a depth-stencil view, for a render target etc. /// Description of the resource view to create. - /// Pointer to a variable that is set to the handle of the created resource view. - /// if the resource view was successfully created, otherwise (in this case is set to zero). - virtual bool create_resource_view(resource resource, resource_usage usage_type, const resource_view_desc &desc, resource_view *out_handle) = 0; + /// Pointer to a variable that is set to the handle of the created resource view. + /// if the resource view was successfully created, otherwise (in this case is set to zero). + virtual bool create_resource_view(resource resource, resource_usage usage_type, const resource_view_desc &desc, resource_view *out_view) = 0; /// /// Instantly destroys a resource view that was previously created via . /// - virtual void destroy_resource_view(resource_view handle) = 0; + virtual void destroy_resource_view(resource_view view) = 0; /// /// Gets the handle to the underlying resource the specified resource was created for. @@ -382,53 +434,53 @@ namespace reshade { namespace api /// /// Pipeline layout to use. /// Number of sub-objects. - /// Pointer to an array of sub-objects that describe this pipeline. - /// Pointer to a variable that is set to the handle of the created pipeline state object. - /// if the pipeline state object was successfully created, otherwise (in this case is set to zero). - virtual bool create_pipeline(pipeline_layout layout, uint32_t subobject_count, const pipeline_subobject *subobjects, pipeline *out_handle) = 0; + /// Pointer to the first element of an array of sub-objects that describe this pipeline. + /// Pointer to a variable that is set to the handle of the created pipeline state object. + /// if the pipeline state object was successfully created, otherwise (in this case is set to zero). + virtual bool create_pipeline(pipeline_layout layout, uint32_t subobject_count, const pipeline_subobject *subobjects, pipeline *out_pipeline) = 0; /// /// Instantly destroys a pipeline state object that was previously created via . /// - virtual void destroy_pipeline(pipeline handle) = 0; + virtual void destroy_pipeline(pipeline pipeline) = 0; /// /// Creates a new pipeline layout. /// /// Number of layout parameters. - /// Pointer to an array of layout parameters that describe this pipeline layout. - /// Pointer to a variable that is set to the handle of the created pipeline layout. - /// if the pipeline layout was successfully created, otherwise (in this case is set to zero). - virtual bool create_pipeline_layout(uint32_t param_count, const pipeline_layout_param *params, pipeline_layout *out_handle) = 0; + /// Pointer to the first element of an array of layout parameters that describe this pipeline layout. + /// Pointer to a variable that is set to the handle of the created pipeline layout. + /// if the pipeline layout was successfully created, otherwise (in this case is set to zero). + virtual bool create_pipeline_layout(uint32_t param_count, const pipeline_layout_param *params, pipeline_layout *out_layout) = 0; /// /// Instantly destroys a pipeline layout that was previously created via . /// - virtual void destroy_pipeline_layout(pipeline_layout handle) = 0; + virtual void destroy_pipeline_layout(pipeline_layout layout) = 0; /// - /// Allocates a descriptor table from an internal heap. + /// Allocates a descriptor table from an internal descriptor heap. /// /// Pipeline layout that contains a parameter that describes the descriptor table. /// Index of the pipeline layout parameter that describes the descriptor table. - /// Pointer to a a variable that is set to the handles of the created descriptor table. - /// if the descriptor table was successfully allocated, otherwise (in this case is set to zeroe). - inline bool allocate_descriptor_table(pipeline_layout layout, uint32_t param, descriptor_table *out_handle) { return allocate_descriptor_tables(1, layout, param, out_handle); } + /// Pointer to a a variable that is set to the handles of the created descriptor table. + /// if the descriptor table was successfully allocated, otherwise (in this case is set to zeroe). + bool allocate_descriptor_table(pipeline_layout layout, uint32_t param, descriptor_table *out_table) { return allocate_descriptor_tables(1, layout, param, out_table); } /// - /// Allocates one or more descriptor tables from an internal heap. + /// Allocates one or more descriptor tables from an internal descriptor heap. /// /// Number of descriptor tables to allocate. - /// Pipeline layout that contains a parameter that describes the descriptor table. - /// Index of the pipeline layout parameter that describes the descriptor table. - /// Pointer to an array of handles with at least elements that is filled with the handles of the created descriptor tables. - /// if the descriptor tables were successfully allocated, otherwise (in this case is filled with zeroes). - virtual bool allocate_descriptor_tables(uint32_t count, pipeline_layout layout, uint32_t param, descriptor_table *out_handles) = 0; + /// Pipeline layout that contains a parameter that describes the descriptor tables. + /// Index of the pipeline layout parameter that describes the descriptor tables. + /// Pointer to the first element of an array of handles with at least elements that is filled with the handles of the created descriptor tables. + /// if the descriptor tables were successfully allocated, otherwise (in this case is filled with zeroes). + virtual bool allocate_descriptor_tables(uint32_t count, pipeline_layout layout, uint32_t param, descriptor_table *out_tables) = 0; /// - /// Frees a descriptor table that was previously allocated via . + /// Frees a descriptor table that was previously allocated via . /// - inline void free_descriptor_table(descriptor_table handle) { free_descriptor_tables(1, &handle); } + void free_descriptor_table(descriptor_table table) { free_descriptor_tables(1, &table); } /// - /// Frees one or more descriptor tables that were previously allocated via . + /// Frees one or more descriptor tables that were previously allocated via . /// - virtual void free_descriptor_tables(uint32_t count, const descriptor_table *handles) = 0; + virtual void free_descriptor_tables(uint32_t count, const descriptor_table *tables) = 0; /// /// Gets the offset (in descriptors) of the specified binding in the underlying descriptor heap of a descriptor table. @@ -444,23 +496,23 @@ namespace reshade { namespace api /// Copies the contents of a descriptor table to another descriptor table. /// /// Descriptor table copy to process. - inline void copy_descriptors(const descriptor_table_copy ©) { copy_descriptor_tables(1, ©); } + void copy_descriptors(const descriptor_table_copy ©) { copy_descriptor_tables(1, ©); } /// /// Copies the contents between multiple descriptor tables. /// /// Number of to process. - /// Pointer to an array of descriptor table copies to process. + /// Pointer to the first element of an array of descriptor table copies to process. virtual void copy_descriptor_tables(uint32_t count, const descriptor_table_copy *copies) = 0; /// /// Updates the contents of a descriptor table with the specified descriptors. /// /// Descriptor table update to process. - inline void update_descriptors(const descriptor_table_update &update) { update_descriptor_tables(1, &update); } + void update_descriptors(const descriptor_table_update &update) { update_descriptor_tables(1, &update); } /// /// Updates the contents of multiple descriptor tables with the specified descriptors. /// /// Number of to process. - /// Pointer to an array of descriptor table updates to process. + /// Pointer to the first element of an array of descriptor table updates to process. virtual void update_descriptor_tables(uint32_t count, const descriptor_table_update *updates) = 0; /// @@ -468,13 +520,13 @@ namespace reshade { namespace api /// /// Type of queries that will be used with this query heap. /// Number of queries to allocate in the query heap. - /// Pointer to a variable that is set to the handle of the created query heap. - /// if the query heap was successfully created, otherwise (in this case is set to zero). - virtual bool create_query_heap(query_type type, uint32_t size, query_heap *out_handle) = 0; + /// Pointer to a variable that is set to the handle of the created query heap. + /// if the query heap was successfully created, otherwise (in this case is set to zero). + virtual bool create_query_heap(query_type type, uint32_t size, query_heap *out_heap) = 0; /// /// Instantly destroys a query heap that was previously created via . /// - virtual void destroy_query_heap(query_heap handle) = 0; + virtual void destroy_query_heap(query_heap heap) = 0; /// /// Gets the results of queries in a query heap. @@ -482,7 +534,7 @@ namespace reshade { namespace api /// Query heap that contains the queries. /// Index of the first query in the query heap to copy the results from. /// Number of query results to copy. - /// Pointer to an array that is filled with the results. + /// Pointer to the first element of an array that is filled with the results. The necessary data type is documented at the enumeration. /// Size (in bytes) of each element in the array. /// if the query results were successfully downloaded from the GPU, otherwise. virtual bool get_query_heap_results(query_heap heap, uint32_t first, uint32_t count, void *results, uint32_t stride) = 0; @@ -490,29 +542,29 @@ namespace reshade { namespace api /// /// Associates a name with a resource, for easier debugging in external tools. /// - /// Resource to associate a name with. + /// Resource to associate a name with. /// Null-terminated name string. - virtual void set_resource_name(resource handle, const char *name) = 0; + virtual void set_resource_name(resource resource, const char *name) = 0; /// /// Associates a name with a resource view, for easier debugging in external tools. /// - /// Resource view to associate a name with. + /// Resource view to associate a name with. /// Null-terminated name string. - virtual void set_resource_view_name(resource_view handle, const char *name) = 0; + virtual void set_resource_view_name(resource_view view, const char *name) = 0; /// /// Creates a new fence synchronization object. /// /// The initial value for the fence. /// Fence creation options. - /// Pointer to a variable that is set to the handle of the created fence. + /// Pointer to a variable that is set to the handle of the created fence. /// Optional pointer to a variable of type HANDLE used when contains . When that variable is a , it is set to the exported shared handle of the created fence. When that variable is a valid handle, the fence is imported from that shared handle. - /// if the fence was successfully created, otherwise (in this case is set to zero). - virtual bool create_fence(uint64_t initial_value, fence_flags flags, fence *out_handle, void **shared_handle = nullptr) = 0; + /// if the fence was successfully created, otherwise (in this case is set to zero). + virtual bool create_fence(uint64_t initial_value, fence_flags flags, fence *out_fence, void **shared_handle = nullptr) = 0; /// /// Instantly destroys a fence that was previously created via . /// - virtual void destroy_fence(fence handle) = 0; + virtual void destroy_fence(fence fence) = 0; /// /// Gets the current value of the specified fence. @@ -536,9 +588,43 @@ namespace reshade { namespace api virtual bool signal(fence fence, uint64_t value) = 0; /// - /// Gets information about the primary adapter associated with this logical render device. + /// Gets data for a of this device. /// - virtual device_properties get_properties() const = 0; + /// Property to query. + /// Pointer to a variable that is set to the value of the property. The necessary data type is documented at the enumeration. + /// if the property exists and was retrieved, otherwise. + virtual bool get_property(device_properties property, void *data) const = 0; + + /// + /// Gets the GPU address for a resource view. + /// + /// Resource view to query. + /// GPU address of the resource view, or zero in case of failure or when no fixed GPU address exists. + virtual uint64_t get_resource_view_gpu_address(resource_view view) const = 0; + + /// + /// Gets the required acceleration structure size needed to build the specified data. + /// + /// + /// Type of the acceleration structure. + /// Acceleration structure build options. + /// Number of build inputs. + /// Pointer to the first element of an array of build inputs describing the geometry of the acceleration structure. + /// Pointer to a variable that is set to the required buffer size for the acceleration structure. + /// Pointer to a variable that is set to the required scratch buffer size for building the acceleration structure. + /// Pointer to a variable that is set to the required scratch buffer size for updating the acceleration structure. + virtual void get_acceleration_structure_size(acceleration_structure_type type, acceleration_structure_build_flags flags, uint32_t input_count, const acceleration_structure_build_input *inputs, uint64_t *out_size, uint64_t *out_build_scratch_size, uint64_t *out_update_scratch_size) const = 0; + + /// + /// Gets the shader group handles for a ray tracing pipeline, to be put into a shader binding table. + /// + /// + /// Ray tracing pipeline to query. + /// Index of the first shader group in the array that was used to create the pipeline. + /// Number of shader groups to get handles for. + /// Pointer to the first element of an array (with elements of the size reported by ) that is filled with the handles. + /// if the shader group handles were successfully retrieved, otherwise. + virtual bool get_pipeline_shader_group_handles(pipeline pipeline, uint32_t first, uint32_t count, void *out_handles) = 0; }; /// @@ -553,14 +639,17 @@ namespace reshade { namespace api }; /// - /// The available indirect command types. + /// Type of an indirect draw/dispatch command. /// + /// enum class indirect_command { unknown, draw, draw_indexed, - dispatch + dispatch, + dispatch_mesh, + dispatch_rays }; /// @@ -574,26 +663,27 @@ namespace reshade { namespace api { /// /// Adds a barrier for the specified to the command stream. - /// When both and are a UAV barrier is added, otherwise a state transition is performed. + /// Multiple barriers are more efficiently issued using the overload that takes arrays. + /// When both and are , a UAV barrier is added, otherwise a state transition is performed. /// /// Resource to transition. /// Usage flags describing how the was used before this barrier. /// Usage flags describing how the will be used after this barrier. - inline void barrier(resource resource, resource_usage old_state, resource_usage new_state) { barrier(1, &resource, &old_state, &new_state); } + void barrier(resource resource, resource_usage old_state, resource_usage new_state) { barrier(1, &resource, &old_state, &new_state); } /// /// Adds a barrier for the specified to the command stream. /// /// Number of resources to transition. - /// Pointer to an array of resources to transition. - /// Pointer to an array of usage flags describing how the were used before this barrier. - /// Pointer to an array of usage flags describing how the will be used after this barrier. + /// Pointer to the first element of an array of resources to transition. + /// Pointer to the first element of an array of usage flags describing how the were used before this barrier. + /// Pointer to the first element of an array of usage flags describing how the will be used after this barrier. virtual void barrier(uint32_t count, const resource *resources, const resource_usage *old_states, const resource_usage *new_states) = 0; /// /// Begins a render pass and binds render target and depth-stencil resource views. /// /// Number of render target views to bind. - /// Pointer to an array of render target descriptions. + /// Pointer to the first element of an array of render target descriptions. /// Optional pointer to a depth-stencil description, or to bind none. virtual void begin_render_pass(uint32_t count, const render_pass_render_target_desc *rts, const render_pass_depth_stencil_desc *ds = nullptr) = 0; /// @@ -608,7 +698,7 @@ namespace reshade { namespace api /// /// /// Number of render target views to bind. - /// Pointer to an array of render target views to bind. + /// Pointer to the first element of an array of render target views to bind. /// Depth-stencil view to bind, or zero to bind none. virtual void bind_render_targets_and_depth_stencil(uint32_t count, const resource_view *rtvs, resource_view dsv = { 0 }) = 0; @@ -624,14 +714,14 @@ namespace reshade { namespace api /// /// Pipeline state to update. /// Value to update the pipeline state to. - inline void bind_pipeline_state(dynamic_state state, uint32_t value) { bind_pipeline_states(1, &state, &value); } + void bind_pipeline_state(dynamic_state state, uint32_t value) { bind_pipeline_states(1, &state, &value); } /// /// Updates the specfified pipeline to the specified . /// This is only valid for states that have been listed in the dynamic states provided at creation of the currently bound pipeline state object (). /// /// Number of pipeline states to update. - /// Pointer to an array of pipeline states to update. - /// Pointer to an array of values to update the pipeline states to, with one for each state in . + /// Pointer to the first element of an array of pipeline states to update. + /// Pointer to the first element of an array of values to update the pipeline states to, with one for each state in . virtual void bind_pipeline_states(uint32_t count, const dynamic_state *states, const uint32_t *values) = 0; /// /// Binds an array of viewports to the rasterizer stage. @@ -639,7 +729,7 @@ namespace reshade { namespace api /// /// Index of the first viewport to bind. In D3D9, D3D10, D3D11 and D3D12 this has to be 0. /// Number of viewports to bind. - /// Pointer to an array of viewports. + /// Pointer to the first element of an array of viewports. virtual void bind_viewports(uint32_t first, uint32_t count, const viewport *viewports) = 0; /// /// Binds an array of scissor rectangles to the rasterizer stage. @@ -647,7 +737,7 @@ namespace reshade { namespace api /// /// Index of the first scissor rectangle to bind. In D3D9, D3D10, D3D11 and D3D12 this has to be 0. /// Number of scissor rectangles to bind. - /// Pointer to an array of scissor rectangles. + /// Pointer to the first element of an array of scissor rectangles. virtual void bind_scissor_rects(uint32_t first, uint32_t count, const rect *rects) = 0; /// @@ -660,7 +750,7 @@ namespace reshade { namespace api /// Layout parameter index of the constant range in the pipeline (root parameter index in D3D12). /// Start offset (in 32-bit values) to the first constant in the constant range to begin updating. /// Number of 32-bit values to update. - /// Pointer to an array of 32-bit values to set the constants to. These can be floating-point, integer or boolean depending on what the shader is expecting. + /// Pointer to the first element of an array of 32-bit values to set the constants to. These can be floating-point, integer or boolean depending on what the shader is expecting. virtual void push_constants(shader_stage stages, pipeline_layout layout, uint32_t param, uint32_t first, uint32_t count, const void *values) = 0; /// /// Directly binds a temporary descriptor table for the specfified shader pipeline stage and updates with an array of descriptors. @@ -678,7 +768,7 @@ namespace reshade { namespace api /// Pipeline layout that describes the descriptors. /// Index of the pipeline parameter that describes the descriptor table (root parameter index in D3D12, descriptor set index in Vulkan). /// Descriptor table to bind. - inline void bind_descriptor_table(shader_stage stages, pipeline_layout layout, uint32_t param, descriptor_table table) { bind_descriptor_tables(stages, layout, param, 1, &table); } + void bind_descriptor_table(shader_stage stages, pipeline_layout layout, uint32_t param, descriptor_table table) { bind_descriptor_tables(stages, layout, param, 1, &table); } /// /// Binds an array of descriptor tables. /// @@ -686,7 +776,7 @@ namespace reshade { namespace api /// Pipeline layout that describes the descriptors. /// Index of the first pipeline parameter that describes the first descriptor table to bind (root parameter index in D3D12, descriptor set index in Vulkan). /// Number of descriptor tables to bind. - /// Pointer to an array of descriptor tables to bind. + /// Pointer to the first element of an array of descriptor tables to bind. virtual void bind_descriptor_tables(shader_stage stages, pipeline_layout layout, uint32_t first, uint32_t count, const descriptor_table *tables) = 0; /// @@ -703,15 +793,15 @@ namespace reshade { namespace api /// Vertex buffer resource. This resources must have been created with the usage. /// Offset (in bytes) from the start of the vertex buffer to the first vertex element to use. /// Size (in bytes) of the vertex element that will be used from the vertex buffer (is added to an element offset to advance to the next). - inline void bind_vertex_buffer(uint32_t index, resource buffer, uint64_t offset, uint32_t stride) { bind_vertex_buffers(index, 1, &buffer, &offset, &stride); } + void bind_vertex_buffer(uint32_t index, resource buffer, uint64_t offset, uint32_t stride) { bind_vertex_buffers(index, 1, &buffer, &offset, &stride); } /// /// Binds an array of vertex buffers to the input-assembler stage. /// /// First input slot for binding. /// Number of vertex buffers to bind. - /// Pointer to an array of vertex buffer resources. These resources must have been created with the usage. - /// Pointer to an array of offset values, one for each buffer. Each offset is the number of bytes from the start of the vertex buffer to the first vertex element to use. - /// Pointer to an array of stride values, one for each buffer. Each stride is the size (in bytes) of the vertex element that will be used from that vertex buffer (is added to an element offset to advance to the next). + /// Pointer to the first element of an array of vertex buffer resources. These resources must have been created with the usage. + /// Pointer to the first element of an array of offset values, one for each buffer. Each offset is the number of bytes from the start of the vertex buffer to the first vertex element to use. + /// Pointer to the first element of an array of stride values, one for each buffer. Each stride is the size (in bytes) of the vertex element that will be used from that vertex buffer (is added to an element offset to advance to the next). virtual void bind_vertex_buffers(uint32_t first, uint32_t count, const resource *buffers, const uint64_t *offsets, const uint32_t *strides) = 0; /// @@ -719,11 +809,11 @@ namespace reshade { namespace api /// /// First stream-output slot for binding. /// Number of stream-output targets to bind. - /// Pointer to an array of buffer resources. These resources must have been created with the usage. - /// Pointer to an array of offset values, one for each buffer. Each offset is the number of bytes from the start of the buffer to the first element to write to. + /// Pointer to the first element of an array of buffer resources. These resources must have been created with the usage. + /// Pointer to the first element of an array of offset values, one for each buffer. Each offset is the number of bytes from the start of the buffer to the first element to write to. /// Optional pointer to an array of size values, one for each buffer. Can be or have elements set to UINT64_MAX to use the entire buffer. - /// Pointer to an array of counter buffer resources. These resources must have been created with the usage. - /// Pointer to an array of counter offset values, one for each counter buffer. Each offset is the number of bytes from the start of the counter buffer to the first element to write to. + /// Pointer to the first element of an array of counter buffer resources. These resources must have been created with the usage. + /// Pointer to the first element of an array of counter offset values, one for each counter buffer. Each offset is the number of bytes from the start of the counter buffer to the first element to write to. virtual void bind_stream_output_buffers(uint32_t first, uint32_t count, const api::resource *buffers, const uint64_t *offsets, const uint64_t *max_sizes, const api::resource *counter_buffers, const uint64_t *counter_offsets) = 0; /// @@ -866,7 +956,7 @@ namespace reshade { namespace api /// Optional value to clear the depth buffer with. /// Optional value to clear the stencil buffer with. /// Number of rectangles to clear in the depth-stencil resource, or zero to clear the whole resource. - /// Pointer to an array of rectangles. + /// Pointer to the first element of an array of rectangles. virtual void clear_depth_stencil_view(resource_view dsv, const float *depth, const uint8_t *stencil, uint32_t rect_count = 0, const rect *rects = nullptr) = 0; /// /// Clears the resource referenced by the render target view. @@ -877,7 +967,7 @@ namespace reshade { namespace api /// Resource view handle of the render target. /// Value to clear the resource with. /// Number of rectangles to clear in the render target resource, or zero to clear the whole resource. - /// Pointer to an array of rectangles. + /// Pointer to the first element of an array of rectangles. virtual void clear_render_target_view(resource_view rtv, const float color[4], uint32_t rect_count = 0, const rect *rects = nullptr) = 0; /// /// Clears the resource referenced by the unordered access view. @@ -888,7 +978,7 @@ namespace reshade { namespace api /// Resource view handle of the unordered access view. /// Value to clear the resource with. /// Number of rectangles to clear in the unordered access resource, or zero to clear the whole resource. - /// Pointer to an array of rectangles. + /// Pointer to the first element of an array of rectangles. virtual void clear_unordered_access_view_uint(resource_view uav, const uint32_t values[4], uint32_t rect_count = 0, const rect *rects = nullptr) = 0; /// /// Clears the resource referenced by the unordered access view. @@ -899,7 +989,7 @@ namespace reshade { namespace api /// Resource view handle of the unordered access view. /// Value to clear the resource with. /// Number of rectangles to clear in the unordered access resource, or zero to clear the whole resource. - /// Pointer to an array of rectangles. + /// Pointer to the first element of an array of rectangles. virtual void clear_unordered_access_view_float(resource_view uav, const float values[4], uint32_t rect_count = 0, const rect *rects = nullptr) = 0; /// @@ -959,11 +1049,69 @@ namespace reshade { namespace api /// Null-terminated string containing the label of the debug marker. /// Optional RGBA color value associated with the debug marker. virtual void insert_debug_marker(const char *label, const float color[4] = nullptr) = 0; + + /// + /// Performs a mesh shader dispatch. + /// + /// + /// Number of thread groups dispatched in the x direction. + /// Number of thread groups dispatched in the y direction. + /// Number of thread groups dispatched in the z direction. + virtual void dispatch_mesh(uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z) = 0; + + /// + /// Performs a ray tracing dispatch. + /// + /// + /// The buffer resources have to be in the state. + /// + /// + /// Buffer resource containing the ray generation shader handle to use. + /// Buffer resource containing the miss shader handles to use. + /// Buffer resource containing the hit group handles to use. + /// Buffer resource containing the callable shader handles to use. + /// Width of the ray generation shader thread grid. + /// Height of the ray generation shader thread grid. + /// Depth of the ray generation shader thread grid. + virtual void dispatch_rays(resource raygen, uint64_t raygen_offset, uint64_t raygen_size, resource miss, uint64_t miss_offset, uint64_t miss_size, uint64_t miss_stride, resource hit_group, uint64_t hit_group_offset, uint64_t hit_group_size, uint64_t hit_group_stride, resource callable, uint64_t callable_offset, uint64_t callable_size, uint64_t callable_stride, uint32_t width, uint32_t height, uint32_t depth) = 0; + + /// + /// Copies or transforms data from the acceleration structure to the ination acceleration structure. + /// + /// + /// The and ination acceleration structure resources have to be in the state. + /// + /// + /// Acceleration structure to copy from. + /// Acceleration structure to copy to. + /// Choose between copying or transforming the data in the acceleration structure. + virtual void copy_acceleration_structure(resource_view source, resource_view dest, acceleration_structure_copy_mode mode) = 0; + + /// + /// Builds or updates an acceleration structure for ray tracing. + /// + /// + /// The build input vertex, index and instance buffers have to be in the state. + /// The resource has to be in the state. + /// The and ination acceleration structure resources have to be in the state. + /// + /// + /// Type of the acceleration structure to build. + /// Acceleration structure build options. + /// Number of build inputs. + /// Pointer to the first element of an array of build inputs describing the geometry of the acceleration structure to build. + /// Buffer resource to use as scratch space during building. + /// Offset (in bytes) into the buffer. + /// Acceleration structure to read data from when is , otherwise zero. + /// Acceleration structure to write data to. + /// Choose between building a new or updating an existing acceleration structure. + virtual void build_acceleration_structure(acceleration_structure_type type, acceleration_structure_build_flags flags, uint32_t input_count, const acceleration_structure_build_input *inputs, api::resource scratch, uint64_t scratch_offset, resource_view source, resource_view dest, acceleration_structure_build_mode mode) = 0; }; /// - /// A list of flags that represent the available command queue types, as returned by . + /// Command queue type flags, which can be combined to describe the capabilities of a command queue. /// + /// enum class command_queue_type { graphics = 0x1, @@ -1039,6 +1187,7 @@ namespace reshade { namespace api /// /// Queries the GPU timestamp frequency in ticks per second. /// + /// Timestamp frequency in number of ticks per second, or zero if GPU timestamps are not supported on this queue. virtual uint64_t get_timestamp_frequency() const = 0; }; @@ -1059,15 +1208,26 @@ namespace reshade { namespace api /// /// Defines how the back buffers should be swapped when a present occurs. - /// Depending on the render API this can be a 'D3DSWAPEFFECT', 'DXGI_SWAP_EFFECT', 'WGL_SWAP_METHOD_ARB' or 'VkPresentModeKHR' value. + /// Depending on the graphics API this can be a 'D3DSWAPEFFECT', 'DXGI_SWAP_EFFECT', 'WGL_SWAP_METHOD_ARB' or 'VkPresentModeKHR' value. /// uint32_t present_mode = 0; /// /// Swap chain creation flags. - /// Depending on the render API this can be a 'D3DPRESENT', 'DXGI_PRESENT', 'PFD_*' or 'VkSwapchainCreateFlagsKHR' value. + /// Depending on the graphics API this can be a 'D3DPRESENT', 'DXGI_PRESENT', 'PFD_*' or 'VkSwapchainCreateFlagsKHR' value. /// uint32_t present_flags = 0; + + /// + /// Initial fullscreen state. + /// + bool fullscreen_state = false; + + /// + /// Refresh rate of the display in fullscreen mode, in Hertz. + /// Set to zero to use the default. + /// + float fullscreen_refresh_rate = 0; }; /// @@ -1095,7 +1255,7 @@ namespace reshade { namespace api /// /// Gets the current back buffer resource. /// - inline resource get_current_back_buffer() { return get_back_buffer(get_current_back_buffer_index()); } + resource get_current_back_buffer() { return get_back_buffer(get_current_back_buffer_index()); } /// /// Gets the index of the back buffer resource that can currently be rendered into. /// diff --git a/depends/include/ReShade/reshade_api_display.hpp b/depends/include/ReShade/reshade_api_display.hpp new file mode 100644 index 000000000..934099d39 --- /dev/null +++ b/depends/include/ReShade/reshade_api_display.hpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2024 Patrick Mours + * SPDX-License-Identifier: BSD-3-Clause OR MIT + */ + +#pragma once + +#include "reshade_api_device.hpp" +#include +#include + +namespace reshade { namespace api +{ + /// + /// Describes quantities defined precisely as the ratio of two integers, such as refresh rates. + /// + struct rational + { + uint32_t numerator = 0; + uint32_t denomenator = 0; + + constexpr float as_float() const { return denomenator != 0 ? static_cast (numerator)/static_cast(denomenator) : 0.0f; } + }; + + /// + /// Describes the colorimetry of a colorspace. + /// + struct colorimetry + { + float red [2] = { 0.0f, 0.0f }; + float green [2] = { 0.0f, 0.0f }; + float blue [2] = { 0.0f, 0.0f }; + float white [2] = { 0.0f, 0.0f }; + }; + + /// + /// Describes the dynamic range of a display or image. + /// + struct luminance_levels + { + float min_nits = 0.0f; + float max_nits = 0.0f; + float max_avg_nits = 0.0f; + }; + + /// + /// An output display. + /// Functionally equivalent to a 'IDXGIOutput'. + /// + struct __declspec(novtable) display : public api_object + { + /// + /// Indicates if cached properties are valid or potentially stale (i.e. refresh rate or resolution have changed). + /// + /// + /// If this returns false, wait one frame and call runtime::get_active_display() to get updated data. + /// + virtual bool is_current() const = 0; + + using monitor = void*; + + /// + /// Gets the handle of the monitor this display encapsulates. + /// + virtual monitor get_monitor() const = 0; + + /// + /// Gets the (GDI) device name (i.e. \\DISPLAY1) of the the monitor; do not use this as a persistent display identifier! + /// + /// + /// This device name is not valid as a persistent display identifier for storage in configuration files, it may not refer to the same display device after a reboot. + /// + virtual const wchar_t* get_device_name() const = 0; + + /// + /// Gets the device path (i.e. \\?\DISPLAY#DELA1E4#5&d93f871&0&UID33025#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) of the the monitor. + /// + /// + /// The device path uniquely identifies a specific monitor (down to its serial number and the port it is attached to) and remains valid across system reboots. + /// This identifier is suitable for persistent user-defined display configuration, partial name matches can be used to identify instances of the same monitor when the port it attaches to is unimportant. + /// + virtual const wchar_t* get_device_path() const = 0; + + /// + /// Gets the human readable name (i.e. Dell AW3423DW) of the the monitor. + /// + virtual const wchar_t* get_display_name() const = 0; + + /// + /// Gets the size and location of the display on the desktop. + /// + virtual rect get_desktop_coords() const = 0; + + /// + /// Gets the current color depth of the display. + /// + virtual uint32_t get_color_depth() const = 0; + + /// + /// Gets the current refresh rate of the display. + /// + virtual rational get_refresh_rate() const = 0; + + /// + /// Gets the current color space used for desktop composition. + /// + /// + /// This is independent from swap chain colorspace, it identifies a display as HDR capable even when not rendering in HDR. + /// + virtual color_space get_color_space() const = 0; + + /// + /// Gets the display's reported native colorimetry (the data provided are often invalid or placeholders). + /// + /// + /// Users running Windows 11 or newer are encouraged to run "Windows HDR Calibration" to ensure the values reported to ReShade and games are accurate. + /// + virtual colorimetry get_colorimetry() const = 0; + + /// + /// Gets the display's light output capabilities (the data provided are often invalid or placeholders). + /// + /// + /// Users running Windows 11 or newer are encouraged to run "Windows HDR Calibration" to ensure the values reported to ReShade and games are accurate. + /// + virtual luminance_levels get_luminance_caps() const = 0; + + /// + /// Gets the desktop compositor's whitelevel for mapping SDR content to HDR. + /// + virtual float get_sdr_white_nits() const = 0; + + /// + /// Checks if HDR is supported on the display, even if it is not currently enabled. + /// + virtual bool is_hdr_supported() const = 0; + + /// + /// Checks if HDR is enabled on the display. + /// + virtual bool is_hdr_enabled() const = 0; + + /// + /// Enables HDR on the display. + /// + /// + /// Be aware that this is a global display setting, and will not automatically revert to its original state when the application exits. + /// + virtual bool enable_hdr(bool enable) = 0; + }; + + using display_cache = std::unordered_map>; +} } \ No newline at end of file diff --git a/depends/include/ReShade/reshade_api_format.hpp b/depends/include/ReShade/reshade_api_format.hpp index 023b87e05..363e00076 100644 --- a/depends/include/ReShade/reshade_api_format.hpp +++ b/depends/include/ReShade/reshade_api_format.hpp @@ -11,7 +11,7 @@ namespace reshade { namespace api { /// - /// The available data and texture formats. + /// Available data and texture formats. /// This is mostly compatible with 'DXGI_FORMAT'. /// enum class format : uint32_t @@ -336,6 +336,7 @@ namespace reshade { namespace api case format::b10g10r10a2_typeless: return format::b10g10r10a2_unorm; case format::d16_unorm: + return format::r16_unorm; case format::r16_typeless: return format::r16_float; case format::r16g16_typeless: @@ -415,6 +416,50 @@ namespace reshade { namespace api } } + /// + /// Gets the average component bit depth of the specified format . + /// + inline const uint32_t format_bit_depth(format value) + { + switch (value) + { + case format::b5g6r5_unorm: + case format::b5g5r5a1_unorm: + case format::b5g5r5x1_unorm: + return 5; + case format::r8g8b8a8_typeless: + case format::r8g8b8a8_unorm: + case format::r8g8b8a8_unorm_srgb: + case format::r8g8b8x8_unorm: + case format::r8g8b8x8_unorm_srgb: + case format::b8g8r8a8_typeless: + case format::b8g8r8a8_unorm: + case format::b8g8r8a8_unorm_srgb: + case format::b8g8r8x8_typeless: + case format::b8g8r8x8_unorm: + case format::b8g8r8x8_unorm_srgb: + return 8; + case format::r10g10b10a2_typeless: + case format::r10g10b10a2_unorm: + case format::r10g10b10a2_xr_bias: + case format::b10g10r10a2_typeless: + case format::b10g10r10a2_unorm: + return 10; + case format::r11g11b10_float: + return 11; + case format::r16g16b16a16_typeless: + case format::r16g16b16a16_float: + return 16; + case format::r32g32b32_typeless: + case format::r32g32b32_float: + case format::r32g32b32a32_typeless: + case format::r32g32b32a32_float: + return 32; + default: + return 0; + } + } + /// /// Gets the number of bytes a texture row of the specified format occupies. /// diff --git a/depends/include/ReShade/reshade_api_pipeline.hpp b/depends/include/ReShade/reshade_api_pipeline.hpp index 71fc10e51..b9758a8f3 100644 --- a/depends/include/ReShade/reshade_api_pipeline.hpp +++ b/depends/include/ReShade/reshade_api_pipeline.hpp @@ -10,7 +10,7 @@ namespace reshade { namespace api { /// - /// A list of flags that represent the available shader stages in the render pipeline. + /// Flags that specify the shader stages in the render pipeline. /// enum class shader_stage : uint32_t { @@ -21,14 +21,25 @@ namespace reshade { namespace api pixel = 0x10, compute = 0x20, + amplification = 0x40, + mesh = 0x80, + + raygen = 0x0100, + any_hit = 0x0200, + closest_hit = 0x0400, + miss = 0x0800, + intersection = 0x1000, + callable = 0x2000, + all = 0x7FFFFFFF, all_compute = compute, - all_graphics = vertex | hull | domain | geometry | pixel + all_graphics = vertex | hull | domain | geometry | pixel | amplification | mesh, + all_ray_tracing = raygen | any_hit | closest_hit | miss | intersection | callable }; RESHADE_DEFINE_ENUM_FLAG_OPERATORS(shader_stage); /// - /// A list of flags that represent the available pipeline stages in the render pipeline. + /// Flags that specify the pipeline stages in the render pipeline. /// enum class pipeline_stage : uint32_t { @@ -39,6 +50,11 @@ namespace reshade { namespace api pixel_shader = 0x80, compute_shader = 0x800, + amplification_shader = 0x80000, + mesh_shader = 0x100000, + + ray_tracing_shader = 0x00200000, + input_assembler = 0x2, stream_output = 0x4, rasterizer = 0x100, @@ -48,32 +64,67 @@ namespace reshade { namespace api all = 0x7FFFFFFF, all_compute = compute_shader, all_graphics = vertex_shader | hull_shader | domain_shader | geometry_shader | pixel_shader | input_assembler | stream_output | rasterizer | depth_stencil | output_merger, + all_ray_tracing = ray_tracing_shader, all_shader_stages = vertex_shader | hull_shader | domain_shader | geometry_shader | pixel_shader | compute_shader }; RESHADE_DEFINE_ENUM_FLAG_OPERATORS(pipeline_stage); /// - /// The available descriptor types. + /// Type of a descriptor. /// enum class descriptor_type : uint32_t { + /// + /// Descriptors are an array of . + /// sampler = 0, + /// + /// Descriptors are an array of . + /// sampler_with_resource_view = 1, - shader_resource_view = 2, - unordered_access_view = 3, + /// + /// Descriptors are an array of . + /// + buffer_shader_resource_view = 4, + /// + /// Descriptors are an array of . + /// + buffer_unordered_access_view = 5, + /// + /// Descriptors are an array of . + /// + texture_shader_resource_view = 2, + shader_resource_view = texture_shader_resource_view, + /// + /// Descriptors are an array of . + /// + texture_unordered_access_view = 3, + unordered_access_view = texture_unordered_access_view, + /// + /// Descriptors are an array of . + /// constant_buffer = 6, - shader_storage_buffer = 7 + /// + /// Descriptors are an array of . + /// + shader_storage_buffer = 7, + /// + /// Descriptors are an array of . + /// + acceleration_structure = 8 }; /// - /// The available pipeline layout parameter types. + /// Type of a pipeline layout parameter. /// enum class pipeline_layout_param_type : uint32_t { push_constants = 1, descriptor_table = 0, + descriptor_table_with_static_samplers = 4, push_descriptors = 2, - push_descriptors_with_ranges = 3 + push_descriptors_with_ranges = 3, + push_descriptors_with_static_samplers = 5 }; /// @@ -141,6 +192,13 @@ namespace reshade { namespace api /// descriptor_type type = descriptor_type::sampler; }; + struct descriptor_range_with_static_samplers : public descriptor_range + { + /// + /// Optional array of sampler descriptions to statically embed into the descriptor table when the descriptor type is or . + /// + const sampler_desc *static_samplers = nullptr; + }; /// /// Describes a single parameter in a pipeline layout. @@ -150,7 +208,9 @@ namespace reshade { namespace api constexpr pipeline_layout_param() : push_descriptors() {} constexpr pipeline_layout_param(const constant_range &push_constants) : type(pipeline_layout_param_type::push_constants), push_constants(push_constants) {} constexpr pipeline_layout_param(const descriptor_range &push_descriptors) : type(pipeline_layout_param_type::push_descriptors), push_descriptors(push_descriptors) {} + constexpr pipeline_layout_param(const descriptor_range_with_static_samplers &push_descriptors) : type(pipeline_layout_param_type::push_descriptors_with_static_samplers), descriptor_table_with_static_samplers({ 1, &push_descriptors }) {} constexpr pipeline_layout_param(uint32_t count, const descriptor_range *ranges) : type(pipeline_layout_param_type::descriptor_table), descriptor_table({ count, ranges }) {} + constexpr pipeline_layout_param(uint32_t count, const descriptor_range_with_static_samplers *ranges) : type(pipeline_layout_param_type::descriptor_table_with_static_samplers), descriptor_table_with_static_samplers({ count, ranges }) {} /// /// Type of the parameter. @@ -177,6 +237,15 @@ namespace reshade { namespace api uint32_t count; const descriptor_range *ranges; } descriptor_table; + + /// + /// Used when parameter type is or . + /// + struct + { + uint32_t count; + const descriptor_range_with_static_samplers *ranges; + } descriptor_table_with_static_samplers; }; }; @@ -187,7 +256,7 @@ namespace reshade { namespace api RESHADE_DEFINE_HANDLE(pipeline_layout); /// - /// The fill mode to use when rendering triangles. + /// Fill mode to use when rendering triangles. /// enum class fill_mode : uint32_t { @@ -209,7 +278,7 @@ namespace reshade { namespace api RESHADE_DEFINE_ENUM_FLAG_OPERATORS(cull_mode); /// - /// The available logic operations. + /// Logic operations. /// enum class logic_op : uint32_t { @@ -232,7 +301,7 @@ namespace reshade { namespace api }; /// - /// The available color or alpha blending operations. + /// Color or alpha blending operations. /// enum class blend_op : uint32_t { @@ -244,7 +313,7 @@ namespace reshade { namespace api }; /// - /// The available blend factors in color or alpha blending operations. + /// Blend factors in color or alpha blending operations, which modulate values between the pixel shader output and render target. /// enum class blend_factor : uint32_t { @@ -270,7 +339,7 @@ namespace reshade { namespace api }; /// - /// The available stencil operations that can be performed during depth-stencil testing. + /// Stencil operations that can be performed during depth-stencil testing. /// enum class stencil_op : uint32_t { @@ -372,6 +441,96 @@ namespace reshade { namespace api const uint32_t *spec_constant_values = nullptr; }; + /// + /// Type of a ray tracing shader group. + /// + enum class shader_group_type + { + raygen = 0, + miss = 3, + hit_group_triangles = 1, + hit_group_aabbs = 2, + callable = 4, + }; + + /// + /// Describes a ray tracing shader group. + /// + struct shader_group + { + shader_group() : hit_group() {} + shader_group(shader_group_type type, uint32_t closest_hit_shader_index, uint32_t any_hit_shader_index = UINT32_MAX, uint32_t intersection_shader_index = UINT32_MAX) : type(type), hit_group({ closest_hit_shader_index, any_hit_shader_index, intersection_shader_index }) {} + + /// + /// Type of the shader group. + /// + shader_group_type type = shader_group_type::raygen; + + union + { + /// + /// Used when type is . + /// + struct + { + /// + /// Index of the shader in the ray generation shader pipeline subobject. + /// + /// + uint32_t shader_index = UINT32_MAX; + } raygen; + + /// + /// Used when type is . + /// + struct + { + /// + /// Index of the shader in the miss shader pipeline subobject. + /// + /// + uint32_t shader_index = UINT32_MAX; + } miss; + + /// + /// Used when type is or . + /// + struct + { + /// + /// Index of the shader in the closest-hit shader pipeline subobject. + /// Set to -1 (UINT32_MAX) to indicate that this shader type is not used in the hit group. + /// + /// + uint32_t closest_hit_shader_index = UINT32_MAX; + /// + /// Index of the shader in the any-hit shader pipeline subobject. + /// Set to -1 (UINT32_MAX) to indicate that this shader type is not used in the hit group. + /// + /// + uint32_t any_hit_shader_index = UINT32_MAX; + /// + /// Index of the shader in the intersection shader pipeline subobject. + /// Set to -1 (UINT32_MAX) to indicate that this shader type is not used in the hit group. + /// + /// + uint32_t intersection_shader_index = UINT32_MAX; + } hit_group; + + /// + /// Used when type is . + /// + struct + { + /// + /// Index of the shader in the callable shader pipeline subobject. + /// + /// + uint32_t shader_index = UINT32_MAX; + } callable; + }; + }; + /// /// Describes a single element in the vertex layout for the input-assembler stage. /// @@ -622,7 +781,19 @@ namespace reshade { namespace api }; /// - /// The available pipeline sub-object types. + /// Flags that specify additional parameters of a pipeline. + /// + enum class pipeline_flags : uint32_t + { + none = 0, + library = (1 << 0), + skip_triangles = (1 << 1), + skip_aabbs = (1 << 2), + }; + RESHADE_DEFINE_ENUM_FLAG_OPERATORS(pipeline_flags); + + /// + /// Type of a pipeline sub-object. /// enum class pipeline_subobject_type : uint32_t { @@ -739,7 +910,93 @@ namespace reshade { namespace api /// Maximum number of vertices a draw call with this pipeline will draw. /// Sub-object data is a pointer to a 32-bit unsigned integer value. /// - max_vertex_count + max_vertex_count, + /// + /// Amplification shader to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + amplification_shader, + /// + /// Mesh shader to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + mesh_shader, + /// + /// Ray generation shader(s) to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + raygen_shader, + /// + /// Any-hit shader(s) to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + any_hit_shader, + /// + /// Closest-hit shader(s) to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + closest_hit_shader, + /// + /// Miss shader(s) to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + miss_shader, + /// + /// Intersection shader(s) to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + intersection_shader, + /// + /// Callable shader(s) to use. + /// Sub-object data is a pointer to a . + /// + /// + /// + callable_shader, + /// + /// Existing shader libraries added to this pipeline. + /// Sub-object data is a pointer to an array of handles. + /// + libraries, + /// + /// Ray tracing shader groups to use. + /// Sub-object data is a pointer to an array of values. + /// + shader_groups, + /// + /// Maximum payload size of shaders executed by this pipeline. + /// Sub-object data is a pointer to a 32-bit unsigned integer value. + /// + max_payload_size, + /// + /// Maximum hit attribute size of shaders executed by this pipeline. + /// Sub-object data is a pointer to a 32-bit unsigned integer value. + /// + max_attribute_size, + /// + /// Maximum recursion depth of shaders executed by this pipeline. + /// Sub-object data is a pointer to a 32-bit unsigned integer value. + /// + max_recursion_depth, + /// + /// Additional pipeline creation flags. + /// Sub-object data is a pointer to a value. + /// + flags }; /// @@ -875,7 +1132,7 @@ namespace reshade { namespace api descriptor_type type = descriptor_type::sampler; /// /// Pointer to an array of descriptors to update in the descriptor table (which should be as large as the specified ). - /// Depending on the descriptor this should be pointer to an array of , , or . + /// Depending on the descriptor this should be pointer to an array of , , , or . /// const void *descriptors = nullptr; }; @@ -887,14 +1144,34 @@ namespace reshade { namespace api RESHADE_DEFINE_HANDLE(descriptor_heap); /// - /// The available query types. + /// Type of a query. /// enum class query_type { + /// + /// Number of samples that passed the depth and stencil tests between beginning and end of the query. + /// Data is a 64-bit unsigned integer value. + /// occlusion = 0, + /// + /// Zero if no samples passed, one if at least one sample passed the depth and stencil tests between beginning and end of the query. + /// Data is a 64-bit unsigned integer value. + /// binary_occlusion = 1, + /// + /// GPU timestamp at the frequency returned by . + /// Data is a 64-bit unsigned integer value. + /// timestamp = 2, + /// + /// Pipeline statistics (such as the number of shader invocations) between beginning and end of the query. + /// Data is a structure of type { uint64_t ia_vertices; uint64_t ia_primitives; uint64_t vs_invocations; uint64_t gs_invocations; uint64_t gs_primitives; uint64_t invocations; uint64_t primitives; uint64_t ps_invocations; uint64_t hs_invocations; uint64_t ds_invocations; uint64_t cs_invocations; }. + /// pipeline_statistics = 3, + /// + /// Streaming output statistics for stream 0 between beginning and end of the query. + /// Data is a structure of type { uint64_t primitives_written; uint64_t primitives_storage_needed; }. + /// stream_output_statistics_0 = 4, stream_output_statistics_1, stream_output_statistics_2, @@ -909,7 +1186,7 @@ namespace reshade { namespace api /// /// A list of all possible render pipeline states that can be set independent of pipeline state objects. - /// Support for these varies between render APIs (e.g. modern APIs like D3D12 and Vulkan support much less dynamic states than D3D9). + /// Support for these varies between graphics APIs (e.g. modern APIs like D3D12 and Vulkan support much less dynamic states than D3D9). /// enum class dynamic_state { @@ -970,6 +1247,10 @@ namespace reshade { namespace api back_stencil_pass_op = 188, back_stencil_fail_op = 186, back_stencil_depth_fail_op = 187, + + // Ray tracing state + + ray_tracing_pipeline_stack_size = 2000 }; /// @@ -1000,7 +1281,7 @@ namespace reshade { namespace api }; /// - /// A list of flags that describe fence creation options. + /// Flags that specify additional parameters of a fence. /// enum class fence_flags : uint32_t { diff --git a/depends/include/ReShade/reshade_api_resource.hpp b/depends/include/ReShade/reshade_api_resource.hpp index 9da2df04f..b70229be0 100644 --- a/depends/include/ReShade/reshade_api_resource.hpp +++ b/depends/include/ReShade/reshade_api_resource.hpp @@ -29,7 +29,7 @@ namespace reshade { namespace api { /// - /// The available comparison types. + /// Comparison operations. /// enum class compare_op : uint32_t { @@ -44,7 +44,7 @@ namespace reshade { namespace api }; /// - /// The available filtering modes used for texture sampling operations. + /// Texture filtering modes available for texture sampling operations. /// enum class filter_mode : uint32_t { @@ -71,7 +71,7 @@ namespace reshade { namespace api }; /// - /// Specifies behavior of sampling with texture coordinates outside a texture resource. + /// Sampling behavior at texture coordinates outside the bounds of a texture resource. /// enum class texture_address_mode : uint32_t { @@ -131,12 +131,12 @@ namespace reshade { namespace api /// /// An opaque handle to a sampler state object. - /// Depending on the render API this can be a pointer to a 'ID3D10SamplerState', 'ID3D11SamplerState' or a 'D3D12_CPU_DESCRIPTOR_HANDLE' (to a sampler descriptor) or 'VkSampler' handle. + /// Depending on the graphics API this can be a pointer to a 'ID3D10SamplerState', 'ID3D11SamplerState' or a 'D3D12_CPU_DESCRIPTOR_HANDLE' (to a sampler descriptor) or 'VkSampler' handle. /// RESHADE_DEFINE_HANDLE(sampler); /// - /// The available memory mapping access types. + /// Memory mapping access types. /// enum class map_access { @@ -147,7 +147,7 @@ namespace reshade { namespace api }; /// - /// The available memory heap types, which give a hint as to where to place the memory allocation for a resource. + /// Memory heap types, which give a hint as to where to place the allocation for a resource. /// enum class memory_heap : uint32_t { @@ -162,7 +162,7 @@ namespace reshade { namespace api }; /// - /// The available resource types. The type of a resource is specified during creation and is immutable. + /// Type of a resource. This is specified during creation and is immutable. /// Various operations may have special requirements on the type of resources they operate on (e.g. copies can only happen between resources of the same type, ...). /// enum class resource_type : uint32_t @@ -176,23 +176,39 @@ namespace reshade { namespace api }; /// - /// A list of flags that describe additional parameters of a resource. + /// Flags that specify additional parameters of a resource. /// enum class resource_flags : uint32_t { none = 0, + /// + /// Dynamic resources can be frequently updated during a frame, with previous contents automatically being shadowed so to no affect already executing operations on the GPU. + /// Required for . The flag is not supported in D3D12 or Vulkan. + /// dynamic = (1 << 3), + /// + /// Required to create or views of the resource. + /// cube_compatible = (1 << 2), + /// + /// Required to use the resource with . + /// generate_mipmaps = (1 << 0), + /// + /// Shared resources can be imported/exported from/to different graphics APIs and/or processes. + /// Required to use the "shared_handle" parameter of . + /// shared = (1 << 1), shared_nt_handle = (1 << 11), - structured = (1 << 6), - sparse_binding = (1 << 18) + /// + /// Resource is backed using sparse memory binding. + /// + sparse_binding = (1 << 18), }; RESHADE_DEFINE_ENUM_FLAG_OPERATORS(resource_flags); /// - /// A list of flags that specify how a resource is to be used. + /// Flags that specify how a resource is used. /// This needs to be specified during creation and is also used to transition between different resource states within a command list. /// enum class resource_usage : uint32_t @@ -219,6 +235,8 @@ namespace reshade { namespace api resolve_dest = 0x1000, resolve_source = 0x2000, + acceleration_structure = 0x400000, + // The following are special resource states and may only be used in barriers: general = 0x80000000, @@ -233,8 +251,8 @@ namespace reshade { namespace api struct [[nodiscard]] resource_desc { constexpr resource_desc() : texture() {} - constexpr resource_desc(uint64_t size, memory_heap heap, resource_usage usage) : - type(resource_type::buffer), buffer({ size }), heap(heap), usage(usage) {} + constexpr resource_desc(uint64_t size, memory_heap heap, resource_usage usage, resource_flags flags = resource_flags::none) : + type(resource_type::buffer), buffer({ size }), heap(heap), usage(usage), flags(flags) {} constexpr resource_desc(uint32_t width, uint32_t height, uint16_t layers, uint16_t levels, format format, uint16_t samples, memory_heap heap, resource_usage usage, resource_flags flags = resource_flags::none) : type(resource_type::texture_2d), texture({ width, height, layers, levels, format, samples }), heap(heap), usage(usage), flags(flags) {} constexpr resource_desc(resource_type type, uint32_t width, uint32_t height, uint16_t depth_or_layers, uint16_t levels, format format, uint16_t samples, memory_heap heap, resource_usage usage, resource_flags flags = resource_flags::none) : @@ -300,24 +318,25 @@ namespace reshade { namespace api /// memory_heap heap = memory_heap::unknown; /// - /// Flags that specify how this resource may be used. + /// Flags that specify how this resource is used. + /// This should contain all resource states the resource will ever be transitioned to (including the initial state specified for resource creation). /// resource_usage usage = resource_usage::undefined; /// - /// Flags that describe additional parameters. + /// Flags that specify additional parameters. /// resource_flags flags = resource_flags::none; }; /// /// An opaque handle to a resource object (buffer, texture, ...). - /// Resources created by the application are only guaranteed to be valid during event callbacks. - /// Depending on the render API this can be a pointer to a 'IDirect3DResource9', 'ID3D10Resource', 'ID3D11Resource' or 'ID3D12Resource' object or a 'VkImage' handle. + /// Resources created by the application are only guaranteed to be valid during event callbacks. + /// Depending on the graphics API this can be a pointer to a 'IDirect3DResource9', 'ID3D10Resource', 'ID3D11Resource' or 'ID3D12Resource' object or a 'VkImage' handle. /// RESHADE_DEFINE_HANDLE(resource); /// - /// The available resource view types. These identify how a resource view interprets the data of its resource. + /// Type of a resource view. This identifies how a resource view interprets the data of its resource. /// enum class resource_view_type : uint32_t { @@ -331,7 +350,8 @@ namespace reshade { namespace api texture_2d_multisample_array, texture_3d, texture_cube, - texture_cube_array + texture_cube_array, + acceleration_structure }; /// @@ -344,6 +364,8 @@ namespace reshade { namespace api type(resource_view_type::buffer), format(format), buffer({ offset, size }) {} constexpr resource_view_desc(format format, uint32_t first_level, uint32_t levels, uint32_t first_layer, uint32_t layers) : type(resource_view_type::texture_2d), format(format), texture({ first_level, levels, first_layer, layers }) {} + constexpr resource_view_desc(resource_view_type type, format format, uint64_t offset, uint64_t size) : + type(type), format(format), buffer({ offset, size }) {} constexpr resource_view_desc(resource_view_type type, format format, uint32_t first_level, uint32_t levels, uint32_t first_layer, uint32_t layers) : type(type), format(format), texture({ first_level, levels, first_layer, layers }) {} constexpr explicit resource_view_desc(format format) : type(resource_view_type::texture_2d), format(format), texture({ 0, 1, 0, 1 }) {} @@ -360,7 +382,7 @@ namespace reshade { namespace api union { /// - /// Used when view type is a buffer. + /// Used when view type is a buffer or acceleration structure. /// struct { @@ -404,8 +426,8 @@ namespace reshade { namespace api /// /// An opaque handle to a resource view object (depth-stencil, render target, shader resource view, ...). - /// Resource views created by the application are only guaranteed to be valid during event callbacks. - /// Depending on the render API this can be a pointer to a 'IDirect3DResource9', 'ID3D10View' or 'ID3D11View' object, or a 'D3D12_CPU_DESCRIPTOR_HANDLE' (to a view descriptor) or 'VkImageView' handle. + /// Resource views created by the application are only guaranteed to be valid during event callbacks. + /// Depending on the graphics API this can be a pointer to a 'IDirect3DResource9', 'ID3D10View' or 'ID3D11View' object, or a 'D3D12_CPU_DESCRIPTOR_HANDLE' (to a view descriptor), 'D3D12_GPU_VIRTUAL_ADDRESS' (to an acceleration structrue), 'VkImageView' or 'VkAccelerationStructureKHR' handle. /// RESHADE_DEFINE_HANDLE(resource_view); @@ -525,4 +547,147 @@ namespace reshade { namespace api /// float clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; }; + + /// + /// Type of an acceleration structure. + /// + enum class acceleration_structure_type + { + top_level = 0, + bottom_level = 1, + generic = 2 + }; + + /// + /// Type of an acceleration structure copy operation. + /// + enum class acceleration_structure_copy_mode + { + clone = 0, + compact = 1, + serialize = 2, + deserialize = 3 + }; + + /// + /// Type of an acceleration structure build operation. + /// + enum class acceleration_structure_build_mode + { + build = 0, + update = 1 + }; + + /// + /// Flags that specify additional parameters to an acceleration structure build operation. + /// + enum class acceleration_structure_build_flags : uint32_t + { + none = 0, + allow_update = (1 << 0), + allow_compaction = (1 << 1), + prefer_fast_trace = (1 << 2), + prefer_fast_build = (1 << 3), + minimize_memory_usage = (1 << 4) + }; + RESHADE_DEFINE_ENUM_FLAG_OPERATORS(acceleration_structure_build_flags); + + /// + /// Type of an acceleration structure structure build input. + /// + enum class acceleration_structure_build_input_type : uint32_t + { + triangles = 0, + aabbs = 1, + instances = 2 + }; + + /// + /// Flags that specify additional parameters of an acceleration structure build input. + /// + enum class acceleration_structure_build_input_flags : uint32_t + { + none = 0, + opaque = (1 << 0), + no_duplicate_any_hit_invocation = (1 << 1) + }; + RESHADE_DEFINE_ENUM_FLAG_OPERATORS(acceleration_structure_build_input_flags); + + /// + /// Describes a single instance in a top-level acceleration structure. + /// The data in should be an array of this structure. + /// + struct acceleration_structure_instance + { + float transform[3][4]; + uint32_t custom_index : 24; + uint32_t mask : 8; + uint32_t shader_binding_table_offset : 24; + uint32_t flags : 8; + uint64_t acceleration_structure_gpu_address; + }; + + /// + /// Describes a build input for an acceleration structure build operation. + /// + struct acceleration_structure_build_input + { + constexpr acceleration_structure_build_input() : triangles() {} + constexpr acceleration_structure_build_input(api::resource vertex_buffer, uint64_t vertex_offset, uint32_t vertex_count, uint64_t vertex_stride, api::format vertex_format, api::resource index_buffer, uint64_t index_offset, uint32_t index_count, api::format index_format, uint64_t transform_address = 0) : type(acceleration_structure_build_input_type::triangles), triangles({ vertex_buffer, vertex_offset, vertex_count, vertex_stride, vertex_format, index_buffer, index_offset, index_count, index_format, transform_address }) {} + constexpr acceleration_structure_build_input(api::resource aabb_buffer, uint64_t aabb_offset, uint32_t aabb_count, uint64_t aabb_stride) : type(acceleration_structure_build_input_type::aabbs), aabbs({ aabb_buffer, aabb_offset, aabb_count, aabb_stride }) {} + constexpr acceleration_structure_build_input(api::resource instance_buffer, uint64_t instance_offset, uint32_t instance_count, bool array_of_pointers = false) : type(acceleration_structure_build_input_type::instances), instances({ instance_buffer, instance_offset, instance_count, array_of_pointers }) {} + + /// + /// Type of the acceleration structure build input. + /// + acceleration_structure_build_input_type type = acceleration_structure_build_input_type::triangles; + + union + { + /// + /// Used when build input type is . + /// + struct + { + api::resource vertex_buffer = {}; + uint64_t vertex_offset = 0; + uint32_t vertex_count = 0; + uint64_t vertex_stride = 0; + api::format vertex_format = api::format::unknown; + api::resource index_buffer = {}; + uint64_t index_offset = 0; + uint32_t index_count = 0; + api::format index_format = api::format::unknown; + api::resource transform_buffer = {}; + uint64_t transform_offset = 0; + } triangles; + + /// + /// Used when build input type is . + /// + struct + { + api::resource buffer = {}; + uint64_t offset = 0; + uint32_t count = 0; + uint64_t stride = 0; + } aabbs; + + /// + /// Used when build input type is . + /// + struct + { + api::resource buffer = {}; + uint64_t offset = 0; + uint32_t count = 0; + bool array_of_pointers = false; + } instances; + }; + + /// + /// Flags that specify additional parameters. + /// + acceleration_structure_build_input_flags flags = acceleration_structure_build_input_flags::none; + }; } } diff --git a/depends/include/ReShade/reshade_events.hpp b/depends/include/ReShade/reshade_events.hpp index 4b30a3a88..89ac91252 100644 --- a/depends/include/ReShade/reshade_events.hpp +++ b/depends/include/ReShade/reshade_events.hpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2021 Patrick Mours * SPDX-License-Identifier: BSD-3-Clause OR MIT */ @@ -106,15 +106,19 @@ namespace reshade /// IDirect3D9::CreateDevice (for the implicit swap chain) /// IDirect3D9Ex::CreateDeviceEx (for the implicit swap chain) /// IDirect3D9Device::CreateAdditionalSwapChain - /// IDirect3DDevice9::Reset (for the implicit swap chain) - /// IDirect3DDevice9Ex::ResetEx (for the implicit swap chain) /// IDXGIFactory::CreateSwapChain /// IDXGIFactory2::CreateSwapChain(...) - /// IDXGISwapChain::ResizeBuffers - /// IDXGISwapChain3::ResizeBuffers1 /// wglMakeCurrent /// wglSwapBuffers (after window was resized) /// vkCreateSwapchainKHR + /// xrCreateSession + /// + /// In addition, called when swap chain is resized, after: + /// + /// IDirect3DDevice9::Reset (for the implicit swap chain) + /// IDirect3DDevice9Ex::ResetEx (for the implicit swap chain) + /// IDXGISwapChain::ResizeBuffers + /// IDXGISwapChain3::ResizeBuffers1 /// /// Callback function signature: void (api::swapchain *swapchain) /// @@ -151,8 +155,9 @@ namespace reshade /// wglDeleteContext /// wglSwapBuffers (after window was resized) /// vkDestroySwapchainKHR + /// xrDestroySession /// - /// In addition, called when swap chain is reset, before: + /// In addition, called when swap chain is resized, before: /// /// IDirect3DDevice9::Reset (for the implicit swap chain) /// IDirect3DDevice9Ex::ResetEx (for the implicit swap chain) @@ -284,6 +289,9 @@ namespace reshade /// /// Callback function signature: void (api::device *device, const api::resource_desc &desc, const api::subresource_data *initial_data, api::resource_usage initial_state, api::resource resource) /// + /// + /// May be called multiple times with the same resource handle (whenever the resource is updated or its reference count is incremented). + /// init_resource, /// @@ -394,9 +402,13 @@ namespace reshade /// glTextureView /// vkCreateBufferView /// vkCreateImageView + /// vkCreateAccelerationStructureKHR /// /// Callback function signature: void (api::device *device, api::resource resource, api::resource_usage usage_type, const api::resource_view_desc &desc, api::resource_view view) /// + /// + /// May be called multiple times with the same resource view handle (whenever the resource view is updated). + /// init_resource_view, /// @@ -422,6 +434,7 @@ namespace reshade /// glTextureView /// vkCreateBufferView /// vkCreateImageView + /// vkCreateAccelerationStructureKHR /// /// Callback function signature: bool (api::device *device, api::resource resource, api::resource_usage usage_type, api::resource_view_desc &desc) /// @@ -440,6 +453,7 @@ namespace reshade /// glDeleteTextures /// vkDestroyBufferView /// vkDestroyImageView + /// vkDestroyAccelerationStructureKHR /// /// Callback function signature: void (api::device *device, api::resource_view view) /// @@ -586,6 +600,8 @@ namespace reshade /// ID3D12Device::CreateComputePipelineState /// ID3D12Device::CreateGraphicsPipelineState /// ID3D12Device2::CreatePipelineState + /// ID3D12Device5::CreateStateObject + /// ID3D12Device7::AddToStateObject /// ID3D12PipelineLibrary::LoadComputePipeline /// ID3D12PipelineLibrary::LoadGraphicsPipeline /// ID3D12PipelineLibrary1::LoadPipeline @@ -632,6 +648,7 @@ namespace reshade /// ID3D12Device::CreateComputePipelineState /// ID3D12Device::CreateGraphicsPipelineState /// ID3D12Device2::CreatePipelineState + /// ID3D12Device5::CreateStateObject /// glShaderSource /// vkCreateComputePipelines /// vkCreateGraphicsPipelines @@ -664,6 +681,7 @@ namespace reshade /// ID3D11DepthStencilState::Release /// ID3D11RasterizerState::Release /// ID3D12PipelineState::Release + /// ID3D12StateObject::Release /// glDeleteProgram /// vkDestroyPipeline /// @@ -682,12 +700,22 @@ namespace reshade /// /// Callback function signature: void (api::device *device, uint32_t param_count, const api::pipeline_layout_param *params, api::pipeline_layout layout) /// + /// + /// In case of D3D9, D3D10, D3D11 and OpenGL this is called during device initialization as well and behaves as if an implicit global pipeline layout was created. + /// init_pipeline_layout, /// - /// Called on pipeline layout creation. - /// Callback function signature: bool (api::device *device, uint32_t param_count, const api::pipeline_layout_param *params) + /// Called on pipeline layout creation, before: + /// + /// ID3D12Device::CreateRootSignature + /// vkCreatePipelineLayout + /// + /// Callback function signature: bool (api::device *device, uint32_t &param_count, api::pipeline_layout_param *&params) /// + /// + /// Is not called in D3D9, D3D10, D3D11 or OpenGL. + /// create_pipeline_layout, /// @@ -853,7 +881,9 @@ namespace reshade /// ID3D11DeviceContext::RSSetState /// ID3D12GraphicsCommandList::Reset /// ID3D12GraphicsCommandList::SetPipelineState + /// ID3D12GraphicsCommandList4::SetPipelineState1 /// glUseProgram + /// glBindVertexArray /// vkCmdBindPipeline /// /// Callback function signature: void (api::command_list *cmd_list, api::pipeline_stage stages, api::pipeline pipeline) @@ -1120,7 +1150,34 @@ namespace reshade /// /// To prevent this command from being executed, return , otherwise return . /// - dispatch, + dispatch = 54, + + /// + /// Called before: + /// + /// ID3D12GraphicsCommandList::DispatchMesh + /// vkCmdDrawMeshTasksEXT + /// + /// Callback function signature: bool (api::command_list *cmd_list, uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z) + /// + /// + /// To prevent this command from being executed, return , otherwise return . + /// + dispatch_mesh = 89, + + /// + /// Called before: + /// + /// ID3D12GraphicsCommandList::DispatchRays + /// vkCmdTraceRaysKHR + /// + /// Callback function signature: bool (api::command_list *cmd_list, api::resource raygen, uint64_t raygen_offset, uint64_t raygen_size, api::resource miss, uint64_t miss_offset, uint64_t miss_size, uint64_t miss_stride, api::resource hit_group, uint64_t hit_group_offset, uint64_t hit_group_size, uint64_t hit_group_stride, api::resource callable, uint64_t callable_offset, uint64_t callable_size, uint64_t callable_stride, uint32_t width, uint32_t height, uint32_t depth) + /// + /// + /// To prevent this command from being executed, return , otherwise return . + /// In case of D3D12 and Vulkan, the shader handle buffer handles may be zero with the buffers instead referred to via a device address passed in the related offset argument. + /// + dispatch_rays = 90, /// /// Called before: @@ -1137,13 +1194,16 @@ namespace reshade /// vkCmdDrawIndirect /// vkCmdDrawIndexedIndirect /// vkCmdDispatchIndirect + /// vkCmdTraceRaysIndirect2KHR + /// vkCmdDrawMeshTasksIndirectEXT + /// vkCmdDrawMeshTasksIndirectCountEXT /// /// Callback function signature: bool (api::command_list *cmd_list, api::indirect_command type, api::resource buffer, uint64_t offset, uint32_t draw_count, uint32_t stride) /// /// /// To prevent this command from being executed, return , otherwise return . /// - draw_or_dispatch_indirect, + draw_or_dispatch_indirect = 55, /// /// Called before: @@ -1403,7 +1463,35 @@ namespace reshade /// /// To prevent this command from being executed, return , otherwise return . /// - copy_query_heap_results, + copy_query_heap_results = 69, + + /// + /// Called before: + /// + /// ID3D12GraphicsCommandList4::CopyRaytracingAccelerationStructure + /// vkCmdCopyAccelerationStructureKHR + /// + /// Callback function signature: bool (api::command_list *cmd_list, api::resource_view source, api::resource_view dest, api::acceleration_structure_copy_mode mode) + /// + /// + /// To prevent this command from being executed, return , otherwise return . + /// + copy_acceleration_structure = 91, + + /// + /// Called before: + /// + /// ID3D12GraphicsCommandList4::BuildRaytracingAccelerationStructure + /// vkCmdBuildAccelerationStructuresKHR + /// + /// Callback function signature: bool (api::command_list *cmd_list, api::acceleration_structure_type type, api::acceleration_structure_build_flags flags, uint32_t input_count, const api::acceleration_structure_build_input *inputs, api::resource scratch, uint64_t scratch_offset, api::resource_view source, api::resource_view dest, api::acceleration_structure_build_mode mode) + /// + /// + /// To prevent this command from being executed, return , otherwise return . + /// In case of D3D12 and Vulkan, the scratch buffer handle may be zero with the buffer instead referred to via a device address passed in the related offset argument. + /// Scratch buffer will be in the resource state. + /// + build_acceleration_structure = 92, /// /// Called before: @@ -1416,7 +1504,7 @@ namespace reshade /// /// Is not called for immediate command lists (since they cannot be reset). /// - reset_command_list, + reset_command_list = 70, /// /// Called before: @@ -1474,6 +1562,7 @@ namespace reshade /// wglSwapBuffers /// vkQueuePresentKHR /// IVRCompositor::Submit + /// xrEndFrame /// /// Callback function signature: void (api::command_queue *queue, api::swapchain *swapchain, const api::rect *source_rect, const api::rect *dest_rect, uint32_t dirty_rect_count, const api::rect *dirty_rects) /// @@ -1482,11 +1571,25 @@ namespace reshade /// present, + /// + /// Called before: + /// + /// IDXGISwapChain::SetFullscreenState + /// vkAcquireFullScreenExclusiveModeEXT + /// vkReleaseFullScreenExclusiveModeEXT + /// + /// Callback function signature: bool (api::swapchain *swapchain, bool fullscreen, void *hmonitor) + /// + /// + /// To prevent the fullscreen state from being changed, return , otherwise return . + /// + set_fullscreen_state = 93, + /// /// Called after ReShade has rendered its overlay. /// Callback function signature: void (api::effect_runtime *runtime) /// - reshade_present, + reshade_present = 75, /// /// Called right before ReShade effects are rendered. @@ -1514,7 +1617,7 @@ namespace reshade /// /// /// To prevent the variable value from being changed, return , otherwise return . - /// The new value has the data type reported by and the new value size is in bytes. + /// The new value has the data type reported by . The new value size is in bytes. /// reshade_set_uniform_value, /// @@ -1548,12 +1651,21 @@ namespace reshade /// reshade_render_technique, + /// + /// Called when all effects are about to be enabled or disabled. + /// Callback function signature: bool (api::effect_runtime *runtime, bool enabled) + /// + /// + /// To prevent the effects state from being changed, return , otherwise return . + /// + reshade_set_effects_state = 94, + /// /// Called after a preset was loaded and applied. /// This occurs after effect reloading or when the user chooses a new preset in the overlay. /// Callback function signature: void (api::effect_runtime *runtime, const char *path) /// - reshade_set_current_preset_path, + reshade_set_current_preset_path = 84, /// /// Called when the rendering order of loaded techniques is changed, with a handle array specifying the new order. @@ -1573,8 +1685,34 @@ namespace reshade /// reshade_open_overlay, + /// + /// Called when a uniform variable widget is added to the variable list in the overlay. + /// Can be used to replace with custom one or add widgets for specific uniform variables. + /// Callback function signature: bool (api::effect_runtime *runtime, api::effect_uniform_variable variable) + /// + /// + /// To prevent the normal widget from being added to the overlay, return , otherwise return . + /// + reshade_overlay_uniform_variable, + + /// + /// Called when a technique is added to the technique list in the overlay. + /// Can be used to replace with custom one or add widgets for specific techniques. + /// Callback function signature: bool (api::effect_runtime *runtime, api::effect_technique technique) + /// + /// + /// To prevent the normal widget from being added to the overlay, return , otherwise return . + /// + reshade_overlay_technique, + + /// + /// Called when the active display changes for the current runtime. + /// Callback function signature: void (api::effect_runtime *runtime, api::display display) + /// + display_change = 95, + #if RESHADE_ADDON - max // Last value used internally by ReShade to determine number of events in this enum + max = 96 // Last value used internally by ReShade to determine number of events in this enum #endif }; @@ -1629,7 +1767,7 @@ namespace reshade RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::destroy_pipeline, void, api::device *device, api::pipeline pipeline); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::init_pipeline_layout, void, api::device *device, uint32_t param_count, const api::pipeline_layout_param *params, api::pipeline_layout layout); - RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::create_pipeline_layout, bool, api::device *device, uint32_t param_count, const api::pipeline_layout_param *params); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::create_pipeline_layout, bool, api::device *device, uint32_t ¶m_count, api::pipeline_layout_param *¶ms); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::destroy_pipeline_layout, void, api::device *device, api::pipeline_layout layout); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::copy_descriptor_tables, bool, api::device *device, uint32_t count, const api::descriptor_table_copy *copies); @@ -1661,6 +1799,8 @@ namespace reshade RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::draw, bool, api::command_list *cmd_list, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::draw_indexed, bool, api::command_list *cmd_list, uint32_t index_count, uint32_t instance_count, uint32_t first_index, int32_t vertex_offset, uint32_t first_instance); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::dispatch, bool, api::command_list *cmd_list, uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::dispatch_mesh, bool, api::command_list *cmd_list, uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::dispatch_rays, bool, api::command_list *cmd_list, api::resource raygen, uint64_t raygen_offset, uint64_t raygen_size, api::resource miss, uint64_t miss_offset, uint64_t miss_size, uint64_t miss_stride, api::resource hit_group, uint64_t hit_group_offset, uint64_t hit_group_size, uint64_t hit_group_stride, api::resource callable, uint64_t callable_offset, uint64_t callable_size, uint64_t callable_stride, uint32_t width, uint32_t height, uint32_t depth); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::draw_or_dispatch_indirect, bool, api::command_list *cmd_list, api::indirect_command type, api::resource buffer, uint64_t offset, uint32_t draw_count, uint32_t stride); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::copy_resource, bool, api::command_list *cmd_list, api::resource source, api::resource dest); @@ -1681,6 +1821,9 @@ namespace reshade RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::end_query, bool, api::command_list *cmd_list, api::query_heap heap, api::query_type type, uint32_t index); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::copy_query_heap_results, bool, api::command_list *cmd_list, api::query_heap heap, api::query_type type, uint32_t first, uint32_t count, api::resource dest, uint64_t dest_offset, uint32_t stride); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::copy_acceleration_structure, bool, api::command_list *cmd_list, api::resource_view source, api::resource_view dest, api::acceleration_structure_copy_mode mode); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::build_acceleration_structure, bool, api::command_list *cmd_list, api::acceleration_structure_type type, api::acceleration_structure_build_flags flags, uint32_t input_count, const api::acceleration_structure_build_input *inputs, api::resource scratch, uint64_t scratch_offset, api::resource_view source, api::resource_view dest, api::acceleration_structure_build_mode mode); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reset_command_list, void, api::command_list *cmd_list); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::close_command_list, void, api::command_list *cmd_list); @@ -1688,6 +1831,7 @@ namespace reshade RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::execute_secondary_command_list, void, api::command_list *cmd_list, api::command_list *secondary_cmd_list); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::present, void, api::command_queue *queue, api::swapchain *swapchain, const api::rect *source_rect, const api::rect *dest_rect, uint32_t dirty_rect_count, const api::rect *dirty_rects); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::set_fullscreen_state, bool, api::swapchain *swapchain, bool fullscreen, void *hmonitor); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_present, void, api::effect_runtime *runtime); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_begin_effects, void, api::effect_runtime *runtime, api::command_list *cmd_list, api::resource_view rtv, api::resource_view rtv_srgb); @@ -1702,8 +1846,14 @@ namespace reshade RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_render_technique, void, api::effect_runtime *runtime, api::effect_technique technique, api::command_list *cmd_list, api::resource_view rtv, api::resource_view rtv_srgb); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_set_effects_state, bool, api::effect_runtime *runtime, bool enabled); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_set_current_preset_path, void, api::effect_runtime *runtime, const char *path); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_reorder_techniques, bool, api::effect_runtime *runtime, size_t count, api::effect_technique *techniques); RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_open_overlay, bool, api::effect_runtime *runtime, bool open, api::input_source source); + + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_overlay_uniform_variable, bool, api::effect_runtime *runtime, api::effect_uniform_variable variable); + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::reshade_overlay_technique, bool, api::effect_runtime *runtime, api::effect_technique technique); + + RESHADE_DEFINE_ADDON_EVENT_TRAITS(addon_event::display_change, void, api::effect_runtime *runtime, api::display* display); } diff --git a/depends/include/ReShade/reshade_overlay.hpp b/depends/include/ReShade/reshade_overlay.hpp index ce34ec7a7..23bbe37c1 100644 --- a/depends/include/ReShade/reshade_overlay.hpp +++ b/depends/include/ReShade/reshade_overlay.hpp @@ -1,28 +1,27 @@ /* * Copyright (C) 2021 Patrick Mours - * Copyright (C) 2014-2023 Omar Cornut + * Copyright (C) 2014-2024 Omar Cornut * SPDX-License-Identifier: BSD-3-Clause OR MIT */ -#if 0 -#if defined(IMGUI_VERSION_NUM) +#if defined(IMGUI_VERSION_NUM) && !defined(RESHADE_NO_IMGUI) -#if IMGUI_VERSION_NUM != 18971 -#error Unexpected ImGui version, please update the "imgui.h" header to version 18971! +#if IMGUI_VERSION_NUM != 19040 +#error Unexpected ImGui version, please update the "imgui.h" header to version 19040! #endif // Check that the 'ImTextureID' type has the same size as 'reshade::api::resource_view' static_assert(sizeof(ImTextureID) == 8, "missing \"#define ImTextureID ImU64\" before \"#include \""); -struct imgui_function_table_18971 +struct imgui_function_table_19040 { ImGuiIO&(*GetIO)(); ImGuiStyle&(*GetStyle)(); const char*(*GetVersion)(); bool(*Begin)(const char* name, bool* p_open, ImGuiWindowFlags flags); void(*End)(); - bool(*BeginChild)(const char* str_id, const ImVec2& size, bool border, ImGuiWindowFlags flags); - bool(*BeginChild2)(ImGuiID id, const ImVec2& size, bool border, ImGuiWindowFlags flags); + bool(*BeginChild)(const char* str_id, const ImVec2& size, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags); + bool(*BeginChild2)(ImGuiID id, const ImVec2& size, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags); void(*EndChild)(); bool(*IsWindowAppearing)(); bool(*IsWindowCollapsed)(); @@ -88,8 +87,17 @@ struct imgui_function_table_18971 ImVec2(*GetFontTexUvWhitePixel)(); ImU32(*GetColorU32)(ImGuiCol idx, float alpha_mul); ImU32(*GetColorU322)(const ImVec4& col); - ImU32(*GetColorU323)(ImU32 col); + ImU32(*GetColorU323)(ImU32 col, float alpha_mul); const ImVec4&(*GetStyleColorVec4)(ImGuiCol idx); + ImVec2(*GetCursorScreenPos)(); + void(*SetCursorScreenPos)(const ImVec2& pos); + ImVec2(*GetCursorPos)(); + float(*GetCursorPosX)(); + float(*GetCursorPosY)(); + void(*SetCursorPos)(const ImVec2& local_pos); + void(*SetCursorPosX)(float local_x); + void(*SetCursorPosY)(float local_y); + ImVec2(*GetCursorStartPos)(); void(*Separator)(); void(*SameLine)(float offset_from_start_x, float spacing); void(*NewLine)(); @@ -99,15 +107,6 @@ struct imgui_function_table_18971 void(*Unindent)(float indent_w); void(*BeginGroup)(); void(*EndGroup)(); - ImVec2(*GetCursorPos)(); - float(*GetCursorPosX)(); - float(*GetCursorPosY)(); - void(*SetCursorPos)(const ImVec2& local_pos); - void(*SetCursorPosX)(float local_x); - void(*SetCursorPosY)(float local_y); - ImVec2(*GetCursorStartPos)(); - ImVec2(*GetCursorScreenPos)(); - void(*SetCursorScreenPos)(const ImVec2& pos); void(*AlignTextToFramePadding)(); float(*GetTextLineHeight)(); float(*GetTextLineHeightWithSpacing)(); @@ -140,13 +139,13 @@ struct imgui_function_table_18971 bool(*RadioButton2)(const char* label, int* v, int v_button); void(*ProgressBar)(float fraction, const ImVec2& size_arg, const char* overlay); void(*Bullet)(); - void(*Image)(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col); - bool(*ImageButton)(const char* str_id, ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col); + void(*Image)(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col); + bool(*ImageButton)(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col); bool(*BeginCombo)(const char* label, const char* preview_value, ImGuiComboFlags flags); void(*EndCombo)(); bool(*Combo)(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items); bool(*Combo2)(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items); - bool(*Combo3)(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items); + bool(*Combo3)(const char* label, int* current_item, const char*(*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items); bool(*DragFloat)(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags); bool(*DragFloat2)(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags); bool(*DragFloat3)(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags); @@ -211,7 +210,7 @@ struct imgui_function_table_18971 bool(*BeginListBox)(const char* label, const ImVec2& size); void(*EndListBox)(); bool(*ListBox)(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items); - bool(*ListBox2)(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items); + bool(*ListBox2)(const char* label, int* current_item, const char*(*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items); void(*PlotLines)(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride); void(*PlotLines2)(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); void(*PlotHistogram)(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride); @@ -251,8 +250,9 @@ struct imgui_function_table_18971 bool(*TableSetColumnIndex)(int column_n); void(*TableSetupColumn)(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id); void(*TableSetupScrollFreeze)(int cols, int rows); - void(*TableHeadersRow)(); void(*TableHeader)(const char* label); + void(*TableHeadersRow)(); + void(*TableAngledHeadersRow)(); ImGuiTableSortSpecs*(*TableGetSortSpecs)(); int(*TableGetColumnCount)(); int(*TableGetColumnIndex)(); @@ -323,8 +323,6 @@ struct imgui_function_table_18971 const char*(*GetStyleColorName)(ImGuiCol idx); void(*SetStateStorage)(ImGuiStorage* storage); ImGuiStorage*(*GetStateStorage)(); - bool(*BeginChildFrame)(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags); - void(*EndChildFrame)(); ImVec2(*CalcTextSize)(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width); ImVec4(*ColorConvertU32ToFloat4)(ImU32 in); ImU32(*ColorConvertFloat4ToU32)(const ImVec4& in); @@ -333,6 +331,7 @@ struct imgui_function_table_18971 bool(*IsKeyDown)(ImGuiKey key); bool(*IsKeyPressed)(ImGuiKey key, bool repeat); bool(*IsKeyReleased)(ImGuiKey key); + bool(*IsKeyChordPressed)(ImGuiKeyChord key_chord); int(*GetKeyPressedAmount)(ImGuiKey key, float repeat_delay, float rate); const char*(*GetKeyName)(ImGuiKey key); void(*SetNextFrameWantCaptureKeyboard)(bool want_capture_keyboard); @@ -370,14 +369,14 @@ struct imgui_function_table_18971 bool*(*ImGuiStorage_GetBoolRef)(ImGuiStorage *_this, ImGuiID key, bool default_val); float*(*ImGuiStorage_GetFloatRef)(ImGuiStorage *_this, ImGuiID key, float default_val); void**(*ImGuiStorage_GetVoidPtrRef)(ImGuiStorage *_this, ImGuiID key, void* default_val); - void(*ImGuiStorage_SetAllInt)(ImGuiStorage *_this, int val); void(*ImGuiStorage_BuildSortByKey)(ImGuiStorage *_this); + void(*ImGuiStorage_SetAllInt)(ImGuiStorage *_this, int val); void(*ConstructImGuiListClipper)(ImGuiListClipper *_this); void(*DestructImGuiListClipper)(ImGuiListClipper *_this); void(*ImGuiListClipper_Begin)(ImGuiListClipper *_this, int items_count, float items_height); void(*ImGuiListClipper_End)(ImGuiListClipper *_this); bool(*ImGuiListClipper_Step)(ImGuiListClipper *_this); - void(*ImGuiListClipper_IncludeRangeByIndices)(ImGuiListClipper *_this, int item_begin, int item_end); + void(*ImGuiListClipper_IncludeItemsByIndex)(ImGuiListClipper *_this, int item_begin, int item_end); void(*ImDrawList_PushClipRect)(ImDrawList *_this, const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); void(*ImDrawList_PushClipRectFullScreen)(ImDrawList *_this); void(*ImDrawList_PopClipRect)(ImDrawList *_this); @@ -395,6 +394,8 @@ struct imgui_function_table_18971 void(*ImDrawList_AddCircleFilled)(ImDrawList *_this, const ImVec2& center, float radius, ImU32 col, int num_segments); void(*ImDrawList_AddNgon)(ImDrawList *_this, const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness); void(*ImDrawList_AddNgonFilled)(ImDrawList *_this, const ImVec2& center, float radius, ImU32 col, int num_segments); + void(*ImDrawList_AddEllipse)(ImDrawList *_this, const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments, float thickness); + void(*ImDrawList_AddEllipseFilled)(ImDrawList *_this, const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments); void(*ImDrawList_AddText)(ImDrawList *_this, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end); void(*ImDrawList_AddText2)(ImDrawList *_this, const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect); void(*ImDrawList_AddPolyline)(ImDrawList *_this, const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); @@ -406,6 +407,7 @@ struct imgui_function_table_18971 void(*ImDrawList_AddImageRounded)(ImDrawList *_this, ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags); void(*ImDrawList_PathArcTo)(ImDrawList *_this, const ImVec2& center, float radius, float a_min, float a_max, int num_segments); void(*ImDrawList_PathArcToFast)(ImDrawList *_this, const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); + void(*ImDrawList_PathEllipticalArcTo)(ImDrawList *_this, const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments); void(*ImDrawList_PathBezierCubicCurveTo)(ImDrawList *_this, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments); void(*ImDrawList_PathBezierQuadraticCurveTo)(ImDrawList *_this, const ImVec2& p2, const ImVec2& p3, int num_segments); void(*ImDrawList_PathRect)(ImDrawList *_this, const ImVec2& rect_min, const ImVec2& rect_max, float rounding, ImDrawFlags flags); @@ -428,7 +430,7 @@ struct imgui_function_table_18971 }; -using imgui_function_table = imgui_function_table_18971; +using imgui_function_table = imgui_function_table_19040; inline const imgui_function_table *&imgui_function_table_instance() { @@ -445,8 +447,8 @@ namespace ImGui inline const char* GetVersion() { return imgui_function_table_instance()->GetVersion(); } inline bool Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { return imgui_function_table_instance()->Begin(name, p_open, flags); } inline void End() { imgui_function_table_instance()->End(); } - inline bool BeginChild(const char* str_id, const ImVec2& size, bool border, ImGuiWindowFlags flags) { return imgui_function_table_instance()->BeginChild(str_id, size, border, flags); } - inline bool BeginChild(ImGuiID id, const ImVec2& size, bool border, ImGuiWindowFlags flags) { return imgui_function_table_instance()->BeginChild2(id, size, border, flags); } + inline bool BeginChild(const char* str_id, const ImVec2& size, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { return imgui_function_table_instance()->BeginChild(str_id, size, child_flags, window_flags); } + inline bool BeginChild(ImGuiID id, const ImVec2& size, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { return imgui_function_table_instance()->BeginChild2(id, size, child_flags, window_flags); } inline void EndChild() { imgui_function_table_instance()->EndChild(); } inline bool IsWindowAppearing() { return imgui_function_table_instance()->IsWindowAppearing(); } inline bool IsWindowCollapsed() { return imgui_function_table_instance()->IsWindowCollapsed(); } @@ -512,8 +514,17 @@ namespace ImGui inline ImVec2 GetFontTexUvWhitePixel() { return imgui_function_table_instance()->GetFontTexUvWhitePixel(); } inline ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { return imgui_function_table_instance()->GetColorU32(idx, alpha_mul); } inline ImU32 GetColorU32(const ImVec4& col) { return imgui_function_table_instance()->GetColorU322(col); } - inline ImU32 GetColorU32(ImU32 col) { return imgui_function_table_instance()->GetColorU323(col); } + inline ImU32 GetColorU32(ImU32 col, float alpha_mul) { return imgui_function_table_instance()->GetColorU323(col, alpha_mul); } inline const ImVec4& GetStyleColorVec4(ImGuiCol idx) { return imgui_function_table_instance()->GetStyleColorVec4(idx); } + inline ImVec2 GetCursorScreenPos() { return imgui_function_table_instance()->GetCursorScreenPos(); } + inline void SetCursorScreenPos(const ImVec2& pos) { imgui_function_table_instance()->SetCursorScreenPos(pos); } + inline ImVec2 GetCursorPos() { return imgui_function_table_instance()->GetCursorPos(); } + inline float GetCursorPosX() { return imgui_function_table_instance()->GetCursorPosX(); } + inline float GetCursorPosY() { return imgui_function_table_instance()->GetCursorPosY(); } + inline void SetCursorPos(const ImVec2& local_pos) { imgui_function_table_instance()->SetCursorPos(local_pos); } + inline void SetCursorPosX(float local_x) { imgui_function_table_instance()->SetCursorPosX(local_x); } + inline void SetCursorPosY(float local_y) { imgui_function_table_instance()->SetCursorPosY(local_y); } + inline ImVec2 GetCursorStartPos() { return imgui_function_table_instance()->GetCursorStartPos(); } inline void Separator() { imgui_function_table_instance()->Separator(); } inline void SameLine(float offset_from_start_x, float spacing) { imgui_function_table_instance()->SameLine(offset_from_start_x, spacing); } inline void NewLine() { imgui_function_table_instance()->NewLine(); } @@ -523,15 +534,6 @@ namespace ImGui inline void Unindent(float indent_w) { imgui_function_table_instance()->Unindent(indent_w); } inline void BeginGroup() { imgui_function_table_instance()->BeginGroup(); } inline void EndGroup() { imgui_function_table_instance()->EndGroup(); } - inline ImVec2 GetCursorPos() { return imgui_function_table_instance()->GetCursorPos(); } - inline float GetCursorPosX() { return imgui_function_table_instance()->GetCursorPosX(); } - inline float GetCursorPosY() { return imgui_function_table_instance()->GetCursorPosY(); } - inline void SetCursorPos(const ImVec2& local_pos) { imgui_function_table_instance()->SetCursorPos(local_pos); } - inline void SetCursorPosX(float local_x) { imgui_function_table_instance()->SetCursorPosX(local_x); } - inline void SetCursorPosY(float local_y) { imgui_function_table_instance()->SetCursorPosY(local_y); } - inline ImVec2 GetCursorStartPos() { return imgui_function_table_instance()->GetCursorStartPos(); } - inline ImVec2 GetCursorScreenPos() { return imgui_function_table_instance()->GetCursorScreenPos(); } - inline void SetCursorScreenPos(const ImVec2& pos) { imgui_function_table_instance()->SetCursorScreenPos(pos); } inline void AlignTextToFramePadding() { imgui_function_table_instance()->AlignTextToFramePadding(); } inline float GetTextLineHeight() { return imgui_function_table_instance()->GetTextLineHeight(); } inline float GetTextLineHeightWithSpacing() { return imgui_function_table_instance()->GetTextLineHeightWithSpacing(); } @@ -570,13 +572,13 @@ namespace ImGui inline bool RadioButton(const char* label, int* v, int v_button) { return imgui_function_table_instance()->RadioButton2(label, v, v_button); } inline void ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) { imgui_function_table_instance()->ProgressBar(fraction, size_arg, overlay); } inline void Bullet() { imgui_function_table_instance()->Bullet(); } - inline void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) { imgui_function_table_instance()->Image(user_texture_id, size, uv0, uv1, tint_col, border_col); } - inline bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) { return imgui_function_table_instance()->ImageButton(str_id, user_texture_id, size, uv0, uv1, bg_col, tint_col); } + inline void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) { imgui_function_table_instance()->Image(user_texture_id, image_size, uv0, uv1, tint_col, border_col); } + inline bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) { return imgui_function_table_instance()->ImageButton(str_id, user_texture_id, image_size, uv0, uv1, bg_col, tint_col); } inline bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) { return imgui_function_table_instance()->BeginCombo(label, preview_value, flags); } inline void EndCombo() { imgui_function_table_instance()->EndCombo(); } inline bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items) { return imgui_function_table_instance()->Combo(label, current_item, items, items_count, popup_max_height_in_items); } inline bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items) { return imgui_function_table_instance()->Combo2(label, current_item, items_separated_by_zeros, popup_max_height_in_items); } - inline bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items) { return imgui_function_table_instance()->Combo3(label, current_item, items_getter, data, items_count, popup_max_height_in_items); } + inline bool Combo(const char* label, int* current_item, const char*(*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items) { return imgui_function_table_instance()->Combo3(label, current_item, getter, user_data, items_count, popup_max_height_in_items); } inline bool DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return imgui_function_table_instance()->DragFloat(label, v, v_speed, v_min, v_max, format, flags); } inline bool DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return imgui_function_table_instance()->DragFloat2(label, v, v_speed, v_min, v_max, format, flags); } inline bool DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return imgui_function_table_instance()->DragFloat3(label, v, v_speed, v_min, v_max, format, flags); } @@ -645,7 +647,7 @@ namespace ImGui inline bool BeginListBox(const char* label, const ImVec2& size) { return imgui_function_table_instance()->BeginListBox(label, size); } inline void EndListBox() { imgui_function_table_instance()->EndListBox(); } inline bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items) { return imgui_function_table_instance()->ListBox(label, current_item, items, items_count, height_in_items); } - inline bool ListBox(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items) { return imgui_function_table_instance()->ListBox2(label, current_item, items_getter, data, items_count, height_in_items); } + inline bool ListBox(const char* label, int* current_item, const char*(*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items) { return imgui_function_table_instance()->ListBox2(label, current_item, getter, user_data, items_count, height_in_items); } inline void PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) { imgui_function_table_instance()->PlotLines(label, values, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, stride); } inline void PlotLines(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) { imgui_function_table_instance()->PlotLines2(label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } inline void PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) { imgui_function_table_instance()->PlotHistogram(label, values, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, stride); } @@ -687,8 +689,9 @@ namespace ImGui inline bool TableSetColumnIndex(int column_n) { return imgui_function_table_instance()->TableSetColumnIndex(column_n); } inline void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) { imgui_function_table_instance()->TableSetupColumn(label, flags, init_width_or_weight, user_id); } inline void TableSetupScrollFreeze(int cols, int rows) { imgui_function_table_instance()->TableSetupScrollFreeze(cols, rows); } - inline void TableHeadersRow() { imgui_function_table_instance()->TableHeadersRow(); } inline void TableHeader(const char* label) { imgui_function_table_instance()->TableHeader(label); } + inline void TableHeadersRow() { imgui_function_table_instance()->TableHeadersRow(); } + inline void TableAngledHeadersRow() { imgui_function_table_instance()->TableAngledHeadersRow(); } inline ImGuiTableSortSpecs* TableGetSortSpecs() { return imgui_function_table_instance()->TableGetSortSpecs(); } inline int TableGetColumnCount() { return imgui_function_table_instance()->TableGetColumnCount(); } inline int TableGetColumnIndex() { return imgui_function_table_instance()->TableGetColumnIndex(); } @@ -759,8 +762,6 @@ namespace ImGui inline const char* GetStyleColorName(ImGuiCol idx) { return imgui_function_table_instance()->GetStyleColorName(idx); } inline void SetStateStorage(ImGuiStorage* storage) { imgui_function_table_instance()->SetStateStorage(storage); } inline ImGuiStorage* GetStateStorage() { return imgui_function_table_instance()->GetStateStorage(); } - inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags) { return imgui_function_table_instance()->BeginChildFrame(id, size, flags); } - inline void EndChildFrame() { imgui_function_table_instance()->EndChildFrame(); } inline ImVec2 CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) { return imgui_function_table_instance()->CalcTextSize(text, text_end, hide_text_after_double_hash, wrap_width); } inline ImVec4 ColorConvertU32ToFloat4(ImU32 in) { return imgui_function_table_instance()->ColorConvertU32ToFloat4(in); } inline ImU32 ColorConvertFloat4ToU32(const ImVec4& in) { return imgui_function_table_instance()->ColorConvertFloat4ToU32(in); } @@ -769,6 +770,7 @@ namespace ImGui inline bool IsKeyDown(ImGuiKey key) { return imgui_function_table_instance()->IsKeyDown(key); } inline bool IsKeyPressed(ImGuiKey key, bool repeat) { return imgui_function_table_instance()->IsKeyPressed(key, repeat); } inline bool IsKeyReleased(ImGuiKey key) { return imgui_function_table_instance()->IsKeyReleased(key); } + inline bool IsKeyChordPressed(ImGuiKeyChord key_chord) { return imgui_function_table_instance()->IsKeyChordPressed(key_chord); } inline int GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float rate) { return imgui_function_table_instance()->GetKeyPressedAmount(key, repeat_delay, rate); } inline const char* GetKeyName(ImGuiKey key) { return imgui_function_table_instance()->GetKeyName(key); } inline void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard) { imgui_function_table_instance()->SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } @@ -809,14 +811,14 @@ inline int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) { return imgui inline bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) { return imgui_function_table_instance()->ImGuiStorage_GetBoolRef(this, key, default_val); } inline float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) { return imgui_function_table_instance()->ImGuiStorage_GetFloatRef(this, key, default_val); } inline void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) { return imgui_function_table_instance()->ImGuiStorage_GetVoidPtrRef(this, key, default_val); } -inline void ImGuiStorage::SetAllInt(int val) { imgui_function_table_instance()->ImGuiStorage_SetAllInt(this, val); } inline void ImGuiStorage::BuildSortByKey() { imgui_function_table_instance()->ImGuiStorage_BuildSortByKey(this); } +inline void ImGuiStorage::SetAllInt(int val) { imgui_function_table_instance()->ImGuiStorage_SetAllInt(this, val); } inline ImGuiListClipper::ImGuiListClipper() { imgui_function_table_instance()->ConstructImGuiListClipper(this); } inline ImGuiListClipper::~ImGuiListClipper() { imgui_function_table_instance()->DestructImGuiListClipper(this); } inline void ImGuiListClipper::Begin(int items_count, float items_height) { imgui_function_table_instance()->ImGuiListClipper_Begin(this, items_count, items_height); } inline void ImGuiListClipper::End() { imgui_function_table_instance()->ImGuiListClipper_End(this); } inline bool ImGuiListClipper::Step() { return imgui_function_table_instance()->ImGuiListClipper_Step(this); } -inline void ImGuiListClipper::IncludeRangeByIndices(int item_begin, int item_end) { imgui_function_table_instance()->ImGuiListClipper_IncludeRangeByIndices(this, item_begin, item_end); } +inline void ImGuiListClipper::IncludeItemsByIndex(int item_begin, int item_end) { imgui_function_table_instance()->ImGuiListClipper_IncludeItemsByIndex(this, item_begin, item_end); } inline void ImDrawList::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) { imgui_function_table_instance()->ImDrawList_PushClipRect(this, clip_rect_min, clip_rect_max, intersect_with_current_clip_rect); } inline void ImDrawList::PushClipRectFullScreen() { imgui_function_table_instance()->ImDrawList_PushClipRectFullScreen(this); } inline void ImDrawList::PopClipRect() { imgui_function_table_instance()->ImDrawList_PopClipRect(this); } @@ -834,6 +836,8 @@ inline void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, inline void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { imgui_function_table_instance()->ImDrawList_AddCircleFilled(this, center, radius, col, num_segments); } inline void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) { imgui_function_table_instance()->ImDrawList_AddNgon(this, center, radius, col, num_segments, thickness); } inline void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { imgui_function_table_instance()->ImDrawList_AddNgonFilled(this, center, radius, col, num_segments); } +inline void ImDrawList::AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments, float thickness) { imgui_function_table_instance()->ImDrawList_AddEllipse(this, center, radius_x, radius_y, col, rot, num_segments, thickness); } +inline void ImDrawList::AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments) { imgui_function_table_instance()->ImDrawList_AddEllipseFilled(this, center, radius_x, radius_y, col, rot, num_segments); } inline void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) { imgui_function_table_instance()->ImDrawList_AddText(this, pos, col, text_begin, text_end); } inline void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) { imgui_function_table_instance()->ImDrawList_AddText2(this, font, font_size, pos, col, text_begin, text_end, wrap_width, cpu_fine_clip_rect); } inline void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) { imgui_function_table_instance()->ImDrawList_AddPolyline(this, points, num_points, col, flags, thickness); } @@ -845,6 +849,7 @@ inline void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& inline void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags) { imgui_function_table_instance()->ImDrawList_AddImageRounded(this, user_texture_id, p_min, p_max, uv_min, uv_max, col, rounding, flags); } inline void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments) { imgui_function_table_instance()->ImDrawList_PathArcTo(this, center, radius, a_min, a_max, num_segments); } inline void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12) { imgui_function_table_instance()->ImDrawList_PathArcToFast(this, center, radius, a_min_of_12, a_max_of_12); } +inline void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments) { imgui_function_table_instance()->ImDrawList_PathEllipticalArcTo(this, center, radius_x, radius_y, rot, a_min, a_max, num_segments); } inline void ImDrawList::PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments) { imgui_function_table_instance()->ImDrawList_PathBezierCubicCurveTo(this, p2, p3, p4, num_segments); } inline void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments) { imgui_function_table_instance()->ImDrawList_PathBezierQuadraticCurveTo(this, p2, p3, num_segments); } inline void ImDrawList::PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding, ImDrawFlags flags) { imgui_function_table_instance()->ImDrawList_PathRect(this, rect_min, rect_max, rounding, flags); } @@ -869,4 +874,3 @@ inline void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& #endif #endif -#endif \ No newline at end of file diff --git a/include/SpecialK/DLL_VERSION.H b/include/SpecialK/DLL_VERSION.H index 7067ee280..ddbc27d3a 100644 --- a/include/SpecialK/DLL_VERSION.H +++ b/include/SpecialK/DLL_VERSION.H @@ -2,9 +2,9 @@ #define SK_YEAR 24 #define SK_MONTH 11 -#define SK_DATE 16 -#define SK_REV_N 3 -#define SK_REV 3 +#define SK_DATE 25 +#define SK_REV_N 0 +#define SK_REV 0 #ifndef _A2 #define _A2(a) #a diff --git a/include/SpecialK/config.h b/include/SpecialK/config.h index 824ecb0f7..8a750c75e 100644 --- a/include/SpecialK/config.h +++ b/include/SpecialK/config.h @@ -821,7 +821,7 @@ struct sk_config_t bool temporary_dwm_hdr = false; // Always turns HDR on and off for this game bool disable_virtual_vbi = true; // Disable Windows 11 Dynamic Refresh Rate bool ignore_thread_flags = false; // Remove threading flags from D3D11 devices - bool clear_flipped_chain = true; // Clear buffers on present? (non-compliant) + bool clear_flipped_chain = false; // Clear buffers on present? (non-compliant) float chain_clear_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; bool suppress_resize_fail = true; // Workaround DLSS FrameGen compat. issues in D3D12 bool suppress_rtv_mismatch= false; // Hide SwapChain RTV format warnings for buggy games @@ -1280,6 +1280,11 @@ struct sk_config_t int use_joystick_thread = -1; int poll_sentinel = -1; } sdl; + // Messages that SK may post to a game's + // window in order to trigger various + // window management responsibilities. + bool allow_fake_displaychange = true; + bool allow_fake_size = true; } compatibility; struct apis_s { @@ -1731,6 +1736,8 @@ enum class SK_GAME_ID MonsterHunterWilds, // MonsterHunterWilds{Beta}.exe DragonAgeTheVeilguard, // Dragon Age The Veilguard.exe TombRaider123Remastered, // tomb123.exe + Stalker2, // Stalker2-WinGDK-Shipping.exe (Microsoft Store) Stalker2-Win64-Shipping.exe (Steam) + vlc, // vlc.exe UNKNOWN_GAME = 0xffff }; diff --git a/include/SpecialK/diagnostics/debug_utils.h b/include/SpecialK/diagnostics/debug_utils.h index eaefcb6f5..dbf25737f 100644 --- a/include/SpecialK/diagnostics/debug_utils.h +++ b/include/SpecialK/diagnostics/debug_utils.h @@ -23,6 +23,7 @@ #define __SK__DEBUG_UTILS_H__ #include +#include #include #include @@ -879,4 +880,38 @@ bool SK_Process_Resume (DWORD dwPid); void WINAPI SK_OutputDebugStringW (LPCWSTR lpOutputString); void WINAPI SK_OutputDebugStringA (LPCSTR lpOutputString); +using SetLastError_pfn = void (WINAPI *)(_In_ DWORD dwErrCode); +using GetProcAddress_pfn = FARPROC (WINAPI *)(HMODULE,LPCSTR); +using CloseHandle_pfn = BOOL (WINAPI *)(HANDLE); + +using GetCommandLineW_pfn = LPWSTR (WINAPI *)(void); +using GetCommandLineA_pfn = LPSTR (WINAPI *)(void); +using TerminateThread_pfn = BOOL (WINAPI *)( _In_ HANDLE hThread, + _In_ DWORD dwExitCode ); + using ExitThread_pfn = VOID (WINAPI *)(_In_ DWORD dwExitCode); +using _endthreadex_pfn = void (__cdecl *)( _In_ unsigned _ReturnCode ); +using NtTerminateProcess_pfn = NTSTATUS (*)(HANDLE, NTSTATUS); +using RtlExitUserThread_pfn = VOID (NTAPI *)(_In_ NTSTATUS Status); +using SHGetKnownFolderPath_pfn = HRESULT (WINAPI *)(REFKNOWNFOLDERID,DWORD,HANDLE,PWSTR*); + +extern SHGetKnownFolderPath_pfn SHGetKnownFolderPath_Original; + +extern GetCommandLineW_pfn GetCommandLineW_Original; +extern GetCommandLineA_pfn GetCommandLineA_Original; + +extern NtTerminateProcess_pfn NtTerminateProcess_Original; +extern RtlExitUserThread_pfn RtlExitUserThread_Original; +extern ExitThread_pfn ExitThread_Original; +extern _endthreadex_pfn _endthreadex_Original; +extern TerminateThread_pfn TerminateThread_Original; + +extern RaiseException_pfn RaiseException_Original; +extern SetLastError_pfn SetLastError_Original; +extern GetProcAddress_pfn GetProcAddress_Original; +extern TerminateProcess_pfn TerminateProcess_Original; +extern ExitProcess_pfn ExitProcess_Original; +extern OutputDebugStringA_pfn OutputDebugStringA_Original; +extern OutputDebugStringW_pfn OutputDebugStringW_Original; +extern CloseHandle_pfn CloseHandle_Original; + #endif /* __SK__DEBUG_UTILS_H__ */ diff --git a/include/SpecialK/diagnostics/memory.h b/include/SpecialK/diagnostics/memory.h index 8accc8221..47991749c 100644 --- a/include/SpecialK/diagnostics/memory.h +++ b/include/SpecialK/diagnostics/memory.h @@ -1,4 +1,4 @@ -/** +/** * This file is part of Special K. * * Special K is free software : you can redistribute it @@ -82,7 +82,7 @@ typedef BOOL (WINAPI *HeapFree_pfn)( extern VirtualAlloc_pfn VirtualAlloc_Original; extern VirtualFree_pfn VirtualFree_Original; - extern RtlAllocateHeap_pfn RtlAllocaeHeap_Original; + extern RtlAllocateHeap_pfn RtlAllocateHeap_Original; extern HeapFree_pfn HeapFree_Original; diff --git a/include/SpecialK/input/input.h b/include/SpecialK/input/input.h index ea1190f57..ce84fa67f 100644 --- a/include/SpecialK/input/input.h +++ b/include/SpecialK/input/input.h @@ -46,6 +46,8 @@ extern int64_t SK_PerfFreq; bool SK_ImGui_WantGamepadCapture (bool update = false); bool SK_ImGui_WantHWCursor (void); bool SK_ImGui_WantMouseCapture (bool update = false); +bool SK_ImGui_WantMouseButtonCapture + (void); bool SK_ImGui_WantMouseCaptureEx (DWORD dwReasonMask = 0xFFFF); bool SK_ImGui_WantKeyboardCapture (bool update = false); bool SK_ImGui_WantTextCapture (void); @@ -105,25 +107,26 @@ enum class sk_cursor_state { struct sk_imgui_cursor_s { - HWND child_input = HWND_DESKTOP; - RECT child_client = { 0, 0, 0, 0 }; - RECT child_rect = { 0, 0, 0, 0 }; - - HCURSOR real_img = nullptr; - POINT orig_pos = { 0, 0 }; - bool orig_vis = false; - - HCURSOR img = nullptr; - POINT pos = { 0, 0 }; - - bool visible = false; - bool idle = true; // Hasn't moved - DWORD last_move = MAXDWORD; - DWORD last_toggle = 0; - DWORD refs_added = 0; - DWORD64 times_set = 0; // Times the game has set a non-zero cursor - - sk_cursor_state force = sk_cursor_state::None; + HWND child_input = HWND_DESKTOP; + RECT child_client = { 0, 0, 0, 0 }; + RECT child_rect = { 0, 0, 0, 0 }; + + HCURSOR real_img = nullptr; + POINT orig_pos = { 0, 0 }; + bool orig_vis = false; + + HCURSOR img = nullptr; + POINT pos = { 0, 0 }; + + bool visible = false; + bool idle = true; // Hasn't moved + DWORD last_move = MAXDWORD; + DWORD last_toggle = 0; + DWORD refs_added = 0; + POINT last_screen_pos = { 0, 0 }; + DWORD64 times_set = 0; // Times the game has set a non-zero cursor + + sk_cursor_state force = sk_cursor_state::None; void showSystemCursor (bool system = true); void showImGuiCursor (void); diff --git a/include/SpecialK/plugin/reshade.h b/include/SpecialK/plugin/reshade.h index 71659021e..b1318dd0e 100644 --- a/include/SpecialK/plugin/reshade.h +++ b/include/SpecialK/plugin/reshade.h @@ -27,6 +27,7 @@ #include #include <../depends/include/ReShade/reshade_api.hpp> +#include <../depends/include/ReShade/reshade_api_display.hpp> #include <../depends/include/DirectXTex/DirectXTex.h> HMODULE diff --git a/include/SpecialK/render/backend.h b/include/SpecialK/render/backend.h index 7db8a32ad..d0063aeb6 100644 --- a/include/SpecialK/render/backend.h +++ b/include/SpecialK/render/backend.h @@ -570,6 +570,7 @@ class SK_RenderBackend_V2 : public SK_RenderBackend_V1 bool unreal = false; bool capcom = false; bool sdl = false; + bool atlus = false; void setFocus (HWND hWndFocus); void setDevice (HWND hWndRender); diff --git a/include/SpecialK/render/d3d11/d3d11_core.h b/include/SpecialK/render/d3d11/d3d11_core.h index 4ef168053..e6c4797b9 100644 --- a/include/SpecialK/render/d3d11/d3d11_core.h +++ b/include/SpecialK/render/d3d11/d3d11_core.h @@ -136,7 +136,8 @@ class SK_D3D11_HookTallyWhacker const bool bIsDevCtxDeferred = \ SK_D3D11_IsDevCtxDeferred (pDevCtx); \ \ - if (! bIsDevCtxDeferred) \ + std::ignore = bIsDevCtxDeferred; \ + if (true)/*! bIsDevCtxDeferred)*/ \ { \ call_tally.hooked ( bWrapped ? 0 : 1 ); \ call_tally.wrapped ( bWrapped ? 1 : 0 ); \ diff --git a/include/SpecialK/stdafx.h b/include/SpecialK/stdafx.h index 694d47427..181b9ec2a 100644 --- a/include/SpecialK/stdafx.h +++ b/include/SpecialK/stdafx.h @@ -16648,4 +16648,6 @@ extern const char* SK_VersionStrA; #include -#pragma warning ( disable : 4652 ) \ No newline at end of file +#pragma warning ( disable : 4652 ) + +#define RESHADE_NO_IMGUI \ No newline at end of file diff --git a/include/SpecialK/window.h b/include/SpecialK/window.h index de8557f91..65692550d 100644 --- a/include/SpecialK/window.h +++ b/include/SpecialK/window.h @@ -398,7 +398,7 @@ struct sk_window_s { bool active = true; - struct { + struct cursor_s { bool inside = true; bool tracking = false; bool can_track = false; // Able to use TrackMouseEvent? @@ -455,6 +455,7 @@ struct sk_window_s { LONG game_x = 640; // Resolution game thinks it's running at LONG game_y = 480; // Resolution game thinks it's running at + BOOL size_move = FALSE; RECT cursor_clip { LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX }; @@ -475,6 +476,7 @@ struct sk_window_s { bool needsCoordTransform (void); void updateDims (void); + bool isCursorHovering (void); SetWindowLongPtr_pfn SetWindowLongPtr = SK_SetWindowLongPtrW; GetWindowLongPtr_pfn GetWindowLongPtr = SK_GetWindowLongPtrW; diff --git a/include/imgui/imgui_user.inl b/include/imgui/imgui_user.inl index e390459ff..b90421d88 100644 --- a/include/imgui/imgui_user.inl +++ b/include/imgui/imgui_user.inl @@ -383,14 +383,16 @@ SK_ImGui_ProcessRawInput ( _In_ HRAWINPUT hRawInput, { case RIM_TYPEMOUSE: { - if (SK_ImGui_WantMouseCapture ()) + //// Block mouse input to the game while it's in the background + if ((! foreground) && config.input.mouse.disabled_to_game == 2) { filter = true; } - // Block mouse input to the game while it's in the background - if (SK_WantBackgroundRender () && (! focus)) + else if (SK_ImGui_WantMouseCapture ()) + { filter = true; + } mouse = true; @@ -415,62 +417,59 @@ SK_ImGui_ProcessRawInput ( _In_ HRAWINPUT hRawInput, (((RAWINPUT *)pData)->data.keyboard.VKey & 0xFF); - // Only filter keydown message, not key releases - if (SK_ImGui_WantKeyboardCapture ()) + if (VKey & 0xF8) // Valid Keys: 8 - 255 { - if (VKey & 0xF8) // Valid Keys: 8 - 255 - filter = true; + keyboard = true; } - - if (SK_ImGui_WantMouseCapture ()) + // That's actually a mouse button... + else if (VKey < 7) { - // That's actually a mouse button... - if (foreground && VKey < 7) - { - if (((RAWINPUT *)pData)->data.keyboard.Message == WM_KEYDOWN) - filter = true; + mouse = true; - if (((RAWINPUT *)pData)->data.keyboard.Message == WM_SYSKEYDOWN) - filter = true; - - if (((RAWINPUT *)pData)->data.keyboard.Message == WM_KEYUP) - filter = true; - - if (((RAWINPUT *)pData)->data.keyboard.Message == WM_SYSKEYUP) - filter = true; + if (((! foreground) && config.input.mouse.disabled_to_game == 2) || SK_ImGui_WantMouseCapture ()) + { + switch (((RAWINPUT *)pData)->data.keyboard.Message) + { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + filter = true; + break; + } } } + if (keyboard) + { + // Block keyboard input to the game while the console is active + if (pConsole->isVisible ()) + filter = true; - // Block keyboard input to the game while the console is active - if (pConsole->isVisible () && (VKey & 0xFF) > 7) - filter = true; - - - // Block keyboard input to the game while it's in the background - if (SK_WantBackgroundRender () && (! focus)) - filter = true; - - - if (VKey & 0xF8) // Valid Keys: 8 - 255 - keyboard = true; + // Block keyboard input to the game while it does not have keyboard focus + else if ((! focus)) + filter = true; - if (keyboard && ( SK_ImGui_WantKeyboardCapture () || - (((RAWINPUT *)pData)->data.keyboard.Message == WM_CHAR || - ((RAWINPUT *)pData)->data.keyboard.Message == WM_SYSCHAR) )) - filter = true; + else if ( SK_ImGui_WantKeyboardCapture () || + (((RAWINPUT *)pData)->data.keyboard.Message == WM_CHAR || + ((RAWINPUT *)pData)->data.keyboard.Message == WM_SYSCHAR) ) + filter = true; + } if ( (! already_processed) && uiCommand == RID_INPUT ) { + const auto type = + (keyboard ? sk_input_dev_type::Keyboard : sk_input_dev_type::Mouse); + if (! filter) { - SK_RAWINPUT_READ (sk_input_dev_type::Keyboard) - SK_RAWINPUT_VIEW (sk_input_dev_type::Keyboard) + SK_RAWINPUT_READ (type) + SK_RAWINPUT_VIEW (type) } - else SK_RAWINPUT_HIDE (sk_input_dev_type::Keyboard) + else SK_RAWINPUT_HIDE (type) } } break; @@ -514,23 +513,39 @@ SK_ImGui_ProcessRawInput ( _In_ HRAWINPUT hRawInput, if (self) { if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN ) - io.MouseDown [0] = true; + io.AddMouseButtonEvent (ImGuiKey_MouseLeft, true); + //if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_UP ) + // io.AddMouseButtonEvent (ImGuiKey_MouseLeft, false); if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_RIGHT_BUTTON_DOWN ) - io.MouseDown [1] = true; + io.AddMouseButtonEvent (ImGuiKey_MouseRight, true); + //if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_RIGHT_BUTTON_UP ) + // io.AddMouseButtonEvent (ImGuiKey_MouseRight, false); if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_MIDDLE_BUTTON_DOWN ) - io.MouseDown [2] = true; + io.AddMouseButtonEvent (ImGuiKey_MouseMiddle, true); + //if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_MIDDLE_BUTTON_UP ) + // io.AddMouseButtonEvent (ImGuiKey_MouseMiddle, false); if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_BUTTON_4_DOWN ) - io.MouseDown [3] = true; + io.AddMouseButtonEvent (ImGuiKey_MouseX1, true); + //if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_BUTTON_4_UP ) + // io.AddMouseButtonEvent (ImGuiKey_MouseX1, false); if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_BUTTON_5_DOWN ) - io.MouseDown [4] = true; - } + io.AddMouseButtonEvent (ImGuiKey_MouseX2, true); + //if ( ((RAWINPUT *)pData)->data.mouse.ulButtons & RI_MOUSE_BUTTON_5_UP ) + // io.AddMouseButtonEvent (ImGuiKey_MouseX2, false); - if ( ((RAWINPUT *)pData)->data.mouse.usButtonFlags == RI_MOUSE_WHEEL && self ) - { - io.MouseWheel += - ((float)(short)((RAWINPUT *)pData)->data.mouse.usButtonData) / - (float)WHEEL_DELTA; + if ( ((RAWINPUT *)pData)->data.mouse.usButtonFlags & RI_MOUSE_WHEEL ) + { + io.AddMouseWheelEvent (0.0f, + ((float)(short)((RAWINPUT *)pData)->data.mouse.usButtonData) / + (float)WHEEL_DELTA); + } + if ( ((RAWINPUT *)pData)->data.mouse.usButtonFlags & RI_MOUSE_HWHEEL ) + { + io.AddMouseWheelEvent ( + ((float)(short)((RAWINPUT *)pData)->data.mouse.usButtonData) / + (float)WHEEL_DELTA, 0.0f); + } } } } break; @@ -1047,6 +1062,15 @@ ImGui_WndProcHandler ( HWND hWnd, UINT msg, } } + if (msg == WM_ENTERSIZEMOVE || msg == WM_EXITSIZEMOVE) + { + if (hWnd == game_window.hWnd) + { + game_window.size_move = (msg == WM_ENTERSIZEMOVE); + SK_Window_RepositionIfNeeded (); + } + } + if (msg == WM_SETCURSOR) { //SK_LOG0 ( (L"ImGui Witnessed WM_SETCURSOR"), L"Window Mgr" ); @@ -2895,11 +2919,13 @@ SK_ImGui_FallbackTrackMouseEvent (POINT& cursor_pos) else { - last.hWndTop = game_window.hWnd; - last.cursor_pos = cursor_pos; + last.hWndTop = game_window.hWnd; } + + if (last.hWndTop == game_window.hWnd) + last.cursor_pos = cursor_pos; } - + hWndTop = last.hWndTop; @@ -3358,8 +3384,18 @@ SK_ImGui_User_NewFrame (void) hWndFocus : hWndGame != hWndFocus ? hWndGame : nullptr; + static POINT last_cursor_pos; + static bool last_fg_or_top; + bool bMouseIsForegroundOrTop = ( hWndForeground == hWndMouse0 || hWndForeground == hWndMouse1 ); + + if (std::exchange(last_cursor_pos.x,cursor_pos.x) == cursor_pos.x&& + std::exchange(last_cursor_pos.y,cursor_pos.y) == cursor_pos.y) + { + bMouseIsForegroundOrTop = last_fg_or_top; + } + if (! bMouseIsForegroundOrTop) { const HWND hWndAtCursor = @@ -3370,6 +3406,8 @@ SK_ImGui_User_NewFrame (void) hWndAtCursor == hWndMouse1 ); } + last_fg_or_top = bMouseIsForegroundOrTop; + if (bMouseIsForegroundOrTop) { SK_ImGui_Cursor.ScreenToLocal (&cursor_pos); @@ -3377,8 +3415,8 @@ SK_ImGui_User_NewFrame (void) if ( cursor_pos.x != last_x || cursor_pos.y != last_y ) { - if ( abs (SK_ImGui_Cursor.pos.x - cursor_pos.x) > 3 || - abs (SK_ImGui_Cursor.pos.y - cursor_pos.y) > 3 ) + if ( abs (SK_ImGui_Cursor.pos.x - cursor_pos.x) > 0 || + abs (SK_ImGui_Cursor.pos.y - cursor_pos.y) > 0 ) { SK_ImGui_Cursor.pos = cursor_pos; } @@ -3391,6 +3429,11 @@ SK_ImGui_User_NewFrame (void) io.MousePos.y = static_cast (SK_ImGui_Cursor.pos.y); } } + + else + { + game_window.mouse.inside = false; + } } // Cursor stops being treated as idle when it's not in the game window :) @@ -3445,8 +3488,8 @@ SK_ImGui_User_NewFrame (void) // regular mouse capture includes swallowing input for "Disabled to Game". bool bWantMouseCaptureForUI = SK_ImGui_WantMouseCaptureEx (0x0) && (anything_hovered || ImGui::IsPopupOpen (nullptr, ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel)); - if ( abs (last_x - SK_ImGui_Cursor.pos.x) > 3 || - abs (last_y - SK_ImGui_Cursor.pos.y) > 3 || + if ( abs (last_x - SK_ImGui_Cursor.pos.x) > 0 || + abs (last_y - SK_ImGui_Cursor.pos.y) > 0 || bWantMouseCaptureForUI ) { SK_ImGui_Cursor.last_move = SK::ControlPanel::current_time; @@ -3526,7 +3569,7 @@ SK_ImGui_User_NewFrame (void) if (! SK_ImGui_Cursor.idle) { - if (capture_mouse && anything_hovered) + if (capture_mouse && anything_hovered && (last_x != SK_ImGui_Cursor.pos.x || last_y != SK_ImGui_Cursor.pos.y)) { SK_SendMsgSetCursor (ImGui_DesiredCursor ()); } @@ -3678,6 +3721,9 @@ SK_ImGui_User_NewFrame (void) SK_ImGui_WantMouseCapture (true); SK_ImGui_WantGamepadCapture (true); SK_IsGameWindowActive (true); + + SK_GetCursorPos (&cursor_pos); + SK_ImGui_Cursor.last_screen_pos = cursor_pos; } bool diff --git a/src/SpecialK.cpp b/src/SpecialK.cpp index d7f1e9271..8b8f0d041 100644 --- a/src/SpecialK.cpp +++ b/src/SpecialK.cpp @@ -592,6 +592,7 @@ DllMain ( HMODULE hModule, if (DLL_ROLE::INVALID == SK_GetDLLRole ()) return EarlyOut (TRUE); if (! SK_Attach (SK_GetDLLRole ())) return EarlyOut (TRUE); + SK_MinHook_Init (); CreateTeardownEvent (); InterlockedIncrementRelease ( diff --git a/src/config.cpp b/src/config.cpp index 3887bb593..03d1f6e38 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -267,7 +267,10 @@ SK_GetCurrentGameID (void) { L"MonsterHunterWilds.exe", SK_GAME_ID::MonsterHunterWilds }, { L"MonsterHunterWildsBeta.exe", SK_GAME_ID::MonsterHunterWilds }, { L"Dragon Age The Veilguard.exe", SK_GAME_ID::DragonAgeTheVeilguard }, - { L"tomb123.exe", SK_GAME_ID::TombRaider123Remastered } + { L"tomb123.exe", SK_GAME_ID::TombRaider123Remastered }, + { L"Stalker2-WinGDK-Shipping.exe", SK_GAME_ID::Stalker2 }, + { L"Stalker2-Win64-Shipping.exe", SK_GAME_ID::Stalker2 }, + { L"vlc.exe", SK_GAME_ID::vlc } }; first_check = false; @@ -3695,7 +3698,13 @@ auto DeclKeybind = config.render.dxgi.srgb_behavior = 0; break; + case SK_GAME_ID::Stalker2: + // Stupid game requires Fullscreen Exclusive (in D3D12) for HDR + config.render.dxgi.fake_fullscreen_mode = true; + break; + case SK_GAME_ID::Metaphor: + config.threads.enable_dynamic_spinlocks = true; config.compatibility.init_on_separate_thread = false; config.priority.perf_cores_only = true; config.window.background_render = true; diff --git a/src/control_panel.cpp b/src/control_panel.cpp index 2afc27fff..349fed183 100644 --- a/src/control_panel.cpp +++ b/src/control_panel.cpp @@ -867,61 +867,12 @@ SK_ImGui_ControlPanelTitle (void) void SK_ImGui_AdjustCursor (void) { -#if 0 - static SK_AutoHandle hAdjustEvent ( - SK_CreateEvent (nullptr, TRUE, FALSE, nullptr) - ); - - SetEvent (hAdjustEvent.m_h); - - static HANDLE - hThread = SK_Thread_CreateEx ( - [](LPVOID pUser)-> DWORD - { - HANDLE hSignals [] = { - __SK_DLL_TeardownEvent, - (HANDLE)pUser - }; - - DWORD dwWaitStatus = - WAIT_ABANDONED; - - while (dwWaitStatus != WAIT_OBJECT_0) - { - dwWaitStatus = - WaitForMultipleObjects ( 2, hSignals, FALSE, INFINITE ); - - if (dwWaitStatus == (WAIT_OBJECT_0 + 1)) - { - ResetEvent (hSignals [1]); - - //SK_ClipCursor (nullptr); - // SK_AdjustWindow (); // Restore game's clip cursor behavior - - SK_Window_RepositionIfNeeded (); - - //extern void SK_AdjustClipRect (void); - // SK_AdjustClipRect (); - } - }; - - hAdjustEvent.Close (); - - SK_Thread_CloseSelf (); - - return 0; - }, - L"[SK] Cursor Adjustment Thread", - (LPVOID)hAdjustEvent.m_h - ); -#else // This really doesn't need to be done in a second thread, it's already // got a thread that waits for signaled work. SK_Window_RepositionIfNeeded (); // The logic used to be different, but now RepositionIfNeeded also handles // any necessary changes to the cursor clipping rectangle. -#endif } bool reset_frame_history = true; @@ -1177,7 +1128,7 @@ SK_Display_ResolutionSelectUI (bool bMarkDirty) for ( auto& display : rb.displays ) { - if (display.attached) + //if (display.attached) { outputs.push_back ( sk::narrow_cast @@ -1200,12 +1151,16 @@ SK_Display_ResolutionSelectUI (bool bMarkDirty) } } - display_list += + auto utf8_name = SK_WideCharToUTF8 ( - rb.displays [output].name - ); + rb.displays [output].name + ); - display_list += '\0'; + if (*utf8_name.c_str () != '\0') + { + display_list += utf8_name.c_str (); + display_list += '\0'; + } } // Give it another go, the monitor was no-show... @@ -2247,9 +2202,11 @@ SK_Display_ResolutionSelectUI (bool bMarkDirty) { // Trigger the game to resize the SwapChain so we can change its aspect ratio // + if (config.compatibility.allow_fake_size) PostMessage ( game_window.hWnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM (config.window.res.override.x, config.window.res.override.y) ); + if (config.compatibility.allow_fake_displaychange) PostMessage ( game_window.hWnd, WM_DISPLAYCHANGE, 32, MAKELPARAM (config.window.res.override.x, config.window.res.override.y) ); @@ -2373,11 +2330,13 @@ DisplayModeMenu (bool windowed) // Trigger the game to resize the SwapChain so we can change its format and colorspace // + if (config.compatibility.allow_fake_size) PostMessage ( game_window.hWnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM (game_window.actual.client.right - game_window.actual.client.left, game_window.actual.client.bottom - game_window.actual.client.top ) ); + if (config.compatibility.allow_fake_displaychange) PostMessage ( game_window.hWnd, WM_DISPLAYCHANGE, 32, MAKELPARAM (game_window.actual.client.right - game_window.actual.client.left, game_window.actual.client.bottom - @@ -7665,7 +7624,7 @@ LRESULT CALLBACK SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) { - if (code < 0 || (! SK_IsGameWindowActive ())) // We saw nothing (!!) + if (code < 0 || GImGui == nullptr || GImGui->CurrentWindow == nullptr) // We saw nothing (!!) return CallNextHookEx (0, code, wParam, lParam); auto& io = @@ -7703,12 +7662,12 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) case WM_LBUTTONDBLCLK: if (! bPassthrough) { - io.MouseDown [0] = true; + io.AddMouseButtonEvent (ImGuiKey_MouseLeft, true); // Only capture mouse clicks when the window is in the foreground, failure to let // left-clicks passthrough would prevent activating the game window. - if ( SK_ImGui_WantMouseCapture () && game_window.active && - SK_GetForegroundWindow () == game_window.hWnd ) + if ( game_window.active && SK_ImGui_WantMouseButtonCapture () && + game_window.hWnd == SK_GetForegroundWindow () ) return 1; } break; @@ -7716,7 +7675,9 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) case WM_LBUTTONUP: if (! bPassthrough) { - if (SK_ImGui_WantMouseCapture ()) + //io.AddMouseButtonEvent (ImGuiKey_MouseLeft, false); + + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; @@ -7725,9 +7686,9 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) case WM_RBUTTONDBLCLK: if (! bPassthrough) { - io.MouseDown [1] = true; + io.AddMouseButtonEvent (ImGuiKey_MouseRight, true); - if (SK_ImGui_WantMouseCapture ()) + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; @@ -7735,7 +7696,9 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) case WM_RBUTTONUP: if (! bPassthrough) { - if (SK_ImGui_WantMouseCapture ()) + //io.AddMouseButtonEvent (ImGuiKey_MouseRight, false); + + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; @@ -7744,9 +7707,9 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) case WM_MBUTTONDBLCLK: if (! bPassthrough) { - io.MouseDown [2] = true; + io.AddMouseButtonEvent (ImGuiKey_MouseMiddle, true); - if (SK_ImGui_WantMouseCapture ()) + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; @@ -7754,7 +7717,9 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) case WM_MBUTTONUP: if (! bPassthrough) { - if (SK_ImGui_WantMouseCapture ()) + //io.AddMouseButtonEvent (ImGuiKey_MouseMiddle, false); + + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; @@ -7766,17 +7731,27 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) MOUSEHOOKSTRUCTEX* mhsx = (MOUSEHOOKSTRUCTEX*)lParam; - io.MouseDown [3] |= ((HIWORD (mhsx->mouseData)) == XBUTTON1); - io.MouseDown [4] |= ((HIWORD (mhsx->mouseData)) == XBUTTON2); + if (((HIWORD (mhsx->mouseData)) == XBUTTON1)) + io.AddMouseButtonEvent (ImGuiKey_MouseX1, true); + if (((HIWORD (mhsx->mouseData)) == XBUTTON2)) + io.AddMouseButtonEvent (ImGuiKey_MouseX2, true); - if (SK_ImGui_WantMouseCapture ()) + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; case WM_XBUTTONUP: if (! bPassthrough) { - if (SK_ImGui_WantMouseCapture ()) + // MOUSEHOOKSTRUCTEX* mhsx = + //(MOUSEHOOKSTRUCTEX*)lParam; + + //if (((HIWORD (mhsx->mouseData)) == XBUTTON1)) + // io.AddMouseButtonEvent (ImGuiKey_MouseX1, false); + //if (((HIWORD (mhsx->mouseData)) == XBUTTON2)) + // io.AddMouseButtonEvent (ImGuiKey_MouseX2, false); + + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; @@ -7789,18 +7764,18 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) if (wParam == WM_MOUSEWHEEL) { - io.MouseWheel += + io.AddMouseWheelEvent (0.0f, (float)GET_WHEEL_DELTA_WPARAM (mhsx->mouseData) / - (float)WHEEL_DELTA; + (float)WHEEL_DELTA); } else { - io.MouseWheelH += + io.AddMouseWheelEvent ( (float)GET_WHEEL_DELTA_WPARAM (mhsx->mouseData) / - (float)WHEEL_DELTA; + (float)WHEEL_DELTA, 0.0f); } - if (SK_ImGui_WantMouseCapture ()) + if (SK_ImGui_WantMouseButtonCapture ()) return 1; } break; @@ -7812,14 +7787,20 @@ SK_ImGui_MouseProc (int code, WPARAM wParam, LPARAM lParam) { // Install a mouse tracker to get WM_MOUSELEAVE if (! (game_window.mouse.tracking && game_window.mouse.inside)) - SK_ImGui_UpdateMouseTracker (); + { + if (wParam != WM_NCMOUSEMOVE) + { + SK_ImGui_UpdateMouseTracker (); + } + } // Returning 1 here breaks WM_SETCURSOR behavior; // // Hopefully we have a subclassed window / window proc hook and // can remove mouse motion that way, because returning 1 is // not an option. - return 0; + if (wParam != WM_NCMOUSEMOVE) + return 0; } } @@ -9228,8 +9209,6 @@ SK_ImGui_Toggle (void) { SK_ImGui_Cursor.last_move = current_time; - //SK_ImGui_Cursor.showImGuiCursor (); - if (SK::ControlPanel::Platform::WarnIfUnsupported ()) config.imgui.show_eula = true; else @@ -9257,78 +9236,79 @@ SK_ImGui_Toggle (void) if (SK::SteamAPI::AppID () != 0 && SK_ImGui_Visible) SK::SteamAPI::UpdateNumPlayers (); - static SK_AutoHandle hMoveCursor ( - SK_CreateEvent (nullptr, FALSE, FALSE, nullptr) - ); - - static POINT ptCursorPos = { }; - - SK_RunOnce ( - SK_Thread_CreateEx ([](LPVOID) -> DWORD - { - HANDLE hEvents [] = { - __SK_DLL_TeardownEvent, - hMoveCursor.m_h - }; + if (config.input.ui.center_cursor) + { + static SK_AutoHandle hMoveCursor ( + SK_CreateEvent (nullptr, FALSE, FALSE, nullptr) + ); - while (true) + SK_RunOnce ( + SK_Thread_CreateEx ([](LPVOID) -> DWORD { - DWORD dwWait = - WaitForMultipleObjectsEx (2, hEvents, FALSE, INFINITE, FALSE); + SK_Thread_SetCurrentPriority (THREAD_PRIORITY_IDLE); - if (dwWait == WAIT_OBJECT_0) - break; + HANDLE hEvents [] = { + __SK_DLL_TeardownEvent, + hMoveCursor.m_h + }; - // Stupid hack to make sure the mouse cursor swaps between SK's and - // the game's in response to opening/closing the control panel - if (dwWait == WAIT_OBJECT_0 + 1) + while (true) { - auto frames_drawn = - SK_GetFramesDrawn (); + DWORD dwWait = + WaitForMultipleObjectsEx (2, hEvents, FALSE, INFINITE, FALSE); - while (frames_drawn > SK_GetFramesDrawn () - 2) - SK_Sleep (0); + if (dwWait == WAIT_OBJECT_0) + break; - POINT ptCursor; - if (SK_GetCursorPos (&ptCursor) && SK_GetForegroundWindow () == game_window.hWnd) + // Stupid hack to make sure the mouse cursor swaps between SK's and + // the game's in response to opening/closing the control panel + if (dwWait == WAIT_OBJECT_0 + 1) { - GetWindowRect (game_window.hWnd, - &game_window.actual.window); - if (PtInRect (&game_window.actual.window, ptCursor)) - { - SK_SetCursorPos (ptCursor.x + 1, ptCursor.y - 1); - Send_WM_SETCURSOR (); + auto frames_drawn = + SK_GetFramesDrawn (); - frames_drawn = - SK_GetFramesDrawn (); + while (frames_drawn > SK_GetFramesDrawn () - 2) + SwitchToThread (); - while (frames_drawn > SK_GetFramesDrawn () - 2) + POINT ptCursor; + if (SK_GetCursorPos (&ptCursor) && SK_GetForegroundWindow () == game_window.hWnd) + { + GetWindowRect (game_window.hWnd, + &game_window.actual.window); + if (PtInRect (&game_window.actual.window, ptCursor)) { - SK_Sleep (0); - } + SK_SetCursorPos (ptCursor.x + 1, ptCursor.y - 1); + Send_WM_SETCURSOR (); + + frames_drawn = + SK_GetFramesDrawn (); - SK_GetCursorPos (&ptCursor); - SK_SetCursorPos ( ptCursor.x - 1, ptCursor.y + 1); - Send_WM_SETCURSOR ( ); + while (frames_drawn > SK_GetFramesDrawn () - 2) + SwitchToThread (); + + SK_GetCursorPos (&ptCursor); + SK_SetCursorPos ( ptCursor.x - 1, ptCursor.y + 1); + Send_WM_SETCURSOR ( ); + } } } } - } - SK_Thread_CloseSelf (); + SK_Thread_CloseSelf (); - return 0; - }, L"[SK] Rodeo Mouse Wrangler"); - ); + return 0; + }, L"[SK] Rodeo Mouse Wrangler"); + ); + + // Move the cursor a couple of times to change the loaded image + if (SK_ImGui_WantHWCursor ()) + SetEvent (hMoveCursor); + } // Save config on control panel close, not open if (! SK_ImGui_Visible) config.utility.save_async (); - // Move the cursor a couple of times to change the loaded image - if (SK_ImGui_WantHWCursor ()) - SetEvent (hMoveCursor); - // Immediately stop capturing keyboard/mouse events, // this is the only way to preserve cursor visibility diff --git a/src/control_panel/cfg_input.cpp b/src/control_panel/cfg_input.cpp index 41beb9ec8..13aea3848 100644 --- a/src/control_panel/cfg_input.cpp +++ b/src/control_panel/cfg_input.cpp @@ -303,31 +303,22 @@ SK::ControlPanel::Input::Draw (void) //bool is_emulating_xinput = // steam_ctx.Input ()->GetControllerForGamepadIndex (0) != 0; - if (ImGui::IsItemHovered ( )) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip ( ); - { - ImGui::BeginGroup ( ); - if (steam.active [0]) ImGui::TextUnformatted ("Xbox"); - if (steam.active [1]) ImGui::TextUnformatted ("PlayStation"); - if (steam.active [2]) ImGui::TextUnformatted ("Generic"); - if (steam.active [3]) ImGui::TextUnformatted ("Nintendo"); - ImGui::EndGroup ( ); - ImGui::SameLine ( ); - ImGui::BeginGroup ( ); - if (steam.active [0]) ImGui::Text ("%lu", steam.reads [0]); - if (steam.active [1]) ImGui::Text ("%lu", steam.reads [1]); - if (steam.active [2]) ImGui::Text ("%lu", steam.reads [2]); - if (steam.active [3]) ImGui::Text ("%lu", steam.reads [3]); - ImGui::EndGroup ( ); - - //if (is_emulating_xinput) - //{ - // ImGui::Separator (); - // ImGui::BulletText ("Click to configure (XInput Emulation)"); - //} - } - ImGui::EndTooltip ( ); + ImGui::BeginGroup ( ); + if (steam.active [0]) ImGui::TextUnformatted ("Xbox"); + if (steam.active [1]) ImGui::TextUnformatted ("PlayStation"); + if (steam.active [2]) ImGui::TextUnformatted ("Generic"); + if (steam.active [3]) ImGui::TextUnformatted ("Nintendo"); + ImGui::EndGroup ( ); + ImGui::SameLine ( ); + ImGui::BeginGroup ( ); + if (steam.active [0]) ImGui::Text ("%lu", steam.reads [0]); + if (steam.active [1]) ImGui::Text ("%lu", steam.reads [1]); + if (steam.active [2]) ImGui::Text ("%lu", steam.reads [2]); + if (steam.active [3]) ImGui::Text ("%lu", steam.reads [3]); + ImGui::EndGroup ( ); + ImGui::EndTooltip ( ); } //if (is_emulating_xinput && ImGui::IsItemClicked ()) @@ -348,18 +339,17 @@ SK::ControlPanel::Input::Draw (void) ImGui::Text (" %s", SK_XInput_GetPrimaryHookName ()); ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - ImGui::BeginGroup (); + ImGui::BeginGroup (); for ( int i = 0 ; i < XUSER_MAX_COUNT ; ++i ) { if (xinput.reads [i] > 0) ImGui::Text ("Gamepad %d %lu", i, xinput.reads [i]); } - ImGui::EndGroup (); - ImGui::SameLine (); - ImGui::BeginGroup (); + ImGui::EndGroup (); + ImGui::SameLine (); + ImGui::BeginGroup (); for ( int i = 0 ; i < XUSER_MAX_COUNT ; ++i ) { if (xinput.reads [i] > 0) @@ -369,8 +359,8 @@ SK::ControlPanel::Input::Draw (void) " Disabled" : "" ); } } - ImGui::EndGroup (); - ImGui::EndTooltip (); + ImGui::EndGroup (); + ImGui::EndTooltip (); } } @@ -399,16 +389,15 @@ SK::ControlPanel::Input::Draw (void) SETUP_LABEL_COLOR (wgi, 500.0f); - ImGui::SameLine (); - ImGui::Text (SK_WGI_EmulatedPlayStation ? " Windows.Gaming.Input " ICON_FA_PLAYSTATION - : " Windows.Gaming.Input"); - ImGui::PopStyleColor (); + ImGui::SameLine (); + ImGui::Text (SK_WGI_EmulatedPlayStation ? " Windows.Gaming.Input " ICON_FA_PLAYSTATION + : " Windows.Gaming.Input"); + ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ( )) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip ( ); - ImGui::Text ("Gamepad %lu", wgi.reads); - ImGui::EndTooltip ( ); + ImGui::Text ("Gamepad %lu", wgi.reads); + ImGui::EndTooltip (); } } @@ -431,10 +420,8 @@ SK::ControlPanel::Input::Draw (void) ImGui::Text (" HID"); ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - if (hid.kbd_reads > 0) ImGui::Text ("Keyboard %lu", hid.kbd_reads); if (hid.mouse_reads > 0) @@ -451,16 +438,15 @@ SK::ControlPanel::Input::Draw (void) { SETUP_LABEL_COLOR (winmm, 500.0f); - ImGui::SameLine (); - ImGui::Text (" WinMM Joystick"); - ImGui::PopStyleColor (); + ImGui::SameLine (); + ImGui::Text (" WinMM Joystick"); + ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); if (winmm.reads > 0) - ImGui::Text ("Gamepad %lu", winmm.reads); - ImGui::EndTooltip (); + ImGui::Text ("Gamepad %lu", winmm.reads); + ImGui::EndTooltip (); } } @@ -475,12 +461,11 @@ SK::ControlPanel::Input::Draw (void) ImGui::Text (" NVIDIA MessageBus"); ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); if (messagebus.reads > 0) - ImGui::Text ("Gamepad %lu", messagebus.reads); - ImGui::EndTooltip (); + ImGui::Text ("Gamepad %lu", messagebus.reads); + ImGui::EndTooltip (); } } #endif @@ -490,25 +475,23 @@ SK::ControlPanel::Input::Draw (void) { SETUP_LABEL_COLOR (di7, 500.0f); - ImGui::SameLine (); - ImGui::Text (" DirectInput 7"); - ImGui::PopStyleColor (); + ImGui::SameLine (); + ImGui::Text (" DirectInput 7"); + ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - if (di7.kbd_reads > 0) { - ImGui::Text ("Keyboard %lu", di7.kbd_reads); + ImGui::Text ("Keyboard %lu", di7.kbd_reads); } if (di7.mouse_reads > 0) { - ImGui::Text ("Mouse %lu", di7.mouse_reads); + ImGui::Text ("Mouse %lu", di7.mouse_reads); } if (di7.gamepad_reads > 0) { - ImGui::Text ("Gamepad %lu", di7.gamepad_reads); + ImGui::Text ("Gamepad %lu", di7.gamepad_reads); }; - ImGui::EndTooltip (); + ImGui::EndTooltip (); } } @@ -517,25 +500,23 @@ SK::ControlPanel::Input::Draw (void) { SETUP_LABEL_COLOR (di8, 500.0f); - ImGui::SameLine (); - ImGui::Text (" DirectInput 8"); - ImGui::PopStyleColor (); + ImGui::SameLine (); + ImGui::Text (" DirectInput 8"); + ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - if (di8.kbd_reads > 0) { - ImGui::Text ("Keyboard %lu", di8.kbd_reads); + ImGui::Text ("Keyboard %lu", di8.kbd_reads); } if (di8.mouse_reads > 0) { - ImGui::Text ("Mouse %lu", di8.mouse_reads); + ImGui::Text ("Mouse %lu", di8.mouse_reads); } if (di8.gamepad_reads > 0) { - ImGui::Text ("Gamepad %lu", di8.gamepad_reads); + ImGui::Text ("Gamepad %lu", di8.gamepad_reads); }; - ImGui::EndTooltip (); + ImGui::EndTooltip (); } } @@ -548,14 +529,13 @@ SK::ControlPanel::Input::Draw (void) ImGui::Text (" Windows Hook"); ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); if (winhook.mouse_reads > 0) - ImGui::Text ("Mouse %lu", winhook.mouse_reads); + ImGui::Text ("Mouse %lu", winhook.mouse_reads); if (winhook.kbd_reads > 0) - ImGui::Text ("Keyboard %lu", winhook.kbd_reads); - ImGui::EndTooltip (); + ImGui::Text ("Keyboard %lu", winhook.kbd_reads); + ImGui::EndTooltip (); } } @@ -568,33 +548,36 @@ SK::ControlPanel::Input::Draw (void) ImGui::Text (" Win32"); ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - ImGui::BeginGroup (); + ImGui::BeginGroup (); if (win32.asynckeystate > 0) - ImGui::TextUnformatted ("GetAsyncKeyState\t"); + ImGui::TextUnformatted + ("GetAsyncKeyState\t"); if (win32.keystate > 0) - ImGui::TextUnformatted ("GetKeyState\t"); + ImGui::TextUnformatted + ("GetKeyState\t"); if (win32.keyboardstate > 0) - ImGui::TextUnformatted ("GetKeyboardState\t"); + ImGui::TextUnformatted + ("GetKeyboardState\t"); if (win32.cursorpos > 0) - ImGui::TextUnformatted ("GetCursorPos\t"); + ImGui::TextUnformatted + ("GetCursorPos\t"); - ImGui::EndGroup (); - ImGui::SameLine (); - ImGui::BeginGroup (); + ImGui::EndGroup (); + ImGui::SameLine (); + ImGui::BeginGroup (); if (win32.asynckeystate > 0) - ImGui::Text ("%lu", win32.asynckeystate); + ImGui::Text ("%lu", win32.asynckeystate); if (win32.keystate > 0) - ImGui::Text ("%lu", win32.keystate); + ImGui::Text ("%lu", win32.keystate); if (win32.keyboardstate > 0) - ImGui::Text ("%lu", win32.keyboardstate); + ImGui::Text ("%lu", win32.keyboardstate); if (win32.cursorpos > 0) ImGui::Text ("%lu", win32.cursorpos); - ImGui::EndGroup (); - ImGui::EndTooltip (); + ImGui::EndGroup (); + ImGui::EndTooltip (); } } @@ -604,25 +587,23 @@ SK::ControlPanel::Input::Draw (void) { SETUP_LABEL_COLOR (rawinput, 500.0f); - ImGui::SameLine (); - ImGui::Text (" Raw Input"); - ImGui::PopStyleColor (); + ImGui::SameLine (); + ImGui::Text (" Raw Input"); + ImGui::PopStyleColor (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - if (raw_input.kbd_reads > 0) { - ImGui::Text ("Keyboard %lu", raw_input.kbd_reads); + ImGui::Text ("Keyboard %lu", raw_input.kbd_reads); } if (raw_input.mouse_reads > 0) { - ImGui::Text ("Mouse %lu", raw_input.mouse_reads); + ImGui::Text ("Mouse %lu", raw_input.mouse_reads); } if (raw_input.gamepad_reads > 0) { - ImGui::Text ("Gamepad %lu", raw_input.gamepad_reads); + ImGui::Text ("Gamepad %lu", raw_input.gamepad_reads); } - ImGui::EndTooltip (); + ImGui::EndTooltip (); } } } @@ -634,7 +615,7 @@ SK::ControlPanel::Input::Draw (void) ImGui::PushStyleColor (ImGuiCol_HeaderActive, ImVec4 (0.87f, 0.78f, 0.14f, 0.80f)); ImGui::TreePush (""); - if (ImGui::CollapsingHeader ("Mouse Cursor")) + if (ImGui::CollapsingHeader ("Mouse")) { auto _CursorBoundaryWidget = [&]() { @@ -657,26 +638,22 @@ SK::ControlPanel::Input::Draw (void) ImVec2 vCursorWidgetPos (0.0f, 0.0f); - if (config.input.cursor.manage) { + if (config.input.cursor.manage) + { ImGui::TreePush (""); ImGui::BeginGroup ( ); - ImGui::Checkbox ( "Keyboard Activates", - &config.input.cursor.keys_activate ); -#if 1 - ImGui::Checkbox ( "Gamepad Deactivates", - &config.input.cursor.gamepad_deactivates ); - if (ImGui::IsItemHovered ()) - { - ImGui::SetTooltip ( - "Uses XInput or HID (PlayStation) to auto-hide the cursor " - "on gamepad input." - ); - } -#endif + ImGui::Checkbox ( "Keyboard Activates", + &config.input.cursor.keys_activate ); + ImGui::Checkbox ( "Gamepad Deactivates", + &config.input.cursor.gamepad_deactivates ); + ImGui::SetItemTooltip + ( + "Auto-hide the cursor in response to XInput or HID (PlayStation) activity." + ); ImGui::EndGroup ( ); ImGui::SameLine ( ); vCursorWidgetPos = - ImGui::GetCursorPos (); + ImGui::GetCursorPos(); ImGui::TreePop ( ); } @@ -760,7 +737,63 @@ SK::ControlPanel::Input::Draw (void) _CursorBoundaryWidget (); } - ImGui::TreePop (); +#if 0 + ImGui::BeginGroup ( ); + ImGui::Text ("Mouse Problems?"); + ImGui::TreePush (""); + + ImGui::Checkbox ("Fix Synaptics Scroll", &config.input.mouse.fix_synaptics); + + if (ImGui::BeginItemTooltip ()) + { + ImGui::Text ("Generate Missing DirectInput / RawInput / HID Events for Touchpad Scroll"); + ImGui::Separator (); + ImGui::BulletText ("Synaptics touchpads only generate Win32 API messages and scroll events go unnoticed by most games."); + ImGui::BulletText ("Enabling this will attempt to fix missing input APIs for the Synaptics driver."); + ImGui::EndTooltip (); + } + + ImGui::TreePop (); + ImGui::EndGroup (); + + ImGui::SameLine (); + ImGui::SeparatorEx (ImGuiSeparatorFlags_Vertical); + ImGui::SameLine (); +#endif + + ImGui::Separator ( ); + ImGui::BeginGroup ( ); + ImGui::Text ("Mouse Input Capture"); + ImGui::TreePush (""); + if (ImGui::Checkbox ("Block Mouse Input when Overlay is Visible", &config.input.ui.capture_mouse)) + { + SK_ImGui_UpdateCursor (); + //SK_ImGui_AdjustCursor (); + } + + if (ImGui::BeginItemTooltip ()) + { + ImGui::TextColored (ImVec4 (1.f, 1.f, 1.f, 1.f), + "Prevent Game from Detecting All Forms of Mouse Input while this UI is Visible."); + ImGui::EndTooltip (); + } + + if (! config.input.ui.capture_mouse) + { + ImGui::SameLine (0.0f, 15); + ImGui::Checkbox ("Block Mouse Input if No Cursor is Visible", &config.input.ui.capture_hidden); + + if (ImGui::BeginItemTooltip ()) + { + ImGui::BulletText ("Normally, SK allows games to see mouse clicks and movement as long as the cursor is not hovering SK's UI."); + ImGui::BulletText ("If the System Cursor is not visible, games are usually in mouselook mode... which could cause UI problems."); + ImGui::EndTooltip (); + } + } + + ImGui::TreePop (); + ImGui::EndGroup (); + ImGui::TreePop (); } if (bHasPlayStation) @@ -868,25 +901,23 @@ SK::ControlPanel::Input::Draw (void) ImGui::Columns (2); if (config.input.gamepad.hook_xinput) { - ImGui::Checkbox ("Haptic UI Feedback", &config.input.gamepad.haptic_ui); + ImGui::Checkbox ("Haptic UI Feedback", &config.input.gamepad.haptic_ui); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Rumble when interacting with SK's control panel using a gamepad"); ImGui::Separator (); ImGui::BulletText ("Quickly identifies when games are not receiving gamepad input because of the control panel."); ImGui::EndTooltip (); } - ImGui::SameLine (); + ImGui::SameLine (); if (config.input.gamepad.hook_xinput && config.input.gamepad.xinput.hook_setstate) - ImGui::Checkbox ("Disable ALL Rumble", &config.input.gamepad.disable_rumble); + ImGui::Checkbox ("Disable ALL Rumble", &config.input.gamepad.disable_rumble); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Prevent the GAME from making use of controller vibration"); ImGui::Separator (); ImGui::BulletText ("In some games, there is a performance penalty for rumble and it cannot be turned off in-game..."); @@ -894,20 +925,19 @@ SK::ControlPanel::Input::Draw (void) } } - ImGui::NextColumn (); + ImGui::NextColumn (); if (config.input.gamepad.hook_xinput) { ImGui::Checkbox ("Rehook XInput", &config.input.gamepad.rehook_xinput); ImGui::SameLine (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextColored (ImVec4 (1.f, 1.f, 1.f, 1.f), "Re-installs input hooks if third-party hooks are detected."); - ImGui::Separator (); - ImGui::BulletText ("This may improve compatibility with x360ce, but will require a game restart."); - ImGui::EndTooltip (); + ImGui::Separator (); + ImGui::BulletText ("This may improve compatibility with x360ce, but will require a game restart."); + ImGui::EndTooltip (); } } @@ -929,9 +959,8 @@ SK::ControlPanel::Input::Draw (void) _need_restart = true; } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Consider blocking XInput in games that natively support non-Xbox controllers."); ImGui::Separator (); ImGui::BulletText ("Blocking XInput may prevent double-inputs if using something like DS4Windows."); @@ -947,9 +976,8 @@ SK::ControlPanel::Input::Draw (void) _need_restart = true; } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Sometimes a game supports both HID and XInput, but XInput has more features..."); ImGui::Separator (); ImGui::BulletText ("Blocking HID may prevent double-inputs."); @@ -990,14 +1018,10 @@ SK::ControlPanel::Input::Draw (void) { _need_restart = true; } - if (ImGui::IsItemHovered ()) - { - ImGui::SetTooltip ( - "Work In Progress: " - "You probably will not get gamepad input at all if Steam Input is active and blocked." - ); - } - ImGui::EndGroup (); + ImGui::SetItemTooltip ("Work In Progress: " + "You probably will not get gamepad input at all if Steam Input is active and blocked."); + + ImGui::EndGroup ( ); if (_need_restart) { @@ -1005,13 +1029,13 @@ SK::ControlPanel::Input::Draw (void) ImGui::BulletText ("Game Restart May Be Required"); ImGui::PopStyleColor (); } - ImGui::EndMenu (); + ImGui::EndMenu ( ); } ImGui::NextColumn ( ); ImGui::Columns (1); - ImGui::Separator (); + ImGui::Separator ( ); bool connected [XUSER_MAX_COUNT] = { SK_XInput_WasLastPollSuccessful (0), SK_XInput_WasLastPollSuccessful (1), @@ -1056,8 +1080,7 @@ SK::ControlPanel::Input::Draw (void) ImGui::RadioButton ("Nothing##XInputSlot", (int *)&config.input.gamepad.xinput.ui_slot, 4); - if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("Config menu will only respond to keyboard/mouse input"); + ImGui::SetItemTooltip ("Config menu will only respond to keyboard/mouse input"); ImGui::NextColumn ( ); @@ -1066,8 +1089,7 @@ SK::ControlPanel::Input::Draw (void) { ImGui::Checkbox ("Dynamic XInput " ICON_FA_GAMEPAD " 0", &config.input.gamepad.xinput.auto_slot_assign); - if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("Automatically reassign slot 0 in response to gamepad input"); + ImGui::SetItemTooltip ("Automatically reassign slot 0 in response to gamepad input"); } else @@ -1089,13 +1111,14 @@ SK::ControlPanel::Input::Draw (void) ImGui::Checkbox (szChordLabel, &config.input.gamepad.scepad.enhanced_ps_button); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { if (config.input.gamepad.xinput.ui_slot > 3) - ImGui::SetTooltip ("Will not work while \"UI Controller\" is set to 'Nothing'"); + { + ImGui::TextUnformatted ("Will not work while \"UI Controller\" is set to 'Nothing'"); + } else { - ImGui::BeginTooltip (); if (bHasPlayStation) ImGui::TextUnformatted ("Exit \"Control Panel Exclusive Input Mode\" by Holding Share/Select or Pressing Caps Lock"); else @@ -1164,8 +1187,8 @@ SK::ControlPanel::Input::Draw (void) ImGui::TextUnformatted ("Media Next Track"); ImGui::EndGroup (); } - ImGui::EndTooltip (); } + ImGui::EndTooltip (); } ImGui::NextColumn ( ); @@ -1176,17 +1199,16 @@ SK::ControlPanel::Input::Draw (void) ImGui::Text ("XInput Slots:\t"); ImGui::SameLine (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - ImGui::TextColored (ImVec4 (1.f, 1.f, 1.f, 1.f), - "Substitute (or Disable) XInput Controllers With Virtual Ones Until A Real One Is Connected"); - ImGui::Separator (); - ImGui::BulletText ("Placeholding (checked) a slot is useful for games that do not normally support hot-plugging"); - ImGui::BulletText ("Disabling (red button) a slot is useful if Steam Input and DS4Windows are both emulating XInput"); - ImGui::Separator (); - ImGui::BulletText ("Both may improve performance in games that poll disconnected controllers"); - ImGui::EndTooltip (); + ImGui::TextColored (ImVec4 (1.f, 1.f, 1.f, 1.f), + "Substitute (or Disable) XInput Controllers With Virtual Ones Until A Real One Is Connected"); + ImGui::Separator (); + ImGui::BulletText ("Placeholding (checked) a slot is useful for games that do not normally support hot-plugging"); + ImGui::BulletText ("Disabling (red button) a slot is useful if Steam Input and DS4Windows are both emulating XInput"); + ImGui::Separator (); + ImGui::BulletText ("Both may improve performance in games that poll disconnected controllers"); + ImGui::EndTooltip (); } auto XInputPlaceholderCheckbox = [](const char* szName, DWORD dwIndex) @@ -1253,62 +1275,56 @@ SK::ControlPanel::Input::Draw (void) ImGui::PopStyleColor (4); } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { const SK_XInput_PacketJournal journal = SK_XInput_GetPacketJournal (dwIndex); - ImGui::BeginTooltip ( ); - - ImGui::BeginGroup ( ); + ImGui::BeginGroup ( ); ImGui::TextUnformatted ("Device State: "); ImGui::TextUnformatted ("Placeholding: "); - ImGui::EndGroup ( ); - - ImGui::SameLine ( ); - - ImGui::BeginGroup ( ); + ImGui::EndGroup ( ); + ImGui::SameLine ( ); + ImGui::BeginGroup ( ); if (config.input.gamepad.xinput.disable [dwIndex] || config.input.gamepad.xinput.blackout_api) - ImGui::TextColored (ImVec4 (1.0f, 0.1f, 0.1f, 1.0f), "Disabled"); + ImGui::TextColored (ImVec4 (1.0f, 0.1f, 0.1f, 1.0f), "Disabled"); else if (SK_ImGui_WantGamepadCapture ()) - ImGui::TextColored (ImVec4 (1.0f, 1.0f, 0.1f, 1.0f), "Blocked"); + ImGui::TextColored (ImVec4 (1.0f, 1.0f, 0.1f, 1.0f), "Blocked"); else - ImGui::TextColored (ImVec4 (0.1f, 1.0f, 0.1f, 1.0f), "Enabled"); + ImGui::TextColored (ImVec4 (0.1f, 1.0f, 0.1f, 1.0f), "Enabled"); if (config.input.gamepad.xinput.placehold [dwIndex]) { if (SK_XInput_Holding (dwIndex)) - ImGui::TextColored (ImVec4 ( 0.1f, 1.0f, 0.1f, 1.0f), "Enabled and Active"); + ImGui::TextColored (ImVec4 ( 0.1f, 1.0f, 0.1f, 1.0f), "Enabled and Active"); else - ImGui::TextColored (ImVec4 (0.75f, 0.75f, 0.75f, 1.0f), "Enabled"); + ImGui::TextColored (ImVec4 (0.75f, 0.75f, 0.75f, 1.0f), "Enabled"); } else - ImGui::TextColored (ImVec4 ( 0.5f, 0.5f, 0.5f, 1.0f), "N/A"); - ImGui::EndGroup ( ); - - ImGui::Separator ( ); - + ImGui::TextColored (ImVec4 ( 0.5f, 0.5f, 0.5f, 1.0f), "N/A"); + ImGui::EndGroup ( ); + ImGui::Separator ( ); if (config.input.gamepad.xinput.placehold [dwIndex] && journal.packet_count.virt > 0) { - ImGui::TextColored (ImColor (255, 255, 255), "Hardware Packet Sequencing"); - ImGui::TextColored (ImColor (160, 160, 160), "(Last: %lu | Now: %lu)", - journal.sequence.last, journal.sequence.current); - ImGui::Separator ( ); - ImGui::Columns (2, nullptr, false); - ImGui::TextColored (ImColor (255, 165, 0), "Virtual Packets..."); ImGui::NextColumn (); - ImGui::Text ("%+07li", journal.packet_count.virt); ImGui::NextColumn (); - ImGui::TextColored (ImColor (127, 255, 0), "Real Packets..."); ImGui::NextColumn (); - ImGui::Text ("%+07li", journal.packet_count.real); - ImGui::Columns (1); + ImGui::TextColored (ImColor (255, 255, 255), "Hardware Packet Sequencing"); + ImGui::TextColored (ImColor (160, 160, 160), "(Last: %lu | Now: %lu)", + journal.sequence.last, journal.sequence.current); + ImGui::Separator ( ); + ImGui::Columns (2, nullptr, false); + ImGui::TextColored (ImColor (255, 165, 0), "Virtual Packets..."); ImGui::NextColumn (); + ImGui::Text ("%+07li", journal.packet_count.virt); ImGui::NextColumn (); + ImGui::TextColored (ImColor (127, 255, 0), "Real Packets..."); ImGui::NextColumn (); + ImGui::Text ("%+07li", journal.packet_count.real); + ImGui::Columns (1); } else { - ImGui::BulletText ("Inputs Processed:\t%lu", journal.packet_count.real); + ImGui::BulletText ("Inputs Processed:\t%lu", journal.packet_count.real); } - ImGui::EndTooltip ( ); + ImGui::EndTooltip ( ); } }; @@ -1430,17 +1446,14 @@ SK::ControlPanel::Input::Draw (void) if (*ps_controller.wszSerialNumber != L'\0') { - if (ImGui::IsItemHovered ()) - { - ImGui::SetTooltip ( - "Serial # %wc%wc:%wc%wc:%wc%wc:%wc%wc:%wc%wc:%wc%wc", - (unsigned short)ps_controller.wszSerialNumber [ 0], (unsigned short)ps_controller.wszSerialNumber [ 1], - (unsigned short)ps_controller.wszSerialNumber [ 2], (unsigned short)ps_controller.wszSerialNumber [ 3], - (unsigned short)ps_controller.wszSerialNumber [ 4], (unsigned short)ps_controller.wszSerialNumber [ 5], - (unsigned short)ps_controller.wszSerialNumber [ 6], (unsigned short)ps_controller.wszSerialNumber [ 7], - (unsigned short)ps_controller.wszSerialNumber [ 8], (unsigned short)ps_controller.wszSerialNumber [ 9], - (unsigned short)ps_controller.wszSerialNumber [10], (unsigned short)ps_controller.wszSerialNumber [11] ); - } + ImGui::SetItemTooltip ( "Serial # %wc%wc:%wc%wc:%wc%wc:%wc%wc:%wc%wc:%wc%wc", + (unsigned short)ps_controller.wszSerialNumber [ 0], (unsigned short)ps_controller.wszSerialNumber [ 1], + (unsigned short)ps_controller.wszSerialNumber [ 2], (unsigned short)ps_controller.wszSerialNumber [ 3], + (unsigned short)ps_controller.wszSerialNumber [ 4], (unsigned short)ps_controller.wszSerialNumber [ 5], + (unsigned short)ps_controller.wszSerialNumber [ 6], (unsigned short)ps_controller.wszSerialNumber [ 7], + (unsigned short)ps_controller.wszSerialNumber [ 8], (unsigned short)ps_controller.wszSerialNumber [ 9], + (unsigned short)ps_controller.wszSerialNumber [10], (unsigned short)ps_controller.wszSerialNumber [11] + ); } } ImGui::EndGroup (); @@ -1586,9 +1599,8 @@ SK::ControlPanel::Input::Draw (void) ImGui::OpenPopup ("PowerManagementMenu"); } - else if (ImGui::IsItemHovered ()) + else if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip ( ); ImGui::BeginGroup ( ); ImGui::TextColored ( ImColor::HSV (0.18f, 0.88f, 0.94f), " Left-Click" ); @@ -1617,8 +1629,7 @@ SK::ControlPanel::Input::Draw (void) config.utility.save_async (); } - if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("Polls gyro and touchpad less frequently to save power."); + ImGui::SetItemTooltip ("Polls gyro and touchpad less frequently to save power."); } if (ImGui::SliderFloat ("Critical Battery Level", &config.input.gamepad.low_battery_percent, 0.0f, 45.0f, "%3.0f%% Remaining")) @@ -1626,16 +1637,15 @@ SK::ControlPanel::Input::Draw (void) config.utility.save_async (); } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Display warning notifications when PlayStation controller battery levels are critical."); ImGui::Separator (); ImGui::BulletText ("The warning is only displayed while the controller is running on battery."); ImGui::BulletText ("The warning can be disabled by setting 0%%"); ImGui::EndTooltip (); } - ImGui::EndPopup (); + ImGui::EndPopup (); } } } break; @@ -1690,9 +1700,8 @@ SK::ControlPanel::Input::Draw (void) config.utility.save_async (); } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Adds PlayStation controller support to Xbox-only games"); ImGui::Separator (); ImGui::BulletText ("Fully supports DualSense and DualShock 4 (USB and Bluetooth)"); @@ -1733,8 +1742,10 @@ SK::ControlPanel::Input::Draw (void) if (SK_ImGui_IsItemRightClicked ()) show_debug_option = true; - else if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("Apply a Deadzone to Analog Stick Input (" ICON_FA_XBOX " Mode)"); + else + { + ImGui::SetItemTooltip ("Apply a Deadzone to Analog Stick Input (" ICON_FA_XBOX " Mode)"); + } if (show_debug_option) { @@ -1813,9 +1824,9 @@ SK::ControlPanel::Input::Draw (void) config.utility.save_async (); } - if (ImGui::IsItemHovered () && bHasBluetooth) + if (bHasBluetooth) { - ImGui::SetTooltip ("RGB lighting can be turned off to save battery..."); + ImGui::SetItemTooltip ("RGB lighting can be turned off to save battery..."); } ImGui::BeginGroup (); @@ -1862,8 +1873,7 @@ SK::ControlPanel::Input::Draw (void) config.utility.save_async (); } - if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("Controls the brightness of status lights as well as RGB"); + ImGui::SetItemTooltip ("Controls the brightness of status lights as well as RGB"); } else { ImGui::SameLine (); @@ -1872,9 +1882,8 @@ SK::ControlPanel::Input::Draw (void) ///if (bHasBluetooth && bHasSimpleBluetooth && (! bHasNonBluetooth)) ///{ - /// if (ImGui::IsItemHovered ()) + /// if (ImGui::BeginItemTooltip ()) /// { - /// ImGui::BeginTooltip (); /// ImGui::TextUnformatted ("Bluetooth Compatibility Mode is Active"); /// ImGui::Separator (); /// ImGui::BulletText ("RGB Overrides may only apply after a game triggers rumble, or if you use USB."); @@ -1888,9 +1897,8 @@ SK::ControlPanel::Input::Draw (void) ImGui::SliderInt ( "HID Input Buffers", &config.input.gamepad.hid.max_allowed_buffers, 2, 128, "%d-Buffer Circular Queue" ); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Reduce Input Buffer Queue (Latency) on Gamepads"); ImGui::Separator (); ImGui::BulletText ( @@ -1940,9 +1948,8 @@ SK::ControlPanel::Input::Draw (void) " Compatibility Mode: Features newer than DualShock 3 unsupported." ); - if (ImGui::IsItemHovered ( )) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip ( ); ImGui::TextUnformatted ( "Plug your controller in, or trigger rumble in-game to put the " "Bluetooth controller into DualShock 4 / DualSense mode; " @@ -1952,13 +1959,13 @@ SK::ControlPanel::Input::Draw (void) #ifdef SK_HID_BROKEN_DUALSHOCK4_REV2 if (bHasDualShock4v2_Bt) { - ImGui::Separator (); - ImGui::BulletText ( + ImGui::Separator (); + ImGui::BulletText ( "DualShock 4 v2 controllers will not work over Bluetooth with SK in Compatibility Mode." ); } #endif - ImGui::EndTooltip ( ); + ImGui::EndTooltip (); } } @@ -1994,8 +2001,7 @@ SK::ControlPanel::Input::Draw (void) { ImGui::Checkbox ("Hook libScePad", &config.input.gamepad.hook_scepad); - if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("SONY's native input API; unlocks additional settings in games that use it"); + ImGui::SetItemTooltip ("SONY's native input API; unlocks additional settings in games that use it"); if (config.input.gamepad.hook_scepad && last_scepad != 0) { @@ -2015,7 +2021,10 @@ SK::ControlPanel::Input::Draw (void) #endif ImGui::BeginGroup (); - if (ImGui::TreeNode ("Compatibility Options")) + bool compat_expanded = + ImGui::TreeNode ("Compatibility Options"); + + if (compat_expanded) { bool hovered = false; bool changed = false; @@ -2091,23 +2100,38 @@ SK::ControlPanel::Input::Draw (void) { if (alt_models) ImGui::SameLine (); - ImGui::BeginGroup (); + ImGui::BeginGroup (); if (ImGui::Checkbox ("Current Game Requires " ICON_FA_BLUETOOTH " Compatibility Mode", &config.input.gamepad.bt_input_only)) { if (config.input.gamepad.bt_input_only) { - SK_DeferCommand ("Input.Gamepad.PowerOff 1"); + if ( SK_WinMM_Backend->reads [2] + + SK_DI7_Backend->reads [2] + + SK_DI8_Backend->reads [2] > 0 ) + { + SK_DeferCommand ("Input.Gamepad.PowerOff 1"); + } } changed = true; } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::SetTooltip ( - "Enable this if your current game only supports DirectInput, " - "SK will power-off your controller(s) if necessary." - ); + ImGui::TextUnformatted + ( "Enable this if the current game only has " + "support for DirectInput" + ); + ImGui::Separator (); + ImGui::BulletText ( + "SK will power-off your controller(s) if it detects the game" + " trying to use WinMM or DirectInput."); + ImGui::Separator (); + ImGui::TextUnformatted + ( "When powered-on, the controller will be " + "compatible with DirectInput (until something uses rumble " + "or sets LEDs)." ); + ImGui::EndTooltip (); } if (! config.input.gamepad.bt_input_only) @@ -2118,9 +2142,8 @@ SK::ControlPanel::Input::Draw (void) changed = true; } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Allow SK to use your controller's full functionality, " "even if that requires enabling Advanced Bluetooth mode."); ImGui::Separator (); @@ -2133,14 +2156,14 @@ SK::ControlPanel::Input::Draw (void) #ifdef SK_HID_BROKEN_DUALSHOCK4_REV2 if (bHasDualShock4v2_Bt) { - ImGui::Separator (); - ImGui::BulletText ( + ImGui::Separator (); + ImGui::BulletText ( "DualShock 4 v2 controllers will not work over Bluetooth with SK unless this is enabled" ); } else { - ImGui::Separator (); + ImGui::Separator (); } ImGui::TextUnformatted ("This is a global setting."); @@ -2157,6 +2180,7 @@ SK::ControlPanel::Input::Draw (void) ImGui::TreePop ( ); } ImGui::EndGroup (); + if (!compat_expanded) ImGui::SameLine (); ImGui::BeginGroup (); if (ImGui::TreeNode ("Button Mapping")) @@ -2373,16 +2397,10 @@ extern float SK_ImGui_PulseNav_Strength; bool expanded = ImGui::CollapsingHeader (SK_FormatString ("%ws##JOYSTICK_DEBUG", joy_caps.szPname).c_str ()); - ImGui::Combo ("Gamepad Type", &config.input.gamepad.predefined_layout, "PlayStation 4\0Steam\0\0", 2); - - if (ImGui::IsItemHovered ()) - { - ImGui::SetTooltip ("This setting is only used if XInput or DirectInput are not working."); - } - - ImGui::SameLine (); - - ImGui::Checkbox ("Use DirectInput instead of XInput", &config.input.gamepad.native_ps4); + ImGui::Combo ("Gamepad Type", &config.input.gamepad.predefined_layout, "PlayStation 4\0Steam\0\0", 2); + ImGui::SetItemTooltip ("This setting is only used if XInput or DirectInput are not working."); + ImGui::SameLine (); + ImGui::Checkbox ("Use DirectInput instead of XInput", &config.input.gamepad.native_ps4); if (expanded) { @@ -2546,9 +2564,8 @@ extern float SK_ImGui_PulseNav_Strength; } } - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); ImGui::TextUnformatted ("Tests the latency of DS4Windows, Steam Input or a native Xbox controller"); ImGui::Separator (); ImGui::BulletText ("If you have no Xbox controllers or third-party utilities emulating XInput, this does nothing"); @@ -2598,99 +2615,6 @@ extern float SK_ImGui_PulseNav_Strength; ImGui::TreePop ( ); } - if (ImGui::CollapsingHeader ("Low-Level Mouse Settings")) - { - ImGui::TreePush (""); - - ImGui::BeginGroup ( ); - ImGui::Text ("Mouse Problems?"); - ImGui::TreePush (""); - - ImGui::Checkbox ("Fix Synaptics Scroll", &config.input.mouse.fix_synaptics); - - if (ImGui::IsItemHovered ()) - { - ImGui::BeginTooltip (); - ImGui::Text ("Generate Missing DirectInput / RawInput / HID Events for Touchpad Scroll"); - ImGui::Separator (); - ImGui::BulletText ("Synaptics touchpads only generate Win32 API messages and scroll events go unnoticed by most games."); - ImGui::BulletText ("Enabling this will attempt to fix missing input APIs for the Synaptics driver."); - ImGui::EndTooltip (); - } - - ImGui::TreePop (); - ImGui::EndGroup (); - - ImGui::SameLine (); - ImGui::SeparatorEx (ImGuiSeparatorFlags_Vertical); - ImGui::SameLine (); - - ImGui::BeginGroup (); - ImGui::Text ("Mouse Input Capture"); - ImGui::TreePush (""); - - ImGui::BeginGroup ( ); - - if (ImGui::Checkbox ("Block Mouse", &config.input.ui.capture_mouse)) - { - SK_ImGui_UpdateCursor (); - //SK_ImGui_AdjustCursor (); - } - - if (ImGui::IsItemHovered ()) - { - ImGui::BeginTooltip (); - ImGui::TextColored (ImVec4 (1.f, 1.f, 1.f, 1.f), "Prevent Game from Detecting Mouse Input while this UI is Visible"); - ImGui::Separator (); - ImGui::BulletText ("May help with mouselook in some games"); - ImGui::EndTooltip (); - } - - ImGui::SameLine (); - - if (ImGui::Checkbox ("Use Hardware Cursor", &config.input.ui.use_hw_cursor)) - { - SK_ImGui_UpdateCursor (); - } - - if (ImGui::IsItemHovered ()) - { - ImGui::BeginTooltip (); - ImGui::TextColored (ImVec4 (1.f, 1.f, 1.f, 1.f), "Reduce Input Latency -- (Trade Cursor Lag for UI Lag)"); - ImGui::Separator (); - ImGui::BulletText ("You will experience several frames of lag while dragging UI windows around."); - ImGui::BulletText ("Most Games use Hardware Cursors; turning this on will reduce visible cursor trails."); - ImGui::BulletText ("Automatically switches to Software when the game is not using Hardware."); - ImGui::EndTooltip (); - } - - ImGui::SameLine (); - - ImGui::Checkbox ("Block Mouse if No Cursor is Visible", &config.input.ui.capture_hidden); - - if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("Generally prevents mouselook if you move your cursor away from the config UI"); - - ImGui::EndGroup ( ); - ImGui::TreePop ( ); - ImGui::EndGroup ( ); - -#if 0 - extern bool SK_DInput8_BlockWindowsKey (bool block); - extern bool SK_DInput8_HasKeyboard (void); - - if (SK_DInput8_HasKeyboard ()) - { - if (ImGui::Checkbox ("Block Windows Key", &config.input.keyboard.block_windows_key)) - { - config.input.keyboard.block_windows_key = SK_DInput8_BlockWindowsKey (config.input.keyboard.block_windows_key); - } - } -#endif - - ImGui::TreePop (); - } - const bool devices = ImGui::CollapsingHeader ("Enable / Disable Devices", ImGuiTreeNodeFlags_DefaultOpen); @@ -2714,8 +2638,8 @@ extern float SK_ImGui_PulseNav_Strength; if (mouse_changed || keyboard_changed) config.utility.save_async (); - if (ImGui::IsItemHovered () && config.input.keyboard.disabled_to_game == SK_InputEnablement::DisabledInBackground) - ImGui::SetTooltip ("Most games block keyboard input in the background to begin with..."); + if (config.input.keyboard.disabled_to_game == SK_InputEnablement::DisabledInBackground) + ImGui::SetItemTooltip ("Most games block keyboard input in the background to begin with..."); if (/*config.input.gamepad.hook_dinput7 ||*/ config.input.gamepad.hook_dinput8 || config.input.gamepad.hook_hid || config.input.gamepad.hook_xinput || @@ -3170,17 +3094,32 @@ SK_ImGui_GamepadComboDialog0 (SK_GamepadCombo_V0* combo) void SK_ImGui_CursorBoundaryConfig (bool window_mgmt = false) { - ImGui::BeginGroup ( ); - ImGui::Text ("Cursor Boundaries"); + ImGui::BeginGroup ( ); + ImGui::Text ("Cursor Boundaries"); if (! window_mgmt) { - ImGui::SameLine ( ); - ImGui::SeparatorEx (ImGuiSeparatorFlags_Vertical); - ImGui::SameLine ( ); - ImGui::Checkbox ("Center Cursor on UI When Opening Overlay", &config.input.ui.center_cursor); + ImGui::SameLine (0.0f, 15); + ImGui::SeparatorEx (ImGuiSeparatorFlags_Vertical); + ImGui::SameLine (0.0f, 15); + ImGui::Checkbox ("Center Cursor on UI", &config.input.ui.center_cursor); + ImGui::SetItemTooltip + ("Move the System Cursor to the center of SK's Control Panel when opening it."); + ImGui::SameLine (0.0f, 15); + if (ImGui::Checkbox ("Use Hardware Cursor", &config.input.ui.use_hw_cursor)) + { + SK_ImGui_UpdateCursor (); + } + if (ImGui::BeginItemTooltip ()) + { + ImGui::TextColored (ImVec4 (1.f, 1.f, 1.f, 1.f), "Reduce Mouse Latency in SK's Overlay"); + ImGui::Separator ( ); + ImGui::BulletText ("Enabling this may cause some games to use SK's cursor image instead of their own."); + ImGui::BulletText ("Normally the cursor will revert back to whatever the game was using when not hovering SK's UI."); + ImGui::EndTooltip ( ); + } } - ImGui::EndGroup ( ); - ImGui::TreePush (""); + ImGui::EndGroup ( ); + ImGui::TreePush (""); int ovr = 0; bool changed = false; @@ -3193,19 +3132,17 @@ SK_ImGui_CursorBoundaryConfig (bool window_mgmt = false) changed |= ImGui::RadioButton ("Normal Game Behavior", &ovr, 0); ImGui::SameLine (); changed |= ImGui::RadioButton ("Keep Inside Window", &ovr, 1); ImGui::SameLine (); - if (ImGui::IsItemHovered ()) + if (ImGui::BeginItemTooltip ()) { - ImGui::BeginTooltip (); - ImGui::Text ("Prevents Mouse Cursor from Leaving the Game Window"); - ImGui::Separator (); - ImGui::BulletText ("This window-lock will be disengaged when you press Alt + Tab"); - ImGui::EndTooltip (); + ImGui::Text ("Prevents Mouse Cursor from Leaving the Game Window"); + ImGui::Separator (); + ImGui::BulletText ("This window-lock will be disengaged when you press Alt + Tab"); + ImGui::EndTooltip (); } changed |= ImGui::RadioButton ("Unrestrict Cursor", &ovr, 2); - if (ImGui::IsItemHovered ()) - ImGui::SetTooltip ("Prevent Game from Restricting Cursor to Window"); + ImGui::SetItemTooltip ("Prevent Game from Restricting Cursor to Window"); if (changed) { diff --git a/src/core.cpp b/src/core.cpp index 438ebe436..58e1e932d 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -701,7 +701,11 @@ void SK_SEH_InitFinishCallback (void) { if (! (SK_GetDLLRole () & DLL_ROLE::DXGI)) SK::DXGI::StartBudgetThread_NoAdapter (); - + }__except(GetExceptionCode()==EXCEPTION_WINE_STUB ? + EXCEPTION_EXECUTE_HANDLER: + EXCEPTION_CONTINUE_SEARCH){ } + __try + { static const GUID nil_guid = { }; GUID* pGUID = nullptr; @@ -721,14 +725,15 @@ void SK_SEH_InitFinishCallback (void) { PowerSetActiveScheme (nullptr, &config.cpu.power_scheme_guid); } - + }__except(GetExceptionCode()==EXCEPTION_WINE_STUB ? + EXCEPTION_EXECUTE_HANDLER: + EXCEPTION_CONTINUE_SEARCH){ } + __try + { SK_LoadGPUVendorAPIs (); - } - - __except ( GetExceptionCode () == EXCEPTION_WINE_STUB ? - EXCEPTION_EXECUTE_HANDLER : - EXCEPTION_CONTINUE_SEARCH ) - { } + }__except(GetExceptionCode()==EXCEPTION_WINE_STUB ? + EXCEPTION_EXECUTE_HANDLER: + EXCEPTION_CONTINUE_SEARCH){ } } void @@ -2879,8 +2884,7 @@ __stdcall SK_ShutdownCore (const wchar_t* backend) { SK_Inject_BroadcastExitNotify (); - - SK_DisableApplyQueuedHooks (); + SK_DisableApplyQueuedHooks (); if ( __SK_DLL_TeardownEvent != nullptr) SetEvent (__SK_DLL_TeardownEvent); @@ -3139,29 +3143,22 @@ SK_ShutdownCore (const wchar_t* backend) dll_log->LogEx (false, L"done! (%4u ms)\n", SK_timeGetTime () - dwTime); } + // Unload imports before shutting down MinHook + SK_UnloadImports (); + dll_log->LogEx (true, L"[ SpecialK ] Shutting down MinHook... "); dwTime = SK_timeGetTime (); SK_MinHook_UnInit (); dll_log->LogEx (false, L"done! (%4u ms)\n", SK_timeGetTime () - dwTime); - LoadLibraryW_Original = nullptr; - LoadLibraryA_Original = nullptr; - LoadLibraryExA_Original = nullptr; - LoadLibraryExW_Original = nullptr; - FreeLibrary_Original = nullptr; - SleepEx_Original = nullptr; - - // ... Many, many more... - dll_log->LogEx (true, L"[ SpecialK ] Closing secondary logs... "); dwTime = SK_timeGetTime (); SK_Log_CleanupLogs (); + SK_ReShadeAddOn_CleanupConfigAndLogs + (); dll_log->LogEx (false, L"done! (%4u ms)\n", SK_timeGetTime () - dwTime); - SK_UnloadImports (); - - SK_ReShadeAddOn_CleanupConfigAndLogs (); } @@ -3190,12 +3187,19 @@ SK_FrameCallback ( SK_RenderBackend& rb, ULONG64 frames_drawn = SK_GetFramesDrawn () ) { + void + ActivateWindow ( HWND hWnd, + bool active = false, + HWND hWndDeactivated = 0 ); + switch (frames_drawn) { // First frame // case 0: { + ActivateWindow (game_window.hWnd, SK_GetForegroundWindow () == game_window.hWnd); + // Notify anything that was waiting for injection into this game SK_Inject_BroadcastInjectionNotify (); @@ -3268,6 +3272,8 @@ SK_FrameCallback ( SK_RenderBackend& rb, // default: { + ActivateWindow (game_window.hWnd, SK_GetForegroundWindow () == game_window.hWnd); + if (game_window.active) SK_RunOnce (SK_Steam_ProcessWindowActivation (game_window.active)); @@ -4403,6 +4409,13 @@ SK_EndBufferSwap (HRESULT hr, IUnknown* device, SK_TLS* pTLS) void SK_ImGui_DrawGraph_Latency (bool predraw); SK_ImGui_DrawGraph_Latency (true); + // While in the size/move modal loop, continually evaluate + // window size/position and unrestrict the mouse. + if (game_window.size_move) + { + SK_Window_RepositionIfNeeded (); + } + return hr; } diff --git a/src/diagnostics/debug_utils.cpp b/src/diagnostics/debug_utils.cpp index 9060e8255..5bfbf8233 100644 --- a/src/diagnostics/debug_utils.cpp +++ b/src/diagnostics/debug_utils.cpp @@ -44,47 +44,22 @@ SHGetKnownFolderPath_Detour ( _In_ REFKNOWNFOLDERID rfid, _In_opt_ HANDLE hToken, _Outptr_ PWSTR * ppszPath ); -using GetCommandLineW_pfn = LPWSTR (WINAPI *)(void); - GetCommandLineW_pfn - GetCommandLineW_Original = nullptr; - -using GetCommandLineA_pfn = LPSTR (WINAPI *)(void); - GetCommandLineA_pfn - GetCommandLineA_Original = nullptr; - -using TerminateThread_pfn = BOOL (WINAPI *)( _In_ HANDLE hThread, - _In_ DWORD dwExitCode ); - TerminateThread_pfn - TerminateThread_Original = nullptr; - -using ExitThread_pfn = VOID (WINAPI *)(_In_ DWORD dwExitCode); - ExitThread_pfn - ExitThread_Original = nullptr; - -using _endthreadex_pfn = void (__cdecl *)( _In_ unsigned _ReturnCode ); - _endthreadex_pfn - _endthreadex_Original = nullptr; - -using NtTerminateProcess_pfn = NTSTATUS (*)(HANDLE, NTSTATUS); - NtTerminateProcess_pfn - NtTerminateProcess_Original = nullptr; - -using RtlExitUserThread_pfn = VOID (NTAPI *)(_In_ NTSTATUS Status); - RtlExitUserThread_pfn - RtlExitUserThread_Original = nullptr; - -using SHGetKnownFolderPath_pfn = HRESULT (WINAPI *)(REFKNOWNFOLDERID,DWORD,HANDLE,PWSTR*); - SHGetKnownFolderPath_pfn - SHGetKnownFolderPath_Original = nullptr; - -using CloseHandle_pfn = BOOL (WINAPI *)(HANDLE); - -TerminateProcess_pfn TerminateProcess_Original = nullptr; -ExitProcess_pfn ExitProcess_Original = nullptr; -ExitProcess_pfn ExitProcess_Hook = nullptr; -OutputDebugStringA_pfn OutputDebugStringA_Original = nullptr; -OutputDebugStringW_pfn OutputDebugStringW_Original = nullptr; -CloseHandle_pfn CloseHandle_Original = nullptr; +SHGetKnownFolderPath_pfn SHGetKnownFolderPath_Original = nullptr; + +GetCommandLineW_pfn GetCommandLineW_Original = nullptr; +GetCommandLineA_pfn GetCommandLineA_Original = nullptr; + +NtTerminateProcess_pfn NtTerminateProcess_Original = nullptr; +RtlExitUserThread_pfn RtlExitUserThread_Original = nullptr; +ExitThread_pfn ExitThread_Original = nullptr; +_endthreadex_pfn _endthreadex_Original = nullptr; +TerminateThread_pfn TerminateThread_Original = nullptr; +TerminateProcess_pfn TerminateProcess_Original = nullptr; +ExitProcess_pfn ExitProcess_Original = nullptr; +ExitProcess_pfn ExitProcess_Hook = nullptr; +OutputDebugStringA_pfn OutputDebugStringA_Original = nullptr; +OutputDebugStringW_pfn OutputDebugStringW_Original = nullptr; +CloseHandle_pfn CloseHandle_Original = nullptr; bool SK_SEH_CompatibleCallerName (LPCVOID lpAddr, wchar_t* wszDllFullName);\ @@ -188,13 +163,8 @@ static SymGetTypeInfo_pfn SymGetTypeInfo_Imp = nullptr; void SK_SymSetOpts (void); -using SetLastError_pfn = void (WINAPI *)(_In_ DWORD dwErrCode); - SetLastError_pfn - SetLastError_Original = nullptr; - -using GetProcAddress_pfn = FARPROC (WINAPI *)(HMODULE,LPCSTR); - GetProcAddress_pfn - GetProcAddress_Original = nullptr; +SetLastError_pfn SetLastError_Original = nullptr; +GetProcAddress_pfn GetProcAddress_Original = nullptr; using LdrLockLoaderLock_pfn = NTSTATUS (WINAPI *)(ULONG Flags, ULONG *State, ULONG_PTR *Cookie); using LdrUnlockLoaderLock_pfn = NTSTATUS (WINAPI *)(ULONG Flags, ULONG_PTR Cookie); diff --git a/src/hooks.cpp b/src/hooks.cpp index 51a2e4ba8..5d5a85ec2 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -1761,6 +1761,44 @@ SK_MinHook_UnInit (void) SK_LOG_MINHOOK_ ( status, L"Failed to Uninitialize MinHook Library!" ); } + LoadLibraryW_Original = nullptr; + LoadLibraryA_Original = nullptr; + LoadLibraryExA_Original = nullptr; + LoadLibraryExW_Original = nullptr; + FreeLibrary_Original = nullptr; + SleepEx_Original = nullptr; + Sleep_Original = nullptr; + GetProcAddress_Original = nullptr; + SetLastError_Original = nullptr; + RaiseException_Original = nullptr; + NtTerminateProcess_Original = nullptr; + RtlExitUserThread_Original = nullptr; + ExitThread_Original = nullptr; + _endthreadex_Original = nullptr; + TerminateThread_Original = nullptr; + TerminateProcess_Original = nullptr; + ExitProcess_Original = nullptr; + OutputDebugStringA_Original = nullptr; + OutputDebugStringW_Original = nullptr; + + CloseHandle_Original = nullptr; + + GlobalAlloc_Original = nullptr; + GlobalFree_Original = nullptr; + LocalAlloc_Original = nullptr; + LocalFree_Original = nullptr; + VirtualAlloc_Original = nullptr; + VirtualFree_Original = nullptr; + RtlAllocateHeap_Original = nullptr; + HeapFree_Original = nullptr; + + GetCommandLineW_Original = nullptr; + GetCommandLineA_Original = nullptr; + + SHGetKnownFolderPath_Original = nullptr; + + // ... Many, many more... + return status; } diff --git a/src/imgui/backends/imgui_d3d11.cpp b/src/imgui/backends/imgui_d3d11.cpp index 968e17350..89fb29925 100644 --- a/src/imgui/backends/imgui_d3d11.cpp +++ b/src/imgui/backends/imgui_d3d11.cpp @@ -1963,7 +1963,6 @@ SK_D3D11_RenderCtx::release (IDXGISwapChain* pSwapChain) // ) //{ //} - if ( (_pSwapChain.p != nullptr && pSwapChain == nullptr) || _pSwapChain.IsEqualObject (pSwapChain) )//|| //_pSwapChain.IsEqualObject (pUnwrapped) ) diff --git a/src/imgui/backends/imgui_d3d12.cpp b/src/imgui/backends/imgui_d3d12.cpp index 27a18d5b2..5ef26c81d 100644 --- a/src/imgui/backends/imgui_d3d12.cpp +++ b/src/imgui/backends/imgui_d3d12.cpp @@ -1197,6 +1197,9 @@ ImGui_ImplDX12_Init ( ID3D12Device* device, void ImGui_ImplDX12_Shutdown (void) { + extern void SK_D3D12_ProcessScreenshotQueueEx (SK_ScreenshotStage, bool, bool); + SK_D3D12_ProcessScreenshotQueueEx (SK_ScreenshotStage::_FlushQueue, true,false); + ///ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ///IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); diff --git a/src/import.cpp b/src/import.cpp index 95ea3ebb6..03465cf01 100644 --- a/src/import.cpp +++ b/src/import.cpp @@ -450,7 +450,7 @@ SK_LoadEarlyImports64 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Early Custom Import %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Early Custom Import %s... ", file.m_pData); if (! blacklisted) @@ -467,7 +467,7 @@ SK_LoadEarlyImports64 (void) SK_GetModuleFullName ( import.hLibrary ).c_str () ); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; if (import.role->is_equal (SK_IMPORT_ROLE_PLUGIN)) { @@ -483,7 +483,7 @@ SK_LoadEarlyImports64 (void) _com_error err (HRESULT_FROM_WIN32 (GetLastError ())); import.hLibrary = (HMODULE)-2; - dll_log->LogEx (false, L"failed: 0x%04X (%s)!\n", + dll_log->Log (L"LoadLibrary failed: 0x%04X (%s)!\n", err.WCode (), err.ErrorMessage () ); } } @@ -534,7 +534,7 @@ SK_LoadPlugIns64 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Special K Plug-In %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Special K Plug-In %s... ", file.m_pData); if (! blacklisted) @@ -546,7 +546,7 @@ SK_LoadPlugIns64 (void) if (SK_Import_GetShimmedLibrary (import.hLibrary, import.hShim)) std::swap (import.hLibrary, import.hShim); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; import.product_desc = @@ -619,7 +619,7 @@ SK_LoadLateImports64 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Late Custom Import %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Late Custom Import %s... ", file.m_pData); if (! blacklisted) @@ -631,7 +631,7 @@ SK_LoadLateImports64 (void) if (SK_Import_GetShimmedLibrary (import.hLibrary, import.hShim)) std::swap (import.hLibrary, import.hShim); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; import.product_desc = @@ -645,14 +645,14 @@ SK_LoadLateImports64 (void) _com_error err (HRESULT_FROM_WIN32 (GetLastError ())); import.hLibrary = (HMODULE)-2; - dll_log->LogEx (false, L"failed: 0x%04X (%s)!\n", + dll_log->Log (L"LoadLibrary failed: 0x%04X (%s)!\n", err.WCode (), err.ErrorMessage () ); } } else { - dll_log->LogEx (false, L"failed: Host App is Blacklisted!\n"); + dll_log->Log (L"LoadLibrary failed: Host App is Blacklisted!\n"); } } } @@ -696,7 +696,7 @@ SK_LoadLazyImports64 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Lazy Custom Import %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Lazy Custom Import %s... ", file.m_pData); if (! blacklisted) @@ -708,7 +708,7 @@ SK_LoadLazyImports64 (void) if (SK_Import_GetShimmedLibrary (import.hLibrary, import.hShim)) std::swap (import.hLibrary, import.hShim); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; import.product_desc = @@ -722,14 +722,14 @@ SK_LoadLazyImports64 (void) _com_error err (HRESULT_FROM_WIN32 (GetLastError ())); import.hLibrary = (HMODULE)-3; - dll_log->LogEx (false, L"failed: 0x%04X (%s)!\n", + dll_log->Log (L"LoadLibrary failed: 0x%04X (%s)!\n", err.WCode (), err.ErrorMessage () ); } } else { - dll_log->LogEx (false, L"failed: Host App is Blacklisted!\n"); + dll_log->Log (L"LoadLibrary failed: Host App is Blacklisted!\n"); } } } @@ -816,7 +816,7 @@ SK_LoadEarlyImports32 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Early Custom Import %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Early Custom Import %s... ", file.m_pData); if (! blacklisted) @@ -828,7 +828,7 @@ SK_LoadEarlyImports32 (void) if (SK_Import_GetShimmedLibrary (import.hLibrary, import.hShim)) std::swap (import.hLibrary, import.hShim); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; import.product_desc = @@ -850,14 +850,14 @@ SK_LoadEarlyImports32 (void) _com_error err (HRESULT_FROM_WIN32 (GetLastError ())); import.hLibrary = (HMODULE)-2; - dll_log->LogEx (false, L"failed: 0x%04X (%s)!\n", + dll_log->Log (L"LoadLibrary failed: 0x%04X (%s)!\n", err.WCode (), err.ErrorMessage () ); } } else { - dll_log->LogEx (false, L"failed: Host App is Blacklisted!\n"); + dll_log->Log (L"LoadLibrary failed: Host App is Blacklisted!\n"); } } } @@ -901,7 +901,7 @@ SK_LoadPlugIns32 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Special K Plug-In %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Special K Plug-In %s... ", file.m_pData); if (! blacklisted) @@ -913,7 +913,7 @@ SK_LoadPlugIns32 (void) if (SK_Import_GetShimmedLibrary (import.hLibrary, import.hShim)) std::swap (import.hLibrary, import.hShim); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; import.product_desc = @@ -986,7 +986,7 @@ SK_LoadLateImports32 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Late Custom Import %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Late Custom Import %s... ", file.m_pData); if (! blacklisted) @@ -998,7 +998,7 @@ SK_LoadLateImports32 (void) if (SK_Import_GetShimmedLibrary (import.hLibrary, import.hShim)) std::swap (import.hLibrary, import.hShim); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; import.product_desc = @@ -1012,14 +1012,14 @@ SK_LoadLateImports32 (void) _com_error err (HRESULT_FROM_WIN32 (GetLastError ())); import.hLibrary = (HMODULE)-2; - dll_log->LogEx (false, L"failed: 0x%04X (%s)!\n", + dll_log->Log (L"LoadLibrary failed: 0x%04X (%s)!\n", err.WCode (), err.ErrorMessage () ); } } else { - dll_log->LogEx (false, L"failed: Host App is Blacklisted!\n"); + dll_log->Log (L"LoadLibrary failed: Host App is Blacklisted!\n"); } } } @@ -1063,7 +1063,7 @@ SK_LoadLazyImports32 (void) SK_StripUserNameFromPathW (file); - dll_log->LogEx (true, L"[ SpecialK ] * Loading Lazy Custom Import %s... ", + dll_log->Log (L"[ SpecialK ] * Loading Lazy Custom Import %s... ", file.m_pData); if (! blacklisted) @@ -1075,7 +1075,7 @@ SK_LoadLazyImports32 (void) if (SK_Import_GetShimmedLibrary (import.hLibrary, import.hShim)) std::swap (import.hLibrary, import.hShim); - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); ++success; import.product_desc = @@ -1089,14 +1089,14 @@ SK_LoadLazyImports32 (void) _com_error err (HRESULT_FROM_WIN32 (GetLastError ())); import.hLibrary = (HMODULE)-3; - dll_log->LogEx (false, L"failed: 0x%04X (%s)!\n", + dll_log->Log (L"LoadLibrary failed: 0x%04X (%s)!\n", err.WCode (), err.ErrorMessage () ); } } else { - dll_log->LogEx (false, L"failed: Host App is Blacklisted!\n"); + dll_log->Log (L"LoadLibrary failed: Host App is Blacklisted!\n"); import.hLibrary = (HMODULE)-3; } } @@ -1121,16 +1121,16 @@ SK_LogLastErr (void) void SK_UnloadImports (void) { - auto orig_se = - SK_SEH_ApplyTranslator ( - SK_FilteringStructuredExceptionTranslator ( - EXCEPTION_ACCESS_VIOLATION - ) - ); - try { - // Unload in reverse order, because that's safer :) - for (int i = SK_MAX_IMPORTS - 1; i >= 0; i--) - { + // Unload in reverse order, because that's safer :) + for (int i = SK_MAX_IMPORTS - 1; i >= 0; i--) + { + auto orig_se = + SK_SEH_ApplyTranslator ( + SK_FilteringStructuredExceptionTranslator ( + EXCEPTION_ACCESS_VIOLATION + ) + ); + try { auto& import = imports->imports [i]; @@ -1156,7 +1156,7 @@ SK_UnloadImports (void) if (SKPlugIn_Shutdown != nullptr) SKPlugIn_Shutdown (nullptr); } - + ///dll_log.Log ( L"[ SpecialK ] Unloading Custom Import %s...", /// import.filename->get_value_str ().c_str () ); @@ -1165,8 +1165,8 @@ SK_UnloadImports (void) SK_FreeLibrary (import.hLibrary) ) { dll_log->LogEx ( false, - L"-------------------------[ Free Lib ] " - L" success! (%4u ms)\n", + L"-------------------------[ Free Lib ] %41ws" + L" success! (%4u ms)\n", import.name.c_str (), SK_timeGetTime ( ) - dwTime ); } @@ -1176,11 +1176,16 @@ SK_UnloadImports (void) } } } - } - catch (const SK_SEH_IgnoredException&) - { } - SK_SEH_RemoveTranslator (orig_se); + catch (const SK_SEH_IgnoredException&) + { + dll_log->Log ( + L"Structured Exception encountered while unloading library: %ws!", + imports->imports [i].name.c_str () + ); + } + SK_SEH_RemoveTranslator (orig_se); + } } diff --git a/src/input/cursor.cpp b/src/input/cursor.cpp index 7e95622cd..534873e9d 100644 --- a/src/input/cursor.cpp +++ b/src/input/cursor.cpp @@ -528,6 +528,19 @@ sk_imgui_cursor_s::activateWindow (bool active) static constexpr const DWORD REASON_DISABLED = 0x4; +bool +sk_window_s::isCursorHovering (void) +{ + if (! SK_GImDefaultContext ()) + return mouse.inside; + + const auto& io = + ImGui::GetIO (); + + return + mouse.inside && io.MousePos.x != -FLT_MAX && io.MousePos.y != -FLT_MAX; +} + bool SK_ImGui_WantMouseCaptureEx (DWORD dwReasonMask) { @@ -554,6 +567,10 @@ SK_ImGui_WantMouseCaptureEx (DWORD dwReasonMask) bool imgui_capture = false; + LRESULT hit_test = 0; + POINT ptCursor; + SK_GetCursorPos (&ptCursor); + if (SK_ImGui_IsMouseRelevantEx (false)) { static const auto& io = @@ -573,6 +590,28 @@ SK_ImGui_WantMouseCaptureEx (DWORD dwReasonMask) if (game_window.active && ReadULong64Acquire (&config.input.mouse.temporarily_allow) > SK_GetFramesDrawn () - 20) imgui_capture = false; + + if ((! imgui_capture) && (! game_window.isCursorHovering ()) && (! SK_IsGameWindowActive ())) + { + hit_test = + DefWindowProcW (game_window.hWnd,WM_NCHITTEST,0,MAKELPARAM(ptCursor.x,ptCursor.y)); + + // Do not block the mouse while it is on the window's titlebar, resize grips, etc. + if (hit_test == HTCLIENT) + { + if (SK_WantBackgroundRender ()) + imgui_capture = true; + + else + { + DWORD dwProcId; + GetWindowThreadProcessId (WindowFromPoint (SK_ImGui_Cursor.last_screen_pos), &dwProcId); + + if (dwProcId != GetCurrentProcessId ()) + imgui_capture = true; + } + } + } } if ((! SK_IsGameWindowActive ()) && config.input.mouse.disabled_to_game == SK_InputEnablement::DisabledInBackground) @@ -589,6 +628,27 @@ SK_ImGui_WantHWCursor (void) ( config.input.ui.use_hw_cursor ); } +bool +SK_ImGui_WantMouseButtonCapture (void) +{ + bool capture = SK_ImGui_WantMouseCapture (); + if ( capture ) + { + POINT ptCursor = {}; + if (SK_GetCursorPos (&ptCursor)) + { + LRESULT hit_test = + DefWindowProcW (game_window.hWnd,WM_NCHITTEST,0,MAKELPARAM(ptCursor.x,ptCursor.y)); + + // Do not block the mouse while it is on the window's titlebar, resize grips, etc. + if (hit_test > HTCLIENT) + capture = false; + } + } + + return capture; +} + bool SK_ImGui_WantMouseCapture (bool update) { @@ -1057,8 +1117,7 @@ GetCursorPos_Detour (LPPOINT lpPoint) #endif } - - if (SK_ImGui_IsMouseRelevant ()) + if (!game_window.isCursorHovering () || SK_ImGui_IsMouseRelevant()) { // // Compute delta mouse coordinates for games that use cursor warping (i.e. mouselook) diff --git a/src/input/hid_reports/playstation.cpp b/src/input/hid_reports/playstation.cpp index 5607dcffb..5ea4baf65 100644 --- a/src/input/hid_reports/playstation.cpp +++ b/src/input/hid_reports/playstation.cpp @@ -1503,14 +1503,22 @@ SK_HID_PlayStationDevice::request_input_report (void) { if (config.input.gamepad.bt_input_only) { - SK_ImGui_CreateNotification ( "HID.Bluetooth.ModeChange", SK_ImGui_Toast::Warning, - "Reconnect them to Activate DualShock 3 Compatibility Mode", - "Special K has Disconnected all Bluetooth Controllers!", - //"Bluetooth PlayStation Controller(s) Running in DualShock 4 / DualSense Mode!", - 15000UL, SK_ImGui_Toast::UseDuration | SK_ImGui_Toast::ShowTitle | - SK_ImGui_Toast::ShowCaption | SK_ImGui_Toast::ShowNewest ); - - SK_DeferCommand ("Input.Gamepad.PowerOff 1"); + const bool legacy_input_detected = + ( SK_WinMM_Backend->reads [2] + + SK_DI7_Backend->reads [2] + + SK_DI8_Backend->reads [2] > 0 ); + + if (legacy_input_detected) + { + SK_ImGui_CreateNotification ( "HID.Bluetooth.ModeChange", SK_ImGui_Toast::Warning, + "Reconnect them to Activate DualShock 3 Compatibility Mode", + "Special K has Disconnected all Bluetooth Controllers!", + //"Bluetooth PlayStation Controller(s) Running in DualShock 4 / DualSense Mode!", + 15000UL, SK_ImGui_Toast::UseDuration | SK_ImGui_Toast::ShowTitle | + SK_ImGui_Toast::ShowCaption | SK_ImGui_Toast::ShowNewest ); + + SK_DeferCommand ("Input.Gamepad.PowerOff 1"); + } } else diff --git a/src/input/input.cpp b/src/input/input.cpp index a76d0bf73..8568da200 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -293,6 +293,17 @@ SK_ImGui_HandlesMessage (MSG *lpMsg, bool /*remove*/, bool /*peek*/) } break; + case WM_ENTERSIZEMOVE: + case WM_EXITSIZEMOVE: + if (lpMsg->hwnd == game_window.hWnd) + { + game_window.size_move = + (lpMsg->message == WM_ENTERSIZEMOVE); + + SK_Window_RepositionIfNeeded (); + } + break; + case WM_CHAR: case WM_MENUCHAR: { diff --git a/src/input/keyboard.cpp b/src/input/keyboard.cpp index 290811e31..30cf295b3 100644 --- a/src/input/keyboard.cpp +++ b/src/input/keyboard.cpp @@ -233,8 +233,10 @@ SK_ImGui_WantKeyboardCapture (bool update) else { + auto temp_poke_frame = ReadULong64Acquire (&config.input.keyboard.temporarily_allow); + // Poke through input for a special-case - if (ReadULong64Acquire (&config.input.keyboard.temporarily_allow) > framesDrawn - 40) + if (temp_poke_frame > 0 && temp_poke_frame > framesDrawn - 40) { imgui_capture = false; } diff --git a/src/input/winhook_input.cpp b/src/input/winhook_input.cpp index 63d874c1e..7d63a52e2 100644 --- a/src/input/winhook_input.cpp +++ b/src/input/winhook_input.cpp @@ -61,93 +61,117 @@ SK_Proxy_MouseProc ( { if (nCode == HC_ACTION || nCode == HC_NOREMOVE) { - if (nCode == HC_ACTION) + if (SK_GImDefaultContext ()) { - switch (wParam) + if (nCode == HC_ACTION) { - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - case WM_XBUTTONDOWN: - case WM_XBUTTONDBLCLK: + switch (wParam) { - MOUSEHOOKSTRUCT *mhs = - (MOUSEHOOKSTRUCT *)lParam; + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONDBLCLK: + { + MOUSEHOOKSTRUCT *mhs = + (MOUSEHOOKSTRUCT *)lParam; - static auto& io = - ImGui::GetIO (); + auto& io = + ImGui::GetIO (); - io.KeyCtrl |= ((mhs->dwExtraInfo & MK_CONTROL) != 0); - io.KeyShift |= ((mhs->dwExtraInfo & MK_SHIFT ) != 0); + io.KeyCtrl |= ((mhs->dwExtraInfo & MK_CONTROL) != 0); + io.KeyShift |= ((mhs->dwExtraInfo & MK_SHIFT ) != 0); - switch (wParam) - { - case WM_MOUSEMOVE: + // No TrackMouseEvent available, have to do this manually + if (! game_window.mouse.can_track) { - // No TrackMouseEvent available, have to do this manually - if (! game_window.mouse.can_track) + POINT pt (mhs->pt); + ScreenToClient (game_window.child != nullptr ? + game_window.child : + game_window.hWnd, &pt); + if (ChildWindowFromPointEx (game_window.child != nullptr ? + game_window.child : + game_window.hWnd, pt, CWP_SKIPDISABLED) == (game_window.child != nullptr ? + game_window.child : + game_window.hWnd)) { - POINT pt (mhs->pt); - ScreenToClient (game_window.child != nullptr ? - game_window.child : - game_window.hWnd, &pt); - if (ChildWindowFromPointEx (game_window.child != nullptr ? - game_window.child : - game_window.hWnd, pt, CWP_SKIPDISABLED) == (game_window.child != nullptr ? - game_window.child : - game_window.hWnd)) - { - SK_ImGui_Cursor.ClientToLocal (&pt); - SK_ImGui_Cursor.pos = pt; - - io.MousePos.x = (float)SK_ImGui_Cursor.pos.x; - io.MousePos.y = (float)SK_ImGui_Cursor.pos.y; - } + SK_ImGui_Cursor.ClientToLocal (&pt); + SK_ImGui_Cursor.pos = pt; - else - io.MousePos = ImVec2 (-FLT_MAX, -FLT_MAX); + io.MousePos.x = (float)SK_ImGui_Cursor.pos.x; + io.MousePos.y = (float)SK_ImGui_Cursor.pos.y; } - // Install a mouse tracker to get WM_MOUSELEAVE - if (! (game_window.mouse.tracking && game_window.mouse.inside)) + else + io.MousePos = ImVec2 (-FLT_MAX, -FLT_MAX); + } + + // Install a mouse tracker to get WM_MOUSELEAVE + if (! (game_window.mouse.tracking && game_window.mouse.inside)) + { + if (wParam != WM_NCMOUSEMOVE) { if (SK_ImGui_WantMouseCapture ()) { SK_ImGui_UpdateMouseTracker (); } } - } break; + } - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - io.MouseDown [0] = true; - break; + switch (wParam) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + io.AddMouseButtonEvent (ImGuiKey_MouseLeft, true); + break; + + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + io.AddMouseButtonEvent (ImGuiKey_MouseRight, true); + break; + + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + io.AddMouseButtonEvent (ImGuiKey_MouseMiddle, true); + break; + + case WM_XBUTTONDOWN: + case WM_XBUTTONDBLCLK: + { + MOUSEHOOKSTRUCTEX* mhsx = + (MOUSEHOOKSTRUCTEX*)lParam; - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - io.MouseDown [1] = true; - break; + if ((HIWORD (mhsx->mouseData)) == XBUTTON1) io.AddMouseButtonEvent (ImGuiKey_MouseX1, true); + if ((HIWORD (mhsx->mouseData)) == XBUTTON2) io.AddMouseButtonEvent (ImGuiKey_MouseX2, true); + } break; - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - io.MouseDown [2] = true; - break; + case WM_LBUTTONUP: + //io.AddMouseButtonEvent (ImGuiKey_MouseLeft, false); + break; - case WM_XBUTTONDOWN: - case WM_XBUTTONDBLCLK: - { - MOUSEHOOKSTRUCTEX* mhsx = - (MOUSEHOOKSTRUCTEX*)lParam; + case WM_RBUTTONUP: + //io.AddMouseButtonEvent (ImGuiKey_MouseRight, false); + break; - if ((HIWORD (mhsx->mouseData)) == XBUTTON1) io.MouseDown [3] = true; - if ((HIWORD (mhsx->mouseData)) == XBUTTON2) io.MouseDown [4] = true; - } break; - } - } break; + case WM_MBUTTONUP: + //io.AddMouseButtonEvent (ImGuiKey_MouseMiddle, false); + break; + + case WM_XBUTTONUP: + { + //MOUSEHOOKSTRUCTEX* mhsx = + // (MOUSEHOOKSTRUCTEX*)lParam; + + //if ((HIWORD (mhsx->mouseData)) == XBUTTON1) io.AddMouseButtonEvent (ImGuiKey_MouseX1, false); + //if ((HIWORD (mhsx->mouseData)) == XBUTTON2) io.AddMouseButtonEvent (ImGuiKey_MouseX2, false); + } break; + } + } break; + } } } @@ -203,51 +227,87 @@ SK_Proxy_LLMouseProc ( { if (nCode == HC_ACTION) { - switch (wParam) - { - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - case WM_XBUTTONDOWN: - case WM_XBUTTONDBLCLK: - { - MSLLHOOKSTRUCT *mhs = - (MSLLHOOKSTRUCT *)lParam; + MSLLHOOKSTRUCT *mhs = + (MSLLHOOKSTRUCT *)lParam; - static auto& io = - ImGui::GetIO (); + if (SK_GImDefaultContext ()) + { + auto& io = + ImGui::GetIO (); - io.KeyCtrl |= ((mhs->dwExtraInfo & MK_CONTROL) != 0); - io.KeyShift |= ((mhs->dwExtraInfo & MK_SHIFT ) != 0); + // No TrackMouseEvent available, have to do this manually + if (! game_window.mouse.can_track) + { + POINT pt (mhs->pt); + ScreenToClient (game_window.child != nullptr ? + game_window.child : + game_window.hWnd, &pt); + if (ChildWindowFromPointEx (game_window.child != nullptr ? + game_window.child : + game_window.hWnd, pt, CWP_SKIPDISABLED) == (game_window.child != nullptr ? + game_window.child : + game_window.hWnd)) + { + SK_ImGui_Cursor.ClientToLocal (&pt); + SK_ImGui_Cursor.pos = pt; + + io.MousePos.x = (float)SK_ImGui_Cursor.pos.x; + io.MousePos.y = (float)SK_ImGui_Cursor.pos.y; + } + + else + io.MousePos = ImVec2 (-FLT_MAX, -FLT_MAX); + } + + // Install a mouse tracker to get WM_MOUSELEAVE + if (! (game_window.mouse.tracking && game_window.mouse.inside)) + { + if (SK_ImGui_WantMouseCapture ()) + { + SK_ImGui_UpdateMouseTracker (); + } + } - switch (wParam) + switch (wParam) + { + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONDBLCLK: { - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - io.MouseDown [0] = true; - break; + io.KeyCtrl |= ((mhs->dwExtraInfo & MK_CONTROL) != 0); + io.KeyShift |= ((mhs->dwExtraInfo & MK_SHIFT ) != 0); - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - io.MouseDown [1] = true; - break; + switch (wParam) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + io.AddMouseButtonEvent (ImGuiKey_MouseLeft, true); + break; - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - io.MouseDown [2] = true; - break; + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + io.AddMouseButtonEvent (ImGuiKey_MouseRight, true); + break; - case WM_XBUTTONDOWN: - case WM_XBUTTONDBLCLK: - if ((HIWORD (mhs->mouseData)) == XBUTTON1) io.MouseDown [3] = true; - if ((HIWORD (mhs->mouseData)) == XBUTTON2) io.MouseDown [4] = true; - break; - } - } break; + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + io.AddMouseButtonEvent (ImGuiKey_MouseMiddle, true); + break; + + case WM_XBUTTONDOWN: + case WM_XBUTTONDBLCLK: + if ((HIWORD (mhs->mouseData)) == XBUTTON1) io.AddMouseButtonEvent (ImGuiKey_MouseX1, true); + if ((HIWORD (mhs->mouseData)) == XBUTTON2) io.AddMouseButtonEvent (ImGuiKey_MouseX2, true); + break; + } + } break; + } } if (SK_ImGui_WantMouseCapture ()) @@ -260,31 +320,28 @@ SK_Proxy_LLMouseProc ( wParam, lParam ); } - else + // Game uses a mouse hook for input that the Steam overlay cannot block + if (SK_GetStoreOverlayState (true)) { - // Game uses a mouse hook for input that the Steam overlay cannot block - if (SK_GetStoreOverlayState (true)) - { - SK_WinHook_Backend->markHidden (sk_input_dev_type::Mouse); + SK_WinHook_Backend->markHidden (sk_input_dev_type::Mouse); - return - CallNextHookEx (0, nCode, wParam, lParam); - } + return + CallNextHookEx (0, nCode, wParam, lParam); + } - SK_WinHook_Backend->markRead (sk_input_dev_type::Mouse); + SK_WinHook_Backend->markRead (sk_input_dev_type::Mouse); - DWORD dwTid = - GetCurrentThreadId (); + DWORD dwTid = + GetCurrentThreadId (); - auto hook_fn = __hooks._RealMouseProcs [dwTid]; - hook_fn = - hook_fn != nullptr ? - hook_fn : - __hooks._RealMouseProc; - - if (hook_fn != nullptr) - return hook_fn (nCode, wParam, lParam); - } + auto hook_fn = __hooks._RealMouseProcs [dwTid]; + hook_fn = + hook_fn != nullptr ? + hook_fn : + __hooks._RealMouseProc; + + if (hook_fn != nullptr) + return hook_fn (nCode, wParam, lParam); } return @@ -303,7 +360,7 @@ SK_Proxy_KeyboardProc ( { LPARAM lParamOrig = lParam; - if (nCode == HC_ACTION) + if (nCode == HC_ACTION || nCode == HC_NOREMOVE) { bool wasPressed = (((DWORD)lParam) & (1UL << 30UL)) != 0UL, isPressed = (((DWORD)lParam) & (1UL << 31UL)) == 0UL, @@ -324,7 +381,10 @@ SK_Proxy_KeyboardProc ( } if ((! isPressed) || SK_IsGameWindowActive ()) - ImGui::GetIO ().KeysDown [vKey] = isPressed; + { + if (SK_GImDefaultContext ()) + ImGui::GetIO ().KeysDown [vKey] = isPressed; + } bool hide = SK_ImGui_WantKeyboardCapture (); @@ -363,9 +423,9 @@ SK_Proxy_KeyboardProc ( { if (hook_fn != nullptr && config.input.keyboard.disabled_to_game != 1) { - lParam &= ~(1<<31); - lParam &= ~(1<<30); - lParam &= ~(1<<29); + lParam &= ~(1UL<<31UL); + lParam &= ~(1UL<<30UL); + lParam &= ~(1UL<<29UL); hook_fn (nCode, wParam, lParam); @@ -447,7 +507,10 @@ SK_Proxy_LLKeyboardProc ( } if (bWindowActive || (! isPressed)) - ImGui::GetIO ().KeysDown [vKey] = isPressed; + { + if (SK_GImDefaultContext ()) + ImGui::GetIO ().KeysDown [vKey] = isPressed; + } bool hide = SK_ImGui_WantKeyboardCapture (); @@ -486,9 +549,9 @@ SK_Proxy_LLKeyboardProc ( { if (hook_fn != nullptr && config.input.keyboard.disabled_to_game != 1) { - lParam &= ~(1<<31); - lParam &= ~(1<<30); - lParam &= ~(1<<29); + lParam &= ~(1UL<<31UL); + lParam &= ~(1UL<<30UL); + lParam &= ~(1UL<<29UL); hook_fn (nCode, wParam, lParam); diff --git a/src/nvapi.cpp b/src/nvapi.cpp index f96904a79..bdba02848 100644 --- a/src/nvapi.cpp +++ b/src/nvapi.cpp @@ -464,69 +464,94 @@ NvAPI_Disp_GetHdrCapabilities_Override ( NvU32 displayId, std::lock_guard lock (SK_NvAPI_Threading->locks.Disp_GetHdrCapabilities); - SK_LOG0 ( ( L"NV_HDR_CAPABILITIES Version: %lu", pHdrCapabilities->version ), - __SK_SUBSYSTEM__ ); - SK_LOG0 ( ( L" >> Wants Driver to Expand Default HDR Params: %s", - pHdrCapabilities->driverExpandDefaultHdrParameters ? L"Yes" : - L"No" ), - __SK_SUBSYSTEM__ ); + static NvU32 version = pHdrCapabilities->version; + static DWORD calls = 0; - // We don't care what the game wants, we're filling-in default values dammit! - pHdrCapabilities->driverExpandDefaultHdrParameters = true; + if (version == pHdrCapabilities->version) + calls++; + else + { + version = pHdrCapabilities->version; + calls = 0; + } + + if (calls == 5) + { + SK_LOGi0 ( + L"Repeated calls to NvAPI_Disp_GetHdrCapabilities (version=%x), silencing future calls...", + version + ); + } + + if (calls < 5) + { + // We don't care what the game wants, we're filling-in default values dammit! + pHdrCapabilities->driverExpandDefaultHdrParameters = true; + } NvAPI_Status ret = NvAPI_Disp_GetHdrCapabilities_Original ( displayId, pHdrCapabilities ); - const SK_RenderBackend_V2::output_s* const pBackendDisplay = - SK_GetCurrentRenderBackend ().displays->nvapi.getDisplayFromId (displayId); - - dll_log->LogEx ( true, - L"[ HDR Caps ]\n" - L" +-----------------+---------------------\n" - L" | Red Primary.... | %f, %f\n" - L" | Green Primary.. | %f, %f\n" - L" | Blue Primary... | %f, %f\n" - L" | White Point.... | %f, %f\n" - L" | =============== |\n" - L" | Min Luminance.. | %10.5f cd/m²\n" - L" | Max Luminance.. | %10.5f cd/m²\n" - L" | |- FullFrame.. | %10.5f cd/m²\n" - L" | SDR Luminance.. | %10.5f cd/m²\n" - L" | =============== |\n" - L" | ST2084 EOTF.... | %s\n" - L" | CTA-861.3 HDR.. | %s\n" - L" | CTA-861.3 SDR.. | %s\n" - L" | =============== |\n" - L" | HDR10+......... | %s\n" - L" | HDR10+ Gaming.. | %s\n" - L" | =============== |\n" - L" | Dolby Vision... | %s\n" - L" | YUV 4:2:2 12bpc | %s\n" - L" | Low Latency.... | %s\n" - L" | |- 4:4:4 10bpc | %s\n" - L" | |- 4:4:4 12bpc | %s\n" - L" +-----------------+---------------------\n", - (float)pHdrCapabilities->display_data.displayPrimary_x0 / (float)0xC350, (float)pHdrCapabilities->display_data.displayPrimary_y0 / (float)0xC350, - (float)pHdrCapabilities->display_data.displayPrimary_x1 / (float)0xC350, (float)pHdrCapabilities->display_data.displayPrimary_y1 / (float)0xC350, - (float)pHdrCapabilities->display_data.displayPrimary_x2 / (float)0xC350, (float)pHdrCapabilities->display_data.displayPrimary_y2 / (float)0xC350, - (float)pHdrCapabilities->display_data.displayWhitePoint_x / (float)0xC350, (float)pHdrCapabilities->display_data.displayWhitePoint_y / (float)0xC350, - (float)pHdrCapabilities->display_data.desired_content_min_luminance * 0.0001f, - (float)pHdrCapabilities->display_data.desired_content_max_luminance, - (float)pHdrCapabilities->display_data.desired_content_max_frame_average_luminance, - pBackendDisplay != nullptr ? - pBackendDisplay->hdr.white_level : - (float)pHdrCapabilities->display_data.desired_content_max_frame_average_luminance, - pHdrCapabilities->isST2084EotfSupported ? L"Yes" : L"No", - pHdrCapabilities->isTraditionalHdrGammaSupported ? L"Yes" : L"No", - pHdrCapabilities->isTraditionalSdrGammaSupported ? L"Yes" : L"No", - pHdrCapabilities->isHdr10PlusSupported ? L"Yes" : L"No", - pHdrCapabilities->isHdr10PlusGamingSupported ? L"Yes" : L"No", - pHdrCapabilities->isDolbyVisionSupported ? L"Yes" : L"No", - pHdrCapabilities->dv_static_metadata.supports_YUV422_12bit ? L"Yes" : L"No", - (pHdrCapabilities->dv_static_metadata.interface_supported_by_sink - & 0x2) ? L"Yes" : L"No", - (pHdrCapabilities->dv_static_metadata.supports_10b_12b_444 & 0x1) ? L"Yes" : L"No", - (pHdrCapabilities->dv_static_metadata.supports_10b_12b_444 & 0x2) ? L"Yes" : L"No"); + if (calls < 5) + { + SK_LOG0 ( ( L"NV_HDR_CAPABILITIES Version: %lu", pHdrCapabilities->version ), + __SK_SUBSYSTEM__ ); + SK_LOG0 ( ( L" >> Wants Driver to Expand Default HDR Params: %s", + pHdrCapabilities->driverExpandDefaultHdrParameters ? L"Yes" : + L"No" ), + __SK_SUBSYSTEM__ ); + + const SK_RenderBackend_V2::output_s* const pBackendDisplay = + SK_GetCurrentRenderBackend ().displays->nvapi.getDisplayFromId (displayId); + + dll_log->LogEx ( true, + L"[ HDR Caps ]\n" + L" +-----------------+---------------------\n" + L" | Red Primary.... | %f, %f\n" + L" | Green Primary.. | %f, %f\n" + L" | Blue Primary... | %f, %f\n" + L" | White Point.... | %f, %f\n" + L" | =============== |\n" + L" | Min Luminance.. | %10.5f cd/m²\n" + L" | Max Luminance.. | %10.5f cd/m²\n" + L" | |- FullFrame.. | %10.5f cd/m²\n" + L" | SDR Luminance.. | %10.5f cd/m²\n" + L" | =============== |\n" + L" | ST2084 EOTF.... | %s\n" + L" | CTA-861.3 HDR.. | %s\n" + L" | CTA-861.3 SDR.. | %s\n" + L" | =============== |\n" + L" | HDR10+......... | %s\n" + L" | HDR10+ Gaming.. | %s\n" + L" | =============== |\n" + L" | Dolby Vision... | %s\n" + L" | YUV 4:2:2 12bpc | %s\n" + L" | Low Latency.... | %s\n" + L" | |- 4:4:4 10bpc | %s\n" + L" | |- 4:4:4 12bpc | %s\n" + L" +-----------------+---------------------\n", + (float)pHdrCapabilities->display_data.displayPrimary_x0 / (float)0xC350, (float)pHdrCapabilities->display_data.displayPrimary_y0 / (float)0xC350, + (float)pHdrCapabilities->display_data.displayPrimary_x1 / (float)0xC350, (float)pHdrCapabilities->display_data.displayPrimary_y1 / (float)0xC350, + (float)pHdrCapabilities->display_data.displayPrimary_x2 / (float)0xC350, (float)pHdrCapabilities->display_data.displayPrimary_y2 / (float)0xC350, + (float)pHdrCapabilities->display_data.displayWhitePoint_x / (float)0xC350, (float)pHdrCapabilities->display_data.displayWhitePoint_y / (float)0xC350, + (float)pHdrCapabilities->display_data.desired_content_min_luminance * 0.0001f, + (float)pHdrCapabilities->display_data.desired_content_max_luminance, + (float)pHdrCapabilities->display_data.desired_content_max_frame_average_luminance, + pBackendDisplay != nullptr ? + pBackendDisplay->hdr.white_level : + (float)pHdrCapabilities->display_data.desired_content_max_frame_average_luminance, + pHdrCapabilities->isST2084EotfSupported ? L"Yes" : L"No", + pHdrCapabilities->isTraditionalHdrGammaSupported ? L"Yes" : L"No", + pHdrCapabilities->isTraditionalSdrGammaSupported ? L"Yes" : L"No", + pHdrCapabilities->isHdr10PlusSupported ? L"Yes" : L"No", + pHdrCapabilities->isHdr10PlusGamingSupported ? L"Yes" : L"No", + pHdrCapabilities->isDolbyVisionSupported ? L"Yes" : L"No", + pHdrCapabilities->dv_static_metadata.supports_YUV422_12bit ? L"Yes" : L"No", + (pHdrCapabilities->dv_static_metadata.interface_supported_by_sink + & 0x2) ? L"Yes" : L"No", + (pHdrCapabilities->dv_static_metadata.supports_10b_12b_444 & 0x1) ? L"Yes" : L"No", + (pHdrCapabilities->dv_static_metadata.supports_10b_12b_444 & 0x2) ? L"Yes" : L"No"); + } return ret; } diff --git a/src/plugins/reshade.cpp b/src/plugins/reshade.cpp index a56961b0e..34d527ed6 100644 --- a/src/plugins/reshade.cpp +++ b/src/plugins/reshade.cpp @@ -566,6 +566,20 @@ SK_ReShadeAddOn_ToggleOverlay (void) SK_ReShadeAddOn_ActivateOverlay (!ReShadeOverlayActive); } +void +__cdecl +SK_ReShadeAddOn_DisplayChange (reshade::api::effect_runtime *runtime, reshade::api::display* display) +{ + std::ignore = runtime; + std::ignore = display; + +#if 0 + SK_ImGui_Warning ( + SK_FormatStringW (L"ReShade Display Change: %ws - Max Luminance: %3.1f nits", display != nullptr ? display->get_display_name () : L"Unknown Monitor", display != nullptr ? display->get_luminance_caps ().max_nits : 0.0f).c_str () + ); +#endif +} + bool __cdecl SK_ReShadeAddOn_OverlayActivation (reshade::api::effect_runtime *runtime, bool open, reshade::api::input_source source) @@ -1150,6 +1164,7 @@ SK_ReShadeAddOn_Init (HMODULE reshade_module) reshade::register_event (SK_ReShadeAddOn_DestroySwapChain); reshade::register_event (SK_ReShadeAddOn_DestroyCmdQueue); reshade::register_event (SK_ReShadeAddOn_OverlayActivation); + reshade::register_event (SK_ReShadeAddOn_DisplayChange); auto _AutoLoadAddOns = [&](void) { @@ -1178,8 +1193,8 @@ SK_ReShadeAddOn_Init (HMODULE reshade_module) const auto filename = path.filename ().wstring (); const auto filename_utf8 = path.filename ().u8string (); - dll_log->LogEx ( - true, L"[ SpecialK ] * Loading ReShade AddOn: '%ws' from '%ws' ... ", + dll_log->Log ( + L"[ SpecialK ] * Loading ReShade AddOn: '%ws' from '%ws' ... ", filename.c_str (), SK_StripUserNameFromPathW (path.parent_path ().wstring ().data ()) ); @@ -1190,7 +1205,7 @@ SK_ReShadeAddOn_Init (HMODULE reshade_module) if (hModAddOn != skModuleRegistry::INVALID_MODULE) { - dll_log->LogEx (false, L"success!\n"); + //dll_log->LogEx (false, L"success!\n"); // Don't announce global AddOns if (! StrStrIW (path.c_str (), L"Global\\ReShade\\")) @@ -1209,7 +1224,7 @@ SK_ReShadeAddOn_Init (HMODULE reshade_module) { _com_error err (HRESULT_FROM_WIN32 (GetLastError ())); - dll_log->LogEx (false, L"failed: 0x%04X (%s)!\n", + dll_log->Log (L"LoadLibrary failed: 0x%04X (%s)!\n", err.WCode (), err.ErrorMessage () ); } } diff --git a/src/render/d3d11/d3d11.cpp b/src/render/d3d11/d3d11.cpp index 83347bed2..bf68f21a5 100644 --- a/src/render/d3d11/d3d11.cpp +++ b/src/render/d3d11/d3d11.cpp @@ -3046,6 +3046,8 @@ SK_D3D11_DrawHandler ( ID3D11DeviceContext *pDevCtx, return Normal; } + std::scoped_lock shader_lock (*cs_render_view); + using _Registry = SK_D3D11_KnownShaders::ShaderRegistry *; @@ -3207,6 +3209,8 @@ const for ( auto* tracker : trackers ) { + std::scoped_lock tracker_lock (*cs_render_view); + const bool active = tracker->active.get (dev_idx); @@ -3272,6 +3276,8 @@ const if (SK_D3D11_ShouldSkipHUD ()) { + std::scoped_lock hud_lock (*cs_render_view); + if ( vertex.hud.find (current_vs) != vertex.hud.cend () || pixel.hud.find (current_ps) != pixel.hud.cend () || geometry.hud.find (current_gs) != geometry.hud.cend () || @@ -3304,6 +3310,8 @@ const if ( blacklist_cache.count > 0 ) { + std::scoped_lock blacklist_lock (*cs_render_view); + if ( vertex.blacklist.find (current_vs) != vertex.blacklist.cend () || pixel.blacklist.find (current_ps) != pixel.blacklist.cend () || geometry.blacklist.find (current_gs) != geometry.blacklist.cend () || @@ -3336,6 +3344,8 @@ const auto& views = blacklist.first->current.views [dev_idx]; + std::scoped_lock blacklist_view_lock (*cs_render_view); + for (auto& it2 : views) { if (it2 == nullptr) @@ -3424,6 +3434,8 @@ const if (pDev != nullptr) { + std::scoped_lock auto_lock (*cs_render_view); + auto& pTLS_d3d11 = _SetupOverrideContext (); @@ -3493,6 +3505,8 @@ const if (pDev != nullptr) { + std::scoped_lock auto_lock (*cs_render_view); + auto& pTLS_d3d11 = _SetupOverrideContext (); @@ -3553,6 +3567,8 @@ const overrides = { nullptr }; + std::scoped_lock cbuffer_lock (*cs_render_view); + for (int i = 0; i < 5; i++) { if (current_shaders [i] == 0x00) @@ -6236,7 +6252,7 @@ D3D11Dev_CreateTexture2DCore_Impl ( if (cacheable) { cache_tag = - safe_crc32c (top_crc32, (uint8_t *)(pDesc), sizeof D3D11_TEXTURE2D_DESC); + safe_crc32c (top_crc32, (uint8_t *)(pDesc), sizeof (D3D11_TEXTURE2D_DESC)); // Adds and holds a reference pCachedTex = (ID3D11Texture2D1 *) @@ -9237,6 +9253,8 @@ D3D11Dev_GetImmediateContext3_Override ( void SK_D3D11_EndFrame (SK_TLS* pTLS) { + std::scoped_lock auto_lock2 (*cs_render_view); + for ( auto end_frame_fn : plugin_mgr->end_frame_fns ) { end_frame_fn (); @@ -9273,9 +9291,6 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) #ifdef TRACK_THREADS { - std::scoped_lock - auto_lock (*cs_render_view); - SK_D3D11_MemoryThreads->clear_active (); SK_D3D11_ShaderThreads->clear_active (); SK_D3D11_DrawThreads->clear_active (); @@ -9288,9 +9303,6 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) shaders->reshade_triggered = false; { - std::scoped_lock - auto_lock (*cs_render_view); - RtlZeroMemory ( reshade_trigger_before->data (), reshade_trigger_before->size () * sizeof (bool) ); RtlZeroMemory ( reshade_trigger_after->data (), @@ -9304,42 +9316,32 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) static auto& hull = shaders->hull; static auto& compute = shaders->compute; - { - const UINT dev_idx = - SK_D3D11_GetDeviceContextHandle (rb.d3d11.immediate_ctx); - - std::scoped_lock - auto_lock (*cs_render_view); + const UINT dev_idx = + SK_D3D11_GetDeviceContextHandle (rb.d3d11.immediate_ctx); - vertex.tracked.deactivate (nullptr, dev_idx); - pixel.tracked.deactivate (nullptr, dev_idx); - geometry.tracked.deactivate (nullptr, dev_idx); - hull.tracked.deactivate (nullptr, dev_idx); - domain.tracked.deactivate (nullptr, dev_idx); - compute.tracked.deactivate (nullptr, dev_idx); + vertex.tracked.deactivate (nullptr, dev_idx); + pixel.tracked.deactivate (nullptr, dev_idx); + geometry.tracked.deactivate (nullptr, dev_idx); + hull.tracked.deactivate (nullptr, dev_idx); + domain.tracked.deactivate (nullptr, dev_idx); + compute.tracked.deactivate (nullptr, dev_idx); - if (dev_idx < SK_D3D11_MAX_DEV_CONTEXTS) - { - RtlZeroMemory (vertex.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); - RtlZeroMemory (pixel.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); - RtlZeroMemory (geometry.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); - RtlZeroMemory (domain.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); - RtlZeroMemory (hull.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); - RtlZeroMemory (compute.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); - } + if (dev_idx < SK_D3D11_MAX_DEV_CONTEXTS) + { + RtlZeroMemory (vertex.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); + RtlZeroMemory (pixel.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); + RtlZeroMemory (geometry.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); + RtlZeroMemory (domain.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); + RtlZeroMemory (hull.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); + RtlZeroMemory (compute.current.views [dev_idx], sizeof (ID3D11ShaderResourceView*) * 128); } + tracked_rtv->clear (); - { - std::scoped_lock - auto_lock (*cs_render_view); - tracked_rtv->clear (); - - ////for ( auto& it : *used_textures ) it->Release (); + ////for ( auto& it : *used_textures ) it->Release (); - used_textures->clear (); - mem_map_stats->clear (); - } + used_textures->clear (); + mem_map_stats->clear (); // True if the disjoint query is complete and we can get the results of // each tracked shader's timing @@ -9371,7 +9373,7 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) HRESULT const hr = pDevCtx->GetData (d3d11_shader_tracking_s::disjoint_query.async, &d3d11_shader_tracking_s::disjoint_query.last_results, - sizeof D3D11_QUERY_DATA_TIMESTAMP_DISJOINT, + sizeof (D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), D3D11_ASYNC_GETDATA_DONOTFLUSH); if (hr == S_OK) @@ -9427,7 +9429,7 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) if ( dev_ctx != nullptr && SUCCEEDED ( dev_ctx->GetData (duration->start.async, &duration->start.last_results, - sizeof UINT64, D3D11_ASYNC_GETDATA_DONOTFLUSH) ) + sizeof (UINT64), D3D11_ASYNC_GETDATA_DONOTFLUSH) ) ) { duration->start.async = nullptr; @@ -9461,7 +9463,7 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) if ( dev_ctx != nullptr && SUCCEEDED ( dev_ctx->GetData (duration->end.async, &duration->end.last_results, - sizeof UINT64, D3D11_ASYNC_GETDATA_DONOTFLUSH) + sizeof (UINT64), D3D11_ASYNC_GETDATA_DONOTFLUSH) ) ) { @@ -9614,9 +9616,6 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) } } - const UINT dev_idx = - SK_D3D11_GetDeviceContextHandle (rb.d3d11.immediate_ctx); - if (it_ctx.ctx_id_ == dev_idx) { it_ctx.temp_resources.clear (); @@ -9628,12 +9627,7 @@ SK_D3D11_EndFrame (SK_TLS* pTLS) InterlockedExchange (&it_ctx.writing_, 0); } - { - std::scoped_lock - auto_lock (*cs_render_view); - - SK_D3D11_TempResources->clear (); - } + SK_D3D11_TempResources->clear (); SK_D3D11_Resampler_ProcessFinished (pDev, pDevCtx, pTLS); } diff --git a/src/render/d3d11/d3d11_screenshot.cpp b/src/render/d3d11/d3d11_screenshot.cpp index 54d4e4b98..af58dbfd8 100644 --- a/src/render/d3d11/d3d11_screenshot.cpp +++ b/src/render/d3d11/d3d11_screenshot.cpp @@ -333,12 +333,6 @@ SK_D3D11_Screenshot::SK_D3D11_Screenshot (const SK_ComPtr & pDevic else pImmediateCtx = rb.d3d11.immediate_ctx; - SK_ComQIPtr pImmediateCtx3 (pImmediateCtx); - - if ( pImmediateCtx3 != nullptr && - pImmediateCtx3 != pImmediateCtx ) - { pImmediateCtx = pImmediateCtx3; } - D3D11_QUERY_DESC fence_query_desc = { D3D11_QUERY_EVENT, @@ -682,6 +676,8 @@ SK_D3D11_Screenshot::SK_D3D11_Screenshot (const SK_ComPtr & pDevic pImmediateCtx->CopyResource ( pStagingBackbufferCopy, pBackbufferSurface ); } + + pBackbufferSurface.Release (); } else @@ -709,14 +705,12 @@ SK_D3D11_Screenshot::SK_D3D11_Screenshot (const SK_ComPtr & pDevic pImmediateCtx->CopyResource ( pStagingBackbufferCopy, pResolvedTex ); } - } - if (pImmediateCtx3 != nullptr) - { - pImmediateCtx3->Flush1 (D3D11_CONTEXT_TYPE_COPY, nullptr); + pBackbufferSurface.Release (); } - pImmediateCtx->End (pPixelBufferFence); + pImmediateCtx->End (pPixelBufferFence); + pImmediateCtx->Flush (); if (bPlaySound) SK_Screenshot_PlaySound (); @@ -911,6 +905,12 @@ volatile LONG __SK_D3D11_InitiateHudFreeShot = 0; SK_LazyGlobal > screenshot_queue; SK_LazyGlobal > screenshot_write_queue; +// Any incomplete captures are pushed onto this queue, and then the pending +// queue (once drained) is re-built. +// +// This is faster than iterating a synchronized list in highly multi-threaded engines. +SK_LazyGlobal > rejected_screenshots; +SK_LazyGlobal > raw_images_; static volatile LONG @@ -1824,9 +1824,6 @@ SK_D3D11_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_, continue; } - static concurrency::concurrent_queue - raw_images_; - SK_Screenshot::framebuffer_s* fb_orig = it->getFinishedData (); @@ -1854,7 +1851,7 @@ SK_D3D11_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_, fb_copy->PixelBuffer = std::move (fb_orig->PixelBuffer); - raw_images_.push (fb_copy); + raw_images_->push (fb_copy); ++enqueued_lossless; } @@ -2085,7 +2082,7 @@ SK_D3D11_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_, return 0; }, L"[SK] D3D11 Screenshot Encoder", - (LPVOID)&raw_images_ ); + (LPVOID)raw_images_.getPtr () ); } } if (enqueued_lossless > 0) @@ -2115,13 +2112,6 @@ SK_D3D11_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_, if (stage_ != SK_ScreenshotStage::_FlushQueue && wait == false && purge == false) return; - - // Any incomplete captures are pushed onto this queue, and then the pending - // queue (once drained) is re-built. - // - // This is faster than iterating a synchronized list in highly multi-threaded engines. - static concurrency::concurrent_queue rejected_screenshots; - bool new_jobs = false; do @@ -2152,16 +2142,16 @@ SK_D3D11_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_, } else - rejected_screenshots.push (pop_off); + rejected_screenshots->push (pop_off); } } } while ((! screenshot_queue->empty ()) && (purge || wait)); do { - SK_D3D11_Screenshot* push_back = nullptr; - if ( rejected_screenshots.try_pop (push_back) && - push_back != nullptr ) + SK_D3D11_Screenshot* push_back = nullptr; + if ( rejected_screenshots->try_pop (push_back) && + push_back != nullptr ) { if (purge) delete push_back; @@ -2169,13 +2159,13 @@ SK_D3D11_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_, else screenshot_queue->push (push_back); } - } while ((! rejected_screenshots.empty ()) && (purge || wait)); + } while ((! rejected_screenshots->empty ()) && (purge || wait)); if ( wait || purge ) { - if ( screenshot_queue->empty () && - rejected_screenshots.empty () ) + if ( screenshot_queue->empty () && + rejected_screenshots->empty () ) { if ( purge && (! screenshot_write_queue->empty ()) ) { diff --git a/src/render/d3d11/d3d11_shader.cpp b/src/render/d3d11/d3d11_shader.cpp index dfb50f880..a2ccdb743 100644 --- a/src/render/d3d11/d3d11_shader.cpp +++ b/src/render/d3d11/d3d11_shader.cpp @@ -952,7 +952,9 @@ SK_D3D11_SetShaderResources_Impl ( // current shader matches the debug tracker if ( (active && shader_crc32c == tracked.crc32c) && cs_lock != nullptr) { - std::scoped_lock auto_lock (*cs_lock); + std::lock (*cs_lock, *cs_render_view); + std::lock_guard auto_lock1 (*cs_lock, std::adopt_lock); + std::lock_guard auto_lock2 (*cs_render_view, std::adopt_lock); for (UINT i = 0; i < NumViews; i++) { @@ -2244,7 +2246,9 @@ const concurrency::concurrent_unordered_set auto_lock (*cs_render_view); + std::lock (*cs_shader, *cs_render_view); + std::lock_guard auto_lock1 (*cs_shader, std::adopt_lock); + std::lock_guard auto_lock2 (*cs_render_view, std::adopt_lock); SK_ComPtr pSRV2 = nullptr; @@ -2414,7 +2418,9 @@ SK_LiveShaderClassView (sk_shader_class shader_type, bool& can_scroll) ID3D11Device* pDevice = (ID3D11Device *)(SK_GetCurrentRenderBackend ().device.p); - std::scoped_lock auto_lock (*cs_shader); + std::lock (*cs_shader, *cs_render_view); + std::lock_guard auto_lock1 (*cs_shader, std::adopt_lock); + std::lock_guard auto_lock2 (*cs_render_view, std::adopt_lock); auto& io = ImGui::GetIO (); diff --git a/src/render/d3d11/hdr/d3d11_hdr.cpp b/src/render/d3d11/hdr/d3d11_hdr.cpp index fa6663ff6..62135a753 100644 --- a/src/render/d3d11/hdr/d3d11_hdr.cpp +++ b/src/render/d3d11/hdr/d3d11_hdr.cpp @@ -590,8 +590,8 @@ SK_HDR_SanitizeFP16SwapChain (void) { _ReadWriteBarrier (); - memcpy ( static_cast (mapped_resource.pData), - &cbuffer_luma, sizeof HDR_LUMINANCE ); + memcpy ( static_cast (mapped_resource.pData), + &cbuffer_luma, sizeof (HDR_LUMINANCE) ); pDevCtx->Unmap (hdr_base->mainSceneCBuffer, 0); @@ -611,8 +611,8 @@ SK_HDR_SanitizeFP16SwapChain (void) { _ReadWriteBarrier (); - memcpy ( static_cast (mapped_resource.pData), - &cbuffer_cspace, sizeof HDR_COLORSPACE_PARAMS ); + memcpy ( static_cast (mapped_resource.pData), + &cbuffer_cspace, sizeof (HDR_COLORSPACE_PARAMS) ); pDevCtx->Unmap (hdr_base->colorSpaceCBuffer, 0); @@ -945,8 +945,8 @@ SK_HDR_SnapshotSwapchain (void) { _ReadWriteBarrier (); - memcpy ( static_cast (mapped_resource.pData), - &cbuffer_luma, sizeof HDR_LUMINANCE ); + memcpy ( static_cast (mapped_resource.pData), + &cbuffer_luma, sizeof (HDR_LUMINANCE) ); pDevCtx->Unmap (hdr_base->mainSceneCBuffer, 0); } @@ -1004,8 +1004,8 @@ SK_HDR_SnapshotSwapchain (void) { _ReadWriteBarrier (); - memcpy ( static_cast (mapped_resource.pData), - &cbuffer_cspace, sizeof HDR_COLORSPACE_PARAMS ); + memcpy ( static_cast (mapped_resource.pData), + &cbuffer_cspace, sizeof (HDR_COLORSPACE_PARAMS) ); pDevCtx->Unmap (hdr_base->colorSpaceCBuffer, 0); } @@ -1239,7 +1239,7 @@ SK_D3D11_EndFrameHDR (void) HRESULT const hr = pDevCtx->GetData (SK_D3D11_HDRDisjointQuery.async, &SK_D3D11_HDRDisjointQuery.last_results, - sizeof D3D11_QUERY_DATA_TIMESTAMP_DISJOINT, + sizeof (D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), D3D11_ASYNC_GETDATA_DONOTFLUSH); if (hr == S_OK) @@ -1290,7 +1290,7 @@ SK_D3D11_EndFrameHDR (void) if ( dev_ctx != nullptr && SUCCEEDED ( dev_ctx->GetData (duration->start.async, &duration->start.last_results, - sizeof UINT64, D3D11_ASYNC_GETDATA_DONOTFLUSH) ) + sizeof (UINT64), D3D11_ASYNC_GETDATA_DONOTFLUSH) ) ) { duration->start.async = nullptr; @@ -1324,7 +1324,7 @@ SK_D3D11_EndFrameHDR (void) if ( dev_ctx != nullptr && SUCCEEDED ( dev_ctx->GetData (duration->end.async, &duration->end.last_results, - sizeof UINT64, D3D11_ASYNC_GETDATA_DONOTFLUSH) + sizeof (UINT64), D3D11_ASYNC_GETDATA_DONOTFLUSH) ) ) { diff --git a/src/render/d3d11/mod_tools/d3d11_shader_mods.cpp b/src/render/d3d11/mod_tools/d3d11_shader_mods.cpp index 80a03ab0e..1282afb55 100644 --- a/src/render/d3d11/mod_tools/d3d11_shader_mods.cpp +++ b/src/render/d3d11/mod_tools/d3d11_shader_mods.cpp @@ -265,15 +265,6 @@ SK_D3D11_ShaderModDlg (SK_TLS* pTLS = SK_TLS_Bottom ()) const SK_RenderBackend_V2& rb = SK_GetCurrentRenderBackend (); - std::scoped_lock < SK_Thread_HybridSpinlock, SK_Thread_HybridSpinlock, - SK_Thread_HybridSpinlock, SK_Thread_HybridSpinlock, - SK_Thread_HybridSpinlock, SK_Thread_HybridSpinlock, - SK_Thread_HybridSpinlock > - fort_knox ( *cs_shader, *cs_shader_vs, *cs_shader_ps, - *cs_shader_gs, *cs_shader_hs, *cs_shader_ds, - *cs_shader_cs ); - - const float font_size = (ImGui::GetFont ()->FontSize * io.FontGlobalScale); const float font_size_multiline = font_size + ImGui::GetStyle ().ItemSpacing.y + ImGui::GetStyle ().ItemInnerSpacing.y; @@ -293,6 +284,14 @@ SK_D3D11_ShaderModDlg (SK_TLS* pTLS = SK_TLS_Bottom ()) // SK_D3D11_DispatchThreads.count_active (), SK_D3D11_DispatchThreads.count_all () ).c_str (), &show_dlg ) ) { + std::scoped_lock < SK_Thread_HybridSpinlock, SK_Thread_HybridSpinlock, + SK_Thread_HybridSpinlock, SK_Thread_HybridSpinlock, + SK_Thread_HybridSpinlock, SK_Thread_HybridSpinlock, + SK_Thread_HybridSpinlock, SK_Thread_HybridSpinlock > + fort_knox ( *cs_shader, *cs_shader_vs, *cs_shader_ps, + *cs_shader_gs, *cs_shader_hs, *cs_shader_ds, + *cs_shader_cs, *cs_render_view ); + static bool draw_srv_overlay = false; static SK_ComPtr pOverlaySRV; diff --git a/src/render/d3d11/mod_tools/d3d11_texture_mods.cpp b/src/render/d3d11/mod_tools/d3d11_texture_mods.cpp index 426008837..8ac1b3746 100644 --- a/src/render/d3d11/mod_tools/d3d11_texture_mods.cpp +++ b/src/render/d3d11/mod_tools/d3d11_texture_mods.cpp @@ -143,7 +143,7 @@ SK_D3D11_LiveTextureView (bool& can_scroll, SK_TLS* pTLS = SK_TLS_Bottom ()) auto& Textures_2D = textures->Textures_2D; - std::scoped_lock auto_lock (*cs_render_view); + std::scoped_lock auto_lock (*cs_render_view); const float font_size = ImGui::GetFont ()->FontSize * io.FontGlobalScale; @@ -418,6 +418,8 @@ SK_D3D11_LiveTextureView (bool& can_scroll, SK_TLS* pTLS = SK_TLS_Bottom ()) if (list_dirty) { + std::scoped_lock auto_lock1 (*cs_render_view); + if (debug_tex_id == 0) last_ht = 0.0f; diff --git a/src/render/d3d11/tex_mgr/d3d11_tex_mgr.cpp b/src/render/d3d11/tex_mgr/d3d11_tex_mgr.cpp index 784feb743..385d75b6a 100644 --- a/src/render/d3d11/tex_mgr/d3d11_tex_mgr.cpp +++ b/src/render/d3d11/tex_mgr/d3d11_tex_mgr.cpp @@ -2504,8 +2504,11 @@ SK_D3D11_TextureIsCachedEx (ID3D11Texture2D* pTex, bool touch = false) bool use_l3 = config.textures.d3d11.use_l3_hash; - if (( use_l3 && textures->HashMap_Fmt [tex_desc.Format].map [tex_desc.MipLevels].contains (pTex)) || - (!use_l3 && textures->HashMap_2D [tex_desc.MipLevels].contains (pTex))) + if (( use_l3 && (size_t)tex_desc.Format < textures->HashMap_Fmt.size () && + tex_desc.MipLevels < textures->HashMap_Fmt [tex_desc.Format].map.size () && + textures->HashMap_Fmt [tex_desc.Format].map [tex_desc.MipLevels].contains (pTex)) || + (!use_l3 && tex_desc.MipLevels < textures->HashMap_2D.size () && + textures->HashMap_2D [tex_desc.MipLevels].contains (pTex))) { if (touch && (! SK_D3D11_IsTexInjectThread ())) { @@ -2608,6 +2611,78 @@ SK_D3D11_UseTexture (ID3D11Texture2D* pTex) SK_D3D11_TextureIsCachedEx (pTex, true); } +void +SK_D3D11_SafeCopyDebugName (ID3D11DeviceChild* pObject, std::string& debug_name) +{ + if (pObject == nullptr || (! debug_name.empty ())) + return; + + UINT uiDescLen = 127; + + __try + { + wchar_t wszDesc [128] = { }; + uiDescLen = sizeof (wszDesc) - sizeof (wchar_t); + + if ( SUCCEEDED ( + pObject->GetPrivateData ( + WKPDID_D3DDebugObjectNameW, + &uiDescLen, wszDesc ) + ) && uiDescLen > sizeof (wchar_t) + ) + { + wszDesc [127] = L'\0'; + + debug_name.resize (uiDescLen + / sizeof (wchar_t) + 1); + std::string_view d (debug_name.data (), 128); + SK_FormatStringView (d,"%ws",wszDesc); + } + } + __except (EXCEPTION_EXECUTE_HANDLER) {}; + + if (! debug_name.empty ()) + return; + + __try + { + char szDesc [128] = { }; + uiDescLen = sizeof (szDesc) - sizeof (char); + + if ( SUCCEEDED ( + pObject->GetPrivateData ( + WKPDID_D3DDebugObjectName, + &uiDescLen, szDesc ) + ) && uiDescLen > sizeof (char) + ) + { + szDesc [127] = '\0'; + + debug_name.assign (szDesc); + } + } + __except (EXCEPTION_EXECUTE_HANDLER) {}; +} + +void +SK_D3D11_SafeAssignTexDebugName (ID3D11Texture2D* tex_ref) +{ + __try + { + auto& tex_desc = + SK_D3D11_Textures->Textures_2D [tex_ref]; + + if (tex_desc.debug_name.empty ()) + { + SK_D3D11_SafeCopyDebugName (tex_ref, tex_desc.debug_name); + } + } + + __except (EXCEPTION_EXECUTE_HANDLER) + { + }; +} + bool __stdcall SK_D3D11_RemoveTexFromCache (ID3D11Texture2D* pTex, bool blacklist) @@ -2693,57 +2768,10 @@ SK_D3D11_TexMgr::updateDebugNames (void) if ( TexRefs_2D.count (it2.second) && Textures_2D.count (it2.second) ) { - const auto& tex_ref = - TexRefs_2D.find (it2.second); - - auto& tex_desc = - Textures_2D [*tex_ref]; - - if (tex_desc.debug_name.empty ()) + if (const auto& tex_ref = TexRefs_2D.find (it2.second); + tex_ref != TexRefs_2D.end ()) { - char szDesc [128] = { }; - wchar_t wszDesc [128] = { }; - UINT uiDescLen = 127; - - auto se_orig = - SK_SEH_ApplyTranslator ( - SK_FilteringStructuredExceptionTranslator ( - EXCEPTION_ACCESS_VIOLATION - ) - ); - try - { - uiDescLen = sizeof (wszDesc) - sizeof (wchar_t); - - if ( SUCCEEDED ( - (*tex_ref)->GetPrivateData ( - WKPDID_D3DDebugObjectNameW, - &uiDescLen, wszDesc ) - ) && uiDescLen > sizeof (wchar_t) - ) - { - tex_desc.debug_name = - SK_WideCharToUTF8 (wszDesc); - } - - else - { - uiDescLen = sizeof (szDesc) - sizeof (char); - - if ( SUCCEEDED ( - (*tex_ref)->GetPrivateData ( - WKPDID_D3DDebugObjectName, - &uiDescLen, szDesc ) - ) && uiDescLen > sizeof (char) - ) - { - tex_desc.debug_name = - szDesc; - } - } - } - catch (const SK_SEH_IgnoredException&) { } - SK_SEH_RemoveTranslator (se_orig); + SK_D3D11_SafeAssignTexDebugName (*tex_ref); } } } diff --git a/src/render/d3d12/d3d12_screenshot.cpp b/src/render/d3d12/d3d12_screenshot.cpp index 1dde5c754..19f5362b3 100644 --- a/src/render/d3d12/d3d12_screenshot.cpp +++ b/src/render/d3d12/d3d12_screenshot.cpp @@ -813,6 +813,12 @@ volatile LONG __SK_D3D12_InitiateHudFreeShot = 0; SK_LazyGlobal > screenshot_queue; SK_LazyGlobal > screenshot_write_queue; +// Any incomplete captures are pushed onto this queue, and then the pending +// queue (once drained) is re-built. +// +// This is faster than iterating a synchronized list in highly multi-threaded engines. +SK_LazyGlobal > rejected_screenshots; +SK_LazyGlobal > raw_images_; //static volatile LONG @@ -1054,6 +1060,15 @@ SK_D3D12_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_ = SK_ScreenshotSta bool wait = false, bool purge = false ) { + static std::atomic_int run_count = 0; + + if (stage_ != SK_ScreenshotStage::_FlushQueue) + ++run_count; + + else if (run_count == 0) + return; + + const SK_RenderBackend& rb = SK_GetCurrentRenderBackend (); @@ -1790,9 +1805,6 @@ SK_D3D12_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_ = SK_ScreenshotSta continue; } - static concurrency::concurrent_queue - raw_images_; - SK_Screenshot::framebuffer_s* fb_orig = it->getFinishedData (); @@ -1820,7 +1832,7 @@ SK_D3D12_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_ = SK_ScreenshotSta fb_copy->PixelBuffer = std::move (fb_orig->PixelBuffer); - raw_images_.push (fb_copy); + raw_images_->push (fb_copy); ++enqueued_lossless; } @@ -2107,7 +2119,7 @@ SK_D3D12_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_ = SK_ScreenshotSta return 0; }, L"[SK] D3D12 Screenshot Encoder", - (LPVOID)&raw_images_ ); + (LPVOID)raw_images_.getPtr () ); } } if (enqueued_lossless > 0) @@ -2137,13 +2149,6 @@ SK_D3D12_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_ = SK_ScreenshotSta if (stage_ != SK_ScreenshotStage::_FlushQueue && wait == false && purge == false) return; - - // Any incomplete captures are pushed onto this queue, and then the pending - // queue (once drained) is re-built. - // - // This is faster than iterating a synchronized list in highly multi-threaded engines. - static concurrency::concurrent_queue rejected_screenshots; - bool new_jobs = false; do @@ -2174,16 +2179,16 @@ SK_D3D12_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_ = SK_ScreenshotSta } else - rejected_screenshots.push (pop_off); + rejected_screenshots->push (pop_off); } } } while ((! screenshot_queue->empty ()) && (purge || wait)); do { - SK_D3D12_Screenshot* push_back = nullptr; - if ( rejected_screenshots.try_pop (push_back) && - push_back != nullptr ) + SK_D3D12_Screenshot* push_back = nullptr; + if ( rejected_screenshots->try_pop (push_back) && + push_back != nullptr ) { if (purge) delete push_back; @@ -2191,13 +2196,13 @@ SK_D3D12_ProcessScreenshotQueueEx ( SK_ScreenshotStage stage_ = SK_ScreenshotSta else screenshot_queue->push (push_back); } - } while ((!rejected_screenshots.empty ()) && (purge || wait)); + } while ((!rejected_screenshots->empty ()) && (purge || wait)); if ( wait || purge ) { - if ( screenshot_queue->empty () && - rejected_screenshots.empty () ) + if ( screenshot_queue->empty () && + rejected_screenshots->empty () ) { if ( purge && (! screenshot_write_queue->empty ()) ) { diff --git a/src/render/dxgi/dxgi_swapchain.cpp b/src/render/dxgi/dxgi_swapchain.cpp index 64c65fba5..50fc48d46 100644 --- a/src/render/dxgi/dxgi_swapchain.cpp +++ b/src/render/dxgi/dxgi_swapchain.cpp @@ -2054,7 +2054,37 @@ SK_DXGI_SwapChain_ResizeBuffers_Impl ( if (SUCCEEDED (ret)) { if (rb.api == SK_RenderAPI::D3D12) _d3d12_rbk->init ((IDXGISwapChain3 *)pSwapChain, _d3d12_rbk->_pCommandQueue); - else if (rb.api == SK_RenderAPI::D3D11) _d3d11_rbk->init ((IDXGISwapChain3 *)pSwapChain, _d3d11_rbk->_pDevice, _d3d11_rbk->_pDeviceCtx); + else if (rb.api == SK_RenderAPI::D3D11) + { // The D3D11 backend releases device and device context, unlike D3D12 that has a + // persistent command queue object across destruction and creation of new swapchains. + SK_ComPtr pDevice (_d3d11_rbk->_pDevice); + SK_ComPtr pDeviceCtx (_d3d11_rbk->_pDeviceCtx); + + if ( pDevice && !pDeviceCtx.p) + pDevice->GetImmediateContext (&pDeviceCtx.p); + else if (pDeviceCtx && !pDevice.p) + pDeviceCtx->GetDevice (&pDevice.p); + if (SUCCEEDED(pSwapChain->GetDevice (IID_ID3D11Device, + reinterpret_cast(&pDevice.p)))) + pDevice-> + GetImmediateContext(&pDeviceCtx.p); + + if (rb.device == nullptr) + { + rb.setDevice (pDevice); + rb.d3d11.immediate_ctx = pDeviceCtx; + } + + _d3d11_rbk->init ((IDXGISwapChain3 *)pSwapChain, pDevice, pDeviceCtx); + } + } + + else + { + rb.releaseOwnedResources (); + + if (rb.api == SK_RenderAPI::D3D12) ResetImGui_D3D12 (pSwapChain); + else if (rb.api == SK_RenderAPI::D3D11) ResetImGui_D3D11 (pSwapChain); } }; @@ -2386,10 +2416,16 @@ SK_DXGI_SwapChain_ResizeBuffers_Impl ( { if (ret != DXGI_ERROR_DEVICE_REMOVED && ret != E_ACCESSDENIED) { - SK_LOGi0 ( L"SwapChain Resize Failed (%x) - Error Suppressed!", - ret ); + SK_LOGi0 ( L"SwapChain Resize Failed [%x](%ws)!", + ret, _com_error (ret).ErrorMessage () ); _ReleaseResourcesAndRetryResize (ret); + + if (SUCCEEDED (ret)) + { + SK_LOGi0 (L" # Successfully recovered after a full teardown of all " + L"owned and shared SwapChain resources."); + } } } @@ -2463,10 +2499,16 @@ SK_DXGI_SwapChain_ResizeBuffers_Impl ( { if (ret != DXGI_ERROR_DEVICE_REMOVED && ret != E_ACCESSDENIED) { - SK_LOGi0 ( L"SwapChain Resize Failed (%x) - Error Suppressed!", - ret ); + SK_LOGi0 ( L"SwapChain Resize Failed [%x](%ws)!", + ret, _com_error (ret).ErrorMessage () ); _ReleaseResourcesAndRetryResize (ret); + + if (SUCCEEDED (ret)) + { + SK_LOGi0 (L" # Successfully recovered after a full teardown of all " + L"owned and shared SwapChain resources."); + } } } @@ -2476,6 +2518,12 @@ SK_DXGI_SwapChain_ResizeBuffers_Impl ( rb.swapchain_consistent = SUCCEEDED (ret); + if (rb.swapchain_consistent) + { + SK_LOGi0 (L" # Successfully recovered after a full teardown of all " + L"owned and shared SwapChain resources."); + } + if (SK_IsDebuggerPresent ()) { SK_DXGI_OutputDebugString ( "IDXGISwapChain::ResizeBuffers (...) failed, look alive...", diff --git a/src/render/render_backend.cpp b/src/render/render_backend.cpp index 37373d137..7e17df550 100644 --- a/src/render/render_backend.cpp +++ b/src/render/render_backend.cpp @@ -1150,6 +1150,7 @@ SK_RenderBackend_V2::requestFullscreenMode (bool override) SUCCEEDED (SK_DXGI_ResizeTarget (pSwapChain, &swap_desc.BufferDesc, TRUE)) ) { + if (config.compatibility.allow_fake_size) PostMessage ( swap_desc.OutputWindow, WM_SIZE, SIZE_RESTORED, MAKELPARAM ( swap_desc.BufferDesc.Width, swap_desc.BufferDesc.Height ) ); diff --git a/src/render/screenshot.cpp b/src/render/screenshot.cpp index e94370d1b..a59f49593 100644 --- a/src/render/screenshot.cpp +++ b/src/render/screenshot.cpp @@ -358,22 +358,27 @@ SK_PNG_CopyToClipboard (const DirectX::Image& image, const void *pData, size_t d wcscpy ((wchar_t*)&df [1], (const wchar_t *)pData); bool clipboard_open = false; - for (UINT i = 0 ; i < 20 ; ++i) + + for (auto attempts = 0; attempts < 8; ++attempts) { - clipboard_open = OpenClipboard (game_window.hWnd); + if (attempts > 0) + { + SK_Sleep (1 << (attempts - 1)); + } - if (clipboard_open) + if (OpenClipboard (game_window.hWnd)) + { + clipboard_open = true; break; - - SK_Sleep (5); + } } if (clipboard_open) { EmptyClipboard (); SetClipboardData (CF_HDROP, hdrop); - GlobalUnlock (hdrop); CloseClipboard (); + GlobalUnlock ( hdrop); return true; } @@ -524,14 +529,19 @@ SK_ScreenshotManager::copyToClipboard ( const DirectX::Image& image, SelectObject (hdcDst, hbmpDst); bool clipboard_open = false; - for (UINT i = 0 ; i < 20 ; ++i) + + for (auto attempts = 0; attempts < 8; ++attempts) { - clipboard_open = OpenClipboard (game_window.hWnd); + if (attempts > 0) + { + SK_Sleep (1 << (attempts - 1)); + } - if (clipboard_open) + if (OpenClipboard (game_window.hWnd)) + { + clipboard_open = true; break; - - SK_Sleep (5); + } } if (clipboard_open) @@ -2182,15 +2192,7 @@ SK_PNG_MakeHDR ( const wchar_t* wszFilePath, // Write the remainder of the original file fwrite (insert_ptr, size - insert_pos, 1, fPNG); - - auto final_size = - ftell (fPNG); - - auto full_png = - std::make_unique (final_size); - - rewind (fPNG); - fread (full_png.get (), final_size, 1, fPNG); + fflush (fPNG); fclose (fPNG); SK_LOGi1 (L"Applied HDR10 PNG chunks to %ws.", wszFilePath); diff --git a/src/steam/steam_api.cpp b/src/steam/steam_api.cpp index 459aba7cc..2b9be9ef9 100644 --- a/src/steam/steam_api.cpp +++ b/src/steam/steam_api.cpp @@ -5422,7 +5422,7 @@ SK_Steam_PiratesAhoy (void) // Older versions of SteamAPI may not support the necessary interface version if ( pUtils != nullptr && pApps != nullptr && - validation_pass != SK_Steam_FileSigPass_e::Done ) + validation_pass != SK_Steam_FileSigPass_e::Done && !SK_IsCurrentGame (SK_GAME_ID::Fallout4) ) { DepotId_t depots [16] = { }; diff --git a/src/widgets/hdr.cpp b/src/widgets/hdr.cpp index dbca136f7..c375bb9f9 100644 --- a/src/widgets/hdr.cpp +++ b/src/widgets/hdr.cpp @@ -1233,11 +1233,13 @@ class SKWG_HDR_Control : public SK_Widget, SK_IVariableListener // Trigger the game to resize the SwapChain so we can change its format and colorspace // + if (config.compatibility.allow_fake_size) PostMessage ( game_window.hWnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM (game_window.actual.client.right - game_window.actual.client.left, game_window.actual.client.bottom - game_window.actual.client.top ) ); + if (config.compatibility.allow_fake_displaychange) PostMessage ( game_window.hWnd, WM_DISPLAYCHANGE, 32, MAKELPARAM (game_window.actual.client.right - game_window.actual.client.left, game_window.actual.client.bottom - diff --git a/src/window.cpp b/src/window.cpp index 549286bd8..938227ba1 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -53,6 +53,32 @@ static constexpr int SK_MAX_WINDOW_DIM = 16384; # define SK_WINDOW_LOG_CALL_UNTESTED() { } #endif +using SetWindowDisplayAffinity_pfn = BOOL (WINAPI *)(HWND,DWORD); +static SetWindowDisplayAffinity_pfn + SetWindowDisplayAffinity_Original = nullptr; + +BOOL +WINAPI +SetWindowDisplayAffinity_Detour ( + _In_ HWND hWnd, + _In_ DWORD dwAffinity ) +{ + SK_LOG_FIRST_CALL + + if (dwAffinity != WDA_NONE) + { + SK_LOGi0 ( + L"SetWindowDisplayAffinity (...) called with dwAffinity = %x on HWND %x", + dwAffinity, hWnd + ); + } + + dwAffinity = WDA_NONE; + + return + SetWindowDisplayAffinity_Original (hWnd, dwAffinity); +} + BOOL WINAPI SetWindowPlacement_Detour ( @@ -3473,7 +3499,7 @@ SK_Window_RepositionIfNeeded (void) dwWaitState = WaitForMultipleObjects (2, hSignals, FALSE, INFINITE); - while (ullLastFrame == SK_GetFramesDrawn ()) + while (ullLastFrame > SK_GetFramesDrawn () - 5) { if (WaitForSingleObject (hSignals [0], 3UL) == _EndSignal) { @@ -3518,63 +3544,68 @@ SK_Window_RepositionIfNeeded (void) SK_RunOnce (rb.updateOutputTopology ()); + bool move_monitors = rb.monitor != rb.next_monitor && rb.next_monitor != 0; + + //HMONITOR hMonitorBeforeRepos = + // MonitorFromWindow (game_window.hWnd, MONITOR_DEFAULTTONEAREST); + if (! rb.isTrueFullscreen ()) { - if ( center || - borderless || - - (rb.monitor != rb.next_monitor && - rb.next_monitor != 0) || - - lastFullscreen != fullscreen || - lastBorderless != borderless || - lastCenter != center || - lastOffset.x.absolute != config.window.offset.x.absolute || - lastOffset.y.absolute != config.window.offset.y.absolute || - lastOffset.x.percent != config.window.offset.x.percent || - lastOffset.y.percent != config.window.offset.y.percent || - lastResOverride.override.x != config.window.res.override.x || - lastResOverride.override.y != config.window.res.override.y || - - (! EqualRect (&rcClientOrig, &rcClientLast)) || - (! EqualRect (&rcWindowOrig, &rcWindowLast)) ) - { - if (rb.monitor != rb.next_monitor && rb.next_monitor != 0) + if ( center || + borderless || + + (rb.monitor != rb.next_monitor && + rb.next_monitor != 0) || + + lastFullscreen != fullscreen || + lastBorderless != borderless || + lastCenter != center || + lastOffset.x.absolute != config.window.offset.x.absolute || + lastOffset.y.absolute != config.window.offset.y.absolute || + lastOffset.x.percent != config.window.offset.x.percent || + lastOffset.y.percent != config.window.offset.y.percent || + lastResOverride.override.x != config.window.res.override.x || + lastResOverride.override.y != config.window.res.override.y || + + (! EqualRect (&rcClientOrig, &rcClientLast)) || + (! EqualRect (&rcWindowOrig, &rcWindowLast)) ) { - // We have to either center the window or stretch it to move monitors, - // if user's preference is neither, then stretch it temporarily. - switch (config.window.borderless) + if (rb.monitor != rb.next_monitor && rb.next_monitor != 0) { - case true: - config.window.fullscreen |= - ( center == false && fullscreen == false ); - break; - - default: - config.window.center = true; - break; + // We have to either center the window or stretch it to move monitors, + // if user's preference is neither, then stretch it temporarily. + switch (config.window.borderless) + { + case true: + config.window.fullscreen |= + ( center == false && fullscreen == false ); + break; + + default: + config.window.center = true; + break; + } } - } - SK_AdjustBorder (); - SK_AdjustWindow (); + SK_AdjustBorder (); + SK_AdjustWindow (); - lastBorderless = borderless; - lastCenter = center; - lastFullscreen = fullscreen; - - lastOffset.x.absolute = config.window.offset.x.absolute; - lastOffset.y.absolute = config.window.offset.y.absolute; - lastOffset.x.percent = config.window.offset.x.percent; - lastOffset.y.percent = config.window.offset.y.percent; - - if (std::exchange (lastResOverride.override.x, config.window.res.override.x) - != config.window.res.override.x) - _overrideRes = true; - if (std::exchange (lastResOverride.override.y, config.window.res.override.y) - != config.window.res.override.y) - _overrideRes = true; - } + lastBorderless = borderless; + lastCenter = center; + lastFullscreen = fullscreen; + + lastOffset.x.absolute = config.window.offset.x.absolute; + lastOffset.y.absolute = config.window.offset.y.absolute; + lastOffset.x.percent = config.window.offset.x.percent; + lastOffset.y.percent = config.window.offset.y.percent; + + if (std::exchange (lastResOverride.override.x, config.window.res.override.x) + != config.window.res.override.x) + _overrideRes = true; + if (std::exchange (lastResOverride.override.y, config.window.res.override.y) + != config.window.res.override.y) + _overrideRes = true; + } } SK_GetWindowRect (game_window.hWnd, &game_window.actual.window); @@ -3616,16 +3647,27 @@ SK_Window_RepositionIfNeeded (void) SK_Display_ResolutionSelectUI (true); rb.gsync_state.update (true); - PostMessage ( game_window.hWnd, WM_SIZE, SIZE_RESTORED, - MAKELPARAM (game_window.actual.client.right - - game_window.actual.client.left, game_window.actual.client.bottom - - game_window.actual.client.top ) - ); - PostMessage ( game_window.hWnd, WM_DISPLAYCHANGE, 32, - MAKELPARAM (game_window.actual.client.right - - game_window.actual.client.left, game_window.actual.client.bottom - - game_window.actual.client.top ) - ); + // We programatically moved the window to a different monitor, so we need to + // send the game a few messages to get the SwapChain to be owned by that + // monitor... + if (move_monitors || !config.display.monitor_path_ccd.empty ()) + // This generally helps (Unity engine games mostly) to apply SwapChain overrides + // immediately, but ATLUS games will respond by moving the game back to the primary + // monitor... + { + if (config.compatibility.allow_fake_size) + PostMessage ( game_window.hWnd, WM_SIZE, SIZE_RESTORED, + MAKELPARAM (game_window.actual.client.right - + game_window.actual.client.left, game_window.actual.client.bottom - + game_window.actual.client.top ) + ); + if (config.compatibility.allow_fake_displaychange) + PostMessage ( game_window.hWnd, WM_DISPLAYCHANGE, 32, + MAKELPARAM (game_window.actual.client.right - + game_window.actual.client.left, game_window.actual.client.bottom - + game_window.actual.client.top ) + ); + } } // Clear any window move requests @@ -3654,6 +3696,12 @@ SK_Window_RepositionIfNeeded (void) void SK_AdjustClipRect (void) { + if (game_window.size_move) + { + SK_ClipCursor (nullptr); + return; + } + // Post-Process Results: // // If window is moved as a result of this function, we need to: @@ -5709,6 +5757,14 @@ SK_DetourWindowProc ( _In_ HWND hWnd, } } break; + case WM_GETMINMAXINFO: + return 0; + + case WM_ENTERSIZEMOVE: + case WM_EXITSIZEMOVE: + ImGui_WndProcHandler (hWnd, uMsg, wParam, lParam); + break; + case WM_MOUSEMOVE: //if (hWnd == game_window.hWnd || hWnd == game_window.child) { @@ -5971,7 +6027,7 @@ SK_DetourWindowProc ( _In_ HWND hWnd, ActivateWindow (hWnd, true); - if (! SK_ImGui_WantMouseCapture ()) + if (! SK_ImGui_WantMouseButtonCapture ()) return MA_ACTIVATE; // We don't want it, and the game doesn't expect it else return MA_ACTIVATEANDEAT; // We want it, game doesn't need it @@ -6011,7 +6067,7 @@ SK_DetourWindowProc ( _In_ HWND hWnd, L"Window Mgr" ); ActivateWindow (hWnd, true); - + if (SK_WantBackgroundRender ()) SK_DetourWindowProc ( hWnd, WM_SETFOCUS, (WPARAM)nullptr, (LPARAM)nullptr ); } @@ -6029,10 +6085,6 @@ SK_DetourWindowProc ( _In_ HWND hWnd, game_window.DefWindowProc ( hWnd, uMsg, wParam, lParam ); - ////SK_COMPAT_SafeCallProc (&game_window, - //// hWnd, uMsg, TRUE, lParam - ////); - SK_DetourWindowProc ( hWnd, WM_KILLFOCUS, (WPARAM)nullptr, (LPARAM)nullptr ); HWND hWndForeground = @@ -6066,10 +6118,6 @@ SK_DetourWindowProc ( _In_ HWND hWnd, game_window.DefWindowProc ( hWnd, uMsg, wParam, lParam ); - //SK_COMPAT_SafeCallProc (&game_window, - // hWnd, uMsg, TRUE, 0 - //); - SK_DetourWindowProc ( hWnd, WM_KILLFOCUS, (WPARAM)nullptr, (LPARAM)nullptr ); return 0; @@ -6078,7 +6126,7 @@ SK_DetourWindowProc ( _In_ HWND hWnd, else if (SK_WantBackgroundRender ()) { - ActivateWindow (hWnd, true); + ActivateWindow ( hWnd, true ); SK_DetourWindowProc ( hWnd, WM_SETFOCUS, (WPARAM)nullptr, (LPARAM)nullptr ); } } @@ -6109,11 +6157,12 @@ SK_DetourWindowProc ( _In_ HWND hWnd, } break; } - if (last_active) + if (game_window.active) { if (! activate) { - ActivateWindow (hWnd, activate); + if (! (! rb.isTrueFullscreen ()) && SK_WantBackgroundRender () ) + ActivateWindow (hWnd, activate); SK_LOG2 ( ( L"Application Deactivated %s", source ), L"Window Mgr" ); @@ -6136,12 +6185,9 @@ SK_DetourWindowProc ( _In_ HWND hWnd, if (! activate) { game_window.DefWindowProc ( hWnd, uMsg, - wParam, lParam ); - - SK_DetourWindowProc ( hWnd, WM_KILLFOCUS, (WPARAM)nullptr, (LPARAM)nullptr ); - ActivateWindow ( hWnd, false ); + wParam, lParam ); - return 1; + return 0; } else @@ -7273,6 +7319,10 @@ SK_MakeWindowHook (WNDPROC class_proc, WNDPROC wnd_proc, HWND hWnd) } + if ( SetWindowDisplayAffinity_Original != nullptr) + SetWindowDisplayAffinity_Original (game_window.hWnd, WDA_NONE); + else SetWindowDisplayAffinity (game_window.hWnd, WDA_NONE); + dll_log->Log ( L"[Window Mgr] Hooking the Window Procedure for " L"%s Window Class ('%s' - \"%s\" * %x)", game_window.unicode ? L"Unicode" : L"ANSI", @@ -7439,6 +7489,16 @@ SK_MakeWindowHook (WNDPROC class_proc, WNDPROC wnd_proc, HWND hWnd) SK_GetCurrentRenderBackend ().windows.sdl = true; } + else if (SK_GetCurrentGameID () == SK_GAME_ID::Metaphor || + SK_GetCurrentGameID () == SK_GAME_ID::Persona4 || + SK_GetCurrentGameID () == SK_GAME_ID::Persona5 || + SK_GetCurrentGameID () == SK_GAME_ID::Persona5Strikers) + { + SK_GetCurrentRenderBackend ().windows.atlus = true; + config.compatibility.allow_fake_displaychange = false; + config.compatibility.allow_fake_size = false; + } + if (SK_IsInjected ()) { @@ -7913,6 +7973,11 @@ SK_HookWinAPI (void) GetGUIThreadInfo_Detour, static_cast_p2p (&GetGUIThreadInfo_Original) ); + SK_CreateDLLHook2 ( L"user32", + "SetWindowDisplayAffinity", + SetWindowDisplayAffinity_Detour, + static_cast_p2p (&SetWindowDisplayAffinity_Original) ); + GetWindowBand = (GetWindowBand_pfn)SK_GetProcAddress (L"user32.dll", "GetWindowBand"); @@ -8180,7 +8245,7 @@ WINAPI SK_ClipCursor (const RECT *lpRect) { // Do not allow cursor clipping when the game's window is inactive - if (! game_window.active) + if ((! game_window.active) || (game_window.size_move)) // Or being moved lpRect = nullptr; return