On 5/20/22 14:16, Zebediah Figura wrote:
On 5/18/22 01:49, Zhiyi Zhang wrote:
@@ -1046,6 +1060,135 @@ 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;
The test also waits for 1 second, which seems like it'd be liable to fail intermittently, if I read this correctly. Should we increase the polling interval here? (Or reduce it in the test?)
I can probably reduce the timeout in the test. It was picked rather randomly and didn't mean the test would fail intermittently.
+ }
+ 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; + HANDLE thread = NULL; + 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); + thread = CreateThread(NULL, 0, notification_thread_func, notification_thread_stop_event, + CREATE_SUSPENDED, NULL); + notification_thread = thread; + } + wined3d_mutex_unlock(); + if (thread) + ResumeThread(thread);
What's the reason for creating the thread suspended?
Because the thread also calls wined3d_mutex_lock/unlock().
+ return WINED3D_OK; +}