Skip to content

Commit

Permalink
Add VK_NV_low_latency2 support
Browse files Browse the repository at this point in the history
This commit add support for the VK_NV_low_latency2 extension, and
implements the ID3DLowLatencyDevice interface.
  • Loading branch information
esullivan-nvidia committed Oct 13, 2023
1 parent e6e806d commit 74c1ba4
Show file tree
Hide file tree
Showing 17 changed files with 554 additions and 46 deletions.
168 changes: 153 additions & 15 deletions src/d3d11/d3d11_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "d3d11_device.h"
#include "d3d11_fence.h"
#include "d3d11_input_layout.h"
#include "d3d11_interfaces.h"
#include "d3d11_interop.h"
#include "d3d11_query.h"
#include "d3d11_resource.h"
Expand Down Expand Up @@ -2469,12 +2470,14 @@ namespace dxvk {
return deviceFeatures.nvxBinaryImport
&& deviceFeatures.vk12.bufferDeviceAddress;

case D3D11_VK_NV_LOW_LATENCY_2:
return deviceFeatures.nvLowLatency2;

default:
return false;
}
}



bool STDMETHODCALLTYPE D3D11DeviceExt::GetCudaTextureObjectNVX(uint32_t srvDriverHandle, uint32_t samplerDriverHandle, uint32_t* pCudaTextureHandle) {
ID3D11ShaderResourceView* srv = HandleToSrvNVX(srvDriverHandle);

Expand Down Expand Up @@ -2783,8 +2786,133 @@ namespace dxvk {




D3D11LowLatencyDevice::D3D11LowLatencyDevice(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice)
: m_container(pContainer), m_device(pDevice) {

}


ULONG STDMETHODCALLTYPE D3D11LowLatencyDevice::AddRef() {
return m_container->AddRef();
}


ULONG STDMETHODCALLTYPE D3D11LowLatencyDevice::Release() {
return m_container->Release();
}


HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_container->QueryInterface(riid, ppvObject);
}

BOOL STDMETHODCALLTYPE D3D11LowLatencyDevice::SupportsLowLatency() {
return m_device->GetDXVKDevice()->features().nvLowLatency2;
}

HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::LatencySleep() {
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
return E_NOINTERFACE;
}

D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();
if (pSwapChain && pSwapChain->LowLatencyEnabled()) {
VkResult res = pSwapChain->LatencySleep();
if (res != VK_SUCCESS) {
return S_FALSE;
}
}

return S_OK;
}

HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::SetLatencySleepMode(BOOL lowLatencyMode, BOOL lowLatencyBoost, uint32_t minimumIntervalUs) {
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
return E_NOINTERFACE;
}

D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();
if (pSwapChain) {
VkResult res = pSwapChain->SetLatencySleepMode(lowLatencyMode, lowLatencyBoost, minimumIntervalUs);
if (res != VK_SUCCESS) {
return S_FALSE;
}
}

return S_OK;
}

HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::SetLatencyMarker(uint64_t frameID, uint32_t markerType) {
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
return E_NOINTERFACE;
}

D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();
VkLatencyMarkerNV marker = static_cast<VkLatencyMarkerNV>(markerType);
uint64_t internalFrameId = frameID + DXGI_MAX_SWAP_CHAIN_BUFFERS;

m_device->GetDXVKDevice()->setLatencyMarker(marker, internalFrameId);

if (pSwapChain && pSwapChain->LowLatencyEnabled()) {
pSwapChain->SetLatencyMarker(marker, internalFrameId);
}

return S_OK;
}

