Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NV low latency support #3690

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/vulkan
Submodule vulkan updated 71 files
+0 −1 .github/ISSUE_TEMPLATE/bug_report.md
+12 −0 .github/dependabot.yml
+0 −1 .github/pull_request_template.md
+16 −64 .github/workflows/ci.yml
+4 −4 .reuse/dep5
+7 −1 BUILD.gn
+5 −0 CMakeLists.txt
+0 −1 CONTRIBUTING.md
+0 −105 INTEGRATION.md
+6 −10 README.md
+392 −0 include/vk_video/vulkan_video_codec_av1std.h
+109 −0 include/vk_video/vulkan_video_codec_av1std_decode.h
+2 −1 include/vk_video/vulkan_video_codec_h264std.h
+1 −1 include/vk_video/vulkan_video_codec_h264std_decode.h
+7 −6 include/vk_video/vulkan_video_codec_h264std_encode.h
+2 −1 include/vk_video/vulkan_video_codec_h265std.h
+1 −1 include/vk_video/vulkan_video_codec_h265std_decode.h
+20 −19 include/vk_video/vulkan_video_codec_h265std_encode.h
+1 −1 include/vk_video/vulkan_video_codecs_common.h
+1 −1 include/vulkan/vk_platform.h
+2,026 −235 include/vulkan/vulkan.cppm
+1 −1 include/vulkan/vulkan.h
+4,784 −1,664 include/vulkan/vulkan.hpp
+27 −1 include/vulkan/vulkan_android.h
+1 −593 include/vulkan/vulkan_beta.h
+1,753 −255 include/vulkan/vulkan_core.h
+1 −1 include/vulkan/vulkan_directfb.h
+1,046 −560 include/vulkan/vulkan_enums.hpp
+2,157 −804 include/vulkan/vulkan_extension_inspection.hpp
+2 −1 include/vulkan/vulkan_format_traits.hpp
+1 −1 include/vulkan/vulkan_fuchsia.h
+5,937 −2,471 include/vulkan/vulkan_funcs.hpp
+1 −1 include/vulkan/vulkan_ggp.h
+1,276 −447 include/vulkan/vulkan_handles.hpp
+1,484 −444 include/vulkan/vulkan_hash.hpp
+297 −0 include/vulkan/vulkan_hpp_macros.hpp
+1 −1 include/vulkan/vulkan_ios.h
+1 −1 include/vulkan/vulkan_macos.h
+1 −1 include/vulkan/vulkan_metal.h
+5,015 −2,809 include/vulkan/vulkan_raii.hpp
+1 −1 include/vulkan/vulkan_screen.h
+1,087 −0 include/vulkan/vulkan_shared.hpp
+757 −206 include/vulkan/vulkan_static_assertions.hpp
+15,205 −6,994 include/vulkan/vulkan_structs.hpp
+565 −352 include/vulkan/vulkan_to_string.hpp
+1 −1 include/vulkan/vulkan_vi.h
+32 −26 include/vulkan/vulkan_video.hpp
+1 −1 include/vulkan/vulkan_wayland.h
+1 −1 include/vulkan/vulkan_win32.h
+1 −1 include/vulkan/vulkan_xcb.h
+1 −1 include/vulkan/vulkan_xlib.h
+1 −1 include/vulkan/vulkan_xlib_xrandr.h
+1 −1 registry/apiconventions.py
+1 −1 registry/cgenerator.py
+3 −4 registry/generator.py
+0 −1,116 registry/genvk.py
+9 −30 registry/parse_dependency.py
+149 −140 registry/profiles/VP_KHR_roadmap.json
+1 −1 registry/reg.py
+87 −5 registry/spec_tools/conventions.py
+1 −2 registry/spec_tools/util.py
+44,431 −18,823 registry/validusage.json
+516 −27 registry/video.xml
+1,660 −589 registry/vk.xml
+16 −3 registry/vkconventions.py
+25 −38 tests/CMakeLists.txt
+0 −30 tests/add_subdirectory/CMakeLists.txt
+0 −30 tests/find_package/CMakeLists.txt
+73 −0 tests/integration/CMakeLists.txt
+2 −2 tests/vk_icd.c
+2 −2 tests/vk_layer.c
171 changes: 154 additions & 17 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,132 @@ 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()) {
pSwapChain->LatencySleep();
}

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) {
pSwapChain->SetLatencySleepMode(lowLatencyMode, lowLatencyBoost, minimumIntervalUs);
}

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* latencyResults)
{
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];
latencyResults->frame_reports[i].frameID = frameReport.presentID - DXGI_MAX_SWAP_CHAIN_BUFFERS;
latencyResults->frame_reports[i].inputSampleTime = frameReport.inputSampleTimeUs;
latencyResults->frame_reports[i].simStartTime = frameReport.simStartTimeUs;
latencyResults->frame_reports[i].simEndTime = frameReport.simEndTimeUs;
latencyResults->frame_reports[i].renderSubmitStartTime = frameReport.renderSubmitStartTimeUs;
latencyResults->frame_reports[i].renderSubmitEndTime = frameReport.renderSubmitEndTimeUs;
latencyResults->frame_reports[i].presentStartTime = frameReport.presentStartTimeUs;
latencyResults->frame_reports[i].presentEndTime = frameReport.presentEndTimeUs;
latencyResults->frame_reports[i].driverStartTime = frameReport.driverStartTimeUs;
latencyResults->frame_reports[i].driverEndTime = frameReport.driverEndTimeUs;
latencyResults->frame_reports[i].osRenderQueueStartTime = frameReport.osRenderQueueStartTimeUs;
latencyResults->frame_reports[i].osRenderQueueEndTime = frameReport.osRenderQueueEndTimeUs;
latencyResults->frame_reports[i].gpuRenderStartTime = frameReport.gpuRenderStartTimeUs;
latencyResults->frame_reports[i].gpuRenderEndTime = frameReport.gpuRenderEndTimeUs;
latencyResults->frame_reports[i].gpuActiveRenderTimeUs =
frameReport.gpuRenderEndTimeUs - frameReport.gpuRenderStartTimeUs;
latencyResults->frame_reports[i].gpuFrameTimeUs = 0;

if (i) {
latencyResults->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 +3148,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());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to miss a matching RemoveSwapchain call.

}

*ppSwapChain = presenter.ref();
return S_OK;
} catch (const DxvkError& e) {
Expand Down Expand Up @@ -3078,17 +3209,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 +3274,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
78 changes: 67 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,18 @@ namespace dxvk {

bool Is11on12Device() const;

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

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

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 +477,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 +560,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 +601,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* latencyResults);

private:

D3D11DXGIDevice* m_container;
D3D11Device* m_device;
};

/**
* \brief D3D11 video device
Expand Down Expand Up @@ -856,12 +911,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
2 changes: 1 addition & 1 deletion src/d3d11/d3d11_initializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ namespace dxvk {


void D3D11Initializer::FlushInternal() {
m_context->flushCommandList(nullptr);
m_context->flushCommandList(nullptr, false);

m_transferCommands = 0;
m_transferMemory = 0;
Expand Down
Loading
Loading