dzn: Support device factories in addition to global device creation
authorJesse Natalie <jenatali@microsoft.com>
Mon, 29 Aug 2022 19:57:41 +0000 (12:57 -0700)
committerMarge Bot <emma+marge@anholt.net>
Thu, 20 Oct 2022 14:40:49 +0000 (14:40 +0000)
Acked-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18306>

src/microsoft/vulkan/dzn_device.c
src/microsoft/vulkan/dzn_private.h
src/microsoft/vulkan/dzn_util.c

index edca4fb..6790e1d 100644 (file)
@@ -168,12 +168,33 @@ dzn_instance_destroy(struct dzn_instance *instance, const VkAllocationCallbacks
       dzn_physical_device_destroy(pdev);
    }
 
+   if (instance->factory)
+      ID3D12DeviceFactory_Release(instance->factory);
+
    util_dl_close(instance->d3d12_mod);
 
    vk_instance_finish(&instance->vk);
    vk_free2(vk_default_allocator(), alloc, instance);
 }
 
+static ID3D12DeviceFactory *
+try_create_device_factory(struct util_dl_library *d3d12_mod)
+{
+   /* A device factory allows us to isolate things like debug layer enablement from other callers,
+   * and can potentially even refer to a different D3D12 redist implementation from others.
+   */
+   ID3D12DeviceFactory *factory = NULL;
+
+   PFN_D3D12_GET_INTERFACE D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetInterface");
+   if (!D3D12GetInterface) {
+      mesa_loge("Failed to retrieve D3D12GetInterface\n");
+      return NULL;
+   }
+
+   (void)D3D12GetInterface(&CLSID_D3D12DeviceFactory, &IID_ID3D12DeviceFactory, (void **)&factory);
+   return factory;
+}
+
 static VkResult
 dzn_instance_create(const VkInstanceCreateInfo *pCreateInfo,
                     const VkAllocationCallbacks *pAllocator,
@@ -246,10 +267,12 @@ dzn_instance_create(const VkInstanceCreateInfo *pCreateInfo,
       return vk_error(NULL, VK_ERROR_INITIALIZATION_FAILED);
    }
 
+   instance->factory = try_create_device_factory(instance->d3d12_mod);
+
    if (instance->debug_flags & DZN_DEBUG_D3D12)
-      d3d12_enable_debug_layer(instance->d3d12_mod);
+      d3d12_enable_debug_layer(instance->d3d12_mod, instance->factory);
    if (instance->debug_flags & DZN_DEBUG_GBV)
-      d3d12_enable_gpu_validation(instance->d3d12_mod);
+      d3d12_enable_gpu_validation(instance->d3d12_mod, instance->factory);
 
    instance->sync_binary_type = vk_sync_binary_get_type(&dzn_sync_type);
 
@@ -597,7 +620,10 @@ dzn_physical_device_get_d3d12_dev(struct dzn_physical_device *pdev)
 
    mtx_lock(&pdev->dev_lock);
    if (!pdev->dev) {
-      pdev->dev = d3d12_create_device(instance->d3d12_mod, pdev->adapter, !instance->dxil_validator);
+      pdev->dev = d3d12_create_device(instance->d3d12_mod,
+                                      pdev->adapter,
+                                      instance->factory,
+                                      !instance->dxil_validator);
 
       dzn_physical_device_cache_caps(pdev);
       dzn_physical_device_init_memory(pdev);
index fd49531..ca780f1 100644 (file)
@@ -231,13 +231,13 @@ PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE
 d3d12_get_serialize_root_sig(struct util_dl_library *d3d12_mod);
 
 void
-d3d12_enable_debug_layer(struct util_dl_library *d3d12_mod);
+d3d12_enable_debug_layer(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory);
 
 void
-d3d12_enable_gpu_validation(struct util_dl_library *d3d12_mod);
+d3d12_enable_gpu_validation(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory);
 
 ID3D12Device2 *
-d3d12_create_device(struct util_dl_library *d3d12_mod, IUnknown *adapter, bool experimental_features);
+d3d12_create_device(struct util_dl_library *d3d12_mod, IUnknown *adapter, ID3D12DeviceFactory *factory, bool experimental_features);
 
 struct dzn_queue {
    struct vk_queue vk;
@@ -1048,6 +1048,7 @@ struct dzn_instance {
 
    struct dxil_validator *dxil_validator;
    struct util_dl_library *d3d12_mod;
+   ID3D12DeviceFactory *factory;
    struct {
       PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE serialize_root_sig;
    } d3d12;
index 0dba79b..19a938d 100644 (file)
@@ -297,30 +297,37 @@ dzn_translate_rect(D3D12_RECT *out,
 }
 
 static ID3D12Debug *
-get_debug_interface(struct util_dl_library *d3d12_mod)
+get_debug_interface(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
 {
    typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);
    PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;
 
-   D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface");
-   if (!D3D12GetDebugInterface) {
-      mesa_loge("failed to load D3D12GetDebugInterface from D3D12.DLL\n");
-      return NULL;
-   }
-
    ID3D12Debug *debug;
-   if (FAILED(D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug))) {
-      mesa_loge("D3D12GetDebugInterface failed\n");
-      return NULL;
+   if (factory) {
+      if (FAILED(ID3D12DeviceFactory_GetConfigurationInterface(factory, &CLSID_D3D12Debug, &IID_ID3D12Debug, (void **)&debug))) {
+         mesa_loge("Failed to retrieve ID3D12Debug from device factory\n");
+         return NULL;
+      }
+   } else {
+      D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface");
+      if (!D3D12GetDebugInterface) {
+         mesa_loge("failed to load D3D12GetDebugInterface from D3D12.DLL\n");
+         return NULL;
+      }
+
+      if (FAILED(D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug))) {
+         mesa_loge("D3D12GetDebugInterface failed\n");
+         return NULL;
+      }
    }
 
    return debug;
 }
 
 void
-d3d12_enable_debug_layer(struct util_dl_library *d3d12_mod)
+d3d12_enable_debug_layer(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
 {
-   ID3D12Debug *debug = get_debug_interface(d3d12_mod);
+   ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
    if (debug) {
       ID3D12Debug_EnableDebugLayer(debug);
       ID3D12Debug_Release(debug);
@@ -328,9 +335,9 @@ d3d12_enable_debug_layer(struct util_dl_library *d3d12_mod)
 }
 
 void
-d3d12_enable_gpu_validation(struct util_dl_library *d3d12_mod)
+d3d12_enable_gpu_validation(struct util_dl_library *d3d12_mod, ID3D12DeviceFactory *factory)
 {
-   ID3D12Debug *debug = get_debug_interface(d3d12_mod);
+   ID3D12Debug *debug = get_debug_interface(d3d12_mod, factory);
    if (debug) {
       ID3D12Debug3 *debug3;
       if (SUCCEEDED(ID3D12Debug_QueryInterface(debug,
@@ -344,38 +351,54 @@ d3d12_enable_gpu_validation(struct util_dl_library *d3d12_mod)
 }
 
 ID3D12Device2 *
-d3d12_create_device(struct util_dl_library *d3d12_mod, IUnknown *adapter, bool experimental_features)
+d3d12_create_device(struct util_dl_library *d3d12_mod, IUnknown *adapter, ID3D12DeviceFactory *factory, bool experimental_features)
 {
-   typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **);
-   PFN_D3D12CREATEDEVICE D3D12CreateDevice;
-
 #ifdef _WIN32
    if (experimental_features)
 #endif
    {
-      typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID *, void *, UINT *);
-      PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures =
-         (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
-      if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
-         mesa_loge("failed to enable experimental shader models\n");
-         return NULL;
+      if (factory) {
+         if (FAILED(ID3D12DeviceFactory_EnableExperimentalFeatures(factory, 1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
+            mesa_loge("failed to enable experimental shader models\n");
+            return NULL;
+         }
+      } else {
+         typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID *, void *, UINT *);
+         PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures =
+            (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
+         if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {
+            mesa_loge("failed to enable experimental shader models\n");
+            return NULL;
+         }
       }
    }
 
-   D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
-   if (!D3D12CreateDevice) {
-      mesa_loge("failed to load D3D12CreateDevice from D3D12\n");
-      return NULL;
-   }
-
    ID3D12Device2 *dev;
-   if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
-                 &IID_ID3D12Device2,
-                 (void **)&dev)))
-      return dev;
+   if (factory) {
+      if (FAILED(ID3D12DeviceFactory_CreateDevice(factory, adapter, D3D_FEATURE_LEVEL_11_0,
+                                                  &IID_ID3D12Device2,
+                                                  (void **)&dev))) {
+         mesa_loge("ID3D12DeviceFactory::CreateDevice failed\n");
+         return NULL;
+      }
+   } else {
+      typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **);
+      PFN_D3D12CREATEDEVICE D3D12CreateDevice;
 
-   mesa_loge("D3D12CreateDevice failed\n");
-   return NULL;
+      D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");
+      if (!D3D12CreateDevice) {
+         mesa_loge("failed to load D3D12CreateDevice from D3D12\n");
+         return NULL;
+      }
+
+      if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
+                                   &IID_ID3D12Device2,
+                                   (void **)&dev))) {
+         mesa_loge("D3D12CreateDevice failed\n");
+         return NULL;
+      }
+   }
+   return dev;
 }
 
 PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE