From: Conor McCarthy Subject: [PATCH v4 4/5] dxgi: Implement IDXGIAdapter3::RegisterVideoMemoryBudgetChangeNotificationEvent(). Message-Id: <20191204141118.27501-4-cmccarthy@codeweavers.com> Date: Thu, 5 Dec 2019 00:11:17 +1000 In-Reply-To: <20191204141118.27501-1-cmccarthy@codeweavers.com> References: <20191204141118.27501-1-cmccarthy@codeweavers.com> Used by Hitman 2. Also implements the unregister function. Signed-off-by: Conor McCarthy --- dlls/dxgi/adapter.c | 14 ++++-- dlls/wined3d/adapter_gl.c | 3 ++ dlls/wined3d/adapter_vk.c | 3 ++ dlls/wined3d/directx.c | 88 ++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 2 + dlls/wined3d/wined3d_private.h | 3 ++ include/wine/wined3d.h | 4 ++ 7 files changed, 114 insertions(+), 3 deletions(-) diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index 3db10e8a..d7afad62 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -356,15 +356,23 @@ 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); + + return wined3d_register_adapter_memory_event(adapter->factory->wined3d, adapter->ordinal, event, cookie); } static void STDMETHODCALLTYPE dxgi_adapter_UnregisterVideoMemoryBudgetChangeNotification( IWineDXGIAdapter *iface, DWORD cookie) { - FIXME("iface %p, cookie %#x stub!\n", iface, cookie); + struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface); + HRESULT hr; + + TRACE("iface %p, cookie %#x.\n", iface, cookie); + + if (FAILED(hr = wined3d_unregister_adapter_memory_event(adapter->factory->wined3d, adapter->ordinal, cookie))) + ERR("Failed to unregister notification, hr %#x.\n", hr); } static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetDesc3(IWineDXGIAdapter *iface, DXGI_ADAPTER_DESC3 *desc) diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 0adcc165..91f97399 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -3882,6 +3882,9 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, driver_info->version_high, driver_info->version_low); memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage)); + adapter->memory_events = NULL; + adapter->event_capacity = 0; + adapter->event_count = 0; TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(driver_info->vram_bytes)); if (gl_info->supported[EXT_MEMORY_OBJECT]) diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index f00de70c..faa940e9 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1181,6 +1181,9 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk, adapter_vk_init_driver_info(adapter, &properties2.properties, &memory_properties); memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage)); + adapter->memory_events = NULL; + adapter->event_capacity = 0; + adapter->event_count = 0; TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes)); memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid)); diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 0d2bdc8e..4625009c 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -157,6 +157,7 @@ UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, enum wined3d_adapt INT64 amount) { uint64_t bytes_total; + uint32_t i; adapter->memory_usage[type].bytes_used += amount; TRACE("Adjusted used adapter memory type %u by 0x%s to 0x%s.\n", type, @@ -169,12 +170,17 @@ UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, enum wined3d_adapt wine_dbgstr_longlong(adapter->memory_usage[type].bytes_used), wine_dbgstr_longlong(bytes_total)); + for (i = 0; i < adapter->event_count; ++i) + if (adapter->memory_events[i]) + SetEvent(adapter->memory_events[i]); + return adapter->memory_usage[type].bytes_used; } void wined3d_adapter_cleanup(struct wined3d_adapter *adapter) { wined3d_output_cleanup(&adapter->output); + heap_free(adapter->memory_events); heap_free(adapter->formats); } @@ -1458,6 +1464,85 @@ fail: return E_INVALIDARG; } +/* Most apps need only one event handle. Large numbers are unlikely so this function is not optimised. */ +static BOOL wined3d_set_unused_event_handle(struct wined3d_adapter *adapter, HANDLE event, DWORD *cookie) +{ + DWORD i; + for (i = 0; i < adapter->event_count; ++i) + { + if (!adapter->memory_events[i]) + { + adapter->memory_events[i] = event; + *cookie = i; + return TRUE; + } + } + return FALSE; +} + +HRESULT CDECL wined3d_register_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx, + HANDLE event, DWORD *cookie) +{ + struct wined3d_adapter *adapter; + HRESULT hr = E_INVALIDARG; + + TRACE("wined3d %p, adapter_idx %u, event %p, cookie %p.\n", + wined3d, adapter_idx, event, cookie); + + if (!cookie) + return E_INVALIDARG; + + wined3d_mutex_lock(); + + if (adapter_idx >= wined3d->adapter_count) + goto done; + + adapter = wined3d->adapters[adapter_idx]; + if (!wined3d_set_unused_event_handle(adapter, event, cookie)) + { + if(!wined3d_array_reserve((void **)&adapter->memory_events, &adapter->event_capacity, + adapter->event_count + 1, sizeof(*adapter->memory_events))) + { + hr = E_OUTOFMEMORY; + goto done; + } + adapter->memory_events[adapter->event_count] = event; + *cookie = adapter->event_count++; + } + + hr = WINED3D_OK; + +done: + wined3d_mutex_unlock(); + return hr; +} + +HRESULT CDECL wined3d_unregister_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx, + DWORD cookie) +{ + struct wined3d_adapter *adapter; + + TRACE("wined3d %p, adapter_idx %u, cookie %u.\n", wined3d, adapter_idx, cookie); + + wined3d_mutex_lock(); + + if (adapter_idx >= wined3d->adapter_count) + goto fail; + + adapter = wined3d->adapters[adapter_idx]; + if (cookie >= adapter->event_count) + goto fail; + adapter->memory_events[cookie] = NULL; + + wined3d_mutex_unlock(); + + return WINED3D_OK; + +fail: + wined3d_mutex_unlock(); + return E_INVALIDARG; +} + HRESULT CDECL wined3d_get_adapter_raster_status(const struct wined3d *wined3d, UINT adapter_idx, struct wined3d_raster_status *raster_status) { @@ -2860,6 +2945,9 @@ static struct wined3d_adapter *wined3d_adapter_no3d_create(unsigned int ordinal, wined3d_driver_info_init(&adapter->driver_info, &gpu_description, 0, 0); memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage)); + adapter->memory_events = NULL; + adapter->event_capacity = 0; + adapter->event_count = 0; TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes)); if (!wined3d_adapter_init(adapter, ordinal, &wined3d_adapter_no3d_ops)) diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 1ff73adf..17cfed9c 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -21,10 +21,12 @@ @ cdecl wined3d_get_device_caps(ptr long long ptr) @ cdecl wined3d_get_output_desc(ptr long ptr) @ cdecl wined3d_incref(ptr) +@ cdecl wined3d_register_adapter_memory_event(ptr long ptr ptr) @ cdecl wined3d_register_software_device(ptr ptr) @ cdecl wined3d_register_window(ptr ptr ptr long) @ cdecl wined3d_set_adapter_display_mode(ptr long ptr) @ cdecl wined3d_set_adapter_reserved_memory(ptr long long int64); +@ cdecl wined3d_unregister_adapter_memory_event(ptr long long); @ cdecl wined3d_unregister_windows(ptr) @ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3b4145fd..d09d60d3 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2886,6 +2886,9 @@ struct wined3d_adapter struct wined3d_driver_info driver_info; struct wined3d_output output; struct wined3d_adapter_memory_usage memory_usage[WINED3D_ADAPTER_MEMORY_COUNT]; + HANDLE *memory_events; + SIZE_T event_capacity; + DWORD event_count; GUID driver_uuid; GUID device_uuid; LUID luid; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 5ca1673d..30c97492 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2230,6 +2230,8 @@ HRESULT __cdecl wined3d_get_device_caps(const struct wined3d *wined3d, unsigned HRESULT __cdecl wined3d_get_output_desc(const struct wined3d *wined3d, unsigned int adapter_idx, struct wined3d_output_desc *desc); ULONG __cdecl wined3d_incref(struct wined3d *wined3d); +HRESULT __cdecl wined3d_register_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx, + HANDLE event, DWORD *cookie); HRESULT __cdecl wined3d_register_software_device(struct wined3d *wined3d, void *init_function); BOOL __cdecl wined3d_register_window(struct wined3d *wined3d, HWND window, struct wined3d_device *device, unsigned int flags); @@ -2237,6 +2239,8 @@ HRESULT __cdecl wined3d_set_adapter_display_mode(struct wined3d *wined3d, UINT adapter_idx, const struct wined3d_display_mode *mode); HRESULT __cdecl wined3d_set_adapter_reserved_memory(const struct wined3d *wined3d, unsigned int adapter_idx, enum wined3d_adapter_memory_type type, UINT64 reservation); +HRESULT __cdecl wined3d_unregister_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx, + DWORD cookie); void __cdecl wined3d_unregister_windows(struct wined3d *wined3d); HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc, -- 2.24.0