Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/tests/dxgi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 874c39b8..1b132f92 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -941,7 +941,9 @@ 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; IDXGIAdapter3 *adapter3; + DXGI_ADAPTER_DESC desc; IDXGIAdapter *adapter; IDXGIDevice *device; ULONG refcount; @@ -981,6 +983,29 @@ 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 = IDXGIAdapter_GetDesc(adapter, &desc); + ok(SUCCEEDED(hr), "GetDesc failed, 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); + hr = IDXGIAdapter3_SetVideoMemoryReservation(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, reservation); + todo_wine_if(!desc.DedicatedVideoMemory) + ok(hr == (desc.DedicatedVideoMemory ? S_OK : E_INVALIDARG), "Got unexpected hr %#x.\n", 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); + todo_wine + 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, "Failed to query video memory info, hr %#x.\n", hr); + todo_wine_if(desc.DedicatedVideoMemory) + ok(memory_info.CurrentReservation == reservation || !desc.DedicatedVideoMemory, "Got unexpected current reservation 0x%s.\n", + wine_dbgstr_longlong(memory_info.CurrentReservation)); + IDXGIAdapter3_Release(adapter3);
done:
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/ddraw/ddraw.c | 7 ++-- dlls/dxgi/adapter.c | 53 ++++++++++++++++------------- dlls/wined3d/adapter_gl.c | 2 +- dlls/wined3d/adapter_vk.c | 2 +- dlls/wined3d/device.c | 6 ++-- dlls/wined3d/directx.c | 61 +++++++++++++++++++++++++++++----- dlls/wined3d/resource.c | 5 +-- dlls/wined3d/texture.c | 2 +- dlls/wined3d/wined3d.spec | 1 + dlls/wined3d/wined3d_private.h | 11 ++++-- include/wine/wined3d.h | 18 ++++++++-- 11 files changed, 121 insertions(+), 47 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index d744df8c..bbb71cce 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1926,10 +1926,11 @@ static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *c
if (total) { - struct wined3d_adapter_identifier desc = {0}; + struct wined3d_adapter_memory_info memory_info = {0};
- hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0, &desc); - total_vidmem = min(UINT_MAX, desc.video_memory); + hr = wined3d_get_adapter_memory_info(ddraw->wined3d, WINED3DADAPTER_DEFAULT, + WINED3D_ADAPTER_MEMORY_LOCAL, &memory_info); + total_vidmem = min(UINT_MAX, memory_info.total); *total = framebuffer_size > total_vidmem ? 0 : total_vidmem - framebuffer_size; TRACE("Total video memory %#x.\n", *total); } diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index d2fc629c..b0825cc5 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -149,7 +149,9 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_EnumOutputs(IWineDXGIAdapter *ifac
static HRESULT dxgi_adapter_get_desc(struct dxgi_adapter *adapter, DXGI_ADAPTER_DESC3 *desc) { + struct wined3d_adapter_memory_info mem_non_local; char description[ARRAY_SIZE(desc->Description)]; + struct wined3d_adapter_memory_info mem_local; struct wined3d_adapter_identifier adapter_id; HRESULT hr;
@@ -160,6 +162,11 @@ static HRESULT dxgi_adapter_get_desc(struct dxgi_adapter *adapter, DXGI_ADAPTER_
if (FAILED(hr = wined3d_get_adapter_identifier(adapter->factory->wined3d, adapter->ordinal, 0, &adapter_id))) return hr; + if (FAILED(hr = wined3d_get_adapter_memory_info(adapter->factory->wined3d, + adapter->ordinal, WINED3D_ADAPTER_MEMORY_LOCAL, &mem_local)) + || FAILED(hr = wined3d_get_adapter_memory_info(adapter->factory->wined3d, + adapter->ordinal, WINED3D_ADAPTER_MEMORY_NON_LOCAL, &mem_non_local))) + return hr;
if (!MultiByteToWideChar(CP_ACP, 0, description, -1, desc->Description, ARRAY_SIZE(description))) { @@ -172,9 +179,10 @@ static HRESULT dxgi_adapter_get_desc(struct dxgi_adapter *adapter, DXGI_ADAPTER_ desc->DeviceId = adapter_id.device_id; desc->SubSysId = adapter_id.subsystem_id; desc->Revision = adapter_id.revision; - desc->DedicatedVideoMemory = adapter_id.video_memory; + /* On UMA adapters DXGI defines all memory as local, and the non-local total is 0. */ + desc->DedicatedVideoMemory = !mem_non_local.total ? 0 : mem_local.total; desc->DedicatedSystemMemory = 0; /* FIXME */ - desc->SharedSystemMemory = adapter_id.shared_system_memory; + desc->SharedSystemMemory = !mem_non_local.total ? mem_local.total : mem_non_local.total; desc->AdapterLuid = adapter_id.adapter_luid; desc->Flags = 0; desc->GraphicsPreemptionGranularity = 0; /* FIXME */ @@ -290,45 +298,42 @@ static void STDMETHODCALLTYPE dxgi_adapter_UnregisterHardwareContentProtectionTe FIXME("iface %p, cookie %#x stub!\n", iface, cookie); }
+/* Required for query and reservation functions. */ +C_ASSERT(DXGI_MEMORY_SEGMENT_GROUP_LOCAL == (int)WINED3D_ADAPTER_MEMORY_LOCAL + && DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL == (int)WINED3D_ADAPTER_MEMORY_NON_LOCAL); + static HRESULT STDMETHODCALLTYPE dxgi_adapter_QueryVideoMemoryInfo(IWineDXGIAdapter *iface, 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), diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 7018c6da..0adcc165 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -3881,7 +3881,7 @@ 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)); 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..f00de70c 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1180,7 +1180,7 @@ 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)); 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 98559e4f..0f6ee51b 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1198,10 +1198,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[WINED3D_ADAPTER_MEMORY_LOCAL].bytes_used), + wine_dbgstr_longlong(driver_info->vram_bytes - device->adapter->memory_usage[WINED3D_ADAPTER_MEMORY_LOCAL].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[WINED3D_ADAPTER_MEMORY_LOCAL].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..4a8baed3 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -143,14 +143,33 @@ static HRESULT wined3d_output_init(struct wined3d_output *output, const WCHAR *d return WINED3D_OK; }
+static uint64_t adapter_get_total_memory(const struct wined3d_adapter *adapter, enum wined3d_adapter_memory_type type) +{ + /* vram_bytes may be zero for a UMA adapter. DXGI defines all memory as local for UMA adapters. */ + if (!adapter->driver_info.vram_bytes) + return type == WINED3D_ADAPTER_MEMORY_NON_LOCAL ? 0 : adapter->driver_info.sysmem_bytes; + else + return type == WINED3D_ADAPTER_MEMORY_NON_LOCAL ? adapter->driver_info.sysmem_bytes : adapter->driver_info.vram_bytes; +} + /* Adjust the amount of used texture memory */ -UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) +UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, enum wined3d_adapter_memory_type type, + INT64 amount) { - adapter->vram_bytes_used += amount; - TRACE("Adjusted used adapter memory by 0x%s to 0x%s.\n", + uint64_t bytes_total; + + adapter->memory_usage[type].bytes_used += amount; + TRACE("Adjusted used adapter memory type %u by 0x%s to 0x%s.\n", type, wine_dbgstr_longlong(amount), - wine_dbgstr_longlong(adapter->vram_bytes_used)); - return adapter->vram_bytes_used; + wine_dbgstr_longlong(adapter->memory_usage[type].bytes_used)); + + bytes_total = adapter_get_total_memory(adapter, type); + if (bytes_total && adapter->memory_usage[type].bytes_used > bytes_total) + WARN("Current type %u usage estimate 0x%s exceeds 0x%s available.\n", type, + wine_dbgstr_longlong(adapter->memory_usage[type].bytes_used), + wine_dbgstr_longlong(bytes_total)); + + return adapter->memory_usage[type].bytes_used; }
void wined3d_adapter_cleanup(struct wined3d_adapter *adapter) @@ -1365,8 +1384,6 @@ HRESULT CDECL wined3d_get_adapter_identifier(const struct wined3d *wined3d, identifier->device_uuid = adapter->device_uuid; identifier->whql_level = (flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1; identifier->adapter_luid = adapter->luid; - identifier->video_memory = min(~(SIZE_T)0, adapter->driver_info.vram_bytes); - identifier->shared_system_memory = min(~(SIZE_T)0, adapter->driver_info.sysmem_bytes);
wined3d_mutex_unlock();
@@ -1377,6 +1394,34 @@ fail: return WINED3DERR_INVALIDCALL; }
+HRESULT CDECL wined3d_get_adapter_memory_info(const struct wined3d *wined3d, unsigned int adapter_idx, + enum wined3d_adapter_memory_type type, struct wined3d_adapter_memory_info *info) +{ + const struct wined3d_adapter *adapter; + + TRACE("wined3d %p, adapter_idx %u, type %u, info %p.\n", + wined3d, adapter_idx, type, info); + + wined3d_mutex_lock(); + + if (adapter_idx >= wined3d->adapter_count || type >= ARRAY_SIZE(adapter->memory_usage)) + goto fail; + + adapter = wined3d->adapters[adapter_idx]; + + info->total = adapter_get_total_memory(adapter, type); + info->used = adapter->memory_usage[type].bytes_used; + info->reserved = adapter->memory_usage[type].bytes_reserved; + + 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) { @@ -2778,7 +2823,7 @@ 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)); 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/resource.c b/dlls/wined3d/resource.c index bba940f4..4feecedc 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -227,7 +227,8 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * ERR("Out of adapter memory.\n"); return WINED3DERR_OUTOFVIDEOMEMORY; } - adapter_adjust_memory(device->adapter, size); + /* FIXME: non-local memory can be accounted for too if it proves necessary. */ + adapter_adjust_memory(device->adapter, WINED3D_ADAPTER_MEMORY_LOCAL, size); }
device_resource_add(device, resource); @@ -256,7 +257,7 @@ void resource_cleanup(struct wined3d_resource *resource) if (!(resource->access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING) { TRACE("Decrementing device memory pool by %u.\n", resource->size); - adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size); + adapter_adjust_memory(resource->device->adapter, WINED3D_ADAPTER_MEMORY_LOCAL, (INT64)0 - resource->size); }
device_resource_released(resource->device, resource); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index d4d90c28..2f6ebf17 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -1596,7 +1596,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT texture->resource.width = width; texture->resource.height = height; if (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING) - adapter_adjust_memory(device->adapter, (INT64)texture->slice_pitch - texture->resource.size); + adapter_adjust_memory(device->adapter, WINED3D_ADAPTER_MEMORY_LOCAL, (INT64)texture->slice_pitch - texture->resource.size); texture->resource.size = texture->slice_pitch; sub_resource->size = texture->slice_pitch; sub_resource->locations = WINED3D_LOCATION_DISCARDED; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index fed5ce1b..e618b6fd 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -14,6 +14,7 @@ @ 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) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3ae7dab8..3b4145fd 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,7 @@ 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[WINED3D_ADAPTER_MEMORY_COUNT]; GUID driver_uuid; GUID device_uuid; LUID luid; @@ -2956,7 +2962,8 @@ BOOL wined3d_adapter_gl_init_format_info(struct wined3d_adapter *adapter, BOOL wined3d_adapter_no3d_init_format_info(struct wined3d_adapter *adapter) DECLSPEC_HIDDEN; BOOL wined3d_adapter_vk_init_format_info(struct wined3d_adapter_vk *adapter_vk, const struct wined3d_vk_info *vk_info) DECLSPEC_HIDDEN; -UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) DECLSPEC_HIDDEN; +UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, enum wined3d_adapter_memory_type type, + INT64 amount) DECLSPEC_HIDDEN;
BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx *ctx) DECLSPEC_HIDDEN;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index eba14e9a..7e5ca169 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1738,8 +1738,20 @@ struct wined3d_adapter_identifier GUID device_uuid; DWORD whql_level; LUID adapter_luid; - SIZE_T video_memory; - SIZE_T shared_system_memory; +}; + +enum wined3d_adapter_memory_type +{ + WINED3D_ADAPTER_MEMORY_LOCAL = 0, + WINED3D_ADAPTER_MEMORY_NON_LOCAL = 1, + WINED3D_ADAPTER_MEMORY_COUNT = 2, +}; + +struct wined3d_adapter_memory_info +{ + UINT64 total; + UINT64 used; + UINT64 reserved; };
struct wined3d_swapchain_desc @@ -2206,6 +2218,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, + enum wined3d_adapter_memory_type type, 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);
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 ++++-- dlls/dxgi/tests/dxgi.c | 2 -- dlls/wined3d/directx.c | 36 ++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 2 ++ 5 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index b0825cc5..3db10e8a 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -345,10 +345,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( diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 1b132f92..e788a25c 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -996,13 +996,11 @@ static void test_query_video_memory_info(void)
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); - todo_wine 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, "Failed to query video memory info, hr %#x.\n", hr); - todo_wine_if(desc.DedicatedVideoMemory) ok(memory_info.CurrentReservation == reservation || !desc.DedicatedVideoMemory, "Got unexpected current reservation 0x%s.\n", wine_dbgstr_longlong(memory_info.CurrentReservation));
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 4a8baed3..0d2bdc8e 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1422,6 +1422,42 @@ fail: return E_INVALIDARG; }
+HRESULT CDECL wined3d_set_adapter_reserved_memory(const struct wined3d *wined3d, unsigned int adapter_idx, + enum wined3d_adapter_memory_type type, UINT64 reservation) +{ + struct wined3d_adapter_memory_info memory_info; + struct wined3d_adapter *adapter; + HRESULT hr; + + TRACE("wined3d %p, adapter_idx %u, type %u, reservation 0x%s.\n", + wined3d, adapter_idx, type, wine_dbgstr_longlong(reservation)); + + if (FAILED(hr = wined3d_get_adapter_memory_info(wined3d, adapter_idx, type, &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 || type >= 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[type].bytes_reserved = reservation; + + 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 e618b6fd..1ff73adf 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -24,6 +24,7 @@ @ 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_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 7e5ca169..5ca1673d 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2235,6 +2235,8 @@ 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, + enum wined3d_adapter_memory_type type, UINT64 reservation); void __cdecl wined3d_unregister_windows(struct wined3d *wined3d);
HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
Used by Hitman 2. Also implements the unregister function.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- 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,
For use by future patched vkd3d and Wine d3d12 modules.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/adapter.c | 13 +++++++++++++ dlls/wined3d/directx.c | 21 +++++++++++++++++++++ dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 2 ++ include/wine/winedxgi.idl | 4 ++++ 5 files changed, 41 insertions(+)
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c index d7afad62..f6410f44 100644 --- a/dlls/dxgi/adapter.c +++ b/dlls/dxgi/adapter.c @@ -409,6 +409,18 @@ 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, INT64 bytes_added) +{ + struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface); + + TRACE("iface %p, non-local %u, bytes added 0x%s.\n", iface, non_local, + wine_dbgstr_longlong(bytes_added)); + + wined3d_update_adapter_memory_usage(adapter->factory->wined3d, adapter->ordinal, + non_local ? WINED3D_ADAPTER_MEMORY_NON_LOCAL : WINED3D_ADAPTER_MEMORY_LOCAL, bytes_added); +} + static const struct IWineDXGIAdapterVtbl dxgi_adapter_vtbl = { dxgi_adapter_QueryInterface, @@ -437,6 +449,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/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 4625009c..7011f737 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1400,6 +1400,27 @@ fail: return WINED3DERR_INVALIDCALL; }
+void CDECL wined3d_update_adapter_memory_usage(const struct wined3d *wined3d, unsigned int adapter_idx, + enum wined3d_adapter_memory_type type, INT64 bytes_added) +{ + struct wined3d_adapter *adapter; + + wined3d_mutex_lock(); + + if (adapter_idx >= wined3d->adapter_count || type >= ARRAY_SIZE(adapter->memory_usage)) + { + ERR("Invalid call.\n"); + goto done; + } + + adapter = wined3d->adapters[adapter_idx]; + + adapter_adjust_memory(adapter, type, bytes_added); + +done: + wined3d_mutex_unlock(); +} + HRESULT CDECL wined3d_get_adapter_memory_info(const struct wined3d *wined3d, unsigned int adapter_idx, enum wined3d_adapter_memory_type type, struct wined3d_adapter_memory_info *info) { diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 17cfed9c..07a59ec3 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -27,6 +27,7 @@ @ 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_usage(ptr long long 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 30c97492..e584d763 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2241,6 +2241,8 @@ HRESULT __cdecl wined3d_set_adapter_reserved_memory(const struct wined3d *wined3 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_update_adapter_memory_usage(const struct wined3d *wined3d, unsigned int adapter_idx, + enum wined3d_adapter_memory_type type, 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, diff --git a/include/wine/winedxgi.idl b/include/wine/winedxgi.idl index 070ac2fd..fbc224a9 100644 --- a/include/wine/winedxgi.idl +++ b/include/wine/winedxgi.idl @@ -82,6 +82,10 @@ 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] INT64 bytes_added + ); }
[