diff options
author | Stelios Tsampas | 2023-11-23 00:53:42 +0200 |
---|---|---|
committer | Stelios Tsampas | 2023-11-23 00:53:42 +0200 |
commit | fcac8fefb30d9b38144ae109b304e4a8d44726a8 (patch) | |
tree | edf9e4cbfc6b735fee7b79319d7fa0ecbca54f42 | |
parent | 004abfb951f37cd79f994e0ceff99b30fd5d5958 (diff) | |
download | aur-fcac8fefb30d9b38144ae109b304e4a8d44726a8.tar.gz |
[wine etc] Remove reflex patches
-rw-r--r-- | 82-nv_low_latency_dxvk_nvapi.patch | 1202 | ||||
-rw-r--r-- | PKGBUILD.personal | 4 |
2 files changed, 0 insertions, 1206 deletions
diff --git a/82-nv_low_latency_dxvk_nvapi.patch b/82-nv_low_latency_dxvk_nvapi.patch deleted file mode 100644 index ce5b3ccfee79..000000000000 --- a/82-nv_low_latency_dxvk_nvapi.patch +++ /dev/null @@ -1,1202 +0,0 @@ -From 0738bfdd9b9fbdcba019bfdbcd2e29ffc8fe557a Mon Sep 17 00:00:00 2001 -From: Eric Sullivan <esullivan@nvidia.com> -Date: Fri, 13 Oct 2023 01:38:30 +0000 -Subject: [PATCH] nvapi: Add support for Reflex - -The intent of this commit is to enable Reflex for all D3D11, -and D3D12 titles using dxvk-nvapi. It does this through a new -device interface called ID3DLowLatencyDevice. This interface -will be implemented by ID3D12Device in vkd3d-proton, and -ID3D11Device in dxvk. - -To provide compatibility with LatencyFleX this change will -only use the ID3DLowLatencyDevice interface when LatencyFleX -is not detected. ---- - src/d3d/nvapi_d3d_instance.cpp | 40 ++- - src/d3d/nvapi_d3d_instance.h | 14 +- - src/d3d/nvapi_d3d_low_latency_device.cpp | 58 +++++ - src/d3d/nvapi_d3d_low_latency_device.h | 23 ++ - src/d3d12/nvapi_d3d12_device.cpp | 26 ++ - src/d3d12/nvapi_d3d12_device.h | 4 + - src/meson.build | 2 + - src/nvapi_d3d.cpp | 76 ++++-- - src/nvapi_d3d12.cpp | 52 ++++ - src/nvapi_interface.cpp | 2 + - src/shared/shared_interfaces.cpp | 3 + - src/shared/shared_interfaces.h | 61 +++++ - src/vkd3d-proton/vkd3d-proton_interfaces.cpp | 1 + - src/vkd3d-proton/vkd3d-proton_interfaces.h | 17 +- - tests/meson.build | 2 + - tests/nvapi_d3d.cpp | 252 ++++++++++++++++++- - tests/nvapi_d3d12.cpp | 126 ++++++++++ - tests/nvapi_d3d12_mocks.h | 25 ++ - tests/nvapi_d3d_mocks.h | 12 + - tests/nvapi_tests_private.h | 1 + - 20 files changed, 750 insertions(+), 47 deletions(-) - create mode 100644 src/d3d/nvapi_d3d_low_latency_device.cpp - create mode 100644 src/d3d/nvapi_d3d_low_latency_device.h - create mode 100644 src/shared/shared_interfaces.cpp - create mode 100644 src/shared/shared_interfaces.h - -diff --git a/src/d3d/nvapi_d3d_instance.cpp b/src/d3d/nvapi_d3d_instance.cpp -index 6cdf2609..e1687ad7 100644 ---- a/src/d3d/nvapi_d3d_instance.cpp -+++ b/src/d3d/nvapi_d3d_instance.cpp -@@ -1,4 +1,5 @@ - #include "../util/util_log.h" -+#include "nvapi_d3d_low_latency_device.h" - #include "nvapi_d3d_instance.h" - - namespace dxvk { -@@ -13,25 +14,40 @@ namespace dxvk { - log::write("LatencyFleX loaded and initialized successfully"); - } - -- bool NvapiD3dInstance::IsReflexAvailable() { -- return m_lfx->IsAvailable(); -+ bool NvapiD3dInstance::IsReflexAvailable(IUnknown* device) { -+ return NvapiD3dLowLatencyDevice::SupportsLowLatency(device) || m_lfx->IsAvailable(); - } - -- bool NvapiD3dInstance::IsReflexEnabled() const { -- return m_isLfxEnabled; -+ bool NvapiD3dInstance::IsLowLatencyEnabled() const { -+ return m_isLowLatencyEnabled; - } - -- void NvapiD3dInstance::SetReflexEnabled(bool value) { -- m_isLfxEnabled = value; -+ bool NvapiD3dInstance::IsUsingLfx() const { -+ return m_lfx->IsAvailable(); - } - -- void NvapiD3dInstance::Sleep() { -- if (m_isLfxEnabled) -- m_lfx->WaitAndBeginFrame(); -+ bool NvapiD3dInstance::SetReflexMode(IUnknown* device, bool enable, bool boost, uint32_t frameTimeUs) { -+ bool result = true; -+ -+ if (IsReflexAvailable(device)) -+ m_isLowLatencyEnabled = enable; -+ -+ if (m_lfx->IsAvailable() && enable) -+ m_lfx->SetTargetFrameTime(frameTimeUs * kNanoInMicro); -+ else if (NvapiD3dLowLatencyDevice::SupportsLowLatency(device)) -+ result = NvapiD3dLowLatencyDevice::SetLatencySleepMode(device, enable, boost, frameTimeUs); -+ -+ return result; - } - -- void NvapiD3dInstance::SetTargetFrameTime(uint64_t frameTimeUs) { -- constexpr uint64_t kNanoInMicro = 1000; -- m_lfx->SetTargetFrameTime(frameTimeUs * kNanoInMicro); -+ bool NvapiD3dInstance::Sleep(IUnknown* device) { -+ bool result = true; -+ -+ if (m_lfx->IsAvailable() && m_isLowLatencyEnabled) -+ m_lfx->WaitAndBeginFrame(); -+ else if (NvapiD3dLowLatencyDevice::SupportsLowLatency(device)) -+ result = NvapiD3dLowLatencyDevice::LatencySleep(device); -+ -+ return result; - } - } -\ No newline at end of file -diff --git a/src/d3d/nvapi_d3d_instance.h b/src/d3d/nvapi_d3d_instance.h -index 5a223714..eb7d9388 100644 ---- a/src/d3d/nvapi_d3d_instance.h -+++ b/src/d3d/nvapi_d3d_instance.h -@@ -10,15 +10,17 @@ namespace dxvk { - ~NvapiD3dInstance(); - - void Initialize(); -- [[nodiscard]] bool IsReflexAvailable(); -- [[nodiscard]] bool IsReflexEnabled() const; -- void SetReflexEnabled(bool value); -- void Sleep(); -- void SetTargetFrameTime(uint64_t frameTimeUs); -+ [[nodiscard]] bool IsReflexAvailable(IUnknown* device); -+ [[nodiscard]] bool IsLowLatencyEnabled() const; -+ [[nodiscard]] bool IsUsingLfx() const; -+ [[nodiscard]] bool SetReflexMode(IUnknown* device, bool enable, bool boost, uint32_t frameTimeUs); -+ [[nodiscard]] bool Sleep(IUnknown* device); - - private: -+ constexpr static uint64_t kNanoInMicro = 1000; -+ - ResourceFactory& m_resourceFactory; - std::unique_ptr<Lfx> m_lfx; -- bool m_isLfxEnabled = false; -+ bool m_isLowLatencyEnabled = false; - }; - } -\ No newline at end of file -diff --git a/src/d3d/nvapi_d3d_low_latency_device.cpp b/src/d3d/nvapi_d3d_low_latency_device.cpp -new file mode 100644 -index 00000000..37c8dd75 ---- /dev/null -+++ b/src/d3d/nvapi_d3d_low_latency_device.cpp -@@ -0,0 +1,58 @@ -+#include "nvapi_d3d_low_latency_device.h" -+ -+namespace dxvk { -+ bool NvapiD3dLowLatencyDevice::SupportsLowLatency(IUnknown* device) { -+ auto d3dLowLatencyDevice = GetLowLatencyDevice(device); -+ if (d3dLowLatencyDevice == nullptr) -+ return false; -+ -+ return d3dLowLatencyDevice->SupportsLowLatency(); -+ } -+ -+ bool NvapiD3dLowLatencyDevice::LatencySleep(IUnknown* device) { -+ auto d3dLowLatencyDevice = GetLowLatencyDevice(device); -+ if (d3dLowLatencyDevice == nullptr) -+ return false; -+ -+ return SUCCEEDED(d3dLowLatencyDevice->LatencySleep()); -+ } -+ -+ bool NvapiD3dLowLatencyDevice::SetLatencySleepMode(IUnknown* device, bool lowLatencyMode, bool lowLatencyBoost, uint32_t minimumIntervalUs) { -+ auto d3dLowLatencyDevice = GetLowLatencyDevice(device); -+ if (d3dLowLatencyDevice == nullptr) -+ return false; -+ -+ return SUCCEEDED(d3dLowLatencyDevice->SetLatencySleepMode(lowLatencyMode, lowLatencyBoost, minimumIntervalUs)); -+ } -+ -+ bool NvapiD3dLowLatencyDevice::GetLatencyInfo(IUnknown* device, D3D_LATENCY_RESULTS* latencyResults) { -+ auto d3dLowLatencyDevice = GetLowLatencyDevice(device); -+ if (d3dLowLatencyDevice == nullptr) -+ return false; -+ -+ return SUCCEEDED(d3dLowLatencyDevice->GetLatencyInfo(latencyResults)); -+ } -+ -+ bool NvapiD3dLowLatencyDevice::SetLatencyMarker(IUnknown* device, uint64_t frameID, uint32_t markerType) { -+ auto d3dLowLatencyDevice = GetLowLatencyDevice(device); -+ if (d3dLowLatencyDevice == nullptr) -+ return false; -+ -+ return SUCCEEDED(d3dLowLatencyDevice->SetLatencyMarker(frameID, markerType)); -+ } -+ -+ Com<ID3DLowLatencyDevice> NvapiD3dLowLatencyDevice::GetLowLatencyDevice(IUnknown* device) { -+ std::scoped_lock lock(m_LowLatencyDeviceMutex); -+ auto it = m_lowLatencyDeviceMap.find(device); -+ if (it != m_lowLatencyDeviceMap.end()) -+ return it->second; -+ -+ Com<ID3DLowLatencyDevice> d3dLowLatencyDevice; -+ if (FAILED(device->QueryInterface(IID_PPV_ARGS(&d3dLowLatencyDevice)))) -+ return nullptr; -+ -+ m_lowLatencyDeviceMap.emplace(device, d3dLowLatencyDevice.ptr()); -+ -+ return d3dLowLatencyDevice; -+ } -+} -diff --git a/src/d3d/nvapi_d3d_low_latency_device.h b/src/d3d/nvapi_d3d_low_latency_device.h -new file mode 100644 -index 00000000..77938340 ---- /dev/null -+++ b/src/d3d/nvapi_d3d_low_latency_device.h -@@ -0,0 +1,23 @@ -+#pragma once -+ -+#include "../nvapi_private.h" -+#include "../shared/shared_interfaces.h" -+#include "../util/com_pointer.h" -+ -+namespace dxvk { -+ class NvapiD3dLowLatencyDevice { -+ public: -+ static bool SupportsLowLatency(IUnknown* device); -+ static bool LatencySleep(IUnknown* device); -+ static bool SetLatencySleepMode(IUnknown* device, bool lowLatencyMode, bool lowLatencyBoost, uint32_t minimumIntervalUs); -+ static bool GetLatencyInfo(IUnknown* device, D3D_LATENCY_RESULTS* latencyResults); -+ static bool SetLatencyMarker(IUnknown* device, uint64_t frameID, uint32_t markerType); -+ -+ private: -+ inline static std::unordered_map<IUnknown*, ID3DLowLatencyDevice*> m_lowLatencyDeviceMap; -+ -+ inline static std::mutex m_LowLatencyDeviceMutex; -+ -+ [[nodiscard]] static Com<ID3DLowLatencyDevice> GetLowLatencyDevice(IUnknown* device); -+ }; -+} -\ No newline at end of file -diff --git a/src/d3d12/nvapi_d3d12_device.cpp b/src/d3d12/nvapi_d3d12_device.cpp -index 0d30d347..b69fa982 100644 ---- a/src/d3d12/nvapi_d3d12_device.cpp -+++ b/src/d3d12/nvapi_d3d12_device.cpp -@@ -81,6 +81,14 @@ namespace dxvk { - return SUCCEEDED(cubinDevice->GetCudaSurfaceObject(uavHandle, reinterpret_cast<UINT32*>(cudaSurfaceHandle))); - } - -+ bool NvapiD3d12Device::NotifyOutOfBandCommandQueue(ID3D12CommandQueue* commandQueue, D3D12_OUT_OF_BAND_CQ_TYPE type) { -+ auto commandQueueExt = GetCommandQueueExt(commandQueue); -+ if (commandQueueExt == nullptr) -+ return false; -+ -+ return SUCCEEDED(commandQueueExt->NotifyOutOfBandCommandQueue(type)); -+ } -+ - bool NvapiD3d12Device::LaunchCubinShader(ID3D12GraphicsCommandList* commandList, NVDX_ObjectHandle pShader, NvU32 blockX, NvU32 blockY, NvU32 blockZ, const void* params, NvU32 paramSize) { - auto commandListExt = GetCommandListExt(commandList); - if (!commandListExt.has_value()) -@@ -146,6 +154,22 @@ namespace dxvk { - return deviceExt; - } - -+ Com<ID3D12CommandQueueExt> NvapiD3d12Device::GetCommandQueueExt(ID3D12CommandQueue* commandQueue) { -+ std::scoped_lock lock(m_commandQueueMutex); -+ auto it = m_commandQueueMap.find(commandQueue); -+ if (it != m_commandQueueMap.end()) -+ return it->second; -+ -+ Com<ID3D12CommandQueueExt> commandQueueExt; -+ if (FAILED(commandQueue->QueryInterface(IID_PPV_ARGS(&commandQueueExt)))) -+ return nullptr; -+ -+ if (commandQueueExt != nullptr) -+ m_commandQueueMap.emplace(commandQueue, commandQueueExt.ptr()); -+ -+ return commandQueueExt; -+ } -+ - std::optional<NvapiD3d12Device::CommandListExtWithVersion> NvapiD3d12Device::GetCommandListExt(ID3D12GraphicsCommandList* commandList) { - std::scoped_lock lock(m_commandListMutex); - auto it = m_commandListMap.find(commandList); -@@ -169,11 +193,13 @@ namespace dxvk { - } - - void NvapiD3d12Device::ClearCacheMaps() { -+ std::scoped_lock commandQueueLock(m_commandQueueMutex); - std::scoped_lock commandListLock(m_commandListMutex); - std::scoped_lock cubinDeviceLock(m_cubinDeviceMutex); - std::scoped_lock cubinSmemLock(m_cubinSmemMutex); - - m_cubinDeviceMap.clear(); -+ m_commandQueueMap.clear(); - m_commandListMap.clear(); - m_cubinSmemMap.clear(); - } -diff --git a/src/d3d12/nvapi_d3d12_device.h b/src/d3d12/nvapi_d3d12_device.h -index ef419d34..386de906 100644 ---- a/src/d3d12/nvapi_d3d12_device.h -+++ b/src/d3d12/nvapi_d3d12_device.h -@@ -24,6 +24,7 @@ namespace dxvk { - static bool DestroyCubinComputeShader(ID3D12Device* device, NVDX_ObjectHandle shader); - static bool GetCudaTextureObject(ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE srvHandle, D3D12_CPU_DESCRIPTOR_HANDLE samplerHandle, NvU32* cudaTextureHandle); - static bool GetCudaSurfaceObject(ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE uavHandle, NvU32* cudaSurfaceHandle); -+ static bool NotifyOutOfBandCommandQueue(ID3D12CommandQueue* commandQueue, D3D12_OUT_OF_BAND_CQ_TYPE type); - static bool LaunchCubinShader(ID3D12GraphicsCommandList* commandList, NVDX_ObjectHandle shader, NvU32 blockX, NvU32 blockY, NvU32 blockZ, const void* params, NvU32 paramSize); - static bool CaptureUAVInfo(ID3D12Device* device, NVAPI_UAV_INFO* uavInfo); - static bool IsFatbinPTXSupported(ID3D12Device* device); -@@ -32,15 +33,18 @@ namespace dxvk { - - private: - inline static std::unordered_map<ID3D12Device*, ID3D12DeviceExt*> m_cubinDeviceMap; -+ inline static std::unordered_map<ID3D12CommandQueue*, ID3D12CommandQueueExt*> m_commandQueueMap; - inline static std::unordered_map<ID3D12GraphicsCommandList*, CommandListExtWithVersion> m_commandListMap; - inline static std::unordered_map<NVDX_ObjectHandle, NvU32> m_cubinSmemMap; - - inline static std::mutex m_commandListMutex; -+ inline static std::mutex m_commandQueueMutex; - inline static std::mutex m_cubinDeviceMutex; - inline static std::mutex m_cubinSmemMutex; - - [[nodiscard]] static Com<ID3D12DeviceExt> GetCubinDevice(ID3D12Device* device); - [[nodiscard]] static Com<ID3D12DeviceExt> GetDeviceExt(ID3D12Device* device, D3D12_VK_EXTENSION extension); -+ [[nodiscard]] static Com<ID3D12CommandQueueExt> GetCommandQueueExt(ID3D12CommandQueue* commandQueue); - [[nodiscard]] static std::optional<CommandListExtWithVersion> GetCommandListExt(ID3D12GraphicsCommandList* commandList); - }; - } -diff --git a/src/meson.build b/src/meson.build -index 98410c0f..daabb3f8 100644 ---- a/src/meson.build -+++ b/src/meson.build -@@ -1,6 +1,7 @@ - nvapi_src = files([ - 'dxvk/dxvk_interfaces.cpp', - 'vkd3d-proton/vkd3d-proton_interfaces.cpp', -+ 'shared/shared_interfaces.cpp', - 'util/util_string.cpp', - 'util/util_env.cpp', - 'util/util_log.cpp', -@@ -12,6 +13,7 @@ nvapi_src = files([ - 'resource_factory.cpp', - 'd3d/lfx.cpp', - 'd3d/nvapi_d3d_instance.cpp', -+ 'd3d/nvapi_d3d_low_latency_device.cpp', - 'd3d11/nvapi_d3d11_device.cpp', - 'd3d12/nvapi_d3d12_device.cpp', - 'nvapi_globals.cpp', -diff --git a/src/nvapi_d3d.cpp b/src/nvapi_d3d.cpp -index 7f1168bf..166abc06 100644 ---- a/src/nvapi_d3d.cpp -+++ b/src/nvapi_d3d.cpp -@@ -1,3 +1,5 @@ -+#include "dxvk/dxvk_interfaces.h" -+#include "d3d/nvapi_d3d_low_latency_device.h" - #include "nvapi_private.h" - #include "nvapi_globals.h" - #include "util/util_statuscode.h" -@@ -106,23 +108,26 @@ extern "C" { - - NvAPI_Status __cdecl NvAPI_D3D_Sleep(IUnknown* pDevice) { - constexpr auto n = __func__; -+ static bool alreadyLoggedNoReflex = false; -+ static bool alreadyLoggedError = false; - static bool alreadyLoggedOk = false; -- static bool alreadyLoggedNoLfx = false; - - if (nvapiAdapterRegistry == nullptr) - return ApiNotInitialized(n); - -- if (!nvapiD3dInstance->IsReflexAvailable()) -- return NoImplementation(n, alreadyLoggedNoLfx); -+ if (!nvapiD3dInstance->IsReflexAvailable(pDevice)) -+ return NoImplementation(n, alreadyLoggedNoReflex); - -- nvapiD3dInstance->Sleep(); -+ if (!nvapiD3dInstance->Sleep(pDevice)) -+ return Error(n, alreadyLoggedError); - - return Ok(n, alreadyLoggedOk); - } - - NvAPI_Status __cdecl NvAPI_D3D_SetSleepMode(IUnknown* pDevice, NV_SET_SLEEP_MODE_PARAMS* pSetSleepModeParams) { - constexpr auto n = __func__; -- static bool alreadyLoggedNoLfx = false; -+ static bool alreadyLoggedNoReflex = false; -+ static bool alreadyLoggedError = false; - - if (nvapiAdapterRegistry == nullptr) - return ApiNotInitialized(n); -@@ -130,19 +135,19 @@ extern "C" { - if (pSetSleepModeParams->version != NV_SET_SLEEP_MODE_PARAMS_VER1) - return IncompatibleStructVersion(n); - -- if (!nvapiD3dInstance->IsReflexAvailable()) -- return NoImplementation(n, alreadyLoggedNoLfx); -+ if (!nvapiD3dInstance->IsReflexAvailable(pDevice)) -+ return NoImplementation(n, alreadyLoggedNoReflex); - -- nvapiD3dInstance->SetReflexEnabled(pSetSleepModeParams->bLowLatencyMode); -- if (pSetSleepModeParams->bLowLatencyMode) -- nvapiD3dInstance->SetTargetFrameTime(pSetSleepModeParams->minimumIntervalUs); -+ if (!nvapiD3dInstance->SetReflexMode(pDevice, pSetSleepModeParams->bLowLatencyMode, pSetSleepModeParams->bLowLatencyBoost, pSetSleepModeParams->minimumIntervalUs)) -+ return Error(n, alreadyLoggedError); - - return Ok(str::format(n, " (", pSetSleepModeParams->bLowLatencyMode ? (str::format("Enabled/", pSetSleepModeParams->minimumIntervalUs, "us")) : "Disabled", ")")); - } - - NvAPI_Status __cdecl NvAPI_D3D_GetSleepStatus(IUnknown* pDevice, NV_GET_SLEEP_STATUS_PARAMS* pGetSleepStatusParams) { - constexpr auto n = __func__; -- static bool alreadyLoggedNoLfx = false; -+ static bool alreadyLoggedNoReflex = false; -+ static bool alreadyLoggedOk = false; - - if (nvapiAdapterRegistry == nullptr) - return ApiNotInitialized(n); -@@ -150,20 +155,53 @@ extern "C" { - if (pGetSleepStatusParams->version != NV_GET_SLEEP_STATUS_PARAMS_VER1) - return IncompatibleStructVersion(n); - -- if (!nvapiD3dInstance->IsReflexAvailable()) -- return NoImplementation(n, alreadyLoggedNoLfx); -+ if (!nvapiD3dInstance->IsReflexAvailable(pDevice)) -+ return NoImplementation(n, alreadyLoggedNoReflex); - -- pGetSleepStatusParams->bLowLatencyMode = nvapiD3dInstance->IsReflexEnabled(); -- return Ok(n); -+ pGetSleepStatusParams->bLowLatencyMode = nvapiD3dInstance->IsLowLatencyEnabled(); -+ -+ return Ok(n, alreadyLoggedOk); - } - - NvAPI_Status __cdecl NvAPI_D3D_GetLatency(IUnknown* pDev, NV_LATENCY_RESULT_PARAMS* pGetLatencyParams) { -- static bool alreadyLogged = false; -- return NoImplementation(__func__, alreadyLogged); -+ constexpr auto n = __func__; -+ static bool alreadyLoggedNoImpl = false; -+ static bool alreadyLoggedError = false; -+ static bool alreadyLoggedOk = false; -+ -+ if (nvapiAdapterRegistry == nullptr) -+ return ApiNotInitialized(n); -+ -+ if (pGetLatencyParams->version != NV_LATENCY_RESULT_PARAMS_VER1) -+ return IncompatibleStructVersion(n); -+ -+ if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pDev)) -+ return NoImplementation(n, alreadyLoggedNoImpl); -+ -+ if (!NvapiD3dLowLatencyDevice::GetLatencyInfo(pDev, reinterpret_cast<D3D_LATENCY_RESULTS*>(pGetLatencyParams))) -+ return Error(n, alreadyLoggedError); -+ -+ return Ok(n, alreadyLoggedOk); - } - - NvAPI_Status __cdecl NvAPI_D3D_SetLatencyMarker(IUnknown* pDev, NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) { -- static bool alreadyLogged = false; -- return NoImplementation(__func__, alreadyLogged); -+ constexpr auto n = __func__; -+ static bool alreadyLoggedNoImpl = false; -+ static bool alreadyLoggedError = false; -+ static bool alreadyLoggedOk = false; -+ -+ if (nvapiAdapterRegistry == nullptr) -+ return ApiNotInitialized(n); -+ -+ if (pSetLatencyMarkerParams->version != NV_LATENCY_MARKER_PARAMS_VER1) -+ return IncompatibleStructVersion(n); -+ -+ if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pDev)) -+ return NoImplementation(n, alreadyLoggedNoImpl); -+ -+ if (!NvapiD3dLowLatencyDevice::SetLatencyMarker(pDev, pSetLatencyMarkerParams->frameID, pSetLatencyMarkerParams->markerType)) -+ return Error(n, alreadyLoggedError); -+ -+ return Ok(n, alreadyLoggedOk); - } - } -diff --git a/src/nvapi_d3d12.cpp b/src/nvapi_d3d12.cpp -index aadd7f22..c989cc42 100644 ---- a/src/nvapi_d3d12.cpp -+++ b/src/nvapi_d3d12.cpp -@@ -1,5 +1,6 @@ - #include "nvapi_private.h" - #include "nvapi_globals.h" -+#include "d3d/nvapi_d3d_low_latency_device.h" - #include "d3d12/nvapi_d3d12_device.h" - #include "util/util_statuscode.h" - #include "util/util_op_code.h" -@@ -397,4 +398,55 @@ extern "C" { - - return Ok(n, alreadyLoggedOk); - } -+ -+ NvAPI_Status __cdecl NvAPI_D3D12_NotifyOutOfBandCommandQueue(ID3D12CommandQueue* pCommandQueue, NV_OUT_OF_BAND_CQ_TYPE cqType) { -+ constexpr auto n = __func__; -+ static bool alreadyLoggedError = false; -+ static bool alreadyLoggedOk = false; -+ -+ if (nvapiAdapterRegistry == nullptr) -+ return ApiNotInitialized(n); -+ -+ if (pCommandQueue == nullptr) -+ return InvalidArgument(n); -+ -+ ID3D12Device* pDevice; -+ if (FAILED(pCommandQueue->GetDevice(IID_PPV_ARGS(&pDevice)))) -+ return InvalidArgument(n); -+ -+ if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pDevice)) -+ return NoImplementation(n); -+ -+ if (!NvapiD3d12Device::NotifyOutOfBandCommandQueue(pCommandQueue, static_cast<D3D12_OUT_OF_BAND_CQ_TYPE>(cqType))) -+ return Error(n, alreadyLoggedError); -+ -+ return Ok(n, alreadyLoggedOk); -+ } -+ -+ NvAPI_Status __cdecl NvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue, NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams) { -+ constexpr auto n = __func__; -+ static bool alreadyLoggedError = false; -+ static bool alreadyLoggedOk = false; -+ -+ if (nvapiAdapterRegistry == nullptr) -+ return ApiNotInitialized(n); -+ -+ if (pSetLatencyMarkerParams->version != NV_LATENCY_MARKER_PARAMS_VER1) -+ return IncompatibleStructVersion(n); -+ -+ if (pCommandQueue == nullptr) -+ return InvalidArgument(n); -+ -+ ID3D12Device* pDevice; -+ if (FAILED(pCommandQueue->GetDevice(IID_PPV_ARGS(&pDevice)))) -+ return InvalidArgument(n); -+ -+ if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pDevice)) -+ return NoImplementation(n); -+ -+ if (!NvapiD3dLowLatencyDevice::SetLatencyMarker(pDevice, pSetLatencyMarkerParams->frameID, pSetLatencyMarkerParams->markerType)) -+ return Error(n, alreadyLoggedError); -+ -+ return Ok(n, alreadyLoggedOk); -+ } - } -diff --git a/src/nvapi_interface.cpp b/src/nvapi_interface.cpp -index b461166e..4b6f24b3 100644 ---- a/src/nvapi_interface.cpp -+++ b/src/nvapi_interface.cpp -@@ -69,6 +69,8 @@ extern "C" { - INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D12_GetRaytracingCaps) - INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D12_GetRaytracingAccelerationStructurePrebuildInfoEx) - INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D12_BuildRaytracingAccelerationStructureEx) -+ INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D12_NotifyOutOfBandCommandQueue) -+ INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D12_SetAsyncFrameMarker) - INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_GetObjectHandleForResource) - INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetResourceHint) - INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_GetCurrentSLIState) -diff --git a/src/shared/shared_interfaces.cpp b/src/shared/shared_interfaces.cpp -new file mode 100644 -index 00000000..2d675ebc ---- /dev/null -+++ b/src/shared/shared_interfaces.cpp -@@ -0,0 +1,3 @@ -+#include "shared_interfaces.h" -+ -+const GUID ID3DLowLatencyDevice::guid = {0xf3112584, 0x41f9, 0x348d, {0xa5, 0x9b, 0x00, 0xb7, 0xe1, 0xd2, 0x85, 0xd6}}; -diff --git a/src/shared/shared_interfaces.h b/src/shared/shared_interfaces.h -new file mode 100644 -index 00000000..bc5e0baa ---- /dev/null -+++ b/src/shared/shared_interfaces.h -@@ -0,0 +1,61 @@ -+#pragma once -+ -+#include "../nvapi_private.h" -+ -+#ifdef __GNUC__ -+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" -+#endif // __GNUC__ -+ -+#define SHARED_DEFINE_GUID(iface) \ -+ template <> \ -+ inline GUID const& __mingw_uuidof<iface>() { return iface::guid; } -+ -+/** -+ * \brief Frame Report Info -+ */ -+typedef struct D3D_LATENCY_RESULTS { -+ UINT32 version; -+ struct D3D_FRAME_REPORT { -+ UINT64 frameID; -+ UINT64 inputSampleTime; -+ UINT64 simStartTime; -+ UINT64 simEndTime; -+ UINT64 renderSubmitStartTime; -+ UINT64 renderSubmitEndTime; -+ UINT64 presentStartTime; -+ UINT64 presentEndTime; -+ UINT64 driverStartTime; -+ UINT64 driverEndTime; -+ UINT64 osRenderQueueStartTime; -+ UINT64 osRenderQueueEndTime; -+ UINT64 gpuRenderStartTime; -+ UINT64 gpuRenderEndTime; -+ UINT32 gpuActiveRenderTimeUs; -+ UINT32 gpuFrameTimeUs; -+ UINT8 rsvd[120]; -+ } frame_reports[64]; -+ UINT8 rsvd[32]; -+} D3D_LATENCY_RESULTS; -+ -+MIDL_INTERFACE("f3112584-41f9-348d-a59b-00b7e1d285d6") -+ID3DLowLatencyDevice : public IUnknown { -+ static const GUID guid; -+ -+ virtual BOOL STDMETHODCALLTYPE SupportsLowLatency() = 0; -+ -+ virtual HRESULT STDMETHODCALLTYPE LatencySleep() = 0; -+ -+ virtual HRESULT STDMETHODCALLTYPE SetLatencySleepMode( -+ BOOL lowLatencyMode, -+ BOOL lowLatencyBoost, -+ uint32_t minimumIntervalUs) = 0; -+ -+ virtual HRESULT STDMETHODCALLTYPE SetLatencyMarker( -+ uint64_t frameID, -+ uint32_t markerType) = 0; -+ -+ virtual HRESULT STDMETHODCALLTYPE GetLatencyInfo( -+ D3D_LATENCY_RESULTS * latencyResults) = 0; -+}; -+ -+SHARED_DEFINE_GUID(ID3DLowLatencyDevice) -diff --git a/src/vkd3d-proton/vkd3d-proton_interfaces.cpp b/src/vkd3d-proton/vkd3d-proton_interfaces.cpp -index 03a4acd1..7b41fb7d 100644 ---- a/src/vkd3d-proton/vkd3d-proton_interfaces.cpp -+++ b/src/vkd3d-proton/vkd3d-proton_interfaces.cpp -@@ -20,3 +20,4 @@ - const GUID ID3D12DeviceExt::guid = {0x11ea7a1a, 0x0f6a, 0x49bf, {0xb6, 0x12, 0x3e, 0x30, 0xf8, 0xe2, 0x01, 0xdd}}; - const GUID ID3D12GraphicsCommandListExt::guid = {0x77a86b09, 0x2bea, 0x4801, {0xb8, 0x9a, 0x37, 0x64, 0x8e, 0x10, 0x4a, 0xf1}}; - const GUID ID3D12GraphicsCommandListExt1::guid = {0xd53b0028, 0xafb4, 0x4b65, {0xa4, 0xf1, 0x7b, 0x0d, 0xaa, 0xa6, 0x5b, 0x4f}}; -+const GUID ID3D12CommandQueueExt::guid = {0x40ed3f96, 0xe773, 0xe9bc, {0xfc, 0x0c, 0xe9, 0x55, 0x60, 0xc9, 0x9a, 0xd6}}; -diff --git a/src/vkd3d-proton/vkd3d-proton_interfaces.h b/src/vkd3d-proton/vkd3d-proton_interfaces.h -index 8f388ac6..b16f38d7 100644 ---- a/src/vkd3d-proton/vkd3d-proton_interfaces.h -+++ b/src/vkd3d-proton/vkd3d-proton_interfaces.h -@@ -29,7 +29,13 @@ - - enum D3D12_VK_EXTENSION : uint32_t { - D3D12_VK_NVX_BINARY_IMPORT = 0x1, -- D3D12_VK_NVX_IMAGE_VIEW_HANDLE = 0x2 -+ D3D12_VK_NVX_IMAGE_VIEW_HANDLE = 0x2, -+ D3D12_VK_NV_LOW_LATENCY_2 = 0x3 -+}; -+ -+enum D3D12_OUT_OF_BAND_CQ_TYPE : uint32_t { -+ D3D_OUT_OF_BAND_RENDER = 0x0, -+ D3D_OUT_OF_BAND_PRESENT = 0x1 - }; - - struct D3D12_CUBIN_DATA_HANDLE { -@@ -114,6 +120,15 @@ ID3D12GraphicsCommandListExt1 : public ID3D12GraphicsCommandListExt { - UINT32 raw_params_count) = 0; - }; - -+MIDL_INTERFACE("40ed3f96-e773-e9bc-fc0c-e95560c99ad6") -+ID3D12CommandQueueExt : public IUnknown { -+ static const GUID guid; -+ -+ virtual HRESULT STDMETHODCALLTYPE NotifyOutOfBandCommandQueue( -+ D3D12_OUT_OF_BAND_CQ_TYPE type) = 0; -+}; -+ - VKD3D_PROTON_GUID(ID3D12DeviceExt) - VKD3D_PROTON_GUID(ID3D12GraphicsCommandListExt) - VKD3D_PROTON_GUID(ID3D12GraphicsCommandListExt1) -+VKD3D_PROTON_GUID(ID3D12CommandQueueExt) -diff --git a/tests/meson.build b/tests/meson.build -index 5aca1d56..c967aed8 100644 ---- a/tests/meson.build -+++ b/tests/meson.build -@@ -1,6 +1,7 @@ - nvapi_src = files([ - '../src/dxvk/dxvk_interfaces.cpp', - '../src/vkd3d-proton/vkd3d-proton_interfaces.cpp', -+ '../src/shared/shared_interfaces.cpp', - '../src/util/util_string.cpp', - '../src/util/util_env.cpp', - '../src/util/util_log.cpp', -@@ -8,6 +9,7 @@ nvapi_src = files([ - '../src/sysinfo/nvml.cpp', - '../src/d3d/lfx.cpp', - '../src/d3d/nvapi_d3d_instance.cpp', -+ '../src/d3d/nvapi_d3d_low_latency_device.cpp', - '../src/sysinfo/nvapi_output.cpp', - '../src/sysinfo/nvapi_adapter.cpp', - '../src/sysinfo/nvapi_adapter_registry.cpp', -diff --git a/tests/nvapi_d3d.cpp b/tests/nvapi_d3d.cpp -index 2b32d69e..afc10fec 100644 ---- a/tests/nvapi_d3d.cpp -+++ b/tests/nvapi_d3d.cpp -@@ -116,11 +116,16 @@ TEST_CASE("D3D Reflex/LatencyFleX depending methods succeed", "[.d3d]") { - auto vulkan = std::make_unique<VulkanMock>(); - auto nvml = std::make_unique<NvmlMock>(); - auto lfx = std::make_unique<LfxMock>(); -+ D3DLowLatencyDeviceMock lowLatencyDevice; - DXGIDxvkAdapterMock adapter; - DXGIOutput6Mock output; -+ auto lowLatencyDeviceRefCount = 0; - - auto e = ConfigureDefaultTestEnvironment(*dxgiFactory, *vulkan, *nvml, *lfx, adapter, output); - -+ ALLOW_CALL(unknown, QueryInterface(ID3DLowLatencyDevice::guid, _)) -+ .RETURN(E_NOINTERFACE); -+ - ALLOW_CALL(*lfx, IsAvailable()) - .RETURN(false); - -@@ -223,17 +228,246 @@ TEST_CASE("D3D Reflex/LatencyFleX depending methods succeed", "[.d3d]") { - SECTION("Sleep returns NoImplementation") { - REQUIRE(NvAPI_D3D_Sleep(&unknown) == NVAPI_NO_IMPLEMENTATION); - } -- } - -- SECTION("GetLatency returns no-implementation") { -- NV_LATENCY_RESULT_PARAMS params; -- params.version = NV_LATENCY_RESULT_PARAMS_VER; -- REQUIRE(NvAPI_D3D_GetLatency(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ SECTION("GetLatency returns no-implementation") { -+ NV_LATENCY_RESULT_PARAMS params; -+ params.version = NV_LATENCY_RESULT_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_GetLatency(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ -+ SECTION("SetLatencyMarker returns no-implementation") { -+ NV_LATENCY_MARKER_PARAMS params; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } - } - -- SECTION("SetLatencyMarker returns no-implementation") { -- NV_LATENCY_MARKER_PARAMS params; -- params.version = NV_LATENCY_MARKER_PARAMS_VER; -- REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ SECTION("Reflex depending methods succeed when D3DLowLatencyDevice is available") { -+ ALLOW_CALL(unknown, QueryInterface(ID3DLowLatencyDevice::guid, _)) -+ .LR_SIDE_EFFECT(*_2 = static_cast<ID3DLowLatencyDevice*>(&lowLatencyDevice)) -+ .LR_SIDE_EFFECT(lowLatencyDeviceRefCount++) -+ .RETURN(S_OK); -+ ALLOW_CALL(lowLatencyDevice, AddRef()) -+ .LR_SIDE_EFFECT(lowLatencyDeviceRefCount++) -+ .RETURN(lowLatencyDeviceRefCount); -+ ALLOW_CALL(lowLatencyDevice, Release()) -+ .LR_SIDE_EFFECT(lowLatencyDeviceRefCount--) -+ .RETURN(lowLatencyDeviceRefCount); -+ -+ ALLOW_CALL(lowLatencyDevice, SupportsLowLatency()) -+ .RETURN(false); -+ -+ SECTION("D3DLowLatencyDevice does not support low latency") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ SECTION("GetSleepStatus returns NoImplementation") { -+ REQUIRE_CALL(lowLatencyDevice, SupportsLowLatency()) -+ .RETURN(false); -+ -+ NV_GET_SLEEP_STATUS_PARAMS_V1 params{}; -+ params.version = NV_GET_SLEEP_STATUS_PARAMS_VER1; -+ REQUIRE(NvAPI_D3D_GetSleepStatus(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ -+ SECTION("SetSleepMode returns NoImplementation") { -+ NV_SET_SLEEP_MODE_PARAMS params{}; -+ params.version = NV_SET_SLEEP_MODE_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_SetSleepMode(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ -+ SECTION("Sleep returns NoImplementation") { -+ REQUIRE(NvAPI_D3D_Sleep(&unknown) == NVAPI_NO_IMPLEMENTATION); -+ } -+ -+ SECTION("GetLatency returns no-implementation") { -+ NV_LATENCY_RESULT_PARAMS params; -+ params.version = NV_LATENCY_RESULT_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_GetLatency(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ -+ SECTION("SetLatencyMarker returns no-implementation") { -+ NV_LATENCY_MARKER_PARAMS params; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ } -+ -+ SECTION("D3DLowLatencyDevice supports low latency") { -+ ALLOW_CALL(lowLatencyDevice, SupportsLowLatency()) -+ .RETURN(true); -+ -+ SECTION("GetSleepStatus returns OK") { -+ REQUIRE_CALL(lowLatencyDevice, SupportsLowLatency()) -+ .RETURN(true); -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_GET_SLEEP_STATUS_PARAMS_V1 params{}; -+ params.version = NV_GET_SLEEP_STATUS_PARAMS_VER1; -+ REQUIRE(NvAPI_D3D_GetSleepStatus(&unknown, ¶ms) == NVAPI_OK); -+ } -+ -+ SECTION("SetSleepMode calls ID3DLowLatencyDevice::SetLatencySleepMode returns OK") { -+ FORBID_CALL(*lfx, SetTargetFrameTime(_)); // NOLINT(bugprone-use-after-move) -+ -+ REQUIRE_CALL(lowLatencyDevice, SetLatencySleepMode(true, false, 250U)) -+ .RETURN(S_OK); -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_SET_SLEEP_MODE_PARAMS_V1 params{}; -+ params.version = NV_SET_SLEEP_MODE_PARAMS_VER1; -+ params.bLowLatencyMode = true; -+ params.minimumIntervalUs = 250; -+ REQUIRE(NvAPI_D3D_SetSleepMode(&unknown, ¶ms) == NVAPI_OK); -+ } -+ -+ SECTION("Sleep calls ID3DLowLatencyDevice::LatencySleep and returns OK") { -+ FORBID_CALL(*lfx, SetTargetFrameTime(_)); // NOLINT(bugprone-use-after-move) -+ FORBID_CALL(*lfx, WaitAndBeginFrame()); -+ -+ REQUIRE_CALL(lowLatencyDevice, SetLatencySleepMode(true, false, 500U)) -+ .RETURN(S_OK); -+ REQUIRE_CALL(lowLatencyDevice, LatencySleep()) -+ .RETURN(S_OK); -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_SET_SLEEP_MODE_PARAMS sleepModeParams{}; -+ sleepModeParams.version = NV_SET_SLEEP_MODE_PARAMS_VER; -+ sleepModeParams.bLowLatencyMode = true; -+ sleepModeParams.minimumIntervalUs = 500; -+ REQUIRE(NvAPI_D3D_SetSleepMode(&unknown, &sleepModeParams) == NVAPI_OK); -+ REQUIRE(NvAPI_D3D_Sleep(&unknown) == NVAPI_OK); -+ } -+ -+ SECTION("SetLatencyMarker calls ID3DLowLatencyDevice::SetLatencyMarker and returns OK") { -+ REQUIRE_CALL(lowLatencyDevice, SetLatencySleepMode(true, false, 750U)) -+ .RETURN(S_OK); -+ REQUIRE_CALL(lowLatencyDevice, LatencySleep()) -+ .RETURN(S_OK); -+ REQUIRE_CALL(lowLatencyDevice, SetLatencyMarker(123ULL, SIMULATION_START)) -+ .RETURN(S_OK); -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_SET_SLEEP_MODE_PARAMS sleepModeParams{}; -+ sleepModeParams.version = NV_SET_SLEEP_MODE_PARAMS_VER; -+ sleepModeParams.bLowLatencyMode = true; -+ sleepModeParams.minimumIntervalUs = 750; -+ NV_LATENCY_MARKER_PARAMS latencyMarkerParams{}; -+ latencyMarkerParams.version = NV_LATENCY_MARKER_PARAMS_VER1; -+ latencyMarkerParams.frameID = 123ULL; -+ latencyMarkerParams.markerType = SIMULATION_START; -+ REQUIRE(NvAPI_D3D_SetSleepMode(&unknown, &sleepModeParams) == NVAPI_OK); -+ REQUIRE(NvAPI_D3D_Sleep(&unknown) == NVAPI_OK); -+ REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, &latencyMarkerParams) == NVAPI_OK); -+ } -+ -+ SECTION("SetLatencyMarker with unknown struct version returns incompatible-struct-version") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_MARKER_PARAMS params{}; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER1 + 1; -+ REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, ¶ms) == NVAPI_INCOMPATIBLE_STRUCT_VERSION); -+ } -+ -+ SECTION("SetLatencyMarker with current struct version returns not incompatible-struct-version") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ ALLOW_CALL(lowLatencyDevice, SetLatencyMarker(_, _)) -+ .RETURN(S_OK); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_MARKER_PARAMS params{}; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, ¶ms) != NVAPI_INCOMPATIBLE_STRUCT_VERSION); -+ } -+ -+ SECTION("GetLatency calls ID3DLowLatencyDevice::GetLatencyInfo and returns OK") { -+ REQUIRE_CALL(lowLatencyDevice, SetLatencySleepMode(true, false, 1000U)) -+ .RETURN(S_OK); -+ REQUIRE_CALL(lowLatencyDevice, GetLatencyInfo(_)) -+ .RETURN(S_OK); -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_SET_SLEEP_MODE_PARAMS sleepModeParams{}; -+ sleepModeParams.version = NV_SET_SLEEP_MODE_PARAMS_VER; -+ sleepModeParams.bLowLatencyMode = true; -+ sleepModeParams.minimumIntervalUs = 1000; -+ NV_LATENCY_RESULT_PARAMS latencyResults{}; -+ latencyResults.version = NV_LATENCY_RESULT_PARAMS_VER1; -+ REQUIRE(NvAPI_D3D_SetSleepMode(&unknown, &sleepModeParams) == NVAPI_OK); -+ REQUIRE(NvAPI_D3D_GetLatency(&unknown, &latencyResults) == NVAPI_OK); -+ } -+ } -+ -+ SECTION("D3DLowLatencyDevice supports low latency and LFX is available") { -+ ALLOW_CALL(lowLatencyDevice, SupportsLowLatency()) -+ .RETURN(true); -+ ALLOW_CALL(*lfx, IsAvailable()) -+ .RETURN(true); // NOLINT(bugprone-use-after-move) -+ -+ SECTION("SetSleepMode calls Lfx::SetTargetFrameTime returns OK") { -+ REQUIRE_CALL(*lfx, SetTargetFrameTime(250ULL * 1000)); // NOLINT(bugprone-use-after-move) -+ -+ FORBID_CALL(lowLatencyDevice, SetLatencySleepMode(_, _, _)); -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_SET_SLEEP_MODE_PARAMS_V1 params{}; -+ params.version = NV_SET_SLEEP_MODE_PARAMS_VER1; -+ params.bLowLatencyMode = true; -+ params.minimumIntervalUs = 250; -+ REQUIRE(NvAPI_D3D_SetSleepMode(&unknown, ¶ms) == NVAPI_OK); -+ } -+ -+ SECTION("Sleep calls Lfx::WaitAndBeginFrame and returns OK") { -+ REQUIRE_CALL(*lfx, SetTargetFrameTime(500ULL * 1000)); // NOLINT(bugprone-use-after-move) -+ REQUIRE_CALL(*lfx, WaitAndBeginFrame()); -+ -+ FORBID_CALL(lowLatencyDevice, SetLatencySleepMode(_, _, _)); -+ FORBID_CALL(lowLatencyDevice, LatencySleep()); -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_SET_SLEEP_MODE_PARAMS params{}; -+ params.version = NV_SET_SLEEP_MODE_PARAMS_VER; -+ params.bLowLatencyMode = true; -+ params.minimumIntervalUs = 500; -+ REQUIRE(NvAPI_D3D_SetSleepMode(&unknown, ¶ms) == NVAPI_OK); -+ REQUIRE(NvAPI_D3D_Sleep(&unknown) == NVAPI_OK); -+ } -+ -+ SECTION("GetLatency returns no-implementation") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_RESULT_PARAMS params; -+ params.version = NV_LATENCY_RESULT_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_GetLatency(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ -+ SECTION("SetLatencyMarker returns no-implementation") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_MARKER_PARAMS params; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER; -+ REQUIRE(NvAPI_D3D_SetLatencyMarker(&unknown, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ } - } - } -diff --git a/tests/nvapi_d3d12.cpp b/tests/nvapi_d3d12.cpp -index 7e587280..05bf0ba9 100644 ---- a/tests/nvapi_d3d12.cpp -+++ b/tests/nvapi_d3d12.cpp -@@ -2,6 +2,7 @@ - #include "resource_factory_util.h" - #include "nvapi_sysinfo_mocks.h" - #include "nvapi_d3d12_mocks.h" -+#include "nvapi_d3d_mocks.h" - - using namespace trompeloeil; - -@@ -21,9 +22,13 @@ typedef struct _NVAPI_D3D12_RAYTRACING_GEOMETRY_DESC_EX_R520 { - - TEST_CASE("D3D12 methods succeed", "[.d3d12]") { - D3D12Vkd3dDeviceMock device; -+ D3D12Vkd3dCommandQueueMock commandQueue; -+ D3DLowLatencyDeviceMock lowLatencyDevice; - D3D12Vkd3dGraphicsCommandListMock commandList; - auto deviceRefCount = 0; - auto commandListRefCount = 0; -+ auto commandQueueRefCount = 0; -+ auto lowLatencyDeviceRefCount = 0; - - ALLOW_CALL(device, QueryInterface(ID3D12DeviceExt::guid, _)) - .LR_SIDE_EFFECT(*_2 = static_cast<ID3D12DeviceExt*>(&device)) -@@ -36,6 +41,9 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") { - .LR_SIDE_EFFECT(deviceRefCount--) - .RETURN(deviceRefCount); - -+ ALLOW_CALL(device, QueryInterface(ID3DLowLatencyDevice::guid, _)) -+ .RETURN(E_NOINTERFACE); -+ - ALLOW_CALL(device, GetExtensionSupport(_)) - .RETURN(true); - -@@ -58,6 +66,24 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") { - .LR_SIDE_EFFECT(commandListRefCount--) - .RETURN(commandListRefCount); - -+ ALLOW_CALL(commandQueue, QueryInterface(__uuidof(ID3D12CommandQueue), _)) -+ .LR_SIDE_EFFECT(*_2 = static_cast<ID3D12CommandQueue*>(&commandQueue)) -+ .LR_SIDE_EFFECT(commandQueueRefCount++) -+ .RETURN(S_OK); -+ ALLOW_CALL(commandQueue, QueryInterface(ID3D12CommandQueueExt::guid, _)) -+ .LR_SIDE_EFFECT(*_2 = static_cast<ID3D12CommandQueueExt*>(&commandQueue)) -+ .LR_SIDE_EFFECT(commandQueueRefCount++) -+ .RETURN(S_OK); -+ ALLOW_CALL(commandQueue, AddRef()) -+ .LR_SIDE_EFFECT(commandQueueRefCount++) -+ .RETURN(commandQueueRefCount); -+ ALLOW_CALL(commandQueue, Release()) -+ .LR_SIDE_EFFECT(commandQueueRefCount--) -+ .RETURN(commandQueueRefCount); -+ ALLOW_CALL(commandQueue, GetDevice(__uuidof(ID3D12Device), _)) -+ .LR_SIDE_EFFECT(*_2 = static_cast<ID3D12Device*>(&device)) -+ .RETURN(S_OK); -+ - SECTION("CreateGraphicsPipelineState for other than SetDepthBounds returns not-supported") { - FORBID_CALL(device, CreateGraphicsPipelineState(_, _, _)); - -@@ -748,4 +774,104 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") { - REQUIRE(NvAPI_D3D12_BuildRaytracingAccelerationStructureEx(static_cast<ID3D12GraphicsCommandList4*>(&commandList), ¶ms) != NVAPI_INCOMPATIBLE_STRUCT_VERSION); - } - } -+ -+ SECTION("D3DLowLatencyDevice methods succeed") { -+ auto dxgiFactory = std::make_unique<DXGIDxvkFactoryMock>(); -+ auto vulkan = std::make_unique<VulkanMock>(); -+ auto nvml = std::make_unique<NvmlMock>(); -+ auto lfx = std::make_unique<LfxMock>(); -+ DXGIDxvkAdapterMock adapter; -+ DXGIOutput6Mock output; -+ -+ auto e = ConfigureDefaultTestEnvironment(*dxgiFactory, *vulkan, *nvml, *lfx, adapter, output); -+ -+ ALLOW_CALL(device, QueryInterface(ID3DLowLatencyDevice::guid, _)) -+ .LR_SIDE_EFFECT(*_2 = static_cast<ID3DLowLatencyDevice*>(&lowLatencyDevice)) -+ .LR_SIDE_EFFECT(lowLatencyDeviceRefCount++) -+ .RETURN(S_OK); -+ ALLOW_CALL(lowLatencyDevice, AddRef()) -+ .LR_SIDE_EFFECT(lowLatencyDeviceRefCount++) -+ .RETURN(lowLatencyDeviceRefCount); -+ ALLOW_CALL(lowLatencyDevice, Release()) -+ .LR_SIDE_EFFECT(lowLatencyDeviceRefCount--) -+ .RETURN(lowLatencyDeviceRefCount); -+ -+ ALLOW_CALL(lowLatencyDevice, SupportsLowLatency()) -+ .RETURN(true); -+ -+ SECTION("NotifyOutOfBandCommandQueue succeeds") { -+ SECTION("NotifyOutOfBandCommandQueue returns OK") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ REQUIRE_CALL(commandQueue, NotifyOutOfBandCommandQueue(static_cast<D3D12_OUT_OF_BAND_CQ_TYPE>(OUT_OF_BAND_RENDER))) -+ .RETURN(S_OK); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ REQUIRE(NvAPI_D3D12_NotifyOutOfBandCommandQueue(&commandQueue, OUT_OF_BAND_RENDER) == NVAPI_OK); -+ } -+ -+ SECTION("NotifyOutOfBandCommandQueue returns no-implementation with LFX") { -+ ALLOW_CALL(*lfx, IsAvailable()) -+ .RETURN(true); // NOLINT(bugprone-use-after-move) -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ REQUIRE(NvAPI_D3D12_NotifyOutOfBandCommandQueue(&commandQueue, OUT_OF_BAND_RENDER) == NVAPI_NO_IMPLEMENTATION); -+ } -+ } -+ -+ SECTION("SetAsyncFrameMarker succeeds") { -+ SECTION("SetAsyncFrameMarker returns OK") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ REQUIRE_CALL(lowLatencyDevice, SetLatencyMarker(123ULL, OUT_OF_BAND_RENDERSUBMIT_START)) -+ .RETURN(S_OK); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_MARKER_PARAMS params{}; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER1; -+ params.frameID = 123ULL; -+ params.markerType = OUT_OF_BAND_RENDERSUBMIT_START; -+ REQUIRE(NvAPI_D3D12_SetAsyncFrameMarker(&commandQueue, ¶ms) == NVAPI_OK); -+ } -+ -+ SECTION("SetAsyncFrameMarker returns no-implementation with LFX") { -+ ALLOW_CALL(*lfx, IsAvailable()) -+ .RETURN(true); // NOLINT(bugprone-use-after-move) -+ -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_MARKER_PARAMS params{}; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER1; -+ REQUIRE(NvAPI_D3D12_SetAsyncFrameMarker(&commandQueue, ¶ms) == NVAPI_NO_IMPLEMENTATION); -+ } -+ -+ SECTION("SetAsyncFrameMarker with unknown struct version returns incompatible-struct-version") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_MARKER_PARAMS params{}; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER1 + 1; -+ REQUIRE(NvAPI_D3D12_SetAsyncFrameMarker(&commandQueue, ¶ms) == NVAPI_INCOMPATIBLE_STRUCT_VERSION); -+ } -+ -+ SECTION("SetAsyncFrameMarker with current struct version returns not incompatible-struct-version") { -+ SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); -+ -+ ALLOW_CALL(lowLatencyDevice, SetLatencyMarker(_, _)) -+ .RETURN(S_OK); -+ -+ REQUIRE(NvAPI_Initialize() == NVAPI_OK); -+ -+ NV_LATENCY_MARKER_PARAMS params{}; -+ params.version = NV_LATENCY_MARKER_PARAMS_VER; -+ REQUIRE(NvAPI_D3D12_SetAsyncFrameMarker(&commandQueue, ¶ms) != NVAPI_INCOMPATIBLE_STRUCT_VERSION); -+ } -+ } -+ } - } -diff --git a/tests/nvapi_d3d12_mocks.h b/tests/nvapi_d3d12_mocks.h -index a3cff713..cf6529f5 100644 ---- a/tests/nvapi_d3d12_mocks.h -+++ b/tests/nvapi_d3d12_mocks.h -@@ -164,3 +164,28 @@ class D3D12Vkd3dGraphicsCommandListMock final : public trompeloeil::mock_interfa - IMPLEMENT_MOCK6(LaunchCubinShader); - IMPLEMENT_MOCK9(LaunchCubinShaderEx); - }; -+ -+class ID3D12Vkd3dCommandQueue : public ID3D12CommandQueue, public ID3D12CommandQueueExt {}; -+ -+class D3D12Vkd3dCommandQueueMock final : public trompeloeil::mock_interface<ID3D12Vkd3dCommandQueue> { -+ MAKE_MOCK2(QueryInterface, HRESULT(REFIID, void**), override); -+ MAKE_MOCK0(AddRef, ULONG(), override); -+ MAKE_MOCK0(Release, ULONG(), override); -+ IMPLEMENT_MOCK3(GetPrivateData); -+ IMPLEMENT_MOCK3(SetPrivateData); -+ IMPLEMENT_MOCK2(SetPrivateDataInterface); -+ IMPLEMENT_MOCK1(SetName); -+ IMPLEMENT_MOCK2(GetDevice); -+ IMPLEMENT_MOCK10(UpdateTileMappings); -+ IMPLEMENT_MOCK6(CopyTileMappings); -+ IMPLEMENT_MOCK2(ExecuteCommandLists); -+ IMPLEMENT_MOCK3(SetMarker); -+ IMPLEMENT_MOCK3(BeginEvent); -+ IMPLEMENT_MOCK0(EndEvent); -+ IMPLEMENT_MOCK2(Signal); -+ IMPLEMENT_MOCK2(Wait); -+ IMPLEMENT_MOCK1(GetTimestampFrequency); -+ IMPLEMENT_MOCK2(GetClockCalibration); -+ MAKE_MOCK1(GetDesc, D3D12_COMMAND_QUEUE_DESC*(D3D12_COMMAND_QUEUE_DESC*), override); -+ IMPLEMENT_MOCK1(NotifyOutOfBandCommandQueue); -+}; -\ No newline at end of file -diff --git a/tests/nvapi_d3d_mocks.h b/tests/nvapi_d3d_mocks.h -index d1e7ac72..472cfc54 100644 ---- a/tests/nvapi_d3d_mocks.h -+++ b/tests/nvapi_d3d_mocks.h -@@ -1,6 +1,7 @@ - #pragma once - - #include "nvapi_tests_private.h" -+#include "../src/shared/shared_interfaces.h" - #include "../src/d3d/lfx.h" - - class UnknownMock : public trompeloeil::mock_interface<IUnknown> { -@@ -14,3 +15,14 @@ class LfxMock : public trompeloeil::mock_interface<dxvk::Lfx> { - IMPLEMENT_MOCK0(WaitAndBeginFrame); - IMPLEMENT_MOCK1(SetTargetFrameTime); - }; -+ -+class D3DLowLatencyDeviceMock : public trompeloeil::mock_interface<ID3DLowLatencyDevice> { -+ MAKE_MOCK2(QueryInterface, HRESULT(REFIID, void**), override); -+ MAKE_MOCK0(AddRef, ULONG(), override); -+ MAKE_MOCK0(Release, ULONG(), override); -+ IMPLEMENT_MOCK0(SupportsLowLatency); -+ IMPLEMENT_MOCK0(LatencySleep); -+ IMPLEMENT_MOCK3(SetLatencySleepMode); -+ IMPLEMENT_MOCK2(SetLatencyMarker); -+ IMPLEMENT_MOCK1(GetLatencyInfo); -+}; -\ No newline at end of file -diff --git a/tests/nvapi_tests_private.h b/tests/nvapi_tests_private.h -index e126e61b..ff1856ae 100644 ---- a/tests/nvapi_tests_private.h -+++ b/tests/nvapi_tests_private.h -@@ -2,6 +2,7 @@ - - #include "../src/nvapi_private.h" - #include "../src/nvapi_globals.h" -+#include "../src/d3d/nvapi_d3d_low_latency_device.h" - #include "../src/d3d11/nvapi_d3d11_device.h" - #include "../src/d3d12/nvapi_d3d12_device.h" - #include "../inc/catch_amalgamated.hpp" diff --git a/PKGBUILD.personal b/PKGBUILD.personal index ad1f883e9ed9..83df3ad7a137 100644 --- a/PKGBUILD.personal +++ b/PKGBUILD.personal @@ -19,7 +19,6 @@ source=( ) #Optional patches source+=( - 82-nv_low_latency_dxvk_nvapi.patch ) pkgver() { @@ -34,8 +33,6 @@ prepare() { git remote set-url origin https://github.com/jp7677/dxvk-nvapi.git git submodule update --init --filter=tree:0 --recursive - patch -p1 -i "$srcdir"/82-nv_low_latency_dxvk_nvapi.patch - # Uncomment to enable extra optimizations # Patch crossfiles with extra optimizations from makepkg.conf patch -p1 -i "$srcdir"/dxvk-nvapi-extraopts.patch @@ -121,5 +118,4 @@ sha256sums=('SKIP' '62a14512ab32ff534d8b07f2cdefae17ee679c73465edeb11bfac1e88f0a7109' '1f4934c5bfcf208e288a0eda2f385f82acc9e78a4b0ac2a77b5af14c64c8e21e') sha256sums+=( - 'SKIP' ) |