├── LICENSE
├── CMakeLists.txt
├── README.md
├── src
└── main.cpp
└── .gitignore
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 milkru
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.6 FATAL_ERROR)
2 | cmake_policy(VERSION 3.6)
3 | project(gpu_clock_stabilizer VERSION 1.0.0 LANGUAGES C CXX)
4 |
5 | set(CMAKE_SUPPRESS_REGENERATION true)
6 | set(DCMAKE_GENERATOR_PLATFORM "x64")
7 | set(CMAKE_CXX_EXTENSIONS OFF)
8 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
9 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
10 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
11 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
12 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
13 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
14 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
15 |
16 | file(GLOB_RECURSE SRC_FILES RELATIVE
17 | ${CMAKE_CURRENT_SOURCE_DIR}
18 | ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
19 | ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
20 | )
21 |
22 | foreach(source IN LISTS SRC_FILES)
23 | get_filename_component(source_path "${source}" PATH)
24 | string(REPLACE "/" "\\" source_path_msvc "${source_path}")
25 | string(REPLACE "src" "" source_path_final "${source_path_msvc}")
26 | source_group("${source_path_final}" FILES "${source}")
27 | endforeach()
28 |
29 | add_executable(${PROJECT_NAME} ${SRC_FILES})
30 |
31 | set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)
32 | set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
33 |
34 | if (MSVC)
35 | set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})
36 | endif()
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # About
2 | A simple *DirectX 12* based *GPU clock stabilizer* used for consistent *GPU* profiling on *Windows*. It can be used for profiling applications made with other modern graphics APIs as well. It utilizes *DirectX 12's* `SetStablePowerState` device method in order to achieve this. This allows more deterministic timestamp query results used for calculating elapsed *GPU* time for any given range of render calls at the expense of lower performance. You can read more about it [here](https://developer.nvidia.com/dx12-dos-and-donts#powerstate). Also, make sure that your GPU actually supports [ID3D12Device::SetStablePowerState](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate).
3 |
4 | ## Installation
5 | The *DirectX 12 SDK* comes included with the *Windows 10 SDK* which is part of the *Visual Studio* installation. Just make sure you install the *Game Development with C++* in the *Visual Studio Installer*.
6 |
7 | Run cmd `cmake . -B bin -A x64` in the project's root.
8 |
9 | ## How it works
10 | If not specified in the command line, the first available *GPU* will be chosen. You can also specifiy the *GPU* explicitly by passing the name of the preferred *GPU*, for example "*NVIDIA GeForce RTX 3070*". Names of your *GPUs* can be found in *Device Manager*, *Display Adapters* tab. This way the application can work on *multi GPU system*. In order for *GPU clock* to remain stable, the application should remain running at all times. After exiting the application, or after one hour, clock stabilization will stop working. For testing the *GPU clock* I recommend using the [TechPowerUp GPU-Z](https://www.techpowerup.com/download/techpowerup-gpu-z/). Observe the *Sensors/GPU Core Clock's* behavior with and without the application running.
11 |
12 | ## Results
13 | First image shows the usual GPU clock values on *NVidia GeForce RTX 3070* and the second one shows the clock with the *gpu_clock_stabilizer* running. This was captured using the [TechPowerUp GPU-Z](https://www.techpowerup.com/download/techpowerup-gpu-z/).
14 |  
15 |
16 | ## Troubleshooting
17 | If `SetStablePowerState` is failing, please refer to the [SetStablePowerState Microsoft Documentation](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate) for troubleshooting. This mostly happens if *Developer Mode* is not enabled on *Windows*.
18 |
19 | ## License
20 | Distributed under the MIT License. See `LICENSE` for more information.
21 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #pragma comment(lib, "d3d12.lib")
2 | #pragma comment(lib, "dxgi.lib")
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | int wmain(int argc, wchar_t* argv[], wchar_t* envp[])
12 | {
13 | wchar_t* requestedAdapterName = argc > 1 ? argv[1] : nullptr;
14 |
15 | // Create Factory.
16 | Microsoft::WRL::ComPtr factory;
17 | if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory))))
18 | {
19 | fprintf_s(stderr, "IDXGIFactory4 creation FAILED.\n");
20 |
21 | std::this_thread::sleep_for(std::chrono::minutes(1));
22 | return EXIT_FAILURE;
23 | }
24 |
25 | // Pick Adapter.
26 | bool adapterFound = false;
27 | Microsoft::WRL::ComPtr adapter;
28 | DXGI_ADAPTER_DESC1 adapterDescriptor;
29 | for (UINT adapterIndex = 0; factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex)
30 | {
31 | adapter->GetDesc1(&adapterDescriptor);
32 |
33 | // Skip software adapters.
34 | if ((adapterDescriptor.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0)
35 | {
36 | continue;
37 | }
38 |
39 | // Skip an adapter if it's not requested.
40 | if (requestedAdapterName != nullptr && wcscmp(requestedAdapterName, adapterDescriptor.Description) != 0)
41 | {
42 | continue;
43 | }
44 |
45 | // Adequate adapter found.
46 | if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
47 | {
48 | adapterFound = true;
49 | break;
50 | }
51 | }
52 |
53 | if (adapterFound)
54 | {
55 | fwprintf_s(stdout, L"Adapter \"%ls\" successfully FOUND.\n", adapterDescriptor.Description);
56 | }
57 | else if (requestedAdapterName != nullptr)
58 | {
59 | fwprintf_s(stderr, L"Required adapter \"%ls\" NOT FOUND.\n", requestedAdapterName);
60 |
61 | std::this_thread::sleep_for(std::chrono::minutes(1));
62 | return EXIT_FAILURE;
63 | }
64 | else
65 | {
66 | fwprintf_s(stderr, L"NOT a single adapter was FOUND.\n");
67 |
68 | std::this_thread::sleep_for(std::chrono::minutes(1));
69 | return EXIT_FAILURE;
70 | }
71 |
72 | // Create Device.
73 | Microsoft::WRL::ComPtr device;
74 | if (FAILED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device))))
75 | {
76 | fwprintf_s(stderr, L"ID3D12Device creation FAILED for \"%ls\".\n", adapterDescriptor.Description);
77 |
78 | std::this_thread::sleep_for(std::chrono::minutes(1));
79 | return EXIT_FAILURE;
80 | }
81 |
82 | // Stabilize power state.
83 | if (FAILED(device->SetStablePowerState(TRUE)))
84 | {
85 | fwprintf_s(stderr, L"SetStablePowerState(TRUE) FAILED for \"%ls\" adapter.\n", adapterDescriptor.Description);
86 |
87 | std::this_thread::sleep_for(std::chrono::minutes(1));
88 | return EXIT_FAILURE;
89 | }
90 |
91 | fwprintf_s(stdout, L"SetStablePowerState(TRUE) SUCCEEDED for \"%ls\" adapter.\n", adapterDescriptor.Description);
92 | fprintf_s(stdout, "Clock will remain stable while the application is running.\n");
93 |
94 | // Turning off the application reverts the clock.
95 | std::this_thread::sleep_for(std::chrono::hours(1));
96 | return EXIT_SUCCESS;
97 | }
98 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # CMake
2 | CMakeCache.txt
3 | CMakeFiles
4 | CMakeScripts
5 | Testing
6 | Makefile
7 | cmake_install.cmake
8 | install_manifest.txt
9 | compile_commands.json
10 | CTestTestfile.cmake
11 | *.tcl
12 | *_autogen
13 | *.dir
14 | build/
15 | visualstudio/
16 | xcode/
17 | androidstudio/
18 | make/
19 | webassembly/
20 |
21 | ## Visual Studio
22 | # User-specific files
23 | *.vs
24 | *.vscode
25 | *.sln
26 | *.vcxproj
27 | *.filters
28 | *.suo
29 | *.user
30 | *.userosscache
31 | *.sln.docstates
32 |
33 |
34 | # User-specific files (MonoDevelop/Xamarin Studio)
35 | *.userprefs
36 |
37 | # Build results
38 | [Dd]ebug/
39 | [Dd]ebugPublic/
40 | [Rr]elease/
41 | [Rr]eleases/
42 | x64/
43 | x86/
44 | bld/
45 | [Bb]in/
46 | [Oo]bj/
47 | [Ll]og/
48 |
49 | # Windows
50 |
51 | *.DS_Store
52 |
53 | # Visual Studio 2015 cache/options directory
54 | .vs/
55 | # Uncomment if you have tasks that create the project's static files in wwwroot
56 | #wwwroot/
57 |
58 | # MSTest test Results
59 | [Tt]est[Rr]esult*/
60 | [Bb]uild[Ll]og.*
61 |
62 | # NUNIT
63 | *.VisualState.xml
64 | TestResult.xml
65 |
66 | # Build Results of an ATL Project
67 | [Dd]ebugPS/
68 | [Rr]eleasePS/
69 | dlldata.c
70 |
71 | # Benchmark Results
72 | BenchmarkDotNet.Artifacts/
73 |
74 | # .NET Core
75 | project.lock.json
76 | project.fragment.lock.json
77 | artifacts/
78 | **/Properties/launchSettings.json
79 |
80 | *_i.c
81 | *_p.c
82 | *_i.h
83 | *.ilk
84 | *.meta
85 | *.obj
86 | *.pch
87 | *.pdb
88 | *.pgc
89 | *.pgd
90 | *.rsp
91 | *.sbr
92 | *.tlb
93 | *.tli
94 | *.tlh
95 | *.tmp
96 | *.tmp_proj
97 | *.log
98 | *.vspscc
99 | *.vssscc
100 | .builds
101 | *.pidb
102 | *.svclog
103 | *.scc
104 |
105 | # Chutzpah Test files
106 | _Chutzpah*
107 |
108 | # Visual C++ cache files
109 | ipch/
110 | *.aps
111 | *.ncb
112 | *.opendb
113 | *.opensdf
114 | *.sdf
115 | *.cachefile
116 | *.VC.db
117 | *.VC.VC.opendb
118 |
119 | # Visual Studio profiler
120 | *.psess
121 | *.vsp
122 | *.vspx
123 | *.sap
124 |
125 | # TFS 2012 Local Workspace
126 | $tf/
127 |
128 | # Guidance Automation Toolkit
129 | *.gpState
130 |
131 | # ReSharper is a .NET coding add-in
132 | _ReSharper*/
133 | *.[Rr]e[Ss]harper
134 | *.DotSettings.user
135 |
136 | # JustCode is a .NET coding add-in
137 | .JustCode
138 |
139 | # TeamCity is a build add-in
140 | _TeamCity*
141 |
142 | # DotCover is a Code Coverage Tool
143 | *.dotCover
144 |
145 | # Visual Studio code coverage results
146 | *.coverage
147 | *.coveragexml
148 |
149 | # NCrunch
150 | _NCrunch_*
151 | .*crunch*.local.xml
152 | nCrunchTemp_*
153 |
154 | # MightyMoose
155 | *.mm.*
156 | AutoTest.Net/
157 |
158 | # Web workbench (sass)
159 | .sass-cache/
160 |
161 | # Installshield output folder
162 | [Ee]xpress/
163 |
164 | # DocProject is a documentation generator add-in
165 | DocProject/buildhelp/
166 | DocProject/Help/*.HxT
167 | DocProject/Help/*.HxC
168 | DocProject/Help/*.hhc
169 | DocProject/Help/*.hhk
170 | DocProject/Help/*.hhp
171 | DocProject/Help/Html2
172 | DocProject/Help/html
173 |
174 | # Click-Once directory
175 | publish/
176 |
177 | # Publish Web Output
178 | *.[Pp]ublish.xml
179 | *.azurePubxml
180 | # Note: Comment the next line if you want to checkin your web deploy settings,
181 | # but database connection strings (with potential passwords) will be unencrypted
182 | *.pubxml
183 | *.publishproj
184 |
185 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
186 | # checkin your Azure Web App publish settings, but sensitive information contained
187 | # in these scripts will be unencrypted
188 | PublishScripts/
189 |
190 | # NuGet Packages
191 | *.nupkg
192 | # The packages folder can be ignored because of Package Restore
193 | **/packages/*
194 | # except build/, which is used as an MSBuild target.
195 | !**/packages/build/
196 | # Uncomment if necessary however generally it will be regenerated when needed
197 | #!**/packages/repositories.config
198 | # NuGet v3's project.json files produces more ignorable files
199 | *.nuget.props
200 | *.nuget.targets
201 |
202 | # Microsoft Azure Build Output
203 | csx/
204 | *.build.csdef
205 |
206 | # Microsoft Azure Emulator
207 | ecf/
208 | rcf/
209 |
210 | # Windows Store app package directories and files
211 | AppPackages/
212 | BundleArtifacts/
213 | Package.StoreAssociation.xml
214 | _pkginfo.txt
215 | *.appx
216 |
217 | # Visual Studio cache files
218 | # files ending in .cache can be ignored
219 | *.[Cc]ache
220 | # but keep track of directories ending in .cache
221 | !*.[Cc]ache/
222 |
223 | # Others
224 | ClientBin/
225 | ~$*
226 | *~
227 | *.dbmdl
228 | *.dbproj.schemaview
229 | *.jfm
230 | *.pfx
231 | *.publishsettings
232 | orleans.codegen.cs
233 |
234 | # Since there are multiple workflows, uncomment next line to ignore bower_components
235 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
236 | #bower_components/
237 |
238 | # RIA/Silverlight projects
239 | Generated_Code/
240 |
241 | # Backup & report files from converting an old project file
242 | # to a newer Visual Studio version. Backup files are not needed,
243 | # because we have git
244 | _UpgradeReport_Files/
245 | Backup*/
246 | UpgradeLog*.XML
247 | UpgradeLog*.htm
248 |
249 | # SQL Server files
250 | *.mdf
251 | *.ldf
252 | *.ndf
253 |
254 | # Business Intelligence projects
255 | *.rdl.data
256 | *.bim.layout
257 | *.bim_*.settings
258 |
259 | # Microsoft Fakes
260 | FakesAssemblies/
261 |
262 | # GhostDoc plugin setting file
263 | *.GhostDoc.xml
264 |
265 | # Node.js Tools for Visual Studio
266 | .ntvs_analysis.dat
267 | node_modules/
268 |
269 | # Typescript v1 declaration files
270 | typings/
271 |
272 | # Visual Studio 6 build log
273 | *.plg
274 |
275 | # Visual Studio 6 workspace options file
276 | *.opt
277 |
278 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
279 | *.vbw
280 |
281 | # Visual Studio LightSwitch build output
282 | **/*.HTMLClient/GeneratedArtifacts
283 | **/*.DesktopClient/GeneratedArtifacts
284 | **/*.DesktopClient/ModelManifest.xml
285 | **/*.Server/GeneratedArtifacts
286 | **/*.Server/ModelManifest.xml
287 | _Pvt_Extensions
288 |
289 | # Paket dependency manager
290 | .paket/paket.exe
291 | paket-files/
292 |
293 | # FAKE - F# Make
294 | .fake/
295 |
296 | # JetBrains Rider
297 | .idea/
298 | *.sln.iml
299 |
300 | # CodeRush
301 | .cr/
302 |
303 | # Python Tools for Visual Studio (PTVS)
304 | __pycache__/
305 | *.pyc
306 |
307 | # Cake - Uncomment if you are using it
308 | # tools/**
309 | # !tools/packages.config
310 |
311 | # Tabs Studio
312 | *.tss
313 |
314 | # Telerik's JustMock configuration file
315 | *.jmconfig
316 |
317 | # BizTalk build output
318 | *.btp.cs
319 | *.btm.cs
320 | *.odx.cs
321 | *.xsd.cs
322 |
323 | # Xcode
324 | #
325 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
326 |
327 | ## Build generated
328 | build/
329 | DerivedData/
330 |
331 | ## Various settings
332 | *.pbxuser
333 | !default.pbxuser
334 | *.mode1v3
335 | !default.mode1v3
336 | *.mode2v3
337 | !default.mode2v3
338 | *.perspectivev3
339 | !default.perspectivev3
340 | xcuserdata/
341 |
342 | ## Other
343 | *.moved-aside
344 | *.xccheckout
345 | *.xcscmblueprint
346 | *.db
347 |
348 | ## Xcode
349 | *.xcworkspace
350 | *.xcodeproj
--------------------------------------------------------------------------------