diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp
index a33379f96..2ffc50e26 100644
--- a/src/d3d11/d3d11_device.cpp
+++ b/src/d3d11/d3d11_device.cpp
@@ -3062,7 +3062,10 @@ namespace dxvk {
           D3D11DXGIDevice*        pContainer,
           D3D11Device*            pDevice)
   : m_container(pContainer), m_device(pDevice) {
+    auto dxvkDevice = pDevice->GetDXVKDevice();
 
+    m_reflexEnabled = dxvkDevice->features().nvLowLatency2
+                   && dxvkDevice->config().latencySleep == Tristate::Auto;
   }
 
 
@@ -3089,12 +3092,25 @@ namespace dxvk {
 
 
   BOOL STDMETHODCALLTYPE D3D11ReflexDevice::SupportsLowLatency() {
-    return FALSE;
+    return m_reflexEnabled;
   }
 
 
   HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::LatencySleep() {
-    return E_NOTIMPL;
+    if (!m_reflexEnabled)
+      return DXGI_ERROR_INVALID_CALL;
+
+    // Don't keep object locked while sleeping
+    Rc<DxvkReflexLatencyTrackerNv> tracker;
+
+    { std::lock_guard lock(m_mutex);
+      tracker = m_tracker;
+    }
+
+    if (tracker)
+      tracker->latencySleep();
+
+    return S_OK;
   }
 
 
@@ -3102,21 +3118,133 @@ namespace dxvk {
           BOOL                          LowLatencyEnable,
           BOOL                          LowLatencyBoost,
           UINT32                        MinIntervalUs) {
-    return E_NOTIMPL;
+    if (!m_reflexEnabled)
+      return DXGI_ERROR_INVALID_CALL;
+
+    std::lock_guard lock(m_mutex);
+
+    if (m_tracker) {
+      m_tracker->setLatencySleepMode(
+        LowLatencyEnable, LowLatencyBoost, MinIntervalUs);
+    }
+
+    // Write back in case we have no swapchain yet
+    m_enableLowLatency = LowLatencyEnable;
+    m_enableBoost      = LowLatencyBoost;
+    m_minIntervalUs    = MinIntervalUs;
+    return S_OK;
   }
 
 
   HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::SetLatencyMarker(
           UINT64                        FrameId,
           UINT32                        MarkerType) {
-    return E_NOTIMPL;
+    if (!m_reflexEnabled)
+      return DXGI_ERROR_INVALID_CALL;
+
+    std::lock_guard lock(m_mutex);
+
+    if (m_tracker) {
+      auto marker = VkLatencyMarkerNV(MarkerType);
+      m_tracker->setLatencyMarker(FrameId, marker);
+
+      if (marker == VK_LATENCY_MARKER_RENDERSUBMIT_START_NV) {
+        m_device->GetContext()->InjectCs(DxvkCsQueue::Ordered, [
+          cTracker  = m_tracker,
+          cFrameId  = FrameId
+        ] (DxvkContext* ctx) {
+          uint64_t frameId = cTracker->frameIdFromAppFrameId(cFrameId);
+
+          if (frameId)
+            ctx->beginLatencyTracking(cTracker, frameId);
+        });
+      } else if (marker == VK_LATENCY_MARKER_RENDERSUBMIT_END_NV) {
+        m_device->GetContext()->InjectCs(DxvkCsQueue::Ordered, [
+          cTracker  = m_tracker
+        ] (DxvkContext* ctx) {
+          ctx->endLatencyTracking(cTracker);
+        });
+      }
+    }
+
+    return S_OK;
   }
 
 
   HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::GetLatencyInfo(
           D3D_LOW_LATENCY_RESULTS*      pLowLatencyResults) {
-    *pLowLatencyResults = D3D_LOW_LATENCY_RESULTS();
-    return E_NOTIMPL;
+    constexpr static size_t FrameCount = 64;
+
+    if (!pLowLatencyResults)
+      return E_INVALIDARG;
+
+    for (size_t i = 0; i < FrameCount; i++)
+      pLowLatencyResults->frameReports[i] = D3D_LOW_LATENCY_FRAME_REPORT();
+
+    if (!m_reflexEnabled)
+      return DXGI_ERROR_INVALID_CALL;
+
+    std::lock_guard lock(m_mutex);
+
+    if (!m_tracker)
+      return S_OK;
+
+    // Apparently we have to report all 64 frames, or nothing
+    std::array<DxvkReflexFrameReport, FrameCount> reports = { };
+    uint32_t reportCount = m_tracker->getFrameReports(FrameCount, reports.data());
+
+    if (reportCount < FrameCount)
+      return S_OK;
+
+    for (uint32_t i = 0; i < FrameCount; i++) {
+      auto& src = reports[i];
+      auto& dst = pLowLatencyResults->frameReports[i];
+
+      dst.frameID = src.report.presentID;
+      dst.inputSampleTime = src.report.inputSampleTimeUs;
+      dst.simStartTime = src.report.simStartTimeUs;
+      dst.simEndTime = src.report.simEndTimeUs;
+      dst.renderSubmitStartTime = src.report.renderSubmitStartTimeUs;
+      dst.renderSubmitEndTime = src.report.renderSubmitEndTimeUs;
+      dst.presentStartTime = src.report.presentStartTimeUs;
+      dst.presentEndTime = src.report.presentEndTimeUs;
+      dst.driverStartTime = src.report.driverStartTimeUs;
+      dst.driverEndTime = src.report.driverEndTimeUs;
+      dst.osRenderQueueStartTime = src.report.osRenderQueueStartTimeUs;
+      dst.osRenderQueueEndTime = src.report.osRenderQueueEndTimeUs;
+      dst.gpuRenderStartTime = src.report.gpuRenderStartTimeUs;
+      dst.gpuRenderEndTime = src.report.gpuRenderEndTimeUs;
+      dst.gpuActiveRenderTimeUs = src.gpuActiveTimeUs;
+      dst.gpuFrameTimeUs = 0;
+
+      if (i) {
+        dst.gpuFrameTimeUs = reports[i - 0].report.gpuRenderEndTimeUs
+                           - reports[i - 1].report.gpuRenderEndTimeUs;
+      }
+    }
+
+    return S_OK;
+  }
+
+
+  void D3D11ReflexDevice::RegisterLatencyTracker(
+          Rc<DxvkLatencyTracker>          Tracker) {
+    std::lock_guard lock(m_mutex);
+
+    if (m_tracker)
+      return;
+
+    if ((m_tracker = dynamic_cast<DxvkReflexLatencyTrackerNv*>(Tracker.ptr())))
+      m_tracker->setLatencySleepMode(m_enableLowLatency, m_enableBoost, m_minIntervalUs);
+  }
+
+
+  void D3D11ReflexDevice::UnregisterLatencyTracker(
+          Rc<DxvkLatencyTracker>          Tracker) {
+    std::lock_guard lock(m_mutex);
+
+    if (m_tracker == Tracker)
+      m_tracker = nullptr;
   }
 
 
diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h
index 7adcf0db6..48356f8b4 100644
--- a/src/d3d11/d3d11_device.h
+++ b/src/d3d11/d3d11_device.h
@@ -9,6 +9,7 @@
 #include "../dxgi/dxgi_interfaces.h"
 
 #include "../dxvk/dxvk_cs.h"
+#include "../dxvk/dxvk_latency_reflex.h"
 
 #include "../d3d10/d3d10_device.h"
 
@@ -788,11 +789,26 @@ namespace dxvk {
     HRESULT STDMETHODCALLTYPE GetLatencyInfo(
             D3D_LOW_LATENCY_RESULTS*      pLowLatencyResults);
 
+    void RegisterLatencyTracker(
+            Rc<DxvkLatencyTracker>          Tracker);
+
+    void UnregisterLatencyTracker(
+            Rc<DxvkLatencyTracker>          Tracker);
+
   private:
 
     D3D11DXGIDevice*  m_container;
     D3D11Device*      m_device;
 
+    bool              m_reflexEnabled = false;
+
+    dxvk::mutex       m_mutex;
+
+    bool              m_enableLowLatency  = false;
+    bool              m_enableBoost       = false;
+    uint64_t          m_minIntervalUs     = 0u;
+
+    Rc<DxvkReflexLatencyTrackerNv>  m_tracker;
   };
 
 
diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp
index 6219f3985..da0ebcb9c 100644
--- a/src/d3d11/d3d11_swapchain.cpp
+++ b/src/d3d11/d3d11_swapchain.cpp
@@ -517,6 +517,9 @@ namespace dxvk {
     m_presenter->setFrameRateLimit(m_targetFrameRate, GetActualFrameLatency());
 
     m_latency = m_device->createLatencyTracker(m_presenter);
+
+    Com<D3D11ReflexDevice> reflex = GetReflexDevice();
+    reflex->RegisterLatencyTracker(m_latency);
   }
 
 
@@ -617,6 +620,9 @@ namespace dxvk {
     ] (DxvkContext* ctx) {
       ctx->endLatencyTracking(cLatency);
     });
