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
2425namespace {
@@ -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+
499669void OnPresetOff () {
500670// renodx::utils::settings::UpdateSetting("ToneMapType", 0.f);
501671// renodx::utils::settings::UpdateSetting("ToneMapPeakNits", 1000.f);
@@ -520,6 +690,7 @@ void OnPresetOff() {
520690bool fired_on_init_swapchain = false ;
521691
522692void 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