mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-09-24 22:35:57 +00:00
Merge pull request #2 from FakeMichau/antilag2
AntiLag 2 and LatencyFlex
This commit is contained in:
Executable → Regular
+128
-30
@@ -1,24 +1,24 @@
|
||||
#include "nvapi.h"
|
||||
#include "fakenvapi.h"
|
||||
#include <string>
|
||||
|
||||
namespace nvd {
|
||||
NvAPI_Status __cdecl NvAPI_Initialize() {
|
||||
IDXGIFactory1* pFactory = nullptr;
|
||||
if (FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory))) {
|
||||
log("Failed to create DXGI Factory");
|
||||
spdlog::error("Failed to create DXGI Factory");
|
||||
return Error();
|
||||
}
|
||||
|
||||
IDXGIAdapter1* pAdapter = nullptr;
|
||||
if (FAILED(pFactory->EnumAdapters1(0, &pAdapter))) {
|
||||
log("Failed to enumerate adapters");
|
||||
spdlog::error("Failed to enumerate adapters");
|
||||
pFactory->Release();
|
||||
return Error();
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC1 adapterDesc;
|
||||
if (FAILED(pAdapter->GetDesc1(&adapterDesc))) {
|
||||
log("Failed to get adapter description");
|
||||
spdlog::error("Failed to get adapter description");
|
||||
pAdapter->Release();
|
||||
pFactory->Release();
|
||||
return Error();
|
||||
@@ -33,6 +33,8 @@ namespace nvd {
|
||||
pAdapter->Release();
|
||||
pFactory->Release();
|
||||
|
||||
lowlatency_ctx.init_lfx();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -57,7 +59,7 @@ namespace nvd {
|
||||
if (displayId == 0) {
|
||||
return Ok();
|
||||
}
|
||||
return Error(NVAPI_NVIDIA_DISPLAY_NOT_FOUND);
|
||||
return Error(NVAPI_END_ENUMERATION);
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_GetLogicalGPUFromPhysicalGPU(NvPhysicalGpuHandle physicalHandle, NvLogicalGpuHandle* logicalHandle) {
|
||||
@@ -85,7 +87,7 @@ namespace nvd {
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_GetErrorMessage(NvAPI_Status status, NvAPI_ShortString szMsg) {
|
||||
std::string error = fromErrorNr(status);
|
||||
log(std::format("NvAPI_GetErrorMessage gave this error: {}", error));
|
||||
spdlog::error("NvAPI_GetErrorMessage gave this error: {}", error);
|
||||
tonvss(szMsg, error);
|
||||
return Ok();
|
||||
}
|
||||
@@ -105,12 +107,12 @@ namespace nvd {
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_GPU_GetArchInfo(NvPhysicalGpuHandle handle, NV_GPU_ARCH_INFO* archInfo) {
|
||||
archInfo->architecture = spoof::arch;
|
||||
archInfo->architecture_id = spoof::arch;
|
||||
archInfo->implementation = spoof::implementation;
|
||||
archInfo->implementation_id = spoof::implementation;
|
||||
archInfo->revision = spoof::revision;
|
||||
archInfo->revision_id = spoof::revision;
|
||||
archInfo->architecture = NV_GPU_ARCHITECTURE_AD100;
|
||||
archInfo->architecture_id = NV_GPU_ARCHITECTURE_AD100;
|
||||
archInfo->implementation = NV_GPU_ARCH_IMPLEMENTATION_AD102;
|
||||
archInfo->implementation_id = NV_GPU_ARCH_IMPLEMENTATION_AD102;
|
||||
archInfo->revision = NV_GPU_CHIP_REV_UNKNOWN;
|
||||
archInfo->revision_id = NV_GPU_CHIP_REV_UNKNOWN;
|
||||
|
||||
return Ok();
|
||||
}
|
||||
@@ -131,7 +133,7 @@ namespace nvd {
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_GPU_GetFullName(NvPhysicalGpuHandle hPhysicalGpu, NvAPI_ShortString szName) {
|
||||
tonvss(szName, spoof::fullGPUName);
|
||||
tonvss(szName, "NVIDIA GeForce RTX 4090");
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -262,15 +264,19 @@ namespace nvd {
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_SYS_GetDisplayDriverInfo(NV_DISPLAY_DRIVER_INFO* driverInfo) {
|
||||
spoof::driverInfo(driverInfo);
|
||||
driverInfo->driverVersion = 99999;
|
||||
tonvss(driverInfo->szBuildBranch, "buildBranch");
|
||||
driverInfo->bIsDCHDriver = 1;
|
||||
driverInfo->bIsNVIDIAStudioPackage = 1;
|
||||
driverInfo->bIsNVIDIARTXProductionBranchPackage = 1;
|
||||
driverInfo->bIsNVIDIARTXNewFeatureBranchPackage = 1;
|
||||
if (driverInfo->version == 2)
|
||||
tonvss(driverInfo->szBuildBaseBranch, "buildBaseBranch");
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_SYS_GetDriverAndBranchVersion(NvU32* pDriverVersion, NvAPI_ShortString szBuildBranchString) {
|
||||
memset(pDriverVersion, 0, sizeof(NvU32));
|
||||
memcpy(pDriverVersion, &spoof::driverVersion, sizeof(NvU32));
|
||||
// *pDriverVersion = spoof::driverVersion;
|
||||
tonvss(szBuildBranchString, spoof::buildBranch);
|
||||
tonvss(szBuildBranchString, "buildBranch");
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -295,6 +301,9 @@ namespace nvd {
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_D3D_GetSleepStatus(IUnknown* pDevice, NV_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams) {
|
||||
pGetSleepStatusParams->bLowLatencyMode = lowlatency_ctx.active;
|
||||
pGetSleepStatusParams->bFsVrr = true;
|
||||
pGetSleepStatusParams->bCplVsyncOn = true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -303,14 +312,46 @@ namespace nvd {
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_D3D_SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams) {
|
||||
lowlatency_ctx.active = pSetSleepModeParams->bLowLatencyMode;
|
||||
#ifdef TESTING
|
||||
lowlatency_ctx.force_lfx = pSetSleepModeParams->bLowLatencyBoost;
|
||||
#endif
|
||||
lowlatency_ctx.set_min_interval_us(pSetSleepModeParams->minimumIntervalUs);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_D3D_SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) {
|
||||
if (!pDev)
|
||||
return Error();
|
||||
spdlog::debug("markerType: {}, frame id: {}", (unsigned int)pSetLatencyMarkerParams->markerType, (unsigned long long)pSetLatencyMarkerParams->frameID);
|
||||
lowlatency_ctx.init_al2(pDev);
|
||||
switch (pSetLatencyMarkerParams->markerType) {
|
||||
case SIMULATION_START:
|
||||
if (lowlatency_ctx.call_spot != SimulationStart) break;
|
||||
spdlog::debug("LowLatency update called on simulation start with result: {}", lowlatency_ctx.update());
|
||||
break;
|
||||
case INPUT_SAMPLE:
|
||||
if (lowlatency_ctx.call_spot == SleepCall) break;
|
||||
lowlatency_ctx.call_spot = InputSample;
|
||||
spdlog::debug("LowLatency update called on input sample with result: {}", lowlatency_ctx.update());
|
||||
break;
|
||||
case PRESENT_START:
|
||||
if (lowlatency_ctx.fg) lowlatency_ctx.mark_end_of_rendering();
|
||||
break;
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_D3D_Sleep(IUnknown* pDevice) {
|
||||
if (!pDevice)
|
||||
return Error();
|
||||
lowlatency_ctx.init_al2(pDevice);
|
||||
lowlatency_ctx.call_spot = SleepCall;
|
||||
spdlog::debug("LowLatency update called on sleep with result: {}", lowlatency_ctx.update());
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_D3D_SetReflexSync(IUnknown* pDev, NV_SET_REFLEX_SYNC_PARAMS* pSetReflexSyncParams) {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -390,6 +431,7 @@ namespace nvd {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// Taken directly from dxvk-nvapi
|
||||
static bool ConvertBuildRaytracingAccelerationStructureInputs(const NVAPI_D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS_EX* nvDesc, std::vector<D3D12_RAYTRACING_GEOMETRY_DESC>& geometryDescs, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS* d3dDesc) {
|
||||
d3dDesc->Type = nvDesc->type;
|
||||
// assume that OMM via VK_EXT_opacity_micromap and DMM via VK_NV_displacement_micromap are not supported, allow only standard flags to be passed
|
||||
@@ -426,13 +468,13 @@ namespace nvd {
|
||||
d3dGeoDesc.AABBs = nvGeoDesc.aabbs;
|
||||
break;
|
||||
case NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_OMM_TRIANGLES_EX: // GetRaytracingCaps reports no OMM caps, we shouldn't reach this
|
||||
log("Triangles with OMM attachment passed to acceleration structure build when OMM is not supported");
|
||||
spdlog::error("Triangles with OMM attachment passed to acceleration structure build when OMM is not supported");
|
||||
return false;
|
||||
case NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_DMM_TRIANGLES_EX: // GetRaytracingCaps reports no DMM caps, we shouldn't reach this
|
||||
log("Triangles with DMM attachment passed to acceleration structure build when DMM is not supported");
|
||||
spdlog::error("Triangles with DMM attachment passed to acceleration structure build when DMM is not supported");
|
||||
return false;
|
||||
default:
|
||||
log("Unknown NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_EX");
|
||||
spdlog::error("Unknown NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_EX");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -468,7 +510,12 @@ namespace nvd {
|
||||
return Error(NVAPI_INVALID_ARGUMENT);
|
||||
|
||||
pCommandList->BuildRaytracingAccelerationStructure(&desc, pParams->numPostbuildInfoDescs, pParams->pPostbuildInfoDescs);
|
||||
return Ok();
|
||||
static bool logged = false;
|
||||
if (!logged) {
|
||||
logged = true;
|
||||
return Ok();
|
||||
}
|
||||
else return NVAPI_OK; //return without logging
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_D3D12_NotifyOutOfBandCommandQueue(ID3D12CommandQueue* pCommandQueue, NV_OUT_OF_BAND_CQ_TYPE cqType) {
|
||||
@@ -476,6 +523,30 @@ namespace nvd {
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue, NV_ASYNC_FRAME_MARKER_PARAMS* pSetAsyncFrameMarkerParams) {
|
||||
if (pSetAsyncFrameMarkerParams->markerType == OUT_OF_BAND_PRESENT_START) {
|
||||
constexpr unsigned int history_size = 10;
|
||||
static NvU64 counter = 0;
|
||||
static NvU64 previous_frame_ids[history_size] = {};
|
||||
static NvU64 previous_frame_id = 0;
|
||||
NvU64 current_frame_id = pSetAsyncFrameMarkerParams->frameID;
|
||||
|
||||
previous_frame_ids[counter%history_size] = current_frame_id;
|
||||
counter++;
|
||||
|
||||
std::unordered_set<NvU64> seen;
|
||||
unsigned int repeat_count = 0;
|
||||
for (const NvU64& frame_id : previous_frame_ids) {
|
||||
if (seen.contains(frame_id)) repeat_count++;
|
||||
else seen.insert(frame_id);
|
||||
}
|
||||
|
||||
if (lowlatency_ctx.fg && repeat_count == 0) lowlatency_ctx.fg = false;
|
||||
else if (!lowlatency_ctx.fg && repeat_count >= history_size / 2) lowlatency_ctx.fg = true;
|
||||
|
||||
if (lowlatency_ctx.fg) lowlatency_ctx.set_fg_type(previous_frame_id == current_frame_id);
|
||||
previous_frame_id = current_frame_id;
|
||||
}
|
||||
spdlog::debug("Async markerType: {}, frame id: {}", (unsigned int)pSetAsyncFrameMarkerParams->markerType, (unsigned long long)pSetAsyncFrameMarkerParams->frameID);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -488,30 +559,57 @@ namespace nvd {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_DRS_SaveSettings(NvDRSSessionHandle session) {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_DRS_GetBaseProfile(NvDRSSessionHandle session, NvDRSProfileHandle* profile) {
|
||||
*profile = drsProfile;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_DRS_GetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NvU32 settingId, NVDRS_SETTING* pSetting) {
|
||||
log(std::format("Missing setting: {}", settingId));
|
||||
return Error(NVAPI_SETTING_NOT_FOUND);
|
||||
spdlog::debug("Missing get setting: {}", settingId);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_DRS_SetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NVDRS_SETTING *pSetting) {
|
||||
spdlog::debug("Missing set setting: {}", pSetting->settingId);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_DRS_DestroySession(NvDRSSessionHandle session) {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_Unload() {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl MISC_unknown(IUnknown* unknown, uint32_t* pMiscUnk) {
|
||||
NvAPI_Status __cdecl NvAPI_Unknown_1(IUnknown* unknown, uint32_t* pMiscUnk) {
|
||||
std::fill(pMiscUnk, pMiscUnk + 4, 0x1);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl MISC_vulkan(IUnknown* unknown) {
|
||||
NvAPI_Status __cdecl NvAPI_Vulkan_1(IUnknown* unknown) {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_Unload() {
|
||||
lowlatency_ctx.unload();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl Dummy_GetLatency(uint64_t* call_spot, uint64_t* target, uint64_t* latency, uint64_t* frame_time) {
|
||||
#if _MSC_VER && _WIN64
|
||||
if (!call_spot || !target || !latency || !frame_time) return Error(NVAPI_INVALID_POINTER);
|
||||
|
||||
if (lowlatency_ctx.get_mode() != LatencyFlex) return Error(NVAPI_DATA_NOT_FOUND);
|
||||
*call_spot = (uint64_t)lowlatency_ctx.call_spot;
|
||||
|
||||
*target = lowlatency_ctx.lfx_stats.target;
|
||||
*latency = lowlatency_ctx.lfx_stats.latency;
|
||||
*frame_time = lowlatency_ctx.lfx_stats.frame_time;
|
||||
|
||||
return Ok();
|
||||
#else
|
||||
return Error(NVAPI_DATA_NOT_FOUND);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Executable → Regular
+12
-4
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <numeric>
|
||||
#include <format>
|
||||
|
||||
#include <dxgi.h>
|
||||
@@ -11,8 +13,9 @@
|
||||
#endif
|
||||
#include <vector>
|
||||
|
||||
#include "lowlatency.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "spoofInfo.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace nvd {
|
||||
@@ -20,13 +23,14 @@ namespace nvd {
|
||||
static auto drsSession = reinterpret_cast<NvDRSSessionHandle>(&drs);
|
||||
static auto drsProfile = reinterpret_cast<NvDRSProfileHandle>(&drs);
|
||||
|
||||
|
||||
static LUID luid;
|
||||
static UINT deviceId;
|
||||
static UINT vendorId;
|
||||
static UINT subSysId;
|
||||
static UINT revisionId;
|
||||
|
||||
static LowLatency lowlatency_ctx;
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_Initialize();
|
||||
NvAPI_Status __cdecl NvAPI_GetInterfaceVersionString(NvAPI_ShortString desc);
|
||||
NvAPI_Status __cdecl NvAPI_EnumPhysicalGPUs(NvPhysicalGpuHandle handles[NVAPI_MAX_PHYSICAL_GPUS], NvU32* count);
|
||||
@@ -63,6 +67,7 @@ namespace nvd {
|
||||
NvAPI_Status __cdecl NvAPI_D3D_SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams);
|
||||
NvAPI_Status __cdecl NvAPI_D3D_SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams);
|
||||
NvAPI_Status __cdecl NvAPI_D3D_Sleep(IUnknown* pDevice);
|
||||
NvAPI_Status __cdecl NvAPI_D3D_SetReflexSync(IUnknown* pDev, NV_SET_REFLEX_SYNC_PARAMS* pSetReflexSyncParams);
|
||||
NvAPI_Status __cdecl NvAPI_D3D11_IsNvShaderExtnOpCodeSupported(IUnknown* invalid, NvU32 opCode, bool* pSupported);
|
||||
NvAPI_Status __cdecl NvAPI_D3D11_BeginUAVOverlap(IUnknown* pDeviceOrContext);
|
||||
NvAPI_Status __cdecl NvAPI_D3D11_EndUAVOverlap(IUnknown* pDeviceOrContext);
|
||||
@@ -76,10 +81,13 @@ namespace nvd {
|
||||
NvAPI_Status __cdecl NvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue, NV_ASYNC_FRAME_MARKER_PARAMS* pSetAsyncFrameMarkerParams);
|
||||
NvAPI_Status __cdecl NvAPI_DRS_CreateSession(NvDRSSessionHandle* session);
|
||||
NvAPI_Status __cdecl NvAPI_DRS_LoadSettings(NvDRSSessionHandle session);
|
||||
NvAPI_Status __cdecl NvAPI_DRS_SaveSettings(NvDRSSessionHandle session);
|
||||
NvAPI_Status __cdecl NvAPI_DRS_GetBaseProfile(NvDRSSessionHandle session, NvDRSProfileHandle* profile);
|
||||
NvAPI_Status __cdecl NvAPI_DRS_GetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NvU32 settingId, NVDRS_SETTING* pSetting);
|
||||
NvAPI_Status __cdecl NvAPI_DRS_SetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NVDRS_SETTING *pSetting);
|
||||
NvAPI_Status __cdecl NvAPI_DRS_DestroySession(NvDRSSessionHandle session);
|
||||
NvAPI_Status __cdecl NvAPI_Unknown_1(IUnknown* unknown, uint32_t* pMiscUnk);
|
||||
NvAPI_Status __cdecl NvAPI_Vulkan_1(IUnknown* unknown);
|
||||
NvAPI_Status __cdecl NvAPI_Unload();
|
||||
NvAPI_Status __cdecl MISC_unknown(IUnknown* unknown, uint32_t* pMiscUnk);
|
||||
NvAPI_Status __cdecl MISC_vulkan(IUnknown* unknown);
|
||||
NvAPI_Status __cdecl Dummy_GetLatency(uint64_t* call_spot, uint64_t* waitTarget, uint64_t* latency, uint64_t* frameTime);
|
||||
}
|
||||
@@ -1,52 +1,43 @@
|
||||
#include "log.h"
|
||||
|
||||
std::ostream null(nullptr);
|
||||
std::ostream* logStream = &null;
|
||||
std::ofstream fileStream;
|
||||
|
||||
std::string getCurrentTimeFormatted() {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto now_t = std::chrono::system_clock::to_time_t(now);
|
||||
auto now_tm = *std::localtime(&now_t);
|
||||
auto now_duration = now - std::chrono::system_clock::from_time_t(std::mktime(&now_tm));
|
||||
auto now_us = std::chrono::duration_cast<std::chrono::microseconds>(now_duration);
|
||||
std::ostringstream oss;
|
||||
oss << std::setfill('0') << std::setw(2) << now_tm.tm_hour << ":"
|
||||
<< std::setfill('0') << std::setw(2) << now_tm.tm_min << ":"
|
||||
<< std::setfill('0') << std::setw(2) << now_tm.tm_sec << "."
|
||||
<< std::setfill('0') << std::setw(6) << now_us.count();
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void log(const std::string& log) {
|
||||
*logStream << "[" << getCurrentTimeFormatted() << "] " << log << std::endl;
|
||||
}
|
||||
|
||||
NvAPI_Status Ok(const std::source_location& location) {
|
||||
log(std::format("{}: {}", location.function_name(), "OK"));
|
||||
return NVAPI_OK;
|
||||
}
|
||||
|
||||
NvAPI_Status Error(NvAPI_Status status, const std::source_location& location) {
|
||||
log(std::format("{}: {}", location.function_name(), fromErrorNr(status)));
|
||||
return status;
|
||||
}
|
||||
|
||||
void prepareLogging(std::optional<std::string> fileName) {
|
||||
if (fileName.has_value()) {
|
||||
fileStream.open(fileName.value(), std::ios_base::out | std::ios_base::app);
|
||||
if (fileStream.is_open()) {
|
||||
logStream = &fileStream;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to open log file: " << fileName.value() << std::endl;
|
||||
}
|
||||
}
|
||||
// logStream = &std::cout;
|
||||
}
|
||||
|
||||
void closeLogging() {
|
||||
fileStream.close();
|
||||
#include "log.h"
|
||||
|
||||
inline std::string extractFunctionName(const std::string& signature) {
|
||||
size_t start = signature.find("nvd::");
|
||||
if (start == std::string::npos) return {};
|
||||
start += 5;
|
||||
size_t end = signature.find('(', start);
|
||||
if (end == std::string::npos) return {};
|
||||
|
||||
return signature.substr(start, end - start);
|
||||
}
|
||||
|
||||
NvAPI_Status Ok(const std::source_location& location) {
|
||||
spdlog::trace("{}: {}", extractFunctionName(location.function_name()), "OK");
|
||||
return NVAPI_OK;
|
||||
}
|
||||
|
||||
NvAPI_Status Error(NvAPI_Status status, const std::source_location& location) {
|
||||
spdlog::trace("{}: {}", extractFunctionName(location.function_name()), fromErrorNr(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
void prepareLogging(spdlog::level::level_enum level) {
|
||||
try {
|
||||
if (level != spdlog::level::off) {
|
||||
auto logger = spdlog::basic_logger_mt("basic_logger", "fakenvapi.log");
|
||||
spdlog::set_default_logger(logger);
|
||||
if (level == spdlog::level::trace)
|
||||
spdlog::set_pattern("[%H:%M:%S.%f] [%L] [thread %t] %v");
|
||||
else
|
||||
spdlog::set_pattern("[%H:%M:%S.%f] [%L] %v");
|
||||
spdlog::set_level(level);
|
||||
spdlog::flush_on(level);
|
||||
}
|
||||
} catch (const spdlog::spdlog_ex &ex) {
|
||||
std::cout << "Log init failed: " << ex.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void closeLogging() {
|
||||
spdlog::default_logger()->flush();
|
||||
spdlog::shutdown();
|
||||
}
|
||||
Regular → Executable
+4
-4
@@ -7,11 +7,11 @@
|
||||
#include <format>
|
||||
#include <source_location>
|
||||
#include "util.h"
|
||||
#include "../include/nvapi.h"
|
||||
#include "../external/nvapi.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "spdlog/sinks/basic_file_sink.h"
|
||||
|
||||
std::string getCurrentTimeFormatted();
|
||||
void log(const std::string& log);
|
||||
NvAPI_Status Ok(const std::source_location &location = std::source_location::current());
|
||||
NvAPI_Status Error(NvAPI_Status status = NVAPI_ERROR, const std::source_location &location = std::source_location::current());
|
||||
void prepareLogging(std::optional<std::string> fileName);
|
||||
void prepareLogging(spdlog::level::level_enum level);
|
||||
void closeLogging();
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <dxgi.h>
|
||||
#if defined __MINGW64__ || defined __MINGW32__
|
||||
#include "../external/d3d12.h"
|
||||
#else
|
||||
#include <d3d12.h>
|
||||
#endif
|
||||
|
||||
#if _MSC_VER && _WIN64
|
||||
#include "../external/ffx_antilag2_dx12.h"
|
||||
#include "../external/ffx_antilag2_dx11.h"
|
||||
#endif
|
||||
|
||||
#include "../external/latencyflex.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
enum Mode {
|
||||
AntiLag2,
|
||||
LatencyFlex,
|
||||
};
|
||||
|
||||
enum CallSpot {
|
||||
SleepCall = 0,
|
||||
InputSample = 1,
|
||||
SimulationStart = 2
|
||||
};
|
||||
|
||||
struct LFXStats {
|
||||
uint64_t latency = 0;
|
||||
uint64_t frame_time = 1;
|
||||
uint64_t target = 0;
|
||||
uint64_t frame_id = 0;
|
||||
bool needs_reset = false;
|
||||
};
|
||||
|
||||
class LowLatency {
|
||||
#if _MSC_VER && _WIN64
|
||||
AMD::AntiLag2DX12::Context context_dx12 = {};
|
||||
AMD::AntiLag2DX11::Context context_dx11 = {};
|
||||
Mode mode = AntiLag2;
|
||||
#else
|
||||
Mode mode = LatencyFlex;
|
||||
#endif
|
||||
lfx::LatencyFleX *lf;
|
||||
unsigned long min_interval_us = 0;
|
||||
bool al_available = false;
|
||||
|
||||
static inline uint64_t GetTimestamp() {
|
||||
LARGE_INTEGER frequency;
|
||||
LARGE_INTEGER counter;
|
||||
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
QueryPerformanceCounter(&counter);
|
||||
return static_cast<uint64_t>(counter.QuadPart) * UINT64_C(1000000000) / static_cast<uint64_t>(frequency.QuadPart);
|
||||
}
|
||||
|
||||
public:
|
||||
CallSpot call_spot = SimulationStart;
|
||||
LFXStats lfx_stats = {};
|
||||
bool fg = false;
|
||||
bool active = true;
|
||||
bool force_lfx = false;
|
||||
|
||||
inline HRESULT init_al2(IUnknown *pDevice) {
|
||||
#if _MSC_VER && _WIN64
|
||||
if (mode == AntiLag2 && !context_dx12.m_pAntiLagAPI && !context_dx11.m_pAntiLagAPI) {
|
||||
ID3D12Device* device = nullptr;
|
||||
HRESULT hr = pDevice->QueryInterface(__uuidof(ID3D12Device), reinterpret_cast<void**>(&device));
|
||||
HRESULT init_return = S_FALSE;
|
||||
if (hr == S_OK) {
|
||||
init_return = AMD::AntiLag2DX12::Initialize(&context_dx12, device);
|
||||
} else {
|
||||
init_return = AMD::AntiLag2DX11::Initialize(&context_dx11);
|
||||
}
|
||||
al_available = init_return == S_OK;
|
||||
}
|
||||
#else
|
||||
al_available = false;
|
||||
#endif
|
||||
return 0x2137;
|
||||
}
|
||||
|
||||
void init_lfx() {
|
||||
lf = new lfx::LatencyFleX();
|
||||
}
|
||||
|
||||
inline HRESULT update() {
|
||||
if (!active) return S_FALSE;
|
||||
|
||||
if (al_available && !force_lfx && (min_interval_us == 0 || !fg))
|
||||
mode = AntiLag2;
|
||||
else
|
||||
mode = LatencyFlex;
|
||||
|
||||
spdlog::debug("LowLatency algo: {}", mode == AntiLag2 ? "AntiLag 2" : "LatencyFlex");
|
||||
spdlog::debug("FG status: {}", fg ? "enabled" : "disabled");
|
||||
|
||||
if (mode == AntiLag2) {
|
||||
#if _MSC_VER && _WIN64
|
||||
if (lfx_stats.frame_id != 1) lfx_stats.needs_reset = true;
|
||||
int max_fps = min_interval_us > 0 ? 1000000 / min_interval_us : 0;
|
||||
if (context_dx12.m_pAntiLagAPI)
|
||||
return AMD::AntiLag2DX12::Update(&context_dx12, true, max_fps);
|
||||
else if (context_dx11.m_pAntiLagAPI)
|
||||
return AMD::AntiLag2DX11::Update(&context_dx11, true, max_fps);
|
||||
#endif
|
||||
} else if (mode == LatencyFlex) {
|
||||
if (lfx_stats.needs_reset) {
|
||||
spdlog::info("LFX Reset");
|
||||
lfx_stats.frame_id = 1;
|
||||
lfx_stats.needs_reset = false;
|
||||
lf->Reset();
|
||||
}
|
||||
uint64_t current_timestamp = GetTimestamp();
|
||||
uint64_t timestamp;
|
||||
|
||||
// Set FPS Limiter
|
||||
lf->target_frame_time = 1000 * min_interval_us;
|
||||
|
||||
lf->EndFrame(lfx_stats.frame_id, current_timestamp, &lfx_stats.latency, &lfx_stats.frame_time);
|
||||
spdlog::debug("LFX latency: {}, frame_time: {}, current_timestamp: {}", lfx_stats.latency, lfx_stats.frame_time, current_timestamp);
|
||||
lfx_stats.frame_id++;
|
||||
lfx_stats.target = lf->GetWaitTarget(lfx_stats.frame_id);
|
||||
|
||||
if (lfx_stats.target > current_timestamp) {
|
||||
uint64_t extra_delay = 0;
|
||||
// uint64_t extra_delay = (lfx_stats.target - current_timestamp) * 0.15;
|
||||
static uint64_t timeout_events = 0;
|
||||
uint64_t timeout_timestamp = current_timestamp + 50000000ULL;
|
||||
if (lfx_stats.target > timeout_timestamp) {
|
||||
timestamp = timeout_timestamp;
|
||||
timeout_events++;
|
||||
lfx_stats.needs_reset = timeout_events > 5;
|
||||
} else {
|
||||
timestamp = lfx_stats.target + extra_delay;
|
||||
timeout_events = 0;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::nanoseconds(lfx_stats.target + extra_delay - current_timestamp));
|
||||
} else {
|
||||
timestamp = current_timestamp;
|
||||
}
|
||||
|
||||
lf->BeginFrame(lfx_stats.frame_id, lfx_stats.target, timestamp);
|
||||
return S_OK;
|
||||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
inline HRESULT set_fg_type(bool interpolated) {
|
||||
#if _MSC_VER && _WIN64
|
||||
if (mode == AntiLag2)
|
||||
return AMD::AntiLag2DX12::SetFrameGenFrameType(&context_dx12, interpolated);
|
||||
#endif
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
inline HRESULT mark_end_of_rendering() {
|
||||
#if _MSC_VER && _WIN64
|
||||
if (mode == AntiLag2)
|
||||
return AMD::AntiLag2DX12::MarkEndOfFrameRendering(&context_dx12);
|
||||
#endif
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
inline void unload() {
|
||||
#if _MSC_VER && _WIN64
|
||||
if (context_dx12.m_pAntiLagAPI) AMD::AntiLag2DX12::DeInitialize(&context_dx12);
|
||||
if (context_dx11.m_pAntiLagAPI) AMD::AntiLag2DX11::DeInitialize(&context_dx11);
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_min_interval_us(unsigned long interval_us) {
|
||||
if (min_interval_us != interval_us) {
|
||||
min_interval_us = interval_us;
|
||||
spdlog::info("Changed max fps: {}", interval_us > 0 ? 1000000 / interval_us : 0);
|
||||
}
|
||||
}
|
||||
|
||||
Mode get_mode() {
|
||||
return mode;
|
||||
}
|
||||
};
|
||||
@@ -4,26 +4,31 @@
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <d3d11.h>
|
||||
#include "../include/nvapi_interface.h"
|
||||
#include "../external/nvapi_interface.h"
|
||||
#if defined __MINGW64__ || defined __MINGW32__
|
||||
#include "../include/d3d12.h"
|
||||
#else
|
||||
#include <d3d12.h>
|
||||
#endif
|
||||
#include "../include/nvapi.h"
|
||||
#include "nvapi.h"
|
||||
#include "../external/nvapi.h"
|
||||
#include "fakenvapi.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||
auto logEnv = std::getenv("NVAPI_LOG");
|
||||
auto logEnv = std::getenv("FAKENVAPI_LOG");
|
||||
#ifdef TESTING
|
||||
bool force_log = true;
|
||||
#else
|
||||
bool force_log = false;
|
||||
#endif
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
if (logEnv && *logEnv == '1')
|
||||
prepareLogging("nvapi-dummy.log");
|
||||
if ((logEnv && *logEnv == '1') || force_log)
|
||||
prepareLogging(spdlog::level::trace);
|
||||
else
|
||||
prepareLogging(std::nullopt);
|
||||
log("--------------");
|
||||
prepareLogging(spdlog::level::off);
|
||||
spdlog::critical("----------------");
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
closeLogging();
|
||||
@@ -36,15 +41,17 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||
NVAPI_INTERFACE_TABLE additional_interface_table[] = {
|
||||
{ "NvAPI_Diag_ReportCallStart", 0x33c7358c },
|
||||
{ "NvAPI_Diag_ReportCallReturn", 0x593e8644 },
|
||||
{ "MISC_unknown", 0xe9b009b9 },
|
||||
{ "MISC_vulkan", 0x17d13d6 }
|
||||
{ "NvAPI_Unknown_1", 0xe9b009b9 },
|
||||
{ "NvAPI_Vulkan_1", 0x17d13d6 },
|
||||
{ "Dummy_GetLatency", 0x21372137 }
|
||||
};
|
||||
|
||||
namespace nvd {
|
||||
extern "C" {
|
||||
NvAPI_Status __cdecl placeholder() {
|
||||
// return Ok();
|
||||
return Error(NVAPI_NO_IMPLEMENTATION);
|
||||
// return Error(NVAPI_NO_IMPLEMENTATION);
|
||||
return NVAPI_NO_IMPLEMENTATION; // no logging
|
||||
}
|
||||
|
||||
static std::unordered_map<NvU32, void*> registry;
|
||||
@@ -67,7 +74,7 @@ namespace nvd {
|
||||
[id](const auto& item) { return item.id == id; });
|
||||
|
||||
if (it == std::end(extended_interface_table)) {
|
||||
log(std::format("NvAPI_QueryInterface (0x{:x}): Unknown interface ID", id));
|
||||
spdlog::debug("NvAPI_QueryInterface (0x{:x}): Unknown interface ID", id);
|
||||
return registry.insert({ id, nullptr }).first->second;
|
||||
}
|
||||
|
||||
@@ -107,6 +114,7 @@ namespace nvd {
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetSleepMode)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetLatencyMarker)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_Sleep)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetReflexSync)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D11_IsNvShaderExtnOpCodeSupported)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D11_BeginUAVOverlap)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D11_EndUAVOverlap)
|
||||
@@ -120,14 +128,17 @@ namespace nvd {
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D12_SetAsyncFrameMarker)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_CreateSession)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_LoadSettings)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_SaveSettings)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_GetBaseProfile)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_GetSetting)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_SetSetting)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_DRS_DestroySession)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_Unknown_1)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_Vulkan_1)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_Unload)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(MISC_unknown)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(MISC_vulkan)
|
||||
INSERT_AND_RETURN_WHEN_EQUALS(Dummy_GetLatency)
|
||||
|
||||
log(std::format("{}: not implemented, placeholder given", it->func));
|
||||
spdlog::debug("{}: not implemented, placeholder given", it->func);
|
||||
return registry.insert({ id, (void*)placeholder }).first->second;
|
||||
// return registry.insert({ id, nullptr }).first->second;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
dll = shared_library(
|
||||
'nvapi'+target_suffix,
|
||||
['main.cpp', 'nvapi.cpp', 'spoofInfo.cpp', 'util.cpp', 'log.cpp'],
|
||||
['main.cpp', 'fakenvapi.cpp', 'util.cpp', 'log.cpp'],
|
||||
name_prefix : '',
|
||||
dependencies : [ lib_dxgi ],
|
||||
include_directories: [ spdlog_headers ],
|
||||
install: true
|
||||
)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "spoofInfo.h"
|
||||
|
||||
namespace spoof {
|
||||
void driverInfo(NV_DISPLAY_DRIVER_INFO* driverInfo) {
|
||||
driverInfo->driverVersion = driverVersion;
|
||||
tonvss(driverInfo->szBuildBranch, buildBranch);
|
||||
driverInfo->bIsDCHDriver = isDCHDriver;
|
||||
driverInfo->bIsNVIDIAStudioPackage = isNVIDIAStudioPackage;
|
||||
driverInfo->bIsNVIDIARTXProductionBranchPackage = isNVIDIARTXProductionBranchPackage;
|
||||
driverInfo->bIsNVIDIARTXNewFeatureBranchPackage = isNVIDIARTXNewFeatureBranchPackage;
|
||||
if (driverInfo->version == 2)
|
||||
tonvss(driverInfo->szBuildBaseBranch, buildBaseBranch);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include "util.h"
|
||||
|
||||
namespace spoof {
|
||||
constexpr NvU32 driverVersion = 99999;
|
||||
constexpr auto buildBranch = "buildBranch";
|
||||
constexpr NvU32 isDCHDriver = 1;
|
||||
constexpr NvU32 isNVIDIAStudioPackage = 1;
|
||||
constexpr NvU32 isNVIDIARTXProductionBranchPackage = 1;
|
||||
constexpr NvU32 isNVIDIARTXNewFeatureBranchPackage = 1;
|
||||
constexpr auto buildBaseBranch = "buildBaseBranch";
|
||||
|
||||
constexpr auto fullGPUName = "NVIDIA GeForce RTX 4090";
|
||||
constexpr NV_GPU_ARCHITECTURE_ID arch = NV_GPU_ARCHITECTURE_AD100;
|
||||
constexpr NV_GPU_ARCH_IMPLEMENTATION_ID implementation = NV_GPU_ARCH_IMPLEMENTATION_AD102;
|
||||
constexpr NV_GPU_CHIP_REVISION revision = NV_GPU_CHIP_REV_UNKNOWN;
|
||||
|
||||
void driverInfo(NV_DISPLAY_DRIVER_INFO* driverInfo);
|
||||
}
|
||||
Regular → Executable
+1
-1
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "../include/nvapi.h"
|
||||
#include "../external/nvapi.h"
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
|
||||
Reference in New Issue
Block a user