forked from ge9/IddSampleDriver
-
-
Notifications
You must be signed in to change notification settings - Fork 158
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GPU fallback and XML + EDID update
- Loading branch information
Showing
2 changed files
with
331 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,129 @@ | ||
#pragma once | ||
|
||
// Anonymous namespace for usings | ||
namespace | ||
{ | ||
using namespace std; | ||
using namespace Microsoft::IndirectDisp; | ||
using namespace Microsoft::WRL; | ||
|
||
struct AdapterOption | ||
{ | ||
bool hasTargetAdapter{}; | ||
LUID adapterLuid{}; | ||
|
||
void load(const char* path) | ||
{ | ||
ifstream ifs{ path }; | ||
|
||
if (!ifs.is_open()) | ||
{ | ||
return; | ||
} | ||
#include <wrl/client.h> // For ComPtr | ||
#include <dxgi.h> // For IDXGIAdapter, IDXGIFactory1 | ||
#include <algorithm> // For sort | ||
|
||
using namespace std; | ||
using namespace Microsoft::WRL; | ||
|
||
// Structure to vector gpus | ||
struct GPUInfo { | ||
wstring name; // GPU name | ||
ComPtr<IDXGIAdapter> adapter;// COM pointer to the adapter | ||
DXGI_ADAPTER_DESC desc; // Adapter description | ||
}; | ||
|
||
// Sort function for GPUs by dedicated video memory | ||
bool CompareGPUs(const GPUInfo& a, const GPUInfo& b) { | ||
return a.desc.DedicatedVideoMemory > b.desc.DedicatedVideoMemory; | ||
} | ||
|
||
// Get a enumerate list of available GPUs | ||
vector<GPUInfo> getAvailableGPUs() { | ||
vector<GPUInfo> gpus; // Vector to hold all GPU's information | ||
|
||
ComPtr<IDXGIFactory1> factory; | ||
if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) { | ||
return gpus; | ||
} | ||
|
||
// Enumerate all adapters (GPUs) | ||
for (UINT i = 0;; i++) { | ||
ComPtr<IDXGIAdapter> adapter; | ||
if (!SUCCEEDED(factory->EnumAdapters(i, &adapter))) { | ||
break; | ||
} | ||
|
||
DXGI_ADAPTER_DESC desc; | ||
|
||
if (!SUCCEEDED(adapter->GetDesc(&desc))) { | ||
continue; | ||
} | ||
|
||
// Add the adapter information to the list | ||
GPUInfo info{ desc.Description, adapter, desc }; | ||
gpus.push_back(info); | ||
} | ||
|
||
return gpus; | ||
} | ||
|
||
class AdapterOption { | ||
public: | ||
bool hasTargetAdapter{}; // Indicates if a target adapter is selected | ||
LUID adapterLuid{}; // Adapter's unique identifier (LUID) | ||
wstring target_name{}; // Target adapter name | ||
|
||
std::string line; | ||
// Select the best GPU based on dedicated video memory | ||
wstring selectBestGPU() { | ||
auto gpus = getAvailableGPUs(); | ||
if (gpus.empty()) { | ||
return L""; // Error check for headless / vm | ||
} | ||
|
||
// Sort GPUs by dedicated video memory in descending order | ||
sort(gpus.begin(), gpus.end(), CompareGPUs); | ||
auto bestGPU = gpus.front(); // Get the GPU with the most memory | ||
|
||
return bestGPU.name; | ||
} | ||
|
||
// Load friendlyname from a file OR select the best GPU | ||
void load(const wchar_t* path) { | ||
ifstream ifs{ path }; | ||
|
||
if (!ifs.is_open()) { | ||
target_name = selectBestGPU(); | ||
} | ||
else { | ||
string line; | ||
getline(ifs, line); | ||
target_name.assign(line.begin(), line.end()); | ||
} | ||
|
||
std::wstring target_name{ line.begin(), line.end() }; | ||
// Find and set the adapter based on the target name | ||
if (!findAndSetAdapter(target_name)) { | ||
// If the adapter is not found, select the best GPU and retry | ||
target_name = selectBestGPU(); | ||
findAndSetAdapter(target_name); | ||
} | ||
} | ||
|
||
ComPtr<IDXGIFactory1> factory{}; | ||
if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) | ||
{ | ||
return; | ||
} | ||
// Set the target adapter from a given name and validate it | ||
void xmlprovide(const wstring& xtarg) { | ||
target_name = xtarg; | ||
if (!findAndSetAdapter(target_name)) { | ||
// If the adapter is not found, select the best GPU and retry | ||
target_name = selectBestGPU(); | ||
findAndSetAdapter(target_name); | ||
} | ||
} | ||
|
||
for (UINT i = 0;; i++) | ||
{ | ||
ComPtr<IDXGIAdapter> adapter{}; | ||
if (!SUCCEEDED(factory->EnumAdapters(i, &adapter))) | ||
{ | ||
break; | ||
} | ||
|
||
DXGI_ADAPTER_DESC desc; | ||
if (!SUCCEEDED(adapter->GetDesc(&desc))) | ||
{ | ||
break; | ||
} | ||
|
||
// We found our target | ||
if (_wcsicmp(target_name.c_str(), desc.Description) == 0) | ||
{ | ||
adapterLuid = desc.AdapterLuid; | ||
hasTargetAdapter = true; | ||
} | ||
} | ||
// Apply the adapter settings to the specified adapter | ||
void apply(const IDDCX_ADAPTER& adapter) { | ||
if (hasTargetAdapter && IDD_IS_FUNCTION_AVAILABLE(IddCxAdapterSetRenderAdapter)) { | ||
IDARG_IN_ADAPTERSETRENDERADAPTER arg{}; | ||
arg.PreferredRenderAdapter = adapterLuid; | ||
IddCxAdapterSetRenderAdapter(adapter, &arg); | ||
} | ||
} | ||
|
||
private: | ||
// Find and set the adapter by its name | ||
bool findAndSetAdapter(const wstring& adapterName) { | ||
auto gpus = getAvailableGPUs(); | ||
|
||
void apply(const IDDCX_ADAPTER& adapter) | ||
{ | ||
if (hasTargetAdapter) | ||
{ | ||
if (IDD_IS_FUNCTION_AVAILABLE(IddCxAdapterSetRenderAdapter)) | ||
{ | ||
IDARG_IN_ADAPTERSETRENDERADAPTER arg{}; | ||
arg.PreferredRenderAdapter = adapterLuid; | ||
|
||
IddCxAdapterSetRenderAdapter(adapter, &arg); | ||
} | ||
// Iterate through all available GPUs | ||
for (const auto& gpu : gpus) { | ||
if (_wcsicmp(gpu.name.c_str(), adapterName.c_str()) == 0) { | ||
adapterLuid = gpu.desc.AdapterLuid; // Set the adapter LUID | ||
hasTargetAdapter = true; // Indicate that a target adapter is selected | ||
return true; | ||
} | ||
} | ||
}; | ||
} | ||
|
||
hasTargetAdapter = false; // Indicate that no target adapter is selected | ||
return false; | ||
} | ||
}; |
Oops, something went wrong.