+
+    Com<D3D11ReflexDevice> reflex = GetReflexDevice();
+    reflex->UnregisterLatencyTracker(m_latency);
   }
 
 
@@ -678,6 +684,14 @@ namespace dxvk {
   }
 
 
+  Com<D3D11ReflexDevice> D3D11SwapChain::GetReflexDevice() {
+    Com<ID3DLowLatencyDevice> llDevice;
+    m_parent->QueryInterface(__uuidof(ID3DLowLatencyDevice), reinterpret_cast<void**>(&llDevice));
+
+    return static_cast<D3D11ReflexDevice*>(llDevice.ptr());
+  }
+
+
   std::string D3D11SwapChain::GetApiName() const {
     Com<IDXGIDXVKDevice> device;
     m_parent->QueryInterface(__uuidof(IDXGIDXVKDevice), reinterpret_cast<void**>(&device));
diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h
index cb51182d0..99f09450c 100644
--- a/src/d3d11/d3d11_swapchain.h
+++ b/src/d3d11/d3d11_swapchain.h
@@ -148,9 +148,11 @@ namespace dxvk {
     void SyncFrameLatency();
 
     uint32_t GetActualFrameLatency();
-    
+
     VkSurfaceFormatKHR GetSurfaceFormat(DXGI_FORMAT Format);
-    
+
+    Com<D3D11ReflexDevice> GetReflexDevice();
+
     std::string GetApiName() const;
 
   };