From nobody Mon Apr 6 11:00:53 2026 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 349E03FADFD for ; Thu, 19 Mar 2026 20:25:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773951945; cv=none; b=HkSDsSTaNaD14UIEdmqCixYPbVKOgkXOswY6mal55skY12scQz4ZABlARNMRMu3Bx5NiRZV8ZSv+HWjCSfDKmD84ifd+0fEjQ4XU8UGK1omMvPRdE3XMy21BkpgFAB63vzLPLqiHxtFqQK7c4u5U+0FP0CbEZz8M7PL4poB/wW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773951945; c=relaxed/simple; bh=cTHMrhLFBJpZSrHBJN9rBbXEZ9RqxyfSw9KSRCI/12c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tHE2jyS4JbRII42FGn9DflybAxF/kIkWJ65/TPuuvm2cYmuBZR5d/AV9IXbdQaspz7XiXSZca34YSUnHsXn/VASjtiYCJuECkIiz/SS/bcttADubjxZX7qcJr05PTFYrqPnLjpe2SJQthUno6iMszl3MG1SqAyAbX+KxcQ/Zvsc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=eBhpYbMt; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eBhpYbMt" Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-43b4d734678so1373002f8f.1 for ; Thu, 19 Mar 2026 13:25:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773951940; x=1774556740; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ItlcFlAFNUK9iEL+O6oBAG3ZQTT/S5ep55yAMkx91hI=; b=eBhpYbMt77jPeDCqLa/DYL/PjikezLVRpAf8ERX6k1bbmw51OCPJka+lNXxkk4623U 1gem5Dm2fG5//4x5gNuq/E2Xpcw9+epflfHW4mY7vLuM7ah221yfU4lfv2qQd2rILqSe Bht5BU49yfZLGMvhczUdv6N7zNU8jOwBMxmxaz5TBfnvDNiXcg9GRA+oar0DnGVmbN+4 Jrz+1o4YrimhE5V0WJ0TF4qbYTC75tOhKHC8T1apMYRHIVSBwoyKgWJD0eS07U1Fbo8O /634Icoe58yap9kfgwl0G61n+n/xZ6w8+ZtNddOtD9/jifINsHSTRWJv5sSwKjH/Q+Qp +KdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773951940; x=1774556740; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ItlcFlAFNUK9iEL+O6oBAG3ZQTT/S5ep55yAMkx91hI=; b=GhNlddzkdh0rKQBhprrlKnd9jVYGdj4nf10ZgkX9UVOxwbteSVyWv5KT5dKEjP1/zz cVZ/+vPUS3WVwMwYS9EYxmyHD3m4Dfvxd+3G4LWzi71SDfUcpqpMWWrVXEdKq+9Vwlg3 xSu5108MERWREBNLecbRlL3Z1oImr0G81kJD88QWNfItNuX0MLIGFYZSxzyIyWN9+hg8 zjh17N+gDJz+mNciAxtYCQv/5DscG9TkJw1KQNpBP7rkaYaF6cBfl0yMwy45nIc2ZlG7 hblPnVwYSn9oNUxtm71Cc/JHHEOTEJegfUYtlsM4clPKvwMPiA1dhMdzId8sfxrw2PLf Fbfg== X-Gm-Message-State: AOJu0YxYBjVivAbfCqUSEedx0o3q9IVXnEXbrvgp/+p7ul8CQuQNYyKb jJuSHIQjsVtTWu5scup47m61zNxMvasHVVNtPTiyAykUSDVoGM5RUVnc X-Gm-Gg: ATEYQzy0mcgXDaT9fHbi9fXglCOrgLniT+lpQUCDzrGPjG4d3CDYp5uNIAW4ifWBNTy ecFj1ay5GOirxuZVvvS+XEYBBjyokfs8ApMZ7FkMTBzu0cndQf+SjDQ4dbjnSwcx9y2LP6Ia47x yVgPo2//dxKYdYOXbpTgMlVOyQCdB9/ew3XXvB9qAzVe0+Gz79W8+x2uZxv+lfdNKx05Ej8iL46 ga4rAtyiYIFWxBLRXFJaSc2TcVlN3gJ5cQl8Y/9FJgNl/HVWj50dWLw0uJQQcqDNqgdQubLkoO4 6ToT6AgbZSNbsxPg5PQ7qFpNJmse1sIfwAO3b0xN18TFucgZDLLZ4+DYL2hUWpsKnwmM+CJjFfz pto7fB7WLYF5AVxgus8bPWyfTzbBhYyO6IXmlpE82oviL1YOzHu0Cdz9qFsnT34L8aJvRZlevf4 BZBjQsBd8BR6ReJVfE0sloi34ynQF210oYV7t9HWrOWU3waTm3f35FEUfhqT8= X-Received: by 2002:a05:6000:26c3:b0:43b:45d1:f438 with SMTP id ffacd0b85a97d-43b64234722mr1193145f8f.3.1773951940150; Thu, 19 Mar 2026 13:25:40 -0700 (PDT) Received: from LQ5W56KC4T ([2001:8a0:672f:7800:e0e1:55cd:f0b:b1e5]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43b644ae16fsm1347544f8f.8.2026.03.19.13.25.39 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 19 Mar 2026 13:25:39 -0700 (PDT) From: Eric Curtin X-Google-Original-From: Eric Curtin To: linux-hyperv@vger.kernel.org Cc: linux-kernel@vger.kernel.org, iourit@linux.microsoft.com, wei.liu@kernel.org, decui@microsoft.com, haiyangz@microsoft.com Subject: [PATCH 23/55] drivers: hv: dxgkrnl: Ioctls to query statistics and clock calibration Date: Thu, 19 Mar 2026 20:24:37 +0000 Message-ID: <20260319202509.63802-24-eric.curtin@docker.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com> References: <20260319202509.63802-1-eric.curtin@docker.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Iouri Tarassov Implement ioctls to query statistics from the VGPU device (LX_DXQUERYSTATISTICS) and to query clock calibration (LX_DXQUERYCLOCKCALIBRATION). The LX_DXQUERYSTATISTICS ioctl is used to query various statistics from the compute device on the host. The LX_DXQUERYCLOCKCALIBRATION ioctl queries the compute device clock and is used for performance monitoring. Signed-off-by: Iouri Tarassov [kms: forward port to 6.6 from 6.1. No code changes made.] Signed-off-by: Kelsey Steele --- drivers/hv/dxgkrnl/dxgkrnl.h | 8 +++ drivers/hv/dxgkrnl/dxgvmbus.c | 77 +++++++++++++++++++++++ drivers/hv/dxgkrnl/dxgvmbus.h | 21 +++++++ drivers/hv/dxgkrnl/ioctl.c | 111 +++++++++++++++++++++++++++++++++- include/uapi/misc/d3dkmthk.h | 62 +++++++++++++++++++ 5 files changed, 277 insertions(+), 2 deletions(-) diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h index b454c7430f06..a55873bdd9a6 100644 --- a/drivers/hv/dxgkrnl/dxgkrnl.h +++ b/drivers/hv/dxgkrnl/dxgkrnl.h @@ -885,6 +885,11 @@ int dxgvmb_send_query_adapter_info(struct dxgprocess *= process, int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_submitcommandtohwqueue *a); +int dxgvmb_send_query_clock_calibration(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmt_queryclockcalibration *a, + struct d3dkmt_queryclockcalibration + *__user inargs); int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_flushheaptransitions *arg); @@ -929,6 +934,9 @@ int dxgvmb_send_get_stdalloc_data(struct dxgdevice *dev= ice, void *prive_alloc_data, u32 *res_priv_data_size, void *priv_res_data); +int dxgvmb_send_query_statistics(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmt_querystatistics *args); int dxgvmb_send_async_msg(struct dxgvmbuschannel *channel, void *command, u32 cmd_size); diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c index f7264b12a477..9a1864bb4e14 100644 --- a/drivers/hv/dxgkrnl/dxgvmbus.c +++ b/drivers/hv/dxgkrnl/dxgvmbus.c @@ -1829,6 +1829,48 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess= *process, return ret; } =20 +int dxgvmb_send_query_clock_calibration(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmt_queryclockcalibration + *args, + struct d3dkmt_queryclockcalibration + *__user inargs) +{ + struct dxgkvmb_command_queryclockcalibration *command; + struct dxgkvmb_command_queryclockcalibration_return result; + int ret; + struct dxgvmbusmsg msg =3D {.hdr =3D NULL}; + + ret =3D init_message(&msg, adapter, process, sizeof(*command)); + if (ret) + goto cleanup; + command =3D (void *)msg.msg; + + command_vgpu_to_host_init2(&command->hdr, + DXGK_VMBCOMMAND_QUERYCLOCKCALIBRATION, + process->host_handle); + command->args =3D *args; + + ret =3D dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size, + &result, sizeof(result)); + if (ret < 0) + goto cleanup; + ret =3D copy_to_user(&inargs->clock_data, &result.clock_data, + sizeof(result.clock_data)); + if (ret) { + pr_err("%s failed to copy clock data", __func__); + ret =3D -EINVAL; + goto cleanup; + } + ret =3D ntstatus2int(result.status); + +cleanup: + free_message(&msg, process); + if (ret) + DXG_TRACE("err: %d", ret); + return ret; +} + int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_flushheaptransitions *args) @@ -3242,3 +3284,38 @@ int dxgvmb_send_submit_command_hwqueue(struct dxgpro= cess *process, return ret; } =20 +int dxgvmb_send_query_statistics(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmt_querystatistics *args) +{ + struct dxgkvmb_command_querystatistics *command; + struct dxgkvmb_command_querystatistics_return *result; + int ret; + struct dxgvmbusmsgres msg =3D {.hdr =3D NULL}; + + ret =3D init_message_res(&msg, adapter, process, sizeof(*command), + sizeof(*result)); + if (ret) + goto cleanup; + command =3D msg.msg; + result =3D msg.res; + + command_vgpu_to_host_init2(&command->hdr, + DXGK_VMBCOMMAND_QUERYSTATISTICS, + process->host_handle); + command->args =3D *args; + + ret =3D dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size, + result, msg.res_size); + if (ret < 0) + goto cleanup; + + args->result =3D result->result; + ret =3D ntstatus2int(result->status); + +cleanup: + free_message((struct dxgvmbusmsg *)&msg, process); + if (ret) + DXG_TRACE("err: %d", ret); + return ret; +} diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h index a66e11097bb2..17768ed0e68d 100644 --- a/drivers/hv/dxgkrnl/dxgvmbus.h +++ b/drivers/hv/dxgkrnl/dxgvmbus.h @@ -372,6 +372,16 @@ struct dxgkvmb_command_flushheaptransitions { struct dxgkvmb_command_vgpu_to_host hdr; }; =20 +struct dxgkvmb_command_queryclockcalibration { + struct dxgkvmb_command_vgpu_to_host hdr; + struct d3dkmt_queryclockcalibration args; +}; + +struct dxgkvmb_command_queryclockcalibration_return { + struct ntstatus status; + struct dxgk_gpuclockdata clock_data; +}; + struct dxgkvmb_command_createallocation_allocinfo { u32 flags; u32 priv_drv_data_size; @@ -408,6 +418,17 @@ struct dxgkvmb_command_openresource_return { /* struct d3dkmthandle allocation[allocation_count]; */ }; =20 +struct dxgkvmb_command_querystatistics { + struct dxgkvmb_command_vgpu_to_host hdr; + struct d3dkmt_querystatistics args; +}; + +struct dxgkvmb_command_querystatistics_return { + struct ntstatus status; + u32 reserved; + struct d3dkmt_querystatistics_result result; +}; + struct dxgkvmb_command_getstandardallocprivdata { struct dxgkvmb_command_vgpu_to_host hdr; enum d3dkmdt_standardallocationtype alloc_type; diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c index ce4af610ada7..4babb21f38a9 100644 --- a/drivers/hv/dxgkrnl/ioctl.c +++ b/drivers/hv/dxgkrnl/ioctl.c @@ -149,6 +149,65 @@ static int dxgkio_open_adapter_from_luid(struct dxgpro= cess *process, return ret; } =20 +static int dxgkio_query_statistics(struct dxgprocess *process, + void __user *inargs) +{ + struct d3dkmt_querystatistics *args; + int ret; + struct dxgadapter *entry; + struct dxgadapter *adapter =3D NULL; + struct winluid tmp; + struct dxgglobal *dxgglobal =3D dxggbl(); + + args =3D vzalloc(sizeof(struct d3dkmt_querystatistics)); + if (args =3D=3D NULL) { + ret =3D -ENOMEM; + goto cleanup; + } + + ret =3D copy_from_user(args, inargs, sizeof(*args)); + if (ret) { + DXG_ERR("failed to copy input args"); + ret =3D -EINVAL; + goto cleanup; + } + + dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED); + list_for_each_entry(entry, &dxgglobal->adapter_list_head, + adapter_list_entry) { + if (dxgadapter_acquire_lock_shared(entry) =3D=3D 0) { + if (*(u64 *) &entry->luid =3D=3D + *(u64 *) &args->adapter_luid) { + adapter =3D entry; + break; + } + dxgadapter_release_lock_shared(entry); + } + } + dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED); + if (adapter) { + tmp =3D args->adapter_luid; + args->adapter_luid =3D adapter->host_adapter_luid; + ret =3D dxgvmb_send_query_statistics(process, adapter, args); + if (ret >=3D 0) { + args->adapter_luid =3D tmp; + ret =3D copy_to_user(inargs, args, sizeof(*args)); + if (ret) { + DXG_ERR("failed to copy args"); + ret =3D -EINVAL; + } + } + dxgadapter_release_lock_shared(adapter); + } + +cleanup: + if (args) + vfree(args); + + DXG_TRACE("ioctl:%s %d", errorstr(ret), ret); + return ret; +} + static int dxgkp_enum_adapters(struct dxgprocess *process, union d3dkmt_enumadapters_filter filter, @@ -3536,6 +3595,54 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *= process, void *__user inargs return ret; } =20 +static int +dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user in= args) +{ + struct d3dkmt_queryclockcalibration args; + int ret; + struct dxgadapter *adapter =3D NULL; + bool adapter_locked =3D false; + + ret =3D copy_from_user(&args, inargs, sizeof(args)); + if (ret) { + DXG_ERR("failed to copy input args"); + ret =3D -EINVAL; + goto cleanup; + } + + adapter =3D dxgprocess_adapter_by_handle(process, args.adapter); + if (adapter =3D=3D NULL) { + ret =3D -EINVAL; + goto cleanup; + } + + ret =3D dxgadapter_acquire_lock_shared(adapter); + if (ret < 0) { + adapter =3D NULL; + goto cleanup; + } + adapter_locked =3D true; + + args.adapter =3D adapter->host_handle; + ret =3D dxgvmb_send_query_clock_calibration(process, adapter, + &args, inargs); + if (ret < 0) + goto cleanup; + ret =3D copy_to_user(inargs, &args, sizeof(args)); + if (ret) { + DXG_ERR("failed to copy output args"); + ret =3D -EINVAL; + } + +cleanup: + + if (adapter_locked) + dxgadapter_release_lock_shared(adapter); + if (adapter) + kref_put(&adapter->adapter_kref, dxgadapter_release); + return ret; +} + static int dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user ina= rgs) { @@ -4470,14 +4577,14 @@ static struct ioctl_desc ioctls[] =3D { /* 0x3b */ {dxgkio_wait_sync_object_gpu, LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU}, /* 0x3c */ {dxgkio_get_allocation_priority, LX_DXGETALLOCATIONPRIORITY}, -/* 0x3d */ {}, +/* 0x3d */ {dxgkio_query_clock_calibration, LX_DXQUERYCLOCKCALIBRATION}, /* 0x3e */ {dxgkio_enum_adapters3, LX_DXENUMADAPTERS3}, /* 0x3f */ {dxgkio_share_objects, LX_DXSHAREOBJECTS}, /* 0x40 */ {dxgkio_open_sync_object_nt, LX_DXOPENSYNCOBJECTFROMNTHANDLE2}, /* 0x41 */ {dxgkio_query_resource_info_nt, LX_DXQUERYRESOURCEINFOFROMNTHANDLE}, /* 0x42 */ {dxgkio_open_resource_nt, LX_DXOPENRESOURCEFROMNTHANDLE}, -/* 0x43 */ {}, +/* 0x43 */ {dxgkio_query_statistics, LX_DXQUERYSTATISTICS}, /* 0x44 */ {dxgkio_share_object_with_host, LX_DXSHAREOBJECTWITHHOST}, /* 0x45 */ {}, }; diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h index ce5a638a886d..ea18242ceb83 100644 --- a/include/uapi/misc/d3dkmthk.h +++ b/include/uapi/misc/d3dkmthk.h @@ -996,6 +996,34 @@ struct d3dkmt_queryadapterinfo { __u32 private_data_size; }; =20 +#pragma pack(push, 1) + +struct dxgk_gpuclockdata_flags { + union { + struct { + __u32 context_management_processor:1; + __u32 reserved:31; + }; + __u32 value; + }; +}; + +struct dxgk_gpuclockdata { + __u64 gpu_frequency; + __u64 gpu_clock_counter; + __u64 cpu_clock_counter; + struct dxgk_gpuclockdata_flags flags; +} __packed; + +struct d3dkmt_queryclockcalibration { + struct d3dkmthandle adapter; + __u32 node_ordinal; + __u32 physical_adapter_index; + struct dxgk_gpuclockdata clock_data; +}; + +#pragma pack(pop) + struct d3dkmt_flushheaptransitions { struct d3dkmthandle adapter; }; @@ -1238,6 +1266,36 @@ struct d3dkmt_enumadapters3 { #endif }; =20 +enum d3dkmt_querystatistics_type { + _D3DKMT_QUERYSTATISTICS_ADAPTER =3D 0, + _D3DKMT_QUERYSTATISTICS_PROCESS =3D 1, + _D3DKMT_QUERYSTATISTICS_PROCESS_ADAPTER =3D 2, + _D3DKMT_QUERYSTATISTICS_SEGMENT =3D 3, + _D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT =3D 4, + _D3DKMT_QUERYSTATISTICS_NODE =3D 5, + _D3DKMT_QUERYSTATISTICS_PROCESS_NODE =3D 6, + _D3DKMT_QUERYSTATISTICS_VIDPNSOURCE =3D 7, + _D3DKMT_QUERYSTATISTICS_PROCESS_VIDPNSOURCE =3D 8, + _D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_GROUP =3D 9, + _D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER =3D 10, +}; + +struct d3dkmt_querystatistics_result { + char size[0x308]; +}; + +struct d3dkmt_querystatistics { + union { + struct { + enum d3dkmt_querystatistics_type type; + struct winluid adapter_luid; + __u64 process; + struct d3dkmt_querystatistics_result result; + }; + char size[0x328]; + }; +}; + struct d3dkmt_shareobjectwithhost { struct d3dkmthandle device_handle; struct d3dkmthandle object_handle; @@ -1328,6 +1386,8 @@ struct d3dkmt_shareobjectwithhost { _IOWR(0x47, 0x3b, struct d3dkmt_waitforsynchronizationobjectfromgpu) #define LX_DXGETALLOCATIONPRIORITY \ _IOWR(0x47, 0x3c, struct d3dkmt_getallocationpriority) +#define LX_DXQUERYCLOCKCALIBRATION \ + _IOWR(0x47, 0x3d, struct d3dkmt_queryclockcalibration) #define LX_DXENUMADAPTERS3 \ _IOWR(0x47, 0x3e, struct d3dkmt_enumadapters3) #define LX_DXSHAREOBJECTS \ @@ -1338,6 +1398,8 @@ struct d3dkmt_shareobjectwithhost { _IOWR(0x47, 0x41, struct d3dkmt_queryresourceinfofromnthandle) #define LX_DXOPENRESOURCEFROMNTHANDLE \ _IOWR(0x47, 0x42, struct d3dkmt_openresourcefromnthandle) +#define LX_DXQUERYSTATISTICS \ + _IOWR(0x47, 0x43, struct d3dkmt_querystatistics) #define LX_DXSHAREOBJECTWITHHOST \ _IOWR(0x47, 0x44, struct d3dkmt_shareobjectwithhost)