diff --git a/OptiScaler/DllNames.h b/OptiScaler/DllNames.h index 85899170..e99e2320 100644 --- a/OptiScaler/DllNames.h +++ b/OptiScaler/DllNames.h @@ -201,6 +201,7 @@ DEFINE_NAME_VECTORS(fsr3BE, "ffx_backend_dx12_x64"); DEFINE_NAME_VECTORS(ffxDx12, "amd_fidelityfx_dx12", "amd_fidelityfx_loader_dx12"); DEFINE_NAME_VECTORS(ffxDx12Upscaler, "amd_fidelityfx_upscaler_dx12"); DEFINE_NAME_VECTORS(ffxDx12FG, "amd_fidelityfx_framegeneration_dx12"); +DEFINE_NAME_VECTORS(ffxDx12Denoiser, "amd_fidelityfx_denoiser_dx12"); DEFINE_NAME_VECTORS(ffxVk, "amd_fidelityfx_vk"); inline static bool CompareFileName(std::string* first, std::string* second) diff --git a/OptiScaler/dllmain.cpp b/OptiScaler/dllmain.cpp index 56b8256e..cafcb50a 100644 --- a/OptiScaler/dllmain.cpp +++ b/OptiScaler/dllmain.cpp @@ -989,6 +989,14 @@ static void CheckWorkingMode() FfxApiProxy::InitFfxDx12_FG(ffxDx12FGModule); } + HMODULE ffxDx12DenoiserModule = nullptr; + ffxDx12DenoiserModule = GetDllNameWModule(&ffxDx12DenoiserNamesW); + if (ffxDx12DenoiserModule != nullptr) + { + LOG_DEBUG("amd_fidelityfx_denoiser_dx12.dll already in memory"); + FfxApiProxy::InitFfxDx12_Denoiser(ffxDx12FGModule); + } + // FFX Vulkan HMODULE ffxVkModule = nullptr; ffxVkModule = GetDllNameWModule(&ffxVkNamesW); diff --git a/OptiScaler/proxies/FfxApi_Proxy.h b/OptiScaler/proxies/FfxApi_Proxy.h index 813124a2..569c4c74 100644 --- a/OptiScaler/proxies/FfxApi_Proxy.h +++ b/OptiScaler/proxies/FfxApi_Proxy.h @@ -75,6 +75,7 @@ class FfxApiProxy inline static FfxModule main_dx12; inline static FfxModule upscaling_dx12; inline static FfxModule fg_dx12; + inline static FfxModule denoiser_dx12; inline static FfxModule main_vk; @@ -94,6 +95,7 @@ class FfxApiProxy static HMODULE Dx12Module() { return main_dx12.dll; } static HMODULE Dx12Module_SR() { return upscaling_dx12.dll; } static HMODULE Dx12Module_FG() { return fg_dx12.dll; } + static HMODULE Dx12Module_Denoiser() { return denoiser_dx12.dll; } static bool IsFGReady() { @@ -117,6 +119,17 @@ class FfxApiProxy return result; } + static bool IsDenoiserReady() + { + bool result = (main_dx12.dll && !main_dx12.isLoader) || denoiser_dx12.dll != nullptr; + + if (!result) + ImGui::InsertNotification({ ImGuiToastType::Error, 10000, + "Can't load amd_fidelityfx_dx12\nDid you forget to extract that dll?" }); + + return result; + } + static FFXStructType GetType(ffxStructType_t type) { switch (type & FFX_API_EFFECT_MASK) // type without the specific effect @@ -267,9 +280,10 @@ class FfxApiProxy InitFfxDx12_SR(); InitFfxDx12_FG(); + InitFfxDx12_Denoiser(); bool loadResult = main_dx12.CreateContext != nullptr || upscaling_dx12.CreateContext != nullptr || - fg_dx12.CreateContext != nullptr; + fg_dx12.CreateContext != nullptr || denoiser_dx12.CreateContext != nullptr; LOG_INFO("LoadResult: {}", loadResult); @@ -474,6 +488,104 @@ class FfxApiProxy return loadResult; } + static bool InitFfxDx12_Denoiser(HMODULE module = nullptr) + { + // if dll already loaded + if (denoiser_dx12.dll != nullptr && denoiser_dx12.CreateContext != nullptr) + return true; + + spdlog::info(""); + + if (module != nullptr) + denoiser_dx12.dll = module; + + if (denoiser_dx12.dll == nullptr) + { + // Try new api first + std::vector dllNames = { L"amd_fidelityfx_denoiser_dx12.dll" }; + + for (size_t i = 0; i < dllNames.size(); i++) + { + LOG_DEBUG("Trying to load {}", wstring_to_string(dllNames[i])); + + // if (denoiser_dx12.dll == nullptr && Config::Instance()->FfxDx12Path.has_value()) + //{ + // std::filesystem::path libPath(Config::Instance()->FfxDx12Path.value().c_str()); + + // if (libPath.has_filename()) + // denoiser_dx12.dll = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); + // else + // denoiser_dx12.dll = NtdllProxy::LoadLibraryExW_Ldr((libPath / dllNames[i]).c_str(), NULL, 0); + + // if (denoiser_dx12.dll != nullptr) + // { + // LOG_INFO("{} loaded from {}", wstring_to_string(dllNames[i]), + // wstring_to_string(Config::Instance()->FfxDx12Path.value())); + // break; + // } + //} + + if (denoiser_dx12.dll == nullptr) + { + denoiser_dx12.dll = NtdllProxy::LoadLibraryExW_Ldr(dllNames[i].c_str(), NULL, 0); + + if (denoiser_dx12.dll != nullptr) + { + LOG_INFO("{} loaded from exe folder", wstring_to_string(dllNames[i])); + break; + } + } + } + } + + if (denoiser_dx12.dll != nullptr && denoiser_dx12.Configure == nullptr) + { + denoiser_dx12.Configure = + (PfnFfxConfigure) KernelBaseProxy::GetProcAddress_()(denoiser_dx12.dll, "ffxConfigure"); + denoiser_dx12.CreateContext = + (PfnFfxCreateContext) KernelBaseProxy::GetProcAddress_()(denoiser_dx12.dll, "ffxCreateContext"); + denoiser_dx12.DestroyContext = + (PfnFfxDestroyContext) KernelBaseProxy::GetProcAddress_()(denoiser_dx12.dll, "ffxDestroyContext"); + denoiser_dx12.Dispatch = + (PfnFfxDispatch) KernelBaseProxy::GetProcAddress_()(denoiser_dx12.dll, "ffxDispatch"); + denoiser_dx12.Query = (PfnFfxQuery) KernelBaseProxy::GetProcAddress_()(denoiser_dx12.dll, "ffxQuery"); + + if (Config::Instance()->EnableFfxInputs.value_or_default() && denoiser_dx12.CreateContext != nullptr) + { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + if (denoiser_dx12.Configure != nullptr) + DetourAttach(&(PVOID&) denoiser_dx12.Configure, ffxConfigure_Dx12); + + if (denoiser_dx12.CreateContext != nullptr) + DetourAttach(&(PVOID&) denoiser_dx12.CreateContext, ffxCreateContext_Dx12); + + if (denoiser_dx12.DestroyContext != nullptr) + DetourAttach(&(PVOID&) denoiser_dx12.DestroyContext, ffxDestroyContext_Dx12); + + if (denoiser_dx12.Dispatch != nullptr) + DetourAttach(&(PVOID&) denoiser_dx12.Dispatch, ffxDispatch_Dx12); + + if (denoiser_dx12.Query != nullptr) + DetourAttach(&(PVOID&) denoiser_dx12.Query, ffxQuery_Dx12); + + State::Instance().fsrHooks = true; + + DetourTransactionCommit(); + } + } + + bool loadResult = denoiser_dx12.CreateContext != nullptr; + + LOG_INFO("LoadResult: {}", loadResult); + + if (!loadResult) + denoiser_dx12.dll = nullptr; + + return loadResult; + } + static feature_version VersionDx12() { if (main_dx12.version.major == 0 && main_dx12.Query != nullptr /* && device != nullptr*/) @@ -637,27 +749,34 @@ class FfxApiProxy LOG_DEBUG("Creating with fg_dx12"); return fg_dx12.CreateContext(context, desc, memCb); } - else if (!isFg && upscaling_dx12.dll != nullptr) + else if (type == FFXStructType::Upscaling && upscaling_dx12.dll != nullptr) { LOG_DEBUG("Creating with upscaling_dx12"); return upscaling_dx12.CreateContext(context, desc, memCb); } + else if (type == FFXStructType::Denoiser && denoiser_dx12.dll != nullptr) + { + LOG_DEBUG("Creating with denoiser_dx12"); + return denoiser_dx12.CreateContext(context, desc, memCb); + } - if (main_dx12.dll != nullptr && !(isFg && fg_dx12.skipCreateCalls) && - !(!isFg && upscaling_dx12.skipCreateCalls)) + const auto skipFG = isFg && fg_dx12.skipQueryCalls; + const auto skipUpscaling = type == FFXStructType::Upscaling && upscaling_dx12.skipQueryCalls; + + if (main_dx12.dll != nullptr && !skipFG && !skipUpscaling) { LOG_DEBUG("Creating with main_dx12"); if (isFg) fg_dx12.skipCreateCalls = true; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipCreateCalls = true; auto result = main_dx12.CreateContext(context, desc, memCb); if (isFg) fg_dx12.skipCreateCalls = false; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipCreateCalls = false; return result; @@ -673,8 +792,8 @@ class FfxApiProxy if (contextToType.contains(context)) { - LOG_DEBUG("Found context type mapping: {}", magic_enum::enum_name(type)); type = contextToType[context]; + LOG_DEBUG("Found context type mapping: {}", magic_enum::enum_name(type)); contextToType.erase(context); } else @@ -703,6 +822,12 @@ class FfxApiProxy result = fg_dx12.DestroyContext(context, memCb); break; + case FFXStructType::Denoiser: + LOG_DEBUG("Destroying with denoiser_dx12"); + if (denoiser_dx12.dll != nullptr) + result = denoiser_dx12.DestroyContext(context, memCb); + break; + default: break; } @@ -762,22 +887,26 @@ class FfxApiProxy if (isFg && fg_dx12.dll != nullptr) return fg_dx12.Configure(context, desc); - else if (!isFg && upscaling_dx12.dll != nullptr) + else if (type == FFXStructType::Upscaling && upscaling_dx12.dll != nullptr) return upscaling_dx12.Configure(context, desc); + else if (type == FFXStructType::Denoiser && denoiser_dx12.dll != nullptr) + return denoiser_dx12.Configure(context, desc); - if (main_dx12.dll != nullptr && !(isFg && fg_dx12.skipConfigureCalls) && - !(!isFg && upscaling_dx12.skipConfigureCalls)) + const auto skipFG = isFg && fg_dx12.skipQueryCalls; + const auto skipUpscaling = type == FFXStructType::Upscaling && upscaling_dx12.skipQueryCalls; + + if (main_dx12.dll != nullptr && !skipFG && !skipUpscaling) { if (isFg) fg_dx12.skipConfigureCalls = true; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipConfigureCalls = true; auto result = main_dx12.Configure(context, desc); if (isFg) fg_dx12.skipConfigureCalls = false; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipConfigureCalls = false; return result; @@ -793,21 +922,26 @@ class FfxApiProxy if (isFg && fg_dx12.dll != nullptr) return fg_dx12.Query(context, desc); - else if (!isFg && upscaling_dx12.dll != nullptr) + else if (type == FFXStructType::Upscaling && upscaling_dx12.dll != nullptr) return upscaling_dx12.Query(context, desc); + else if (type == FFXStructType::Denoiser && denoiser_dx12.dll != nullptr) + return denoiser_dx12.Query(context, desc); - if (main_dx12.dll != nullptr && !(isFg && fg_dx12.skipQueryCalls) && !(!isFg && upscaling_dx12.skipQueryCalls)) + const auto skipFG = isFg && fg_dx12.skipQueryCalls; + const auto skipUpscaling = type == FFXStructType::Upscaling && upscaling_dx12.skipQueryCalls; + + if (main_dx12.dll != nullptr && !skipFG && !skipUpscaling) { if (isFg) fg_dx12.skipQueryCalls = true; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipQueryCalls = true; auto result = main_dx12.Query(context, desc); if (isFg) fg_dx12.skipQueryCalls = false; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipQueryCalls = false; return result; @@ -823,22 +957,26 @@ class FfxApiProxy if (isFg && fg_dx12.dll != nullptr) return fg_dx12.Dispatch(context, desc); - else if (!isFg && upscaling_dx12.dll != nullptr) + else if (type == FFXStructType::Upscaling && upscaling_dx12.dll != nullptr) return upscaling_dx12.Dispatch(context, desc); + else if (type == FFXStructType::Denoiser && denoiser_dx12.dll != nullptr) + return denoiser_dx12.Dispatch(context, desc); - if (main_dx12.dll != nullptr && !(isFg && fg_dx12.skipDispatchCalls) && - !(!isFg && upscaling_dx12.skipDispatchCalls)) + const auto skipFG = isFg && fg_dx12.skipQueryCalls; + const auto skipUpscaling = type == FFXStructType::Upscaling && upscaling_dx12.skipQueryCalls; + + if (main_dx12.dll != nullptr && !skipFG && !skipUpscaling) { if (isFg) fg_dx12.skipDispatchCalls = true; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipDispatchCalls = true; auto result = main_dx12.Dispatch(context, desc); if (isFg) fg_dx12.skipDispatchCalls = false; - else + else if (type == FFXStructType::Upscaling) upscaling_dx12.skipDispatchCalls = false; return result;