[dxgi] Workaround UE4 DX11 + HDR crashes

Unreal Engine 4 titles use AGS/NVAPI to try and enable
HDR globally.
They can key this off IDXGIOutput::GetDesc1's ColorSpace
being HDR10.
Many of these UE4 games statically link against AGS.

This is a problem as when UE4 tries to enable HDR via AGS,
it does not check if AGSContext, and the display info etc
are nullptr unlike the rest of the code using AGS.
So we need to special-case UE4 titles to disable reporting a HDR
when they are in DX11 mode.

The simplest way to do this is to key off the fact that all
UE4 titles have an executable ending with "-Win64-Shipping".

We check if d3d12.dll is present, to determine what path in
UE4 we are on, as there are some games that ship both and support HDR.
(eg. The Dark Pictures: House of Ashes, 1281590)
Luckily for us, they only load d3d12.dll on the D3D12 render path
so we can key off that to force disable HDR only in D3D11.
This commit is contained in:
Joshua Ashton 2023-01-09 11:36:30 +00:00 committed by Joshie
parent 3ed0a4fd43
commit 5206d97710
1 changed files with 37 additions and 0 deletions

View File

@ -26,6 +26,39 @@ namespace dxvk {
return id;
}
static bool isHDRDisallowed() {
#ifdef _WIN32
// Unreal Engine 4 titles use AGS/NVAPI to try and enable
// HDR globally.
// The game checks IDXGIOutput::GetDesc1's ColorSpace
// being HDR10 to see if it should enable HDR.
// Many of these UE4 games statically link against AGS.
//
// This is a problem as when UE4 tries to enable HDR via AGS,
// it does not check if AGSContext, and the display info etc
// are nullptr unlike the rest of the code using AGS.
// So we need to special-case UE4 titles to disable reporting a HDR
// when they are in DX11 mode.
//
// The simplest way to do this is to key off the fact that all
// UE4 titles have an executable ending with "-Win64-Shipping".
//
// We check if d3d12.dll is present, to determine what path in
// UE4 we are on, as there are some games that ship both and support HDR.
// (eg. The Dark Pictures: House of Ashes, 1281590)
// Luckily for us, they only load d3d12.dll on the D3D12 render path
// so we can key off that to force disable HDR only in D3D11.
std::string exeName = env::getExeName();
bool isUE4 = exeName.find("-Win64-Shipping") != std::string::npos;
bool hasD3D12 = GetModuleHandleA("d3d12") != nullptr;
if (isUE4 && !hasD3D12)
return true;
#endif
return false;
}
DxgiOptions::DxgiOptions(const Config& config) {
// Fetch these as a string representing a hexadecimal number and parse it.
@ -47,6 +80,10 @@ namespace dxvk {
this->nvapiHack = config.getOption<bool>("dxgi.nvapiHack", true);
this->enableHDR = config.getOption<bool>("dxgi.enableHDR", env::getEnvVar("DXVK_HDR") == "1");
if (this->enableHDR && isHDRDisallowed()) {
Logger::info("HDR was configured to be enabled, but has been force disabled as a UE4 DX11 game was detected.");
this->enableHDR = false;
}
}
}