Skip to content

Commit 6214ae9

Browse files
committed
fix(dragonsdogma2): block amd freesync hdr support from being reported to the game, fixing HDR for AMD GPUs on freesync premium pro displays
1 parent b97d4c6 commit 6214ae9

1 file changed

Lines changed: 173 additions & 3 deletions

File tree

src/games/dragonsdogma2/addon.cpp

Lines changed: 173 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "../../utils/settings.hpp"
2020
#include "../../utils/swapchain.hpp"
2121
#include "../../utils/random.hpp"
22+
#include "../../utils/vtable.hpp"
2223
#include "./shared.h"
2324

2425
namespace {
@@ -496,6 +497,175 @@ renodx::utils::settings::Settings settings = {
496497
}
497498
};
498499

500+
float hide_freesync_hdr = 1.f;
501+
502+
constexpr int AMD_AGS_SUCCESS = 0;
503+
constexpr int AMD_AGS_FAILURE = 1;
504+
505+
struct AmdAgsRect {
506+
int offset_x;
507+
int offset_y;
508+
int width;
509+
int height;
510+
};
511+
512+
struct AmdAgsDisplayInfo {
513+
char name[256];
514+
char display_device_name[32];
515+
unsigned int is_primary_display : 1;
516+
unsigned int hdr10 : 1;
517+
unsigned int dolby_vision : 1;
518+
unsigned int freesync : 1;
519+
unsigned int freesync_hdr : 1;
520+
unsigned int eyefinity_in_group : 1;
521+
unsigned int eyefinity_preferred_display : 1;
522+
unsigned int eyefinity_in_portrait_mode : 1;
523+
unsigned int reserved_padding : 24;
524+
int max_resolution_x;
525+
int max_resolution_y;
526+
float max_refresh_rate;
527+
AmdAgsRect current_resolution;
528+
AmdAgsRect visible_resolution;
529+
float current_refresh_rate;
530+
int eyefinity_grid_coord_x;
531+
int eyefinity_grid_coord_y;
532+
double chromaticity_red_x;
533+
double chromaticity_red_y;
534+
double chromaticity_green_x;
535+
double chromaticity_green_y;
536+
double chromaticity_blue_x;
537+
double chromaticity_blue_y;
538+
double chromaticity_white_point_x;
539+
double chromaticity_white_point_y;
540+
double screen_diffuse_reflectance;
541+
double screen_specular_reflectance;
542+
double min_luminance;
543+
double max_luminance;
544+
double avg_luminance;
545+
int logical_display_index;
546+
int adl_adapter_index;
547+
int reserved;
548+
};
549+
550+
struct AmdAgsDeviceInfo {
551+
const char* adapter_string;
552+
int asic_family;
553+
unsigned int is_apu : 1;
554+
unsigned int is_primary_device : 1;
555+
unsigned int is_external : 1;
556+
unsigned int reserved_padding : 29;
557+
int vendor_id;
558+
int device_id;
559+
int revision_id;
560+
int num_cus;
561+
int num_wgps;
562+
int num_rops;
563+
int core_clock;
564+
int memory_clock;
565+
int memory_bandwidth;
566+
float tera_flops;
567+
unsigned long long local_memory_in_bytes;
568+
unsigned long long shared_memory_in_bytes;
569+
int num_displays;
570+
AmdAgsDisplayInfo* displays;
571+
int eyefinity_enabled;
572+
int eyefinity_grid_width;
573+
int eyefinity_grid_height;
574+
int eyefinity_resolution_x;
575+
int eyefinity_resolution_y;
576+
int eyefinity_bezel_compensated;
577+
int adl_adapter_index;
578+
int reserved;
579+
};
580+
581+
struct AmdAgsGpuInfo {
582+
const char* driver_version;
583+
const char* radeon_software_version;
584+
int num_devices;
585+
AmdAgsDeviceInfo* devices;
586+
};
587+
588+
static void MaskAmdAgsGpuInfo(AmdAgsGpuInfo* gpu_info) {
589+
if (gpu_info == nullptr || gpu_info->devices == nullptr || hide_freesync_hdr == 0.f) return;
590+
if (gpu_info->num_devices < 0 || gpu_info->num_devices > 16) return;
591+
592+
bool masked = false;
593+
594+
for (int device_index = 0; device_index < gpu_info->num_devices; ++device_index) {
595+
auto& device_info = gpu_info->devices[device_index];
596+
if (device_info.displays == nullptr) continue;
597+
if (device_info.num_displays < 0 || device_info.num_displays > 32) continue;
598+
599+
for (int display_index = 0; display_index < device_info.num_displays; ++display_index) {
600+
auto& display_info = device_info.displays[display_index];
601+
if (display_info.freesync_hdr != 0u) {
602+
display_info.freesync_hdr = 0u;
603+
masked = true;
604+
}
605+
}
606+
}
607+
608+
if (masked) {
609+
static bool logged = false;
610+
if (!logged) {
611+
logged = true;
612+
reshade::log::message(
613+
reshade::log::level::info,
614+
"Hiding AMD FreeSync Premium HDR support via AGS while preserving normal HDR10 support.");
615+
}
616+
}
617+
}
618+
619+
using PfnAgsInitialize = int (*)(int ags_version, const void* config, void** context, AmdAgsGpuInfo* gpu_info);
620+
using PfnAgsGetGpuInfo = int (*)(void* context, AmdAgsGpuInfo* gpu_info);
621+
622+
PfnAgsInitialize real_ags_initialize = nullptr;
623+
int HookAgsInitialize(int ags_version, const void* config, void** context, AmdAgsGpuInfo* gpu_info) {
624+
if (real_ags_initialize == nullptr) return AMD_AGS_FAILURE;
625+
626+
const auto result = real_ags_initialize(ags_version, config, context, gpu_info);
627+
if (result == AMD_AGS_SUCCESS) {
628+
MaskAmdAgsGpuInfo(gpu_info);
629+
}
630+
return result;
631+
}
632+
633+
PfnAgsGetGpuInfo real_ags_get_gpu_info = nullptr;
634+
int HookAgsGetGpuInfo(void* context, AmdAgsGpuInfo* gpu_info) {
635+
if (real_ags_get_gpu_info == nullptr) return AMD_AGS_FAILURE;
636+
637+
const auto result = real_ags_get_gpu_info(context, gpu_info);
638+
if (result == AMD_AGS_SUCCESS) {
639+
MaskAmdAgsGpuInfo(gpu_info);
640+
}
641+
return result;
642+
}
643+
644+
void SetupPrototypeHooks() {
645+
static bool setup_complete = false;
646+
static renodx::utils::vtable::HookItem g_ags_hook_items[] = {
647+
{"agsInitialize", reinterpret_cast<void**>(&real_ags_initialize), reinterpret_cast<void*>(&HookAgsInitialize)},
648+
{"agsGetGPUInfo", reinterpret_cast<void**>(&real_ags_get_gpu_info), reinterpret_cast<void*>(&HookAgsGetGpuInfo)},
649+
};
650+
651+
if (setup_complete) return;
652+
653+
HMODULE h_ags = GetModuleHandleW(L"amd_ags_x64.dll");
654+
if (h_ags == nullptr) {
655+
h_ags = GetModuleHandleW(L"amd_ags.dll");
656+
}
657+
if (h_ags == nullptr) {
658+
return;
659+
}
660+
661+
if (!renodx::utils::vtable::Hook(h_ags, g_ags_hook_items)) {
662+
reshade::log::message(reshade::log::level::error, "Failed to hook AMD AGS FreeSync HDR capability queries");
663+
return;
664+
}
665+
666+
setup_complete = true;
667+
}
668+
499669
void OnPresetOff() {
500670
// renodx::utils::settings::UpdateSetting("ToneMapType", 0.f);
501671
// renodx::utils::settings::UpdateSetting("ToneMapPeakNits", 1000.f);
@@ -520,6 +690,7 @@ void OnPresetOff() {
520690
bool fired_on_init_swapchain = false;
521691

522692
void OnInitSwapchain(reshade::api::swapchain* swapchain, bool resize) {
693+
SetupPrototypeHooks();
523694

524695
auto peak = renodx::utils::swapchain::GetPeakNits(swapchain);
525696
if (peak.has_value()) {
@@ -540,7 +711,8 @@ BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) {
540711
switch (fdw_reason) {
541712
case DLL_PROCESS_ATTACH:
542713
if (!reshade::register_addon(h_module)) return FALSE;
543-
reshade::register_event<reshade::addon_event::init_swapchain>(OnInitSwapchain);
714+
SetupPrototypeHooks();
715+
reshade::register_event<reshade::addon_event::init_swapchain>(OnInitSwapchain);
544716
// while (IsDebuggerPresent() == 0) Sleep(100);
545717

546718
renodx::mods::shader::expected_constant_buffer_space = 50;
@@ -571,8 +743,6 @@ BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) {
571743
// .new_format = reshade::api::format::r16g16b16a16_float,
572744
// });
573745

574-
reshade::register_event<reshade::addon_event::init_swapchain>(OnInitSwapchain);
575-
576746
break;
577747
case DLL_PROCESS_DETACH:
578748
reshade::unregister_event<reshade::addon_event::init_swapchain>(OnInitSwapchain);

0 commit comments

Comments
 (0)