Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- This set supersedes 173693 to 173699. --- dlls/wined3d/adapter_gl.c | 4 +++- dlls/wined3d/adapter_vk.c | 4 +++- dlls/wined3d/device.c | 6 +++--- dlls/wined3d/directx.c | 11 +++++++---- dlls/wined3d/wined3d_private.h | 10 +++++++++- 5 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 7018c6da..2cc6aaf9 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -3881,7 +3881,9 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n", driver_info->version_high, driver_info->version_low);
- adapter->vram_bytes_used = 0; + memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage)); + adapter->memory_events = NULL; + 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 21163a20..81526ade 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1180,7 +1180,9 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk, VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk->physical_device, &memory_properties));
adapter_vk_init_driver_info(adapter, &properties2.properties, &memory_properties); - adapter->vram_bytes_used = 0; + memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage)); + adapter->memory_events = NULL; + 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/device.c b/dlls/wined3d/device.c index 87db701d..85532dbd 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1204,10 +1204,10 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device
TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n", wine_dbgstr_longlong(driver_info->vram_bytes), - wine_dbgstr_longlong(device->adapter->vram_bytes_used), - wine_dbgstr_longlong(driver_info->vram_bytes - device->adapter->vram_bytes_used)); + wine_dbgstr_longlong(device->adapter->memory_usage[0].bytes_used), + wine_dbgstr_longlong(driver_info->vram_bytes - device->adapter->memory_usage[0].bytes_used));
- return min(UINT_MAX, driver_info->vram_bytes - device->adapter->vram_bytes_used); + return min(UINT_MAX, driver_info->vram_bytes - device->adapter->memory_usage[0].bytes_used); }
void CDECL wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx, diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 902cc444..fa991d36 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -146,16 +146,17 @@ static HRESULT wined3d_output_init(struct wined3d_output *output, const WCHAR *d /* Adjust the amount of used texture memory */ UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) { - adapter->vram_bytes_used += amount; + adapter->memory_usage[0].bytes_used += amount; TRACE("Adjusted used adapter memory by 0x%s to 0x%s.\n", wine_dbgstr_longlong(amount), - wine_dbgstr_longlong(adapter->vram_bytes_used)); - return adapter->vram_bytes_used; + wine_dbgstr_longlong(adapter->memory_usage[0].bytes_used)); + return adapter->memory_usage[0].bytes_used; }
void wined3d_adapter_cleanup(struct wined3d_adapter *adapter) { wined3d_output_cleanup(&adapter->output); + heap_free(adapter->memory_events); heap_free(adapter->formats); }
@@ -2778,7 +2779,9 @@ static struct wined3d_adapter *wined3d_adapter_no3d_create(unsigned int ordinal, return NULL;
wined3d_driver_info_init(&adapter->driver_info, &gpu_description, 0, 0); - adapter->vram_bytes_used = 0; + memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage)); + adapter->memory_events = NULL; + 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_private.h b/dlls/wined3d/wined3d_private.h index f6d25aa6..7c0a73a0 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2868,6 +2868,12 @@ struct wined3d_output D3DDDI_VIDEO_PRESENT_SOURCE_ID vidpn_source_id; };
+struct wined3d_adapter_memory_usage +{ + UINT64 bytes_used; + UINT64 bytes_reserved; +}; + /* The adapter structure */ struct wined3d_adapter { @@ -2879,7 +2885,9 @@ struct wined3d_adapter struct wined3d_d3d_info d3d_info; struct wined3d_driver_info driver_info; struct wined3d_output output; - UINT64 vram_bytes_used; + struct wined3d_adapter_memory_usage memory_usage[2]; + HANDLE *memory_events; + DWORD event_count; GUID driver_uuid; GUID device_uuid; LUID luid;
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- v3: Receive the change in memory usage instead of the total. --- dlls/wined3d/directx.c | 181 ++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 5 ++ include/wine/wined3d.h | 17 ++++ 3 files changed, 203 insertions(+)
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index fa991d36..3aecc024 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1378,6 +1378,187 @@ 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, INT64 bytes_added) +{ + struct wined3d_adapter *adapter; + DWORD i; + + wined3d_mutex_lock(); + + if (adapter_idx >= wined3d->adapter_count || non_local >= ARRAY_SIZE(adapter->memory_usage)) + { + ERR("Invalid call.\n"); + goto done; + } + + adapter = wined3d->adapters[adapter_idx]; + + adapter->memory_usage[non_local].bytes_used += bytes_added; + if (adapter->memory_usage[non_local].bytes_used > bytes_total) + WARN("Current type %u usage estimate 0x%s exceeds 0x%s available.\n", non_local, + wine_dbgstr_longlong(adapter->memory_usage[non_local].bytes_used), wine_dbgstr_longlong(bytes_total)); + + 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) +{ + struct wined3d_adapter *adapter; + HRESULT hr = E_INVALIDARG; + 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 ea04c85d..05e5570e 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 fac9eef5..02b52f3d 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, INT64 bytes_added); void __cdecl wined3d_unregister_windows(struct wined3d *wined3d);
HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
On Mon, 25 Nov 2019 at 17:43, Conor McCarthy cmccarthy@codeweavers.com wrote:
+void CDECL wined3d_update_adapter_memory_info(const struct wined3d *wined3d, unsigned int adapter_idx,
unsigned int non_local, UINT64 bytes_total, INT64 bytes_added)
Is it ever necessary to override the total amount of video memory? I think it would make most sense to add support for events and different memory types to adapter_adjust_memory(), and then implement this function on top of that one.
+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)
If we have wined3d_get_adapter_memory_info(), the memory information in struct wined3d_adapter_identifier becomes redundant and could be removed. I'd consider splitting this patch set in a slightly different way, essentially introducing the wined3d functions in the same dxgi patch that uses them. E.g., introducing wined3d_get_adapter_memory_info() would be part of the patch that modifies dxgi_adapter_QueryVideoMemoryInfo().
+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)
+{
<snip>
- 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))))
That looks like something that should use a free-list and wined3d_array_reserve().
November 27, 2019 6:01 AM, "Henri Verbeet" hverbeet@gmail.com wrote:
On Mon, 25 Nov 2019 at 17:43, Conor McCarthy cmccarthy@codeweavers.com wrote:
Is it ever necessary to override the total amount of video memory?
If the totals come from adapter_vk they will be correct, but adapter_gl won't have the non-local total. Should a zero total be overridden by a non-zero one? Also should totals be passed in a separate call? That could be done using a more generic messaging callback function.
If we have wined3d_get_adapter_memory_info(), the memory information in struct wined3d_adapter_identifier becomes redundant and could be removed.
Should vram_bytes and sysmem_bytes stay in wined3d_driver_info though?
Conor
On Mon, 2 Dec 2019 at 12:14, Conor McCarthy cmccarthy@codeweavers.com wrote:
November 27, 2019 6:01 AM, "Henri Verbeet" hverbeet@gmail.com wrote:
On Mon, 25 Nov 2019 at 17:43, Conor McCarthy cmccarthy@codeweavers.com wrote: Is it ever necessary to override the total amount of video memory?
If the totals come from adapter_vk they will be correct, but adapter_gl won't have the non-local total. Should a zero total be overridden by a non-zero one? Also should totals be passed in a separate call? That could be done using a more generic messaging callback function.
The GL backend won't be able to query the amount of non-local video memory (unless we add an extension, perhaps), but ultimately that's an implementation detail, and I'm not sure how much it really matters. Chances are we'll ultimately get that information from winex11.
If we have wined3d_get_adapter_memory_info(), the memory information in struct wined3d_adapter_identifier becomes redundant and could be removed.
Should vram_bytes and sysmem_bytes stay in wined3d_driver_info though?
Well, they need to be stored somewhere, but that doesn't necessarily need to be the wined3d_driver_info structure. If you think a separate structure for adapter memory info makes sense, that's fine.
November 27, 2019 6:01 AM, "Henri Verbeet" hverbeet@gmail.com wrote:
That looks like something that should use a free-list and wined3d_array_reserve().
I've modified it to use wined3d_array_reserve(), but I didn't think a free-list was necessary. There are unlikely to be many registered event handles -- in most cases only one. The patch favours simplicity over performance.
Conor
Used by Hitman 2.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/adapter.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-)
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index d2fc629c..d277dfd5 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -294,41 +294,33 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_QueryVideoMemoryInfo(IWineDXGIAdap UINT node_index, DXGI_MEMORY_SEGMENT_GROUP segment_group, DXGI_QUERY_VIDEO_MEMORY_INFO *info) { struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface); - struct wined3d_adapter_identifier adapter_id; + struct wined3d_adapter_memory_info memory_info; static unsigned int once; HRESULT hr;
TRACE("iface %p, node_index %u, segment_group %#x, info %p.\n", iface, node_index, segment_group, info);
+ if (segment_group > DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL) + { + WARN("Invalid memory segment group 0x%x.\n", segment_group); + return E_INVALIDARG; + } + if (!once++) - FIXME("Returning fake video memory info.\n"); + FIXME("Returning fake or estimated video memory info.\n");
if (node_index) FIXME("Ignoring node index %u.\n", node_index);
- adapter_id.driver_size = 0; - adapter_id.description_size = 0; - adapter_id.device_name_size = 0; - - if (FAILED(hr = wined3d_get_adapter_identifier(adapter->factory->wined3d, adapter->ordinal, 0, &adapter_id))) + if (FAILED(hr = wined3d_get_adapter_memory_info(adapter->factory->wined3d, adapter->ordinal, segment_group, &memory_info))) return hr;
- switch (segment_group) - { - case DXGI_MEMORY_SEGMENT_GROUP_LOCAL: - info->Budget = adapter_id.video_memory; - info->CurrentUsage = 0; - info->AvailableForReservation = adapter_id.video_memory / 2; - info->CurrentReservation = 0; - break; - case DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL: - memset(info, 0, sizeof(*info)); - break; - default: - WARN("Invalid memory segment group %#x.\n", segment_group); - return E_INVALIDARG; - } + /* Budget must leave a little extra space. In Windows this seems to always be about total/6.5 if total <= 8 Gb. */ + info->Budget = memory_info.total - memory_info.total / 7u; + info->CurrentUsage = memory_info.used; + info->AvailableForReservation = memory_info.total / 2u; + info->CurrentReservation = memory_info.reserved;
TRACE("Budget 0x%s, usage 0x%s, available for reservation 0x%s, reservation 0x%s.\n", wine_dbgstr_longlong(info->Budget), wine_dbgstr_longlong(info->CurrentUsage),
Used by Hitman 2. Reservations are recorded but nothing is actually reserved.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/adapter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index d277dfd5..5507790c 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -332,10 +332,12 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_QueryVideoMemoryInfo(IWineDXGIAdap static HRESULT STDMETHODCALLTYPE dxgi_adapter_SetVideoMemoryReservation(IWineDXGIAdapter *iface, UINT node_index, DXGI_MEMORY_SEGMENT_GROUP segment_group, UINT64 reservation) { - FIXME("iface %p, node_index %u, segment_group %#x, reservation 0x%s stub!\n", + struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface); + + FIXME("iface %p, node_index %u, segment_group %#x, reservation 0x%s partial stub!\n", iface, node_index, segment_group, wine_dbgstr_longlong(reservation));
- return S_OK; + return wined3d_set_adapter_reserved_memory(adapter->factory->wined3d, adapter->ordinal, segment_group, reservation); }
static HRESULT STDMETHODCALLTYPE dxgi_adapter_RegisterVideoMemoryBudgetChangeNotificationEvent(
Used by Hitman 2. Also implements the unregister function. Events will only be signalled by updates sent from vkd3d.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/adapter.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index 5507790c..31b2d5b4 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -343,15 +343,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)
On Mon, 25 Nov 2019 at 17:43, Conor McCarthy cmccarthy@codeweavers.com wrote:
Events will only be signalled by updates sent from vkd3d.
That seems like an unnecessary limitation; any particular reason?
For use by future patched vkd3d and Wine d3d12 modules.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- v3: Receive the change in memory usage instead of the total. --- dlls/dxgi/adapter.c | 12 ++++++++++++ include/wine/winedxgi.idl | 5 +++++ 2 files changed, 17 insertions(+)
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index 31b2d5b4..d579475b 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -396,6 +396,17 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_get_adapter_info(IWineDXGIAdapter return hr; }
+static void STDMETHODCALLTYPE dxgi_adapter_update_memory_usage(IWineDXGIAdapter *iface, + unsigned int non_local, UINT64 bytes_total, INT64 bytes_added) +{ + struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface); + + TRACE("iface %p, non-local %u, bytes total 0x%s, bytes added 0x%s.\n", iface, non_local, + wine_dbgstr_longlong(bytes_total), wine_dbgstr_longlong(bytes_added)); + + wined3d_update_adapter_memory_info(adapter->factory->wined3d, adapter->ordinal, non_local, bytes_total, bytes_added); +} + static const struct IWineDXGIAdapterVtbl dxgi_adapter_vtbl = { dxgi_adapter_QueryInterface, @@ -424,6 +435,7 @@ static const struct IWineDXGIAdapterVtbl dxgi_adapter_vtbl = dxgi_adapter_GetDesc3, /* IWineDXGIAdapter methods */ dxgi_adapter_get_adapter_info, + dxgi_adapter_update_memory_usage, };
struct dxgi_adapter *unsafe_impl_from_IDXGIAdapter(IDXGIAdapter *iface) diff --git a/include/wine/winedxgi.idl b/include/wine/winedxgi.idl index 070ac2fd..e76e1531 100644 --- a/include/wine/winedxgi.idl +++ b/include/wine/winedxgi.idl @@ -82,6 +82,11 @@ struct wine_dxgi_adapter_info interface IWineDXGIAdapter : IDXGIAdapter4 { HRESULT get_adapter_info([out] struct wine_dxgi_adapter_info *info); + void update_memory_usage( + [in] unsigned int non_local, + [in] UINT64 bytes_total, + [in] INT64 bytes_added + ); }
[
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/tests/dxgi.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 874c39b8..ef221b52 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -941,11 +941,12 @@ static void test_adapter_luid(void) static void test_query_video_memory_info(void) { DXGI_QUERY_VIDEO_MEMORY_INFO memory_info; + const UINT64 reservation = 0x100000; + HRESULT hr, non_local_hr; IDXGIAdapter3 *adapter3; IDXGIAdapter *adapter; IDXGIDevice *device; ULONG refcount; - HRESULT hr;
if (!(device = create_device(0))) { @@ -981,6 +982,23 @@ static void test_query_video_memory_info(void) hr = IDXGIAdapter3_QueryVideoMemoryInfo(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL + 1, &memory_info); ok(hr == E_INVALIDARG, "Failed to query video memory info, hr %#x.\n", hr);
+ hr = IDXGIAdapter3_SetVideoMemoryReservation(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, reservation); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = IDXGIAdapter3_SetVideoMemoryReservation(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, 0); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + non_local_hr = IDXGIAdapter3_SetVideoMemoryReservation(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, reservation); + ok(non_local_hr == S_OK || non_local_hr == E_INVALIDARG, "Got unexpected hr %#x.\n", non_local_hr); + + hr = IDXGIAdapter3_QueryVideoMemoryInfo(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &memory_info); + ok(hr == S_OK, "Failed to query video memory info, hr %#x.\n", hr); + ok(memory_info.CurrentReservation == reservation, "Got unexpected current reservation 0x%s.\n", + wine_dbgstr_longlong(memory_info.CurrentReservation)); + + hr = IDXGIAdapter3_QueryVideoMemoryInfo(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &memory_info); + ok(hr == S_OK || hr == E_INVALIDARG, "Failed to query video memory info, hr %#x.\n", hr); + ok(memory_info.CurrentReservation == reservation || non_local_hr == E_INVALIDARG, "Got unexpected current reservation 0x%s.\n", + wine_dbgstr_longlong(memory_info.CurrentReservation)); + IDXGIAdapter3_Release(adapter3);
done:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=60816
Your paranoid android.
=== w1064v1507 (64 bit report) ===
dxgi: dxgi.c:4927: Test failed: Got unexpected message 0x31f, hwnd 00000000000F0050, wparam 0x1, lparam 0.
On Mon, 25 Nov 2019 at 17:44, Conor McCarthy cmccarthy@codeweavers.com wrote:
- hr = IDXGIAdapter3_SetVideoMemoryReservation(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, reservation);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- hr = IDXGIAdapter3_SetVideoMemoryReservation(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, 0);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- non_local_hr = IDXGIAdapter3_SetVideoMemoryReservation(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, reservation);
- ok(non_local_hr == S_OK || non_local_hr == E_INVALIDARG, "Got unexpected hr %#x.\n", non_local_hr);
Does the E_INVALIDARG return correspond to some property of the adapter by any chance? Like, e.g. being an UMA adapter? Also, where reasonably possible, it makes sense to send patches at the start of the series with todo_wine. That means that tests don't depend on the implementation or fix going in first, and it's more clear what a particular patch fixes in terms of public API.
On Mon, 25 Nov 2019 at 17:43, Conor McCarthy cmccarthy@codeweavers.com wrote:
dlls/wined3d/adapter_gl.c | 4 +++- dlls/wined3d/adapter_vk.c | 4 +++- dlls/wined3d/device.c | 6 +++--- dlls/wined3d/directx.c | 11 +++++++---- dlls/wined3d/wined3d_private.h | 10 +++++++++- 5 files changed, 25 insertions(+), 10 deletions(-)
As it is, most of the things introduced in this patch are unused. With few exceptions, it would be best to introduce things when they're needed.
@@ -1204,10 +1204,10 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device
TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n", wine_dbgstr_longlong(driver_info->vram_bytes),
wine_dbgstr_longlong(device->adapter->vram_bytes_used),
wine_dbgstr_longlong(driver_info->vram_bytes - device->adapter->vram_bytes_used));
wine_dbgstr_longlong(device->adapter->memory_usage[0].bytes_used),
wine_dbgstr_longlong(driver_info->vram_bytes - device->adapter->memory_usage[0].bytes_used));
- return min(UINT_MAX, driver_info->vram_bytes - device->adapter->vram_bytes_used);
- return min(UINT_MAX, driver_info->vram_bytes - device->adapter->memory_usage[0].bytes_used);
}
It doesn't seem great to reference things by fixed indices like this. Could we have an enum?