Zhiyi Zhang : dxgi: Implement adapter video memory budget change notification.
Alexandre Julliard
julliard at winehq.org
Mon May 23 15:51:52 CDT 2022
Module: wine
Branch: master
Commit: fd6e137dfe16700e0a0a7ebb23b413019bc18193
URL: https://source.winehq.org/git/wine.git/?a=commit;h=fd6e137dfe16700e0a0a7ebb23b413019bc18193
Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date: Mon May 23 11:21:16 2022 +0800
dxgi: Implement adapter video memory budget change notification.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51665
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/dxgi/adapter.c | 13 ++++-
dlls/dxgi/tests/dxgi.c | 4 --
dlls/wined3d/directx.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/wined3d/wined3d.spec | 2 +
include/wine/wined3d.h | 3 +
5 files changed, 154 insertions(+), 7 deletions(-)
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c
index 20c017eba08..b178376341b 100644
--- a/dlls/dxgi/adapter.c
+++ b/dlls/dxgi/adapter.c
@@ -333,15 +333,22 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_SetVideoMemoryReservation(IWineDXG
static HRESULT STDMETHODCALLTYPE dxgi_adapter_RegisterVideoMemoryBudgetChangeNotificationEvent(
IWineDXGIAdapter *iface, HANDLE event, DWORD *cookie)
{
- FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
+ struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface);
- return E_NOTIMPL;
+ TRACE("iface %p, event %p, cookie %p.\n", iface, event, cookie);
+
+ if (!event || !cookie)
+ return DXGI_ERROR_INVALID_CALL;
+
+ return wined3d_adapter_register_budget_change_notification(adapter->wined3d_adapter, event, cookie);
}
static void STDMETHODCALLTYPE dxgi_adapter_UnregisterVideoMemoryBudgetChangeNotification(
IWineDXGIAdapter *iface, DWORD cookie)
{
- FIXME("iface %p, cookie %#lx stub!\n", iface, cookie);
+ TRACE("iface %p, cookie %#lx.\n", iface, cookie);
+
+ wined3d_adapter_unregister_budget_change_notification(cookie);
}
static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetDesc3(IWineDXGIAdapter *iface, DXGI_ADAPTER_DESC3 *desc)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
index 04bba29e8e5..33e9ead31ad 100644
--- a/dlls/dxgi/tests/dxgi.c
+++ b/dlls/dxgi/tests/dxgi.c
@@ -7539,16 +7539,13 @@ static void test_video_memory_budget_notification(void)
goto done;
hr = IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3, NULL, &cookie);
- todo_wine
ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
event = CreateEventW(NULL, FALSE, FALSE, NULL);
hr = IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3, event, NULL);
- todo_wine
ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
hr = IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3, event, &cookie);
- todo_wine
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = IDXGIAdapter3_QueryVideoMemoryInfo(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &memory_info);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
@@ -7560,7 +7557,6 @@ static void test_video_memory_budget_notification(void)
if (memory_info.Budget)
{
ret = WaitForSingleObject(event, 1000);
- todo_wine
ok(ret == WAIT_OBJECT_0, "Expected event fired.\n");
}
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 8c58a346add..fb588b88098 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -23,6 +23,7 @@
#include "wined3d_private.h"
#include "winternl.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(winediag);
@@ -38,6 +39,19 @@ enum wined3d_driver_model
DRIVER_MODEL_NT6X
};
+struct wined3d_adapter_budget_change_notification
+{
+ const struct wined3d_adapter *adapter;
+ HANDLE event;
+ DWORD cookie;
+ UINT64 last_local_budget;
+ UINT64 last_non_local_budget;
+ struct list entry;
+};
+
+static struct list adapter_budget_change_notifications = LIST_INIT( adapter_budget_change_notifications );
+static HANDLE notification_thread, notification_thread_stop_event;
+
/* The d3d device ID */
static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
@@ -1046,6 +1060,131 @@ HRESULT CDECL wined3d_adapter_get_video_memory_info(const struct wined3d_adapter
return WINED3D_OK;
}
+static DWORD CALLBACK notification_thread_func(void *stop_event)
+{
+ struct wined3d_adapter_budget_change_notification *notification;
+ struct wined3d_video_memory_info info;
+ HRESULT hr;
+
+ while (TRUE)
+ {
+ wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(notification, &adapter_budget_change_notifications,
+ struct wined3d_adapter_budget_change_notification, entry)
+ {
+ hr = wined3d_adapter_get_video_memory_info(notification->adapter, 0,
+ WINED3D_MEMORY_SEGMENT_GROUP_LOCAL, &info);
+ if (SUCCEEDED(hr) && info.budget != notification->last_local_budget)
+ {
+ notification->last_local_budget = info.budget;
+ SetEvent(notification->event);
+ continue;
+ }
+
+ hr = wined3d_adapter_get_video_memory_info(notification->adapter, 0,
+ WINED3D_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info);
+ if (SUCCEEDED(hr) && info.budget != notification->last_non_local_budget)
+ {
+ notification->last_non_local_budget = info.budget;
+ SetEvent(notification->event);
+ }
+ }
+ wined3d_mutex_unlock();
+
+ if (WaitForSingleObject(stop_event, 1000) == WAIT_OBJECT_0)
+ break;
+ }
+
+ return TRUE;
+}
+
+HRESULT CDECL wined3d_adapter_register_budget_change_notification(const struct wined3d_adapter *adapter,
+ HANDLE event, DWORD *cookie)
+{
+ static DWORD cookie_counter;
+ static BOOL wrapped;
+ struct wined3d_adapter_budget_change_notification *notification, *new_notification;
+ BOOL found = FALSE;
+
+ new_notification = heap_alloc_zero(sizeof(*new_notification));
+ if (!new_notification)
+ return E_OUTOFMEMORY;
+
+ wined3d_mutex_lock();
+ new_notification->adapter = adapter;
+ new_notification->event = event;
+ new_notification->cookie = cookie_counter++;
+ if (cookie_counter < new_notification->cookie)
+ wrapped = TRUE;
+ if (wrapped)
+ {
+ while (TRUE)
+ {
+ LIST_FOR_EACH_ENTRY(notification, &adapter_budget_change_notifications,
+ struct wined3d_adapter_budget_change_notification, entry)
+ {
+ if (notification->cookie == new_notification->cookie)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ break;
+
+ new_notification->cookie = cookie_counter++;
+ }
+ }
+
+ *cookie = new_notification->cookie;
+ list_add_head(&adapter_budget_change_notifications, &new_notification->entry);
+
+ if (!notification_thread)
+ {
+ notification_thread_stop_event = CreateEventW(0, FALSE, FALSE, NULL);
+ notification_thread = CreateThread(NULL, 0, notification_thread_func,
+ notification_thread_stop_event, 0, NULL);
+ }
+ wined3d_mutex_unlock();
+ return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_adapter_unregister_budget_change_notification(DWORD cookie)
+{
+ struct wined3d_adapter_budget_change_notification *notification;
+ HANDLE thread, thread_stop_event;
+
+ wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(notification, &adapter_budget_change_notifications,
+ struct wined3d_adapter_budget_change_notification, entry)
+ {
+ if (notification->cookie == cookie)
+ {
+ list_remove(¬ification->entry);
+ heap_free(notification);
+ break;
+ }
+ }
+
+ if (!list_empty(&adapter_budget_change_notifications))
+ {
+ wined3d_mutex_unlock();
+ return WINED3D_OK;
+ }
+
+ thread = notification_thread;
+ thread_stop_event = notification_thread_stop_event;
+ notification_thread = NULL;
+ notification_thread_stop_event = NULL;
+ wined3d_mutex_unlock();
+ SetEvent(thread_stop_event);
+ WaitForSingleObject(thread, INFINITE);
+ CloseHandle(thread);
+ CloseHandle(thread_stop_event);
+ return WINED3D_OK;
+}
+
HRESULT CDECL wined3d_register_software_device(struct wined3d *wined3d, void *init_function)
{
FIXME("wined3d %p, init_function %p stub!\n", wined3d, init_function);
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 845ca0fb170..63220e1222c 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -22,6 +22,8 @@
@ cdecl wined3d_adapter_get_output(ptr long)
@ cdecl wined3d_adapter_get_output_count(ptr)
@ cdecl wined3d_adapter_get_video_memory_info(ptr long long ptr)
+@ cdecl wined3d_adapter_register_budget_change_notification(ptr ptr ptr)
+@ cdecl wined3d_adapter_unregister_budget_change_notification(long)
@ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr)
@ cdecl wined3d_blend_state_decref(ptr)
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 2b7a626f751..116aea82348 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2364,6 +2364,9 @@ unsigned int __cdecl wined3d_adapter_get_output_count(const struct wined3d_adapt
HRESULT __cdecl wined3d_adapter_get_video_memory_info(const struct wined3d_adapter *adapter,
unsigned int node_idx, enum wined3d_memory_segment_group group,
struct wined3d_video_memory_info *info);
+HRESULT __cdecl wined3d_adapter_register_budget_change_notification(const struct wined3d_adapter *adapter,
+ HANDLE event, DWORD *cookie);
+HRESULT __cdecl wined3d_adapter_unregister_budget_change_notification(DWORD cookie);
HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
More information about the wine-cvs
mailing list