├── .gitignore ├── .gitmodules ├── LICENSE.md ├── README.md ├── ReShade.sln ├── ReShade.vcxproj ├── ReShade.vcxproj.filters ├── ReShadeFX.vcxproj ├── ReShadeFX.vcxproj.filters ├── deps ├── ImGui.props ├── ImGui.vcxproj ├── MinHook.props ├── MinHook.vcxproj ├── MinHook.vcxproj.filters ├── Windows.props ├── gl3w.props ├── gl3w.vcxproj ├── stb.props ├── stb.vcxproj ├── stb_image_dds │ └── stb_image_dds.h └── stb_impl.c ├── res ├── exports.def ├── resource.h ├── resource.rc ├── resource.rc2 ├── shader_copy_ps.hlsl ├── shader_copy_vs.hlsl ├── shader_imgui_ps.hlsl └── shader_imgui_vs.hlsl ├── setup ├── Glass.cs ├── IniFile.cs ├── PEInfo.cs ├── Properties │ ├── App.xaml │ ├── Assembly.manifest │ ├── AssemblyInfo.cs │ └── Icon.ico ├── ReShade Setup.csproj ├── Select.xaml ├── Select.xaml.cs ├── Wizard.xaml └── Wizard.xaml.cs ├── source ├── com_ptr.hpp ├── constant_folding.cpp ├── d3d10 │ ├── d3d10.cpp │ ├── d3d10.hpp │ ├── d3d10_device.cpp │ ├── d3d10_device.hpp │ ├── d3d10_effect_compiler.cpp │ ├── d3d10_effect_compiler.hpp │ ├── d3d10_runtime.cpp │ ├── d3d10_runtime.hpp │ ├── d3d10_stateblock.cpp │ └── d3d10_stateblock.hpp ├── d3d11 │ ├── d3d11.cpp │ ├── d3d11.hpp │ ├── d3d11_device.cpp │ ├── d3d11_device.hpp │ ├── d3d11_device_context.cpp │ ├── d3d11_device_context.hpp │ ├── d3d11_effect_compiler.cpp │ ├── d3d11_effect_compiler.hpp │ ├── d3d11_runtime.cpp │ ├── d3d11_runtime.hpp │ ├── d3d11_stateblock.cpp │ └── d3d11_stateblock.hpp ├── d3d9 │ ├── d3d9.cpp │ ├── d3d9.hpp │ ├── d3d9_device.cpp │ ├── d3d9_device.hpp │ ├── d3d9_effect_compiler.cpp │ ├── d3d9_effect_compiler.hpp │ ├── d3d9_runtime.cpp │ ├── d3d9_runtime.hpp │ ├── d3d9_swapchain.cpp │ └── d3d9_swapchain.hpp ├── directory_watcher.cpp ├── directory_watcher.hpp ├── dllmain.cpp ├── dllmodule.cpp ├── dllmodule.hpp ├── dxgi │ ├── dxgi.cpp │ ├── dxgi.hpp │ ├── dxgi_device.cpp │ ├── dxgi_device.hpp │ ├── dxgi_swapchain.cpp │ └── dxgi_swapchain.hpp ├── effect_lexer.cpp ├── effect_lexer.hpp ├── effect_parser.cpp ├── effect_parser.hpp ├── effect_preprocessor.cpp ├── effect_preprocessor.hpp ├── effect_symbol_table.cpp ├── effect_symbol_table.hpp ├── effect_syntax_tree.hpp ├── effect_syntax_tree_nodes.hpp ├── filesystem.cpp ├── filesystem.hpp ├── hook.cpp ├── hook.hpp ├── hook_manager.cpp ├── hook_manager.hpp ├── ini_file.cpp ├── ini_file.hpp ├── input.cpp ├── input.hpp ├── log.cpp ├── log.hpp ├── module.cpp ├── module.hpp ├── moving_average.hpp ├── opengl │ ├── opengl_effect_compiler.cpp │ ├── opengl_effect_compiler.hpp │ ├── opengl_runtime.cpp │ ├── opengl_runtime.hpp │ ├── opengl_stateblock.cpp │ ├── opengl_stateblock.hpp │ ├── opengl_stubs.hpp │ ├── opengl_stubs_internal.hpp │ ├── stubs_gl.cpp │ └── stubs_wgl.cpp ├── resource_loading.cpp ├── resource_loading.hpp ├── runtime.cpp ├── runtime.hpp ├── runtime_objects.cpp ├── runtime_objects.hpp ├── source_location.hpp ├── string_codecvt.hpp ├── variant.hpp └── windows │ ├── user32.cpp │ └── ws2_32.cpp └── tools └── verbuild.exe /.gitignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | [Bb]in/ 3 | [Oo]bj/ 4 | [Ii]ntermediate/ 5 | [Bb]uild/ 6 | [Dd]ebug/ 7 | [Rr]elease/ 8 | *.cso 9 | 10 | # Visual Studio cache files 11 | .vs/ 12 | ipch/ 13 | *.aps 14 | *.VC.db 15 | *.VC.opendb 16 | *.sdf 17 | *.opensdf 18 | *.suo 19 | *.user 20 | 21 | # Temporary OS files 22 | .DS_Store 23 | Thumbs.db 24 | 25 | # Versioning 26 | /res/Version.h 27 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "imgui"] 2 | path = deps/imgui 3 | url = https://github.com/ocornut/imgui.git 4 | [submodule "minhook"] 5 | path = deps/minhook 6 | url = https://github.com/TsudaKageyu/minhook.git 7 | [submodule "stb"] 8 | path = deps/stb 9 | url = https://github.com/nothings/stb.git 10 | [submodule "gl3w"] 11 | path = deps/gl3w 12 | url = https://github.com/skaslev/gl3w.git 13 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2014 Patrick Mours. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ReShade 2 | ======= 3 | 4 | ReShade is an advanced, fully generic post-processing injector for games and video software. Imagine your favorite game with ambient occlusion, real depth of field effects, color correction and more ... ReShade exposes an automated and generic way to access both frame color and depth information and all the tools to make it happen. 5 | 6 | ## Building 7 | 8 | You'll need both Git and Visual Studio 2017 or higher to build ReShade. Latter is required since the project makes use of some C++14 and C++17 features. Additionally a Python 2.7.9 or later (Python 3 is supported as well) installation is necessary for the `gl3w` dependency to build. 9 | 10 | 1. Clone this repository including all Git submodules 11 | 2. Open the Visual Studio solution 12 | 3. Select either the "32-bit" or "64-bit" target platform and build the solution (this will build ReShade and all dependencies) 13 | 14 | ## Contributing 15 | 16 | Any contributions to the project are welcomed, it's recommended to use GitHub [pull requests](https://help.github.com/articles/using-pull-requests/). 17 | 18 | ## License 19 | 20 | All the source code is licensed under the conditions of the [BSD 3-clause license](LICENSE.md). 21 | -------------------------------------------------------------------------------- /ReShadeFX.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /deps/ImGui.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | $(SolutionDir)deps\imgui;%(AdditionalIncludeDirectories) 7 | 8 | 9 | ImGui.lib;%(AdditionalDependencies) 10 | 11 | 12 | -------------------------------------------------------------------------------- /deps/ImGui.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {9A62233B-0B70-4B48-91E8-35AA666BC32E} 23 | 10.0.16299.0 24 | 25 | 26 | 27 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 28 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ 29 | StaticLibrary 30 | Unicode 31 | v141 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | MultiThreadedDebugDLL 40 | 41 | 42 | 43 | 44 | MultiThreadedDebugDLL 45 | 46 | 47 | 48 | 49 | MultiThreaded 50 | NDEBUG;%(PreprocessorDefinitions) 51 | 52 | 53 | 54 | 55 | MultiThreaded 56 | NDEBUG;%(PreprocessorDefinitions) 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /deps/MinHook.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | $(SolutionDir)deps\minhook\include;%(AdditionalIncludeDirectories) 7 | 8 | 9 | MinHook.lib;%(AdditionalDependencies) 10 | 11 | 12 | -------------------------------------------------------------------------------- /deps/MinHook.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {783FEDFB-5124-4F8C-87BC-70AA8490266B} 23 | 10.0.16299.0 24 | 25 | 26 | 27 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 28 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ 29 | StaticLibrary 30 | Unicode 31 | v141 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | MultiThreadedDebugDLL 40 | 41 | 42 | 43 | 44 | MultiThreadedDebugDLL 45 | 46 | 47 | 48 | 49 | MultiThreaded 50 | 51 | 52 | 53 | 54 | MultiThreaded 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /deps/MinHook.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4f094667-e67f-4105-b94d-5ffd7bc80831} 6 | 7 | 8 | {6d8d397a-3296-469c-bfc1-0138956f951d} 9 | 10 | 11 | 12 | 13 | HDE 14 | 15 | 16 | HDE 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | HDE 25 | 26 | 27 | HDE 28 | 29 | 30 | HDE 31 | 32 | 33 | HDE 34 | 35 | 36 | HDE 37 | 38 | 39 | API 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /deps/Windows.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Shlwapi.lib;%(AdditionalDependencies) 7 | 8 | 9 | -------------------------------------------------------------------------------- /deps/gl3w.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | $(SolutionDir)deps\gl3w\include;%(AdditionalIncludeDirectories) 7 | 8 | 9 | gl3W.lib;%(AdditionalDependencies) 10 | 11 | 12 | -------------------------------------------------------------------------------- /deps/gl3w.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {09C0D610-9B82-40D8-B37E-0D26E3BFF77F} 23 | 10.0.16299.0 24 | 25 | 26 | 27 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 28 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ 29 | StaticLibrary 30 | Unicode 31 | v141 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | gl3w\include;%(AdditionalIncludeDirectories) 40 | 41 | 42 | 43 | 44 | MultiThreadedDebugDLL 45 | _GDI32_;%(PreprocessorDefinitions) 46 | 47 | 48 | 49 | 50 | MultiThreadedDebugDLL 51 | _GDI32_;%(PreprocessorDefinitions) 52 | 53 | 54 | 55 | 56 | MultiThreaded 57 | _GDI32_;%(PreprocessorDefinitions) 58 | 59 | 60 | 61 | 62 | MultiThreaded 63 | _GDI32_;%(PreprocessorDefinitions) 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | $(CleanDependsOn); 77 | CleanGL3WSources; 78 | 79 | 80 | GenerateGL3WSources; 81 | $(BuildDependsOn); 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /deps/stb.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | $(SolutionDir)deps\stb;$(SolutionDir)deps\stb_image_dds;%(AdditionalIncludeDirectories) 7 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 8 | 9 | 10 | stb.lib;%(AdditionalDependencies) 11 | 12 | 13 | -------------------------------------------------------------------------------- /deps/stb.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {723BDEF8-4A39-4961-BDAB-54074012FF47} 23 | 10.0.16299.0 24 | 25 | 26 | 27 | $(SolutionDir)bin\$(Platform)\$(Configuration)\ 28 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(Configuration)\ 29 | StaticLibrary 30 | Unicode 31 | v141 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | stb;stb_image_dds;%(AdditionalIncludeDirectories) 40 | 41 | 42 | 43 | 44 | MultiThreadedDebugDLL 45 | 46 | 47 | 48 | 49 | MultiThreadedDebugDLL 50 | 51 | 52 | 53 | 54 | MultiThreaded 55 | NDEBUG;%(PreprocessorDefinitions) 56 | 57 | 58 | 59 | 60 | MultiThreaded 61 | NDEBUG;%(PreprocessorDefinitions) 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /deps/stb_impl.c: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #define STB_IMAGE_DDS_IMPLEMENTATION 3 | #define STB_IMAGE_WRITE_IMPLEMENTATION 4 | #define STB_IMAGE_RESIZE_IMPLEMENTATION 5 | 6 | #include "stb_image.h" 7 | #include "stb_image_dds.h" 8 | #include "stb_image_write.h" 9 | #include "stb_image_resize.h" 10 | -------------------------------------------------------------------------------- /res/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/04348/reshade_custom/27ffee5852b436d37697c2fd0ee44cdf7423599a/res/resource.h -------------------------------------------------------------------------------- /res/resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/04348/reshade_custom/27ffee5852b436d37697c2fd0ee44cdf7423599a/res/resource.rc -------------------------------------------------------------------------------- /res/resource.rc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/04348/reshade_custom/27ffee5852b436d37697c2fd0ee44cdf7423599a/res/resource.rc2 -------------------------------------------------------------------------------- /res/shader_copy_ps.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D texture0 : register(t0); 2 | SamplerState sampler0 : register(s0); 3 | 4 | float4 main(float4 vpos : SV_POSITION, float2 uv : TEXCOORD) : SV_TARGET 5 | { 6 | return float4(texture0.Sample(sampler0, uv).rgb, 1.0); 7 | } 8 | -------------------------------------------------------------------------------- /res/shader_copy_vs.hlsl: -------------------------------------------------------------------------------- 1 | void main(uint id : SV_VertexID, out float4 pos : SV_Position, out float2 uv : TEXCOORD) 2 | { 3 | uv.x = (id == 2) ? 2.0 : 0.0; 4 | uv.y = (id == 1) ? 2.0 : 0.0; 5 | pos = float4(uv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 6 | } 7 | -------------------------------------------------------------------------------- /res/shader_imgui_ps.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D texture0 : register(t0); 2 | SamplerState sampler0 : register(s0); 3 | 4 | float4 main(float4 vpos : SV_POSITION, float4 col : COLOR0, float2 uv : TEXCOORD0) : SV_TARGET 5 | { 6 | return col * texture0.Sample(sampler0, uv); 7 | } 8 | -------------------------------------------------------------------------------- /res/shader_imgui_vs.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer Globals : register(b0) 2 | { 3 | float4x4 ProjectionMatrix; 4 | }; 5 | 6 | struct VS_INPUT 7 | { 8 | float2 pos : POSITION; 9 | float4 col : COLOR0; 10 | float2 uv : TEXCOORD0; 11 | }; 12 | struct PS_INPUT 13 | { 14 | float4 pos : SV_POSITION; 15 | float4 col : COLOR0; 16 | float2 uv : TEXCOORD0; 17 | }; 18 | 19 | void main(VS_INPUT input, out PS_INPUT output) 20 | { 21 | output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f)); 22 | output.col = input.col; 23 | output.uv = input.uv; 24 | } 25 | -------------------------------------------------------------------------------- /setup/Glass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | using System.Windows.Interop; 5 | using System.Windows.Media; 6 | 7 | public static class Glass 8 | { 9 | [StructLayout(LayoutKind.Sequential)] 10 | private struct MARGINS 11 | { 12 | public int cxLeftWidth; 13 | public int cxRightWidth; 14 | public int cyTopHeight; 15 | public int cyBottomHeight; 16 | } 17 | 18 | [DllImport("dwmapi.dll")] 19 | private static extern int DwmIsCompositionEnabled(out bool enabled); 20 | [DllImport("dwmapi.dll")] 21 | private static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS pMarInset); 22 | [DllImport("user32.dll")] 23 | private static extern int GetWindowLong(IntPtr hwnd, int index); 24 | [DllImport("user32.dll")] 25 | private static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle); 26 | [DllImport("user32.dll")] 27 | private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags); 28 | [DllImport("user32.dll")] 29 | private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); 30 | 31 | public static bool IsEnabled 32 | { 33 | get 34 | { 35 | bool enabled = false; 36 | DwmIsCompositionEnabled(out enabled); 37 | 38 | return enabled; 39 | } 40 | } 41 | 42 | public static void HideIcon(Window window) 43 | { 44 | IntPtr hwnd = new WindowInteropHelper(window).Handle; 45 | 46 | const int WM_SETICON = 0x0080; 47 | 48 | SendMessage(hwnd, WM_SETICON, new IntPtr(1), IntPtr.Zero); 49 | SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero); 50 | 51 | const int GWL_EXSTYLE = -20; 52 | const int WS_EX_DLGMODALFRAME = 0x0001; 53 | 54 | SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_DLGMODALFRAME); 55 | 56 | const int SWP_NOSIZE = 0x0001; 57 | const int SWP_NOMOVE = 0x0002; 58 | const int SWP_NOZORDER = 0x0004; 59 | const int SWP_FRAMECHANGED = 0x0020; 60 | 61 | SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED); 62 | } 63 | public static void HideSystemMenu(Window window, bool hidden = true) 64 | { 65 | IntPtr hwnd = new WindowInteropHelper(window).Handle; 66 | 67 | const int GWL_STYLE = -16; 68 | const int WS_SYSMENU = 0x80000; 69 | 70 | if (hidden) 71 | { 72 | SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU); 73 | } 74 | else 75 | { 76 | SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_SYSMENU); 77 | } 78 | } 79 | 80 | public static bool ExtendFrame(Window window) 81 | { 82 | return ExtendFrame(window, new Thickness(-1, -1, -1, -1)); 83 | } 84 | public static bool ExtendFrame(Window window, Thickness margin) 85 | { 86 | if (!IsEnabled) 87 | { 88 | return false; 89 | } 90 | 91 | IntPtr hwnd = new WindowInteropHelper(window).Handle; 92 | 93 | if (hwnd == IntPtr.Zero) 94 | { 95 | throw new InvalidOperationException("The window must be shown before extending glass effect."); 96 | } 97 | 98 | // Adapted from http://blogs.msdn.com/b/adam_nathan/archive/2006/05/04/589686.aspx 99 | window.Background = Brushes.Transparent; 100 | HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent; 101 | 102 | var margins = new MARGINS { 103 | cxLeftWidth = (int)margin.Left, 104 | cxRightWidth = (int)margin.Right, 105 | cyTopHeight = (int)margin.Top, 106 | cyBottomHeight = (int)margin.Bottom 107 | }; 108 | 109 | DwmExtendFrameIntoClientArea(hwnd, ref margins); 110 | 111 | return true; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /setup/IniFile.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using System.Runtime.InteropServices; 3 | 4 | public static class IniFile 5 | { 6 | [DllImport("kernel32", CharSet = CharSet.Unicode)] 7 | private static extern int GetPrivateProfileString(string section, string key, string defaultValue, StringBuilder value, int size, string filePath); 8 | [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] 9 | [return: MarshalAs(UnmanagedType.Bool)] 10 | private static extern bool WritePrivateProfileString(string section, string key, string value, string filePath); 11 | 12 | public static string ReadValue(string file, string section, string key, string defaultValue = "") 13 | { 14 | var value = new StringBuilder(512); 15 | GetPrivateProfileString(section, key, defaultValue, value, value.Capacity, file); 16 | return value.ToString(); 17 | } 18 | public static bool WriteValue(string file, string section, string key, string value) 19 | { 20 | return WritePrivateProfileString(section, key, value, file); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /setup/PEInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Security; 5 | 6 | public unsafe class PEInfo 7 | { 8 | public enum BinaryType : ushort 9 | { 10 | IMAGE_FILE_MACHINE_UNKNOWN = 0x0, 11 | IMAGE_FILE_MACHINE_I386 = 0x14c, 12 | IMAGE_FILE_MACHINE_AMD64 = 0x8664, 13 | } 14 | 15 | [StructLayout(LayoutKind.Sequential)] 16 | private struct LOADED_IMAGE 17 | { 18 | public IntPtr ModuleName; 19 | public IntPtr hFile; 20 | public IntPtr MappedAddress; 21 | public IntPtr FileHeader; 22 | public IntPtr LastRvaSection; 23 | public uint NumberOfSections; 24 | public IntPtr Sections; 25 | public uint Characteristics; 26 | public ushort fSystemImage; 27 | public ushort fDOSImage; 28 | public ushort fReadOnly; 29 | public ushort Version; 30 | public IntPtr Flink; 31 | public IntPtr BLink; 32 | public uint SizeOfImage; 33 | } 34 | [StructLayout(LayoutKind.Explicit)] 35 | private struct IMAGE_NT_HEADERS 36 | { 37 | [FieldOffset(0)] 38 | public uint Signature; 39 | [FieldOffset(4)] 40 | public IMAGE_FILE_HEADER FileHeader; 41 | } 42 | [StructLayout(LayoutKind.Sequential)] 43 | private struct IMAGE_FILE_HEADER 44 | { 45 | public BinaryType Machine; 46 | public ushort NumberOfSections; 47 | public uint TimeDateStamp; 48 | public uint PointerToSymbolTable; 49 | public uint NumberOfSymbols; 50 | public ushort SizeOfOptionalHeader; 51 | public ushort Characteristics; 52 | } 53 | [StructLayout(LayoutKind.Explicit)] 54 | private struct IMAGE_IMPORT_DESCRIPTOR 55 | { 56 | #region union 57 | [FieldOffset(0)] 58 | public UInt32 Characteristics; 59 | [FieldOffset(0)] 60 | public UInt32 OriginalFirstThunk; 61 | #endregion 62 | 63 | [FieldOffset(4)] 64 | public uint TimeDateStamp; 65 | [FieldOffset(8)] 66 | public uint ForwarderChain; 67 | [FieldOffset(12)] 68 | public uint Name; 69 | [FieldOffset(16)] 70 | public uint FirstThunk; 71 | } 72 | 73 | [DllImport("dbghelp.dll"), SuppressUnmanagedCodeSecurity] 74 | private static extern void* ImageDirectoryEntryToData(void* pBase, bool mappedAsImage, ushort directoryEntry, out uint size); 75 | [DllImport("dbghelp.dll"), SuppressUnmanagedCodeSecurity] 76 | private static extern IntPtr ImageRvaToVa(IntPtr pNtHeaders, IntPtr pBase, uint rva, IntPtr pLastRvaSection); 77 | [DllImport("imagehlp.dll"), SuppressUnmanagedCodeSecurity] 78 | private static extern bool MapAndLoad(string imageName, string dllPath, out LOADED_IMAGE loadedImage, bool dotDll, bool readOnly); 79 | 80 | private readonly BinaryType _binaryType = BinaryType.IMAGE_FILE_MACHINE_UNKNOWN; 81 | private readonly List _modules = new List(); 82 | 83 | // Adapted from http://stackoverflow.com/a/4696857/2055880 84 | public PEInfo(string path) 85 | { 86 | uint size; 87 | LOADED_IMAGE image; 88 | 89 | if (MapAndLoad(path, null, out image, true, true) && image.MappedAddress != IntPtr.Zero) 90 | { 91 | var imports = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData((void*)image.MappedAddress, false, 1, out size); 92 | 93 | if (imports != null) 94 | { 95 | while (imports->OriginalFirstThunk != 0) 96 | { 97 | _modules.Add(Marshal.PtrToStringAnsi(ImageRvaToVa(image.FileHeader, image.MappedAddress, imports->Name, IntPtr.Zero))); 98 | 99 | ++imports; 100 | } 101 | } 102 | 103 | _binaryType = ((IMAGE_NT_HEADERS*)image.FileHeader)->FileHeader.Machine; 104 | } 105 | } 106 | 107 | public BinaryType Type 108 | { 109 | get { return _binaryType; } 110 | } 111 | public IEnumerable Modules 112 | { 113 | get { return _modules; } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /setup/Properties/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | -------------------------------------------------------------------------------- /setup/Properties/Assembly.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /setup/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | [assembly: AssemblyTitle("ReShade Setup")] 4 | [assembly: AssemblyVersion("1.4.0.0")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("crosire")] 8 | [assembly: AssemblyProduct("ReShade")] 9 | [assembly: AssemblyCopyright("Copyright © 2014. All rights reserved.")] 10 | -------------------------------------------------------------------------------- /setup/Properties/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/04348/reshade_custom/27ffee5852b436d37697c2fd0ee44cdf7423599a/setup/Properties/Icon.ico -------------------------------------------------------------------------------- /setup/ReShade Setup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {3B7009FA-0B09-4F27-8126-0885E66A5679} 6 | Debug 7 | AnyCPU 8 | WinExe 9 | ReShade Setup 10 | Properties\Icon.ico 11 | $(SolutionDir)\bin\$(Platform)\$(Configuration)\ 12 | $(SolutionDir)\intermediate\$(AssemblyName)\$(Platform)\$(Configuration)\ 13 | Properties 14 | ReShade.Setup 15 | v4.6 16 | 512 17 | Properties\Assembly.manifest 18 | 4 19 | 20 | 21 | 22 | AnyCPU 23 | true 24 | full 25 | false 26 | DEBUG;TRACE 27 | true 28 | true 29 | true 30 | 31 | 32 | AnyCPU 33 | none 34 | true 35 | true 36 | false 37 | false 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | MSBuild:Compile 50 | Designer 51 | 52 | 53 | 54 | 55 | 56 | Designer 57 | MSBuild:Compile 58 | 59 | 60 | Designer 61 | MSBuild:Compile 62 | 63 | 64 | Select.xaml 65 | 66 | 67 | Wizard.xaml 68 | 69 | 70 | 71 | 72 | Code 73 | 74 | 75 | 76 | 77 | 78 | Designer 79 | 80 | 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /setup/Select.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 87 | -------------------------------------------------------------------------------- /source/com_ptr.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | template 11 | class com_ptr 12 | { 13 | public: 14 | com_ptr() : _object(nullptr) { } 15 | com_ptr(T *object) : _object(nullptr) 16 | { 17 | reset(object); 18 | } 19 | com_ptr(const com_ptr ©) : _object(nullptr) 20 | { 21 | reset(copy._object); 22 | } 23 | com_ptr(com_ptr &&move) : _object(nullptr) 24 | { 25 | std::swap(_object, move._object); 26 | } 27 | 28 | ~com_ptr() 29 | { 30 | reset(); 31 | } 32 | 33 | unsigned long ref_count() const 34 | { 35 | return _object->AddRef(), _object->Release(); 36 | } 37 | 38 | inline T *get() const 39 | { 40 | return _object; 41 | } 42 | T &operator*() const 43 | { 44 | assert(_object != nullptr); 45 | 46 | return *_object; 47 | } 48 | T *operator->() const 49 | { 50 | assert(_object != nullptr); 51 | 52 | return _object; 53 | } 54 | T **operator&() throw() 55 | { 56 | assert(_object == nullptr); 57 | 58 | return &_object; 59 | } 60 | 61 | void reset(T *object = nullptr) 62 | { 63 | if (_object != nullptr) 64 | { 65 | _object->Release(); 66 | } 67 | 68 | _object = object; 69 | 70 | if (_object != nullptr) 71 | { 72 | _object->AddRef(); 73 | } 74 | } 75 | com_ptr &operator=(T *object) 76 | { 77 | reset(object); 78 | 79 | return *this; 80 | } 81 | com_ptr &operator=(const com_ptr ©) 82 | { 83 | reset(copy._object); 84 | 85 | return *this; 86 | } 87 | com_ptr &operator=(com_ptr &&move) 88 | { 89 | if (_object != nullptr) 90 | { 91 | _object->Release(); 92 | } 93 | 94 | _object = move._object; 95 | move._object = nullptr; 96 | 97 | return *this; 98 | } 99 | 100 | bool operator==(T *other) const 101 | { 102 | return _object == other; 103 | } 104 | bool operator==(const com_ptr &other) const 105 | { 106 | return _object == other._object; 107 | } 108 | friend bool operator==(T *left, const com_ptr &right) 109 | { 110 | return right.operator==(left); 111 | } 112 | bool operator!=(T *other) const 113 | { 114 | return _object != other; 115 | } 116 | bool operator!=(const com_ptr &other) const 117 | { 118 | return _object != other._object; 119 | } 120 | friend bool operator!=(T *left, const com_ptr &right) 121 | { 122 | return right.operator!=(left); 123 | } 124 | 125 | private: 126 | T *_object; 127 | }; 128 | -------------------------------------------------------------------------------- /source/d3d10/d3d10.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "log.hpp" 7 | #include "hook_manager.hpp" 8 | #include "d3d10_device.hpp" 9 | #include "../dxgi/dxgi_device.hpp" 10 | 11 | // D3D10 12 | HOOK_EXPORT HRESULT WINAPI D3D10CreateDevice(IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, UINT SDKVersion, ID3D10Device **ppDevice) 13 | { 14 | LOG(INFO) << "Redirecting '" << "D3D10CreateDevice" << "(" << pAdapter << ", " << DriverType << ", " << Software << ", " << std::hex << Flags << std::dec << ", " << SDKVersion << ", " << ppDevice << ")' ..."; 15 | LOG(INFO) << "> Passing on to 'D3D10CreateDeviceAndSwapChain1':"; 16 | 17 | LoadLibraryW(L"d3d10_1.dll"); 18 | 19 | return D3D10CreateDeviceAndSwapChain1(pAdapter, DriverType, Software, Flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, nullptr, nullptr, reinterpret_cast(ppDevice)); 20 | } 21 | HOOK_EXPORT HRESULT WINAPI D3D10CreateDevice1(IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, D3D10_FEATURE_LEVEL1 HardwareLevel, UINT SDKVersion, ID3D10Device1 **ppDevice) 22 | { 23 | LOG(INFO) << "Redirecting '" << "D3D10CreateDevice1" << "(" << pAdapter << ", " << DriverType << ", " << Software << ", " << std::hex << Flags << std::dec << ", " << HardwareLevel << ", " << SDKVersion << ", " << ppDevice << ")' ..."; 24 | LOG(INFO) << "> Passing on to 'D3D10CreateDeviceAndSwapChain1':"; 25 | 26 | return D3D10CreateDeviceAndSwapChain1(pAdapter, DriverType, Software, Flags, HardwareLevel, SDKVersion, nullptr, nullptr, ppDevice); 27 | } 28 | HOOK_EXPORT HRESULT WINAPI D3D10CreateDeviceAndSwapChain(IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, UINT SDKVersion, DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, ID3D10Device **ppDevice) 29 | { 30 | LOG(INFO) << "Redirecting '" << "D3D10CreateDeviceAndSwapChain" << "(" << pAdapter << ", " << DriverType << ", " << Software << ", " << std::hex << Flags << std::dec << ", " << SDKVersion << ", " << pSwapChainDesc << ", " << ppSwapChain << ", " << ppDevice << ")' ..."; 31 | LOG(INFO) << "> Passing on to 'D3D10CreateDeviceAndSwapChain1':"; 32 | 33 | LoadLibraryW(L"d3d10_1.dll"); 34 | 35 | return D3D10CreateDeviceAndSwapChain1(pAdapter, DriverType, Software, Flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, pSwapChainDesc, ppSwapChain, reinterpret_cast(ppDevice)); 36 | } 37 | HOOK_EXPORT HRESULT WINAPI D3D10CreateDeviceAndSwapChain1(IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, D3D10_FEATURE_LEVEL1 HardwareLevel, UINT SDKVersion, DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, ID3D10Device1 **ppDevice) 38 | { 39 | LOG(INFO) << "Redirecting '" << "D3D10CreateDeviceAndSwapChain1" << "(" << pAdapter << ", " << DriverType << ", " << Software << ", " << std::hex << Flags << ", " << HardwareLevel << std::dec << ", " << SDKVersion << ", " << pSwapChainDesc << ", " << ppSwapChain << ", " << ppDevice << ")' ..."; 40 | 41 | #ifdef _DEBUG 42 | Flags |= D3D10_CREATE_DEVICE_DEBUG; 43 | Flags &= ~D3D10_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY; 44 | #endif 45 | 46 | HRESULT hr = reshade::hooks::call(&D3D10CreateDeviceAndSwapChain1)(pAdapter, DriverType, Software, Flags, HardwareLevel, SDKVersion, nullptr, nullptr, ppDevice); 47 | 48 | if (FAILED(hr)) 49 | { 50 | LOG(WARNING) << "> 'D3D10CreateDeviceAndSwapChain1' failed with error code " << std::hex << hr << std::dec << "!"; 51 | 52 | return hr; 53 | } 54 | 55 | if (ppDevice != nullptr) 56 | { 57 | IDXGIDevice1 *dxgidevice = nullptr; 58 | ID3D10Device1 *const device = *ppDevice; 59 | 60 | assert(device != nullptr); 61 | 62 | device->QueryInterface(&dxgidevice); 63 | 64 | assert(dxgidevice != nullptr); 65 | 66 | const auto device_proxy = new D3D10Device(device); 67 | device_proxy->_dxgi_device = new DXGIDevice(dxgidevice, device_proxy); 68 | 69 | if (pSwapChainDesc != nullptr) 70 | { 71 | assert(ppSwapChain != nullptr); 72 | 73 | if (pAdapter != nullptr) 74 | { 75 | pAdapter->AddRef(); 76 | } 77 | else 78 | { 79 | hr = device_proxy->_dxgi_device->GetAdapter(&pAdapter); 80 | 81 | assert(SUCCEEDED(hr)); 82 | } 83 | 84 | IDXGIFactory *factory = nullptr; 85 | 86 | hr = pAdapter->GetParent(IID_PPV_ARGS(&factory)); 87 | 88 | assert(SUCCEEDED(hr)); 89 | 90 | LOG(INFO) << "> Calling 'IDXGIFactory::CreateSwapChain':"; 91 | 92 | hr = factory->CreateSwapChain(device_proxy, pSwapChainDesc, ppSwapChain); 93 | 94 | factory->Release(); 95 | pAdapter->Release(); 96 | } 97 | 98 | if (SUCCEEDED(hr)) 99 | { 100 | LOG(INFO) << "Returning 'IDXGIDevice1' object " << device_proxy->_dxgi_device; 101 | LOG(INFO) << "Returning 'ID3D10Device1' object " << device_proxy; 102 | 103 | *ppDevice = device_proxy; 104 | } 105 | else 106 | { 107 | device_proxy->Release(); 108 | } 109 | } 110 | 111 | return hr; 112 | } 113 | -------------------------------------------------------------------------------- /source/d3d10/d3d10.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "d3d10_runtime.hpp" 9 | 10 | struct __declspec(uuid("88399375-734F-4892-A95F-70DD42CE7CDD")) D3D10Device; 11 | -------------------------------------------------------------------------------- /source/d3d10/d3d10_effect_compiler.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_syntax_tree.hpp" 9 | #include 10 | 11 | namespace reshade::d3d10 12 | { 13 | #pragma region Forward Declarations 14 | struct d3d10_pass_data; 15 | class d3d10_runtime; 16 | #pragma endregion 17 | 18 | class d3d10_effect_compiler 19 | { 20 | public: 21 | d3d10_effect_compiler(d3d10_runtime *runtime, const reshadefx::syntax_tree &ast, std::string &errors, bool skipoptimization = false); 22 | 23 | bool run(); 24 | 25 | private: 26 | void error(const reshadefx::location &location, const std::string &message); 27 | void warning(const reshadefx::location &location, const std::string &message); 28 | 29 | void visit(std::stringstream &output, const reshadefx::nodes::statement_node *node); 30 | void visit(std::stringstream &output, const reshadefx::nodes::expression_node *node); 31 | void visit(std::stringstream &output, const reshadefx::nodes::type_node &type, bool with_qualifiers = true); 32 | void visit(std::stringstream &output, const reshadefx::nodes::lvalue_expression_node *node); 33 | void visit(std::stringstream &output, const reshadefx::nodes::literal_expression_node *node); 34 | void visit(std::stringstream &output, const reshadefx::nodes::expression_sequence_node *node); 35 | void visit(std::stringstream &output, const reshadefx::nodes::unary_expression_node *node); 36 | void visit(std::stringstream &output, const reshadefx::nodes::binary_expression_node *node); 37 | void visit(std::stringstream &output, const reshadefx::nodes::intrinsic_expression_node *node); 38 | void visit(std::stringstream &output, const reshadefx::nodes::conditional_expression_node *node); 39 | void visit(std::stringstream &output, const reshadefx::nodes::swizzle_expression_node *node); 40 | void visit(std::stringstream &output, const reshadefx::nodes::field_expression_node *node); 41 | void visit(std::stringstream &output, const reshadefx::nodes::assignment_expression_node *node); 42 | void visit(std::stringstream &output, const reshadefx::nodes::call_expression_node *node); 43 | void visit(std::stringstream &output, const reshadefx::nodes::constructor_expression_node *node); 44 | void visit(std::stringstream &output, const reshadefx::nodes::initializer_list_node *node); 45 | void visit(std::stringstream &output, const reshadefx::nodes::compound_statement_node *node); 46 | void visit(std::stringstream &output, const reshadefx::nodes::declarator_list_node *node, bool single_statement); 47 | void visit(std::stringstream &output, const reshadefx::nodes::expression_statement_node *node); 48 | void visit(std::stringstream &output, const reshadefx::nodes::if_statement_node *node); 49 | void visit(std::stringstream &output, const reshadefx::nodes::switch_statement_node *node); 50 | void visit(std::stringstream &output, const reshadefx::nodes::case_statement_node *node); 51 | void visit(std::stringstream &output, const reshadefx::nodes::for_statement_node *node); 52 | void visit(std::stringstream &output, const reshadefx::nodes::while_statement_node *node); 53 | void visit(std::stringstream &output, const reshadefx::nodes::return_statement_node *node); 54 | void visit(std::stringstream &output, const reshadefx::nodes::jump_statement_node *node); 55 | void visit(std::stringstream &output, const reshadefx::nodes::struct_declaration_node *node); 56 | void visit(std::stringstream &output, const reshadefx::nodes::variable_declaration_node *node, bool with_type = true); 57 | void visit(std::stringstream &output, const reshadefx::nodes::function_declaration_node *node); 58 | 59 | void visit_texture(const reshadefx::nodes::variable_declaration_node *node); 60 | void visit_sampler(const reshadefx::nodes::variable_declaration_node *node); 61 | void visit_uniform(const reshadefx::nodes::variable_declaration_node *node); 62 | void visit_technique(const reshadefx::nodes::technique_declaration_node *node); 63 | void visit_pass(const reshadefx::nodes::pass_declaration_node *node, d3d10_pass_data &pass); 64 | void visit_pass_shader(const reshadefx::nodes::function_declaration_node *node, const std::string &shadertype, d3d10_pass_data &pass); 65 | 66 | d3d10_runtime *_runtime; 67 | bool _success = true; 68 | const reshadefx::syntax_tree &_ast; 69 | std::string &_errors; 70 | std::stringstream _global_code, _global_uniforms; 71 | bool _skip_shader_optimization, _is_in_parameter_block = false, _is_in_function_block = false; 72 | size_t _uniform_storage_offset = 0, _constant_buffer_size = 0; 73 | HMODULE _d3dcompiler_module = nullptr; 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /source/d3d10/d3d10_runtime.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "runtime.hpp" 10 | #include "d3d10_stateblock.hpp" 11 | 12 | namespace reshade::d3d10 13 | { 14 | struct d3d10_tex_data : base_object 15 | { 16 | com_ptr texture; 17 | com_ptr srv[2]; 18 | com_ptr rtv[2]; 19 | }; 20 | struct d3d10_pass_data : base_object 21 | { 22 | com_ptr vertex_shader; 23 | com_ptr pixel_shader; 24 | com_ptr blend_state; 25 | com_ptr depth_stencil_state; 26 | UINT stencil_reference; 27 | bool clear_render_targets; 28 | com_ptr render_targets[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT]; 29 | com_ptr render_target_resources[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT]; 30 | D3D10_VIEWPORT viewport; 31 | std::vector> shader_resources; 32 | }; 33 | struct d3d10_technique_data : base_object 34 | { 35 | bool query_in_flight = false; 36 | com_ptr timestamp_disjoint; 37 | com_ptr timestamp_query_beg; 38 | com_ptr timestamp_query_end; 39 | }; 40 | 41 | class d3d10_runtime : public runtime 42 | { 43 | public: 44 | d3d10_runtime(ID3D10Device1 *device, IDXGISwapChain *swapchain); 45 | 46 | bool on_init(const DXGI_SWAP_CHAIN_DESC &desc); 47 | void on_reset(); 48 | void on_reset_effect() override; 49 | static void do_draw_fx(void* runtime); 50 | void draw_fx(); 51 | void on_present(); 52 | void on_draw_call(UINT vertices); 53 | void on_set_depthstencil_view(ID3D10DepthStencilView *&depthstencil); 54 | void on_get_depthstencil_view(ID3D10DepthStencilView *&depthstencil); 55 | void on_clear_depthstencil_view(ID3D10DepthStencilView *&depthstencil); 56 | void on_copy_resource(ID3D10Resource *&dest, ID3D10Resource *&source); 57 | 58 | void capture_frame(uint8_t *buffer) const override; 59 | bool load_effect(const reshadefx::syntax_tree &ast, std::string &errors) override; 60 | bool update_texture(texture &texture, const uint8_t *data) override; 61 | 62 | void render_technique(const technique &technique) override; 63 | void render_imgui_draw_data(ImDrawData *data) override; 64 | 65 | com_ptr _device; 66 | com_ptr _swapchain; 67 | 68 | com_ptr _backbuffer_texture; 69 | com_ptr _backbuffer_rtv[3]; 70 | com_ptr _backbuffer_texture_srv[2], _depthstencil_texture_srv; 71 | std::vector> _effect_sampler_states; 72 | std::unordered_map _effect_sampler_descs; 73 | std::vector> _effect_shader_resources; 74 | std::vector> _constant_buffers; 75 | 76 | private: 77 | struct depth_source_info 78 | { 79 | UINT width, height; 80 | UINT drawcall_count, vertices_count; 81 | }; 82 | 83 | bool init_backbuffer_texture(); 84 | bool init_default_depth_stencil(); 85 | bool init_fx_resources(); 86 | bool init_imgui_resources(); 87 | bool init_imgui_font_atlas(); 88 | 89 | void detect_depth_source(); 90 | bool create_depthstencil_replacement(ID3D10DepthStencilView *depthstencil); 91 | 92 | bool _is_multisampling_enabled = false; 93 | DXGI_FORMAT _backbuffer_format = DXGI_FORMAT_UNKNOWN; 94 | d3d10_stateblock _stateblock; 95 | com_ptr _backbuffer, _backbuffer_resolved; 96 | com_ptr _depthstencil, _depthstencil_replacement; 97 | com_ptr _depthstencil_texture; 98 | com_ptr _default_depthstencil; 99 | std::unordered_map _depth_source_table; 100 | com_ptr _copy_vertex_shader; 101 | com_ptr _copy_pixel_shader; 102 | com_ptr _copy_sampler; 103 | com_ptr _effect_rasterizer_state; 104 | 105 | com_ptr _imgui_vertex_buffer, _imgui_index_buffer; 106 | com_ptr _imgui_vertex_shader; 107 | com_ptr _imgui_pixel_shader; 108 | com_ptr _imgui_input_layout; 109 | com_ptr _imgui_constant_buffer; 110 | com_ptr _imgui_texture_sampler; 111 | com_ptr _imgui_rasterizer_state; 112 | com_ptr _imgui_blend_state; 113 | com_ptr _imgui_depthstencil_state; 114 | int _imgui_vertex_buffer_size = 0, _imgui_index_buffer_size = 0; 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /source/d3d10/d3d10_stateblock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "d3d10_stateblock.hpp" 7 | 8 | namespace reshade::d3d10 9 | { 10 | template 11 | static inline void safe_release(T *&object) 12 | { 13 | if (object != nullptr) 14 | { 15 | object->Release(); 16 | object = nullptr; 17 | } 18 | } 19 | 20 | d3d10_stateblock::d3d10_stateblock(const com_ptr &device) 21 | { 22 | ZeroMemory(this, sizeof(*this)); 23 | 24 | _device = device; 25 | } 26 | d3d10_stateblock::~d3d10_stateblock() 27 | { 28 | release_all_device_objects(); 29 | } 30 | 31 | void d3d10_stateblock::capture() 32 | { 33 | _device->IAGetPrimitiveTopology(&_ia_primitive_topology); 34 | _device->IAGetInputLayout(&_ia_input_layout); 35 | 36 | _device->IAGetVertexBuffers(0, ARRAYSIZE(_ia_vertex_buffers), _ia_vertex_buffers, _ia_vertex_strides, _ia_vertex_offsets); 37 | _device->IAGetIndexBuffer(&_ia_index_buffer, &_ia_index_format, &_ia_index_offset); 38 | 39 | _device->RSGetState(&_rs_state); 40 | _device->RSGetViewports(&_rs_num_viewports, nullptr); 41 | _device->RSGetViewports(&_rs_num_viewports, _rs_viewports); 42 | 43 | _device->VSGetShader(&_vs); 44 | _device->VSGetConstantBuffers(0, ARRAYSIZE(_vs_constant_buffers), _vs_constant_buffers); 45 | _device->VSGetSamplers(0, ARRAYSIZE(_vs_sampler_states), _vs_sampler_states); 46 | _device->VSGetShaderResources(0, ARRAYSIZE(_vs_shader_resources), _vs_shader_resources); 47 | 48 | _device->GSGetShader(&_gs); 49 | 50 | _device->PSGetShader(&_ps); 51 | _device->PSGetConstantBuffers(0, ARRAYSIZE(_ps_constant_buffers), _ps_constant_buffers); 52 | _device->PSGetSamplers(0, ARRAYSIZE(_ps_sampler_states), _ps_sampler_states); 53 | _device->PSGetShaderResources(0, ARRAYSIZE(_ps_shader_resources), _ps_shader_resources); 54 | 55 | _device->OMGetBlendState(&_om_blend_state, _om_blend_factor, &_om_sample_mask); 56 | _device->OMGetDepthStencilState(&_om_depth_stencil_state, &_om_stencil_ref); 57 | _device->OMGetRenderTargets(ARRAYSIZE(_om_render_targets), _om_render_targets, &_om_depth_stencil); 58 | } 59 | void d3d10_stateblock::apply_and_release() 60 | { 61 | _device->IASetPrimitiveTopology(_ia_primitive_topology); 62 | _device->IASetInputLayout(_ia_input_layout); 63 | 64 | _device->IASetVertexBuffers(0, ARRAYSIZE(_ia_vertex_buffers), _ia_vertex_buffers, _ia_vertex_strides, _ia_vertex_offsets); 65 | _device->IASetIndexBuffer(_ia_index_buffer, _ia_index_format, _ia_index_offset); 66 | 67 | _device->RSSetState(_rs_state); 68 | _device->RSSetViewports(_rs_num_viewports, _rs_viewports); 69 | 70 | _device->VSSetShader(_vs); 71 | _device->VSSetConstantBuffers(0, ARRAYSIZE(_vs_constant_buffers), _vs_constant_buffers); 72 | _device->VSSetSamplers(0, ARRAYSIZE(_vs_sampler_states), _vs_sampler_states); 73 | _device->VSSetShaderResources(0, ARRAYSIZE(_vs_shader_resources), _vs_shader_resources); 74 | 75 | _device->GSSetShader(_gs); 76 | 77 | _device->PSSetShader(_ps); 78 | _device->PSSetConstantBuffers(0, ARRAYSIZE(_ps_constant_buffers), _ps_constant_buffers); 79 | _device->PSSetSamplers(0, ARRAYSIZE(_ps_sampler_states), _ps_sampler_states); 80 | _device->PSSetShaderResources(0, ARRAYSIZE(_ps_shader_resources), _ps_shader_resources); 81 | 82 | _device->OMSetBlendState(_om_blend_state, _om_blend_factor, _om_sample_mask); 83 | _device->OMSetDepthStencilState(_om_depth_stencil_state, _om_stencil_ref); 84 | _device->OMSetRenderTargets(ARRAYSIZE(_om_render_targets), _om_render_targets, _om_depth_stencil); 85 | 86 | release_all_device_objects(); 87 | } 88 | 89 | void d3d10_stateblock::release_all_device_objects() 90 | { 91 | safe_release(_ia_input_layout); 92 | 93 | for (auto &vertex_buffer : _ia_vertex_buffers) 94 | { 95 | safe_release(vertex_buffer); 96 | } 97 | 98 | safe_release(_ia_index_buffer); 99 | 100 | safe_release(_vs); 101 | 102 | for (auto &constant_buffer : _vs_constant_buffers) 103 | { 104 | safe_release(constant_buffer); 105 | } 106 | for (auto &sampler_state : _vs_sampler_states) 107 | { 108 | safe_release(sampler_state); 109 | } 110 | for (auto &shader_resource : _vs_shader_resources) 111 | { 112 | safe_release(shader_resource); 113 | } 114 | 115 | safe_release(_gs); 116 | 117 | safe_release(_rs_state); 118 | 119 | safe_release(_ps); 120 | 121 | for (auto &constant_buffer : _ps_constant_buffers) 122 | { 123 | safe_release(constant_buffer); 124 | } 125 | for (auto &sampler_state : _ps_sampler_states) 126 | { 127 | safe_release(sampler_state); 128 | } 129 | for (auto &shader_resource : _ps_shader_resources) 130 | { 131 | safe_release(shader_resource); 132 | } 133 | 134 | safe_release(_om_blend_state); 135 | safe_release(_om_depth_stencil_state); 136 | 137 | for (auto &render_target : _om_render_targets) 138 | { 139 | safe_release(render_target); 140 | } 141 | 142 | safe_release(_om_depth_stencil); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /source/d3d10/d3d10_stateblock.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | namespace reshade::d3d10 12 | { 13 | class d3d10_stateblock 14 | { 15 | public: 16 | explicit d3d10_stateblock(const com_ptr &device); 17 | ~d3d10_stateblock(); 18 | 19 | void capture(); 20 | void apply_and_release(); 21 | 22 | private: 23 | void release_all_device_objects(); 24 | 25 | com_ptr _device; 26 | ID3D10InputLayout *_ia_input_layout; 27 | D3D10_PRIMITIVE_TOPOLOGY _ia_primitive_topology; 28 | ID3D10Buffer *_ia_vertex_buffers[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; 29 | UINT _ia_vertex_strides[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; 30 | UINT _ia_vertex_offsets[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; 31 | ID3D10Buffer *_ia_index_buffer; 32 | DXGI_FORMAT _ia_index_format; 33 | UINT _ia_index_offset; 34 | ID3D10VertexShader *_vs; 35 | ID3D10Buffer *_vs_constant_buffers[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; 36 | ID3D10SamplerState *_vs_sampler_states[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; 37 | ID3D10ShaderResourceView *_vs_shader_resources[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; 38 | ID3D10GeometryShader *_gs; 39 | ID3D10RasterizerState *_rs_state; 40 | UINT _rs_num_viewports; 41 | D3D10_VIEWPORT _rs_viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 42 | ID3D10PixelShader *_ps; 43 | ID3D10Buffer *_ps_constant_buffers[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; 44 | ID3D10SamplerState *_ps_sampler_states[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; 45 | ID3D10ShaderResourceView *_ps_shader_resources[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; 46 | ID3D10BlendState *_om_blend_state; 47 | FLOAT _om_blend_factor[4]; 48 | UINT _om_sample_mask; 49 | ID3D10DepthStencilState *_om_depth_stencil_state; 50 | UINT _om_stencil_ref; 51 | ID3D10RenderTargetView *_om_render_targets[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT]; 52 | ID3D10DepthStencilView *_om_depth_stencil; 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /source/d3d11/d3d11.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "log.hpp" 7 | #include "hook_manager.hpp" 8 | #include "d3d11_device.hpp" 9 | #include "d3d11_device_context.hpp" 10 | #include "../dxgi/dxgi_device.hpp" 11 | 12 | // D3D11 13 | HOOK_EXPORT HRESULT WINAPI D3D11CreateDevice(IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, const D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, ID3D11Device **ppDevice, D3D_FEATURE_LEVEL *pFeatureLevel, ID3D11DeviceContext **ppImmediateContext) 14 | { 15 | LOG(INFO) << "Redirecting '" << "D3D11CreateDevice" << "(" << pAdapter << ", " << DriverType << ", " << Software << ", " << std::hex << Flags << std::dec << ", " << pFeatureLevels << ", " << FeatureLevels << ", " << SDKVersion << ", " << ppDevice << ", " << pFeatureLevel << ", " << ppImmediateContext << ")' ..."; 16 | LOG(INFO) << "> Passing on to 'D3D11CreateDeviceAndSwapChain':"; 17 | 18 | return D3D11CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, nullptr, nullptr, ppDevice, pFeatureLevel, ppImmediateContext); 19 | } 20 | HOOK_EXPORT HRESULT WINAPI D3D11CreateDeviceAndSwapChain(IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, const D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, ID3D11Device **ppDevice, D3D_FEATURE_LEVEL *pFeatureLevel, ID3D11DeviceContext **ppImmediateContext) 21 | { 22 | LOG(INFO) << "Redirecting '" << "D3D11CreateDeviceAndSwapChain" << "(" << pAdapter << ", " << DriverType << ", " << Software << ", " << std::hex << Flags << std::dec << ", " << pFeatureLevels << ", " << FeatureLevels << ", " << SDKVersion << ", " << pSwapChainDesc << ", " << ppSwapChain << ", " << ppDevice << ", " << pFeatureLevel << ", " << ppImmediateContext << ")' ..."; 23 | 24 | #ifdef _DEBUG 25 | Flags |= D3D11_CREATE_DEVICE_DEBUG; 26 | Flags &= ~D3D11_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY; 27 | #endif 28 | 29 | D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_0; 30 | 31 | HRESULT hr = reshade::hooks::call(&D3D11CreateDeviceAndSwapChain)(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, nullptr, nullptr, ppDevice, &FeatureLevel, nullptr); 32 | 33 | if (FAILED(hr)) 34 | { 35 | LOG(WARNING) << "> 'D3D11CreateDeviceAndSwapChain' failed with error code " << std::hex << hr << std::dec << "!"; 36 | 37 | return hr; 38 | } 39 | 40 | LOG(INFO) << "> Using feature level " << std::hex << FeatureLevel << std::dec << "."; 41 | 42 | if (ppDevice != nullptr) 43 | { 44 | IDXGIDevice1 *dxgidevice = nullptr; 45 | ID3D11Device *const device = *ppDevice; 46 | ID3D11DeviceContext *devicecontext = nullptr; 47 | 48 | assert(device != nullptr); 49 | 50 | device->QueryInterface(&dxgidevice); 51 | device->GetImmediateContext(&devicecontext); 52 | 53 | assert(dxgidevice != nullptr); 54 | assert(devicecontext != nullptr); 55 | 56 | const auto device_proxy = new D3D11Device(device); 57 | const auto devicecontext_proxy = new D3D11DeviceContext(device_proxy, devicecontext); 58 | device_proxy->_dxgi_device = new DXGIDevice(dxgidevice, device_proxy); 59 | device_proxy->_immediate_context = devicecontext_proxy; 60 | 61 | if (pSwapChainDesc != nullptr) 62 | { 63 | assert(ppSwapChain != nullptr); 64 | 65 | if (pAdapter != nullptr) 66 | { 67 | pAdapter->AddRef(); 68 | } 69 | else 70 | { 71 | hr = device_proxy->_dxgi_device->GetAdapter(&pAdapter); 72 | 73 | assert(SUCCEEDED(hr)); 74 | } 75 | 76 | IDXGIFactory *factory = nullptr; 77 | 78 | hr = pAdapter->GetParent(IID_PPV_ARGS(&factory)); 79 | 80 | assert(SUCCEEDED(hr)); 81 | 82 | LOG(INFO) << "> Calling 'IDXGIFactory::CreateSwapChain':"; 83 | 84 | hr = factory->CreateSwapChain(device_proxy, const_cast(pSwapChainDesc), ppSwapChain); 85 | 86 | factory->Release(); 87 | pAdapter->Release(); 88 | } 89 | 90 | if (SUCCEEDED(hr)) 91 | { 92 | LOG(INFO) << "Returning 'IDXGIDevice1' object " << device_proxy->_dxgi_device; 93 | LOG(INFO) << "Returning 'ID3D11Device' object " << device_proxy; 94 | 95 | *ppDevice = device_proxy; 96 | 97 | if (ppImmediateContext != nullptr) 98 | { 99 | LOG(INFO) << "Returning 'ID3D11DeviceContext' object " << devicecontext_proxy; 100 | 101 | devicecontext_proxy->AddRef(); 102 | *ppImmediateContext = devicecontext_proxy; 103 | } 104 | } 105 | else 106 | { 107 | device_proxy->Release(); 108 | } 109 | } 110 | 111 | if (pFeatureLevel != nullptr) 112 | { 113 | *pFeatureLevel = FeatureLevel; 114 | } 115 | 116 | return hr; 117 | } 118 | -------------------------------------------------------------------------------- /source/d3d11/d3d11.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "d3d11_runtime.hpp" 9 | 10 | struct __declspec(uuid("72299288-2C68-4AD8-945D-2BFB5AA9C609")) D3D11Device; 11 | struct __declspec(uuid("27B0246B-2152-4D42-AD11-32489472238F")) D3D11DeviceContext; 12 | -------------------------------------------------------------------------------- /source/d3d11/d3d11_effect_compiler.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_syntax_tree.hpp" 9 | #include 10 | 11 | namespace reshade::d3d11 12 | { 13 | #pragma region Forward Declarations 14 | struct d3d11_pass_data; 15 | class d3d11_runtime; 16 | #pragma endregion 17 | 18 | class d3d11_effect_compiler 19 | { 20 | public: 21 | d3d11_effect_compiler(d3d11_runtime *runtime, const reshadefx::syntax_tree &ast, std::string &errors, bool skipoptimization = false); 22 | 23 | bool run(); 24 | 25 | private: 26 | void error(const reshadefx::location &location, const std::string &message); 27 | void warning(const reshadefx::location &location, const std::string &message); 28 | 29 | void visit(std::stringstream &output, const reshadefx::nodes::statement_node *node); 30 | void visit(std::stringstream &output, const reshadefx::nodes::expression_node *node); 31 | void visit(std::stringstream &output, const reshadefx::nodes::type_node &type, bool with_qualifiers = true); 32 | void visit(std::stringstream &output, const reshadefx::nodes::lvalue_expression_node *node); 33 | void visit(std::stringstream &output, const reshadefx::nodes::literal_expression_node *node); 34 | void visit(std::stringstream &output, const reshadefx::nodes::expression_sequence_node *node); 35 | void visit(std::stringstream &output, const reshadefx::nodes::unary_expression_node *node); 36 | void visit(std::stringstream &output, const reshadefx::nodes::binary_expression_node *node); 37 | void visit(std::stringstream &output, const reshadefx::nodes::intrinsic_expression_node *node); 38 | void visit(std::stringstream &output, const reshadefx::nodes::conditional_expression_node *node); 39 | void visit(std::stringstream &output, const reshadefx::nodes::swizzle_expression_node *node); 40 | void visit(std::stringstream &output, const reshadefx::nodes::field_expression_node *node); 41 | void visit(std::stringstream &output, const reshadefx::nodes::assignment_expression_node *node); 42 | void visit(std::stringstream &output, const reshadefx::nodes::call_expression_node *node); 43 | void visit(std::stringstream &output, const reshadefx::nodes::constructor_expression_node *node); 44 | void visit(std::stringstream &output, const reshadefx::nodes::initializer_list_node *node); 45 | void visit(std::stringstream &output, const reshadefx::nodes::compound_statement_node *node); 46 | void visit(std::stringstream &output, const reshadefx::nodes::declarator_list_node *node, bool single_statement); 47 | void visit(std::stringstream &output, const reshadefx::nodes::expression_statement_node *node); 48 | void visit(std::stringstream &output, const reshadefx::nodes::if_statement_node *node); 49 | void visit(std::stringstream &output, const reshadefx::nodes::switch_statement_node *node); 50 | void visit(std::stringstream &output, const reshadefx::nodes::case_statement_node *node); 51 | void visit(std::stringstream &output, const reshadefx::nodes::for_statement_node *node); 52 | void visit(std::stringstream &output, const reshadefx::nodes::while_statement_node *node); 53 | void visit(std::stringstream &output, const reshadefx::nodes::return_statement_node *node); 54 | void visit(std::stringstream &output, const reshadefx::nodes::jump_statement_node *node); 55 | void visit(std::stringstream &output, const reshadefx::nodes::struct_declaration_node *node); 56 | void visit(std::stringstream &output, const reshadefx::nodes::variable_declaration_node *node, bool with_type = true); 57 | void visit(std::stringstream &output, const reshadefx::nodes::function_declaration_node *node); 58 | 59 | void visit_texture(const reshadefx::nodes::variable_declaration_node *node); 60 | void visit_sampler(const reshadefx::nodes::variable_declaration_node *node); 61 | void visit_uniform(const reshadefx::nodes::variable_declaration_node *node); 62 | void visit_technique(const reshadefx::nodes::technique_declaration_node *node); 63 | void visit_pass(const reshadefx::nodes::pass_declaration_node *node, d3d11_pass_data &pass); 64 | void visit_pass_shader(const reshadefx::nodes::function_declaration_node *node, const std::string &shadertype, d3d11_pass_data &pass); 65 | 66 | d3d11_runtime *_runtime; 67 | bool _success = true; 68 | const reshadefx::syntax_tree &_ast; 69 | std::string &_errors; 70 | std::stringstream _global_code, _global_uniforms; 71 | bool _skip_shader_optimization, _is_in_parameter_block = false, _is_in_function_block = false; 72 | size_t _uniform_storage_offset = 0, _constant_buffer_size = 0; 73 | HMODULE _d3dcompiler_module = nullptr; 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /source/d3d11/d3d11_runtime.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include "runtime.hpp" 11 | #include "d3d11_stateblock.hpp" 12 | 13 | namespace reshade::d3d11 14 | { 15 | struct d3d11_tex_data : base_object 16 | { 17 | com_ptr texture; 18 | com_ptr srv[2]; 19 | com_ptr rtv[2]; 20 | }; 21 | struct d3d11_pass_data : base_object 22 | { 23 | com_ptr vertex_shader; 24 | com_ptr pixel_shader; 25 | com_ptr blend_state; 26 | com_ptr depth_stencil_state; 27 | UINT stencil_reference; 28 | bool clear_render_targets; 29 | com_ptr render_targets[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; 30 | com_ptr render_target_resources[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; 31 | D3D11_VIEWPORT viewport; 32 | std::vector> shader_resources; 33 | }; 34 | struct d3d11_technique_data : base_object 35 | { 36 | bool query_in_flight = false; 37 | com_ptr timestamp_disjoint; 38 | com_ptr timestamp_query_beg; 39 | com_ptr timestamp_query_end; 40 | }; 41 | 42 | class d3d11_runtime : public runtime 43 | { 44 | public: 45 | d3d11_runtime(ID3D11Device *device, IDXGISwapChain *swapchain); 46 | 47 | bool on_init(const DXGI_SWAP_CHAIN_DESC &desc); 48 | void on_reset(); 49 | void on_reset_effect() override; 50 | static void do_draw_fx(void* runtime); 51 | void draw_fx(); 52 | void on_present(); 53 | void on_draw_call(ID3D11DeviceContext *context, unsigned int vertices); 54 | void on_set_depthstencil_view(ID3D11DepthStencilView *&depthstencil); 55 | void on_get_depthstencil_view(ID3D11DepthStencilView *&depthstencil); 56 | void on_clear_depthstencil_view(ID3D11DepthStencilView *&depthstencil); 57 | void on_copy_resource(ID3D11Resource *&dest, ID3D11Resource *&source); 58 | 59 | void capture_frame(uint8_t *buffer) const override; 60 | bool load_effect(const reshadefx::syntax_tree &ast, std::string &errors) override; 61 | bool update_texture(texture &texture, const uint8_t *data) override; 62 | 63 | void render_technique(const technique &technique) override; 64 | void render_imgui_draw_data(ImDrawData *data) override; 65 | 66 | com_ptr _device; 67 | com_ptr _immediate_context; 68 | com_ptr _swapchain; 69 | 70 | com_ptr _backbuffer_texture; 71 | com_ptr _backbuffer_texture_srv[2]; 72 | com_ptr _backbuffer_rtv[3]; 73 | com_ptr _depthstencil_texture_srv; 74 | std::vector> _effect_sampler_states; 75 | std::unordered_map _effect_sampler_descs; 76 | std::vector> _effect_shader_resources; 77 | std::vector> _constant_buffers; 78 | 79 | private: 80 | struct depth_source_info 81 | { 82 | UINT width, height; 83 | UINT drawcall_count, vertices_count; 84 | }; 85 | 86 | bool init_backbuffer_texture(); 87 | bool init_default_depth_stencil(); 88 | bool init_fx_resources(); 89 | bool init_imgui_resources(); 90 | bool init_imgui_font_atlas(); 91 | 92 | void detect_depth_source(); 93 | bool create_depthstencil_replacement(ID3D11DepthStencilView *depthstencil); 94 | 95 | bool _is_multisampling_enabled = false; 96 | DXGI_FORMAT _backbuffer_format = DXGI_FORMAT_UNKNOWN; 97 | d3d11_stateblock _stateblock; 98 | com_ptr _backbuffer, _backbuffer_resolved; 99 | com_ptr _depthstencil, _depthstencil_replacement; 100 | com_ptr _depthstencil_texture; 101 | com_ptr _default_depthstencil; 102 | std::unordered_map _depth_source_table; 103 | com_ptr _copy_vertex_shader; 104 | com_ptr _copy_pixel_shader; 105 | com_ptr _copy_sampler; 106 | std::mutex _mutex; 107 | com_ptr _effect_rasterizer_state; 108 | 109 | com_ptr _imgui_vertex_buffer, _imgui_index_buffer; 110 | com_ptr _imgui_vertex_shader; 111 | com_ptr _imgui_pixel_shader; 112 | com_ptr _imgui_input_layout; 113 | com_ptr _imgui_constant_buffer; 114 | com_ptr _imgui_texture_sampler; 115 | com_ptr _imgui_rasterizer_state; 116 | com_ptr _imgui_blend_state; 117 | com_ptr _imgui_depthstencil_state; 118 | int _imgui_vertex_buffer_size = 0, _imgui_index_buffer_size = 0; 119 | }; 120 | } 121 | -------------------------------------------------------------------------------- /source/d3d11/d3d11_stateblock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "d3d11_stateblock.hpp" 7 | 8 | namespace reshade::d3d11 9 | { 10 | template 11 | static inline void safe_release(T *&object) 12 | { 13 | if (object != nullptr) 14 | { 15 | object->Release(); 16 | object = nullptr; 17 | } 18 | } 19 | 20 | d3d11_stateblock::d3d11_stateblock(const com_ptr &device) 21 | { 22 | ZeroMemory(this, sizeof(*this)); 23 | 24 | _device = device; 25 | _device_feature_level = device->GetFeatureLevel(); 26 | } 27 | d3d11_stateblock::~d3d11_stateblock() 28 | { 29 | release_all_device_objects(); 30 | } 31 | 32 | void d3d11_stateblock::capture(const com_ptr &devicecontext) 33 | { 34 | _device_context = devicecontext; 35 | 36 | _device_context->IAGetPrimitiveTopology(&_ia_primitive_topology); 37 | _device_context->IAGetInputLayout(&_ia_input_layout); 38 | 39 | if (_device_feature_level > D3D_FEATURE_LEVEL_10_0) 40 | { 41 | _device_context->IAGetVertexBuffers(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, _ia_vertex_buffers, _ia_vertex_strides, _ia_vertex_offsets); 42 | } 43 | else 44 | { 45 | _device_context->IAGetVertexBuffers(0, D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, _ia_vertex_buffers, _ia_vertex_strides, _ia_vertex_offsets); 46 | } 47 | 48 | _device_context->IAGetIndexBuffer(&_ia_index_buffer, &_ia_index_format, &_ia_index_offset); 49 | 50 | _device_context->RSGetState(&_rs_state); 51 | _device_context->RSGetViewports(&_rs_num_viewports, nullptr); 52 | _device_context->RSGetViewports(&_rs_num_viewports, _rs_viewports); 53 | 54 | _vs_num_class_instances = ARRAYSIZE(_vs_class_instances); 55 | _device_context->VSGetShader(&_vs, _vs_class_instances, &_vs_num_class_instances); 56 | _device_context->VSGetConstantBuffers(0, ARRAYSIZE(_vs_constant_buffers), _vs_constant_buffers); 57 | _device_context->VSGetSamplers(0, ARRAYSIZE(_vs_sampler_states), _vs_sampler_states); 58 | _device_context->VSGetShaderResources(0, ARRAYSIZE(_vs_shader_resources), _vs_shader_resources); 59 | 60 | if (_device_feature_level >= D3D_FEATURE_LEVEL_10_0) 61 | { 62 | if (_device_feature_level >= D3D_FEATURE_LEVEL_11_0) 63 | { 64 | _hs_num_class_instances = ARRAYSIZE(_hs_class_instances); 65 | _device_context->HSGetShader(&_hs, _hs_class_instances, &_hs_num_class_instances); 66 | 67 | _ds_num_class_instances = ARRAYSIZE(_ds_class_instances); 68 | _device_context->DSGetShader(&_ds, _ds_class_instances, &_ds_num_class_instances); 69 | } 70 | 71 | _gs_num_class_instances = ARRAYSIZE(_gs_class_instances); 72 | _device_context->GSGetShader(&_gs, _gs_class_instances, &_gs_num_class_instances); 73 | } 74 | 75 | _ps_num_class_instances = ARRAYSIZE(_ps_class_instances); 76 | _device_context->PSGetShader(&_ps, _ps_class_instances, &_ps_num_class_instances); 77 | _device_context->PSGetConstantBuffers(0, ARRAYSIZE(_ps_constant_buffers), _ps_constant_buffers); 78 | _device_context->PSGetSamplers(0, ARRAYSIZE(_ps_sampler_states), _ps_sampler_states); 79 | _device_context->PSGetShaderResources(0, ARRAYSIZE(_ps_shader_resources), _ps_shader_resources); 80 | 81 | _device_context->OMGetBlendState(&_om_blend_state, _om_blend_factor, &_om_sample_mask); 82 | _device_context->OMGetDepthStencilState(&_om_depth_stencil_state, &_om_stencil_ref); 83 | _device_context->OMGetRenderTargets(ARRAYSIZE(_om_render_targets), _om_render_targets, &_om_depth_stencil); 84 | } 85 | void d3d11_stateblock::apply_and_release() 86 | { 87 | _device_context->IASetPrimitiveTopology(_ia_primitive_topology); 88 | _device_context->IASetInputLayout(_ia_input_layout); 89 | 90 | if (_device_feature_level > D3D_FEATURE_LEVEL_10_0) 91 | { 92 | _device_context->IASetVertexBuffers(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, _ia_vertex_buffers, _ia_vertex_strides, _ia_vertex_offsets); 93 | } 94 | else 95 | { 96 | _device_context->IASetVertexBuffers(0, D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, _ia_vertex_buffers, _ia_vertex_strides, _ia_vertex_offsets); 97 | } 98 | 99 | _device_context->IASetIndexBuffer(_ia_index_buffer, _ia_index_format, _ia_index_offset); 100 | 101 | _device_context->RSSetState(_rs_state); 102 | _device_context->RSSetViewports(_rs_num_viewports, _rs_viewports); 103 | 104 | _device_context->VSSetShader(_vs, _vs_class_instances, _vs_num_class_instances); 105 | _device_context->VSSetConstantBuffers(0, ARRAYSIZE(_vs_constant_buffers), _vs_constant_buffers); 106 | _device_context->VSSetSamplers(0, ARRAYSIZE(_vs_sampler_states), _vs_sampler_states); 107 | _device_context->VSSetShaderResources(0, ARRAYSIZE(_vs_shader_resources), _vs_shader_resources); 108 | 109 | if (_device_feature_level >= D3D_FEATURE_LEVEL_10_0) 110 | { 111 | if (_device_feature_level >= D3D_FEATURE_LEVEL_11_0) 112 | { 113 | _device_context->HSSetShader(_hs, _hs_class_instances, _hs_num_class_instances); 114 | 115 | _device_context->DSSetShader(_ds, _ds_class_instances, _ds_num_class_instances); 116 | } 117 | 118 | _device_context->GSSetShader(_gs, _gs_class_instances, _gs_num_class_instances); 119 | } 120 | 121 | _device_context->PSSetShader(_ps, _ps_class_instances, _ps_num_class_instances); 122 | _device_context->PSSetConstantBuffers(0, ARRAYSIZE(_ps_constant_buffers), _ps_constant_buffers); 123 | _device_context->PSSetSamplers(0, ARRAYSIZE(_ps_sampler_states), _ps_sampler_states); 124 | _device_context->PSSetShaderResources(0, ARRAYSIZE(_ps_shader_resources), _ps_shader_resources); 125 | 126 | _device_context->OMSetBlendState(_om_blend_state, _om_blend_factor, _om_sample_mask); 127 | _device_context->OMSetDepthStencilState(_om_depth_stencil_state, _om_stencil_ref); 128 | _device_context->OMSetRenderTargets(ARRAYSIZE(_om_render_targets), _om_render_targets, _om_depth_stencil); 129 | 130 | release_all_device_objects(); 131 | 132 | _device_context.reset(); 133 | } 134 | 135 | void d3d11_stateblock::release_all_device_objects() 136 | { 137 | safe_release(_ia_input_layout); 138 | 139 | for (auto &vertex_buffer : _ia_vertex_buffers) 140 | { 141 | safe_release(vertex_buffer); 142 | } 143 | 144 | safe_release(_ia_index_buffer); 145 | 146 | safe_release(_vs); 147 | 148 | for (UINT i = 0; i < _vs_num_class_instances; i++) 149 | { 150 | safe_release(_vs_class_instances[i]); 151 | } 152 | for (auto &constant_buffer : _vs_constant_buffers) 153 | { 154 | safe_release(constant_buffer); 155 | } 156 | for (auto &sampler_state : _vs_sampler_states) 157 | { 158 | safe_release(sampler_state); 159 | } 160 | for (auto &shader_resource : _vs_shader_resources) 161 | { 162 | safe_release(shader_resource); 163 | } 164 | 165 | safe_release(_hs); 166 | 167 | for (UINT i = 0; i < _hs_num_class_instances; i++) 168 | { 169 | safe_release(_hs_class_instances[i]); 170 | } 171 | 172 | safe_release(_ds); 173 | 174 | for (UINT i = 0; i < _ds_num_class_instances; i++) 175 | { 176 | safe_release(_ds_class_instances[i]); 177 | } 178 | 179 | safe_release(_gs); 180 | 181 | for (UINT i = 0; i < _gs_num_class_instances; i++) 182 | { 183 | safe_release(_gs_class_instances[i]); 184 | } 185 | 186 | safe_release(_rs_state); 187 | 188 | safe_release(_ps); 189 | 190 | for (UINT i = 0; i < _ps_num_class_instances; i++) 191 | { 192 | safe_release(_ps_class_instances[i]); 193 | } 194 | for (auto &constant_buffer : _ps_constant_buffers) 195 | { 196 | safe_release(constant_buffer); 197 | } 198 | for (auto &sampler_state : _ps_sampler_states) 199 | { 200 | safe_release(sampler_state); 201 | } 202 | for (auto &shader_resource : _ps_shader_resources) 203 | { 204 | safe_release(shader_resource); 205 | } 206 | 207 | safe_release(_om_blend_state); 208 | safe_release(_om_depth_stencil_state); 209 | 210 | for (auto &render_target : _om_render_targets) 211 | { 212 | safe_release(render_target); 213 | } 214 | 215 | safe_release(_om_depth_stencil); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /source/d3d11/d3d11_stateblock.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | namespace reshade::d3d11 12 | { 13 | class d3d11_stateblock 14 | { 15 | public: 16 | explicit d3d11_stateblock(const com_ptr &device); 17 | ~d3d11_stateblock(); 18 | 19 | void capture(const com_ptr &devicecontext); 20 | void apply_and_release(); 21 | 22 | private: 23 | void release_all_device_objects(); 24 | 25 | D3D_FEATURE_LEVEL _device_feature_level; 26 | com_ptr _device; 27 | com_ptr _device_context; 28 | ID3D11InputLayout *_ia_input_layout; 29 | D3D11_PRIMITIVE_TOPOLOGY _ia_primitive_topology; 30 | ID3D11Buffer *_ia_vertex_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; 31 | UINT _ia_vertex_strides[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; 32 | UINT _ia_vertex_offsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; 33 | ID3D11Buffer *_ia_index_buffer; 34 | DXGI_FORMAT _ia_index_format; 35 | UINT _ia_index_offset; 36 | ID3D11VertexShader *_vs; 37 | UINT _vs_num_class_instances; 38 | ID3D11ClassInstance *_vs_class_instances[256]; 39 | ID3D11Buffer *_vs_constant_buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; 40 | ID3D11SamplerState *_vs_sampler_states[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; 41 | ID3D11ShaderResourceView *_vs_shader_resources[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; 42 | ID3D11HullShader *_hs; 43 | UINT _hs_num_class_instances; 44 | ID3D11ClassInstance *_hs_class_instances[256]; 45 | ID3D11DomainShader *_ds; 46 | UINT _ds_num_class_instances; 47 | ID3D11ClassInstance *_ds_class_instances[256]; 48 | ID3D11GeometryShader *_gs; 49 | UINT _gs_num_class_instances; 50 | ID3D11ClassInstance *_gs_class_instances[256]; 51 | ID3D11RasterizerState *_rs_state; 52 | UINT _rs_num_viewports; 53 | D3D11_VIEWPORT _rs_viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 54 | ID3D11PixelShader *_ps; 55 | UINT _ps_num_class_instances; 56 | ID3D11ClassInstance *_ps_class_instances[256]; 57 | ID3D11Buffer *_ps_constant_buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; 58 | ID3D11SamplerState *_ps_sampler_states[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; 59 | ID3D11ShaderResourceView *_ps_shader_resources[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; 60 | ID3D11BlendState *_om_blend_state; 61 | FLOAT _om_blend_factor[4]; 62 | UINT _om_sample_mask; 63 | ID3D11DepthStencilState *_om_depth_stencil_state; 64 | UINT _om_stencil_ref; 65 | ID3D11RenderTargetView *_om_render_targets[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; 66 | ID3D11DepthStencilView *_om_depth_stencil; 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /source/d3d9/d3d9.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "d3d9_runtime.hpp" 9 | 10 | struct __declspec(uuid("F1006E9A-1C51-4AF4-ACEF-3605D2D4C8EE")) Direct3DDevice9; 11 | struct __declspec(uuid("BC52FCE4-1EAC-40C8-84CF-863600BBAA01")) Direct3DSwapChain9; 12 | -------------------------------------------------------------------------------- /source/d3d9/d3d9_effect_compiler.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_syntax_tree.hpp" 9 | #include 10 | #include 11 | 12 | namespace reshade::d3d9 13 | { 14 | #pragma region Forward Declarations 15 | struct d3d9_sampler; 16 | struct d3d9_pass_data; 17 | class d3d9_runtime; 18 | #pragma endregion 19 | 20 | class d3d9_effect_compiler 21 | { 22 | public: 23 | d3d9_effect_compiler(d3d9_runtime *runtime, const reshadefx::syntax_tree &ast, std::string &errors, bool skipoptimization = false); 24 | 25 | bool run(); 26 | 27 | private: 28 | void error(const reshadefx::location &location, const std::string &message); 29 | void warning(const reshadefx::location &location, const std::string &message); 30 | 31 | void visit(std::stringstream &output, const reshadefx::nodes::statement_node *node); 32 | void visit(std::stringstream &output, const reshadefx::nodes::expression_node *node); 33 | void visit(std::stringstream &output, const reshadefx::nodes::type_node &type, bool with_qualifiers = true); 34 | void visit(std::stringstream &output, const reshadefx::nodes::lvalue_expression_node *node); 35 | void visit(std::stringstream &output, const reshadefx::nodes::literal_expression_node *node); 36 | void visit(std::stringstream &output, const reshadefx::nodes::expression_sequence_node *node); 37 | void visit(std::stringstream &output, const reshadefx::nodes::unary_expression_node *node); 38 | void visit(std::stringstream &output, const reshadefx::nodes::binary_expression_node *node); 39 | void visit(std::stringstream &output, const reshadefx::nodes::intrinsic_expression_node *node); 40 | void visit(std::stringstream &output, const reshadefx::nodes::conditional_expression_node *node); 41 | void visit(std::stringstream &output, const reshadefx::nodes::swizzle_expression_node *node); 42 | void visit(std::stringstream &output, const reshadefx::nodes::field_expression_node *node); 43 | void visit(std::stringstream &output, const reshadefx::nodes::assignment_expression_node *node); 44 | void visit(std::stringstream &output, const reshadefx::nodes::call_expression_node *node); 45 | void visit(std::stringstream &output, const reshadefx::nodes::constructor_expression_node *node); 46 | void visit(std::stringstream &output, const reshadefx::nodes::initializer_list_node *node); 47 | void visit(std::stringstream &output, const reshadefx::nodes::compound_statement_node *node); 48 | void visit(std::stringstream &output, const reshadefx::nodes::declarator_list_node *node, bool single_statement = false); 49 | void visit(std::stringstream &output, const reshadefx::nodes::expression_statement_node *node); 50 | void visit(std::stringstream &output, const reshadefx::nodes::if_statement_node *node); 51 | void visit(std::stringstream &output, const reshadefx::nodes::switch_statement_node *node); 52 | void visit(std::stringstream &output, const reshadefx::nodes::case_statement_node *node); 53 | void visit(std::stringstream &output, const reshadefx::nodes::for_statement_node *node); 54 | void visit(std::stringstream &output, const reshadefx::nodes::while_statement_node *node); 55 | void visit(std::stringstream &output, const reshadefx::nodes::return_statement_node *node); 56 | void visit(std::stringstream &output, const reshadefx::nodes::jump_statement_node *node); 57 | void visit(std::stringstream &output, const reshadefx::nodes::struct_declaration_node *node); 58 | void visit(std::stringstream &output, const reshadefx::nodes::variable_declaration_node *node, bool with_type = true, bool with_semantic = true); 59 | void visit(std::stringstream &output, const reshadefx::nodes::function_declaration_node *node); 60 | 61 | void visit_texture(const reshadefx::nodes::variable_declaration_node *node); 62 | void visit_sampler(const reshadefx::nodes::variable_declaration_node *node); 63 | void visit_uniform(const reshadefx::nodes::variable_declaration_node *node); 64 | void visit_technique(const reshadefx::nodes::technique_declaration_node *node); 65 | void visit_pass(const reshadefx::nodes::pass_declaration_node *node, d3d9_pass_data &pass); 66 | void visit_pass_shader(const reshadefx::nodes::function_declaration_node *node, const std::string &shadertype, const std::string &samplers, d3d9_pass_data &pass); 67 | 68 | struct function 69 | { 70 | std::string code; 71 | std::vector dependencies; 72 | std::unordered_set sampler_dependencies; 73 | }; 74 | 75 | d3d9_runtime *_runtime; 76 | bool _success = true; 77 | const reshadefx::syntax_tree &_ast; 78 | std::string &_errors; 79 | size_t _uniform_storage_offset = 0, _constant_register_count = 0; 80 | std::stringstream _global_code, _global_uniforms; 81 | bool _skip_shader_optimization; 82 | const reshadefx::nodes::function_declaration_node *_current_function; 83 | std::unordered_map _samplers; 84 | std::unordered_map _functions; 85 | HMODULE _d3dcompiler_module = nullptr; 86 | }; 87 | } 88 | -------------------------------------------------------------------------------- /source/d3d9/d3d9_runtime.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "runtime.hpp" 10 | #include "com_ptr.hpp" 11 | 12 | namespace reshade::d3d9 13 | { 14 | struct d3d9_sampler 15 | { 16 | DWORD states[12]; 17 | struct d3d9_tex_data *texture; 18 | }; 19 | 20 | struct d3d9_tex_data : base_object 21 | { 22 | com_ptr texture; 23 | com_ptr surface; 24 | }; 25 | struct d3d9_pass_data : base_object 26 | { 27 | com_ptr vertex_shader; 28 | com_ptr pixel_shader; 29 | d3d9_sampler samplers[16] = { }; 30 | DWORD sampler_count = 0; 31 | com_ptr stateblock; 32 | bool clear_render_targets = false; 33 | IDirect3DSurface9 *render_targets[8] = { }; 34 | }; 35 | 36 | class d3d9_runtime : public runtime 37 | { 38 | public: 39 | d3d9_runtime(IDirect3DDevice9 *device, IDirect3DSwapChain9 *swapchain); 40 | 41 | bool on_init(const D3DPRESENT_PARAMETERS &pp); 42 | void on_reset(); 43 | static void do_draw_fx(void* runtime); 44 | void draw_fx(); 45 | void on_present(); 46 | void on_draw_call(D3DPRIMITIVETYPE type, UINT count); 47 | void on_set_depthstencil_surface(IDirect3DSurface9 *&depthstencil); 48 | void on_get_depthstencil_surface(IDirect3DSurface9 *&depthstencil); 49 | 50 | void capture_frame(uint8_t *buffer) const override; 51 | bool load_effect(const reshadefx::syntax_tree &ast, std::string &errors) override; 52 | bool update_texture(texture &texture, const uint8_t *data) override; 53 | bool update_texture_reference(texture &texture, texture_reference id); 54 | 55 | void render_technique(const technique &technique) override; 56 | void render_imgui_draw_data(ImDrawData *data) override; 57 | 58 | com_ptr _d3d; 59 | com_ptr _device; 60 | com_ptr _swapchain; 61 | 62 | com_ptr _backbuffer, _backbuffer_resolved; 63 | com_ptr _backbuffer_texture; 64 | com_ptr _backbuffer_texture_surface; 65 | com_ptr _depthstencil_texture; 66 | 67 | private: 68 | struct depth_source_info 69 | { 70 | UINT width, height; 71 | UINT drawcall_count, vertices_count; 72 | }; 73 | 74 | bool init_backbuffer_texture(); 75 | bool init_default_depth_stencil(); 76 | bool init_fx_resources(); 77 | bool init_imgui_font_atlas(); 78 | 79 | void detect_depth_source(); 80 | bool create_depthstencil_replacement(IDirect3DSurface9 *depthstencil); 81 | 82 | UINT _behavior_flags, _num_simultaneous_rendertargets, _num_samplers; 83 | bool _is_multisampling_enabled = false; 84 | D3DFORMAT _backbuffer_format = D3DFMT_UNKNOWN; 85 | com_ptr _stateblock; 86 | com_ptr _depthstencil, _depthstencil_replacement, _default_depthstencil; 87 | std::unordered_map _depth_source_table; 88 | 89 | com_ptr _effect_triangle_buffer; 90 | com_ptr _effect_triangle_layout; 91 | 92 | com_ptr _imgui_vertex_buffer; 93 | com_ptr _imgui_index_buffer; 94 | int _imgui_vertex_buffer_size = 0, _imgui_index_buffer_size = 0; 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /source/d3d9/d3d9_swapchain.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "log.hpp" 7 | #include "d3d9_device.hpp" 8 | #include "d3d9_swapchain.hpp" 9 | 10 | // IDirect3DSwapChain9 11 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::QueryInterface(REFIID riid, void **ppvObj) 12 | { 13 | if (ppvObj == nullptr) 14 | { 15 | return E_POINTER; 16 | } 17 | else if ( 18 | riid == __uuidof(this) || 19 | riid == __uuidof(IUnknown) || 20 | riid == __uuidof(IDirect3DSwapChain9) || 21 | riid == __uuidof(IDirect3DSwapChain9Ex)) 22 | { 23 | #pragma region Update to IDirect3DSwapChain9Ex interface 24 | if (!_extended_interface && riid == __uuidof(IDirect3DSwapChain9Ex)) 25 | { 26 | IDirect3DSwapChain9Ex *swapchainex = nullptr; 27 | 28 | if (FAILED(_orig->QueryInterface(IID_PPV_ARGS(&swapchainex)))) 29 | { 30 | return E_NOINTERFACE; 31 | } 32 | 33 | _orig->Release(); 34 | 35 | LOG(INFO) << "Upgraded 'IDirect3DSwapChain9' object " << this << " to 'IDirect3DSwapChain9Ex'."; 36 | 37 | _orig = swapchainex; 38 | _extended_interface = true; 39 | } 40 | #pragma endregion 41 | 42 | AddRef(); 43 | 44 | *ppvObj = this; 45 | 46 | return S_OK; 47 | } 48 | 49 | return _orig->QueryInterface(riid, ppvObj); 50 | } 51 | ULONG STDMETHODCALLTYPE Direct3DSwapChain9::AddRef() 52 | { 53 | _ref++; 54 | 55 | return _orig->AddRef(); 56 | } 57 | ULONG STDMETHODCALLTYPE Direct3DSwapChain9::Release() 58 | { 59 | if (--_ref == 0) 60 | { 61 | assert(_runtime != nullptr); 62 | 63 | _runtime->on_reset(); 64 | 65 | _runtime.reset(); 66 | 67 | const auto it = std::find(_device->_additional_swapchains.begin(), _device->_additional_swapchains.end(), this); 68 | 69 | if (it != _device->_additional_swapchains.end()) 70 | { 71 | _device->_additional_swapchains.erase(it); 72 | 73 | _device->Release(); 74 | } 75 | } 76 | 77 | ULONG ref = _orig->Release(); 78 | 79 | if (_ref == 0 && ref != 0) 80 | { 81 | LOG(WARNING) << "Reference count for 'IDirect3DSwapChain9" << (_extended_interface ? "Ex" : "") << "' object " << this << " is inconsistent: " << ref << ", but expected 0."; 82 | 83 | ref = 0; 84 | } 85 | 86 | if (ref == 0) 87 | { 88 | assert(_ref <= 0); 89 | 90 | LOG(INFO) << "Destroyed 'IDirect3DSwapChain9" << (_extended_interface ? "Ex" : "") << "' object " << this << "."; 91 | 92 | delete this; 93 | } 94 | 95 | return ref; 96 | } 97 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) 98 | { 99 | assert(_runtime != nullptr); 100 | 101 | _runtime->on_present(); 102 | 103 | return _orig->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); 104 | } 105 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *pDestSurface) 106 | { 107 | return _orig->GetFrontBufferData(pDestSurface); 108 | } 109 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) 110 | { 111 | return _orig->GetBackBuffer(iBackBuffer, Type, ppBackBuffer); 112 | } 113 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *pRasterStatus) 114 | { 115 | return _orig->GetRasterStatus(pRasterStatus); 116 | } 117 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *pMode) 118 | { 119 | return _orig->GetDisplayMode(pMode); 120 | } 121 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetDevice(IDirect3DDevice9 **ppDevice) 122 | { 123 | if (ppDevice == nullptr) 124 | { 125 | return D3DERR_INVALIDCALL; 126 | } 127 | 128 | _device->AddRef(); 129 | 130 | *ppDevice = _device; 131 | 132 | return D3D_OK; 133 | } 134 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetPresentParameters(D3DPRESENT_PARAMETERS *pPresentationParameters) 135 | { 136 | return _orig->GetPresentParameters(pPresentationParameters); 137 | } 138 | 139 | // IDirect3DSwapChain9Ex 140 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetLastPresentCount(UINT *pLastPresentCount) 141 | { 142 | assert(_extended_interface); 143 | 144 | return static_cast(_orig)->GetLastPresentCount(pLastPresentCount); 145 | } 146 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetPresentStats(D3DPRESENTSTATS *pPresentationStatistics) 147 | { 148 | assert(_extended_interface); 149 | 150 | return static_cast(_orig)->GetPresentStats(pPresentationStatistics); 151 | } 152 | HRESULT STDMETHODCALLTYPE Direct3DSwapChain9::GetDisplayModeEx(D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) 153 | { 154 | assert(_extended_interface); 155 | 156 | return static_cast(_orig)->GetDisplayModeEx(pMode, pRotation); 157 | } 158 | -------------------------------------------------------------------------------- /source/d3d9/d3d9_swapchain.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "d3d9.hpp" 9 | 10 | struct Direct3DSwapChain9 : IDirect3DSwapChain9Ex 11 | { 12 | Direct3DSwapChain9(Direct3DDevice9 *device, IDirect3DSwapChain9 *original, const std::shared_ptr &runtime) : 13 | _orig(original), 14 | _extended_interface(false), 15 | _device(device), 16 | _runtime(runtime) { } 17 | Direct3DSwapChain9(Direct3DDevice9 *device, IDirect3DSwapChain9Ex *original, const std::shared_ptr &runtime) : 18 | _orig(original), 19 | _extended_interface(true), 20 | _device(device), 21 | _runtime(runtime) { } 22 | 23 | Direct3DSwapChain9(const Direct3DSwapChain9 &) = delete; 24 | Direct3DSwapChain9 &operator=(const Direct3DSwapChain9 &) = delete; 25 | 26 | #pragma region IUnknown 27 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override; 28 | virtual ULONG STDMETHODCALLTYPE AddRef() override; 29 | virtual ULONG STDMETHODCALLTYPE Release() override; 30 | #pragma endregion 31 | #pragma region IDirect3DSwapChain9 32 | virtual HRESULT STDMETHODCALLTYPE Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) override; 33 | virtual HRESULT STDMETHODCALLTYPE GetFrontBufferData(IDirect3DSurface9 *pDestSurface) override; 34 | virtual HRESULT STDMETHODCALLTYPE GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) override; 35 | virtual HRESULT STDMETHODCALLTYPE GetRasterStatus(D3DRASTER_STATUS *pRasterStatus) override; 36 | virtual HRESULT STDMETHODCALLTYPE GetDisplayMode(D3DDISPLAYMODE *pMode) override; 37 | virtual HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice9 **ppDevice) override; 38 | virtual HRESULT STDMETHODCALLTYPE GetPresentParameters(D3DPRESENT_PARAMETERS *pPresentationParameters) override; 39 | #pragma endregion 40 | #pragma region IDirect3DSwapChain9Ex 41 | virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT *pLastPresentCount) override; 42 | virtual HRESULT STDMETHODCALLTYPE GetPresentStats(D3DPRESENTSTATS *pPresentationStatistics) override; 43 | virtual HRESULT STDMETHODCALLTYPE GetDisplayModeEx(D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) override; 44 | #pragma endregion 45 | 46 | LONG _ref = 1; 47 | IDirect3DSwapChain9 *_orig; 48 | bool _extended_interface; 49 | Direct3DDevice9 *const _device; 50 | std::shared_ptr _runtime; 51 | }; 52 | -------------------------------------------------------------------------------- /source/directory_watcher.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "directory_watcher.hpp" 7 | #include "string_codecvt.hpp" 8 | 9 | #include 10 | 11 | namespace reshade::filesystem 12 | { 13 | directory_watcher::directory_watcher(const path &path) : 14 | _path(path), 15 | _buffer(sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH * sizeof(WCHAR)) 16 | { 17 | _file_handle = CreateFileW(path.wstring().c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); 18 | _completion_handle = CreateIoCompletionPort(_file_handle, nullptr, reinterpret_cast(_file_handle), 1); 19 | 20 | OVERLAPPED overlapped = { }; 21 | ReadDirectoryChangesW(_file_handle, _buffer.data(), static_cast(_buffer.size()), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, nullptr, &overlapped, nullptr); 22 | } 23 | directory_watcher::~directory_watcher() 24 | { 25 | CancelIo(_file_handle); 26 | 27 | CloseHandle(_file_handle); 28 | CloseHandle(_completion_handle); 29 | } 30 | 31 | bool directory_watcher::check(std::vector &modifications) 32 | { 33 | DWORD transferred; 34 | ULONG_PTR key; 35 | OVERLAPPED *overlapped; 36 | 37 | if (!GetQueuedCompletionStatus(_completion_handle, &transferred, &key, &overlapped, 0)) 38 | { 39 | return false; 40 | } 41 | 42 | static DWORD s_last_tick_count = 0; 43 | static std::string s_last_filename; 44 | 45 | auto record = reinterpret_cast(_buffer.data()); 46 | const auto current_tick_count = GetTickCount(); 47 | 48 | while (true) 49 | { 50 | const std::string filename = utf16_to_utf8(record->FileName, record->FileNameLength / sizeof(WCHAR)); 51 | 52 | if (filename != s_last_filename || s_last_tick_count + 2000 < current_tick_count) 53 | { 54 | s_last_filename = filename; 55 | s_last_tick_count = current_tick_count; 56 | 57 | modifications.push_back(_path / filename); 58 | } 59 | 60 | if (record->NextEntryOffset == 0) 61 | { 62 | break; 63 | } 64 | 65 | record = reinterpret_cast(reinterpret_cast(record) + record->NextEntryOffset); 66 | } 67 | 68 | overlapped->hEvent = nullptr; 69 | 70 | ReadDirectoryChangesW(_file_handle, _buffer.data(), static_cast(_buffer.size()), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, nullptr, overlapped, nullptr); 71 | 72 | return true; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /source/directory_watcher.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "filesystem.hpp" 9 | 10 | namespace reshade::filesystem 11 | { 12 | class directory_watcher 13 | { 14 | public: 15 | explicit directory_watcher(const path &path); 16 | ~directory_watcher(); 17 | 18 | bool check(std::vector &modifications); 19 | 20 | private: 21 | path _path; 22 | std::vector _buffer; 23 | void *_file_handle, *_completion_handle; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /source/dllmain.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "log.hpp" 7 | #include "filesystem.hpp" 8 | #include "input.hpp" 9 | #include "runtime.hpp" 10 | #include "hook_manager.hpp" 11 | #include "dllmodule.hpp" 12 | #include "version.h" 13 | #include 14 | 15 | HMODULE g_module_handle = nullptr; 16 | 17 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD fdwReason, LPVOID lpvReserved) 18 | { 19 | UNREFERENCED_PARAMETER(lpvReserved); 20 | 21 | using namespace reshade; 22 | 23 | switch (fdwReason) 24 | { 25 | case DLL_PROCESS_ATTACH: 26 | { 27 | g_module_handle = hModule; 28 | runtime::s_reshade_dll_path = filesystem::get_module_path(hModule); 29 | runtime::s_target_executable_path = filesystem::get_module_path(nullptr); 30 | 31 | log::open(filesystem::path(runtime::s_reshade_dll_path).replace_extension(".log")); 32 | 33 | #ifdef WIN64 34 | LOG(INFO) << "Initializing crosire's ReShade version '" VERSION_STRING_FILE "' (64-bit) built on '" VERSION_DATE " " VERSION_TIME "' loaded from " << runtime::s_reshade_dll_path << " to " << runtime::s_target_executable_path << " ..."; 35 | #else 36 | LOG(INFO) << "Initializing crosire's ReShade version '" VERSION_STRING_FILE "' (32-bit) built on '" VERSION_DATE " " VERSION_TIME "' loaded from " << runtime::s_reshade_dll_path << " to " << runtime::s_target_executable_path << " ..."; 37 | #endif 38 | 39 | const auto system_path = filesystem::get_special_folder_path(filesystem::special_folder::system); 40 | hooks::register_module(system_path / "d3d9.dll"); 41 | hooks::register_module(system_path / "d3d10.dll"); 42 | hooks::register_module(system_path / "d3d10_1.dll"); 43 | hooks::register_module(system_path / "d3d11.dll"); 44 | hooks::register_module(system_path / "dxgi.dll"); 45 | hooks::register_module(system_path / "opengl32.dll"); 46 | hooks::register_module(system_path / "user32.dll"); 47 | hooks::register_module(system_path / "ws2_32.dll"); 48 | DllModule::LoadModule(); 49 | 50 | LOG(INFO) << "Initialized."; 51 | break; 52 | } 53 | case DLL_PROCESS_DETACH: 54 | { 55 | LOG(INFO) << "Exiting ..."; 56 | 57 | input::uninstall(); 58 | hooks::uninstall(); 59 | 60 | LOG(INFO) << "Exited."; 61 | break; 62 | } 63 | } 64 | 65 | return TRUE; 66 | } 67 | -------------------------------------------------------------------------------- /source/dllmodule.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dllmodule.hpp" 4 | 5 | IModule* DllModule::module; 6 | 7 | bool DllModule::isValid = false; 8 | 9 | void DllModule::CreateModule(CreateModuleType f) 10 | { 11 | DllModule::module = f(); 12 | DllModule::isValid = true; 13 | } 14 | 15 | void DllModule::LoadModule() 16 | { 17 | DllModule::isValid = false; 18 | ; 19 | HINSTANCE dllHandle = nullptr; 20 | dllHandle = LoadLibrary(L"module.dll"); 21 | LOG(INFO) << "Loadind module..." << dllHandle; 22 | if (NULL != dllHandle) 23 | { 24 | LOG(INFO) << "Loaded shard lib : " << dllHandle; 25 | CreateModuleType create_module = nullptr; 26 | create_module = (CreateModuleType)GetProcAddress(dllHandle, "CreateModule"); 27 | if (create_module == nullptr) { 28 | LOG(INFO) << "Error : Can't access CreateModule()."; 29 | } 30 | else { 31 | LOG(INFO) << "CreateShard addr : " << (int)create_module; 32 | DllModule::CreateModule(create_module); 33 | } 34 | } 35 | else { 36 | LOG(INFO) << "Error : Can't load module."; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/dllmodule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "module.hpp" 4 | #include "log.hpp" 5 | #include 6 | 7 | class DllModule { 8 | public: 9 | static void CreateModule(CreateModuleType f); 10 | static void LoadModule(); 11 | static bool isValid; 12 | 13 | static IModule* module; 14 | }; 15 | -------------------------------------------------------------------------------- /source/dxgi/dxgi.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include "d3d10/d3d10_device.hpp" 11 | #include "d3d11/d3d11_device.hpp" 12 | 13 | struct __declspec(uuid("CB285C3B-3677-4332-98C7-D6339B9782B1")) DXGIDevice; 14 | struct __declspec(uuid("1F445F9F-9887-4C4C-9055-4E3BADAFCCA8")) DXGISwapChain; 15 | -------------------------------------------------------------------------------- /source/dxgi/dxgi_device.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "log.hpp" 7 | #include "dxgi_device.hpp" 8 | #include "dxgi_swapchain.hpp" 9 | 10 | // IDXGIDevice 11 | HRESULT STDMETHODCALLTYPE DXGIDevice::QueryInterface(REFIID riid, void **ppvObj) 12 | { 13 | if (ppvObj == nullptr) 14 | { 15 | return E_POINTER; 16 | } 17 | else if ( 18 | riid == __uuidof(this) || 19 | riid == __uuidof(IUnknown) || 20 | riid == __uuidof(IDXGIObject) || 21 | riid == __uuidof(IDXGIDevice) || 22 | riid == __uuidof(IDXGIDevice1) || 23 | riid == __uuidof(IDXGIDevice2) || 24 | riid == __uuidof(IDXGIDevice3) || 25 | riid == __uuidof(IDXGIDevice4)) 26 | { 27 | #pragma region Update to IDXGIDevice2 interface 28 | if (riid == __uuidof(IDXGIDevice2) && _interface_version < 2) 29 | { 30 | IDXGIDevice2 *device2 = nullptr; 31 | 32 | if (FAILED(_orig->QueryInterface(&device2))) 33 | { 34 | return E_NOINTERFACE; 35 | } 36 | 37 | _orig->Release(); 38 | 39 | LOG(INFO) << "Upgraded 'IDXGIDevice" << (_interface_version > 0 ? std::to_string(_interface_version) : "") << "' object " << this << " to 'IDXGIDevice2'."; 40 | 41 | _orig = device2; 42 | _interface_version = 2; 43 | } 44 | #pragma endregion 45 | #pragma region Update to IDXGIDevice3 interface 46 | if (riid == __uuidof(IDXGIDevice3) && _interface_version < 3) 47 | { 48 | IDXGIDevice3 *device3 = nullptr; 49 | 50 | if (FAILED(_orig->QueryInterface(&device3))) 51 | { 52 | return E_NOINTERFACE; 53 | } 54 | 55 | _orig->Release(); 56 | 57 | LOG(INFO) << "Upgraded 'IDXGIDevice" << (_interface_version > 0 ? std::to_string(_interface_version) : "") << "' object " << this << " to 'IDXGIDevice3'."; 58 | 59 | _orig = device3; 60 | _interface_version = 3; 61 | } 62 | #pragma endregion 63 | #pragma region Update to IDXGIDevice4 interface 64 | if (riid == __uuidof(IDXGIDevice4) && _interface_version < 4) 65 | { 66 | IDXGIDevice4 *device4 = nullptr; 67 | 68 | if (FAILED(_orig->QueryInterface(&device4))) 69 | { 70 | return E_NOINTERFACE; 71 | } 72 | 73 | _orig->Release(); 74 | 75 | LOG(INFO) << "Upgraded 'IDXGIDevice" << (_interface_version > 0 ? std::to_string(_interface_version) : "") << "' object " << this << " to 'IDXGIDevice4'."; 76 | 77 | _orig = device4; 78 | _interface_version = 4; 79 | } 80 | #pragma endregion 81 | 82 | AddRef(); 83 | 84 | *ppvObj = this; 85 | 86 | return S_OK; 87 | } 88 | 89 | return _direct3d_device->QueryInterface(riid, ppvObj); 90 | } 91 | ULONG STDMETHODCALLTYPE DXGIDevice::AddRef() 92 | { 93 | _ref++; 94 | 95 | return _orig->AddRef(); 96 | } 97 | ULONG STDMETHODCALLTYPE DXGIDevice::Release() 98 | { 99 | ULONG ref = _orig->Release(); 100 | 101 | if (--_ref == 0 && ref != 1) 102 | { 103 | LOG(WARNING) << "Reference count for 'IDXGIDevice" << (_interface_version > 0 ? std::to_string(_interface_version) : "") << "' object " << this << " is inconsistent: " << ref << ", but expected 1."; 104 | 105 | ref = 1; 106 | } 107 | 108 | if (ref == 1) 109 | { 110 | assert(_ref <= 0); 111 | 112 | LOG(INFO) << "Destroyed 'IDXGIDevice" << (_interface_version > 0 ? std::to_string(_interface_version) : "") << "' object " << this << "."; 113 | 114 | delete this; 115 | } 116 | 117 | return ref; 118 | } 119 | HRESULT STDMETHODCALLTYPE DXGIDevice::SetPrivateData(REFGUID Name, UINT DataSize, const void *pData) 120 | { 121 | return _orig->SetPrivateData(Name, DataSize, pData); 122 | } 123 | HRESULT STDMETHODCALLTYPE DXGIDevice::SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown) 124 | { 125 | return _orig->SetPrivateDataInterface(Name, pUnknown); 126 | } 127 | HRESULT STDMETHODCALLTYPE DXGIDevice::GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData) 128 | { 129 | return _orig->GetPrivateData(Name, pDataSize, pData); 130 | } 131 | HRESULT STDMETHODCALLTYPE DXGIDevice::GetParent(REFIID riid, void **ppParent) 132 | { 133 | return _orig->GetParent(riid, ppParent); 134 | } 135 | HRESULT STDMETHODCALLTYPE DXGIDevice::GetAdapter(IDXGIAdapter **pAdapter) 136 | { 137 | return _orig->GetAdapter(pAdapter); 138 | } 139 | HRESULT STDMETHODCALLTYPE DXGIDevice::CreateSurface(const DXGI_SURFACE_DESC *pDesc, UINT NumSurfaces, DXGI_USAGE Usage, const DXGI_SHARED_RESOURCE *pSharedResource, IDXGISurface **ppSurface) 140 | { 141 | return _orig->CreateSurface(pDesc, NumSurfaces, Usage, pSharedResource, ppSurface); 142 | } 143 | HRESULT STDMETHODCALLTYPE DXGIDevice::QueryResourceResidency(IUnknown *const *ppResources, DXGI_RESIDENCY *pResidencyStatus, UINT NumResources) 144 | { 145 | return _orig->QueryResourceResidency(ppResources, pResidencyStatus, NumResources); 146 | } 147 | HRESULT STDMETHODCALLTYPE DXGIDevice::SetGPUThreadPriority(INT Priority) 148 | { 149 | return _orig->SetGPUThreadPriority(Priority); 150 | } 151 | HRESULT STDMETHODCALLTYPE DXGIDevice::GetGPUThreadPriority(INT *pPriority) 152 | { 153 | return _orig->GetGPUThreadPriority(pPriority); 154 | } 155 | 156 | // IDXGIDevice1 157 | HRESULT STDMETHODCALLTYPE DXGIDevice::SetMaximumFrameLatency(UINT MaxLatency) 158 | { 159 | return _orig->SetMaximumFrameLatency(MaxLatency); 160 | } 161 | HRESULT STDMETHODCALLTYPE DXGIDevice::GetMaximumFrameLatency(UINT *pMaxLatency) 162 | { 163 | return _orig->GetMaximumFrameLatency(pMaxLatency); 164 | } 165 | 166 | // IDXGIDevice2 167 | HRESULT STDMETHODCALLTYPE DXGIDevice::OfferResources(UINT NumResources, IDXGIResource *const *ppResources, DXGI_OFFER_RESOURCE_PRIORITY Priority) 168 | { 169 | assert(_interface_version >= 2); 170 | 171 | return static_cast(_orig)->OfferResources(NumResources, ppResources, Priority); 172 | } 173 | HRESULT STDMETHODCALLTYPE DXGIDevice::ReclaimResources(UINT NumResources, IDXGIResource *const *ppResources, BOOL *pDiscarded) 174 | { 175 | assert(_interface_version >= 2); 176 | 177 | return static_cast(_orig)->ReclaimResources(NumResources, ppResources, pDiscarded); 178 | } 179 | HRESULT STDMETHODCALLTYPE DXGIDevice::EnqueueSetEvent(HANDLE hEvent) 180 | { 181 | assert(_interface_version >= 2); 182 | 183 | return static_cast(_orig)->EnqueueSetEvent(hEvent); 184 | } 185 | 186 | // IDXGIDevice3 187 | void STDMETHODCALLTYPE DXGIDevice::Trim() 188 | { 189 | assert(_interface_version >= 3); 190 | 191 | return static_cast(_orig)->Trim(); 192 | } 193 | 194 | // IDXGIDevice4 195 | HRESULT STDMETHODCALLTYPE DXGIDevice::OfferResources1(UINT NumResources, IDXGIResource *const *ppResources, DXGI_OFFER_RESOURCE_PRIORITY Priority, UINT Flags) 196 | { 197 | assert(_interface_version >= 4); 198 | 199 | return static_cast(_orig)->OfferResources1(NumResources, ppResources, Priority, Flags); 200 | } 201 | HRESULT STDMETHODCALLTYPE DXGIDevice::ReclaimResources1(UINT NumResources, IDXGIResource *const *ppResources, DXGI_RECLAIM_RESOURCE_RESULTS *pResults) 202 | { 203 | assert(_interface_version >= 4); 204 | 205 | return static_cast(_orig)->ReclaimResources1(NumResources, ppResources, pResults); 206 | } 207 | -------------------------------------------------------------------------------- /source/dxgi/dxgi_device.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "dxgi.hpp" 9 | 10 | struct DXGIDevice : IDXGIDevice4 11 | { 12 | DXGIDevice(IDXGIDevice1 *original, D3D10Device *direct3d_device) : 13 | _orig(original), 14 | _interface_version(1), 15 | _direct3d_device(direct3d_device) { } 16 | DXGIDevice(IDXGIDevice1 *original, D3D11Device *direct3d_device) : 17 | _orig(original), 18 | _interface_version(1), 19 | _direct3d_device(direct3d_device) { } 20 | 21 | DXGIDevice(const DXGIDevice &) = delete; 22 | DXGIDevice &operator=(const DXGIDevice &) = delete; 23 | 24 | #pragma region IUnknown 25 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override; 26 | virtual ULONG STDMETHODCALLTYPE AddRef() override; 27 | virtual ULONG STDMETHODCALLTYPE Release() override; 28 | #pragma endregion 29 | #pragma region IDXGIObject 30 | virtual HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID Name, UINT DataSize, const void *pData) override; 31 | virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown) override; 32 | virtual HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData) override; 33 | virtual HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void **ppParent) override; 34 | #pragma endregion 35 | #pragma region IDXGIDevice 36 | virtual HRESULT STDMETHODCALLTYPE GetAdapter(IDXGIAdapter **pAdapter) override; 37 | virtual HRESULT STDMETHODCALLTYPE CreateSurface(const DXGI_SURFACE_DESC *pDesc, UINT NumSurfaces, DXGI_USAGE Usage, const DXGI_SHARED_RESOURCE *pSharedResource, IDXGISurface **ppSurface) override; 38 | virtual HRESULT STDMETHODCALLTYPE QueryResourceResidency(IUnknown *const *ppResources, DXGI_RESIDENCY *pResidencyStatus, UINT NumResources) override; 39 | virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(INT Priority) override; 40 | virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(INT *pPriority) override; 41 | #pragma endregion 42 | #pragma region IDXGIDevice1 43 | virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency) override; 44 | virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(UINT *pMaxLatency) override; 45 | #pragma endregion 46 | #pragma region IDXGIDevice2 47 | virtual HRESULT STDMETHODCALLTYPE OfferResources(UINT NumResources, IDXGIResource *const *ppResources, DXGI_OFFER_RESOURCE_PRIORITY Priority) override; 48 | virtual HRESULT STDMETHODCALLTYPE ReclaimResources(UINT NumResources, IDXGIResource *const *ppResources, BOOL *pDiscarded) override; 49 | virtual HRESULT STDMETHODCALLTYPE EnqueueSetEvent(HANDLE hEvent) override; 50 | #pragma endregion 51 | #pragma region IDXGIDevice3 52 | virtual void STDMETHODCALLTYPE Trim() override; 53 | #pragma endregion 54 | #pragma region IDXGIDevice4 55 | virtual HRESULT STDMETHODCALLTYPE OfferResources1(UINT NumResources, IDXGIResource *const *ppResources, DXGI_OFFER_RESOURCE_PRIORITY Priority, UINT Flags) override; 56 | virtual HRESULT STDMETHODCALLTYPE ReclaimResources1(UINT NumResources, IDXGIResource *const *ppResources, DXGI_RECLAIM_RESOURCE_RESULTS *pResults) override; 57 | #pragma endregion 58 | 59 | LONG _ref = 1; 60 | IDXGIDevice1 *_orig; 61 | unsigned int _interface_version; 62 | IUnknown *const _direct3d_device; 63 | }; 64 | -------------------------------------------------------------------------------- /source/dxgi/dxgi_swapchain.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "dxgi.hpp" 9 | 10 | struct DXGISwapChain : IDXGISwapChain4 11 | { 12 | DXGISwapChain(D3D10Device *device, IDXGISwapChain *original, const std::shared_ptr &runtime) : 13 | _orig(original), 14 | _interface_version(0), 15 | _direct3d_device(device), 16 | _direct3d_version(10), 17 | _runtime(runtime) { } 18 | DXGISwapChain(D3D10Device *device, IDXGISwapChain1 *original, const std::shared_ptr &runtime) : 19 | _orig(original), 20 | _interface_version(1), 21 | _direct3d_device(device), 22 | _direct3d_version(10), 23 | _runtime(runtime) { } 24 | DXGISwapChain(D3D11Device *device, IDXGISwapChain *original, const std::shared_ptr &runtime) : 25 | _orig(original), 26 | _interface_version(0), 27 | _direct3d_device(device), 28 | _direct3d_version(11), 29 | _runtime(runtime) { } 30 | DXGISwapChain(D3D11Device *device, IDXGISwapChain1 *original, const std::shared_ptr &runtime) : 31 | _orig(original), 32 | _interface_version(1), 33 | _direct3d_device(device), 34 | _direct3d_version(11), 35 | _runtime(runtime) { } 36 | 37 | DXGISwapChain(const DXGISwapChain &) = delete; 38 | DXGISwapChain &operator=(const DXGISwapChain &) = delete; 39 | 40 | #pragma region IUnknown 41 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override; 42 | virtual ULONG STDMETHODCALLTYPE AddRef() override; 43 | virtual ULONG STDMETHODCALLTYPE Release() override; 44 | #pragma endregion 45 | #pragma region IDXGIObject 46 | virtual HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID Name, UINT DataSize, const void *pData) override; 47 | virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown) override; 48 | virtual HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData) override; 49 | virtual HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void **ppParent) override; 50 | #pragma endregion 51 | #pragma region IDXGIDeviceSubObject 52 | virtual HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void **ppDevice) override; 53 | #pragma endregion 54 | #pragma region IDXGISwapChain 55 | virtual HRESULT STDMETHODCALLTYPE Present(UINT SyncInterval, UINT Flags) override; 56 | virtual HRESULT STDMETHODCALLTYPE GetBuffer(UINT Buffer, REFIID riid, void **ppSurface) override; 57 | virtual HRESULT STDMETHODCALLTYPE SetFullscreenState(BOOL Fullscreen, IDXGIOutput *pTarget) override; 58 | virtual HRESULT STDMETHODCALLTYPE GetFullscreenState(BOOL *pFullscreen, IDXGIOutput **ppTarget) override; 59 | virtual HRESULT STDMETHODCALLTYPE GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc) override; 60 | virtual HRESULT STDMETHODCALLTYPE ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) override; 61 | virtual HRESULT STDMETHODCALLTYPE ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters) override; 62 | virtual HRESULT STDMETHODCALLTYPE GetContainingOutput(IDXGIOutput **ppOutput) override; 63 | virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats) override; 64 | virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT *pLastPresentCount) override; 65 | #pragma endregion 66 | #pragma region IDXGISwapChain1 67 | virtual HRESULT STDMETHODCALLTYPE GetDesc1(DXGI_SWAP_CHAIN_DESC1 *pDesc) override; 68 | virtual HRESULT STDMETHODCALLTYPE GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pDesc) override; 69 | virtual HRESULT STDMETHODCALLTYPE GetHwnd(HWND *pHwnd) override; 70 | virtual HRESULT STDMETHODCALLTYPE GetCoreWindow(REFIID refiid, void **ppUnk) override; 71 | virtual HRESULT STDMETHODCALLTYPE Present1(UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS *pPresentParameters) override; 72 | virtual BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported() override; 73 | virtual HRESULT STDMETHODCALLTYPE GetRestrictToOutput(IDXGIOutput **ppRestrictToOutput) override; 74 | virtual HRESULT STDMETHODCALLTYPE SetBackgroundColor(const DXGI_RGBA *pColor) override; 75 | virtual HRESULT STDMETHODCALLTYPE GetBackgroundColor(DXGI_RGBA *pColor) override; 76 | virtual HRESULT STDMETHODCALLTYPE SetRotation(DXGI_MODE_ROTATION Rotation) override; 77 | virtual HRESULT STDMETHODCALLTYPE GetRotation(DXGI_MODE_ROTATION *pRotation) override; 78 | #pragma endregion 79 | #pragma region IDXGISwapChain2 80 | virtual HRESULT STDMETHODCALLTYPE SetSourceSize(UINT Width, UINT Height) override; 81 | virtual HRESULT STDMETHODCALLTYPE GetSourceSize(UINT *pWidth, UINT *pHeight) override; 82 | virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency) override; 83 | virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(UINT *pMaxLatency) override; 84 | virtual HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject() override; 85 | virtual HRESULT STDMETHODCALLTYPE SetMatrixTransform(const DXGI_MATRIX_3X2_F *pMatrix) override; 86 | virtual HRESULT STDMETHODCALLTYPE GetMatrixTransform(DXGI_MATRIX_3X2_F *pMatrix) override; 87 | #pragma endregion 88 | #pragma region IDXGISwapChain3 89 | virtual UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex() override; 90 | virtual HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport(DXGI_COLOR_SPACE_TYPE ColorSpace, UINT *pColorSpaceSupport) override; 91 | virtual HRESULT STDMETHODCALLTYPE SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace) override; 92 | virtual HRESULT STDMETHODCALLTYPE ResizeBuffers1(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT Format, UINT SwapChainFlags, const UINT *pCreationNodeMask, IUnknown *const *ppPresentQueue) override; 93 | #pragma endregion 94 | #pragma region IDXGISwapChain4 95 | virtual HRESULT STDMETHODCALLTYPE SetHDRMetaData(DXGI_HDR_METADATA_TYPE Type, UINT Size, void *pMetaData) override; 96 | #pragma endregion 97 | 98 | LONG _ref = 1; 99 | IDXGISwapChain *_orig; 100 | unsigned int _interface_version; 101 | IUnknown *const _direct3d_device; 102 | const unsigned int _direct3d_version; 103 | std::shared_ptr _runtime; 104 | }; 105 | -------------------------------------------------------------------------------- /source/effect_lexer.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "source_location.hpp" 9 | 10 | namespace reshadefx 11 | { 12 | /// 13 | /// A collection of identifiers for various possible tokens. 14 | /// 15 | enum class tokenid 16 | { 17 | unknown = -1, 18 | end_of_file = 0, 19 | end_of_line = '\n', 20 | 21 | // operators 22 | space = ' ', 23 | exclaim = '!', 24 | hash = '#', 25 | dollar = '$', 26 | percent = '%', 27 | ampersand = '&', 28 | parenthesis_open = '(', 29 | parenthesis_close = ')', 30 | star = '*', 31 | plus = '+', 32 | comma = ',', 33 | minus = '-', 34 | dot = '.', 35 | slash = '/', 36 | colon = ':', 37 | semicolon = ';', 38 | less = '<', 39 | equal = '=', 40 | greater = '>', 41 | question = '?', 42 | at = '@', 43 | bracket_open = '[', 44 | backslash = '\\', 45 | bracket_close = ']', 46 | caret = '^', 47 | brace_open = '{', 48 | pipe = '|', 49 | brace_close = '}', 50 | tilde = '~', 51 | exclaim_equal = 256 /* != */, 52 | percent_equal /* %= */, 53 | ampersand_ampersand /* && */, 54 | ampersand_equal /* &= */, 55 | star_equal /* *= */, 56 | plus_plus /* ++*/, 57 | plus_equal /* += */, 58 | minus_minus /* -- */, 59 | minus_equal /* -= */, 60 | arrow /* -> */, 61 | ellipsis /* ... */, 62 | slash_equal /* /= */, 63 | colon_colon /* :: */, 64 | less_less_equal /* <<= */, 65 | less_less /* << */, 66 | less_equal /* <= */, 67 | equal_equal /* == */, 68 | greater_greater_equal /* >>= */, 69 | greater_greater /* >> */, 70 | greater_equal /* >= */, 71 | caret_equal /* ^= */, 72 | pipe_equal /* |= */, 73 | pipe_pipe /* || */, 74 | 75 | // identifiers 76 | reserved, 77 | identifier, 78 | 79 | // literals 80 | true_literal, 81 | false_literal, 82 | int_literal, 83 | uint_literal, 84 | float_literal, 85 | double_literal, 86 | string_literal, 87 | 88 | // keywords 89 | namespace_, 90 | struct_, 91 | technique, 92 | pass, 93 | for_, 94 | while_, 95 | do_, 96 | if_, 97 | else_, 98 | switch_, 99 | case_, 100 | default_, 101 | break_, 102 | continue_, 103 | return_, 104 | discard_, 105 | extern_, 106 | static_, 107 | uniform_, 108 | volatile_, 109 | precise, 110 | in, 111 | out, 112 | inout, 113 | const_, 114 | linear, 115 | noperspective, 116 | centroid, 117 | nointerpolation, 118 | 119 | void_, 120 | bool_, 121 | bool2, 122 | bool2x2, 123 | bool3, 124 | bool3x3, 125 | bool4, 126 | bool4x4, 127 | int_, 128 | int2, 129 | int2x2, 130 | int3, 131 | int3x3, 132 | int4, 133 | int4x4, 134 | uint_, 135 | uint2, 136 | uint2x2, 137 | uint3, 138 | uint3x3, 139 | uint4, 140 | uint4x4, 141 | float_, 142 | float2, 143 | float2x2, 144 | float3, 145 | float3x3, 146 | float4, 147 | float4x4, 148 | vector, 149 | matrix, 150 | string_, 151 | texture, 152 | sampler, 153 | 154 | // preprocessor directives 155 | hash_def, 156 | hash_undef, 157 | hash_if, 158 | hash_ifdef, 159 | hash_ifndef, 160 | hash_else, 161 | hash_elif, 162 | hash_endif, 163 | hash_error, 164 | hash_warning, 165 | hash_pragma, 166 | hash_include, 167 | hash_unknown, 168 | }; 169 | 170 | /// 171 | /// A structure describing a single token in the input string. 172 | /// 173 | struct token 174 | { 175 | tokenid id; 176 | location location; 177 | size_t offset, length; 178 | union 179 | { 180 | int literal_as_int; 181 | unsigned int literal_as_uint; 182 | float literal_as_float; 183 | double literal_as_double; 184 | }; 185 | std::string literal_as_string; 186 | 187 | inline operator tokenid() const { return id; } 188 | }; 189 | 190 | /// 191 | /// A lexical analyzer implementation. 192 | /// 193 | class lexer 194 | { 195 | public: 196 | /// 197 | /// Construct a new lexical analyzer for an input string. 198 | /// 199 | /// The string to analyze. 200 | explicit lexer( 201 | const std::string &input, 202 | bool ignore_whitespace = true, 203 | bool ignore_pp_directives = true, 204 | bool ignore_keywords = false, 205 | bool escape_string_literals = true); 206 | /// 207 | /// Construct a copy of an existing instance. 208 | /// 209 | /// The instance to copy. 210 | lexer(const lexer &lexer); 211 | lexer &operator=(const lexer &); 212 | 213 | /// 214 | /// Get the input string this lexical analyzer works on. 215 | /// 216 | /// A constant reference to the input string. 217 | inline const std::string &input_string() const { return _input; } 218 | 219 | /// 220 | /// Perform lexical analysis on the input string and return the next token in sequence. 221 | /// 222 | /// The next token from the input string. 223 | token lex(); 224 | 225 | /// 226 | /// Advances to the next token that is not whitespace. 227 | /// 228 | void skip_space(); 229 | /// 230 | /// Advances to the next new line, ignoring all tokens. 231 | /// 232 | void skip_to_next_line(); 233 | 234 | private: 235 | /// 236 | /// Skips an arbitary amount of characters in the input string. 237 | /// 238 | /// The number of input characters to skip. 239 | void skip(size_t length); 240 | 241 | void parse_identifier(token &tok) const; 242 | bool parse_pp_directive(token &tok); 243 | void parse_string_literal(token &tok, bool escape) const; 244 | void parse_numeric_literal(token &tok) const; 245 | 246 | std::string _input; 247 | location _cur_location; 248 | const std::string::value_type *_cur, *_end; 249 | bool _ignore_whitespace; 250 | bool _ignore_pp_directives; 251 | bool _ignore_keywords; 252 | bool _escape_string_literals; 253 | }; 254 | } 255 | -------------------------------------------------------------------------------- /source/effect_parser.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "effect_lexer.hpp" 10 | #include "effect_syntax_tree.hpp" 11 | 12 | namespace reshadefx 13 | { 14 | /// 15 | /// A parser for the ReShade FX language. 16 | /// 17 | class parser 18 | { 19 | public: 20 | /// 21 | /// Construct a new parser instance. 22 | /// 23 | explicit parser(syntax_tree &ast); 24 | parser(const parser &) = delete; 25 | ~parser(); 26 | 27 | parser &operator=(const parser &) = delete; 28 | 29 | /// 30 | /// Gets the list of error messages. 31 | /// 32 | const std::string &errors() const { return _errors; } 33 | 34 | /// 35 | /// Parse the provided input string. 36 | /// 37 | /// The string to analyze. 38 | /// A boolean value indicating whether parsing was successful or not. 39 | bool run(const std::string &source); 40 | 41 | private: 42 | void error(const location &location, unsigned int code, const std::string &message); 43 | void warning(const location &location, unsigned int code, const std::string &message); 44 | 45 | void backup(); 46 | void restore(); 47 | 48 | bool peek(tokenid tokid) const; 49 | bool peek(char tok) const { return peek(static_cast(tok)); } 50 | bool peek_multary_op(enum nodes::binary_expression_node::op &op, unsigned int &precedence) const; 51 | void consume(); 52 | void consume_until(tokenid tokid); 53 | void consume_until(char tok) { return consume_until(static_cast(tok)); } 54 | bool accept(tokenid tokid); 55 | bool accept(char tok) { return accept(static_cast(tok)); } 56 | bool accept_type_class(nodes::type_node &type); 57 | bool accept_type_qualifiers(nodes::type_node &type); 58 | bool accept_unary_op(enum nodes::unary_expression_node::op &op); 59 | bool accept_postfix_op(enum nodes::unary_expression_node::op &op); 60 | bool accept_assignment_op(enum nodes::assignment_expression_node::op &op); 61 | bool expect(tokenid tokid); 62 | bool expect(char tok) { return expect(static_cast(tok)); } 63 | 64 | bool parse_top_level(); 65 | bool parse_namespace(); 66 | bool parse_type(nodes::type_node &type); 67 | bool parse_expression(nodes::expression_node *&node); 68 | bool parse_expression_unary(nodes::expression_node *&node); 69 | bool parse_expression_multary(nodes::expression_node *&left, unsigned int left_precedence = 0); 70 | bool parse_expression_assignment(nodes::expression_node *&left); 71 | bool parse_statement(nodes::statement_node *&statement, bool scoped = true); 72 | bool parse_statement_block(nodes::statement_node *&statement, bool scoped = true); 73 | bool parse_statement_declarator_list(nodes::statement_node *&statement); 74 | bool parse_array(int &size); 75 | bool parse_annotations(std::unordered_map &annotations); 76 | bool parse_struct(nodes::struct_declaration_node *&structure); 77 | bool parse_function_declaration(nodes::type_node &type, std::string name, nodes::function_declaration_node *&function); 78 | bool parse_variable_declaration(nodes::type_node &type, std::string name, nodes::variable_declaration_node *&variable, bool global = false); 79 | bool parse_variable_assignment(nodes::expression_node *&expression); 80 | bool parse_variable_properties(nodes::variable_declaration_node *variable); 81 | bool parse_variable_properties_expression(nodes::expression_node *&expression); 82 | bool parse_technique(nodes::technique_declaration_node *&technique); 83 | bool parse_technique_pass(nodes::pass_declaration_node *&pass); 84 | bool parse_technique_pass_expression(nodes::expression_node *&expression); 85 | 86 | syntax_tree &_ast; 87 | std::string _errors; 88 | std::unique_ptr _lexer, _lexer_backup; 89 | token _token, _token_next, _token_backup; 90 | std::unique_ptr _symbol_table; 91 | }; 92 | } 93 | -------------------------------------------------------------------------------- /source/effect_preprocessor.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "effect_lexer.hpp" 13 | #include "filesystem.hpp" 14 | 15 | namespace reshadefx 16 | { 17 | /// 18 | /// A C-style pre-processor implementation. 19 | /// 20 | class preprocessor 21 | { 22 | public: 23 | struct macro 24 | { 25 | std::string replacement_list; 26 | bool is_function_like = false, is_variadic = false; 27 | std::vector parameters; 28 | }; 29 | 30 | void add_include_path(const reshade::filesystem::path &path); 31 | bool add_macro_definition(const std::string &name, const macro ¯o); 32 | bool add_macro_definition(const std::string &name, const std::string &value = "1"); 33 | 34 | const std::string &errors() const { return _errors; } 35 | const std::string ¤t_output() const { return _output; } 36 | const std::vector ¤t_pragmas() const { return _pragmas; } 37 | 38 | bool run(const reshade::filesystem::path &file_path); 39 | bool run(const reshade::filesystem::path &file_path, std::vector &included_files); 40 | 41 | private: 42 | struct if_level 43 | { 44 | token token; 45 | bool value, skipping; 46 | if_level *parent; 47 | }; 48 | struct input_level 49 | { 50 | input_level(const std::string &name, const std::string &text, input_level *parent) : 51 | _name(name), 52 | _lexer(new lexer(text, false, false, true, false)), 53 | _parent(parent) 54 | { 55 | _next_token.id = tokenid::unknown; 56 | _next_token.offset = _next_token.length = 0; 57 | } 58 | 59 | std::string _name; 60 | std::unique_ptr _lexer; 61 | token _next_token; 62 | size_t _offset; 63 | std::stack _if_stack; 64 | input_level *_parent; 65 | }; 66 | 67 | void error(const location &location, const std::string &message); 68 | void warning(const location &location, const std::string &message); 69 | 70 | lexer ¤t_lexer(); 71 | inline token current_token() const { return _token; } 72 | std::stack ¤t_if_stack(); 73 | if_level ¤t_if_level(); 74 | void push(const std::string &input, const std::string &name = std::string()); 75 | bool peek(tokenid token) const; 76 | void consume(); 77 | void consume_until(tokenid token); 78 | bool accept(tokenid token); 79 | bool expect(tokenid token); 80 | 81 | void parse(); 82 | void parse_def(); 83 | void parse_undef(); 84 | void parse_if(); 85 | void parse_ifdef(); 86 | void parse_ifndef(); 87 | void parse_elif(); 88 | void parse_else(); 89 | void parse_endif(); 90 | void parse_error(); 91 | void parse_warning(); 92 | void parse_pragma(); 93 | void parse_include(); 94 | 95 | bool evaluate_expression(); 96 | bool evaluate_identifier_as_macro(); 97 | 98 | void expand_macro(const macro ¯o, const std::vector &arguments, std::string &out); 99 | void create_macro_replacement_list(macro ¯o); 100 | 101 | bool _success = true; 102 | token _token; 103 | std::stack _input_stack; 104 | location _output_location; 105 | std::string _output, _errors, _current_token_raw_data; 106 | int _recursion_count = 0; 107 | std::unordered_map _macros; 108 | std::vector _pragmas; 109 | std::vector _include_paths; 110 | std::unordered_map _filecache; 111 | }; 112 | } 113 | -------------------------------------------------------------------------------- /source/effect_symbol_table.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace reshadefx 13 | { 14 | #pragma region Forward Declarations 15 | namespace nodes 16 | { 17 | struct declaration_node; 18 | struct call_expression_node; 19 | } 20 | #pragma endregion 21 | 22 | /// 23 | /// A scope encapsulating a list of symbols. 24 | /// 25 | struct scope 26 | { 27 | std::string name; 28 | unsigned int level, namespace_level; 29 | }; 30 | 31 | /// 32 | /// A single symbol in the symbol table. 33 | /// 34 | using symbol = nodes::declaration_node *; 35 | 36 | /// 37 | /// A symbol table managing a list of scopes and symbols. 38 | /// 39 | class symbol_table 40 | { 41 | public: 42 | symbol_table(); 43 | 44 | void enter_scope(symbol parent = nullptr); 45 | void enter_namespace(const std::string &name); 46 | void leave_scope(); 47 | void leave_namespace(); 48 | 49 | symbol current_parent() const { return _parent_stack.empty() ? nullptr : _parent_stack.top(); } 50 | const scope ¤t_scope() const { return _current_scope; } 51 | 52 | bool insert(symbol symbol, bool global = false); 53 | symbol find(const std::string &name) const; 54 | symbol find(const std::string &name, const scope &scope, bool exclusive) const; 55 | bool resolve_call(nodes::call_expression_node *call, const scope &scope, bool &intrinsic, bool &ambiguous) const; 56 | 57 | private: 58 | scope _current_scope; 59 | std::stack _parent_stack; 60 | std::unordered_map>> _symbol_stack; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /source/effect_syntax_tree.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_syntax_tree_nodes.hpp" 9 | #include 10 | 11 | namespace reshadefx 12 | { 13 | class syntax_tree 14 | { 15 | syntax_tree(const syntax_tree &) = delete; 16 | syntax_tree &operator=(const syntax_tree &) = delete; 17 | 18 | public: 19 | syntax_tree() { } 20 | 21 | template 22 | T *make_node(const location &location) 23 | { 24 | const auto node = _pool.add(); 25 | node->location = location; 26 | 27 | return node; 28 | } 29 | 30 | std::vector structs; 31 | std::vector variables; 32 | std::vector functions; 33 | std::vector techniques; 34 | 35 | private: 36 | class memory_pool 37 | { 38 | struct page 39 | { 40 | explicit page(size_t size) : cursor(0), memory(size, '\0') { } 41 | 42 | size_t cursor; 43 | std::vector memory; 44 | }; 45 | struct nodeinfo 46 | { 47 | size_t size; 48 | void(*dtor)(void *); 49 | unsigned char data[sizeof(node)]; 50 | }; 51 | 52 | public: 53 | ~memory_pool() 54 | { 55 | clear(); 56 | } 57 | 58 | template 59 | T *add() 60 | { 61 | auto size = sizeof(nodeinfo) - sizeof(node) + sizeof(T); 62 | auto page = std::find_if(_pages.begin(), _pages.end(), 63 | [size](const struct page &page) 64 | { 65 | return page.cursor + size < page.memory.size(); 66 | }); 67 | 68 | if (page == _pages.end()) 69 | { 70 | _pages.emplace_back(std::max(size_t(4096), size)); 71 | 72 | page = std::prev(_pages.end()); 73 | } 74 | 75 | const auto node = new (&page->memory.at(page->cursor)) nodeinfo; 76 | const auto node_data = new (&node->data) T(); 77 | node->size = size; 78 | node->dtor = [](void *object) { reinterpret_cast(object)->~T(); }; 79 | 80 | page->cursor += node->size; 81 | 82 | return node_data; 83 | } 84 | void clear() 85 | { 86 | for (auto &page : _pages) 87 | { 88 | auto node = reinterpret_cast(&page.memory.front()); 89 | 90 | do 91 | { 92 | node->dtor(node->data); 93 | node = reinterpret_cast(reinterpret_cast(node) + node->size); 94 | } 95 | while (node->size > 0 && (page.cursor -= node->size) > 0); 96 | } 97 | } 98 | 99 | private: 100 | std::list _pages; 101 | } _pool; 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /source/filesystem.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "filesystem.hpp" 7 | #include "string_codecvt.hpp" 8 | 9 | #include 10 | #include 11 | 12 | namespace reshade::filesystem 13 | { 14 | bool path::operator==(const path &other) const 15 | { 16 | return _stricmp(_data.c_str(), other._data.c_str()) == 0; 17 | } 18 | bool path::operator!=(const path &other) const 19 | { 20 | return !operator==(other); 21 | } 22 | 23 | std::wstring path::wstring() const 24 | { 25 | return utf8_to_utf16(_data); 26 | } 27 | 28 | std::ostream &operator<<(std::ostream &stream, const path &path) 29 | { 30 | WCHAR username[257]; 31 | DWORD username_length = _countof(username); 32 | GetUserNameW(username, &username_length); 33 | username_length -= 1; 34 | 35 | std::wstring result = utf8_to_utf16(path._data); 36 | 37 | for (size_t start_pos = 0; (start_pos = result.find(username, start_pos)) != std::wstring::npos; start_pos += username_length) 38 | { 39 | result.replace(start_pos, username_length, username_length, '*'); 40 | } 41 | 42 | return stream << '\'' << utf16_to_utf8(result) << '\''; 43 | } 44 | 45 | bool path::is_absolute() const 46 | { 47 | return PathIsRelativeW(utf8_to_utf16(_data).c_str()) == FALSE; 48 | } 49 | 50 | path path::parent_path() const 51 | { 52 | WCHAR buffer[MAX_PATH] = { }; 53 | utf8_to_utf16(_data, buffer); 54 | 55 | PathRemoveFileSpecW(buffer); 56 | return utf16_to_utf8(buffer); 57 | } 58 | path path::filename() const 59 | { 60 | WCHAR buffer[MAX_PATH] = { }; 61 | utf8_to_utf16(_data, buffer); 62 | 63 | return utf16_to_utf8(PathFindFileNameW(buffer)); 64 | } 65 | path path::filename_without_extension() const 66 | { 67 | WCHAR buffer[MAX_PATH] = { }; 68 | utf8_to_utf16(_data, buffer); 69 | 70 | PathRemoveExtensionW(buffer); 71 | return utf16_to_utf8(PathFindFileNameW(buffer)); 72 | } 73 | std::string path::extension() const 74 | { 75 | WCHAR buffer[MAX_PATH] = { }; 76 | utf8_to_utf16(_data, buffer); 77 | 78 | return utf16_to_utf8(PathFindExtensionW(buffer)); 79 | } 80 | 81 | path &path::replace_extension(const std::string &extension) 82 | { 83 | WCHAR buffer[MAX_PATH] = { }; 84 | utf8_to_utf16(_data, buffer); 85 | 86 | PathRenameExtensionW(buffer, utf8_to_utf16(extension).c_str()); 87 | return operator=(utf16_to_utf8(buffer)); 88 | } 89 | 90 | path path::operator/(const path &more) const 91 | { 92 | WCHAR buffer[MAX_PATH] = { }; 93 | utf8_to_utf16(_data, buffer); 94 | 95 | PathAppendW(buffer, utf8_to_utf16(more.string()).c_str()); 96 | return utf16_to_utf8(buffer); 97 | } 98 | 99 | bool exists(const path &path) 100 | { 101 | return GetFileAttributesW(path.wstring().c_str()) != INVALID_FILE_ATTRIBUTES; 102 | } 103 | path resolve(const path &filename, const std::vector &paths) 104 | { 105 | for (const auto &path : paths) 106 | { 107 | auto result = absolute(filename, path); 108 | 109 | if (exists(result)) 110 | { 111 | return result; 112 | } 113 | } 114 | 115 | return filename; 116 | } 117 | path absolute(const path &filename, const path &parent_path) 118 | { 119 | if (filename.is_absolute()) 120 | { 121 | return filename; 122 | } 123 | 124 | WCHAR result[MAX_PATH] = { }; 125 | PathCombineW(result, utf8_to_utf16(parent_path.string()).c_str(), utf8_to_utf16(filename.string()).c_str()); 126 | 127 | return utf16_to_utf8(result); 128 | } 129 | 130 | path get_module_path(void *handle) 131 | { 132 | WCHAR result[MAX_PATH] = { }; 133 | GetModuleFileNameW(static_cast(handle), result, MAX_PATH); 134 | 135 | return utf16_to_utf8(result); 136 | } 137 | path get_special_folder_path(special_folder id) 138 | { 139 | WCHAR result[MAX_PATH] = { }; 140 | 141 | switch (id) 142 | { 143 | case special_folder::app_data: 144 | SHGetFolderPathW(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, result); 145 | break; 146 | case special_folder::system: 147 | GetSystemDirectoryW(result, MAX_PATH); 148 | break; 149 | case special_folder::windows: 150 | GetWindowsDirectoryW(result, MAX_PATH); 151 | } 152 | 153 | return utf16_to_utf8(result); 154 | } 155 | 156 | std::vector list_files(const path &path, const std::string &mask, bool recursive) 157 | { 158 | if (!PathIsDirectoryW(path.wstring().c_str())) 159 | { 160 | return { }; 161 | } 162 | 163 | WIN32_FIND_DATAW ffd; 164 | 165 | const HANDLE handle = FindFirstFileW((path / mask).wstring().c_str(), &ffd); 166 | 167 | if (handle == INVALID_HANDLE_VALUE) 168 | { 169 | return { }; 170 | } 171 | 172 | std::vector result; 173 | 174 | do 175 | { 176 | const auto filename = utf16_to_utf8(ffd.cFileName); 177 | 178 | if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 179 | { 180 | if (recursive) 181 | { 182 | const auto recursive_result = list_files(filename, mask, true); 183 | result.insert(result.end(), recursive_result.begin(), recursive_result.end()); 184 | } 185 | } 186 | else 187 | { 188 | result.push_back(path / filename); 189 | } 190 | } 191 | while (FindNextFileW(handle, &ffd)); 192 | 193 | FindClose(handle); 194 | 195 | return result; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /source/filesystem.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace reshade::filesystem 13 | { 14 | enum class special_folder 15 | { 16 | app_data, 17 | system, 18 | windows, 19 | }; 20 | 21 | class path 22 | { 23 | public: 24 | path() { } 25 | path(const char *data) : _data(data) { } 26 | path(std::string data) : _data(std::move(data)) { } 27 | 28 | bool operator==(const path &other) const; 29 | bool operator!=(const path &other) const; 30 | 31 | std::string &string() { return _data; } 32 | const std::string &string() const { return _data; } 33 | std::wstring wstring() const; 34 | 35 | friend std::ostream &operator<<(std::ostream &stream, const path &path); 36 | 37 | bool empty() const { return _data.empty(); } 38 | size_t length() const { return _data.length(); } 39 | bool is_absolute() const; 40 | 41 | path parent_path() const; 42 | path filename() const; 43 | path filename_without_extension() const; 44 | std::string extension() const; 45 | 46 | path &remove_filename() { return operator=(parent_path()); } 47 | path &replace_extension(const std::string &extension); 48 | 49 | path operator/(const path &more) const; 50 | path operator+(char c) const { return _data + c; } 51 | path operator+(const path &more) const { return _data + more._data; } 52 | 53 | private: 54 | std::string _data; 55 | }; 56 | 57 | bool exists(const path &path); 58 | path resolve(const path &filename, const std::vector &paths); 59 | path absolute(const path &filename, const path &parent_path); 60 | 61 | path get_module_path(void *handle); 62 | path get_special_folder_path(special_folder id); 63 | 64 | std::vector list_files(const path &path, const std::string &mask = "*", bool recursive = false); 65 | } 66 | -------------------------------------------------------------------------------- /source/hook.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "hook.hpp" 7 | #include 8 | #include 9 | 10 | namespace reshade 11 | { 12 | static unsigned long s_reference_count = 0; 13 | 14 | void hook::enable(bool enable) const 15 | { 16 | if (enable) 17 | { 18 | MH_QueueEnableHook(target); 19 | } 20 | else 21 | { 22 | MH_QueueDisableHook(target); 23 | } 24 | } 25 | 26 | hook::status hook::install() 27 | { 28 | if (!valid()) 29 | { 30 | return hook::status::unsupported_function; 31 | } 32 | 33 | if (s_reference_count++ == 0) 34 | { 35 | MH_Initialize(); 36 | } 37 | 38 | const MH_STATUS statuscode = MH_CreateHook(target, replacement, &trampoline); 39 | 40 | if (statuscode == MH_OK || statuscode == MH_ERROR_ALREADY_CREATED) 41 | { 42 | enable(true); 43 | 44 | return hook::status::success; 45 | } 46 | 47 | if (--s_reference_count == 0) 48 | { 49 | MH_Uninitialize(); 50 | } 51 | 52 | return static_cast(statuscode); 53 | } 54 | hook::status hook::uninstall() 55 | { 56 | if (!valid()) 57 | { 58 | return hook::status::unsupported_function; 59 | } 60 | 61 | const MH_STATUS statuscode = MH_RemoveHook(target); 62 | 63 | if (statuscode == MH_ERROR_NOT_CREATED) 64 | { 65 | return hook::status::success; 66 | } 67 | else if (statuscode != MH_OK) 68 | { 69 | return static_cast(statuscode); 70 | } 71 | 72 | trampoline = nullptr; 73 | 74 | if (--s_reference_count == 0) 75 | { 76 | MH_Uninitialize(); 77 | } 78 | 79 | return hook::status::success; 80 | } 81 | 82 | hook::address hook::call() const 83 | { 84 | assert(installed()); 85 | 86 | return trampoline; 87 | } 88 | 89 | bool hook::apply_queued_actions() 90 | { 91 | return MH_ApplyQueued() == MH_OK; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /source/hook.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | namespace reshade 9 | { 10 | struct hook 11 | { 12 | /// 13 | /// Address of a function. 14 | /// 15 | using address = void *; 16 | 17 | /// 18 | /// Enumeration of status codes. 19 | /// 20 | enum class status 21 | { 22 | unknown = -1, 23 | success, 24 | not_executable = 7, 25 | unsupported_function, 26 | allocation_failure, 27 | memory_protection_failure, 28 | }; 29 | 30 | /// 31 | /// Actually enable or disable any queues hooks. 32 | /// 33 | static bool apply_queued_actions(); 34 | 35 | /// 36 | /// Return whether the hook is valid. 37 | /// 38 | bool valid() const { return target != nullptr && replacement != nullptr && target != replacement; } 39 | /// 40 | /// Return whether the hook is currently installed. 41 | /// 42 | bool installed() const { return trampoline != nullptr; } 43 | /// 44 | /// Return whether the hook is not currently installed. 45 | /// 46 | bool uninstalled() const { return trampoline == nullptr; } 47 | 48 | /// 49 | /// Enable or disable the hook. This queues the action for later execution in . 50 | /// 51 | /// Boolean indicating if hook should be enabled or disabled. 52 | void enable(bool enable) const; 53 | /// 54 | /// Install the hook. 55 | /// 56 | hook::status install(); 57 | /// 58 | /// Uninstall the hook. 59 | /// 60 | hook::status uninstall(); 61 | 62 | /// 63 | /// Return the trampoline function address of the hook. 64 | /// 65 | address call() const; 66 | template 67 | T call() const { return reinterpret_cast(call()); } 68 | 69 | address target = nullptr; 70 | address trampoline = nullptr; 71 | address replacement = nullptr; 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /source/hook_manager.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "hook.hpp" 9 | #include "filesystem.hpp" 10 | 11 | #define HOOK_EXPORT extern "C" 12 | 13 | template 14 | inline reshade::hook::address *vtable_from_instance(T *instance) 15 | { 16 | static_assert(std::is_polymorphic::value, "can only get virtual function table from polymorphic types"); 17 | 18 | return *reinterpret_cast(instance); 19 | } 20 | 21 | namespace reshade::hooks 22 | { 23 | /// 24 | /// Install hook for the specified target function. 25 | /// 26 | /// The function name. This is used for debugging only. 27 | /// The address of the target function. 28 | /// The address of the hook function. 29 | /// Set this to true to queue the enable action instead of immediately executing it. 30 | /// The status of the hook installation. 31 | bool install(const char *name, hook::address target, hook::address replacement, bool queue_enable = false); 32 | /// 33 | /// Install hook for the specified virtual function table entry. 34 | /// 35 | /// The function name. This is used for debugging only. 36 | /// The virtual function table pointer of the object to targeted object. 37 | /// The index of the target function in the virtual function table. 38 | /// The address of the hook function. 39 | /// The status of the hook installation. 40 | bool install(const char *name, hook::address vtable[], unsigned int offset, hook::address replacement); 41 | /// 42 | /// Uninstall all previously installed hooks. 43 | /// Only call this function as long as the loader-lock is active, since it is not thread-safe. 44 | /// 45 | void uninstall(); 46 | /// 47 | /// Register the matching exports in the specified module and install or delay their hooking. 48 | /// Only call this function as long as the loader-lock is active, since it is not thread-safe. 49 | /// 50 | /// The file path to the target module. 51 | void register_module(const filesystem::path &path); 52 | 53 | /// 54 | /// Call the original/trampoline function for the specified hook. 55 | /// 56 | /// The address of the hook function which was previously used to install a hook. 57 | /// The address of original/trampoline function. 58 | hook::address call(hook::address replacement); 59 | template 60 | inline T call(T replacement) 61 | { 62 | return reinterpret_cast(call(reinterpret_cast(replacement))); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /source/ini_file.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "ini_file.hpp" 7 | #include 8 | 9 | namespace reshade 10 | { 11 | static inline void trim(std::string &str, const char *chars = " \t") 12 | { 13 | str.erase(0, str.find_first_not_of(chars)); 14 | str.erase(str.find_last_not_of(chars) + 1); 15 | } 16 | static inline std::string trim(const std::string &str, const char *chars = " \t") 17 | { 18 | std::string res(str); 19 | trim(res, chars); 20 | return res; 21 | } 22 | 23 | ini_file::ini_file(const filesystem::path &path) : _path(path) 24 | { 25 | load(); 26 | } 27 | ini_file::~ini_file() 28 | { 29 | save(); 30 | } 31 | 32 | void ini_file::load() 33 | { 34 | std::string line, section; 35 | std::ifstream file(_path.wstring()); 36 | 37 | while (std::getline(file, line)) 38 | { 39 | trim(line); 40 | 41 | if (line.empty() || line[0] == ';' || line[0] == '/') 42 | { 43 | continue; 44 | } 45 | 46 | // Read section name 47 | if (line[0] == '[') 48 | { 49 | section = trim(line.substr(0, line.find(']')), " \t[]"); 50 | continue; 51 | } 52 | 53 | // Read section content 54 | const auto assign_index = line.find('='); 55 | 56 | if (assign_index != std::string::npos) 57 | { 58 | const auto key = trim(line.substr(0, assign_index)); 59 | const auto value = trim(line.substr(assign_index + 1)); 60 | std::vector value_splitted; 61 | 62 | for (size_t i = 0, len = value.size(), found; i < len; i = found + 1) 63 | { 64 | found = value.find_first_of(',', i); 65 | 66 | if (found == std::string::npos) 67 | found = len; 68 | 69 | value_splitted.push_back(value.substr(i, found - i)); 70 | } 71 | 72 | _sections[section][key] = value_splitted; 73 | } 74 | else 75 | { 76 | _sections[section][line] = 0; 77 | } 78 | } 79 | } 80 | void ini_file::save() const 81 | { 82 | if (!_modified) 83 | { 84 | return; 85 | } 86 | 87 | std::ofstream file(_path.wstring()); 88 | 89 | const auto it = _sections.find(""); 90 | 91 | if (it != _sections.end()) 92 | { 93 | for (const auto §ion_line : it->second) 94 | { 95 | file << section_line.first << '='; 96 | 97 | size_t i = 0; 98 | 99 | for (const auto &item : section_line.second.data()) 100 | { 101 | if (i++ != 0) 102 | { 103 | file << ','; 104 | } 105 | 106 | file << item; 107 | } 108 | 109 | file << std::endl; 110 | } 111 | 112 | file << std::endl; 113 | } 114 | 115 | for (const auto §ion : _sections) 116 | { 117 | if (section.first.empty()) 118 | { 119 | continue; 120 | } 121 | 122 | file << '[' << section.first << ']' << std::endl; 123 | 124 | for (const auto §ion_line : section.second) 125 | { 126 | file << section_line.first << '='; 127 | 128 | size_t i = 0; 129 | 130 | for (const auto &item : section_line.second.data()) 131 | { 132 | if (i++ != 0) 133 | { 134 | file << ','; 135 | } 136 | 137 | file << item; 138 | } 139 | 140 | file << std::endl; 141 | } 142 | 143 | file << std::endl; 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /source/ini_file.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "variant.hpp" 10 | #include "filesystem.hpp" 11 | 12 | namespace reshade 13 | { 14 | class ini_file 15 | { 16 | public: 17 | explicit ini_file(const filesystem::path &path); 18 | ~ini_file(); 19 | 20 | template 21 | void get(const std::string §ion, const std::string &key, T &value) const 22 | { 23 | const auto it1 = _sections.find(section); 24 | 25 | if (it1 == _sections.end()) 26 | { 27 | return; 28 | } 29 | 30 | const auto it2 = it1->second.find(key); 31 | 32 | if (it2 == it1->second.end()) 33 | { 34 | return; 35 | } 36 | 37 | value = it2->second.as(); 38 | } 39 | template 40 | void get(const std::string §ion, const std::string &key, T(&values)[SIZE]) const 41 | { 42 | const auto it1 = _sections.find(section); 43 | 44 | if (it1 == _sections.end()) 45 | { 46 | return; 47 | } 48 | 49 | const auto it2 = it1->second.find(key); 50 | 51 | if (it2 == it1->second.end()) 52 | { 53 | return; 54 | } 55 | 56 | for (size_t i = 0; i < SIZE; i++) 57 | { 58 | values[i] = it2->second.as(i); 59 | } 60 | } 61 | template 62 | void get(const std::string §ion, const std::string &key, std::vector &values) const 63 | { 64 | const auto it1 = _sections.find(section); 65 | 66 | if (it1 == _sections.end()) 67 | { 68 | return; 69 | } 70 | 71 | const auto it2 = it1->second.find(key); 72 | 73 | if (it2 == it1->second.end()) 74 | { 75 | return; 76 | } 77 | 78 | values.clear(); 79 | 80 | for (size_t i = 0; i < it2->second.data().size(); i++) 81 | { 82 | values.emplace_back(it2->second.as(i)); 83 | } 84 | } 85 | template 86 | void set(const std::string §ion, const std::string &key, const T &value) 87 | { 88 | _modified = true; 89 | _sections[section][key] = value; 90 | } 91 | template 92 | void set(const std::string §ion, const std::string &key, const T(&values)[SIZE]) 93 | { 94 | _modified = true; 95 | _sections[section][key] = values; 96 | } 97 | template 98 | void set(const std::string §ion, const std::string &key, const std::vector &values) 99 | { 100 | _modified = true; 101 | _sections[section][key] = values; 102 | } 103 | 104 | private: 105 | void load(); 106 | void save() const; 107 | 108 | bool _modified = false; 109 | filesystem::path _path; 110 | using section = std::unordered_map; 111 | std::unordered_map _sections; 112 | }; 113 | } 114 | -------------------------------------------------------------------------------- /source/input.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | namespace reshade 11 | { 12 | class input 13 | { 14 | public: 15 | using window_handle = void *; 16 | 17 | explicit input(window_handle window); 18 | 19 | static void register_window_with_raw_input(window_handle window, bool no_legacy_keyboard, bool no_legacy_mouse); 20 | static std::shared_ptr register_window(window_handle window); 21 | static void uninstall(); 22 | 23 | bool is_key_down(unsigned int keycode) const; 24 | bool is_key_down(unsigned int keycode, bool ctrl, bool shift, bool alt) const; 25 | bool is_key_pressed(unsigned int keycode) const; 26 | bool is_key_pressed(unsigned int keycode, bool ctrl, bool shift, bool alt) const; 27 | bool is_key_released(unsigned int keycode) const; 28 | bool is_any_key_down() const; 29 | bool is_any_key_pressed() const; 30 | bool is_any_key_released() const; 31 | unsigned int last_key_pressed() const; 32 | unsigned int last_key_released() const; 33 | bool is_mouse_button_down(unsigned int button) const; 34 | bool is_mouse_button_pressed(unsigned int button) const; 35 | bool is_mouse_button_released(unsigned int button) const; 36 | bool is_any_mouse_button_down() const; 37 | bool is_any_mouse_button_pressed() const; 38 | bool is_any_mouse_button_released() const; 39 | short mouse_wheel_delta() const { return _mouse_wheel_delta; } 40 | unsigned int mouse_position_x() const { return _mouse_position[0]; } 41 | unsigned int mouse_position_y() const { return _mouse_position[1]; } 42 | 43 | unsigned short key_to_text(unsigned int keycode) const; 44 | 45 | void block_mouse_input(bool enable); 46 | void block_keyboard_input(bool enable); 47 | 48 | bool is_blocking_mouse_input() const { return _block_mouse; } 49 | bool is_blocking_keyboard_input() const { return _block_keyboard; } 50 | 51 | void next_frame(); 52 | 53 | static bool handle_window_message(const void *message_data); 54 | 55 | private: 56 | window_handle _window; 57 | bool _block_mouse = false, _block_keyboard = false; 58 | uint8_t _keys[256] = { }, _mouse_buttons[5] = { }; 59 | short _mouse_wheel_delta = 0; 60 | unsigned int _mouse_position[2] = { }; 61 | uint64_t _frame_count = 0; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /source/log.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "log.hpp" 7 | #include 8 | 9 | namespace reshade::log 10 | { 11 | std::ofstream stream; 12 | 13 | message::message(level level) 14 | { 15 | SYSTEMTIME time; 16 | GetLocalTime(&time); 17 | 18 | const char level_names[][6] = { "INFO ", "ERROR", "WARN " }; 19 | 20 | stream << std::right << std::setfill('0') 21 | << std::setw(4) << time.wYear << '-' 22 | << std::setw(2) << time.wMonth << '-' 23 | << std::setw(2) << time.wDay << 'T' 24 | << std::setw(2) << time.wHour << ':' 25 | << std::setw(2) << time.wMinute << ':' 26 | << std::setw(2) << time.wSecond << ':' 27 | << std::setw(3) << time.wMilliseconds << ' ' 28 | << '[' << std::setw(5) << GetCurrentThreadId() << ']' << std::setfill(' ') 29 | << " | " << level_names[static_cast(level)] << " | " << std::left; 30 | } 31 | message::~message() 32 | { 33 | stream << std::endl; 34 | } 35 | 36 | bool open(const filesystem::path &path) 37 | { 38 | stream.open(path.wstring(), std::ios::out | std::ios::trunc); 39 | 40 | if (!stream.is_open()) 41 | { 42 | return false; 43 | } 44 | 45 | stream.setf(std::ios_base::showbase); 46 | 47 | stream.flush(); 48 | 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /source/log.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include "string_codecvt.hpp" 11 | #include "filesystem.hpp" 12 | 13 | #define LOG(LEVEL) LOG_##LEVEL() 14 | #define LOG_INFO() reshade::log::message(reshade::log::level::info) 15 | #define LOG_ERROR() reshade::log::message(reshade::log::level::error) 16 | #define LOG_WARNING() reshade::log::message(reshade::log::level::warning) 17 | 18 | namespace reshade::log 19 | { 20 | enum class level 21 | { 22 | info, 23 | error, 24 | warning, 25 | }; 26 | 27 | extern std::ofstream stream; 28 | 29 | struct message 30 | { 31 | message(level level); 32 | ~message(); 33 | 34 | template 35 | inline message &operator<<(const T &value) 36 | { 37 | stream << value; 38 | 39 | return *this; 40 | } 41 | inline message &operator<<(const char *message) 42 | { 43 | stream << message; 44 | 45 | return *this; 46 | } 47 | template <> 48 | inline message &operator<<(const std::wstring &message) 49 | { 50 | return operator<<(utf16_to_utf8(message)); 51 | } 52 | inline message &operator<<(const wchar_t *message) 53 | { 54 | return operator<<(utf16_to_utf8(message)); 55 | } 56 | }; 57 | 58 | /// 59 | /// Open a log file for writing. 60 | /// 61 | /// The path to the log file. 62 | bool open(const filesystem::path &path); 63 | } 64 | -------------------------------------------------------------------------------- /source/module.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/04348/reshade_custom/27ffee5852b436d37697c2fd0ee44cdf7423599a/source/module.cpp -------------------------------------------------------------------------------- /source/module.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | //struct __declspec(uuid("F1006E9A-1C51-4AF4-ACEF-3605D2D4C8EE")) Direct3DDevice9; 7 | //struct __declspec(uuid("BC52FCE4-1EAC-40C8-84CF-863600BBAA01")) Direct3DSwapChain9; 8 | 9 | typedef void(*draw_fx_func_9)(void*); 10 | typedef void(*draw_fx_func_10)(void*); 11 | typedef void(*draw_fx_func_11)(void*); 12 | 13 | class IModule { 14 | public: 15 | virtual ~IModule() = default; 16 | 17 | virtual void on_Present_9(void* runtime) = 0; 18 | virtual HRESULT CreateVertexShader_9(IDirect3DDevice9* orig, const DWORD *pFunction, IDirect3DVertexShader9 **ppShader) = 0; 19 | virtual HRESULT SetVertexShader_9(IDirect3DDevice9* orig, IDirect3DVertexShader9 *pShader) = 0; 20 | virtual HRESULT CreatePixelShader_9(IDirect3DDevice9* orig, const DWORD *pFunction, IDirect3DPixelShader9 **ppShader) = 0; 21 | virtual HRESULT SetPixelShader_9(IDirect3DDevice9* orig, IDirect3DPixelShader9 *pShader) = 0; 22 | virtual void RegisterDrawFxFunc_9(draw_fx_func_9) = 0; 23 | 24 | virtual void on_Present_10(void* runtime) = 0; 25 | virtual HRESULT CreateVertexShader_10(ID3D10Device* orig, const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10VertexShader **ppVertexShader) = 0; 26 | virtual void SetVertexShader_10(ID3D10Device* orig, ID3D10VertexShader *pPixelShader) = 0; 27 | virtual HRESULT CreatePixelShader_10(ID3D10Device* orig, const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10PixelShader **ppPixelShader) = 0; 28 | virtual void SetPixelShader_10(ID3D10Device* orig, ID3D10PixelShader *pPixelShader) = 0; 29 | virtual void RegisterDrawFxFunc_10(draw_fx_func_10) = 0; 30 | 31 | virtual void on_Present_11(void* runtime) = 0; 32 | virtual HRESULT CreateVertexShader_11(ID3D11Device* orig, const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D11ClassLinkage *pClassLinkage, ID3D11VertexShader **ppVertexShader) = 0; 33 | virtual void SetVertexShader_11(ID3D11DeviceContext* orig, ID3D11VertexShader *pVertexShader, ID3D11ClassInstance *const *ppClassInstances, UINT NumClassInstances) = 0; 34 | virtual HRESULT CreatePixelShader_11(ID3D11Device* orig, const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D11ClassLinkage *pClassLinkage, ID3D11PixelShader **ppPixelShader) = 0; 35 | virtual void SetPixelShader_11(ID3D11DeviceContext* orig, ID3D11PixelShader *pPixelShader, ID3D11ClassInstance *const *ppClassInstances, UINT NumClassInstances) = 0; 36 | virtual void RegisterDrawFxFunc_11(draw_fx_func_11) = 0; 37 | }; 38 | 39 | typedef IModule*(*CreateModuleType)(); 40 | -------------------------------------------------------------------------------- /source/moving_average.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | template 9 | class moving_average 10 | { 11 | public: 12 | moving_average() : _index(0), _average(0), _tick_sum(0), _tick_list() { } 13 | 14 | inline operator T() const { return _average; } 15 | 16 | void clear() 17 | { 18 | _index = 0; 19 | _average = 0; 20 | 21 | for (size_t i = 0; i < SAMPLES; i++) 22 | { 23 | _tick_list[i] = 0; 24 | } 25 | } 26 | void append(T value) 27 | { 28 | _tick_sum -= _tick_list[_index]; 29 | _tick_sum += _tick_list[_index] = value; 30 | _index = ++_index % SAMPLES; 31 | _average = _tick_sum / SAMPLES; 32 | } 33 | 34 | private: 35 | size_t _index; 36 | T _average, _tick_sum, _tick_list[SAMPLES]; 37 | }; 38 | -------------------------------------------------------------------------------- /source/opengl/opengl_effect_compiler.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_syntax_tree.hpp" 9 | #include 10 | 11 | namespace reshade::opengl 12 | { 13 | #pragma region Forward Declarations 14 | struct opengl_pass_data; 15 | class opengl_runtime; 16 | #pragma endregion 17 | 18 | class opengl_effect_compiler 19 | { 20 | public: 21 | opengl_effect_compiler(opengl_runtime *runtime, const reshadefx::syntax_tree &ast, std::string &errors); 22 | 23 | bool run(); 24 | 25 | private: 26 | void error(const reshadefx::location &location, const std::string &message); 27 | void warning(const reshadefx::location &location, const std::string &message); 28 | 29 | void visit(std::stringstream &output, const reshadefx::nodes::statement_node *node); 30 | void visit(std::stringstream &output, const reshadefx::nodes::expression_node *node); 31 | void visit(std::stringstream &output, const reshadefx::nodes::type_node &type, bool with_qualifiers, bool with_inout); 32 | void visit(std::stringstream &output, const reshadefx::nodes::lvalue_expression_node *node); 33 | void visit(std::stringstream &output, const reshadefx::nodes::literal_expression_node *node); 34 | void visit(std::stringstream &output, const reshadefx::nodes::expression_sequence_node *node); 35 | void visit(std::stringstream &output, const reshadefx::nodes::unary_expression_node *node); 36 | void visit(std::stringstream &output, const reshadefx::nodes::binary_expression_node *node); 37 | void visit(std::stringstream &output, const reshadefx::nodes::intrinsic_expression_node *node); 38 | void visit(std::stringstream &output, const reshadefx::nodes::conditional_expression_node *node); 39 | void visit(std::stringstream &output, const reshadefx::nodes::swizzle_expression_node *node); 40 | void visit(std::stringstream &output, const reshadefx::nodes::field_expression_node *node); 41 | void visit(std::stringstream &output, const reshadefx::nodes::assignment_expression_node *node); 42 | void visit(std::stringstream &output, const reshadefx::nodes::call_expression_node *node); 43 | void visit(std::stringstream &output, const reshadefx::nodes::constructor_expression_node *node); 44 | void visit(std::stringstream &output, const reshadefx::nodes::initializer_list_node *node); 45 | void visit(std::stringstream &output, const reshadefx::nodes::initializer_list_node *node, const reshadefx::nodes::type_node &type); 46 | void visit(std::stringstream &output, const reshadefx::nodes::compound_statement_node *node); 47 | void visit(std::stringstream &output, const reshadefx::nodes::declarator_list_node *node, bool single_statement = false); 48 | void visit(std::stringstream &output, const reshadefx::nodes::expression_statement_node *node); 49 | void visit(std::stringstream &output, const reshadefx::nodes::if_statement_node *node); 50 | void visit(std::stringstream &output, const reshadefx::nodes::switch_statement_node *node); 51 | void visit(std::stringstream &output, const reshadefx::nodes::case_statement_node *node); 52 | void visit(std::stringstream &output, const reshadefx::nodes::for_statement_node *node); 53 | void visit(std::stringstream &output, const reshadefx::nodes::while_statement_node *node); 54 | void visit(std::stringstream &output, const reshadefx::nodes::return_statement_node *node); 55 | void visit(std::stringstream &output, const reshadefx::nodes::jump_statement_node *node); 56 | void visit(std::stringstream &output, const reshadefx::nodes::struct_declaration_node *node); 57 | void visit(std::stringstream &output, const reshadefx::nodes::variable_declaration_node *node, bool with_type, bool with_qualifiers, bool with_inout); 58 | void visit(std::stringstream &output, const reshadefx::nodes::function_declaration_node *node); 59 | 60 | void visit_texture(const reshadefx::nodes::variable_declaration_node *node); 61 | void visit_sampler(const reshadefx::nodes::variable_declaration_node *node); 62 | void visit_uniform(const reshadefx::nodes::variable_declaration_node *node); 63 | void visit_technique(const reshadefx::nodes::technique_declaration_node *node); 64 | void visit_pass(const reshadefx::nodes::pass_declaration_node *node, opengl_pass_data &pass); 65 | void visit_pass_shader(const reshadefx::nodes::function_declaration_node *node, unsigned int shadertype, unsigned int &shader); 66 | void visit_shader_param(std::stringstream &output, reshadefx::nodes::type_node type, unsigned int qualifier, const std::string &name, const std::string &semantic, unsigned int shadertype); 67 | 68 | struct function 69 | { 70 | std::string code; 71 | std::vector dependencies; 72 | }; 73 | 74 | opengl_runtime *_runtime; 75 | bool _success; 76 | const reshadefx::syntax_tree &_ast; 77 | std::string &_errors; 78 | std::stringstream _global_code, _global_uniforms; 79 | const reshadefx::nodes::function_declaration_node *_current_function; 80 | std::unordered_map _functions; 81 | GLintptr _uniform_storage_offset = 0, _uniform_buffer_size = 0; 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /source/opengl/opengl_runtime.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "runtime.hpp" 9 | #include "opengl_stateblock.hpp" 10 | 11 | namespace reshade::opengl 12 | { 13 | struct opengl_tex_data : base_object 14 | { 15 | ~opengl_tex_data() 16 | { 17 | if (should_delete) 18 | { 19 | glDeleteTextures(2, id); 20 | } 21 | } 22 | 23 | bool should_delete = false; 24 | GLuint id[2] = { }; 25 | }; 26 | struct opengl_pass_data : base_object 27 | { 28 | ~opengl_pass_data() 29 | { 30 | if (program) 31 | glDeleteProgram(program); 32 | glDeleteFramebuffers(1, &fbo); 33 | } 34 | 35 | GLuint program = 0; 36 | GLuint fbo = 0, draw_textures[8] = { }; 37 | GLint stencil_reference = 0; 38 | GLuint stencil_mask = 0, stencil_read_mask = 0; 39 | GLsizei viewport_width = 0, viewport_height = 0; 40 | GLenum draw_buffers[8] = { }; 41 | GLenum stencil_func = GL_NONE, stencil_op_fail = GL_NONE, stencil_op_z_fail = GL_NONE, stencil_op_z_pass = GL_NONE; 42 | GLenum blend_eq_color = GL_NONE, blend_eq_alpha = GL_NONE, blend_src = GL_NONE, blend_dest = GL_NONE, blend_src_alpha = GL_NONE, blend_dest_alpha = GL_NONE; 43 | GLboolean color_mask[4] = { }; 44 | bool srgb = false, blend = false, stencil_test = false, clear_render_targets = true; 45 | }; 46 | struct opengl_technique_data : base_object 47 | { 48 | ~opengl_technique_data() 49 | { 50 | glDeleteQueries(1, &query); 51 | } 52 | 53 | GLuint query = 0; 54 | bool query_in_flight = false; 55 | }; 56 | 57 | struct opengl_sampler 58 | { 59 | GLuint id; 60 | opengl_tex_data *texture; 61 | bool is_srgb; 62 | bool has_mipmaps; 63 | }; 64 | 65 | class opengl_runtime : public runtime 66 | { 67 | public: 68 | opengl_runtime(HDC device); 69 | 70 | bool on_init(unsigned int width, unsigned int height); 71 | void on_reset(); 72 | void on_reset_effect() override; 73 | void on_present(); 74 | void on_draw_call(unsigned int vertices); 75 | void on_fbo_attachment(GLenum target, GLenum attachment, GLenum objecttarget, GLuint object, GLint level); 76 | 77 | void capture_frame(uint8_t *buffer) const override; 78 | bool load_effect(const reshadefx::syntax_tree &ast, std::string &errors) override; 79 | bool update_texture(texture &texture, const uint8_t *data) override; 80 | bool update_texture_reference(texture &texture, texture_reference id); 81 | 82 | void render_technique(const technique &technique) override; 83 | void render_imgui_draw_data(ImDrawData *data) override; 84 | 85 | HDC _hdc; 86 | 87 | GLuint _reference_count = 1, _current_vertex_count = 0; 88 | GLuint _default_backbuffer_fbo = 0, _default_backbuffer_rbo[2] = { }, _backbuffer_texture[2] = { }; 89 | GLuint _depth_source_fbo = 0, _depth_source = 0, _depth_texture = 0, _blit_fbo = 0; 90 | std::vector _effect_samplers; 91 | GLuint _default_vao = 0; 92 | std::vector> _effect_ubos; 93 | 94 | private: 95 | struct depth_source_info 96 | { 97 | unsigned int width, height; 98 | GLint level, format; 99 | unsigned int drawcall_count, vertices_count; 100 | }; 101 | 102 | bool init_backbuffer_texture(); 103 | bool init_default_depth_stencil(); 104 | bool init_fx_resources(); 105 | bool init_imgui_resources(); 106 | bool init_imgui_font_atlas(); 107 | 108 | void detect_depth_source(); 109 | void create_depth_texture(GLuint width, GLuint height, GLenum format); 110 | 111 | opengl_stateblock _stateblock; 112 | std::unordered_map _depth_source_table; 113 | 114 | GLuint _imgui_shader_program = 0, _imgui_VertHandle = 0, _imgui_FragHandle = 0; 115 | int _imgui_attribloc_tex = 0, _imgui_attribloc_projmtx = 0; 116 | int _imgui_attribloc_pos = 0, _imgui_attribloc_uv = 0, _imgui_attribloc_color = 0; 117 | GLuint _imgui_vbo[2] = { }, _imgui_vao = 0; 118 | }; 119 | } -------------------------------------------------------------------------------- /source/opengl/opengl_stateblock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "opengl_stateblock.hpp" 7 | 8 | namespace reshade::opengl 9 | { 10 | opengl_stateblock::opengl_stateblock() 11 | { 12 | ZeroMemory(this, sizeof(*this)); 13 | } 14 | 15 | void opengl_stateblock::capture() 16 | { 17 | glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &_vao); 18 | glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_vbo); 19 | glGetIntegerv(GL_UNIFORM_BUFFER_BINDING, &_ubo); 20 | glGetIntegerv(GL_CURRENT_PROGRAM, &_program); 21 | glGetIntegerv(GL_ACTIVE_TEXTURE, &_active_texture); 22 | 23 | for (GLuint i = 0; i < 32; i++) 24 | { 25 | glActiveTexture(GL_TEXTURE0 + i); 26 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &_textures2d[i]); 27 | glGetIntegerv(GL_SAMPLER_BINDING, &_samplers[i]); 28 | } 29 | 30 | glGetIntegerv(GL_VIEWPORT, _viewport); 31 | _scissor_test = glIsEnabled(GL_SCISSOR_TEST); 32 | _blend = glIsEnabled(GL_BLEND); 33 | glGetIntegerv(GL_BLEND_SRC, &_blend_src); 34 | glGetIntegerv(GL_BLEND_DST, &_blend_dest); 35 | glGetIntegerv(GL_BLEND_EQUATION_RGB, &_blend_eq_color); 36 | glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &_blend_eq_alpha); 37 | _depth_test = glIsEnabled(GL_DEPTH_TEST); 38 | glGetBooleanv(GL_DEPTH_WRITEMASK, &_depth_mask); 39 | glGetIntegerv(GL_DEPTH_FUNC, &_depth_func); 40 | _stencil_test = glIsEnabled(GL_STENCIL_TEST); 41 | glGetIntegerv(GL_STENCIL_REF, &_stencil_ref); 42 | glGetIntegerv(GL_STENCIL_FUNC, &_stencil_func); 43 | glGetIntegerv(GL_STENCIL_FAIL, &_stencil_op_fail); 44 | glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &_stencil_op_zfail); 45 | glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &_stencil_op_zpass); 46 | glGetIntegerv(GL_STENCIL_VALUE_MASK, &_stencil_read_mask); 47 | glGetIntegerv(GL_STENCIL_WRITEMASK, &_stencil_mask); 48 | glGetIntegerv(GL_POLYGON_MODE, &_polygon_mode); 49 | glGetIntegerv(GL_FRONT_FACE, &_frontface); 50 | _cullface = glIsEnabled(GL_CULL_FACE); 51 | glGetIntegerv(GL_CULL_FACE_MODE, &_cullface_mode); 52 | glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_fbo); 53 | _srgb = glIsEnabled(GL_FRAMEBUFFER_SRGB); 54 | glGetBooleanv(GL_COLOR_WRITEMASK, _color_mask); 55 | 56 | for (GLuint i = 0; i < 8; i++) 57 | { 58 | GLint drawbuffer = GL_NONE; 59 | glGetIntegerv(GL_DRAW_BUFFER0 + i, &drawbuffer); 60 | _drawbuffers[i] = static_cast(drawbuffer); 61 | } 62 | } 63 | void opengl_stateblock::apply() const 64 | { 65 | glBindVertexArray(_vao); 66 | glBindBuffer(GL_ARRAY_BUFFER, _vbo); 67 | glBindBuffer(GL_UNIFORM_BUFFER, _ubo); 68 | glUseProgram(_program); 69 | 70 | for (GLuint i = 0; i < 32; i++) 71 | { 72 | glActiveTexture(GL_TEXTURE0 + i); 73 | glBindTexture(GL_TEXTURE_2D, _textures2d[i]); 74 | glBindSampler(i, _samplers[i]); 75 | } 76 | 77 | glActiveTexture(_active_texture); 78 | glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]); 79 | if (_scissor_test) { glEnable(GL_SCISSOR_TEST); } 80 | else { glDisable(GL_SCISSOR_TEST); } 81 | if (_blend) { glEnable(GL_BLEND); } 82 | else { glDisable(GL_BLEND); } 83 | glBlendFunc(_blend_src, _blend_dest); 84 | glBlendEquationSeparate(_blend_eq_color, _blend_eq_alpha); 85 | if (_depth_test) { glEnable(GL_DEPTH_TEST); } 86 | else { glDisable(GL_DEPTH_TEST); } 87 | glDepthMask(_depth_mask); 88 | glDepthFunc(_depth_func); 89 | if (_stencil_test) { glEnable(GL_STENCIL_TEST); } 90 | else { glDisable(GL_STENCIL_TEST); } 91 | glStencilFunc(_stencil_func, _stencil_ref, _stencil_read_mask); 92 | glStencilOp(_stencil_op_fail, _stencil_op_zfail, _stencil_op_zpass); 93 | glStencilMask(_stencil_mask); 94 | glPolygonMode(GL_FRONT_AND_BACK, _polygon_mode); 95 | glFrontFace(_frontface); 96 | if (_cullface) { glEnable(GL_CULL_FACE); } 97 | else { glDisable(GL_CULL_FACE); } 98 | glCullFace(_cullface_mode); 99 | glBindFramebuffer(GL_FRAMEBUFFER, _fbo); 100 | if (_srgb) { glEnable(GL_FRAMEBUFFER_SRGB); } 101 | else { glDisable(GL_FRAMEBUFFER_SRGB); } 102 | glColorMask(_color_mask[0], _color_mask[1], _color_mask[2], _color_mask[3]); 103 | 104 | if (_drawbuffers[1] == GL_NONE && 105 | _drawbuffers[2] == GL_NONE && 106 | _drawbuffers[3] == GL_NONE && 107 | _drawbuffers[4] == GL_NONE && 108 | _drawbuffers[5] == GL_NONE && 109 | _drawbuffers[6] == GL_NONE && 110 | _drawbuffers[7] == GL_NONE) 111 | { 112 | glDrawBuffer(_drawbuffers[0]); 113 | } 114 | else 115 | { 116 | glDrawBuffers(8, _drawbuffers); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /source/opengl/opengl_stateblock.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "opengl_stubs.hpp" 9 | 10 | namespace reshade::opengl 11 | { 12 | class opengl_stateblock 13 | { 14 | public: 15 | opengl_stateblock(); 16 | 17 | void capture(); 18 | void apply() const; 19 | 20 | private: 21 | GLint _vao; 22 | GLint _vbo; 23 | GLint _ubo; 24 | GLint _program; 25 | GLint _textures2d[32], _samplers[32]; 26 | GLint _active_texture; 27 | GLint _viewport[4]; 28 | GLint _scissor_test; 29 | GLint _blend; 30 | GLint _blend_src, _blend_dest; 31 | GLint _blend_eq_color, _blend_eq_alpha; 32 | GLint _depth_test; 33 | GLboolean _depth_mask; 34 | GLint _depth_func; 35 | GLint _stencil_test; 36 | GLint _stencil_ref; 37 | GLint _stencil_func; 38 | GLint _stencil_op_fail, _stencil_op_zfail, _stencil_op_zpass; 39 | GLint _stencil_read_mask, _stencil_mask; 40 | GLint _polygon_mode, _frontface; 41 | GLint _cullface, _cullface_mode; 42 | GLint _fbo; 43 | GLint _srgb; 44 | GLboolean _color_mask[4]; 45 | GLenum _drawbuffers[8]; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /source/resource_loading.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "resource_loading.hpp" 7 | #include 8 | 9 | extern HMODULE g_module_handle; 10 | 11 | namespace reshade::resources 12 | { 13 | data_resource load_data_resource(unsigned int id) 14 | { 15 | const HRSRC info = FindResource(g_module_handle, MAKEINTRESOURCE(id), RT_RCDATA); 16 | const HGLOBAL handle = LoadResource(g_module_handle, info); 17 | 18 | data_resource result; 19 | result.data = LockResource(handle); 20 | result.data_size = SizeofResource(g_module_handle, info); 21 | 22 | return result; 23 | } 24 | image_resource load_image_resource(unsigned int id) 25 | { 26 | DIBSECTION dib = { }; 27 | const HANDLE handle = LoadImage(g_module_handle, MAKEINTRESOURCE(id), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 28 | GetObject(handle, sizeof(dib), &dib); 29 | 30 | image_resource result; 31 | result.width = dib.dsBm.bmWidth; 32 | result.height = dib.dsBm.bmHeight; 33 | result.bits_per_pixel = dib.dsBm.bmBitsPixel; 34 | result.data = dib.dsBm.bmBits; 35 | result.data_size = dib.dsBmih.biSizeImage; 36 | 37 | return result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/resource_loading.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "resource.h" 9 | 10 | namespace reshade::resources 11 | { 12 | struct data_resource 13 | { 14 | size_t data_size; 15 | const void *data; 16 | }; 17 | struct image_resource : public data_resource 18 | { 19 | unsigned int width, height, bits_per_pixel; 20 | }; 21 | 22 | data_resource load_data_resource(unsigned int id); 23 | image_resource load_image_resource(unsigned int id); 24 | } 25 | -------------------------------------------------------------------------------- /source/runtime_objects.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "variant.hpp" 13 | #include "moving_average.hpp" 14 | 15 | namespace reshade 16 | { 17 | enum class texture_filter 18 | { 19 | min_mag_mip_point = 0, 20 | min_mag_point_mip_linear = 0x1, 21 | min_point_mag_linear_mip_point = 0x4, 22 | min_point_mag_mip_linear = 0x5, 23 | min_linear_mag_mip_point = 0x10, 24 | min_linear_mag_point_mip_linear = 0x11, 25 | min_mag_linear_mip_point = 0x14, 26 | min_mag_mip_linear = 0x15 27 | }; 28 | enum class texture_format 29 | { 30 | unknown, 31 | 32 | r8, 33 | r16f, 34 | r32f, 35 | rg8, 36 | rg16, 37 | rg16f, 38 | rg32f, 39 | rgba8, 40 | rgba16, 41 | rgba16f, 42 | rgba32f, 43 | 44 | dxt1, 45 | dxt3, 46 | dxt5, 47 | latc1, 48 | latc2 49 | }; 50 | enum class texture_address_mode 51 | { 52 | wrap = 1, 53 | mirror = 2, 54 | clamp = 3, 55 | border = 4 56 | }; 57 | enum class texture_reference 58 | { 59 | none, 60 | back_buffer, 61 | depth_buffer 62 | }; 63 | enum class uniform_datatype 64 | { 65 | boolean, 66 | signed_integer, 67 | unsigned_integer, 68 | floating_point 69 | }; 70 | 71 | class base_object abstract 72 | { 73 | public: 74 | virtual ~base_object() { } 75 | 76 | template 77 | T *as() { return dynamic_cast(this); } 78 | template 79 | const T *as() const { return dynamic_cast(this); } 80 | }; 81 | 82 | struct texture final 83 | { 84 | #pragma region Constructors and Assignment Operators 85 | texture() = default; 86 | texture(texture &&) = default; 87 | texture(const texture &) = delete; 88 | 89 | texture &operator=(texture &&) = default; 90 | texture &operator=(const texture &) = delete; 91 | #pragma endregion 92 | 93 | std::string name, unique_name, effect_filename; 94 | unsigned int width = 0, height = 0, levels = 0; 95 | texture_format format = texture_format::unknown; 96 | std::unordered_map annotations; 97 | texture_reference impl_reference = texture_reference::none; 98 | std::unique_ptr impl; 99 | }; 100 | struct uniform final 101 | { 102 | #pragma region Constructors and Assignment Operators 103 | uniform() = default; 104 | uniform(uniform &&) = default; 105 | uniform(const uniform &) = delete; 106 | 107 | uniform &operator=(uniform &&) = default; 108 | uniform &operator=(const uniform &) = delete; 109 | #pragma endregion 110 | 111 | std::string name, unique_name, effect_filename; 112 | uniform_datatype basetype = uniform_datatype::floating_point; 113 | uniform_datatype displaytype = uniform_datatype::floating_point; 114 | unsigned int rows = 0, columns = 0, elements = 0; 115 | size_t storage_offset = 0, storage_size = 0; 116 | std::unordered_map annotations; 117 | bool hidden = false; 118 | }; 119 | struct technique final 120 | { 121 | #pragma region Constructors and Assignment Operators 122 | technique() = default; 123 | technique(technique &&) = default; 124 | technique(const technique &) = delete; 125 | 126 | technique &operator=(technique &&) = default; 127 | technique &operator=(const technique &) = delete; 128 | #pragma endregion 129 | 130 | std::string name, effect_filename; 131 | std::vector> passes; 132 | std::unordered_map annotations; 133 | bool hidden = false; 134 | bool enabled = false; 135 | int32_t timeout = 0; 136 | int32_t timeleft = 0; 137 | uint32_t toggle_key_data[4]; 138 | moving_average average_cpu_duration; 139 | moving_average average_gpu_duration; 140 | ptrdiff_t uniform_storage_offset = 0, uniform_storage_index = -1; 141 | std::unique_ptr impl; 142 | }; 143 | } 144 | -------------------------------------------------------------------------------- /source/source_location.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | namespace reshadefx 11 | { 12 | struct location 13 | { 14 | location() : line(1), column(1) { } 15 | explicit location(unsigned int line, unsigned int column = 1) : line(line), column(column) { } 16 | explicit location(const std::string &source, unsigned int line, unsigned int column = 1) : source(source), line(line), column(column) { } 17 | 18 | std::string source; 19 | unsigned int line, column; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /source/string_codecvt.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | #pragma warning(disable : 4996) 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | inline std::string utf16_to_utf8(const std::wstring &s) 14 | { 15 | return std::wstring_convert>().to_bytes(s); 16 | } 17 | inline std::string utf16_to_utf8(const wchar_t *s, size_t len) 18 | { 19 | return std::wstring_convert>().to_bytes(s, s + len); 20 | } 21 | 22 | template 23 | inline void utf16_to_utf8(const std::wstring &s, char(&target)[OUTSIZE]) 24 | { 25 | const auto o = utf16_to_utf8(s); 26 | std::copy_n(o.begin(), std::min(o.size(), OUTSIZE), target); 27 | } 28 | 29 | inline std::wstring utf8_to_utf16(const std::string &s) 30 | { 31 | return std::wstring_convert>().from_bytes(s); 32 | } 33 | inline std::wstring utf8_to_utf16(const char *s, size_t len) 34 | { 35 | return std::wstring_convert>().from_bytes(s, s + len); 36 | } 37 | 38 | template 39 | inline void utf8_to_utf16(const std::string &s, wchar_t(&target)[OUTSIZE]) 40 | { 41 | const auto o = utf8_to_utf16(s); 42 | std::copy_n(o.begin(), std::min(o.size(), OUTSIZE), target); 43 | } 44 | -------------------------------------------------------------------------------- /source/variant.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include "filesystem.hpp" 11 | 12 | namespace reshade 13 | { 14 | class variant 15 | { 16 | public: 17 | variant() { } 18 | variant(const char *value) : _values(1, value) { } 19 | template 20 | variant(const T &value) : variant(std::to_string(value)) { } 21 | template <> 22 | variant(const bool &value) : variant(value ? "1" : "0") { } 23 | template <> 24 | variant(const std::string &value) : _values(1, value) { } 25 | template <> 26 | variant(const std::vector &values) : _values(values) { } 27 | variant(const std::vector &&values) : _values(std::move(values)) { } 28 | template 29 | variant(InputIt first, InputIt last) : _values(first, last) { } 30 | template <> 31 | variant(const filesystem::path &value) : variant(value.string()) { } 32 | template <> 33 | variant(const std::vector &values) : _values(values.size()) 34 | { 35 | for (size_t i = 0; i < values.size(); i++) 36 | _values[i] = values[i].string(); 37 | } 38 | template 39 | variant(const T *values, size_t count) : _values(count) 40 | { 41 | for (size_t i = 0; i < count; i++) 42 | _values[i] = std::to_string(values[i]); 43 | } 44 | template <> 45 | variant(const bool *values, size_t count) : _values(count) 46 | { 47 | for (size_t i = 0; i < count; i++) 48 | _values[i] = values[i] ? "1" : "0"; 49 | } 50 | template 51 | variant(const T(&values)[COUNT]) : variant(values, COUNT) { } 52 | template 53 | variant(std::initializer_list values) : variant(values.begin(), values.size()) { } 54 | 55 | std::vector &data() 56 | { 57 | return _values; 58 | } 59 | const std::vector &data() const 60 | { 61 | return _values; 62 | } 63 | 64 | template 65 | const T as(size_t index = 0) const; 66 | template <> 67 | const bool as(size_t i) const 68 | { 69 | return as(i) != 0 || i < _values.size() && (_values[i] == "true" || _values[i] == "True" || _values[i] == "TRUE"); 70 | } 71 | template <> 72 | const int as(size_t i) const 73 | { 74 | return static_cast(as(i)); 75 | } 76 | template <> 77 | const unsigned int as(size_t i) const 78 | { 79 | return static_cast(as(i)); 80 | } 81 | template <> 82 | const long as(size_t i) const 83 | { 84 | if (i >= _values.size()) 85 | { 86 | return 0l; 87 | } 88 | 89 | return std::strtol(_values[i].c_str(), nullptr, 10); 90 | } 91 | template <> 92 | const unsigned long as(size_t i) const 93 | { 94 | if (i >= _values.size()) 95 | { 96 | return 0ul; 97 | } 98 | 99 | return std::strtoul(_values[i].c_str(), nullptr, 10); 100 | } 101 | template <> 102 | const float as(size_t i) const 103 | { 104 | return static_cast(as(i)); 105 | } 106 | template <> 107 | const double as(size_t i) const 108 | { 109 | if (i >= _values.size()) 110 | { 111 | return 0.0; 112 | } 113 | 114 | return std::strtod(_values[i].c_str(), nullptr); 115 | } 116 | template <> 117 | const std::string as(size_t i) const 118 | { 119 | if (i >= _values.size()) 120 | { 121 | return std::string(); 122 | } 123 | 124 | return _values[i]; 125 | } 126 | template <> 127 | const filesystem::path as(size_t i) const 128 | { 129 | return as(i); 130 | } 131 | 132 | private: 133 | std::vector _values; 134 | }; 135 | } 136 | -------------------------------------------------------------------------------- /source/windows/user32.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "log.hpp" 7 | #include "hook_manager.hpp" 8 | #include "input.hpp" 9 | #include 10 | #include 11 | 12 | HOOK_EXPORT ATOM WINAPI HookRegisterClassA(const WNDCLASSA *lpWndClass) 13 | { 14 | assert(lpWndClass != nullptr); 15 | 16 | auto wndclass = *lpWndClass; 17 | 18 | if (wndclass.hInstance == GetModuleHandle(nullptr)) 19 | { 20 | LOG(INFO) << "Redirecting '" << "RegisterClassA" << "(" << lpWndClass << ")' ..."; 21 | 22 | if ((wndclass.style & CS_OWNDC) == 0) 23 | { 24 | LOG(INFO) << "> Adding 'CS_OWNDC' window class style flag to '" << wndclass.lpszClassName << "'."; 25 | 26 | wndclass.style |= CS_OWNDC; 27 | } 28 | } 29 | 30 | return reshade::hooks::call(&HookRegisterClassA)(&wndclass); 31 | } 32 | HOOK_EXPORT ATOM WINAPI HookRegisterClassW(const WNDCLASSW *lpWndClass) 33 | { 34 | assert(lpWndClass != nullptr); 35 | 36 | auto wndclass = *lpWndClass; 37 | 38 | if (wndclass.hInstance == GetModuleHandle(nullptr)) 39 | { 40 | LOG(INFO) << "Redirecting '" << "RegisterClassW" << "(" << lpWndClass << ")' ..."; 41 | 42 | if ((wndclass.style & CS_OWNDC) == 0) 43 | { 44 | LOG(INFO) << "> Adding 'CS_OWNDC' window class style flag to '" << wndclass.lpszClassName << "'."; 45 | 46 | wndclass.style |= CS_OWNDC; 47 | } 48 | } 49 | 50 | return reshade::hooks::call(&HookRegisterClassW)(&wndclass); 51 | } 52 | HOOK_EXPORT ATOM WINAPI HookRegisterClassExA(const WNDCLASSEXA *lpWndClassEx) 53 | { 54 | assert(lpWndClassEx != nullptr); 55 | 56 | auto wndclass = *lpWndClassEx; 57 | 58 | if (wndclass.hInstance == GetModuleHandle(nullptr)) 59 | { 60 | LOG(INFO) << "Redirecting '" << "RegisterClassExA" << "(" << lpWndClassEx << ")' ..."; 61 | 62 | if ((wndclass.style & CS_OWNDC) == 0) 63 | { 64 | LOG(INFO) << "> Adding 'CS_OWNDC' window class style flag to '" << wndclass.lpszClassName << "'."; 65 | 66 | wndclass.style |= CS_OWNDC; 67 | } 68 | } 69 | 70 | return reshade::hooks::call(&HookRegisterClassExA)(&wndclass); 71 | } 72 | HOOK_EXPORT ATOM WINAPI HookRegisterClassExW(const WNDCLASSEXW *lpWndClassEx) 73 | { 74 | assert(lpWndClassEx != nullptr); 75 | 76 | auto wndclass = *lpWndClassEx; 77 | 78 | if (wndclass.hInstance == GetModuleHandle(nullptr)) 79 | { 80 | LOG(INFO) << "Redirecting '" << "RegisterClassExW" << "(" << lpWndClassEx << ")' ..."; 81 | 82 | if ((wndclass.style & CS_OWNDC) == 0) 83 | { 84 | LOG(INFO) << "> Adding 'CS_OWNDC' window class style flag to '" << wndclass.lpszClassName << "'."; 85 | 86 | wndclass.style |= CS_OWNDC; 87 | } 88 | } 89 | 90 | return reshade::hooks::call(&HookRegisterClassExW)(&wndclass); 91 | } 92 | -------------------------------------------------------------------------------- /source/windows/ws2_32.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #include "hook_manager.hpp" 7 | 8 | #include 9 | #include 10 | 11 | volatile long g_network_traffic = 0; 12 | 13 | HOOK_EXPORT int WSAAPI HookWSASend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 14 | { 15 | static const auto trampoline = reshade::hooks::call(&HookWSASend); 16 | 17 | for (DWORD i = 0; i < dwBufferCount; ++i) 18 | { 19 | InterlockedAdd(&g_network_traffic, lpBuffers[i].len); 20 | } 21 | 22 | return trampoline(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); 23 | } 24 | HOOK_EXPORT int WSAAPI HookWSASendTo(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, const struct sockaddr *lpTo, int iToLen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 25 | { 26 | static const auto trampoline = reshade::hooks::call(&HookWSASendTo); 27 | 28 | for (DWORD i = 0; i < dwBufferCount; ++i) 29 | { 30 | InterlockedAdd(&g_network_traffic, lpBuffers[i].len); 31 | } 32 | 33 | return trampoline(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iToLen, lpOverlapped, lpCompletionRoutine); 34 | } 35 | HOOK_EXPORT int WSAAPI HookWSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 36 | { 37 | static const auto trampoline = reshade::hooks::call(&HookWSARecv); 38 | 39 | const auto status = trampoline(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine); 40 | 41 | if (status == 0 && lpNumberOfBytesRecvd != nullptr) 42 | { 43 | InterlockedAdd(&g_network_traffic, *lpNumberOfBytesRecvd); 44 | } 45 | 46 | return status; 47 | } 48 | HOOK_EXPORT int WSAAPI HookWSARecvEx(SOCKET s, char *buf, int len, int *flags) 49 | { 50 | static const auto trampoline = reshade::hooks::call(&HookWSARecvEx); 51 | 52 | const int recieved = trampoline(s, buf, len, flags); 53 | 54 | if (recieved > 0) 55 | { 56 | InterlockedAdd(&g_network_traffic, recieved); 57 | } 58 | 59 | return recieved; 60 | } 61 | HOOK_EXPORT int WSAAPI HookWSARecvFrom(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct sockaddr *lpFrom, LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 62 | { 63 | static const auto trampoline = reshade::hooks::call(&HookWSARecvFrom); 64 | 65 | const auto status = trampoline(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine); 66 | 67 | if (status == 0 && lpNumberOfBytesRecvd != nullptr) 68 | { 69 | InterlockedAdd(&g_network_traffic, *lpNumberOfBytesRecvd); 70 | } 71 | 72 | return status; 73 | } 74 | 75 | HOOK_EXPORT int WSAAPI HookSend(SOCKET s, const char *buf, int len, int flags) 76 | { 77 | static const auto trampoline = reshade::hooks::call(&HookSend); 78 | 79 | const auto num_bytes_send = trampoline(s, buf, len, flags); 80 | 81 | if (num_bytes_send != SOCKET_ERROR) 82 | { 83 | InterlockedAdd(&g_network_traffic, num_bytes_send); 84 | } 85 | 86 | return num_bytes_send; 87 | } 88 | HOOK_EXPORT int WSAAPI HookSendTo(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen) 89 | { 90 | static const auto trampoline = reshade::hooks::call(&HookSendTo); 91 | 92 | const auto num_bytes_send = trampoline(s, buf, len, flags, to, tolen); 93 | 94 | if (num_bytes_send != SOCKET_ERROR) 95 | { 96 | InterlockedAdd(&g_network_traffic, num_bytes_send); 97 | } 98 | 99 | return num_bytes_send; 100 | } 101 | HOOK_EXPORT int WSAAPI HookRecv(SOCKET s, char *buf, int len, int flags) 102 | { 103 | static const auto trampoline = reshade::hooks::call(&HookRecv); 104 | 105 | const auto num_bytes_recieved = trampoline(s, buf, len, flags); 106 | 107 | if (num_bytes_recieved != SOCKET_ERROR) 108 | { 109 | InterlockedAdd(&g_network_traffic, num_bytes_recieved); 110 | } 111 | 112 | return num_bytes_recieved; 113 | } 114 | HOOK_EXPORT int WSAAPI HookRecvFrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) 115 | { 116 | static const auto trampoline = reshade::hooks::call(&HookRecvFrom); 117 | 118 | const auto num_bytes_recieved = trampoline(s, buf, len, flags, from, fromlen); 119 | 120 | if (num_bytes_recieved != SOCKET_ERROR) 121 | { 122 | InterlockedAdd(&g_network_traffic, num_bytes_recieved); 123 | } 124 | 125 | return num_bytes_recieved; 126 | } 127 | -------------------------------------------------------------------------------- /tools/verbuild.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/04348/reshade_custom/27ffee5852b436d37697c2fd0ee44cdf7423599a/tools/verbuild.exe --------------------------------------------------------------------------------