├── .gitattributes ├── .github └── workflows │ └── go.yml ├── LICENSE.md ├── README.md ├── go.mod ├── preferdiscretegpu.go ├── preferdiscretegpu_windows.def ├── preferdiscretegpu_windows.go └── testapp └── main.go /.gitattributes: -------------------------------------------------------------------------------- 1 | # Use Unix line endings in all text files. 2 | # This helps prevent inconsistency issues with Windows Git configurations vs Linux 3 | * text=auto eol=lf 4 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | on: [push, pull_request] 3 | jobs: 4 | windows: 5 | runs-on: windows-latest 6 | strategy: 7 | matrix: 8 | go: ['1.12', '1.13', '1.14'] 9 | name: Go ${{ matrix.go }} on Windows 10 | steps: 11 | - name: Check out code into the Go module directory 12 | uses: actions/checkout@v2 13 | 14 | - name: Setup Go 15 | uses: actions/setup-go@v2 16 | with: 17 | go-version: ${{ matrix.go }} 18 | 19 | - name: Build 20 | shell: bash 21 | run: | 22 | go build -v -o testapp.exe ./testapp 23 | 24 | - name: Test 25 | shell: cmd 26 | run: | 27 | call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" 28 | dumpbin /exports testapp.exe > dumpbin_output.txt 29 | grep -q AmdPowerXpressRequestHighPerformance "dumpbin_output.txt" 30 | grep -q NvOptimusEnablement "dumpbin_output.txt" 31 | 32 | macos: 33 | runs-on: macOS-latest 34 | strategy: 35 | matrix: 36 | go: ['1.12'] 37 | name: Go ${{ matrix.go }} on MacOS 38 | steps: 39 | - name: Check out code into the Go module directory 40 | uses: actions/checkout@v2 41 | 42 | - name: Setup Go 43 | uses: actions/setup-go@v2 44 | with: 45 | go-version: ${{ matrix.go }} 46 | 47 | - name: Build 48 | run: | 49 | go build -v -o test ./testapp 50 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2020 Jae Bentvelzen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Prefer Discrete GPU 2 | 3 | [![Actions Status](https://github.com/silbinarywolf/preferdiscretegpu/workflows/Go/badge.svg)](https://github.com/silbinarywolf/preferdiscretegpu/actions) 4 | 5 | **This is a CGo package. Unfortunately there is no way to enable this behaviour without CGo as of Go 1.14** 6 | 7 | For laptops with multiple GPUs, its likely that applications won't launch using the discrete GPU on Windows, but rather the integrated GPU. This can lead to real-time applications like games under-performing by default, which is not the ideal user experience. 8 | 9 | This library exports global variables for NVIDIA and AMD drivers so that they use high performance graphics rendering settings. 10 | 11 | ## Install 12 | 13 | ``` 14 | go get github.com/silbinarywolf/preferdiscretegpu 15 | ``` 16 | 17 | ## Requirements 18 | 19 | * Golang 1.12+ 20 | 21 | ## How to use 22 | 23 | Just import the package for side-effects. This will have no additional behaviour on non-Windows systems. 24 | 25 | ```go 26 | package main 27 | 28 | import ( 29 | "fmt" 30 | 31 | _ "github.com/silbinarywolf/preferdiscretegpu" 32 | ) 33 | 34 | func main() { 35 | // your code here 36 | } 37 | ``` 38 | 39 | ## How to test if this package is working 40 | 41 | 1) Open up the Windows Command Line (not Powershell) and run the following: 42 | 43 | **NOTE: if you have have an older or newer version of Visual Studio installed, vcvarsall.bat will be in a different folder** 44 | ``` 45 | call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" 46 | ``` 47 | 48 | 2) Build the test application that consumes this library 49 | ``` 50 | go build -v -o testapp.exe ./testapp 51 | ``` 52 | 53 | 3) Run dumpbin on it: 54 | ``` 55 | dumpbin /exports testapp.exe 56 | ``` 57 | 58 | 4) It should give you an output mentioning the NVIDIA/AMD constants, like so: 59 | ``` 60 | Microsoft (R) COFF/PE Dumper Version 14.00.24213.1 61 | Copyright (C) Microsoft Corporation. All rights reserved. 62 | 63 | 64 | Dump of file testapp.exe 65 | 66 | File Type: EXECUTABLE IMAGE 67 | 68 | Section contains the following exports for a.out.exe 69 | 70 | 00000000 characteristics 71 | 5F153BFB time date stamp Mon Jul 20 16:38:51 2020 72 | 0.00 version 73 | 1 ordinal base 74 | 2 number of functions 75 | 2 number of names 76 | 77 | ordinal hint RVA name 78 | 79 | 1 0 000B6C00 AmdPowerXpressRequestHighPerformance 80 | 2 1 000B6C04 NvOptimusEnablement 81 | 82 | Summary 83 | 84 | 1000 .CRT 85 | 30000 .bss 86 | 15000 .data 87 | 1000 .debug_abbrev 88 | 1000 .debug_aranges 89 | 14000 .debug_frame 90 | 1000 .debug_gdb_scripts 91 | 82000 .debug_info 92 | 35000 .debug_line 93 | 88000 .debug_loc 94 | 9000 .debug_pubnames 95 | E000 .debug_pubtypes 96 | 30000 .debug_ranges 97 | 1000 .debug_str 98 | 1000 .edata 99 | 1000 .idata 100 | 1000 .pdata 101 | C7000 .rdata 102 | A000 .reloc 103 | A1000 .text 104 | 1000 .tls 105 | 1000 .xdata 106 | ``` 107 | 108 | ## Credits 109 | 110 | * [Hakan Guleryuz](https://groups.google.com/forum/#!topic/golang-nuts/7OHZcXUegF0) for documenting how they were able to export the NVIDIA/AMD variables in Golang and for giving information 111 | * [SFML Contributors](https://github.com/SFML/SFML/commit/9a453ed9e3846e9f7998295b8966428a9a0b86f6#diff-93134bfcdd8e19cbd5fe05a57a658950R63) for inspiring how this feature should be consumed (ie. opt-in imported package) 112 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/silbinarywolf/preferdiscretegpu 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /preferdiscretegpu.go: -------------------------------------------------------------------------------- 1 | package preferdiscretegpu 2 | 3 | // do nothing for all non-Windows platforms 4 | -------------------------------------------------------------------------------- /preferdiscretegpu_windows.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | NvOptimusEnablement @1 DATA 3 | AmdPowerXpressRequestHighPerformance @2 DATA 4 | -------------------------------------------------------------------------------- /preferdiscretegpu_windows.go: -------------------------------------------------------------------------------- 1 | package preferdiscretegpu 2 | 3 | /* 4 | #cgo LDFLAGS: -L${SRCDIR}/preferdiscretegpu_windows.def 5 | 6 | __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; 7 | __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; 8 | */ 9 | import "C" 10 | -------------------------------------------------------------------------------- /testapp/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | _ "github.com/silbinarywolf/preferdiscretegpu" 7 | ) 8 | 9 | func main() { 10 | fmt.Printf(` 11 | This application should not be run to determine if the NVIDIA/AMD flags were set. 12 | It should have "dumpbin" run against it and return something like the following: 13 | 14 | Dump of file defaultgputest.exe 15 | 16 | File Type: EXECUTABLE IMAGE 17 | 18 | Section contains the following exports for a.out.exe 19 | 20 | 00000000 characteristics 21 | 5F15303A time date stamp Mon Jul 20 15:48:42 2020 22 | 0.00 version 23 | 1 ordinal base 24 | 2 number of functions 25 | 2 number of names 26 | 27 | ordinal hint RVA name 28 | 29 | 1 0 0006B820 AmdPowerXpressRequestHighPerformance 30 | 2 1 0006B824 NvOptimusEnablement 31 | 32 | Summary 33 | 34 | 1000 .CRT 35 | 30000 .bss 36 | 4000 .data 37 | 1000 .debug_abbrev 38 | 1000 .debug_aranges 39 | C000 .debug_frame 40 | 1000 .debug_gdb_scripts 41 | 56000 .debug_info 42 | 22000 .debug_line 43 | 5C000 .debug_loc 44 | 3000 .debug_pubnames 45 | A000 .debug_pubtypes 46 | 20000 .debug_ranges 47 | 1000 .debug_str 48 | 1000 .edata 49 | 1000 .idata 50 | 1000 .pdata 51 | 7E000 .rdata 52 | 6000 .reloc 53 | 67000 .text 54 | 1000 .tls 55 | 1000 .xdata 56 | 57 | `) 58 | } 59 | --------------------------------------------------------------------------------