├── .gitignore ├── README.md ├── RenderDocPlugin ├── Binaries │ └── Win64 │ │ ├── UE4Editor-RenderDocPlugin.dll │ │ └── UE4Editor.modules ├── Config │ └── FilterPlugin.ini ├── Documents │ ├── UIInfo1.png │ └── UIInfo2.png ├── RenderDocPlugin.uplugin ├── Resources │ ├── Icon128.png │ ├── Icon20.png │ ├── Icon40.png │ └── SettingsIcon20.png └── Source │ └── RenderDocPlugin │ ├── Private │ ├── RenderDocAPI │ │ └── renderdoc_app.h │ ├── RenderDocPluginAboutWindow.cpp │ ├── RenderDocPluginAboutWindow.h │ ├── RenderDocPluginCommands.cpp │ ├── RenderDocPluginCommands.h │ ├── RenderDocPluginLoader.cpp │ ├── RenderDocPluginLoader.h │ ├── RenderDocPluginModule.cpp │ ├── RenderDocPluginModule.h │ ├── RenderDocPluginNotification.cpp │ ├── RenderDocPluginNotification.h │ ├── RenderDocPluginPrivatePCH.h │ ├── RenderDocPluginSettings.h │ ├── RenderDocPluginStyle.cpp │ ├── RenderDocPluginStyle.h │ ├── RenderDocPluginToolbar.cpp │ └── RenderDocPluginToolbar.h │ ├── Public │ └── IRenderDocPlugin.h │ └── RenderDocPlugin.Build.cs ├── TODO.txt └── doc └── img ├── howto-capture.jpg ├── howto-enable.jpg ├── howto-plugin_menu.jpg └── howto-settings.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | # ======================= # 2 | # Unreal Engine generated # 3 | # ======================= # 4 | DerivedDataCache/ 5 | Intermediate/ 6 | Saved/ 7 | 8 | # ======================= # 9 | # Visual Studio generated # 10 | # ======================= # 11 | *.opensdf 12 | *.sdf 13 | *.sln 14 | *.suo 15 | *.user 16 | *.pdb 17 | 18 | # ============ # 19 | # Third party # 20 | # ============ # 21 | ThirdParty/EyeX/include/ 22 | ThirdParty/EyeX/lib/ 23 | 24 | # ============ # 25 | # OS generated # 26 | # ============ # 27 | Thumbs.db -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UE4RenderDocPlugin 2 | ================== 3 | 4 | A plugin that adds easy access to Renderdoc inside Unreal Engine 4. 5 | Currently, this plugin only runs on Windows systems. 6 | 7 | 8 | 9 | ANNOUNCEMENT: 10 | At the start of the year, I created a pull request to make this plugin a part of the engine, and looking at the 4.17 preview, it seems to be merged. I might still work on experimental stuff in this repo, but it is of course easier to just use the integrated plugin when 4.17 is released if they decide to integrate it into the release. :) 11 | 12 | /Temaran 13 | 14 | 15 | 16 | 17 | Shoutouts 18 | ---------- 19 | 20 | HUGE shoutout to Slomp for contributing a lot of amazing stuff to this project! 21 | https://github.com/slomp 22 | 23 | For BP Projects 24 | --------------- 25 | I put a packaged plugin on my google drive if you cannot build from source: 26 | https://drive.google.com/open?id=0Bz4Uwz2KHfw6VXpQRTliUXJFRTg 27 | 28 | How to Use 29 | ---------- 30 | 31 | 1. Make sure you are using Unreal Engine 4 version **4.10.0 or later**. 32 | There are commit tags in the repository for older versions of the plugin that suit former versions of UE4. 33 | 34 | 2. Copy the contents of this repository into your `/Plugins/` folder. 35 | Alternatively, you may copy it to the `UE4/Engine/Plugins/` folder, thus making the plugin available to all of your projects. 36 | 37 | 3. In order to build the plugin, make sure to run UE4's `Generate Project Files` to register the plugin source code with Unreal Build Tool. 38 | 39 | 4. Download and install RenderDoc from http://renderdoc.org/builds 40 | The stable build v0.32 of 2016-12-02 is recommended. 41 | 42 | 5. From within the UE4 Editor, enable the RenderDocPlugin as shown below; you will need to restart the UE4 Editor for this change to take place. 43 | ![](doc/img/howto-plugin_menu.jpg) | ![](doc/img/howto-enable.jpg) 44 | 45 | 6. The first time the plugin is executed, it will attempt to automatically find a RenderDoc installation. 46 | If unable to locate one, you will be prompted to locate RenderDoc manually through a dialog window. 47 | The plugin will remember the RenderDoc location until it is no longer valid. 48 | 49 | 7. After the plugin has been loaded successfully, you should have two new buttons in the top-right corner of your Level Editor viewport. 50 | The left-most button ![](RenderDocPlugin/Resources/Icon20.png) will capture the next frame and automatically launch RenderDoc to inspect the frame, while the right-most button ![](RenderDocPlugin/Resources/SettingsIcon20.png) exposes some configuration options. 51 | Alternatively, the console command `RenderDoc.CaptureFrame` can also be used for capturing a frame. This is particularly useful when in PIE (Play-in-Editor) mode or when in Game mode, as the Level Editor viewport UI is omitted during gameplay. 52 | ![](doc/img/howto-capture.jpg) 53 | > **NOTE:** if RenderDoc has already been launched and remains open, newly captured frames will not be automatically opened for inspection, but will be enqueued instead; the user must then select in the RenderDoc application the frame capture intended for inspection. 54 | 55 | 8. The configuration button ![](RenderDocPlugin/Resources/SettingsIcon20.png) exposes a few settings that can be tweaked prior to capturing the frame: 56 | ![](doc/img/howto-settings.jpg) 57 | * _Capture all activity_: by default, the plugin only intercepts the rendering activity of the viewport currently active; by checking this setting, all rendering activity of all Editor windows will be captured (such as the Editor UI itself and Material Editor/Thumbnail previews). 58 | * _Capture callstack_: captures the call stack when each rendering API call was issued. 59 | * _Capture all resources_: include all rendering resources of the rendering context in the capture, even those that have not been used/referenced during the frame capture. 60 | * _Save all initial states_: include the initial state of all rendering resources, even if this initial state is found unlikely to contribute to the final contents of the frame being captured (for example, the initial contents of the GBuffer resources may be stripped from the capture since the whole GBuffer is likely to be rewritten by the frame; this setting prevents such a capture heuristic from occurring). 61 | 62 | 63 | For Advanced Users 64 | ------------------ 65 | 66 | * This version of the plugin relies upon a `renderdoc.dll` compatible with the RenderDoc v0.26 API. 67 | Other RenderDoc builds that retain API compatibility with RenderDoc v0.26 should also work with this version of the plugin. 68 | 69 | * The very first time the plugin runs, a valid RenderDoc installation will be inferred by inspecting the following Windows registry key: 70 | `HKEY_LOCAL_MACHINE\SOFTWARE\Classes\RenderDoc.RDCCapture.1\DefaultIcon\` 71 | If RenderDoc can not be located in this registry key (perhaps because you wish to use a portable version of RenderDoc, or decided to build RenderDoc from source), you will be asked to locate `renderdocui.exe` manually through a dialog window. 72 | The plugin will then keep track of this RenderDoc location by adding an entry to the following UE4 configuration file: 73 | `/Saved/Config/Windows/Game.ini` 74 | 75 | * You may also explicitly direct the plugin to a RenderDoc location by editing the following configuration file 76 | `Engine/Config/BaseGame.ini` 77 | and adding the following entry to it: 78 | ````ini 79 | [RenderDoc] 80 | BinaryPath= 81 | GreetingHasBeenShown=True 82 | ```` 83 | This method can be very useful if you wish to deploy RenderDoc into repositories that are shared by entire teams, as the RenderDoc path can be relative to some Game or Engine directory. 84 | 85 | * You may force plugin compilation by setting the following in the `RenderDocPlugin.uplugin` file: 86 | ```json 87 | "EnabledByDefault" : true, 88 | ``` 89 | Note that this will not only force-build the plugin, but will also keep the plugin activated at all times. 90 | You can then selectively disable the plugin by inserting the following into your `.uproject` file: 91 | ```json 92 | { 93 | "Name": "RenderDocPlugin", 94 | "Enabled": false 95 | }, 96 | ``` 97 | 98 | * It is possible to use the plugin in Standalone Game builds (i.e., builds without editor). Open `RenderDocPlugin.uplugin` and change the plugin `"Type"` from `"Developer"` to `"Runtime"`. This will enable the plugin code to be embedded into the game executable (that is, statically linked into the monolithic game binary image). **Note, however, that the plugin will be loaded even on shipping builds!** 99 | -------------------------------------------------------------------------------- /RenderDocPlugin/Binaries/Win64/UE4Editor-RenderDocPlugin.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/RenderDocPlugin/Binaries/Win64/UE4Editor-RenderDocPlugin.dll -------------------------------------------------------------------------------- /RenderDocPlugin/Binaries/Win64/UE4Editor.modules: -------------------------------------------------------------------------------- 1 | { 2 | "Changelist" : 3299760, 3 | "BuildId" : "f0461af1-0094-45b9-9a1b-8fb04b243a20", 4 | "Modules" : 5 | { 6 | "RenderDocPlugin" : "UE4Editor-RenderDocPlugin.dll" 7 | } 8 | } -------------------------------------------------------------------------------- /RenderDocPlugin/Config/FilterPlugin.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | -------------------------------------------------------------------------------- /RenderDocPlugin/Documents/UIInfo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/RenderDocPlugin/Documents/UIInfo1.png -------------------------------------------------------------------------------- /RenderDocPlugin/Documents/UIInfo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/RenderDocPlugin/Documents/UIInfo2.png -------------------------------------------------------------------------------- /RenderDocPlugin/RenderDocPlugin.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion" : 1, 3 | 4 | "FriendlyName" : "RenderDoc Plugin", 5 | "Version" : 2, 6 | "VersionName" : "0.2.0 for UE4.10", 7 | "CreatedBy" : "Temaran", 8 | "CreatedByURL" : "https://github.com/Temaran", 9 | "EngineVersion" : 1579795, 10 | "Description" : "RenderDoc graphics debugger/profiler integration.", 11 | "Category" : "Debugging.Rendering", 12 | "EnabledByDefault" : false, 13 | 14 | "Modules" : 15 | [ 16 | { 17 | "Name" : "RenderDocPlugin", 18 | "Type" : "Developer", 19 | "LoadingPhase" : "PostConfigInit", 20 | "WhitelistPlatforms": [ "Win32", "Win64" ] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /RenderDocPlugin/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/RenderDocPlugin/Resources/Icon128.png -------------------------------------------------------------------------------- /RenderDocPlugin/Resources/Icon20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/RenderDocPlugin/Resources/Icon20.png -------------------------------------------------------------------------------- /RenderDocPlugin/Resources/Icon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/RenderDocPlugin/Resources/Icon40.png -------------------------------------------------------------------------------- /RenderDocPlugin/Resources/SettingsIcon20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/RenderDocPlugin/Resources/SettingsIcon20.png -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocAPI/renderdoc_app.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2016 Baldur Karlsson 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | ////////////////////////////////////////////////////////////////////////////////////////////////// 28 | // 29 | // Documentation for the API is available at https://renderdoc.org/docs/in_application_api.html 30 | // 31 | 32 | #if !defined(RENDERDOC_NO_STDINT) 33 | #include 34 | #endif 35 | 36 | #if defined(WIN32) 37 | #define RENDERDOC_CC __cdecl 38 | #elif defined(__linux__) 39 | #define RENDERDOC_CC 40 | #elif defined(__APPLE__) 41 | #define RENDERDOC_CC 42 | #else 43 | #error "Unknown platform" 44 | #endif 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | ////////////////////////////////////////////////////////////////////////////////////////////////// 51 | // Constants not used directly in below API 52 | 53 | // This is a GUID/magic value used for when applications pass a path where shader debug 54 | // information can be found to match up with a stripped shader. 55 | // the define can be used like so: const GUID RENDERDOC_ShaderDebugMagicValue = 56 | // RENDERDOC_ShaderDebugMagicValue_value 57 | #define RENDERDOC_ShaderDebugMagicValue_struct \ 58 | { \ 59 | 0xeab25520, 0x6670, 0x4865, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \ 60 | } 61 | 62 | // as an alternative when you want a byte array (assuming x86 endianness): 63 | #define RENDERDOC_ShaderDebugMagicValue_bytearray \ 64 | { \ 65 | 0x20, 0x55, 0xb2, 0xea, 0x70, 0x66, 0x65, 0x48, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \ 66 | } 67 | 68 | // truncated version when only a uint64_t is available (e.g. Vulkan tags): 69 | #define RENDERDOC_ShaderDebugMagicValue_truncated 0x48656670eab25520ULL 70 | 71 | ////////////////////////////////////////////////////////////////////////////////////////////////// 72 | // RenderDoc capture options 73 | // 74 | 75 | typedef enum { 76 | // Allow the application to enable vsync 77 | // 78 | // Default - enabled 79 | // 80 | // 1 - The application can enable or disable vsync at will 81 | // 0 - vsync is force disabled 82 | eRENDERDOC_Option_AllowVSync = 0, 83 | 84 | // Allow the application to enable fullscreen 85 | // 86 | // Default - enabled 87 | // 88 | // 1 - The application can enable or disable fullscreen at will 89 | // 0 - fullscreen is force disabled 90 | eRENDERDOC_Option_AllowFullscreen = 1, 91 | 92 | // Record API debugging events and messages 93 | // 94 | // Default - disabled 95 | // 96 | // 1 - Enable built-in API debugging features and records the results into 97 | // the capture logfile, which is matched up with events on replay 98 | // 0 - no API debugging is forcibly enabled 99 | eRENDERDOC_Option_APIValidation = 2, 100 | eRENDERDOC_Option_DebugDeviceMode = 2, // deprecated name of this enum 101 | 102 | // Capture CPU callstacks for API events 103 | // 104 | // Default - disabled 105 | // 106 | // 1 - Enables capturing of callstacks 107 | // 0 - no callstacks are captured 108 | eRENDERDOC_Option_CaptureCallstacks = 3, 109 | 110 | // When capturing CPU callstacks, only capture them from drawcalls. 111 | // This option does nothing without the above option being enabled 112 | // 113 | // Default - disabled 114 | // 115 | // 1 - Only captures callstacks for drawcall type API events. 116 | // Ignored if CaptureCallstacks is disabled 117 | // 0 - Callstacks, if enabled, are captured for every event. 118 | eRENDERDOC_Option_CaptureCallstacksOnlyDraws = 4, 119 | 120 | // Specify a delay in seconds to wait for a debugger to attach, after 121 | // creating or injecting into a process, before continuing to allow it to run. 122 | // 123 | // 0 indicates no delay, and the process will run immediately after injection 124 | // 125 | // Default - 0 seconds 126 | // 127 | eRENDERDOC_Option_DelayForDebugger = 5, 128 | 129 | // Verify any writes to mapped buffers, by checking the memory after the 130 | // bounds of the returned pointer to detect any modification. 131 | // 132 | // Default - disabled 133 | // 134 | // 1 - Verify any writes to mapped buffers 135 | // 0 - No verification is performed, and overwriting bounds may cause 136 | // crashes or corruption in RenderDoc 137 | eRENDERDOC_Option_VerifyMapWrites = 6, 138 | 139 | // Hooks any system API calls that create child processes, and injects 140 | // RenderDoc into them recursively with the same options. 141 | // 142 | // Default - disabled 143 | // 144 | // 1 - Hooks into spawned child processes 145 | // 0 - Child processes are not hooked by RenderDoc 146 | eRENDERDOC_Option_HookIntoChildren = 7, 147 | 148 | // By default RenderDoc only includes resources in the final logfile necessary 149 | // for that frame, this allows you to override that behaviour. 150 | // 151 | // Default - disabled 152 | // 153 | // 1 - all live resources at the time of capture are included in the log 154 | // and available for inspection 155 | // 0 - only the resources referenced by the captured frame are included 156 | eRENDERDOC_Option_RefAllResources = 8, 157 | 158 | // By default RenderDoc skips saving initial states for resources where the 159 | // previous contents don't appear to be used, assuming that writes before 160 | // reads indicate previous contents aren't used. 161 | // 162 | // Default - disabled 163 | // 164 | // 1 - initial contents at the start of each captured frame are saved, even if 165 | // they are later overwritten or cleared before being used. 166 | // 0 - unless a read is detected, initial contents will not be saved and will 167 | // appear as black or empty data. 168 | eRENDERDOC_Option_SaveAllInitials = 9, 169 | 170 | // In APIs that allow for the recording of command lists to be replayed later, 171 | // RenderDoc may choose to not capture command lists before a frame capture is 172 | // triggered, to reduce overheads. This means any command lists recorded once 173 | // and replayed many times will not be available and may cause a failure to 174 | // capture. 175 | // 176 | // Note this is only true for APIs where multithreading is difficult or 177 | // discouraged. Newer APIs like Vulkan and D3D12 will ignore this option 178 | // and always capture all command lists since the API is heavily oriented 179 | // around it and the overheads have been reduced by API design. 180 | // 181 | // 1 - All command lists are captured from the start of the application 182 | // 0 - Command lists are only captured if their recording begins during 183 | // the period when a frame capture is in progress. 184 | eRENDERDOC_Option_CaptureAllCmdLists = 10, 185 | 186 | // Mute API debugging output when the API validation mode option is enabled 187 | // 188 | // Default - enabled 189 | // 190 | // 1 - Mute any API debug messages from being displayed or passed through 191 | // 0 - API debugging is displayed as normal 192 | eRENDERDOC_Option_DebugOutputMute = 11, 193 | 194 | } RENDERDOC_CaptureOption; 195 | 196 | // Sets an option that controls how RenderDoc behaves on capture. 197 | // 198 | // Returns 1 if the option and value are valid 199 | // Returns 0 if either is invalid and the option is unchanged 200 | typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionU32)(RENDERDOC_CaptureOption opt, uint32_t val); 201 | typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionF32)(RENDERDOC_CaptureOption opt, float val); 202 | 203 | // Gets the current value of an option as a uint32_t 204 | // 205 | // If the option is invalid, 0xffffffff is returned 206 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionU32)(RENDERDOC_CaptureOption opt); 207 | 208 | // Gets the current value of an option as a float 209 | // 210 | // If the option is invalid, -FLT_MAX is returned 211 | typedef float(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionF32)(RENDERDOC_CaptureOption opt); 212 | 213 | typedef enum { 214 | // '0' - '9' matches ASCII values 215 | eRENDERDOC_Key_0 = 0x30, 216 | eRENDERDOC_Key_1 = 0x31, 217 | eRENDERDOC_Key_2 = 0x32, 218 | eRENDERDOC_Key_3 = 0x33, 219 | eRENDERDOC_Key_4 = 0x34, 220 | eRENDERDOC_Key_5 = 0x35, 221 | eRENDERDOC_Key_6 = 0x36, 222 | eRENDERDOC_Key_7 = 0x37, 223 | eRENDERDOC_Key_8 = 0x38, 224 | eRENDERDOC_Key_9 = 0x39, 225 | 226 | // 'A' - 'Z' matches ASCII values 227 | eRENDERDOC_Key_A = 0x41, 228 | eRENDERDOC_Key_B = 0x42, 229 | eRENDERDOC_Key_C = 0x43, 230 | eRENDERDOC_Key_D = 0x44, 231 | eRENDERDOC_Key_E = 0x45, 232 | eRENDERDOC_Key_F = 0x46, 233 | eRENDERDOC_Key_G = 0x47, 234 | eRENDERDOC_Key_H = 0x48, 235 | eRENDERDOC_Key_I = 0x49, 236 | eRENDERDOC_Key_J = 0x4A, 237 | eRENDERDOC_Key_K = 0x4B, 238 | eRENDERDOC_Key_L = 0x4C, 239 | eRENDERDOC_Key_M = 0x4D, 240 | eRENDERDOC_Key_N = 0x4E, 241 | eRENDERDOC_Key_O = 0x4F, 242 | eRENDERDOC_Key_P = 0x50, 243 | eRENDERDOC_Key_Q = 0x51, 244 | eRENDERDOC_Key_R = 0x52, 245 | eRENDERDOC_Key_S = 0x53, 246 | eRENDERDOC_Key_T = 0x54, 247 | eRENDERDOC_Key_U = 0x55, 248 | eRENDERDOC_Key_V = 0x56, 249 | eRENDERDOC_Key_W = 0x57, 250 | eRENDERDOC_Key_X = 0x58, 251 | eRENDERDOC_Key_Y = 0x59, 252 | eRENDERDOC_Key_Z = 0x5A, 253 | 254 | // leave the rest of the ASCII range free 255 | // in case we want to use it later 256 | eRENDERDOC_Key_NonPrintable = 0x100, 257 | 258 | eRENDERDOC_Key_Divide, 259 | eRENDERDOC_Key_Multiply, 260 | eRENDERDOC_Key_Subtract, 261 | eRENDERDOC_Key_Plus, 262 | 263 | eRENDERDOC_Key_F1, 264 | eRENDERDOC_Key_F2, 265 | eRENDERDOC_Key_F3, 266 | eRENDERDOC_Key_F4, 267 | eRENDERDOC_Key_F5, 268 | eRENDERDOC_Key_F6, 269 | eRENDERDOC_Key_F7, 270 | eRENDERDOC_Key_F8, 271 | eRENDERDOC_Key_F9, 272 | eRENDERDOC_Key_F10, 273 | eRENDERDOC_Key_F11, 274 | eRENDERDOC_Key_F12, 275 | 276 | eRENDERDOC_Key_Home, 277 | eRENDERDOC_Key_End, 278 | eRENDERDOC_Key_Insert, 279 | eRENDERDOC_Key_Delete, 280 | eRENDERDOC_Key_PageUp, 281 | eRENDERDOC_Key_PageDn, 282 | 283 | eRENDERDOC_Key_Backspace, 284 | eRENDERDOC_Key_Tab, 285 | eRENDERDOC_Key_PrtScrn, 286 | eRENDERDOC_Key_Pause, 287 | 288 | eRENDERDOC_Key_Max, 289 | } RENDERDOC_InputButton; 290 | 291 | // Sets which key or keys can be used to toggle focus between multiple windows 292 | // 293 | // If keys is NULL or num is 0, toggle keys will be disabled 294 | typedef void(RENDERDOC_CC *pRENDERDOC_SetFocusToggleKeys)(RENDERDOC_InputButton *keys, int num); 295 | 296 | // Sets which key or keys can be used to capture the next frame 297 | // 298 | // If keys is NULL or num is 0, captures keys will be disabled 299 | typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureKeys)(RENDERDOC_InputButton *keys, int num); 300 | 301 | typedef enum { 302 | // This single bit controls whether the overlay is enabled or disabled globally 303 | eRENDERDOC_Overlay_Enabled = 0x1, 304 | 305 | // Show the average framerate over several seconds as well as min/max 306 | eRENDERDOC_Overlay_FrameRate = 0x2, 307 | 308 | // Show the current frame number 309 | eRENDERDOC_Overlay_FrameNumber = 0x4, 310 | 311 | // Show a list of recent captures, and how many captures have been made 312 | eRENDERDOC_Overlay_CaptureList = 0x8, 313 | 314 | // Default values for the overlay mask 315 | eRENDERDOC_Overlay_Default = (eRENDERDOC_Overlay_Enabled | eRENDERDOC_Overlay_FrameRate | 316 | eRENDERDOC_Overlay_FrameNumber | eRENDERDOC_Overlay_CaptureList), 317 | 318 | // Enable all bits 319 | eRENDERDOC_Overlay_All = ~0U, 320 | 321 | // Disable all bits 322 | eRENDERDOC_Overlay_None = 0, 323 | } RENDERDOC_OverlayBits; 324 | 325 | // returns the overlay bits that have been set 326 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetOverlayBits)(); 327 | // sets the overlay bits with an and & or mask 328 | typedef void(RENDERDOC_CC *pRENDERDOC_MaskOverlayBits)(uint32_t And, uint32_t Or); 329 | 330 | // this function will attempt to shut down RenderDoc. 331 | // 332 | // Note: that this will only work correctly if done immediately after 333 | // the dll is loaded, before any API work happens. RenderDoc will remove its 334 | // injected hooks and shut down. Behaviour is undefined if this is called 335 | // after any API functions have been called. 336 | typedef void(RENDERDOC_CC *pRENDERDOC_Shutdown)(); 337 | 338 | // This function will unload RenderDoc's crash handler. 339 | // 340 | // If you use your own crash handler and don't want RenderDoc's handler to 341 | // intercede, you can call this function to unload it and any unhandled 342 | // exceptions will pass to the next handler. 343 | typedef void(RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)(); 344 | 345 | // Sets the logfile path template 346 | // 347 | // logfile is a UTF-8 string that gives a template for how captures will be named 348 | // and where they will be saved. 349 | // 350 | // Any extension is stripped off the path, and captures are saved in the directory 351 | // specified, and named with the filename and the frame number appended. If the 352 | // directory does not exist it will be created, including any parent directories. 353 | // 354 | // If pathtemplate is NULL, the template will remain unchanged 355 | // 356 | // Example: 357 | // 358 | // SetLogFilePathTemplate("my_captures/example"); 359 | // 360 | // Capture #1 -> my_captures/example_frame123.rdc 361 | // Capture #2 -> my_captures/example_frame456.rdc 362 | typedef void(RENDERDOC_CC *pRENDERDOC_SetLogFilePathTemplate)(const char *pathtemplate); 363 | 364 | // returns the current logfile template, see SetLogFileTemplate above, as a UTF-8 string 365 | typedef const char *(RENDERDOC_CC *pRENDERDOC_GetLogFilePathTemplate)(); 366 | 367 | // returns the number of captures that have been made 368 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetNumCaptures)(); 369 | 370 | // This function returns the details of a capture, by index. New captures are added 371 | // to the end of the list. 372 | // 373 | // logfile will be filled with the absolute path to the capture file, as a UTF-8 string 374 | // pathlength will be written with the length in bytes of the logfile string 375 | // timestamp will be written with the time of the capture, in seconds since the Unix epoch 376 | // 377 | // Any of the parameters can be NULL and they'll be skipped. 378 | // 379 | // The function will return 1 if the capture index is valid, or 0 if the index is invalid 380 | // If the index is invalid, the values will be unchanged 381 | // 382 | // Note: when captures are deleted in the UI they will remain in this list, so the 383 | // logfile path may not exist anymore. 384 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *logfile, 385 | uint32_t *pathlength, uint64_t *timestamp); 386 | 387 | // returns 1 if the RenderDoc UI is connected to this application, 0 otherwise 388 | // This was renamed to IsTargetControlConnected in API 1.1.1, the old typedef is kept here for 389 | // backwards compatibility with old code, it is castable either way since it's ABI compatible 390 | // as the same function pointer type. 391 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsRemoteAccessConnected)(); 392 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsTargetControlConnected)(); 393 | 394 | // This function will launch the Replay UI associated with the RenderDoc library injected 395 | // into the running application. 396 | // 397 | // if connectTargetControl is 1, the Replay UI will be launched with a command line parameter 398 | // to connect to this application 399 | // cmdline is the rest of the command line, as a UTF-8 string. E.g. a captures to open 400 | // if cmdline is NULL, the command line will be empty. 401 | // 402 | // returns the PID of the replay UI if successful, 0 if not successful. 403 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_LaunchReplayUI)(uint32_t connectTargetControl, 404 | const char *cmdline); 405 | 406 | // RenderDoc can return a higher version than requested if it's backwards compatible, 407 | // this function returns the actual version returned. If a parameter is NULL, it will be 408 | // ignored and the others will be filled out. 409 | typedef void(RENDERDOC_CC *pRENDERDOC_GetAPIVersion)(int *major, int *minor, int *patch); 410 | 411 | ////////////////////////////////////////////////////////////////////////// 412 | // Capturing functions 413 | // 414 | 415 | // A device pointer is a pointer to the API's root handle. 416 | // 417 | // This would be an ID3D11Device, HGLRC/GLXContext, ID3D12Device, etc 418 | typedef void *RENDERDOC_DevicePointer; 419 | 420 | // A window handle is the OS's native window handle 421 | // 422 | // This would be an HWND, GLXDrawable, etc 423 | typedef void *RENDERDOC_WindowHandle; 424 | 425 | // This sets the RenderDoc in-app overlay in the API/window pair as 'active' and it will 426 | // respond to keypresses. Neither parameter can be NULL 427 | typedef void(RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(RENDERDOC_DevicePointer device, 428 | RENDERDOC_WindowHandle wndHandle); 429 | 430 | // capture the next frame on whichever window and API is currently considered active 431 | typedef void(RENDERDOC_CC *pRENDERDOC_TriggerCapture)(); 432 | 433 | // capture the next N frames on whichever window and API is currently considered active 434 | typedef void(RENDERDOC_CC *pRENDERDOC_TriggerMultiFrameCapture)(uint32_t numFrames); 435 | 436 | // When choosing either a device pointer or a window handle to capture, you can pass NULL. 437 | // Passing NULL specifies a 'wildcard' match against anything. This allows you to specify 438 | // any API rendering to a specific window, or a specific API instance rendering to any window, 439 | // or in the simplest case of one window and one API, you can just pass NULL for both. 440 | // 441 | // In either case, if there are two or more possible matching (device,window) pairs it 442 | // is undefined which one will be captured. 443 | // 444 | // Note: for headless rendering you can pass NULL for the window handle and either specify 445 | // a device pointer or leave it NULL as above. 446 | 447 | // Immediately starts capturing API calls on the specified device pointer and window handle. 448 | // 449 | // If there is no matching thing to capture (e.g. no supported API has been initialised), 450 | // this will do nothing. 451 | // 452 | // The results are undefined (including crashes) if two captures are started overlapping, 453 | // even on separate devices and/oror windows. 454 | typedef void(RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(RENDERDOC_DevicePointer device, 455 | RENDERDOC_WindowHandle wndHandle); 456 | 457 | // Returns whether or not a frame capture is currently ongoing anywhere. 458 | // 459 | // This will return 1 if a capture is ongoing, and 0 if there is no capture running 460 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsFrameCapturing)(); 461 | 462 | // Ends capturing immediately. 463 | // 464 | // This will return 1 if the capture succeeded, and 0 if there was an error capturing. 465 | typedef uint32_t(RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(RENDERDOC_DevicePointer device, 466 | RENDERDOC_WindowHandle wndHandle); 467 | 468 | ////////////////////////////////////////////////////////////////////////////////////////////////// 469 | // RenderDoc API versions 470 | // 471 | 472 | // RenderDoc uses semantic versioning (http://semver.org/). 473 | // 474 | // MAJOR version is incremented when incompatible API changes happen. 475 | // MINOR version is incremented when functionality is added in a backwards-compatible manner. 476 | // PATCH version is incremented when backwards-compatible bug fixes happen. 477 | // 478 | // Note that this means the API returned can be higher than the one you might have requested. 479 | // e.g. if you are running against a newer RenderDoc that supports 1.0.1, it will be returned 480 | // instead of 1.0.0. You can check this with the GetAPIVersion entry point 481 | typedef enum { 482 | eRENDERDOC_API_Version_1_0_0 = 10000, // RENDERDOC_API_1_0_0 = 1 00 00 483 | eRENDERDOC_API_Version_1_0_1 = 10001, // RENDERDOC_API_1_0_1 = 1 00 01 484 | eRENDERDOC_API_Version_1_0_2 = 10002, // RENDERDOC_API_1_0_2 = 1 00 02 485 | eRENDERDOC_API_Version_1_1_0 = 10100, // RENDERDOC_API_1_1_0 = 1 01 00 486 | eRENDERDOC_API_Version_1_1_1 = 10101, // RENDERDOC_API_1_1_1 = 1 01 01 487 | } RENDERDOC_Version; 488 | 489 | // API version changelog: 490 | // 491 | // 1.0.0 - initial release 492 | // 1.0.1 - Bugfix: IsFrameCapturing() was returning false for captures that were triggered 493 | // by keypress or TriggerCapture, instead of Start/EndFrameCapture. 494 | // 1.0.2 - Refactor: Renamed eRENDERDOC_Option_DebugDeviceMode to eRENDERDOC_Option_APIValidation 495 | // 1.1.0 - Add feature: TriggerMultiFrameCapture(). Backwards compatible with 1.0.x since the new 496 | // function pointer is added to the end of the struct, the original layout is identical 497 | // 1.1.1 - Refactor: Renamed remote access to target control (to better disambiguate from remote 498 | // replay/remote server concept in replay UI) 499 | 500 | // eRENDERDOC_API_Version_1_1_0 501 | typedef struct 502 | { 503 | pRENDERDOC_GetAPIVersion GetAPIVersion; 504 | 505 | pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32; 506 | pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32; 507 | 508 | pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32; 509 | pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32; 510 | 511 | pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys; 512 | pRENDERDOC_SetCaptureKeys SetCaptureKeys; 513 | 514 | pRENDERDOC_GetOverlayBits GetOverlayBits; 515 | pRENDERDOC_MaskOverlayBits MaskOverlayBits; 516 | 517 | pRENDERDOC_Shutdown Shutdown; 518 | pRENDERDOC_UnloadCrashHandler UnloadCrashHandler; 519 | 520 | pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate; 521 | pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate; 522 | 523 | pRENDERDOC_GetNumCaptures GetNumCaptures; 524 | pRENDERDOC_GetCapture GetCapture; 525 | 526 | pRENDERDOC_TriggerCapture TriggerCapture; 527 | 528 | pRENDERDOC_IsRemoteAccessConnected IsRemoteAccessConnected; 529 | pRENDERDOC_LaunchReplayUI LaunchReplayUI; 530 | 531 | pRENDERDOC_SetActiveWindow SetActiveWindow; 532 | 533 | pRENDERDOC_StartFrameCapture StartFrameCapture; 534 | pRENDERDOC_IsFrameCapturing IsFrameCapturing; 535 | pRENDERDOC_EndFrameCapture EndFrameCapture; 536 | 537 | pRENDERDOC_TriggerMultiFrameCapture TriggerMultiFrameCapture; 538 | } RENDERDOC_API_1_1_0; 539 | 540 | typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_0; 541 | typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_1; 542 | typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_2; 543 | 544 | // although this structure is identical to RENDERDOC_API_1_1_0, the member 545 | // IsRemoteAccessConnected was renamed to IsTargetControlConnected. So that 546 | // old code can still compile with a new header, we must declare a new struct 547 | // type. It can be casted back and forth though, so we will still return a 548 | // pointer to this type for all previous API versions - the above struct is 549 | // purely legacy for compilation compatibility 550 | 551 | // eRENDERDOC_API_Version_1_1_1 552 | typedef struct 553 | { 554 | pRENDERDOC_GetAPIVersion GetAPIVersion; 555 | 556 | pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32; 557 | pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32; 558 | 559 | pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32; 560 | pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32; 561 | 562 | pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys; 563 | pRENDERDOC_SetCaptureKeys SetCaptureKeys; 564 | 565 | pRENDERDOC_GetOverlayBits GetOverlayBits; 566 | pRENDERDOC_MaskOverlayBits MaskOverlayBits; 567 | 568 | pRENDERDOC_Shutdown Shutdown; 569 | pRENDERDOC_UnloadCrashHandler UnloadCrashHandler; 570 | 571 | pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate; 572 | pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate; 573 | 574 | pRENDERDOC_GetNumCaptures GetNumCaptures; 575 | pRENDERDOC_GetCapture GetCapture; 576 | 577 | pRENDERDOC_TriggerCapture TriggerCapture; 578 | 579 | pRENDERDOC_IsTargetControlConnected IsTargetControlConnected; 580 | pRENDERDOC_LaunchReplayUI LaunchReplayUI; 581 | 582 | pRENDERDOC_SetActiveWindow SetActiveWindow; 583 | 584 | pRENDERDOC_StartFrameCapture StartFrameCapture; 585 | pRENDERDOC_IsFrameCapturing IsFrameCapturing; 586 | pRENDERDOC_EndFrameCapture EndFrameCapture; 587 | 588 | pRENDERDOC_TriggerMultiFrameCapture TriggerMultiFrameCapture; 589 | } RENDERDOC_API_1_1_1; 590 | 591 | ////////////////////////////////////////////////////////////////////////////////////////////////// 592 | // RenderDoc API entry point 593 | // 594 | // This entry point can be obtained via GetProcAddress/dlsym if RenderDoc is available. 595 | // 596 | // The name is the same as the typedef - "RENDERDOC_GetAPI" 597 | // 598 | // This function is not thread safe, and should not be called on multiple threads at once. 599 | // Ideally, call this once as early as possible in your application's startup, before doing 600 | // any API work, since some configuration functionality etc has to be done also before 601 | // initialising any APIs. 602 | // 603 | // Parameters: 604 | // version is a single value from the RENDERDOC_Version above. 605 | // 606 | // outAPIPointers will be filled out with a pointer to the corresponding struct of function 607 | // pointers. 608 | // 609 | // Returns: 610 | // 1 - if the outAPIPointers has been filled with a pointer to the API struct requested 611 | // 0 - if the requested version is not supported or the arguments are invalid. 612 | // 613 | typedef int(RENDERDOC_CC *pRENDERDOC_GetAPI)(RENDERDOC_Version version, void **outAPIPointers); 614 | 615 | #ifdef __cplusplus 616 | } // extern "C" 617 | #endif 618 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginAboutWindow.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #if WITH_EDITOR 26 | 27 | #include "RenderDocPluginPrivatePCH.h" 28 | #include "RenderDocPluginAboutWindow.h" 29 | #include "Editor.h" 30 | #include "UnrealClient.h" 31 | #include "RenderDocPluginStyle.h" 32 | 33 | #define LOCTEXT_NAMESPACE "RenderDocPluginAboutWindow" 34 | 35 | void SRenderDocPluginAboutWindow::Construct(const FArguments& InArgs) 36 | { 37 | FString Message = FString( 38 | "Hello and thank you for trying out the RenderDoc plugin!\n\n" \ 39 | "To capture a frame, press the green capture button on the top\n" \ 40 | "right of any viewport. If you cannot see the button, you might\n" \ 41 | "have to adjust your viewport width until all buttons fit the screen.\n" \ 42 | "You can also use the assigned hotkey (default is Alt+F12).\n\n" \ 43 | "For best performance I recommend using the experimental\n" \ 44 | "AutoCompileShaders branch in the repository and downloading\n" \ 45 | "my fork of the engine so you are able to include shader meta\n" \ 46 | "data in your compiled shaders.This will make it easier to step\n" \ 47 | "through your shader code in the UI as you will be able to see \n" \ 48 | "your variable names etc.\n\n" \ 49 | "If you have any questions or suggestions I'll try to answer them \n" \ 50 | "as best I can at:\ntemaran(at) gmail(dot) com.\n\n" \ 51 | "You can find my fork and updates to the plugins at these github repos:\n" \ 52 | "https://github.com/Temaran/UE4RenderDocPlugin\n" \ 53 | "https://github.com/Temaran/UnrealEngine (RenderDocPluginChanges)"); 54 | 55 | SWindow::Construct(SWindow::FArguments() 56 | .SupportsMaximize(false) 57 | .SupportsMinimize(false) 58 | .IsPopupWindow(false) 59 | .CreateTitleBar(false) 60 | .SizingRule(ESizingRule::FixedSize) 61 | .SupportsTransparency(EWindowTransparency::None) 62 | .InitialOpacity(1.0f) 63 | .FocusWhenFirstShown(true) 64 | .bDragAnywhere(false) 65 | .ActivateWhenFirstShown(true) 66 | .ClientSize(FVector2D(400, 400)) 67 | .ScreenPosition(FVector2D((float)(GEditor->GetActiveViewport()->GetSizeXY().X) / 2.0, 68 | (float)(GEditor->GetActiveViewport()->GetSizeXY().Y) / 2.0)) 69 | [ 70 | SNew(SVerticalBox) 71 | + SVerticalBox::Slot() 72 | .FillHeight(0.9f) 73 | .Padding(5) 74 | [ 75 | SNew(STextBlock) 76 | .Text(FText::FromString(Message)) 77 | ] 78 | 79 | + SVerticalBox::Slot() 80 | .FillHeight(0.1f) 81 | [ 82 | SNew(SButton) 83 | .VAlign(VAlign_Center) 84 | .OnClicked(this, &SRenderDocPluginAboutWindow::Close) 85 | .Text(LOCTEXT("OkButton", "Ok")) 86 | ] 87 | ]); 88 | 89 | bIsTopmostWindow = true; 90 | FlashWindow(); 91 | } 92 | 93 | FReply SRenderDocPluginAboutWindow::Close() 94 | { 95 | RequestDestroyWindow(); 96 | return FReply::Handled(); 97 | } 98 | 99 | #undef LOCTEXT_NAMESPACE 100 | 101 | #endif//WITH_EDITOR 102 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginAboutWindow.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #if WITH_EDITOR 28 | 29 | #include "SlateBasics.h" 30 | 31 | class SRenderDocPluginAboutWindow : public SWindow 32 | { 33 | public: 34 | SLATE_BEGIN_ARGS(SRenderDocPluginAboutWindow) 35 | { 36 | } 37 | SLATE_END_ARGS() 38 | 39 | SRenderDocPluginAboutWindow() {} 40 | 41 | /** Widget constructor */ 42 | void Construct(const FArguments& Args); 43 | 44 | private: 45 | FReply Close(); 46 | }; 47 | 48 | #endif//WITH_EDITOR 49 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginCommands.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #if WITH_EDITOR 26 | 27 | #include "RenderDocPluginPrivatePCH.h" 28 | #include "RenderDocPluginCommands.h" 29 | 30 | #define LOCTEXT_NAMESPACE "RenderDocPluginSettingsEditor" 31 | 32 | PRAGMA_DISABLE_OPTIMIZATION 33 | void FRenderDocPluginCommands::RegisterCommands() 34 | { 35 | UI_COMMAND( 36 | CaptureFrame, 37 | "Capture Frame", "Captures the next frame and launches RenderDoc.", 38 | EUserInterfaceActionType::Button, 39 | FInputGesture(EKeys::F12, EModifierKey::Alt) 40 | ); 41 | 42 | UI_COMMAND( 43 | Settings_CaptureAllActivity, 44 | "Capture All Activity", 45 | "If enabled, capture all rendering activity during the next engine update tick; if disabled, only the rendering activity of the active viewport will be captured.", 46 | EUserInterfaceActionType::ToggleButton, 47 | FInputGesture() 48 | ); 49 | 50 | UI_COMMAND( 51 | Settings_CaptureCallstack, 52 | "Capture Callstack", 53 | "Save the call stack for every draw event in addition to the event itself. This is useful when you need additional information to solve your particular problem.", 54 | EUserInterfaceActionType::ToggleButton, 55 | FInputGesture() 56 | ); 57 | 58 | UI_COMMAND( 59 | Settings_CaptureAllResources, 60 | "Capture All Resources", 61 | "Capture all resources, including those that are not referenced by the current frame.", 62 | EUserInterfaceActionType::ToggleButton, 63 | FInputGesture() 64 | ); 65 | 66 | UI_COMMAND( 67 | Settings_SaveAllInitialState, 68 | "Save All Initial State", 69 | "Save the initial status of all resources, even if we think that they will be overwritten in this frame.", 70 | EUserInterfaceActionType::ToggleButton, 71 | FInputGesture() 72 | ); 73 | } 74 | PRAGMA_ENABLE_OPTIMIZATION 75 | 76 | #undef LOCTEXT_NAMESPACE//"RenderDocPluginSettingsEditor" 77 | 78 | #endif//WITH_EDITOR 79 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginCommands.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #if WITH_EDITOR 28 | 29 | #include "SlateBasics.h" 30 | #include "EditorStyle.h" 31 | #include "RenderDocPluginStyle.h" 32 | 33 | class FRenderDocPluginCommands : public TCommands 34 | { 35 | public: 36 | FRenderDocPluginCommands() 37 | : TCommands(TEXT("RenderDocPlugin"), NSLOCTEXT("Contexts", "RenderDocPlugin", "RenderDoc Plugin"), NAME_None, FRenderDocPluginStyle::Get()->GetStyleSetName()) 38 | { 39 | } 40 | 41 | virtual void RegisterCommands() override; 42 | 43 | TSharedPtr CaptureFrame; 44 | TSharedPtr Settings_CaptureAllActivity; 45 | TSharedPtr Settings_CaptureCallstack; 46 | TSharedPtr Settings_CaptureAllResources; 47 | TSharedPtr Settings_SaveAllInitialState; 48 | }; 49 | 50 | #endif//WITH_EDITOR 51 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginLoader.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2016 Fredrik Lindh 5 | * Marcos Slomp 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | ******************************************************************************/ 25 | 26 | #include "RenderDocPluginPrivatePCH.h" 27 | #include "RenderDocPluginLoader.h" 28 | 29 | #include "WindowsHWrapper.h" 30 | 31 | #include "RenderDocPluginModule.h" 32 | 33 | #include "Internationalization.h" 34 | 35 | #include "Developer/DesktopPlatform/public/DesktopPlatformModule.h" 36 | 37 | #include "AllowWindowsPlatformTypes.h" 38 | #include "HideWindowsPlatformTypes.h" 39 | 40 | #define LOCTEXT_NAMESPACE "RenderDocLoaderPluginNamespace" 41 | 42 | static void* LoadAndCheckRenderDocLibrary(FRenderDocPluginLoader::RENDERDOC_API_CONTEXT*& RenderDocAPI, const FString& RenderdocPath) 43 | { 44 | check(nullptr == RenderDocAPI); 45 | 46 | if (RenderdocPath.IsEmpty()) 47 | return(nullptr); 48 | 49 | FString PathToRenderDocDLL = FPaths::Combine(*RenderdocPath, *FString("renderdoc.dll")); 50 | if (!FPaths::FileExists(PathToRenderDocDLL)) 51 | { 52 | UE_LOG(RenderDocPlugin, Warning, TEXT("unable to locate RenderDoc library at: %s"), *PathToRenderDocDLL); 53 | return(nullptr); 54 | } 55 | 56 | UE_LOG(RenderDocPlugin, Log, TEXT("a RenderDoc library has been located at: %s"), *PathToRenderDocDLL); 57 | 58 | void* RenderDocDLL = FPlatformProcess::GetDllHandle(*PathToRenderDocDLL); 59 | if (!RenderDocDLL) 60 | { 61 | UE_LOG(RenderDocPlugin, Warning, TEXT("unable to dynamically load RenderDoc library")); 62 | return(nullptr); 63 | } 64 | 65 | pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)FPlatformProcess::GetDllExport(RenderDocDLL, TEXT("RENDERDOC_GetAPI")); 66 | if (!RENDERDOC_GetAPI) 67 | { 68 | UE_LOG(RenderDocPlugin, Warning, TEXT("unable to obtain 'RENDERDOC_GetAPI' function from 'renderdoc.dll'. You are likely using an incompatible version of RenderDoc."), *PathToRenderDocDLL); 69 | FPlatformProcess::FreeDllHandle(RenderDocDLL); 70 | return(nullptr); 71 | } 72 | 73 | // Version checking and reporting 74 | if (0 == RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_0_0, (void**)&RenderDocAPI)) 75 | { 76 | UE_LOG(RenderDocPlugin, Warning, TEXT("unable to initialize RenderDoc library due to API incompatibility (plugin requires eRENDERDOC_API_Version_1_0_0)."), *PathToRenderDocDLL); 77 | FPlatformProcess::FreeDllHandle(RenderDocDLL); 78 | return(nullptr); 79 | } 80 | 81 | int major(0), minor(0), patch(0); 82 | RenderDocAPI->GetAPIVersion(&major, &minor, &patch); 83 | UE_LOG(RenderDocPlugin, Log, TEXT("RenderDoc library has been loaded (RenderDoc API v%i.%i.%i)."), major, minor, patch); 84 | 85 | return(RenderDocDLL); 86 | } 87 | 88 | static void UpdateConfigFiles(const FString& RenderdocPath) 89 | { 90 | if (GConfig) 91 | { 92 | GConfig->SetString(TEXT("RenderDoc"), TEXT("BinaryPath"), *RenderdocPath, GGameIni); 93 | GConfig->Flush(false, GGameIni); 94 | } 95 | } 96 | 97 | void FRenderDocPluginLoader::Initialize() 98 | { 99 | if (GUsingNullRHI) 100 | { 101 | // THIS WILL NEVER TRIGGER because of a sort of chicken-and-egg problem: RenderDoc Loader is a PostConfigInit 102 | // plugin, and GUsingNullRHI is only initialized properly between PostConfigInit and PreLoadingScreen phases. 103 | // (nevertheless, keep this comment around for future iterations of UE4) 104 | UE_LOG(RenderDocPlugin, Warning, TEXT("this plugin will not be loaded because a null RHI (Cook Server, perhaps) is being used.")); 105 | return; 106 | } 107 | 108 | // Look for a renderdoc.dll somewhere in the system: 109 | UE_LOG(RenderDocPlugin, Log, TEXT("locating RenderDoc library (renderdoc.dll)...")); 110 | RenderDocDLL = RenderDocAPI = NULL; 111 | 112 | // 1) Check the Game configuration files: 113 | if (GConfig) 114 | { 115 | FString RenderdocPath; 116 | GConfig->GetString(TEXT("RenderDoc"), TEXT("BinaryPath"), RenderdocPath, GGameIni); 117 | RenderDocDLL = LoadAndCheckRenderDocLibrary(RenderDocAPI, RenderdocPath); 118 | } 119 | 120 | // 2) Check for a RenderDoc system installation in the registry: 121 | if (!RenderDocDLL) 122 | { 123 | FString RenderdocPath; 124 | FWindowsPlatformMisc::QueryRegKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Classes\\RenderDoc.RDCCapture.1\\DefaultIcon\\"), TEXT(""), RenderdocPath); 125 | RenderDocDLL = LoadAndCheckRenderDocLibrary(RenderDocAPI, RenderdocPath); 126 | if (RenderDocDLL) 127 | UpdateConfigFiles(RenderdocPath); 128 | } 129 | 130 | // 3) Check for a RenderDoc custom installation by prompting the user: 131 | if (!RenderDocDLL) 132 | { 133 | //Renderdoc does not seem to be installed, but it might be built from source or downloaded by archive, 134 | //so prompt the user to navigate to the main exe file 135 | UE_LOG(RenderDocPlugin, Log, TEXT("RenderDoc library not found; provide a custom installation location...")); 136 | FString RenderdocPath; 137 | // TODO: rework the logic here by improving error checking and reporting 138 | IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); 139 | if (DesktopPlatform) 140 | { 141 | FString Filter = TEXT("Renderdoc executable|renderdocui.exe"); 142 | TArray OutFiles; 143 | if (DesktopPlatform->OpenFileDialog(NULL, TEXT("Locate main Renderdoc executable... You can find the latest builds at https://renderdoc.org/builds"), TEXT(""), TEXT(""), Filter, EFileDialogFlags::None, OutFiles)) 144 | RenderdocPath = OutFiles[0]; 145 | } 146 | RenderdocPath = FPaths::GetPath(RenderdocPath); 147 | RenderDocDLL = LoadAndCheckRenderDocLibrary(RenderDocAPI, RenderdocPath); 148 | if (RenderDocDLL) 149 | UpdateConfigFiles(RenderdocPath); 150 | } 151 | 152 | // 4) All bets are off; aborting... 153 | if (!RenderDocDLL) 154 | { 155 | UE_LOG(RenderDocPlugin, Error, TEXT("unable to initialize the plugin because no RenderDoc libray has been located.")); 156 | return; 157 | } 158 | 159 | UE_LOG(RenderDocPlugin, Log, TEXT("plugin has been loaded successfully.")); 160 | } 161 | 162 | void FRenderDocPluginLoader::Release() 163 | { 164 | if (GUsingNullRHI) 165 | return; 166 | 167 | if (RenderDocDLL) 168 | FPlatformProcess::FreeDllHandle(RenderDocDLL); 169 | 170 | UE_LOG(RenderDocPlugin, Log, TEXT("plugin has been unloaded.")); 171 | } 172 | 173 | #undef LOCTEXT_NAMESPACE 174 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginLoader.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2016 Fredrik Lindh 5 | * Marcos Slomp 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | ******************************************************************************/ 25 | 26 | #pragma once 27 | 28 | #include "RenderDocAPI/renderdoc_app.h" 29 | 30 | class FRenderDocPluginLoader 31 | { 32 | public: 33 | void Initialize(); 34 | void Release(); 35 | 36 | typedef RENDERDOC_API_1_0_0 RENDERDOC_API_CONTEXT; 37 | 38 | private: 39 | friend class FRenderDocPluginModule; 40 | friend class SRenderDocPluginSettingsEditorWindow; 41 | 42 | void* RenderDocDLL; 43 | RENDERDOC_API_CONTEXT* RenderDocAPI; 44 | }; 45 | 46 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginModule.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #include "RenderDocPluginPrivatePCH.h" 26 | #include "RenderDocPluginModule.h" 27 | 28 | #include "WindowsHWrapper.h" 29 | 30 | #include "Internationalization.h" 31 | #include "RendererInterface.h" 32 | 33 | #include "RenderDocPluginNotification.h" 34 | 35 | DEFINE_LOG_CATEGORY(RenderDocPlugin); 36 | 37 | #define LOCTEXT_NAMESPACE "RenderDocPlugin" 38 | 39 | 40 | 41 | /** 42 | * A dummy input device in order to be able to listen and respond to engine tick 43 | * events. The whole rendering activity between two engine ticks can be captured 44 | * including SceneCapture updates, Material Editor previews, Material Thumbnail 45 | * previews, Editor UI (Slate) widget rendering, etc. 46 | */ 47 | class FRenderDocPluginModule::FRenderDocDummyInputDevice : public IInputDevice 48 | { 49 | public: 50 | //FRenderDocDummyInputDevice(const TSharedRef< FGenericApplicationMessageHandler >& MessageHandler) : ThePlugin(NULL) { } 51 | FRenderDocDummyInputDevice() : ThePlugin(NULL) { } 52 | virtual ~FRenderDocDummyInputDevice() { } 53 | 54 | /** Tick the interface (used for controlling full engine frame captures). */ 55 | virtual void Tick(float DeltaTime) override 56 | { 57 | check(ThePlugin); 58 | ThePlugin->Tick(DeltaTime); 59 | } 60 | 61 | /** The remaining interfaces are irrelevant for this dummy input device. */ 62 | virtual void SendControllerEvents() override { } 63 | virtual void SetMessageHandler(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) override { } 64 | virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) override { return(false); } 65 | virtual void SetChannelValue(int32 ControllerId, FForceFeedbackChannelType ChannelType, float Value) override { } 66 | virtual void SetChannelValues(int32 ControllerId, const FForceFeedbackValues &values) override { } 67 | 68 | private: 69 | friend class FRenderDocPluginModule; 70 | FRenderDocPluginModule* ThePlugin; 71 | 72 | }; 73 | 74 | TSharedPtr< class IInputDevice > FRenderDocPluginModule::CreateInputDevice(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) 75 | { 76 | UE_LOG(RenderDocPlugin, Log, TEXT("Creating dummy input device (for intercepting engine ticks)")); 77 | FRenderDocDummyInputDevice* InputDev = new FRenderDocDummyInputDevice(); 78 | InputDev->ThePlugin = this; 79 | return( MakeShareable(InputDev) ); 80 | } 81 | 82 | 83 | 84 | void* GetRenderDocLibrary() 85 | { 86 | void* RenderDocDLL (NULL); 87 | if (GConfig) 88 | { 89 | FString RenderdocPath; 90 | GConfig->GetString(TEXT("RenderDoc"), TEXT("BinaryPath"), RenderdocPath, GGameIni); 91 | FString PathToRenderDocDLL = FPaths::Combine(*RenderdocPath, *FString("renderdoc.dll")); 92 | RenderDocDLL = FPlatformProcess::GetDllHandle(*PathToRenderDocDLL); 93 | } 94 | return(RenderDocDLL); 95 | } 96 | 97 | 98 | 99 | void FRenderDocPluginModule::StartupModule() 100 | { 101 | Loader.Initialize(); 102 | 103 | if (!Loader.RenderDocAPI) 104 | return; 105 | 106 | // Regrettably, GUsingNullRHI is set to true AFTER the PostInitConfig modules 107 | // have been loaded (RenderDoc plugin being one of them). When this code runs 108 | // the following condition will never be true, so it must be tested again in 109 | // the Toolbar initialization code. 110 | if (GUsingNullRHI) 111 | { 112 | UE_LOG(RenderDocPlugin, Warning, TEXT("RenderDoc Plugin will not be loaded because a Null RHI (Cook Server, perhaps) is being used.")); 113 | return; 114 | } 115 | 116 | // Obtain a handle to the RenderDoc DLL that has been loaded by the RenderDoc 117 | // Loader Plugin; no need for error handling here since the Loader would have 118 | // already handled and logged these errors (but check() them just in case...) 119 | RenderDocAPI = Loader.RenderDocAPI; 120 | check(RenderDocAPI); 121 | 122 | IModularFeatures::Get().RegisterModularFeature(GetModularFeatureName(), this); 123 | TickNumber = 0; 124 | 125 | // Setup RenderDoc settings 126 | FString RenderDocCapturePath = FPaths::Combine(*FPaths::GameSavedDir(), *FString("RenderDocCaptures")); 127 | if (!IFileManager::Get().DirectoryExists(*RenderDocCapturePath)) 128 | { 129 | IFileManager::Get().MakeDirectory(*RenderDocCapturePath, true); 130 | } 131 | 132 | FString CapturePath = FPaths::Combine(*RenderDocCapturePath, *FDateTime::Now().ToString()); 133 | CapturePath = FPaths::ConvertRelativePathToFull(CapturePath); 134 | FPaths::NormalizeDirectoryName(CapturePath); 135 | 136 | if (sizeof(TCHAR) == sizeof(char)) 137 | RenderDocAPI->SetLogFilePathTemplate((const char*)*CapturePath); 138 | else 139 | RenderDocAPI->SetLogFilePathTemplate(TCHAR_TO_ANSI(*CapturePath)); 140 | 141 | RenderDocAPI->SetFocusToggleKeys(NULL, 0); 142 | RenderDocAPI->SetCaptureKeys(NULL, 0); 143 | 144 | RenderDocAPI->SetCaptureOptionU32(eRENDERDOC_Option_CaptureCallstacks, RenderDocSettings.bCaptureCallStacks ? 1 : 0); 145 | RenderDocAPI->SetCaptureOptionU32(eRENDERDOC_Option_RefAllResources, RenderDocSettings.bRefAllResources ? 1 : 0); 146 | RenderDocAPI->SetCaptureOptionU32(eRENDERDOC_Option_SaveAllInitials, RenderDocSettings.bSaveAllInitials ? 1 : 0); 147 | 148 | RenderDocAPI->MaskOverlayBits(eRENDERDOC_Overlay_None, eRENDERDOC_Overlay_None); 149 | 150 | #if WITH_EDITOR 151 | EditorExtensions = new FRenderDocPluginEditorExtension (this, &RenderDocSettings); 152 | #endif//WITH_EDITOR 153 | 154 | #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) 155 | static FAutoConsoleCommand CCmdRenderDocCaptureFrame = FAutoConsoleCommand( 156 | TEXT("RenderDoc.CaptureFrame"), 157 | TEXT("Captures the rendering commands of the next frame and launches RenderDoc"), 158 | FConsoleCommandDelegate::CreateRaw(this, &FRenderDocPluginModule::CaptureFrame)); 159 | #endif 160 | 161 | UE_LOG(RenderDocPlugin, Log, TEXT("RenderDoc plugin is ready!")); 162 | } 163 | 164 | class FRenderDocPluginModule::FrameCapturer 165 | { 166 | public: 167 | static void BeginCapture(HWND WindowHandle, FRenderDocPluginLoader::RENDERDOC_API_CONTEXT* RenderDocAPI, FRenderDocPluginModule* Plugin) 168 | { 169 | Plugin->UE4_OverrideDrawEventsFlag(); 170 | RENDERDOC_DevicePointer Device = GDynamicRHI->RHIGetNativeDevice(); 171 | RenderDocAPI->StartFrameCapture(Device, WindowHandle); 172 | } 173 | static void EndCapture(HWND WindowHandle, FRenderDocPluginLoader::RENDERDOC_API_CONTEXT* RenderDocAPI, FRenderDocPluginModule* Plugin) 174 | { 175 | RENDERDOC_DevicePointer Device = GDynamicRHI->RHIGetNativeDevice(); 176 | RenderDocAPI->EndFrameCapture(Device, WindowHandle); 177 | Plugin->UE4_RestoreDrawEventsFlag(); 178 | 179 | Plugin->RunAsyncTask(ENamedThreads::GameThread, [Plugin]() 180 | { 181 | Plugin->StartRenderDoc(FPaths::Combine(*FPaths::GameSavedDir(), *FString("RenderDocCaptures"))); 182 | }); 183 | } 184 | }; 185 | 186 | void FRenderDocPluginModule::BeginCapture() 187 | { 188 | UE_LOG(RenderDocPlugin, Log, TEXT("Capture frame and launch renderdoc!")); 189 | #if WITH_EDITOR 190 | FRenderDocPluginNotification::Get().ShowNotification(NSLOCTEXT("LaunchRenderDocGUI", "LaunchRenderDocGUIShow", "Capturing frame")); 191 | #else 192 | // TODO: if there is no editor, notify via game viewport text 193 | #endif//WITH_EDITOR 194 | 195 | // TODO: maybe move these SetOptions() to FRenderDocPluginSettings... 196 | pRENDERDOC_SetCaptureOptionU32 SetOptions = Loader.RenderDocAPI->SetCaptureOptionU32; 197 | int ok = SetOptions(eRENDERDOC_Option_CaptureCallstacks, RenderDocSettings.bCaptureCallStacks ? 1 : 0); check(ok); 198 | ok = SetOptions(eRENDERDOC_Option_RefAllResources, RenderDocSettings.bRefAllResources ? 1 : 0); check(ok); 199 | ok = SetOptions(eRENDERDOC_Option_SaveAllInitials, RenderDocSettings.bSaveAllInitials ? 1 : 0); check(ok); 200 | 201 | HWND WindowHandle = GetActiveWindow(); 202 | 203 | typedef FRenderDocPluginLoader::RENDERDOC_API_CONTEXT RENDERDOC_API_CONTEXT; 204 | ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER( 205 | StartRenderDocCapture, 206 | HWND, WindowHandle, WindowHandle, 207 | RENDERDOC_API_CONTEXT*, RenderDocAPI, RenderDocAPI, 208 | FRenderDocPluginModule*, Plugin, this, 209 | { 210 | FrameCapturer::BeginCapture(WindowHandle, RenderDocAPI, Plugin); 211 | }); 212 | } 213 | 214 | void FRenderDocPluginModule::EndCapture() 215 | { 216 | HWND WindowHandle = GetActiveWindow(); 217 | 218 | typedef FRenderDocPluginLoader::RENDERDOC_API_CONTEXT RENDERDOC_API_CONTEXT; 219 | ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER( 220 | EndRenderDocCapture, 221 | HWND, WindowHandle, WindowHandle, 222 | RENDERDOC_API_CONTEXT*, RenderDocAPI, RenderDocAPI, 223 | FRenderDocPluginModule*, Plugin, this, 224 | { 225 | FrameCapturer::EndCapture(WindowHandle, RenderDocAPI, Plugin); return; 226 | }); 227 | } 228 | 229 | void FRenderDocPluginModule::CaptureFrame() 230 | { 231 | if (RenderDocSettings.bCaptureAllActivity) 232 | CaptureEntireFrame(); 233 | else 234 | CaptureCurrentViewport(); 235 | } 236 | 237 | void FRenderDocPluginModule::CaptureCurrentViewport() 238 | { 239 | BeginCapture(); 240 | 241 | // infer the intended viewport to intercept/capture: 242 | FViewport* Viewport (NULL); 243 | check(GEngine); 244 | if (!Viewport && GEngine->GameViewport) 245 | { 246 | check(GEngine->GameViewport->Viewport); 247 | if (GEngine->GameViewport->Viewport->HasFocus()) 248 | Viewport = GEngine->GameViewport->Viewport; 249 | } 250 | #if WITH_EDITOR 251 | if (!Viewport && GEditor) 252 | { 253 | // WARNING: capturing from a "PIE-Eject" Editor viewport will not work as 254 | // expected; in such case, capture via the console command 255 | // (this has something to do with the 'active' editor viewport when the UI 256 | // button is clicked versus the one which the console is attached to) 257 | Viewport = GEditor->GetActiveViewport(); 258 | } 259 | #endif//WITH_EDITOR 260 | check(Viewport); 261 | Viewport->Draw(true); 262 | 263 | EndCapture(); 264 | } 265 | 266 | void FRenderDocPluginModule::CaptureEntireFrame() 267 | { 268 | // Are we already in thw workings of capturing an entire engine frame? 269 | if (TickNumber != 0) 270 | return; 271 | 272 | // Begin tracking the global tick counter so that the Tick() method below can 273 | // identify the beginning and end of a complete engine update cycle: 274 | TickNumber = GFrameCounter; 275 | // NOTE: GFrameCounter counts engine ticks, while GFrameNumber counts render 276 | // frames. Multiple frames might get rendered in a single engine update tick. 277 | // All active windows are updated, in a round-robin fashion, within a single 278 | // engine tick. This includes thumbnail images for material preview, material 279 | // editor previews, cascade/persona previes, etc. 280 | } 281 | 282 | void FRenderDocPluginModule::Tick(float DeltaTime) 283 | { 284 | if (TickNumber == 0) 285 | return; 286 | 287 | const uint32 TickDiff = GFrameCounter - TickNumber; 288 | const uint32 MaxCount = 2; 289 | 290 | check(TickDiff <= MaxCount); 291 | 292 | if (TickDiff == 1) 293 | BeginCapture(); 294 | 295 | if (TickDiff == MaxCount) 296 | EndCapture(), 297 | TickNumber = 0; 298 | } 299 | 300 | void FRenderDocPluginModule::StartRenderDoc(FString FrameCaptureBaseDirectory) 301 | { 302 | #if WITH_EDITOR 303 | FRenderDocPluginNotification::Get().ShowNotification( NSLOCTEXT("LaunchRenderDocGUI", "LaunchRenderDocGUIShow", "Launching RenderDoc GUI") ); 304 | #else 305 | // TODO: if there is no editor, notify via game viewport text 306 | #endif//WITH_EDITOR 307 | 308 | FString NewestCapture = GetNewestCapture(FrameCaptureBaseDirectory); 309 | FString ArgumentString = FString::Printf(TEXT("\"%s\""), *FPaths::ConvertRelativePathToFull(NewestCapture).Append(TEXT(".log"))); 310 | 311 | if (!NewestCapture.IsEmpty()) 312 | { 313 | // This is the new, recommended way of launching the RenderDoc GUI: 314 | if (!RenderDocAPI->IsRemoteAccessConnected()) 315 | { 316 | uint32 PID = (sizeof(TCHAR) == sizeof(char)) ? 317 | RenderDocAPI->LaunchReplayUI(true, (const char*)(*ArgumentString)) 318 | : RenderDocAPI->LaunchReplayUI(true, TCHAR_TO_ANSI(*ArgumentString)); 319 | 320 | if (0 == PID) 321 | UE_LOG(LogTemp, Error, TEXT("Could not launch RenderDoc!!")); 322 | } 323 | } 324 | 325 | #if WITH_EDITOR 326 | FRenderDocPluginNotification::Get().ShowNotification( NSLOCTEXT("LaunchRenderDocGUI", "LaunchRenderDocGUIHide", "RenderDoc GUI Launched!") ); 327 | #else 328 | // TODO: if there is no editor, notify via game viewport text 329 | #endif//WITH_EDITOR 330 | } 331 | 332 | FString FRenderDocPluginModule::GetNewestCapture(FString BaseDirectory) 333 | { 334 | char LogFile[512]; 335 | uint64_t Timestamp; 336 | uint32_t LogPathLength = 512; 337 | uint32_t Index = 0; 338 | FString OutString; 339 | 340 | while (RenderDocAPI->GetCapture(Index, LogFile, &LogPathLength, &Timestamp)) 341 | { 342 | if (sizeof(TCHAR) == sizeof(char)) 343 | OutString = FString(LogPathLength, (TCHAR*)LogFile); 344 | else 345 | OutString = FString(LogPathLength, ANSI_TO_TCHAR(LogFile)); 346 | 347 | Index++; 348 | } 349 | 350 | return OutString; 351 | } 352 | 353 | void FRenderDocPluginModule::ShutdownModule() 354 | { 355 | if (GUsingNullRHI) 356 | return; 357 | 358 | #if WITH_EDITOR 359 | delete(EditorExtensions); 360 | #endif//WITH_EDITOR 361 | 362 | Loader.Release(); 363 | 364 | RenderDocAPI = NULL; 365 | } 366 | 367 | void FRenderDocPluginModule::UE4_OverrideDrawEventsFlag(const bool flag) 368 | { 369 | //UE_LOG(RenderDocPlugin, Log, TEXT("Overriding GEmitDrawEvents flag")); 370 | //UE_LOG(RenderDocPlugin, Log, TEXT(" GEmitDrawEvents=%d"), GEmitDrawEvents); 371 | UE4_GEmitDrawEvents_BeforeCapture = GEmitDrawEvents; 372 | GEmitDrawEvents = flag; 373 | //UE_LOG(RenderDocPlugin, Log, TEXT(" GEmitDrawEvents=%d"), GEmitDrawEvents); 374 | } 375 | 376 | void FRenderDocPluginModule::UE4_RestoreDrawEventsFlag() 377 | { 378 | //UE_LOG(RenderDocPlugin, Log, TEXT("Restoring GEmitDrawEvents flag")); 379 | //UE_LOG(RenderDocPlugin, Log, TEXT(" GEmitDrawEvents=%d"), GEmitDrawEvents); 380 | GEmitDrawEvents = UE4_GEmitDrawEvents_BeforeCapture; 381 | //UE_LOG(RenderDocPlugin, Log, TEXT(" GEmitDrawEvents=%d"), GEmitDrawEvents); 382 | } 383 | 384 | void FRenderDocPluginModule::RunAsyncTask(ENamedThreads::Type Where, TFunction What) 385 | { 386 | struct FAsyncGraphTask : public FAsyncGraphTaskBase 387 | { 388 | ENamedThreads::Type TargetThread; 389 | TFunction TheTask; 390 | 391 | FAsyncGraphTask(ENamedThreads::Type Thread, TFunction&& Task) : TargetThread(Thread), TheTask(MoveTemp(Task)) { } 392 | void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) { TheTask(); } 393 | ENamedThreads::Type GetDesiredThread() { return(TargetThread); } 394 | }; 395 | 396 | TGraphTask::CreateTask().ConstructAndDispatchWhenReady(Where, MoveTemp(What)); 397 | } 398 | 399 | #undef LOCTEXT_NAMESPACE 400 | 401 | IMPLEMENT_MODULE(FRenderDocPluginModule, RenderDocPlugin) 402 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginModule.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #include "IRenderDocPlugin.h" 28 | 29 | #include "RenderDocPluginLoader.h" 30 | #include "RenderDocPluginSettings.h" 31 | 32 | #if WITH_EDITOR 33 | #include "Editor/LevelEditor/Public/LevelEditor.h" 34 | #include "SlateBasics.h" 35 | #include "MultiBoxExtender.h" 36 | #include "RenderDocPluginStyle.h" 37 | #include "RenderDocPluginCommands.h" 38 | #include "RenderDocPluginToolbar.h" 39 | #include "RenderDocPluginAboutWindow.h" 40 | #endif//WITH_EDITOR 41 | 42 | #include "SharedPointer.h" 43 | #include "Engine.h" 44 | 45 | DECLARE_LOG_CATEGORY_EXTERN(RenderDocPlugin, Log, All); 46 | 47 | class FRenderDocPluginModule : public IRenderDocPlugin 48 | { 49 | public: 50 | virtual void StartupModule() override; 51 | virtual void ShutdownModule() override; 52 | 53 | private: 54 | // Tick made possible via the dummy input device declared below: 55 | void Tick(float DeltaTime); 56 | class FRenderDocDummyInputDevice; 57 | // Mandatory IInputDeviceModule override that spawns the dummy input device: 58 | virtual TSharedPtr< class IInputDevice > CreateInputDevice(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) override; 59 | 60 | void BeginCapture(); 61 | void EndCapture(); 62 | 63 | friend class SRenderDocPluginToolbar; 64 | void CaptureFrame(); 65 | void CaptureCurrentViewport(); 66 | void CaptureEntireFrame(); 67 | 68 | void StartRenderDoc(FString FrameCaptureBaseDirectory); 69 | FString GetNewestCapture(FString BaseDirectory); 70 | 71 | static void RunAsyncTask(ENamedThreads::Type Where, TFunction What); 72 | 73 | // UE4-related: enable DrawEvents during captures, if necessary: 74 | bool UE4_GEmitDrawEvents_BeforeCapture; 75 | void UE4_OverrideDrawEventsFlag(const bool flag=true); 76 | void UE4_RestoreDrawEventsFlag(); 77 | 78 | FRenderDocPluginLoader Loader; 79 | FRenderDocPluginSettings RenderDocSettings; 80 | FRenderDocPluginLoader::RENDERDOC_API_CONTEXT* RenderDocAPI; 81 | 82 | // Tracks the frame count (tick number) for a full frame capture: 83 | uint32 TickNumber; 84 | 85 | #if WITH_EDITOR 86 | FRenderDocPluginEditorExtension* EditorExtensions; 87 | #endif//WITH_EDITOR 88 | 89 | private: 90 | // TODO: refactor the plugin into subclasses: 91 | class InputDevice; 92 | class RenderDocLoader; 93 | class Settings; 94 | class FrameCapturer; 95 | class UserInterface; 96 | 97 | }; 98 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginNotification.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #if WITH_EDITOR 26 | 27 | #include "RenderDocPluginPrivatePCH.h" 28 | #include "RenderDocPluginNotification.h" 29 | 30 | #include "SNotificationList.h" 31 | #include "NotificationManager.h" 32 | 33 | void FRenderDocPluginNotification::ShowNotification(const FText& Message) 34 | { 35 | LastEnableTime = FPlatformTime::Seconds(); 36 | 37 | // Starting a new request! Notify the UI. 38 | if (RenderDocNotificationPtr.IsValid()) 39 | { 40 | RenderDocNotificationPtr.Pin()->ExpireAndFadeout(); 41 | } 42 | 43 | FNotificationInfo Info (Message); 44 | Info.bFireAndForget = false; 45 | 46 | // Setting fade out and expire time to 0 as the expire message is currently very obnoxious 47 | Info.FadeOutDuration = 1.0f; 48 | Info.ExpireDuration = 0.0f; 49 | 50 | RenderDocNotificationPtr = FSlateNotificationManager::Get().AddNotification(Info); 51 | 52 | if (RenderDocNotificationPtr.IsValid()) 53 | { 54 | RenderDocNotificationPtr.Pin()->SetCompletionState(SNotificationItem::CS_Pending); 55 | } 56 | } 57 | 58 | void FRenderDocPluginNotification::HideNotification() 59 | { 60 | // Finished all requests! Notify the UI. 61 | TSharedPtr NotificationItem = RenderDocNotificationPtr.Pin(); 62 | 63 | if (NotificationItem.IsValid()) 64 | { 65 | NotificationItem->SetCompletionState(SNotificationItem::CS_Success); 66 | NotificationItem->ExpireAndFadeout(); 67 | 68 | RenderDocNotificationPtr.Reset(); 69 | } 70 | } 71 | 72 | void FRenderDocPluginNotification::Tick(float DeltaTime) 73 | { 74 | double OpenTime = 5.0; 75 | //if (bIsGUIOpen) 76 | // OpenTime = 0.5; 77 | 78 | if (RenderDocNotificationPtr.IsValid() && (FPlatformTime::Seconds() - LastEnableTime) > OpenTime) 79 | { 80 | HideNotification(); 81 | } 82 | } 83 | 84 | TStatId FRenderDocPluginNotification::GetStatId() const 85 | { 86 | RETURN_QUICK_DECLARE_CYCLE_STAT(FRenderDocPluginNotification, STATGROUP_Tickables); 87 | } 88 | 89 | #endif//WITH_EDITOR 90 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginNotification.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #if WITH_EDITOR 28 | 29 | #include "UnrealEd.h" 30 | #include "NotificationManager.h" 31 | 32 | class FRenderDocPluginNotification : public FTickableEditorObject 33 | { 34 | public: 35 | static FRenderDocPluginNotification& Get() 36 | { 37 | static FRenderDocPluginNotification Instance; 38 | return Instance; 39 | } 40 | 41 | void ShowNotification(const FText& Message); 42 | void HideNotification(); 43 | 44 | protected: 45 | /** FTickableEditorObject interface */ 46 | virtual void Tick(float DeltaTime); 47 | virtual bool IsTickable() const 48 | { 49 | return true; 50 | } 51 | virtual TStatId GetStatId() const override; 52 | 53 | private: 54 | FRenderDocPluginNotification() { LastEnableTime = 0; } 55 | FRenderDocPluginNotification(FRenderDocPluginNotification const&); 56 | void operator=(FRenderDocPluginNotification const&); 57 | 58 | double LastEnableTime; 59 | 60 | /** The source code symbol query in progress message */ 61 | TWeakPtr RenderDocNotificationPtr; 62 | }; 63 | 64 | #endif//WITH_EDITOR 65 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginPrivatePCH.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginSettings.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | struct FRenderDocPluginSettings 28 | { 29 | public: 30 | bool bCaptureAllActivity; 31 | bool bCaptureCallStacks; 32 | bool bRefAllResources; 33 | bool bSaveAllInitials; 34 | 35 | FRenderDocPluginSettings() 36 | { 37 | if (!GConfig->GetBool(TEXT("RenderDoc"), TEXT("CaptureAllActivity"), bCaptureCallStacks, GGameIni)) 38 | bCaptureAllActivity = false; 39 | 40 | if (!GConfig->GetBool(TEXT("RenderDoc"), TEXT("CaptureCallStacks"), bCaptureCallStacks, GGameIni)) 41 | bCaptureCallStacks = false; 42 | 43 | if (!GConfig->GetBool(TEXT("RenderDoc"), TEXT("RefAllResources"), bRefAllResources, GGameIni)) 44 | bRefAllResources = false; 45 | 46 | if (!GConfig->GetBool(TEXT("RenderDoc"), TEXT("SaveAllInitials"), bSaveAllInitials, GGameIni)) 47 | bSaveAllInitials = false; 48 | } 49 | 50 | void Save() const 51 | { 52 | GConfig->SetBool(TEXT("RenderDoc"), TEXT("CaptureAllActivity"), bCaptureAllActivity, GGameIni); 53 | GConfig->SetBool(TEXT("RenderDoc"), TEXT("CaptureCallStacks"), bCaptureCallStacks, GGameIni); 54 | GConfig->SetBool(TEXT("RenderDoc"), TEXT("RefAllResources"), bRefAllResources, GGameIni); 55 | GConfig->SetBool(TEXT("RenderDoc"), TEXT("SaveAllInitials"), bSaveAllInitials, GGameIni); 56 | GConfig->Flush(false, GGameIni); 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginStyle.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #if WITH_EDITOR 26 | 27 | #include "RenderDocPluginPrivatePCH.h" 28 | #include "RenderDocPluginStyle.h" 29 | 30 | #include "SlateStyle.h" 31 | #include "IPluginManager.h" 32 | 33 | FString FRenderDocPluginStyle::InContent(const FString& RelativePath, const ANSICHAR* Extension) 34 | { 35 | auto myself = IPluginManager::Get().FindPlugin(TEXT("RenderDocPlugin")); 36 | check(myself.IsValid()); 37 | static FString ContentDir = myself->GetBaseDir() / TEXT("Resources"); 38 | return (ContentDir / RelativePath) + Extension; 39 | } 40 | 41 | TSharedPtr FRenderDocPluginStyle::StyleSet = NULL; 42 | TSharedPtr FRenderDocPluginStyle::Get() { return StyleSet; } 43 | 44 | void FRenderDocPluginStyle::Initialize() 45 | { 46 | // Const icon sizes 47 | const FVector2D Icon20x20(20.0f, 20.0f); 48 | const FVector2D Icon40x40(40.0f, 40.0f); 49 | 50 | // Only register once 51 | if (StyleSet.IsValid()) 52 | { 53 | return; 54 | } 55 | 56 | StyleSet = MakeShareable(new FSlateStyleSet("RenderDocPluginStyle")); 57 | 58 | FString ProjectResourceDir = FPaths::GamePluginsDir() / TEXT("RenderDocPlugin/Resources"); 59 | FString EngineResourceDir = FPaths::EnginePluginsDir() / TEXT("RenderDocPlugin/Resources"); 60 | 61 | if (IFileManager::Get().DirectoryExists(*ProjectResourceDir)) //Is the plugin in the project? In that case, use those resources 62 | { 63 | StyleSet->SetContentRoot(ProjectResourceDir); 64 | StyleSet->SetCoreContentRoot(ProjectResourceDir); 65 | } 66 | else //Otherwise, use the global ones 67 | { 68 | StyleSet->SetContentRoot(EngineResourceDir); 69 | StyleSet->SetCoreContentRoot(EngineResourceDir); 70 | } 71 | 72 | StyleSet->Set("RenderDocPlugin.CaptureFrameIcon", new FSlateImageBrush(FRenderDocPluginStyle::InContent("Icon40", ".png"), Icon40x40)); 73 | StyleSet->Set("RenderDocPlugin.CaptureFrameIcon.Small", new FSlateImageBrush(FRenderDocPluginStyle::InContent("Icon20", ".png"), Icon20x20)); 74 | StyleSet->Set("RenderDocPlugin.SettingsIcon.Small", new FSlateImageBrush(FRenderDocPluginStyle::InContent("SettingsIcon20", ".png"), Icon20x20)); 75 | 76 | FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get()); 77 | }; 78 | 79 | void FRenderDocPluginStyle::Shutdown() 80 | { 81 | if (StyleSet.IsValid()) 82 | { 83 | FSlateStyleRegistry::UnRegisterSlateStyle(*StyleSet.Get()); 84 | ensure(StyleSet.IsUnique()); 85 | StyleSet.Reset(); 86 | } 87 | } 88 | 89 | #endif//WITH_EDITOR 90 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginStyle.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #if WITH_EDITOR 28 | 29 | #include "SlateBasics.h" 30 | 31 | class FRenderDocPluginStyle 32 | { 33 | public: 34 | static void Initialize(); 35 | 36 | static void Shutdown(); 37 | 38 | static TSharedPtr Get(); 39 | 40 | private: 41 | static FString InContent(const FString& RelativePath, const ANSICHAR* Extension); 42 | 43 | private: 44 | static TSharedPtr StyleSet; 45 | }; 46 | 47 | #endif//WITH_EDITOR 48 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginToolbar.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #if WITH_EDITOR 26 | 27 | #include "RenderDocPluginPrivatePCH.h" 28 | #include "RenderDocPluginToolbar.h" 29 | 30 | #include "Engine.h" 31 | #include "Editor.h" 32 | #include "EditorStyleSet.h" 33 | #include "Editor/UnrealEd/Public/SEditorViewportToolBarMenu.h" 34 | #include "Editor/UnrealEd/Public/SViewportToolBarComboMenu.h" 35 | #include "RenderDocPluginStyle.h" 36 | #include "RenderDocPluginCommands.h" 37 | #include "RenderDocPluginModule.h" 38 | #include "RenderDocPluginAboutWindow.h" 39 | 40 | FRenderDocPluginEditorExtension::FRenderDocPluginEditorExtension(FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* Settings) 41 | { 42 | // Defer Level Editor UI extensions until Level Editor has been loaded: 43 | if (FModuleManager::Get().IsModuleLoaded("LevelEditor")) 44 | Initialize(ThePlugin, Settings); 45 | else 46 | FModuleManager::Get().OnModulesChanged().AddLambda([this, ThePlugin, Settings](FName name, EModuleChangeReason reason) 47 | { 48 | if ((name == "LevelEditor") && (reason == EModuleChangeReason::ModuleLoaded)) 49 | Initialize(ThePlugin, Settings); 50 | }); 51 | } 52 | 53 | FRenderDocPluginEditorExtension::~FRenderDocPluginEditorExtension() 54 | { 55 | if (ExtensionManager.IsValid()) 56 | { 57 | FRenderDocPluginStyle::Shutdown(); 58 | FRenderDocPluginCommands::Unregister(); 59 | 60 | ToolbarExtender->RemoveExtension(ToolbarExtension.ToSharedRef()); 61 | 62 | ExtensionManager->RemoveExtender(ToolbarExtender); 63 | } 64 | else 65 | { 66 | ExtensionManager.Reset(); 67 | } 68 | } 69 | 70 | void FRenderDocPluginEditorExtension::Initialize(FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* Settings) 71 | { 72 | if (GUsingNullRHI) 73 | { 74 | UE_LOG(RenderDocPlugin, Warning, TEXT("RenderDoc Plugin will not be loaded because a Null RHI (Cook Server, perhaps) is being used.")); 75 | return; 76 | } 77 | 78 | // The LoadModule request below will crash if running as an editor commandlet! 79 | // ( the GUsingNullRHI check above should prevent this code from executing, but I am 80 | // re-emphasizing it here since many plugins appear to be ignoring this condition... ) 81 | check(!IsRunningCommandlet()); 82 | 83 | FRenderDocPluginStyle::Initialize(); 84 | FRenderDocPluginCommands::Register(); 85 | 86 | FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked("LevelEditor"); 87 | 88 | TSharedRef CommandBindings = LevelEditorModule.GetGlobalLevelEditorActions(); 89 | 90 | ExtensionManager = LevelEditorModule.GetToolBarExtensibilityManager(); 91 | ToolbarExtender = MakeShareable(new FExtender); 92 | ToolbarExtension = ToolbarExtender->AddToolBarExtension("CameraSpeed", EExtensionHook::After, CommandBindings, 93 | FToolBarExtensionDelegate::CreateLambda([this, ThePlugin, Settings](FToolBarBuilder& ToolbarBuilder) 94 | { AddToolbarExtension(ToolbarBuilder, ThePlugin, Settings); }) 95 | ); 96 | ExtensionManager->AddExtender(ToolbarExtender); 97 | 98 | IsEditorInitialized = false; 99 | FSlateRenderer* SlateRenderer = FSlateApplication::Get().GetRenderer().Get(); 100 | LoadedDelegateHandle = SlateRenderer->OnSlateWindowRendered().AddRaw(this, &FRenderDocPluginEditorExtension::OnEditorLoaded); 101 | } 102 | 103 | void FRenderDocPluginEditorExtension::OnEditorLoaded(SWindow& SlateWindow, void* ViewportRHIPtr) 104 | { 105 | // would be nice to use the preprocessor definition WITH_EDITOR instead, 106 | // but the user may launch a standalone the game through the editor... 107 | if (!GEditor) 108 | return; 109 | 110 | // --> YAGER by SKrysanov 6/11/2014 : fixed crash on removing this callback in render thread. 111 | if (IsInGameThread()) 112 | { 113 | FSlateRenderer* SlateRenderer = FSlateApplication::Get().GetRenderer().Get(); 114 | SlateRenderer->OnSlateWindowRendered().Remove(LoadedDelegateHandle); 115 | } 116 | // <-- YAGER by SKrysanov 6/11/2014 117 | 118 | if (IsEditorInitialized) 119 | { 120 | return; 121 | } 122 | IsEditorInitialized = true; 123 | 124 | if (GConfig) 125 | { 126 | bool bGreetingHasBeenShown (false); 127 | GConfig->GetBool(TEXT("RenderDoc"), TEXT("GreetingHasBeenShown"), bGreetingHasBeenShown, GGameIni); 128 | if (!bGreetingHasBeenShown && GEditor) 129 | { 130 | GEditor->EditorAddModalWindow(SNew(SRenderDocPluginAboutWindow)); 131 | GConfig->SetBool(TEXT("RenderDoc"), TEXT("GreetingHasBeenShown"), true, GGameIni); 132 | } 133 | } 134 | } 135 | 136 | void FRenderDocPluginEditorExtension::AddToolbarExtension(FToolBarBuilder& ToolbarBuilder, FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* Settings) 137 | { 138 | #define LOCTEXT_NAMESPACE "LevelEditorToolBar" 139 | 140 | UE_LOG(RenderDocPlugin, Log, TEXT("Attaching toolbar extension...")); 141 | ToolbarBuilder.AddSeparator(); 142 | 143 | ToolbarBuilder.BeginSection("RenderdocPlugin"); 144 | 145 | ToolbarBuilder.AddWidget( 146 | SNew(SRenderDocPluginToolbar) 147 | .ThePlugin(ThePlugin) 148 | .Settings(Settings) 149 | ); 150 | 151 | ToolbarBuilder.EndSection(); 152 | 153 | #undef LOCTEXT_NAMESPACE//"LevelEditorToolBar" 154 | } 155 | 156 | #define LOCTEXT_NAMESPACE "RenderDocPluginSettingsEditor" 157 | 158 | namespace TransformViewportToolbarDefs 159 | { 160 | /** Size of the arrow shown on SGridSnapSettings Menu button */ 161 | const float DownArrowSize = 4.0f; 162 | 163 | /** Size of the icon displayed on the toggle button of SGridSnapSettings */ 164 | const float ToggleImageScale = 16.0f; 165 | } 166 | 167 | void SRenderDocPluginToolbar::Construct(const FArguments& InArgs) 168 | { 169 | auto ThePlugin = InArgs._ThePlugin; 170 | auto RenderDocSettings = InArgs._Settings; 171 | 172 | BindCommands(ThePlugin, RenderDocSettings); 173 | 174 | FSlateIcon IconBrush = FSlateIcon(FRenderDocPluginStyle::Get()->GetStyleSetName(), "RenderDocPlugin.CaptureFrameIcon.Small"); 175 | FSlateIcon SettingsIconBrush = FSlateIcon(FRenderDocPluginStyle::Get()->GetStyleSetName(), "RenderDocPlugin.SettingsIcon.Small"); 176 | 177 | // Widget inspired by STransformViewportToolbar::MakeSurfaceSnappingButton() 178 | FName ToolBarStyle = TEXT("ViewportMenu"); 179 | ChildSlot 180 | [ 181 | SNew(SHorizontalBox) 182 | 183 | + SHorizontalBox::Slot() 184 | .AutoWidth() 185 | [ 186 | SNew(SButton) 187 | .ToolTipText(FRenderDocPluginCommands::Get().CaptureFrame->GetDescription()) // TODO: [Alt+F12] does not show up in the tooltip... 188 | .OnClicked_Lambda([this]() { CommandList->GetActionForCommand(FRenderDocPluginCommands::Get().CaptureFrame)->Execute(); return(FReply::Handled()); }) 189 | [ 190 | SNew(SImage) 191 | .Image(IconBrush.GetIcon()) 192 | ] 193 | ] 194 | 195 | + SHorizontalBox::Slot() 196 | .AutoWidth() 197 | [ 198 | SNew(SCheckBox) 199 | .Cursor(EMouseCursor::Default) 200 | .Style(FEditorStyle::Get(), EMultiBlockLocation::ToName(FEditorStyle::Join(ToolBarStyle, ".ToggleButton"), EMultiBlockLocation::End)) 201 | .Padding(0) 202 | .ToolTipText(LOCTEXT("RenderDocSettings_ToolTipOverride", "RenderDoc Settings")) 203 | .IsChecked_Static([] { return(ECheckBoxState::Unchecked); }) 204 | .Content() 205 | [ 206 | SNew( SComboButton ) 207 | .ButtonStyle( FEditorStyle::Get(), "HoverHintOnly" ) 208 | .HasDownArrow( false ) 209 | .ContentPadding( 0 ) 210 | .ButtonContent() 211 | [ 212 | SNew( SVerticalBox ) 213 | 214 | + SVerticalBox::Slot() 215 | .AutoHeight() 216 | .Padding(FMargin(3.f, 2.f, 5.f, 0.f)) 217 | [ 218 | SNew( SBox ) 219 | .WidthOverride( TransformViewportToolbarDefs::ToggleImageScale ) 220 | .HeightOverride( TransformViewportToolbarDefs::ToggleImageScale ) 221 | .HAlign( HAlign_Center ) 222 | .VAlign( VAlign_Center ) 223 | [ 224 | SNew( SImage ) 225 | .Image( SettingsIconBrush.GetIcon() ) 226 | ] 227 | ] 228 | 229 | + SVerticalBox::Slot() 230 | .AutoHeight() 231 | .HAlign( HAlign_Center ) 232 | .Padding(FMargin(0.f, 0.f, 0.f, 3.f)) 233 | [ 234 | SNew( SBox ) 235 | .WidthOverride( TransformViewportToolbarDefs::DownArrowSize ) 236 | .HeightOverride( TransformViewportToolbarDefs::DownArrowSize ) 237 | [ 238 | SNew(SImage) 239 | .Image(FEditorStyle::GetBrush("ComboButton.Arrow")) 240 | .ColorAndOpacity(FLinearColor::Black) 241 | ] 242 | ] 243 | ] 244 | .MenuContent() 245 | [ 246 | ([this,RenderDocSettings]() -> TSharedRef 247 | { 248 | auto& Commands = FRenderDocPluginCommands::Get(); 249 | FMenuBuilder ShowMenuBuilder (true, CommandList); 250 | 251 | ShowMenuBuilder.AddMenuEntry(Commands.Settings_CaptureAllActivity); 252 | ShowMenuBuilder.AddMenuEntry(Commands.Settings_CaptureCallstack); 253 | ShowMenuBuilder.AddMenuEntry(Commands.Settings_CaptureAllResources); 254 | ShowMenuBuilder.AddMenuEntry(Commands.Settings_SaveAllInitialState); 255 | 256 | ShowMenuBuilder.AddWidget( 257 | SNew(SVerticalBox) 258 | +SVerticalBox::Slot() 259 | .AutoHeight() 260 | [ 261 | SNew(SHorizontalBox) 262 | + SHorizontalBox::Slot() 263 | .AutoWidth() 264 | .VAlign(EVerticalAlignment::VAlign_Center) 265 | .Padding(5) 266 | [ 267 | SNew(SButton) 268 | .Text(LOCTEXT("SaveButton", "Save")) 269 | .ToolTipText(LOCTEXT("SaveButton_ToolTipOverride", "Save current RenderDoc settings for this game project.")) 270 | .OnClicked_Lambda([RenderDocSettings]() 271 | { 272 | RenderDocSettings->Save(); 273 | return( FReply::Handled() ); 274 | }) 275 | ] 276 | 277 | +SHorizontalBox::Slot() 278 | .AutoWidth() 279 | .VAlign(EVerticalAlignment::VAlign_Center) 280 | .Padding(5) 281 | [ 282 | SNew(SButton) 283 | .Text(LOCTEXT("AboutButton", "About")) 284 | .OnClicked_Lambda([]() 285 | { 286 | GEditor->EditorAddModalWindow( SNew(SRenderDocPluginAboutWindow) ); 287 | return( FReply::Handled() ); 288 | }) 289 | ] 290 | ], 291 | FText() 292 | ); 293 | 294 | return(ShowMenuBuilder.MakeWidget()); 295 | }()) 296 | ] // end of SComboButton::MenuContent() 297 | ] // end of SComboButton 298 | ] // end of SCheckBox 299 | ]; // end of Toolbar extension 300 | 301 | } 302 | 303 | void SRenderDocPluginToolbar::BindCommands(FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* Settings) 304 | { 305 | check(!CommandList.IsValid()); 306 | CommandList = MakeShareable(new FUICommandList); 307 | 308 | auto& Commands = FRenderDocPluginCommands::Get(); 309 | 310 | CommandList->MapAction( 311 | Commands.CaptureFrame, 312 | FExecuteAction::CreateLambda([ThePlugin]() { ThePlugin->CaptureFrame(); }), 313 | FCanExecuteAction() 314 | ); 315 | 316 | CommandList->MapAction( 317 | Commands.Settings_CaptureAllActivity, 318 | FExecuteAction::CreateLambda([](bool* flag) { *flag = !*flag; }, 319 | &Settings->bCaptureAllActivity), 320 | FCanExecuteAction(), 321 | FIsActionChecked::CreateLambda([](const bool* flag) { return(*flag); }, 322 | &Settings->bCaptureAllActivity) 323 | ); 324 | 325 | CommandList->MapAction( 326 | Commands.Settings_CaptureCallstack, 327 | FExecuteAction::CreateLambda([](bool* flag) { *flag = !*flag; }, 328 | &Settings->bCaptureCallStacks), 329 | FCanExecuteAction(), 330 | FIsActionChecked::CreateLambda([](const bool* flag) { return(*flag); }, 331 | &Settings->bCaptureCallStacks) 332 | ); 333 | 334 | CommandList->MapAction( 335 | Commands.Settings_CaptureAllResources, 336 | FExecuteAction::CreateLambda([](bool* flag) { *flag = !*flag; }, 337 | &Settings->bRefAllResources), 338 | FCanExecuteAction(), 339 | FIsActionChecked::CreateLambda([](const bool* flag) { return(*flag); }, 340 | &Settings->bRefAllResources) 341 | ); 342 | 343 | CommandList->MapAction( 344 | Commands.Settings_SaveAllInitialState, 345 | FExecuteAction::CreateLambda([](bool* flag) { *flag = !*flag; }, 346 | &Settings->bSaveAllInitials), 347 | FCanExecuteAction(), 348 | FIsActionChecked::CreateLambda([](const bool* flag) { return(*flag); }, 349 | &Settings->bSaveAllInitials) 350 | ); 351 | } 352 | 353 | #undef LOCTEXT_NAMESPACE 354 | 355 | #endif//WITH_EDITOR 356 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginToolbar.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #if WITH_EDITOR 28 | 29 | #include "SlateBasics.h" 30 | #include "Editor/UnrealEd/Public/SViewportToolBar.h" 31 | #include "RenderDocPluginSettings.h" 32 | 33 | class FRenderDocPluginEditorExtension 34 | { 35 | public: 36 | FRenderDocPluginEditorExtension(FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* Settings); 37 | ~FRenderDocPluginEditorExtension(); 38 | 39 | private: 40 | void Initialize(FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* Settings); 41 | void OnEditorLoaded(SWindow& SlateWindow, void* ViewportRHIPtr); 42 | void AddToolbarExtension(FToolBarBuilder& ToolbarBuilder, FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* Settings); 43 | 44 | bool IsEditorInitialized; 45 | FDelegateHandle LoadedDelegateHandle; 46 | TSharedPtr ExtensionManager; 47 | TSharedPtr ToolbarExtender; 48 | TSharedPtr ToolbarExtension; 49 | }; 50 | 51 | class SRenderDocPluginToolbar : public SViewportToolBar 52 | { 53 | public: 54 | SLATE_BEGIN_ARGS(SRenderDocPluginToolbar) { } 55 | SLATE_ARGUMENT(FRenderDocPluginModule*, ThePlugin) 56 | SLATE_ARGUMENT(FRenderDocPluginSettings*, Settings) 57 | SLATE_END_ARGS() 58 | 59 | /** Widget constructor */ 60 | void Construct(const FArguments& Args); 61 | 62 | private: 63 | TSharedPtr CommandList; 64 | 65 | void BindCommands(FRenderDocPluginModule* ThePlugin, FRenderDocPluginSettings* settings); 66 | }; 67 | 68 | #endif//WITH_EDITOR 69 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/Public/IRenderDocPlugin.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Marcos Slomp 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #include "InputDevice.h" 28 | 29 | 30 | /** 31 | * The RenderDoc plugin has been redesigned as an input plugin. Regular plugins built upon 32 | * IModuleInterface lack the ability of ticking, while IInputDeviceModule instantiates and 33 | * manages an IInputDevice object that is capable of ticking. 34 | * 35 | * By responding to tick events, the RenderDoc plugin is able to intercept the entire frame 36 | * activity, including Editor (Slate) UI rendering and SceneCapture updates; older versions 37 | * of the RenderDoc plugin were limited to capturing particular viewports only. 38 | * 39 | * This public interface wrapper appears to be mandatory for input device plugins/modules. 40 | * Without this public wrapper, the input device (IInputDevice) associated with the plugin 41 | * will not be instantiated during engine/application startup time. 42 | */ 43 | 44 | 45 | /** 46 | * The public interface to this module. In most cases, this interface is only public to sibling modules 47 | * within this plugin. 48 | */ 49 | class IRenderDocPlugin : public IInputDeviceModule 50 | { 51 | public: 52 | 53 | /** 54 | * Singleton-like access to this module's interface. This is just for convenience! 55 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. 56 | * 57 | * @return Returns singleton instance, loading the module on demand if needed 58 | */ 59 | static inline IRenderDocPlugin& Get() 60 | { 61 | return FModuleManager::LoadModuleChecked< IRenderDocPlugin >("RenderDocPlugin"); 62 | } 63 | 64 | /** 65 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. 66 | * 67 | * @return True if the module is loaded and ready to use 68 | */ 69 | static inline bool IsAvailable() 70 | { 71 | return FModuleManager::Get().IsModuleLoaded("RenderDocPlugin"); 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /RenderDocPlugin/Source/RenderDocPlugin/RenderDocPlugin.Build.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014 Fredrik Lindh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | namespace UnrealBuildTool.Rules 26 | { 27 | using System.IO; 28 | 29 | public class RenderDocPlugin : ModuleRules 30 | { 31 | public RenderDocPlugin(TargetInfo Target) 32 | { 33 | PrivateDependencyModuleNames.AddRange(new string[] { }); 34 | 35 | PublicIncludePaths.AddRange(new string[] { "RenderDocPlugin/Public" }); 36 | PrivateIncludePaths.AddRange(new string[] { "RenderDocPlugin/Private" }); 37 | 38 | PublicDependencyModuleNames.AddRange(new string[] 39 | { 40 | "Core" 41 | ,"CoreUObject" 42 | ,"Engine" 43 | ,"InputCore" 44 | ,"DesktopPlatform" 45 | ,"Projects" 46 | ,"RenderCore" 47 | ,"InputDevice" 48 | ,"RHI" // RHI module: required for accessing the UE4 flag GUsingNullRHI. 49 | }); 50 | 51 | if (UEBuildConfiguration.bBuildEditor == true) 52 | { 53 | DynamicallyLoadedModuleNames.AddRange(new string[] { "LevelEditor" }); 54 | PublicDependencyModuleNames.AddRange(new string[] 55 | { 56 | "Slate" 57 | ,"SlateCore" 58 | ,"EditorStyle" 59 | ,"UnrealEd" 60 | ,"MainFrame" 61 | ,"GameProjectGeneration" 62 | }); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | * Capture callstack setting does not appear to be working... 2 | 3 | * Better integration with the many different viewports: 4 | At the moment, only the main Editor viewport contains the plugin's capture and settings buttons. 5 | These buttons should be available on other viewports, such as: 6 | * "Play In Editor" (PIE) viewport 7 | (for the time being, Eject from the PIE viewport to get access to the HUD buttons) 8 | * "Standalone Game" viewports launched via the Editor 9 | (for the time being, use the console command 'RenderDoc.CaptureFrame') 10 | * Tool preview viewports, such the ones in the Material Editor, Persona, Cascade, etc. 11 | (for the time being, rendering activity on these preview viewports can be intercepted 12 | by activating the "capture all activity" toggle in the plugin settings) 13 | 14 | * It would also be nice to have the 'BinaryPath' configuration understand and parse 15 | a RenderDoc installation location relative to the Engine or Game by using the same 16 | syntax of content/asset reference paths like '/Engine/...' and '/Game/...' (at the 17 | moment, it is necessary to use ../.. before /Engine and /Game). 18 | 19 | 20 | 21 | Prompt user if he is sure he wants to recompile all shaders 22 | Explain that this will rebuild all shaders, and it will lock the editor while the shaders are building 23 | 24 | Set Global input variable 25 | D:\My Projects\UnrealEngine\Engine\Config\ConsoleVariables DumpShaderDebugInfo 26 | GDumpShaderDebugInfo 27 | 28 | Force recompile all shaders 29 | 30 | 31 | 32 | 33 | 34 | Amend forum post with info on how to set the shader debug info manually 35 | Create branch that contains the UI and other code to set the render flag automatically 36 | 37 | 38 | 39 | Engine: 40 | Release buffers in correct spot 41 | Shader compile problem 42 | 43 | Release: 44 | Post in forum 45 | Post in wiki 46 | 47 | Tests: 48 | Spam capture button 49 | See that tests are loaded correctly on: Startup, after set. 50 | 51 | Backlog: 52 | Maybe remove irrelevant tabs in renderdoc UI when launched from UE4? Like Launch process tab etc. 53 | -------------------------------------------------------------------------------- /doc/img/howto-capture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/doc/img/howto-capture.jpg -------------------------------------------------------------------------------- /doc/img/howto-enable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/doc/img/howto-enable.jpg -------------------------------------------------------------------------------- /doc/img/howto-plugin_menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/doc/img/howto-plugin_menu.jpg -------------------------------------------------------------------------------- /doc/img/howto-settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Temaran/UE4RenderDocPlugin/1204d436654e0eadfc856ce4032cfc5e2edca756/doc/img/howto-settings.jpg --------------------------------------------------------------------------------