在 C++ 程式中要求系統使用獨立顯示卡

| | 2 Comments| 08:55
Categories:

Heresy 這邊有在透過 C++ / Qt / OpenGL 開發自己的 OpenVR 程式,在部屬給別人用的時候,一個很常見的問題,就是現在的電競筆電的顯示系統大多會是 iGPU(CPU 整合顯示晶片)加上 dGPU(獨立顯示晶片)的設計。

這樣的設計概念,主要是希望在一般使用較省電的 iGPU 來延長電池的使用時間,等到真的有需求的時候,再使用 dGPU 來拉高效能。

而一般來說,Windows 會優先使用 iGPU,如果要使用 dGPU 的話,則會需要使用者自行修改設定;修改的方法是在 Windows 的「設定」、「系統」、「顯示器」的頁面中,點選最下方的「圖形」,然後在「應用程式的自訂選項」修改既有設定、或手動加入應用程式。

下面就是設定的畫面:

但是,如果是以程式開發者的角度來說,其實不會希望還要使用者自己去修改設定啊!畢竟有的使用者根本不知道要怎麼改、也有可能改錯。(附帶一提,更早期應該是要在顯示卡驅動程式設定)

那該怎麼做呢?在GitHub Gist 上的《Trick to tell AMD and Nvidia drivers to use the most powerful GPU instead of a lower-performance (such as integrated) GPU》這個檔案,算是提供了一個 C++ 裡面很簡單的做法。

NVIDIA 的方案

以 NVIDIA 來說,可以參考滿早期就有的 NVIDIA Optimus 的相關文件(連結);裡面的說法是說在 302 版的驅動程式以後,都可以透過在程式中定義 NvOptimusEnablement 的值來做設定。

具體的寫法是:

extern "C" {
  __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}

如此一來,在 NVIDIA dGPU 搭配其他 iGPU 的系統上、應該就會預設改用 NVIDIA 的獨立顯示晶片了。

AMD 的方案

AMD 的話,對應的技術是 PowerXpress ,官方的說明則可以參考《Selecting the Best Graphics Device to Run a 3D Intensive Application》;他的方法類似,不過是變數名稱改成 AmdPowerXpressRequestHighPerformance 而已。

寫法是:

extern "C" {
  _declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
}

理論上也是這樣就可以了~


而如果兩個想一起考慮的話,其實可以寫成:

#ifdef _WIN32
// Use discrete GPU by default.
extern "C" {
  // https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm
  __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
 
  // https://gpuopen.com/learn/amdpowerxpressrequesthighperformance/
  _declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
}
#endif

基本上,Heresy 這邊測試應該是只要把這段程式加在程式碼裡面就可以了;而加上 #ifdef _WIN32 則是因為這個設定應該也只對 Windows 平台有用,其他平台該怎麼辦?恩,不知道。

以 NVIDIA dGPU + Intel iGPU 或 NVIDIA dGPU + AMD iGPU 的系統上,這樣做確實是可以如預期地運作的!至於 AMD 的部分,由於 Heresy 這邊沒有 AMD 顯卡,就只能跳過了。

另外,在 AMD 的文件也有提到,這個方法主要是針對 OpenGL 與 DirectX 的程式,對於 Vulkan 或 OpenCL 的程式來說,由於本來就需要自行決定要使用的裝置,所以不適用這個方法。

不過,個人其實比較好奇,這部分的管理目前應該已經從早期的顯示卡驅動程式變成是 Windows 系統了,那不知道 Windows 有沒有提供對應的 API 可以使用?找了一下,好像沒看到?


附帶一提,Windows 針對個別應用程式設定的資料會儲存在 registry 中,他的路徑是:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\DirectX\UserGpuPreferences

機碼名稱是應用程式的執行檔路徑加上檔名,而值則是「GpuPreference=0;」這樣的形式;這邊的數值,0 是代表由 Windows 判斷、1 是省電(iGPU)、2 是高效能(dGPU)。

所以如果要玩的話,或許也可以透過自動加入機碼的方法、來指定要使用的 GPU?

2 thoughts on “在 C++ 程式中要求系統使用獨立顯示卡”

  1. 感謝Heresy大的分享,沒想到原來這部分是可以透過顯示器的圖形自己調整,原本以為只能用關閉硬體或是用顯卡APP的方式處理,一直活在Win7時期的腦袋真的該更新了,沒想到現在系統本身已經可以自行調配內外顯設定,這樣真的很方便,不然有時候出去談案子不一定都有插座可以用,使用獨顯的時候耗電速度真的夭壽快,還好有看到這篇,不然我可能一輩子都不知道這個東西 哈哈。

    1. Windows 10 / 11 現在對於多顯示卡的支援性已經算是相對好的了,使用上算是滿彈性的。

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *