Increase compatibility of FSR 4 model preset selection

This commit is contained in:
FakeMichau
2026-02-25 23:41:54 +01:00
parent a718e40b30
commit 079563c4ce
6 changed files with 105 additions and 52 deletions
+1 -1
View File
@@ -972,7 +972,7 @@ static void CheckWorkingMode()
if (ffxDx12SRModule != nullptr)
{
LOG_DEBUG("amd_fidelityfx_upscaler_dx12.dll already in memory");
FSR4ModelSelection::Hook(ffxDx12SRModule, true);
FSR4ModelSelection::Hook(ffxDx12SRModule, FSR4Source::SDK);
FfxApiProxy::InitFfxDx12_SR(ffxDx12SRModule);
}
+75 -31
View File
@@ -4,7 +4,8 @@
#include <detours/detours.h>
PFN_getModelBlob FSR4ModelSelection::o_getModelBlob = nullptr;
PFN_createModel FSR4ModelSelection::o_createModel = nullptr;
PFN_createModel FSR4ModelSelection::o_createModelSDK = nullptr;
PFN_createModel FSR4ModelSelection::o_createModelDriver = nullptr;
uint32_t getCorrectedPreset(uint32_t preset)
{
@@ -43,26 +44,36 @@ uint64_t FSR4ModelSelection::hkgetModelBlob(uint32_t preset, uint64_t unknown, u
return result;
}
uint64_t FSR4ModelSelection::hkcreateModel(void* context, uint32_t preset)
uint64_t FSR4ModelSelection::hkcreateModelSDK(void* context, uint32_t preset)
{
LOG_FUNC();
preset = getCorrectedPreset(preset);
auto result = o_createModel(context, preset);
auto result = o_createModelSDK(context, preset);
return result;
}
void FSR4ModelSelection::Hook(HMODULE module, bool unhookOld)
uint64_t FSR4ModelSelection::hkcreateModelDriver(void* context, uint32_t preset)
{
LOG_FUNC();
preset = getCorrectedPreset(preset);
auto result = o_createModelDriver(context, preset);
return result;
}
void FSR4ModelSelection::Hook(HMODULE module, FSR4Source source)
{
if (module == nullptr)
return;
if (unhookOld && (o_getModelBlob || o_createModel))
if (o_getModelBlob)
{
LOG_DEBUG("Unhooking old model selection hooks, o_getModelBlob: {:X}, o_createModel: {:X}",
(uintptr_t) o_getModelBlob, (uintptr_t) o_createModel);
LOG_DEBUG("Unhooking old model selection hooks");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
@@ -70,18 +81,24 @@ void FSR4ModelSelection::Hook(HMODULE module, bool unhookOld)
if (o_getModelBlob != nullptr)
DetourDetach(&(PVOID&) o_getModelBlob, hkgetModelBlob);
if (o_createModel != nullptr)
DetourDetach(&(PVOID&) o_createModel, hkcreateModel);
if (o_createModelSDK && source == FSR4Source::SDK)
DetourDetach(&(PVOID&) o_createModelSDK, hkcreateModelSDK);
else if (o_createModelDriver && source == FSR4Source::DriverDll)
DetourDetach(&(PVOID&) o_createModelDriver, hkcreateModelDriver);
if (DetourTransactionCommit() == 0)
{
LOG_DEBUG("Unhooked old model selection hooks");
o_getModelBlob = nullptr;
o_createModel = nullptr;
if (source == FSR4Source::SDK)
o_createModelSDK = nullptr;
else if (source == FSR4Source::DriverDll)
o_createModelDriver = nullptr;
}
}
if (o_getModelBlob == nullptr && o_createModel == nullptr)
if (o_getModelBlob == nullptr)
{
const char* pattern = "83 F9 05 0F 87";
o_getModelBlob = (PFN_getModelBlob) scanner::GetAddress(module, pattern);
@@ -97,30 +114,57 @@ void FSR4ModelSelection::Hook(HMODULE module, bool unhookOld)
DetourTransactionCommit();
}
else
}
const char* pattern403 =
"48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 0F 29 B4 24 "
"? ? ? ? 0F 29 BC 24 ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 44 8B F2";
if (!o_createModelSDK && source == FSR4Source::SDK)
{
// From amd_fidelityfx_upscaler_dx12 4.0.3.604
o_createModelSDK = (PFN_createModel) scanner::GetAddress(module, pattern403);
LOG_DEBUG("Hooking model selection, o_createModelSDK: {:X}", (uintptr_t) o_createModelSDK);
if (o_createModelSDK)
{
// From amd_fidelityfx_upscaler_dx12 4.0.3.604
const char* pattern =
"48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 0F "
"29 B4 24 ? ? ? ? 0F 29 BC 24 ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 44 8B F2";
o_createModel = (PFN_createModel) scanner::GetAddress(module, pattern);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (o_createModel)
{
LOG_DEBUG("Hooking model selection, o_createModel: {:X}", (uintptr_t) o_createModel);
DetourAttach(&(PVOID&) o_createModelSDK, hkcreateModelSDK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&) o_createModel, hkcreateModel);
DetourTransactionCommit();
}
else
{
LOG_ERROR("Couldn't hook model selection");
}
DetourTransactionCommit();
}
else
LOG_ERROR("Couldn't hook model selection");
}
else if (!o_createModelDriver && source == FSR4Source::DriverDll)
{
o_createModelDriver = (PFN_createModel) scanner::GetAddress(module, pattern403);
if (!o_createModelDriver)
{
// From amdxcffx64 2.1.0.968
const char* pattern = "48 8B C4 48 89 58 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? "
"? ? 0F 29 70 ? 0F 29 78 ? 48 8B 05";
o_createModelDriver = (PFN_createModel) scanner::GetAddress(module, pattern);
}
if (o_createModelDriver)
{
LOG_DEBUG("Hooking model selection, o_createModelDriver: {:X}", (uintptr_t) o_createModelDriver);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&) o_createModelDriver, hkcreateModelDriver);
DetourTransactionCommit();
}
else
LOG_ERROR("Couldn't hook model selection");
}
else
{
+11 -3
View File
@@ -5,13 +5,21 @@
typedef uint64_t (*PFN_getModelBlob)(uint32_t preset, uint64_t unknown, uint64_t* source, uint64_t* size);
typedef uint64_t (*PFN_createModel)(void* context, uint32_t preset);
enum class FSR4Source
{
SDK,
DriverDll,
};
class FSR4ModelSelection
{
static uint64_t hkgetModelBlob(uint32_t preset, uint64_t unknown, uint64_t* source, uint64_t* size);
static PFN_getModelBlob o_getModelBlob;
static uint64_t hkcreateModel(void* context, uint32_t preset);
static PFN_createModel o_createModel;
static uint64_t hkcreateModelSDK(void* context, uint32_t preset);
static uint64_t hkcreateModelDriver(void* context, uint32_t preset);
static PFN_createModel o_createModelSDK;
static PFN_createModel o_createModelDriver;
public:
static void Hook(HMODULE module, bool unhookOld = true);
static void Hook(HMODULE module, FSR4Source source);
};
+16 -15
View File
@@ -28,7 +28,7 @@
#undef FFX_API_CONFIGURE_FG_SWAPCHAIN_KEY_FRAMEPACINGTUNING
static HMODULE moduleAmdxc64 = nullptr;
static HMODULE fsr4Module = nullptr;
static HMODULE moduleAmdxcffx64 = nullptr;
static AmdExtD3DDevice8* amdExtD3DDevice8 = nullptr;
static AmdExtD3DShaderIntrinsics* amdExtD3DShaderIntrinsics = nullptr;
@@ -233,21 +233,21 @@ struct AmdExtFfxApi : public IAmdExtFfxApi
if (o_UpdateFfxApiProvider == nullptr)
{
fsr4Module = NtdllProxy::LoadLibraryExW_Ldr(L"amdxcffx64.dll", NULL, 0);
moduleAmdxcffx64 = NtdllProxy::LoadLibraryExW_Ldr(L"amdxcffx64.dll", NULL, 0);
if (fsr4Module == nullptr)
if (moduleAmdxcffx64 == nullptr)
{
auto storePath = GetDriverStore();
for (size_t i = 0; i < storePath.size(); i++)
{
if (fsr4Module == nullptr)
if (moduleAmdxcffx64 == nullptr)
{
auto dllPath = storePath[i] / L"amdxcffx64.dll";
LOG_DEBUG("Trying to load: {}", wstring_to_string(dllPath.c_str()));
fsr4Module = NtdllProxy::LoadLibraryExW_Ldr(dllPath.c_str(), NULL, 0);
moduleAmdxcffx64 = NtdllProxy::LoadLibraryExW_Ldr(dllPath.c_str(), NULL, 0);
if (fsr4Module != nullptr)
if (moduleAmdxcffx64 != nullptr)
{
LOG_INFO(L"amdxcffx64 loaded from {}", dllPath.wstring());
break;
@@ -260,7 +260,7 @@ struct AmdExtFfxApi : public IAmdExtFfxApi
LOG_INFO("amdxcffx64 loaded from game folder");
}
if (fsr4Module == nullptr)
if (moduleAmdxcffx64 == nullptr)
{
LOG_ERROR("Failed to load amdxcffx64.dll");
return E_NOINTERFACE;
@@ -269,15 +269,16 @@ struct AmdExtFfxApi : public IAmdExtFfxApi
auto sdk2upscalingModule = KernelBaseProxy::GetModuleHandleA_()("amd_fidelityfx_upscaler_dx12.dll");
constexpr bool unhookOld = false;
if (sdk2upscalingModule != nullptr)
FSR4ModelSelection::Hook(sdk2upscalingModule, unhookOld);
else
FSR4ModelSelection::Hook(fsr4Module, unhookOld);
if (sdk2upscalingModule)
FSR4ModelSelection::Hook(sdk2upscalingModule, FSR4Source::SDK);
if (moduleAmdxcffx64)
FSR4ModelSelection::Hook(moduleAmdxcffx64, FSR4Source::DriverDll);
o_UpdateFfxApiProvider =
(PFN_UpdateFfxApiProvider) KernelBaseProxy::GetProcAddress_()(fsr4Module, "UpdateFfxApiProvider");
o_UpdateFfxApiProviderEx =
(PFN_UpdateFfxApiProviderEx) KernelBaseProxy::GetProcAddress_()(fsr4Module, "UpdateFfxApiProviderEx");
(PFN_UpdateFfxApiProvider) KernelBaseProxy::GetProcAddress_()(moduleAmdxcffx64, "UpdateFfxApiProvider");
o_UpdateFfxApiProviderEx = (PFN_UpdateFfxApiProviderEx) KernelBaseProxy::GetProcAddress_()(
moduleAmdxcffx64, "UpdateFfxApiProviderEx");
if (o_UpdateFfxApiProvider == nullptr)
{
@@ -491,7 +492,7 @@ void InitFSR4Update()
}
}
HMODULE GetFSR4Module() { return fsr4Module; }
HMODULE GetFSR4Module() { return moduleAmdxcffx64; }
HRESULT STDMETHODCALLTYPE hkAmdExtD3DCreateInterface(IUnknown* pOuter, REFIID riid, void** ppvObject)
{
+1 -1
View File
@@ -455,7 +455,7 @@ HMODULE LibraryLoadHooks::LoadLibraryCheckW(std::wstring libName, LPCWSTR lpLibF
{
auto module = NtdllProxy::LoadLibraryExW_Ldr(libName.c_str(), NULL, 0);
FSR4ModelSelection::Hook(module, true);
FSR4ModelSelection::Hook(module, FSR4Source::SDK);
if (module != nullptr)
FfxApiProxy::InitFfxDx12_SR(module);
+1 -1
View File
@@ -321,7 +321,7 @@ class FfxApiProxy
if (upscaling_dx12.dll != nullptr)
{
LOG_INFO("{} loaded from exe folder", wstring_to_string(dllNames[i]));
FSR4ModelSelection::Hook(upscaling_dx12.dll);
FSR4ModelSelection::Hook(upscaling_dx12.dll, FSR4Source::SDK);
break;
}
}