Skip to content

Commit 60e1051

Browse files
committed
nvapi-d3d: Always assume IUnknown device
Combine querying for ID3DLowLatencyDevice from IUnknown and ID3D12CommandQueue.
1 parent 0b2c1cb commit 60e1051

File tree

4 files changed

+178
-120
lines changed

4 files changed

+178
-120
lines changed

src/nvapi/nvapi_d3d_low_latency_device.cpp

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,62 @@
44
#include "../util/util_log.h"
55

66
namespace dxvk {
7-
std::unordered_map<IUnknown*, NvapiD3dLowLatencyDevice> NvapiD3dLowLatencyDevice::m_lowLatencyDeviceMap = {};
7+
std::unordered_map<IUnknown*, std::shared_ptr<NvapiD3dLowLatencyDevice>> NvapiD3dLowLatencyDevice::m_lowLatencyDeviceMap = {};
88
std::mutex NvapiD3dLowLatencyDevice::m_mutex = {};
99

1010
void NvapiD3dLowLatencyDevice::Reset() {
1111
std::scoped_lock lock{m_mutex};
1212
m_lowLatencyDeviceMap.clear();
1313
}
1414

15+
static Com<ID3DLowLatencyDevice> GetD3DLowLatencyDevice(IUnknown* device) {
16+
Com<ID3DLowLatencyDevice> d3dLowLatencyDevice;
17+
18+
if (SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&d3dLowLatencyDevice))))
19+
return d3dLowLatencyDevice;
20+
21+
if (Com<ID3D11DeviceChild> d3d11DeviceChild; SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&d3d11DeviceChild)))) {
22+
Com<ID3D11Device> d3d11Device;
23+
d3d11DeviceChild->GetDevice(&d3d11Device);
24+
if (SUCCEEDED(d3d11Device->QueryInterface(IID_PPV_ARGS(&d3dLowLatencyDevice))))
25+
return d3dLowLatencyDevice;
26+
}
27+
28+
if (Com<ID3D12DeviceChild> d3d12DeviceChild; SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&d3d12DeviceChild)))) {
29+
if (SUCCEEDED(d3d12DeviceChild->GetDevice(IID_PPV_ARGS(&d3dLowLatencyDevice))))
30+
return d3dLowLatencyDevice;
31+
}
32+
33+
return nullptr;
34+
}
35+
1536
NvapiD3dLowLatencyDevice* NvapiD3dLowLatencyDevice::GetOrCreate(IUnknown* device) {
1637
std::scoped_lock lock{m_mutex};
1738

1839
if (auto lowLatencyDevice = Get(device))
1940
return lowLatencyDevice;
2041

21-
Com<ID3DLowLatencyDevice> d3dLowLatencyDevice;
22-
if (FAILED(device->QueryInterface(IID_PPV_ARGS(&d3dLowLatencyDevice))))
42+
auto d3dLowLatencyDevice = GetD3DLowLatencyDevice(device);
43+
if (d3dLowLatencyDevice == nullptr)
2344
return nullptr;
2445

25-
auto [it, inserted] = m_lowLatencyDeviceMap.emplace(
26-
std::piecewise_construct,
27-
std::forward_as_tuple(device),
28-
std::forward_as_tuple(d3dLowLatencyDevice.ptr()));
46+
// Look for a cache entry where NvapiD3dLowLatencyDevice's m_d3dLowLatencyDevice matches the one we found
47+
auto itF = std::find_if(m_lowLatencyDeviceMap.begin(), m_lowLatencyDeviceMap.end(),
48+
[&d3dLowLatencyDevice](auto& item) { return item.second->m_d3dLowLatencyDevice == d3dLowLatencyDevice.ptr(); });
49+
50+
auto [itI, inserted] = itF == m_lowLatencyDeviceMap.end()
51+
? m_lowLatencyDeviceMap.emplace(device, std::make_shared<NvapiD3dLowLatencyDevice>(d3dLowLatencyDevice.ptr()))
52+
: m_lowLatencyDeviceMap.emplace(device, itF->second);
2953

3054
if (!inserted)
3155
return nullptr;
3256

33-
return &it->second;
34-
}
35-
36-
NvapiD3dLowLatencyDevice* NvapiD3dLowLatencyDevice::GetOrCreate(ID3D12CommandQueue* commandQueue) {
37-
// some games like The Cycle: Frontier (868270) pass ID3D11DeviceContext to NvAPI_D3D12_SetAsyncFrameMarker,
38-
// so let's not trust the caller and handle this somewhat gracefully instead of just crashing
39-
if (Com<ID3D11DeviceChild> d3d11DeviceChild; SUCCEEDED(commandQueue->QueryInterface(IID_PPV_ARGS(&d3d11DeviceChild)))) {
40-
Com<ID3D11Device> d3d11Device;
41-
d3d11DeviceChild->GetDevice(&d3d11Device);
42-
return GetOrCreate(d3d11Device.ptr());
43-
}
44-
45-
Com<ID3D12Device> d3d12Device;
46-
if (SUCCEEDED(commandQueue->GetDevice(IID_PPV_ARGS(&d3d12Device))))
47-
return GetOrCreate(static_cast<IUnknown*>(d3d12Device.ptr()));
48-
49-
return nullptr;
57+
return itI->second.get();
5058
}
5159

5260
NvapiD3dLowLatencyDevice* NvapiD3dLowLatencyDevice::Get(IUnknown* device) {
5361
auto it = m_lowLatencyDeviceMap.find(device);
54-
return it == m_lowLatencyDeviceMap.end() ? nullptr : &it->second;
62+
return it == m_lowLatencyDeviceMap.end() ? nullptr : it->second.get();
5563
}
5664

5765
std::optional<uint32_t> NvapiD3dLowLatencyDevice::ToMarkerType(NV_LATENCY_MARKER_TYPE markerType) {

src/nvapi/nvapi_d3d_low_latency_device.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ namespace dxvk {
1010
public:
1111
static void Reset();
1212
[[nodiscard]] static NvapiD3dLowLatencyDevice* GetOrCreate(IUnknown* device);
13-
[[nodiscard]] static NvapiD3dLowLatencyDevice* GetOrCreate(ID3D12CommandQueue* commandQueue);
14-
1513
[[nodiscard]] static std::optional<uint32_t> ToMarkerType(NV_LATENCY_MARKER_TYPE markerType);
1614

1715
explicit NvapiD3dLowLatencyDevice(ID3DLowLatencyDevice* m_d3dLowLatencyDevice);
@@ -26,11 +24,11 @@ namespace dxvk {
2624
private:
2725
[[nodiscard]] static NvapiD3dLowLatencyDevice* Get(IUnknown*);
2826

29-
static std::unordered_map<IUnknown*, NvapiD3dLowLatencyDevice> m_lowLatencyDeviceMap;
27+
static std::unordered_map<IUnknown*, std::shared_ptr<NvapiD3dLowLatencyDevice>> m_lowLatencyDeviceMap;
3028
static std::mutex m_mutex;
3129

3230
ID3DLowLatencyDevice* m_d3dLowLatencyDevice{};
33-
bool m_lowLatencyMode{};
3431
LowLatencyFrameIdGenerator m_frameIdGenerator;
32+
bool m_lowLatencyMode{};
3533
};
3634
}

0 commit comments

Comments
 (0)