diff --git a/src/dxgi/dxgi_adapter.cpp b/src/dxgi/dxgi_adapter.cpp index 12fedd3a7..662a61f3f 100644 --- a/src/dxgi/dxgi_adapter.cpp +++ b/src/dxgi/dxgi_adapter.cpp @@ -36,6 +36,7 @@ namespace dxvk { || riid == __uuidof(IDXGIAdapter) || riid == __uuidof(IDXGIAdapter1) || riid == __uuidof(IDXGIAdapter2) + || riid == __uuidof(IDXGIAdapter3) || riid == __uuidof(IDXGIVkAdapter)) { *ppvObject = ref(this); return S_OK; @@ -208,6 +209,95 @@ namespace dxvk { } + HRESULT STDMETHODCALLTYPE DxgiAdapter::QueryVideoMemoryInfo( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + DXGI_QUERY_VIDEO_MEMORY_INFO* pVideoMemoryInfo) { + if (NodeIndex > 0 || !pVideoMemoryInfo) + return DXGI_ERROR_INVALID_CALL; + + if (MemorySegmentGroup != DXGI_MEMORY_SEGMENT_GROUP_LOCAL + && MemorySegmentGroup != DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL) + return DXGI_ERROR_INVALID_CALL; + + DxvkAdapterMemoryInfo memInfo = m_adapter->getMemoryHeapInfo(); + + VkMemoryHeapFlags heapFlagMask = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + VkMemoryHeapFlags heapFlags = 0; + + if (MemorySegmentGroup == DXGI_MEMORY_SEGMENT_GROUP_LOCAL) + heapFlags |= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + + pVideoMemoryInfo->Budget = 0; + pVideoMemoryInfo->CurrentUsage = 0; + + for (uint32_t i = 0; i < memInfo.heapCount; i++) { + if ((memInfo.heaps[i].heapFlags & heapFlagMask) != heapFlags) + continue; + + pVideoMemoryInfo->Budget += memInfo.heaps[i].memoryAvailable; + pVideoMemoryInfo->CurrentUsage += memInfo.heaps[i].memoryAllocated; + } + + // We don't implement reservation, but the observable + // behaviour should match that of Windows drivers + uint32_t segmentId = uint32_t(MemorySegmentGroup); + + pVideoMemoryInfo->AvailableForReservation = pVideoMemoryInfo->Budget / 2; + pVideoMemoryInfo->CurrentReservation = m_memReservation[segmentId]; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::SetVideoMemoryReservation( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + UINT64 Reservation) { + DXGI_QUERY_VIDEO_MEMORY_INFO info; + + HRESULT hr = QueryVideoMemoryInfo( + NodeIndex, MemorySegmentGroup, &info); + + if (FAILED(hr)) + return hr; + + if (Reservation > info.AvailableForReservation) + return DXGI_ERROR_INVALID_CALL; + + uint32_t segmentId = uint32_t(MemorySegmentGroup); + m_memReservation[segmentId] = Reservation; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::RegisterHardwareContentProtectionTeardownStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + Logger::err("DxgiAdapter::RegisterHardwareContentProtectionTeardownStatusEvent: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::RegisterVideoMemoryBudgetChangeNotificationEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + Logger::err("DxgiAdapter::RegisterVideoMemoryBudgetChangeNotificationEvent: Not implemented"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE DxgiAdapter::UnregisterHardwareContentProtectionTeardownStatus( + DWORD dwCookie) { + Logger::err("DxgiAdapter::UnregisterHardwareContentProtectionTeardownStatus: Not implemented"); + } + + + void STDMETHODCALLTYPE DxgiAdapter::UnregisterVideoMemoryBudgetChangeNotification( + DWORD dwCookie) { + Logger::err("DxgiAdapter::UnregisterVideoMemoryBudgetChangeNotification: Not implemented"); + } + + Rc<DxvkAdapter> STDMETHODCALLTYPE DxgiAdapter::GetDXVKAdapter() { return m_adapter; } diff --git a/src/dxgi/dxgi_adapter.h b/src/dxgi/dxgi_adapter.h index 9ca692bb0..d204b8a53 100644 --- a/src/dxgi/dxgi_adapter.h +++ b/src/dxgi/dxgi_adapter.h @@ -46,6 +46,30 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE GetDesc2( DXGI_ADAPTER_DESC2* pDesc) final; + HRESULT STDMETHODCALLTYPE QueryVideoMemoryInfo( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + DXGI_QUERY_VIDEO_MEMORY_INFO* pVideoMemoryInfo) final; + + HRESULT STDMETHODCALLTYPE SetVideoMemoryReservation( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + UINT64 Reservation) final; + + HRESULT STDMETHODCALLTYPE RegisterHardwareContentProtectionTeardownStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) final; + + HRESULT STDMETHODCALLTYPE RegisterVideoMemoryBudgetChangeNotificationEvent( + HANDLE hEvent, + DWORD* pdwCookie) final; + + void STDMETHODCALLTYPE UnregisterHardwareContentProtectionTeardownStatus( + DWORD dwCookie) final; + + void STDMETHODCALLTYPE UnregisterVideoMemoryBudgetChangeNotification( + DWORD dwCookie) final; + Rc<DxvkAdapter> STDMETHODCALLTYPE GetDXVKAdapter() final; HRESULT STDMETHODCALLTYPE CreateDevice( @@ -81,6 +105,7 @@ namespace dxvk { Rc<DxvkAdapter> m_adapter; DXGIVkFormatTable m_formats; + UINT64 m_memReservation[2] = { 0, 0 }; std::mutex m_outputMutex; OutputMap m_outputData; diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index 4405949b9..c63262bb9 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -89,7 +89,7 @@ IDXGIVkDevice : public IDXGIDevice3 { * this interface. */ MIDL_INTERFACE("907bf281-ea3c-43b4-a8e4-9f231107b4ff") -IDXGIVkAdapter : public IDXGIAdapter2 { +IDXGIVkAdapter : public IDXGIAdapter3 { static const GUID guid; virtual dxvk::Rc<dxvk::DxvkAdapter> STDMETHODCALLTYPE GetDXVKAdapter() = 0;