From a112a9b95cec908a091b4e913c95ed11ca7986c4 Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Mon, 20 Jan 2025 19:50:30 +0100 Subject: [PATCH] nvapi-d3d: Drop repeated frame IDs Frame IDs must be monotonic per marker type and device/command queue. --- src/nvapi/nvapi_d3d_low_latency_device.cpp | 17 +++++++++++++++++ src/nvapi/nvapi_d3d_low_latency_device.h | 2 ++ tests/nvapi_d3d.cpp | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/nvapi/nvapi_d3d_low_latency_device.cpp b/src/nvapi/nvapi_d3d_low_latency_device.cpp index ea11b787..26f75df8 100644 --- a/src/nvapi/nvapi_d3d_low_latency_device.cpp +++ b/src/nvapi/nvapi_d3d_low_latency_device.cpp @@ -99,6 +99,9 @@ namespace dxvk { if (d3dLowLatencyDevice == nullptr) return false; + if (IsRepeatedFrame(device, frameID, markerType)) + return true; + return SUCCEEDED(d3dLowLatencyDevice->SetLatencyMarker( GetFrameIdGenerator(d3dLowLatencyDevice.ptr())->GetLowLatencyDeviceFrameId(frameID), markerType)); } @@ -108,6 +111,9 @@ namespace dxvk { if (d3dLowLatencyDevice == nullptr) return false; + if (IsRepeatedFrame(commandQueue, frameID, markerType)) + return true; + return SUCCEEDED(d3dLowLatencyDevice->SetLatencyMarker( GetFrameIdGenerator(d3dLowLatencyDevice.ptr())->GetLowLatencyDeviceFrameId(frameID), markerType)); } @@ -151,11 +157,22 @@ namespace dxvk { return {}; } + bool NvapiD3dLowLatencyDevice::IsRepeatedFrame(IUnknown* commandQueue, uint64_t frameID, uint32_t markerType) { + auto key = std::make_pair(commandQueue, markerType); + if (m_lastFrameIdMap.contains(key) && m_lastFrameIdMap[key] == frameID) { + return true; + } + + m_lastFrameIdMap[key] = frameID; + return false; + } + void NvapiD3dLowLatencyDevice::ClearCacheMaps() { std::scoped_lock lock(m_lowLatencyDeviceMutex, m_lowLatencyFrameIdGeneratorMutex); m_lowLatencyDeviceMap.clear(); m_frameIdGeneratorMap.clear(); + m_lastFrameIdMap.clear(); } Com NvapiD3dLowLatencyDevice::GetLowLatencyDevice(IUnknown* device) { diff --git a/src/nvapi/nvapi_d3d_low_latency_device.h b/src/nvapi/nvapi_d3d_low_latency_device.h index 5fbca359..d5ddce97 100644 --- a/src/nvapi/nvapi_d3d_low_latency_device.h +++ b/src/nvapi/nvapi_d3d_low_latency_device.h @@ -40,6 +40,7 @@ namespace dxvk { private: inline static std::unordered_map m_lowLatencyDeviceMap; inline static std::unordered_map> m_frameIdGeneratorMap; + inline static std::map, uint64_t> m_lastFrameIdMap; inline static std::mutex m_lowLatencyDeviceMutex; inline static std::mutex m_lowLatencyFrameIdGeneratorMutex; @@ -47,5 +48,6 @@ namespace dxvk { [[nodiscard]] static Com GetLowLatencyDevice(IUnknown* device); [[nodiscard]] static Com GetLowLatencyDevice(ID3D12CommandQueue* commandQueue); [[nodiscard]] static LowLatencyFrameIdGenerator* GetFrameIdGenerator(ID3DLowLatencyDevice* device); + [[nodiscard]] static bool IsRepeatedFrame(IUnknown* commandQueue, uint64_t frameID, uint32_t markerType); }; } \ No newline at end of file diff --git a/tests/nvapi_d3d.cpp b/tests/nvapi_d3d.cpp index 7b039bed..b7cb478d 100644 --- a/tests/nvapi_d3d.cpp +++ b/tests/nvapi_d3d.cpp @@ -415,6 +415,24 @@ TEST_CASE("D3D Reflex/LatencyFleX depending methods succeed", "[.d3d]") { REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, &latencyMarkerParams) == NVAPI_OK); } + SECTION("SetLatencyMarker drops repeated frame IDs and returns OK") { + uint64_t lowLatencyDeviceFrameId = 163ULL; + REQUIRE_CALL(lowLatencyDevice, SetLatencyMarker(lowLatencyDeviceFrameId, PRESENT_START)) + .TIMES(1) + .RETURN(S_OK); + + SetupResourceFactory(std::move(dxgiFactory), std::move(vk), std::move(nvml), std::move(lfx)); + REQUIRE(NvAPI_Initialize() == NVAPI_OK); + + NV_LATENCY_MARKER_PARAMS latencyMarkerParams{}; + latencyMarkerParams.version = NV_LATENCY_MARKER_PARAMS_VER1; + latencyMarkerParams.frameID = lowLatencyDeviceFrameId; + latencyMarkerParams.markerType = PRESENT_START; + REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, &latencyMarkerParams) == NVAPI_OK); + REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, &latencyMarkerParams) == NVAPI_OK); + REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, &latencyMarkerParams) == NVAPI_OK); + } + SECTION("SetLatencyMarker correctly produces monotonic frame ids for a sequence of unique application frame ids") { REQUIRE_CALL(lowLatencyDevice, SetLatencySleepMode(true, false, 750U)) .RETURN(S_OK);