HRESULT STDMETHODCALLTYPE D3D11LowLatencyDevice::GetLatencyInfo(D3D11_LATENCY_RESULTS* latency_results)
{
if (!m_device->GetDXVKDevice()->features().nvLowLatency2) {
return E_NOINTERFACE;
}

constexpr uint32_t frameReportSize = 64;
D3D11SwapChain* pSwapChain = m_device->GetLowLatencySwapChain();

if (pSwapChain && pSwapChain->LowLatencyEnabled()) {
std::vector<VkLatencyTimingsFrameReportNV> frameReports;
pSwapChain->GetLatencyTimings(frameReports);

if (frameReports.size() >= frameReportSize) {
for (uint32_t i = 0; i < frameReportSize; i++) {
VkLatencyTimingsFrameReportNV& frameReport = frameReports[i];
latency_results->frame_reports[i].frameID = frameReport.presentID - DXGI_MAX_SWAP_CHAIN_BUFFERS;
latency_results->frame_reports[i].inputSampleTime = frameReport.inputSampleTimeUs;
latency_results->frame_reports[i].simStartTime = frameReport.simStartTimeUs;
latency_results->frame_reports[i].simEndTime = frameReport.simEndTimeUs;
latency_results->frame_reports[i].renderSubmitStartTime = frameReport.renderSubmitStartTimeUs;
latency_results->frame_reports[i].renderSubmitEndTime = frameReport.renderSubmitEndTimeUs;
latency_results->frame_reports[i].presentStartTime = frameReport.presentStartTimeUs;
latency_results->frame_reports[i].presentEndTime = frameReport.presentEndTimeUs;
latency_results->frame_reports[i].driverStartTime = frameReport.driverStartTimeUs;
latency_results->frame_reports[i].driverEndTime = frameReport.driverEndTimeUs;
latency_results->frame_reports[i].osRenderQueueStartTime = frameReport.osRenderQueueStartTimeUs;
latency_results->frame_reports[i].osRenderQueueEndTime = frameReport.osRenderQueueEndTimeUs;
latency_results->frame_reports[i].gpuRenderStartTime = frameReport.gpuRenderStartTimeUs;
latency_results->frame_reports[i].gpuRenderEndTime = frameReport.gpuRenderEndTimeUs;
latency_results->frame_reports[i].gpuActiveRenderTimeUs =
frameReport.gpuRenderEndTimeUs - frameReport.gpuRenderStartTimeUs;
latency_results->frame_reports[i].gpuFrameTimeUs = 0;

if (i) {
latency_results->frame_reports[i].gpuFrameTimeUs =
frameReports[i].gpuRenderEndTimeUs - frameReports[i - 1].gpuRenderEndTimeUs;
}
}
}
}

return S_OK;
}




