[PATCH v2 2/7] wined3d: Add functions to support device local and non-local memory info management.
Conor McCarthy
cmccarthy at codeweavers.com
Thu Nov 14 07:48:26 CST 2019
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
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
More information about the wine-devel
mailing list