Skip to content

Commit

Permalink
[d3d11] Implement ID3DLowLatencyDevice
Browse files Browse the repository at this point in the history
  • Loading branch information
doitsujin committed Jan 21, 2025
1 parent 2dd21fc commit 534b944
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 8 deletions.
140 changes: 134 additions & 6 deletions src/d3d11/d3d11_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand All @@ -3089,34 +3092,159 @@ 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;
}


HRESULT STDMETHODCALLTYPE D3D11ReflexDevice::SetLatencySleepMode(
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;
}


Expand Down
16 changes: 16 additions & 0 deletions src/d3d11/d3d11_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
};


Expand Down
14 changes: 14 additions & 0 deletions src/d3d11/d3d11_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down Expand Up @@ -617,6 +620,9 @@ namespace dxvk {
] (DxvkContext* ctx) {
ctx->endLatencyTracking(cLatency);
});

Com<D3D11ReflexDevice> reflex = GetReflexDevice();
reflex->UnregisterLatencyTracker(m_latency);
}


Expand Down Expand Up @@ -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));
Expand Down
6 changes: 4 additions & 2 deletions src/d3d11/d3d11_swapchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ namespace dxvk {
void SyncFrameLatency();

uint32_t GetActualFrameLatency();

VkSurfaceFormatKHR GetSurfaceFormat(DXGI_FORMAT Format);


Com<D3D11ReflexDevice> GetReflexDevice();

std::string GetApiName() const;

};
Expand Down

0 comments on commit 534b944

Please sign in to comment.