D3D11VideoDevice::D3D11VideoDevice(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice)
Expand Down Expand Up @@ -3021,7 +3149,11 @@ namespace dxvk {

Com<D3D11SwapChain> presenter = new D3D11SwapChain(
m_container, m_device, pSurfaceFactory, pDesc);


if (m_device->GetDXVKDevice()->features().nvLowLatency2) {
m_device->AddSwapchain(presenter.ref());
}

*ppSwapChain = presenter.ref();
return S_OK;
} catch (const DxvkError& e) {
Expand Down Expand Up @@ -3078,17 +3210,18 @@ namespace dxvk {
Rc<DxvkDevice> pDxvkDevice,
D3D_FEATURE_LEVEL FeatureLevel,
UINT FeatureFlags)
: m_dxgiAdapter (pAdapter),
m_dxvkInstance (pDxvkInstance),
m_dxvkAdapter (pDxvkAdapter),
m_dxvkDevice (pDxvkDevice),
m_d3d11Device (this, FeatureLevel, FeatureFlags),
m_d3d11DeviceExt(this, &m_d3d11Device),
m_d3d11Interop (this, &m_d3d11Device),
m_d3d11Video (this, &m_d3d11Device),
m_d3d11on12 (this, &m_d3d11Device, pD3D12Device, pD3D12Queue),
m_metaDevice (this),
m_dxvkFactory (this, &m_d3d11Device) {
: m_dxgiAdapter (pAdapter),
m_dxvkInstance (pDxvkInstance),
m_dxvkAdapter (pDxvkAdapter),
m_dxvkDevice (pDxvkDevice),
m_d3d11Device (this, FeatureLevel, FeatureFlags),
m_d3d11DeviceExt (this, &m_d3d11Device),
m_d3d11Interop (this, &m_d3d11Device),
m_d3dLowLatencyDevice (this, &m_d3d11Device),
m_d3d11Video (this, &m_d3d11Device),
m_d3d11on12 (this, &m_d3d11Device, pD3D12Device, pD3D12Queue),
m_metaDevice (this),
m_dxvkFactory (this, &m_d3d11Device) {

}

Expand Down Expand Up @@ -3142,7 +3275,12 @@ namespace dxvk {
*ppvObject = ref(&m_d3d11DeviceExt);
return S_OK;
}


if (riid == __uuidof(ID3DLowLatencyDevice)) {
*ppvObject = ref(&m_d3dLowLatencyDevice);
return S_OK;
}

if (riid == __uuidof(IDXGIDXVKDevice)) {
*ppvObject = ref(&m_metaDevice);
return S_OK;
Expand Down
82 changes: 71 additions & 11 deletions src/d3d11/d3d11_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "d3d11_options.h"
#include "d3d11_shader.h"
#include "d3d11_state.h"
#include "d3d11_swapchain.h"
#include "d3d11_util.h"

namespace dxvk {
Expand Down Expand Up @@ -428,6 +429,22 @@ namespace dxvk {

bool Is11on12Device() const;

void AddSwapchain(D3D11SwapChain* swapchain) {
m_swapchains.push_back(swapchain);
}

void RemoveSwapchain(D3D11SwapChain* swapchain) {
std::remove(m_swapchains.begin(), m_swapchains.end(), swapchain);
}

UINT GetSwapchainCount() {
return m_swapchains.size();
}

D3D11SwapChain* GetLowLatencySwapChain() {
return (m_swapchains.size()) == 1 ? m_swapchains[0] : nullptr;
}

static D3D_FEATURE_LEVEL GetMaxFeatureLevel(
const Rc<DxvkInstance>& Instance,
const Rc<DxvkAdapter>& Adapter);
Expand Down Expand Up @@ -464,6 +481,8 @@ namespace dxvk {
D3D_FEATURE_LEVEL m_maxFeatureLevel;
D3D11DeviceFeatures m_deviceFeatures;

std::vector<D3D11SwapChain*> m_swapchains;

HRESULT CreateShaderModule(
D3D11CommonShader* pShaderModule,
DxvkShaderKey ShaderKey,
Expand Down Expand Up @@ -545,28 +564,28 @@ namespace dxvk {
uint64_t* gpuVAStart,
uint64_t* gpuVASize);

bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
ID3D11Resource* pResource,
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
ID3D11UnorderedAccessView** ppUAV,
uint32_t* pDriverHandle);

bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
ID3D11Resource* pResource,
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
ID3D11ShaderResourceView** ppSRV,
uint32_t* pDriverHandle);

bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
const D3D11_SAMPLER_DESC* pSamplerDesc,
ID3D11SamplerState** ppSamplerState,
uint32_t* pDriverHandle);

private:

D3D11DXGIDevice* m_container;
D3D11Device* m_device;

void AddSamplerAndHandleNVX(
ID3D11SamplerState* pSampler,
uint32_t Handle);
Expand All @@ -586,6 +605,46 @@ namespace dxvk {
std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr;
};

/**
* \brief Extended D3D11 device
*/
class D3D11LowLatencyDevice : public ID3DLowLatencyDevice {

public:

D3D11LowLatencyDevice(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice);

ULONG STDMETHODCALLTYPE AddRef();

ULONG STDMETHODCALLTYPE Release();

HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);

BOOL STDMETHODCALLTYPE SupportsLowLatency();

HRESULT STDMETHODCALLTYPE LatencySleep();

HRESULT STDMETHODCALLTYPE SetLatencySleepMode(
BOOL lowLatencyMode,
BOOL lowLatencyBoost,
uint32_t minimumIntervalUs);

HRESULT STDMETHODCALLTYPE SetLatencyMarker(
uint64_t frameID,
uint32_t markerType);

HRESULT STDMETHODCALLTYPE GetLatencyInfo(
D3D11_LATENCY_RESULTS* latency_results);

private:

D3D11DXGIDevice* m_container;
D3D11Device* m_device;
};

/**
* \brief D3D11 video device
Expand Down Expand Up @@ -856,12 +915,13 @@ namespace dxvk {
Rc<DxvkAdapter> m_dxvkAdapter;
Rc<DxvkDevice> m_dxvkDevice;

D3D11Device m_d3d11Device;
D3D11DeviceExt m_d3d11DeviceExt;
D3D11VkInterop m_d3d11Interop;
D3D11VideoDevice m_d3d11Video;
D3D11on12Device m_d3d11on12;
DXGIDXVKDevice m_metaDevice;
D3D11Device m_d3d11Device;
D3D11DeviceExt m_d3d11DeviceExt;
D3D11VkInterop m_d3d11Interop;
D3D11LowLatencyDevice m_d3dLowLatencyDevice;
D3D11VideoDevice m_d3d11Video;
D3D11on12Device m_d3d11on12;
DXGIDXVKDevice m_metaDevice;

DXGIVkSwapChainFactory m_dxvkFactory;

Expand Down
Loading

0 comments on commit 74c1ba4

Please sign in to comment.