mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-09-21 21:05:41 +00:00
add pattern search for FSR2 inputs
This commit is contained in:
+316
-35
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
#include "scanner/scanner.h"
|
||||
|
||||
#include "resource.h"
|
||||
#include "NVNGX_Parameter.h"
|
||||
@@ -87,10 +88,14 @@ typedef FfxResourceTiny(*PFN_ffxGetResourceFromDX12Resource_Dx12)(ID3D12Resource
|
||||
typedef Fsr212::FfxErrorCode(*PFN_ffxFsr2GetInterfaceDX12)(Fsr212::FfxFsr2Interface212* fsr2Interface, ID3D12Device* device, void* scratchBuffer, size_t scratchBufferSize);
|
||||
|
||||
static PFN_ffxFsr2ContextCreate o_ffxFsr2ContextCreate_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextCreate o_ffxFsr2ContextCreate_Pattern_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextDispatch o_ffxFsr2ContextDispatch_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextDispatch o_ffxFsr2ContextDispatch_Pattern_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextDispatch o_ffxFsr20ContextDispatch_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextDispatch o_ffxFsr20ContextDispatch_Patern_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextDispatch o_ffxFsr2TinyContextDispatch_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextDestroy o_ffxFsr2ContextDestroy_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2ContextDestroy o_ffxFsr2ContextDestroy_Pattern_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2GetUpscaleRatioFromQualityMode o_ffxFsr2GetUpscaleRatioFromQualityMode_Dx12 = nullptr;
|
||||
static PFN_ffxFsr2GetRenderResolutionFromQualityMode o_ffxFsr2GetRenderResolutionFromQualityMode_Dx12 = nullptr;
|
||||
static PFN_ffxGetResourceFromDX12Resource_Dx12 o_ffxGetResourceFromDX12Resource_Dx12 = nullptr;
|
||||
@@ -101,6 +106,9 @@ static std::map<Fsr212::FfxFsr2Context*, NVSDK_NGX_Parameter*> _nvParams;
|
||||
static std::map<Fsr212::FfxFsr2Context*, NVSDK_NGX_Handle*> _contexts;
|
||||
static ID3D12Device* _d3d12Device = nullptr;
|
||||
static bool _nvnxgInited = false;
|
||||
static bool _skipCreate = false;
|
||||
static bool _skipDispatch = false;
|
||||
static bool _skipDestroy = false;
|
||||
static float qualityRatios[] = { 1.0, 1.5, 1.7, 2.0, 3.0 };
|
||||
|
||||
static bool CreateDLSSContext(Fsr212::FfxFsr2Context* handle, const Fsr212::FfxFsr2DispatchDescription* pExecParams)
|
||||
@@ -332,13 +340,15 @@ static std::optional<float> GetQualityOverrideRatioFfx(const Fsr212::FfxFsr2Qual
|
||||
return output;
|
||||
}
|
||||
|
||||
// FS2 Upscaler
|
||||
// FSR2 Upscaler
|
||||
static Fsr212::FfxErrorCode ffxFsr2ContextCreate_Dx12(Fsr212::FfxFsr2Context* context, Fsr212::FfxFsr2ContextDescription* contextDescription)
|
||||
{
|
||||
if (contextDescription == nullptr || contextDescription->device == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
_skipCreate = true;
|
||||
auto ccResult = o_ffxFsr2ContextCreate_Dx12(context, contextDescription);
|
||||
_skipCreate = false;
|
||||
|
||||
if (ccResult != Fsr212::FFX_OK)
|
||||
{
|
||||
@@ -410,11 +420,151 @@ static Fsr212::FfxErrorCode ffxFsr2ContextCreate_Dx12(Fsr212::FfxFsr2Context* co
|
||||
return Fsr212::FFX_OK;
|
||||
}
|
||||
|
||||
static Fsr212::FfxErrorCode ffxFsr2ContextCreate_Pattern_Dx12(Fsr212::FfxFsr2Context* context, Fsr212::FfxFsr2ContextDescription* contextDescription)
|
||||
{
|
||||
if (contextDescription == nullptr || contextDescription->device == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
auto ccResult = o_ffxFsr2ContextCreate_Pattern_Dx12(context, contextDescription);
|
||||
|
||||
if (_skipCreate)
|
||||
return ccResult;
|
||||
|
||||
if (ccResult != Fsr212::FFX_OK)
|
||||
{
|
||||
LOG_ERROR("ccResult: {:X}", (UINT)ccResult);
|
||||
return ccResult;
|
||||
}
|
||||
|
||||
// check for d3d12 device
|
||||
// to prevent crashes when game is using custom interface and
|
||||
if (_d3d12Device == nullptr)
|
||||
{
|
||||
auto bDevice = (ID3D12Device*)contextDescription->device;
|
||||
|
||||
for (size_t i = 0; i < Config::Instance()->d3d12Devices.size(); i++)
|
||||
{
|
||||
if (Config::Instance()->d3d12Devices[i] == bDevice)
|
||||
{
|
||||
_d3d12Device = bDevice;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if still no device use latest created one
|
||||
// Might fixed TLOU but FMF2 still crashes
|
||||
if (_d3d12Device == nullptr)
|
||||
_d3d12Device = Config::Instance()->d3d12Devices[Config::Instance()->d3d12Devices.size() - 1];
|
||||
|
||||
if (_d3d12Device == nullptr)
|
||||
{
|
||||
LOG_WARN("D3D12 device not found!");
|
||||
return ccResult;
|
||||
}
|
||||
|
||||
NVSDK_NGX_FeatureCommonInfo fcInfo{};
|
||||
wchar_t const** paths = new const wchar_t* [1];
|
||||
auto dllPath = Util::DllPath().remove_filename().wstring();
|
||||
paths[0] = dllPath.c_str();
|
||||
fcInfo.PathListInfo.Path = paths;
|
||||
fcInfo.PathListInfo.Length = 1;
|
||||
|
||||
if (!_nvnxgInited)
|
||||
{
|
||||
|
||||
auto nvResult = NVSDK_NGX_D3D12_Init_with_ProjectID("OptiScaler", NVSDK_NGX_ENGINE_TYPE_CUSTOM, VER_PRODUCT_VERSION_STR, dllPath.c_str(),
|
||||
_d3d12Device, &fcInfo, Config::Instance()->NVNGX_Version);
|
||||
|
||||
if (nvResult != NVSDK_NGX_Result_Success)
|
||||
return Fsr212::FFX_ERROR_BACKEND_API_ERROR;
|
||||
|
||||
_nvnxgInited = true;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Parameter* params = nullptr;
|
||||
|
||||
if (NVSDK_NGX_D3D12_GetCapabilityParameters(¶ms) != NVSDK_NGX_Result_Success)
|
||||
return Fsr212::FFX_ERROR_BACKEND_API_ERROR;
|
||||
|
||||
_nvParams[context] = params;
|
||||
|
||||
Fsr212::FfxFsr2ContextDescription ccd{};
|
||||
ccd.flags = contextDescription->flags;
|
||||
ccd.maxRenderSize = contextDescription->maxRenderSize;
|
||||
ccd.displaySize = contextDescription->displaySize;
|
||||
_initParams[context] = ccd;
|
||||
|
||||
LOG_INFO("context created: {:X}", (size_t)context);
|
||||
|
||||
return Fsr212::FFX_OK;
|
||||
}
|
||||
|
||||
// FSR2.1
|
||||
static Fsr212::FfxErrorCode ffxFsr2ContextDispatch_Dx12(Fsr212::FfxFsr2Context* context, const Fsr212::FfxFsr2DispatchDescription* dispatchDescription)
|
||||
{
|
||||
// Skip OptiScaler stuff
|
||||
if (!Config::Instance()->Fsr2Inputs.value_or(true))
|
||||
return o_ffxFsr2ContextDispatch_Dx12(context, dispatchDescription);
|
||||
{
|
||||
_skipDispatch = true;
|
||||
auto result = o_ffxFsr2ContextDispatch_Dx12(context, dispatchDescription);
|
||||
_skipDispatch = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (dispatchDescription == nullptr || context == nullptr || dispatchDescription->commandList == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
// If not in contexts list create and add context
|
||||
if (!_contexts.contains(context) && _initParams.contains(context) && !CreateDLSSContext(context, dispatchDescription))
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
NVSDK_NGX_Parameter* params = _nvParams[context];
|
||||
NVSDK_NGX_Handle* handle = _contexts[context];
|
||||
|
||||
params->Set(NVSDK_NGX_Parameter_Jitter_Offset_X, dispatchDescription->jitterOffset.x);
|
||||
params->Set(NVSDK_NGX_Parameter_Jitter_Offset_Y, dispatchDescription->jitterOffset.y);
|
||||
params->Set(NVSDK_NGX_Parameter_MV_Scale_X, dispatchDescription->motionVectorScale.x);
|
||||
params->Set(NVSDK_NGX_Parameter_MV_Scale_Y, dispatchDescription->motionVectorScale.y);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Exposure_Scale, 1.0);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Pre_Exposure, dispatchDescription->preExposure);
|
||||
params->Set(NVSDK_NGX_Parameter_Reset, dispatchDescription->reset ? 1 : 0);
|
||||
params->Set(NVSDK_NGX_Parameter_Width, dispatchDescription->renderSize.width);
|
||||
params->Set(NVSDK_NGX_Parameter_Height, dispatchDescription->renderSize.height);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width, dispatchDescription->renderSize.width);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Height, dispatchDescription->renderSize.height);
|
||||
params->Set(NVSDK_NGX_Parameter_Depth, dispatchDescription->depth.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_ExposureTexture, dispatchDescription->exposure.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, dispatchDescription->reactive.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_Color, dispatchDescription->color.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_MotionVectors, dispatchDescription->motionVectors.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_Output, dispatchDescription->output.resource);
|
||||
params->Set("FSR.cameraNear", dispatchDescription->cameraNear);
|
||||
params->Set("FSR.cameraFar", dispatchDescription->cameraFar);
|
||||
params->Set("FSR.cameraFovAngleVertical", dispatchDescription->cameraFovAngleVertical);
|
||||
params->Set("FSR.frameTimeDelta", dispatchDescription->frameTimeDelta);
|
||||
params->Set("FSR.transparencyAndComposition", dispatchDescription->transparencyAndComposition.resource);
|
||||
params->Set("FSR.reactive", dispatchDescription->reactive.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_Sharpness, dispatchDescription->sharpness);
|
||||
|
||||
LOG_DEBUG("handle: {:X}, internalResolution: {}x{}", handle->Id, dispatchDescription->renderSize.width, dispatchDescription->renderSize.height);
|
||||
|
||||
Config::Instance()->setInputApiName = "FSR2.X-DX12";
|
||||
|
||||
auto evalResult = NVSDK_NGX_D3D12_EvaluateFeature((ID3D12GraphicsCommandList*)dispatchDescription->commandList, handle, params, nullptr);
|
||||
|
||||
if (evalResult == NVSDK_NGX_Result_Success)
|
||||
return Fsr212::FFX_OK;
|
||||
|
||||
LOG_ERROR("evalResult: {:X}", (UINT)evalResult);
|
||||
return Fsr212::FFX_ERROR_BACKEND_API_ERROR;
|
||||
}
|
||||
|
||||
static Fsr212::FfxErrorCode ffxFsr2ContextDispatch_Pattern_Dx12(Fsr212::FfxFsr2Context* context, const Fsr212::FfxFsr2DispatchDescription* dispatchDescription)
|
||||
{
|
||||
// Skip OptiScaler stuff
|
||||
if (!Config::Instance()->Fsr2Inputs.value_or(true) || _skipDispatch)
|
||||
return o_ffxFsr2ContextDispatch_Pattern_Dx12(context, dispatchDescription);
|
||||
|
||||
if (dispatchDescription == nullptr || context == nullptr || dispatchDescription->commandList == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
@@ -469,7 +619,67 @@ static Fsr212::FfxErrorCode ffxFsr20ContextDispatch_Dx12(Fsr212::FfxFsr2Context*
|
||||
{
|
||||
// Skip OptiScaler stuff
|
||||
if (!Config::Instance()->Fsr2Inputs.value_or(true))
|
||||
return o_ffxFsr20ContextDispatch_Dx12(context, dispatchDescription);
|
||||
{
|
||||
_skipDispatch = true;
|
||||
auto result = o_ffxFsr20ContextDispatch_Dx12(context, dispatchDescription);
|
||||
_skipDispatch = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (dispatchDescription == nullptr || context == nullptr || dispatchDescription->commandList == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
// If not in contexts list create and add context
|
||||
if (!_contexts.contains(context) && _initParams.contains(context) && !CreateDLSSContext20(context, dispatchDescription))
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
NVSDK_NGX_Parameter* params = _nvParams[context];
|
||||
NVSDK_NGX_Handle* handle = _contexts[context];
|
||||
|
||||
params->Set(NVSDK_NGX_Parameter_Jitter_Offset_X, dispatchDescription->jitterOffset.x);
|
||||
params->Set(NVSDK_NGX_Parameter_Jitter_Offset_Y, dispatchDescription->jitterOffset.y);
|
||||
params->Set(NVSDK_NGX_Parameter_MV_Scale_X, dispatchDescription->motionVectorScale.x);
|
||||
params->Set(NVSDK_NGX_Parameter_MV_Scale_Y, dispatchDescription->motionVectorScale.y);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Exposure_Scale, 1.0);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Pre_Exposure, dispatchDescription->preExposure);
|
||||
params->Set(NVSDK_NGX_Parameter_Reset, dispatchDescription->reset ? 1 : 0);
|
||||
params->Set(NVSDK_NGX_Parameter_Width, dispatchDescription->renderSize.width);
|
||||
params->Set(NVSDK_NGX_Parameter_Height, dispatchDescription->renderSize.height);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width, dispatchDescription->renderSize.width);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Height, dispatchDescription->renderSize.height);
|
||||
params->Set(NVSDK_NGX_Parameter_Depth, dispatchDescription->depth.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_ExposureTexture, dispatchDescription->exposure.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, dispatchDescription->reactive.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_Color, dispatchDescription->color.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_MotionVectors, dispatchDescription->motionVectors.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_Output, dispatchDescription->output.resource);
|
||||
params->Set("FSR.cameraNear", dispatchDescription->cameraNear);
|
||||
params->Set("FSR.cameraFar", dispatchDescription->cameraFar);
|
||||
params->Set("FSR.cameraFovAngleVertical", dispatchDescription->cameraFovAngleVertical);
|
||||
params->Set("FSR.frameTimeDelta", dispatchDescription->frameTimeDelta);
|
||||
params->Set("FSR.transparencyAndComposition", dispatchDescription->transparencyAndComposition.resource);
|
||||
params->Set("FSR.reactive", dispatchDescription->reactive.resource);
|
||||
params->Set(NVSDK_NGX_Parameter_Sharpness, dispatchDescription->sharpness);
|
||||
|
||||
LOG_DEBUG("handle: {:X}, internalResolution: {}x{}", handle->Id, dispatchDescription->renderSize.width, dispatchDescription->renderSize.height);
|
||||
|
||||
Config::Instance()->setInputApiName = "FSR2.0-DX12";
|
||||
|
||||
auto evalResult = NVSDK_NGX_D3D12_EvaluateFeature((ID3D12GraphicsCommandList*)dispatchDescription->commandList, handle, params, nullptr);
|
||||
|
||||
if (evalResult == NVSDK_NGX_Result_Success)
|
||||
return Fsr212::FFX_OK;
|
||||
|
||||
LOG_ERROR("evalResult: {:X}", (UINT)evalResult);
|
||||
return Fsr212::FFX_ERROR_BACKEND_API_ERROR;
|
||||
}
|
||||
|
||||
// FSR2.0 Pattern
|
||||
static Fsr212::FfxErrorCode ffxFsr20ContextDispatch_Pattern_Dx12(Fsr212::FfxFsr2Context* context, const FfxFsr20DispatchDescription* dispatchDescription)
|
||||
{
|
||||
// Skip OptiScaler stuff
|
||||
if (!Config::Instance()->Fsr2Inputs.value_or(true) || _skipDispatch)
|
||||
return o_ffxFsr20ContextDispatch_Patern_Dx12(context, dispatchDescription);
|
||||
|
||||
if (dispatchDescription == nullptr || context == nullptr || dispatchDescription->commandList == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
@@ -579,7 +789,10 @@ static Fsr212::FfxErrorCode ffxFsr2ContextDestroy_Dx12(Fsr212::FfxFsr2Context* c
|
||||
if (context == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
_skipDestroy = true;
|
||||
auto cdResult = o_ffxFsr2ContextDestroy_Dx12(context);
|
||||
_skipDestroy = false;
|
||||
|
||||
LOG_INFO("result: {:X}", (UINT)cdResult);
|
||||
|
||||
if (!_initParams.contains(context) || _d3d12Device == nullptr)
|
||||
@@ -595,6 +808,27 @@ static Fsr212::FfxErrorCode ffxFsr2ContextDestroy_Dx12(Fsr212::FfxFsr2Context* c
|
||||
return Fsr212::FFX_OK;
|
||||
}
|
||||
|
||||
static Fsr212::FfxErrorCode ffxFsr2ContextDestroy_Pattern_Dx12(Fsr212::FfxFsr2Context* context)
|
||||
{
|
||||
if (context == nullptr)
|
||||
return Fsr212::FFX_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
auto cdResult = o_ffxFsr2ContextDestroy_Pattern_Dx12(context);
|
||||
LOG_INFO("result: {:X}", (UINT)cdResult);
|
||||
|
||||
if (!_initParams.contains(context) || _d3d12Device == nullptr || _skipDestroy)
|
||||
return cdResult;
|
||||
|
||||
if (_contexts.contains(context))
|
||||
NVSDK_NGX_D3D12_ReleaseFeature(_contexts[context]);
|
||||
|
||||
_contexts.erase(context);
|
||||
_nvParams.erase(context);
|
||||
_initParams.erase(context);
|
||||
|
||||
return Fsr212::FFX_OK;
|
||||
}
|
||||
|
||||
static float ffxFsr2GetUpscaleRatioFromQualityMode_Dx12(Fsr212::FfxFsr2QualityMode qualityMode)
|
||||
{
|
||||
auto ratio = GetQualityOverrideRatioFfx(qualityMode).value_or(qualityRatios[(UINT)qualityMode]);
|
||||
@@ -635,16 +869,15 @@ void HookFSR2ExeInputs()
|
||||
{
|
||||
LOG_INFO("Trying to hook FSR2 methods");
|
||||
|
||||
auto exeName = wstring_to_string(Util::ExePath().filename());
|
||||
auto exeNameW = Util::ExePath().filename();
|
||||
auto exeName = wstring_to_string(exeNameW);
|
||||
|
||||
// ffxFsr2ContextCreate
|
||||
o_ffxFsr2ContextCreate_Dx12 = (PFN_ffxFsr2ContextCreate)DetourFindFunction(exeName.c_str(), "ffxFsr2ContextCreate");
|
||||
if (o_ffxFsr2ContextCreate_Dx12 == nullptr)
|
||||
o_ffxFsr2ContextCreate_Dx12 = (PFN_ffxFsr2ContextCreate)DetourFindFunction(exeName.c_str(), "?ffxFsr2ContextCreate@@YAHPEAUFfxFsr2Context@@PEBUFfxFsr2ContextDescription@@@Z");
|
||||
|
||||
if (o_ffxFsr2ContextCreate_Dx12 == nullptr)
|
||||
return;
|
||||
|
||||
//ffxFsr2ContextDispatch
|
||||
//ffxFsr2ContextDispatch 2.X
|
||||
o_ffxFsr2ContextDispatch_Dx12 = (PFN_ffxFsr2ContextDispatch)DetourFindFunction(exeName.c_str(), "ffxFsr2ContextDispatch");
|
||||
|
||||
//ffxFsr2ContextDispatch FSR2.0
|
||||
@@ -675,47 +908,95 @@ void HookFSR2ExeInputs()
|
||||
if (o_ffxFsr2GetInterfaceDX12 == nullptr)
|
||||
o_ffxFsr2GetInterfaceDX12 = (PFN_ffxFsr2GetInterfaceDX12)DetourFindFunction(exeName.c_str(), "?ffxFsr2GetInterfaceDX12@@YAHPEAUFfxFsr2Interface@@PEAUID3D12Device@@PEAX_K@Z");
|
||||
|
||||
if (o_ffxFsr2ContextCreate_Dx12 != nullptr)
|
||||
// Pattern matching
|
||||
{
|
||||
LOG_INFO("FSR2 methods found, now hooking");
|
||||
std::wstring_view exeNameV(exeNameW.c_str());
|
||||
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
// Create
|
||||
std::string_view createPattern("40 55 57 41 54 41 56 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B F2 41 B8 ? ? ? ? 33 D2 48 8B F9 E8");
|
||||
o_ffxFsr2ContextCreate_Pattern_Dx12 = (PFN_ffxFsr2ContextCreate)scanner::GetAddress(exeNameV, createPattern, 0);
|
||||
|
||||
if (o_ffxFsr2ContextCreate_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextCreate_Dx12, ffxFsr2ContextCreate_Dx12);
|
||||
// Hooking works but AW2 uses a custom implementation like FMF2 which does not pass correct D3D12Device or CommandList
|
||||
//if (o_ffxFsr2ContextCreate_Pattern_Dx12 == nullptr)
|
||||
//{
|
||||
// std::string_view createPatternAW2("40 55 57 41 54 41 56 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 4C 8B F2 41 B8 ? ? ? ? 33 D2 48 8B F9");
|
||||
// o_ffxFsr2ContextCreate_Pattern_Dx12 = (PFN_ffxFsr2ContextCreate)scanner::GetAddress(exeNameV, createPatternAW2, 0);
|
||||
//}
|
||||
|
||||
if (o_ffxFsr2ContextDispatch_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextDispatch_Dx12, ffxFsr2ContextDispatch_Dx12);
|
||||
// Dispatch 2.0
|
||||
std::string_view dispatchPattern20("40 55 56 41 57 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 80 B9 ? ? ? ? 00 4C 8B FA 48 8B 02 48 8B F1");
|
||||
o_ffxFsr20ContextDispatch_Patern_Dx12 = (PFN_ffxFsr2ContextDispatch)scanner::GetAddress(exeNameV, dispatchPattern20, 0);
|
||||
|
||||
if (o_ffxFsr20ContextDispatch_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr20ContextDispatch_Dx12, ffxFsr20ContextDispatch_Dx12);
|
||||
// Dispatch 2.X
|
||||
std::string_view dispatchPattern("40 55 53 57 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 80 B9 ? ? ? ? 00 48 8B DA 48 8B 02 48 8B F9");
|
||||
o_ffxFsr2ContextDispatch_Pattern_Dx12 = (PFN_ffxFsr2ContextDispatch)scanner::GetAddress(exeNameV, dispatchPattern, 0);
|
||||
|
||||
if (o_ffxFsr2TinyContextDispatch_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2TinyContextDispatch_Dx12, ffxFsr2TinyContextDispatch_Dx12);
|
||||
// Hooking works but AW2 uses a custom implementation like FMF2 which does not pass correct D3D12Device or CommandList
|
||||
//if (o_ffxFsr2ContextDispatch_Pattern_Dx12 == nullptr)
|
||||
//{
|
||||
// std::string_view dispatchPatternAW2("40 55 56 41 56 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 F7 01 ? ? ? ? 4C 8B F2 48 8B F1");
|
||||
// o_ffxFsr2ContextDispatch_Pattern_Dx12 = (PFN_ffxFsr2ContextDispatch)scanner::GetAddress(exeNameV, dispatchPatternAW2, 0);
|
||||
//}
|
||||
|
||||
if (o_ffxFsr2ContextDestroy_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextDestroy_Dx12, ffxFsr2ContextDestroy_Dx12);
|
||||
|
||||
if (o_ffxFsr2GetUpscaleRatioFromQualityMode_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2GetUpscaleRatioFromQualityMode_Dx12, ffxFsr2GetUpscaleRatioFromQualityMode_Dx12);
|
||||
|
||||
if (o_ffxFsr2GetRenderResolutionFromQualityMode_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2GetRenderResolutionFromQualityMode_Dx12, ffxFsr2GetRenderResolutionFromQualityMode_Dx12);
|
||||
|
||||
if (o_ffxFsr2GetInterfaceDX12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2GetInterfaceDX12, hk_ffxFsr2GetInterfaceDX12);
|
||||
|
||||
Config::Instance()->fsrHooks = true;
|
||||
|
||||
DetourTransactionCommit();
|
||||
// Destroy
|
||||
std::string_view destroyPattern("40 53 48 83 EC 20 48 8B D9 48 85 C9 75 0B B8 00 00 00 80 48 83 C4 20 5B C3");
|
||||
o_ffxFsr2ContextDestroy_Pattern_Dx12 = (PFN_ffxFsr2ContextDestroy)scanner::GetAddress(exeNameV, destroyPattern, 0);
|
||||
}
|
||||
|
||||
LOG_INFO("FSR2 methods found, now hooking");
|
||||
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
|
||||
if (o_ffxFsr2ContextCreate_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextCreate_Dx12, ffxFsr2ContextCreate_Dx12);
|
||||
|
||||
if (o_ffxFsr2ContextCreate_Pattern_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextCreate_Pattern_Dx12, ffxFsr2ContextCreate_Pattern_Dx12);
|
||||
|
||||
if (o_ffxFsr2ContextDispatch_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextDispatch_Dx12, ffxFsr2ContextDispatch_Dx12);
|
||||
|
||||
if (o_ffxFsr2ContextDispatch_Pattern_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextDispatch_Pattern_Dx12, ffxFsr2ContextDispatch_Pattern_Dx12);
|
||||
|
||||
if (o_ffxFsr20ContextDispatch_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr20ContextDispatch_Dx12, ffxFsr20ContextDispatch_Dx12);
|
||||
|
||||
if (o_ffxFsr20ContextDispatch_Patern_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr20ContextDispatch_Patern_Dx12, ffxFsr20ContextDispatch_Pattern_Dx12);
|
||||
|
||||
if (o_ffxFsr2TinyContextDispatch_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2TinyContextDispatch_Dx12, ffxFsr2TinyContextDispatch_Dx12);
|
||||
|
||||
if (o_ffxFsr2ContextDestroy_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextDestroy_Dx12, ffxFsr2ContextDestroy_Dx12);
|
||||
|
||||
if (o_ffxFsr2ContextDestroy_Pattern_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2ContextDestroy_Pattern_Dx12, ffxFsr2ContextDestroy_Pattern_Dx12);
|
||||
|
||||
if (o_ffxFsr2GetUpscaleRatioFromQualityMode_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2GetUpscaleRatioFromQualityMode_Dx12, ffxFsr2GetUpscaleRatioFromQualityMode_Dx12);
|
||||
|
||||
if (o_ffxFsr2GetRenderResolutionFromQualityMode_Dx12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2GetRenderResolutionFromQualityMode_Dx12, ffxFsr2GetRenderResolutionFromQualityMode_Dx12);
|
||||
|
||||
if (o_ffxFsr2GetInterfaceDX12 != nullptr)
|
||||
DetourAttach(&(PVOID&)o_ffxFsr2GetInterfaceDX12, hk_ffxFsr2GetInterfaceDX12);
|
||||
|
||||
Config::Instance()->fsrHooks = true;
|
||||
|
||||
DetourTransactionCommit();
|
||||
|
||||
LOG_DEBUG("ffxFsr2ContextCreate_Dx12: {:X}", (size_t)o_ffxFsr2ContextCreate_Dx12);
|
||||
LOG_DEBUG("ffxFsr2ContextCreate_Pattern_Dx12: {:X}", (size_t)o_ffxFsr2ContextCreate_Pattern_Dx12);
|
||||
LOG_DEBUG("ffxFsr2ContextDispatch_Dx12: {:X}", (size_t)o_ffxFsr2ContextDispatch_Dx12);
|
||||
LOG_DEBUG("ffxFsr2ContextDispatch_Pattern_Dx12: {:X}", (size_t)o_ffxFsr2ContextDispatch_Pattern_Dx12);
|
||||
LOG_DEBUG("ffxFsr20ContextDispatch_Dx12: {:X}", (size_t)o_ffxFsr20ContextDispatch_Dx12);
|
||||
LOG_DEBUG("ffxFsr20ContextDispatch_Patern_Dx12: {:X}", (size_t)o_ffxFsr20ContextDispatch_Patern_Dx12);
|
||||
LOG_DEBUG("ffxFsr2TinyContextDispatch_Dx12: {:X}", (size_t)o_ffxFsr2TinyContextDispatch_Dx12);
|
||||
LOG_DEBUG("ffxFsr2ContextDestroy_Dx12: {:X}", (size_t)o_ffxFsr2ContextDestroy_Dx12);
|
||||
LOG_DEBUG("ffxFsr2ContextDestroy_Pattern_Dx12: {:X}", (size_t)o_ffxFsr2ContextDestroy_Pattern_Dx12);
|
||||
LOG_DEBUG("ffxFsr2GetUpscaleRatioFromQualityMode_Dx12: {:X}", (size_t)o_ffxFsr2GetUpscaleRatioFromQualityMode_Dx12);
|
||||
LOG_DEBUG("ffxFsr2GetRenderResolutionFromQualityMode_Dx12: {:X}", (size_t)o_ffxFsr2GetRenderResolutionFromQualityMode_Dx12);
|
||||
LOG_DEBUG("ffxFsr2GetInterfaceDX12: {:X}", (size_t)o_ffxFsr2GetInterfaceDX12);
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "scanner.h"
|
||||
|
||||
std::pair<uintptr_t, uintptr_t> GetModule(const std::wstring_view moduleName)
|
||||
{
|
||||
const static uintptr_t moduleBase = reinterpret_cast<uintptr_t>(GetModuleHandleW(moduleName.data()));
|
||||
const static uintptr_t moduleEnd = [&]()
|
||||
{
|
||||
auto ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS64>(moduleBase + reinterpret_cast<PIMAGE_DOS_HEADER>(moduleBase)->e_lfanew);
|
||||
return static_cast<uintptr_t>(moduleBase + ntHeaders->OptionalHeader.SizeOfImage);
|
||||
}();
|
||||
|
||||
return { moduleBase, moduleEnd };
|
||||
}
|
||||
|
||||
|
||||
uintptr_t FindPattern(uintptr_t startAddress, uintptr_t maxSize, const char* mask)
|
||||
{
|
||||
std::vector<std::pair<uint8_t, bool>> pattern;
|
||||
|
||||
for (size_t i = 0; i < strlen(mask);)
|
||||
{
|
||||
if (mask[i] != '?')
|
||||
{
|
||||
pattern.emplace_back(static_cast<uint8_t>(strtoul(&mask[i], nullptr, 16)), false);
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern.emplace_back(0x00, true);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
const auto dataStart = reinterpret_cast<const uint8_t*>(startAddress);
|
||||
const auto dataEnd = dataStart + maxSize + 1;
|
||||
|
||||
auto sig = std::search(dataStart, dataEnd, pattern.begin(), pattern.end(),
|
||||
[](uint8_t currentByte, std::pair<uint8_t, bool> Pattern)
|
||||
{
|
||||
return Pattern.second || (currentByte == Pattern.first);
|
||||
});
|
||||
|
||||
if (sig == dataEnd)
|
||||
return NULL;
|
||||
|
||||
return std::distance(dataStart, sig) + startAddress;
|
||||
}
|
||||
|
||||
uintptr_t scanner::GetAddress(const std::wstring_view moduleName, const std::string_view pattern, ptrdiff_t offset)
|
||||
{
|
||||
uintptr_t address = FindPattern(GetModule(moduleName.data()).first, GetModule(moduleName.data()).second - GetModule(moduleName.data()).first, pattern.data());
|
||||
|
||||
if ((GetModuleHandleW(moduleName.data()) != nullptr) && (address != NULL))
|
||||
{
|
||||
return (address + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t scanner::GetOffsetFromInstruction(const std::wstring_view moduleName, const std::string_view pattern, ptrdiff_t offset)
|
||||
{
|
||||
uintptr_t address = FindPattern(GetModule(moduleName.data()).first, GetModule(moduleName.data()).second - GetModule(moduleName.data()).first, pattern.data());
|
||||
|
||||
if ((GetModuleHandleW(moduleName.data()) != nullptr) && (address != NULL))
|
||||
{
|
||||
auto reloffset = *reinterpret_cast<int32_t*>(address + offset) + sizeof(int32_t);
|
||||
return (address + offset + reloffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "../pch.h"
|
||||
|
||||
|
||||
namespace scanner
|
||||
{
|
||||
uintptr_t GetAddress(const std::wstring_view moduleName, const std::string_view pattern, ptrdiff_t offset = 0);
|
||||
uintptr_t GetOffsetFromInstruction(const std::wstring_view moduleName, const std::string_view pattern, ptrdiff_t offset = 0);
|
||||
}
|
||||
Reference in New Issue
Block a user