mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 05:52:11 +01:00
[d3d11] Implement ID3DLowLatencyDevice
This commit is contained in:
parent
4f9b106d40
commit
736ee20eb5
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -148,9 +148,11 @@ namespace dxvk {
|
||||
void SyncFrameLatency();
|
||||
|
||||
uint32_t GetActualFrameLatency();
|
||||
|
||||
|
||||
VkSurfaceFormatKHR GetSurfaceFormat(DXGI_FORMAT Format);
|
||||
|
||||
|
||||
Com<D3D11ReflexDevice> GetReflexDevice();
|
||||
|
||||
std::string GetApiName() const;
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user