Skip to content

Commit d0e232c

Browse files
esullivan-nvidiaejsullivan
authored andcommitted
Add VK_NV_low_latency2 support
This commit add support for the VK_NV_low_latency2 extension, and implements the ID3DLowLatencyDevice interface.
1 parent 0cd8e71 commit d0e232c

20 files changed

+618
-55
lines changed

src/d3d11/d3d11_device.cpp

Lines changed: 154 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "d3d11_device.h"
1616
#include "d3d11_fence.h"
1717
#include "d3d11_input_layout.h"
18+
#include "d3d11_interfaces.h"
1819
#include "d3d11_interop.h"
1920
#include "d3d11_query.h"
2021
#include "d3d11_resource.h"
@@ -2469,12 +2470,14 @@ namespace dxvk {
24692470
return deviceFeatures.nvxBinaryImport
24702471
&& deviceFeatures.vk12.bufferDeviceAddress;
24712472

2473+
case D3D11_VK_NV_LOW_LATENCY_2:
2474+
return deviceFeatures.nvLowLatency2;
2475+
24722476
default:
24732477
return false;
24742478
}
24752479
}
2476-
2477-
2480+
24782481
bool STDMETHODCALLTYPE D3D11DeviceExt::GetCudaTextureObjectNVX(uint32_t srvDriverHandle, uint32_t samplerDriverHandle, uint32_t* pCudaTextureHandle) {
24792482
ID3D11ShaderResourceView* srv = HandleToSrvNVX(srvDriverHandle);
24802483

@@ -2783,8 +2786,132 @@ namespace dxvk {
27832786

27842787

27852788

2786-
2787-
2789+
2790+
D3D11LowLatencyDevice::D3D11LowLatencyDevice(
2791+
D3D11DXGIDevice* pContainer,
2792+
D3D11Device* pDevice)
2793+
: m_container(pContainer), m_device(pDevice) {
2794+
2795+
}
2796+
2797+
2798+
ULONG STDMETHODCALLTYPE D3D11LowLatencyDevice::AddRef() {
2799+
return m_container->AddRef();
2800+
}
2801+
2802+
2803+
ULONG STDMETHODCALLTYPE D3D11LowLatencyDevice::Release() {
2804+
return m_container->Release();
2805+
}
2806+
2807+
2808+
HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::QueryInterface(
2809+
REFIID riid,
2810+
void** ppvObject) {
2811+
return m_container->QueryInterface(riid, ppvObject);
2812+
}
2813+
2814+
2815+
BOOL STDMETHODCALLTYPE D3D11LowLatencyDevice::SupportsLowLatency() {
2816+
return m_device->GetDXVKDevice()->features().nvLowLatency2;
2817+
}
2818+
2819+
2820+
HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::LatencySleep() {
2821+
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
2822+
return E_NOINTERFACE;
2823+
}
2824+
2825+
D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();
2826+
if (pSwapChain && pSwapChain->LowLatencyEnabled()) {
2827+
pSwapChain->LatencySleep();
2828+
}
2829+
2830+
return S_OK;
2831+
}
2832+
2833+
2834+
HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::SetLatencySleepMode(BOOL lowLatencyMode, BOOL lowLatencyBoost, uint32_t minimumIntervalUs) {
2835+
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
2836+
return E_NOINTERFACE;
2837+
}
2838+
2839+
D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();
2840+
if (pSwapChain) {
2841+
pSwapChain->SetLatencySleepMode(lowLatencyMode, lowLatencyBoost, minimumIntervalUs);
2842+
}
2843+
2844+
return S_OK;
2845+
}
2846+
2847+
2848+
HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::SetLatencyMarker(uint64_t frameID, uint32_t markerType) {
2849+
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
2850+
return E_NOINTERFACE;
2851+
}
2852+
2853+
D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();
2854+
VkLatencyMarkerNV marker = static_cast<VkLatencyMarkerNV>(markerType);
2855+
uint64_t internalFrameId = frameID + DXGI_MAX_SWAP_CHAIN_BUFFERS;
2856+
2857+
m_device->GetDXVKDevice()->setLatencyMarker(marker, internalFrameId);
2858+
2859+
if (pSwapChain && pSwapChain->LowLatencyEnabled()) {
2860+
pSwapChain->SetLatencyMarker(marker, internalFrameId);
2861+
}
2862+
2863+
return S_OK;
2864+
}
2865+
2866+
2867+
HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::GetLatencyInfo(D3D11_LATENCY_RESULTS* latencyResults)
2868+
{
2869+
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
2870+
return E_NOINTERFACE;
2871+
}
2872+
2873+
constexpr uint32_t frameReportSize = 64;
2874+
D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();
2875+
2876+
if (pSwapChain && pSwapChain->LowLatencyEnabled()) {
2877+
std::vector<VkLatencyTimingsFrameReportNV> frameReports;
2878+
pSwapChain->GetLatencyTimings(frameReports);
2879+
2880+
if (frameReports.size() >= frameReportSize) {
2881+
for (uint32_t i = 0; i < frameReportSize; i++) {
2882+
VkLatencyTimingsFrameReportNV& frameReport = frameReports[i];
2883+
latencyResults->frame_reports[i].frameID = frameReport.presentID - DXGI_MAX_SWAP_CHAIN_BUFFERS;
2884+
latencyResults->frame_reports[i].inputSampleTime = frameReport.inputSampleTimeUs;
2885+
latencyResults->frame_reports[i].simStartTime = frameReport.simStartTimeUs;
2886+
latencyResults->frame_reports[i].simEndTime = frameReport.simEndTimeUs;
2887+
latencyResults->frame_reports[i].renderSubmitStartTime = frameReport.renderSubmitStartTimeUs;
2888+
latencyResults->frame_reports[i].renderSubmitEndTime = frameReport.renderSubmitEndTimeUs;
2889+
latencyResults->frame_reports[i].presentStartTime = frameReport.presentStartTimeUs;
2890+
latencyResults->frame_reports[i].presentEndTime = frameReport.presentEndTimeUs;
2891+
latencyResults->frame_reports[i].driverStartTime = frameReport.driverStartTimeUs;
2892+
latencyResults->frame_reports[i].driverEndTime = frameReport.driverEndTimeUs;
2893+
latencyResults->frame_reports[i].osRenderQueueStartTime = frameReport.osRenderQueueStartTimeUs;
2894+
latencyResults->frame_reports[i].osRenderQueueEndTime = frameReport.osRenderQueueEndTimeUs;
2895+
latencyResults->frame_reports[i].gpuRenderStartTime = frameReport.gpuRenderStartTimeUs;
2896+
latencyResults->frame_reports[i].gpuRenderEndTime = frameReport.gpuRenderEndTimeUs;
2897+
latencyResults->frame_reports[i].gpuActiveRenderTimeUs =
2898+
frameReport.gpuRenderEndTimeUs - frameReport.gpuRenderStartTimeUs;
2899+
latencyResults->frame_reports[i].gpuFrameTimeUs = 0;
2900+
2901+
if (i) {
2902+
latencyResults->frame_reports[i].gpuFrameTimeUs =
2903+
frameReports[i].gpuRenderEndTimeUs - frameReports[i - 1].gpuRenderEndTimeUs;
2904+
}
2905+
}
2906+
}
2907+
}
2908+
2909+
return S_OK;
2910+
}
2911+
2912+
2913+
2914+
27882915
D3D11VideoDevice::D3D11VideoDevice(
27892916
D3D11DXGIDevice* pContainer,
27902917
D3D11Device* pDevice)
@@ -3021,7 +3148,11 @@ namespace dxvk {
30213148

30223149
Com<D3D11SwapChain> presenter = new D3D11SwapChain(
30233150
m_container, m_device, pSurfaceFactory, pDesc);
3024-
3151+
3152+
if (m_device->GetDXVKDevice()->features().nvLowLatency2) {
3153+
m_device->AddSwapchain(presenter.ref());
3154+
}
3155+
30253156
*ppSwapChain = presenter.ref();
30263157
return S_OK;
30273158
} catch (const DxvkError& e) {
@@ -3078,17 +3209,18 @@ namespace dxvk {
30783209
Rc<DxvkDevice> pDxvkDevice,
30793210
D3D_FEATURE_LEVEL FeatureLevel,
30803211
UINT FeatureFlags)
3081-
: m_dxgiAdapter (pAdapter),
3082-
m_dxvkInstance (pDxvkInstance),
3083-
m_dxvkAdapter (pDxvkAdapter),
3084-
m_dxvkDevice (pDxvkDevice),
3085-
m_d3d11Device (this, FeatureLevel, FeatureFlags),
3086-
m_d3d11DeviceExt(this, &m_d3d11Device),
3087-
m_d3d11Interop (this, &m_d3d11Device),
3088-
m_d3d11Video (this, &m_d3d11Device),
3089-
m_d3d11on12 (this, &m_d3d11Device, pD3D12Device, pD3D12Queue),
3090-
m_metaDevice (this),
3091-
m_dxvkFactory (this, &m_d3d11Device) {
3212+
: m_dxgiAdapter (pAdapter),
3213+
m_dxvkInstance (pDxvkInstance),
3214+
m_dxvkAdapter (pDxvkAdapter),
3215+
m_dxvkDevice (pDxvkDevice),
3216+
m_d3d11Device (this, FeatureLevel, FeatureFlags),
3217+
m_d3d11DeviceExt (this, &m_d3d11Device),
3218+
m_d3d11Interop (this, &m_d3d11Device),
3219+
m_d3dLowLatencyDevice (this, &m_d3d11Device),
3220+
m_d3d11Video (this, &m_d3d11Device),
3221+
m_d3d11on12 (this, &m_d3d11Device, pD3D12Device, pD3D12Queue),
3222+
m_metaDevice (this),
3223+
m_dxvkFactory (this, &m_d3d11Device) {
30923224

30933225
}
30943226

@@ -3142,7 +3274,12 @@ namespace dxvk {
31423274
*ppvObject = ref(&m_d3d11DeviceExt);
31433275
return S_OK;
31443276
}
3145-
3277+
3278+
if (riid == __uuidof(ID3DLowLatencyDevice)) {
3279+
*ppvObject = ref(&m_d3dLowLatencyDevice);
3280+
return S_OK;
3281+
}
3282+
31463283
if (riid == __uuidof(IDXGIDXVKDevice)) {
31473284
*ppvObject = ref(&m_metaDevice);
31483285
return S_OK;

src/d3d11/d3d11_device.h

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "d3d11_options.h"
2525
#include "d3d11_shader.h"
2626
#include "d3d11_state.h"
27+
#include "d3d11_swapchain.h"
2728
#include "d3d11_util.h"
2829

2930
namespace dxvk {
@@ -428,6 +429,18 @@ namespace dxvk {
428429

429430
bool Is11on12Device() const;
430431

432+
void AddSwapchain(D3D11SwapChain* swapchain) {
433+
m_swapchains.push_back(swapchain);
434+
}
435+
436+
void RemoveSwapchain(D3D11SwapChain* swapchain) {
437+
m_swapchains.erase(std::remove(m_swapchains.begin(), m_swapchains.end(), swapchain));
438+
}
439+
440+
D3D11SwapChain* GetLowLatencySwapChain() {
441+
return (m_swapchains.size() == 1) ? m_swapchains[0] : nullptr;
442+
}
443+
431444
static D3D_FEATURE_LEVEL GetMaxFeatureLevel(
432445
const Rc<DxvkInstance>& Instance,
433446
const Rc<DxvkAdapter>& Adapter);
@@ -464,6 +477,8 @@ namespace dxvk {
464477
D3D_FEATURE_LEVEL m_maxFeatureLevel;
465478
D3D11DeviceFeatures m_deviceFeatures;
466479

480+
std::vector<D3D11SwapChain*> m_swapchains;
481+
467482
HRESULT CreateShaderModule(
468483
D3D11CommonShader* pShaderModule,
469484
DxvkShaderKey ShaderKey,
@@ -545,28 +560,28 @@ namespace dxvk {
545560
uint64_t* gpuVAStart,
546561
uint64_t* gpuVASize);
547562

548-
bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
563+
bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
549564
ID3D11Resource* pResource,
550565
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
551566
ID3D11UnorderedAccessView** ppUAV,
552567
uint32_t* pDriverHandle);
553568

554-
bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
569+
bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
555570
ID3D11Resource* pResource,
556571
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
557572
ID3D11ShaderResourceView** ppSRV,
558573
uint32_t* pDriverHandle);
559574

560-
bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
575+
bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
561576
const D3D11_SAMPLER_DESC* pSamplerDesc,
562577
ID3D11SamplerState** ppSamplerState,
563578
uint32_t* pDriverHandle);
564-
579+
565580
private:
566581

567582
D3D11DXGIDevice* m_container;
568583
D3D11Device* m_device;
569-
584+
570585
void AddSamplerAndHandleNVX(
571586
ID3D11SamplerState* pSampler,
572587
uint32_t Handle);
@@ -586,6 +601,46 @@ namespace dxvk {
586601
std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr;
587602
};
588603

604+
/**
605+
* \brief Extended D3D11 device
606+
*/
607+
class D3D11LowLatencyDevice : public ID3DLowLatencyDevice {
608+
609+
public:
610+
611+
D3D11LowLatencyDevice(
612+
D3D11DXGIDevice* pContainer,
613+
D3D11Device* pDevice);
614+
615+
ULONG STDMETHODCALLTYPE AddRef();
616+
617+
ULONG STDMETHODCALLTYPE Release();
618+
619+
HRESULT STDMETHODCALLTYPE QueryInterface(
620+
REFIID riid,
621+
void** ppvObject);
622+
623+
BOOL STDMETHODCALLTYPE SupportsLowLatency();
624+
625+
HRESULT STDMETHODCALLTYPE LatencySleep();
626+
627+
HRESULT STDMETHODCALLTYPE SetLatencySleepMode(
628+
BOOL lowLatencyMode,
629+
BOOL lowLatencyBoost,
630+
uint32_t minimumIntervalUs);
631+
632+
HRESULT STDMETHODCALLTYPE SetLatencyMarker(
633+
uint64_t frameID,
634+
uint32_t markerType);
635+
636+
HRESULT STDMETHODCALLTYPE GetLatencyInfo(
637+
D3D11_LATENCY_RESULTS* latencyResults);
638+
639+
private:
640+
641+
D3D11DXGIDevice* m_container;
642+
D3D11Device* m_device;
643+
};
589644

590645
/**
591646
* \brief D3D11 video device
@@ -856,12 +911,13 @@ namespace dxvk {
856911
Rc<DxvkAdapter> m_dxvkAdapter;
857912
Rc<DxvkDevice> m_dxvkDevice;
858913

859-
D3D11Device m_d3d11Device;
860-
D3D11DeviceExt m_d3d11DeviceExt;
861-
D3D11VkInterop m_d3d11Interop;
862-
D3D11VideoDevice m_d3d11Video;
863-
D3D11on12Device m_d3d11on12;
864-
DXGIDXVKDevice m_metaDevice;
914+
D3D11Device m_d3d11Device;
915+
D3D11DeviceExt m_d3d11DeviceExt;
916+
D3D11VkInterop m_d3d11Interop;
917+
D3D11LowLatencyDevice m_d3dLowLatencyDevice;
918+
D3D11VideoDevice m_d3d11Video;
919+
D3D11on12Device m_d3d11on12;
920+
DXGIDXVKDevice m_metaDevice;
865921

866922
DXGIVkSwapChainFactory m_dxvkFactory;
867923

src/d3d11/d3d11_initializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ namespace dxvk {
280280

281281

282282
void D3D11Initializer::FlushInternal() {
283-
m_context->flushCommandList(nullptr);
283+
m_context->flushCommandList(nullptr, false);
284284

285285
m_transferCommands = 0;
286286
m_transferMemory = 0;

0 commit comments

Comments
 (0)