From: Conor McCarthy Subject: [PATCH v2 2/7] wined3d: Add functions to support device local and non-local memory info management. Message-Id: <20191114134831.7896-2-cmccarthy@codeweavers.com> Date: Thu, 14 Nov 2019 23:48:26 +1000 In-Reply-To: <20191114134831.7896-1-cmccarthy@codeweavers.com> References: <20191114134831.7896-1-cmccarthy@codeweavers.com> Signed-off-by: Conor McCarthy --- v2: Prevent external updates occuring when WINED3D_VIDMEM_ACCOUNTING is active, and make wined3d_update_adapter_memory_info() return void. --- dlls/wined3d/directx.c | 182 ++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 5 ++ include/wine/wined3d.h | 17 ++++ 3 files changed, 204 insertions(+) diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index fa991d36..cd1c0996 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1378,6 +1378,188 @@ fail: return WINED3DERR_INVALIDCALL; } +void CDECL wined3d_update_adapter_memory_info(const struct wined3d *wined3d, unsigned int adapter_idx, + unsigned int non_local, UINT64 bytes_total, UINT64 bytes_used) +{ + struct wined3d_adapter *adapter; + DWORD i; + + wined3d_mutex_lock(); + + if (wined3d->flags & WINED3D_VIDMEM_ACCOUNTING) + { + ERR("External memory info updates and WINED3D_VIDMEM_ACCOUNTING are mutually exclusive.\n"); + goto done; + } + + if (adapter_idx >= wined3d->adapter_count || non_local >= ARRAY_SIZE(adapter->memory_usage)) + { + ERR("Invalid parameter.\n"); + goto done; + } + + adapter = wined3d->adapters[adapter_idx]; + adapter->memory_usage[non_local].bytes_used = bytes_used; + if (non_local) + adapter->driver_info.sysmem_bytes = bytes_total; + else + adapter->driver_info.vram_bytes = bytes_total; + + for (i = 0; i < adapter->event_count; ++i) + if (adapter->memory_events[i]) + SetEvent(adapter->memory_events[i]); + +done: + wined3d_mutex_unlock(); +} + +HRESULT CDECL wined3d_get_adapter_memory_info(const struct wined3d *wined3d, unsigned int adapter_idx, + unsigned int non_local, struct wined3d_adapter_memory_info *info) +{ + const struct wined3d_adapter *adapter; + + TRACE("wined3d %p, adapter_idx %u, non_local %u, info %p.\n", + wined3d, adapter_idx, non_local, info); + + wined3d_mutex_lock(); + + if (adapter_idx >= wined3d->adapter_count || non_local >= ARRAY_SIZE(adapter->memory_usage)) + goto fail; + + adapter = wined3d->adapters[adapter_idx]; + + /* vram_bytes may be zero for a UMA adapter. DXGI defines all memory as local for UMA adapters. */ + if (!adapter->driver_info.vram_bytes) + info->total = non_local ? 0 : adapter->driver_info.sysmem_bytes; + else + info->total = non_local ? adapter->driver_info.sysmem_bytes : adapter->driver_info.vram_bytes; + info->used = adapter->memory_usage[non_local].bytes_used; + info->reserved = adapter->memory_usage[non_local].bytes_reserved; + + wined3d_mutex_unlock(); + + return WINED3D_OK; + +fail: + wined3d_mutex_unlock(); + return E_INVALIDARG; +} + +HRESULT CDECL wined3d_set_adapter_reserved_memory(const struct wined3d *wined3d, unsigned int adapter_idx, + unsigned int non_local, UINT64 reservation) +{ + struct wined3d_adapter_memory_info memory_info; + struct wined3d_adapter *adapter; + HRESULT hr; + + TRACE("wined3d %p, adapter_idx %u, non_local %u, reservation 0x%s.\n", + wined3d, adapter_idx, non_local, wine_dbgstr_longlong(reservation)); + + if (FAILED(hr = wined3d_get_adapter_memory_info(wined3d, adapter_idx, non_local, &memory_info))) + return hr; + if (memory_info.total && reservation > memory_info.total) + return E_INVALIDARG; + + /* FIXME: Windows returns E_INVALIDARG if non-local and a non-zero reservation are specified for + * a UMA adapter. UMA status is unknown unless adapter->driver_info.vram_bytes is zero. */ + + wined3d_mutex_lock(); + + if (adapter_idx >= wined3d->adapter_count || non_local >= ARRAY_SIZE(adapter->memory_usage)) + goto fail; + + FIXME("Memory reservation sizes are returned if queried but otherwise are ignored.\n"); + adapter = wined3d->adapters[adapter_idx]; + adapter->memory_usage[non_local].bytes_reserved = reservation; + + wined3d_mutex_unlock(); + + return WINED3D_OK; + +fail: + wined3d_mutex_unlock(); + return E_INVALIDARG; +} + +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) +{ + HRESULT hr = E_INVALIDARG; + struct wined3d_adapter *adapter; + HANDLE *new_buffer; + + 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(!(new_buffer = heap_realloc(adapter->memory_events, (adapter->event_count + 1) * sizeof(*adapter->memory_events)))) + { + hr = E_OUTOFMEMORY; + goto done; + } + adapter->memory_events = new_buffer; + 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) { diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index a4caebe7..8fb6e7b4 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -14,15 +14,20 @@ @ cdecl wined3d_get_adapter_count(ptr) @ cdecl wined3d_get_adapter_display_mode(ptr long ptr ptr) @ cdecl wined3d_get_adapter_identifier(ptr long long ptr) +@ cdecl wined3d_get_adapter_memory_info(ptr long long ptr) @ cdecl wined3d_get_adapter_mode_count(ptr long long long) @ cdecl wined3d_get_adapter_output(ptr long ptr) @ cdecl wined3d_get_adapter_raster_status(ptr long ptr) @ 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_update_adapter_memory_info(ptr long long int64 int64); @ cdecl wined3d_unregister_windows(ptr) @ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index a05305f4..97fce949 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1742,6 +1742,13 @@ struct wined3d_adapter_identifier SIZE_T shared_system_memory; }; +struct wined3d_adapter_memory_info +{ + UINT64 total; + UINT64 used; + UINT64 reserved; +}; + struct wined3d_swapchain_desc { unsigned int backbuffer_width; @@ -2206,6 +2213,8 @@ HRESULT __cdecl wined3d_get_adapter_display_mode(const struct wined3d *wined3d, struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation); HRESULT __cdecl wined3d_get_adapter_identifier(const struct wined3d *wined3d, UINT adapter_idx, DWORD flags, struct wined3d_adapter_identifier *identifier); +HRESULT __cdecl wined3d_get_adapter_memory_info(const struct wined3d *wined3d, unsigned int adapter_idx, + unsigned int non_local, struct wined3d_adapter_memory_info *info); UINT __cdecl wined3d_get_adapter_mode_count(const struct wined3d *wined3d, UINT adapter_idx, enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering); struct wined3d_output * __cdecl wined3d_get_adapter_output(const struct wined3d *wined3d, unsigned int adapter_idx); @@ -2216,11 +2225,19 @@ 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); 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, + unsigned int non_local, UINT64 reservation); +HRESULT __cdecl wined3d_unregister_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx, + DWORD cookie); +void __cdecl wined3d_update_adapter_memory_info(const struct wined3d *wined3d, unsigned int adapter_idx, + unsigned int non_local, UINT64 bytes_total, UINT64 bytes_used); void __cdecl wined3d_unregister_windows(struct wined3d *wined3d); HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc, -- 2.23.0