Skip to content

Commit

Permalink
d3d12: Accept D3D12 command queues in low latency device helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
Saancreed authored and jp7677 committed Jun 15, 2024
1 parent 7839bed commit e93e847
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 11 deletions.
37 changes: 37 additions & 0 deletions src/d3d/nvapi_d3d_low_latency_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ namespace dxvk {
return d3dLowLatencyDevice->SupportsLowLatency();
}

bool NvapiD3dLowLatencyDevice::SupportsLowLatency(ID3D12CommandQueue* commandQueue) {
auto d3dLowLatencyDevice = GetLowLatencyDevice(commandQueue);
if (d3dLowLatencyDevice == nullptr)
return false;

return d3dLowLatencyDevice->SupportsLowLatency();
}

bool NvapiD3dLowLatencyDevice::LatencySleep(IUnknown* device) {
auto d3dLowLatencyDevice = GetLowLatencyDevice(device);
if (d3dLowLatencyDevice == nullptr)
Expand Down Expand Up @@ -93,6 +101,15 @@ namespace dxvk {
GetFrameIdGenerator(d3dLowLatencyDevice.ptr())->GetLowLatencyDeviceFrameId(frameID), markerType));
}

bool NvapiD3dLowLatencyDevice::SetLatencyMarker(ID3D12CommandQueue* commandQueue, uint64_t frameID, uint32_t markerType) {
auto d3dLowLatencyDevice = GetLowLatencyDevice(commandQueue);
if (d3dLowLatencyDevice == nullptr)
return false;

return SUCCEEDED(d3dLowLatencyDevice->SetLatencyMarker(
GetFrameIdGenerator(d3dLowLatencyDevice.ptr())->GetLowLatencyDeviceFrameId(frameID), markerType));
}

void NvapiD3dLowLatencyDevice::ClearCacheMaps() {
std::scoped_lock lock(m_lowLatencyDeviceMutex, m_lowLatencyFrameIdGeneratorMutex);

Expand All @@ -118,6 +135,26 @@ namespace dxvk {
return d3dLowLatencyDevice;
}

Com<ID3DLowLatencyDevice> NvapiD3dLowLatencyDevice::GetLowLatencyDevice(ID3D12CommandQueue* commandQueue) {
if (commandQueue == nullptr)
return nullptr;

auto unknown = static_cast<IUnknown*>(commandQueue);

std::scoped_lock lock(m_lowLatencyDeviceMutex);
auto it = m_lowLatencyDeviceMap.find(unknown);
if (it != m_lowLatencyDeviceMap.end())
return it->second;

Com<ID3DLowLatencyDevice> d3dLowLatencyDevice;
if (FAILED(commandQueue->GetDevice(IID_PPV_ARGS(&d3dLowLatencyDevice))))
return nullptr;

m_lowLatencyDeviceMap.emplace(unknown, d3dLowLatencyDevice.ptr());

return d3dLowLatencyDevice;
}

LowLatencyFrameIdGenerator* NvapiD3dLowLatencyDevice::GetFrameIdGenerator(ID3DLowLatencyDevice* device) {
std::scoped_lock lock(m_lowLatencyFrameIdGeneratorMutex);
auto it = m_frameIdGeneratorMap.find(device);
Expand Down
3 changes: 3 additions & 0 deletions src/d3d/nvapi_d3d_low_latency_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ namespace dxvk {
class NvapiD3dLowLatencyDevice {
public:
static bool SupportsLowLatency(IUnknown* device);
static bool SupportsLowLatency(ID3D12CommandQueue* commandQueue);
static bool LatencySleep(IUnknown* device);
static bool SetLatencySleepMode(IUnknown* device, bool lowLatencyMode, bool lowLatencyBoost, uint32_t minimumIntervalUs);
static bool GetLatencyInfo(IUnknown* device, D3D_LATENCY_RESULTS* latencyResults);
static bool SetLatencyMarker(IUnknown* device, uint64_t frameID, uint32_t markerType);
static bool SetLatencyMarker(ID3D12CommandQueue* commandQueue, uint64_t frameID, uint32_t markerType);

static void ClearCacheMaps();

Expand All @@ -41,6 +43,7 @@ namespace dxvk {
inline static std::mutex m_lowLatencyFrameIdGeneratorMutex;

[[nodiscard]] static Com<ID3DLowLatencyDevice> GetLowLatencyDevice(IUnknown* device);
[[nodiscard]] static Com<ID3DLowLatencyDevice> GetLowLatencyDevice(ID3D12CommandQueue* commandQueue);
[[nodiscard]] static LowLatencyFrameIdGenerator* GetFrameIdGenerator(ID3DLowLatencyDevice* device);
};
}
14 changes: 3 additions & 11 deletions src/nvapi_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,11 +471,7 @@ extern "C" {
if (pCommandQueue == nullptr)
return InvalidPointer(n);

ID3D12Device* pDevice;
if (FAILED(pCommandQueue->GetDevice(IID_PPV_ARGS(&pDevice))))
return InvalidArgument(n);

if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pDevice))
if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pCommandQueue))
return NoImplementation(n);

if (!NvapiD3d12Device::NotifyOutOfBandCommandQueue(pCommandQueue, static_cast<D3D12_OUT_OF_BAND_CQ_TYPE>(cqType)))
Expand All @@ -501,14 +497,10 @@ extern "C" {
if (pSetLatencyMarkerParams->version != NV_LATENCY_MARKER_PARAMS_VER1)
return IncompatibleStructVersion(n);

ID3D12Device* pDevice;
if (FAILED(pCommandQueue->GetDevice(IID_PPV_ARGS(&pDevice))))
return InvalidArgument(n);

if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pDevice))
if (nvapiD3dInstance->IsUsingLfx() || !NvapiD3dLowLatencyDevice::SupportsLowLatency(pCommandQueue))
return NoImplementation(n);

if (!NvapiD3dLowLatencyDevice::SetLatencyMarker(pDevice, pSetLatencyMarkerParams->frameID, pSetLatencyMarkerParams->markerType))
if (!NvapiD3dLowLatencyDevice::SetLatencyMarker(pCommandQueue, pSetLatencyMarkerParams->frameID, pSetLatencyMarkerParams->markerType))
return Error(n, alreadyLoggedError);

return Ok(n, alreadyLoggedOk);
Expand Down
4 changes: 4 additions & 0 deletions tests/nvapi_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,10 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") {

auto e = ConfigureDefaultTestEnvironment(*dxgiFactory, *vulkan, *nvml, *lfx, adapter, output);

ALLOW_CALL(commandQueue, GetDevice(__uuidof(ID3DLowLatencyDevice), _))
.LR_SIDE_EFFECT(*_2 = static_cast<ID3DLowLatencyDevice*>(&lowLatencyDevice))
.LR_SIDE_EFFECT(lowLatencyDeviceRefCount++)
.RETURN(S_OK);
ALLOW_CALL(device, QueryInterface(__uuidof(ID3DLowLatencyDevice), _))
.LR_SIDE_EFFECT(*_2 = static_cast<ID3DLowLatencyDevice*>(&lowLatencyDevice))
.LR_SIDE_EFFECT(lowLatencyDeviceRefCount++)
Expand Down

0 comments on commit e93e847

Please sign in to comment.