[PATCH v3 1/6] dxgi: Add feature level support.

Matteo Bruni mbruni at codeweavers.com
Wed Mar 9 16:19:19 CST 2016


Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
v2: Pass the feature level to d3d11 instead of the maximum shader model,
check that VS AND PS versions are supported.
Still using the shader model instead of d3d_level to verify support for
a feature level to avoid version mismatches or regressing GPU
recognition.
v3: Fix dxgi_check_feature_level_support() prototype and its use in
dxgi_adapter_CheckInterfaceSupport(). Also move setting the default
feature levels to a later patch (and to d3d11, which seems more
appropriate for the job).

 dlls/d3d11/d3d11_main.c    | 17 ++++++++--
 dlls/d3d11/d3d11_private.h |  4 ++-
 dlls/dxgi/adapter.c        |  3 +-
 dlls/dxgi/device.c         | 11 +++++--
 dlls/dxgi/dxgi.spec        |  2 +-
 dlls/dxgi/dxgi_main.c      | 10 +++---
 dlls/dxgi/dxgi_private.h   |  8 +++--
 dlls/dxgi/utils.c          | 77 ++++++++++++++++++++++++++++++++++++++++------
 8 files changed, 109 insertions(+), 23 deletions(-)

diff --git a/dlls/d3d11/d3d11_main.c b/dlls/d3d11/d3d11_main.c
index a4277db..afc161f 100644
--- a/dlls/d3d11/d3d11_main.c
+++ b/dlls/d3d11/d3d11_main.c
@@ -101,11 +101,23 @@ static HRESULT WINAPI layer_create(enum dxgi_device_layer_id id, void **layer_ba
     return S_OK;
 }
 
+static void WINAPI layer_set_feature_level(enum dxgi_device_layer_id id, void *device,
+        D3D_FEATURE_LEVEL feature_level)
+{
+    TRACE("id %#x, device %p, feature_level %u.\n", id, device, feature_level);
+
+    if (id != DXGI_DEVICE_LAYER_D3D10_DEVICE)
+    {
+        WARN("Unknown layer id %#x.\n", id);
+        return;
+    }
+}
+
 HRESULT WINAPI D3D11CoreRegisterLayers(void)
 {
     static const struct dxgi_device_layer layers[] =
     {
-        {DXGI_DEVICE_LAYER_D3D10_DEVICE, layer_init, layer_get_size, layer_create},
+        {DXGI_DEVICE_LAYER_D3D10_DEVICE, layer_init, layer_get_size, layer_create, layer_set_feature_level},
     };
 
     DXGID3D10RegisterLayers(layers, sizeof(layers)/sizeof(*layers));
@@ -116,6 +128,7 @@ HRESULT WINAPI D3D11CoreRegisterLayers(void)
 HRESULT WINAPI D3D11CoreCreateDevice(IDXGIFactory *factory, IDXGIAdapter *adapter, UINT flags,
         const D3D_FEATURE_LEVEL *feature_levels, UINT levels, ID3D11Device **device)
 {
+    static const D3D_FEATURE_LEVEL level = D3D_FEATURE_LEVEL_10_0;
     IUnknown *dxgi_device;
     HMODULE d3d11;
     HRESULT hr;
@@ -126,7 +139,7 @@ HRESULT WINAPI D3D11CoreCreateDevice(IDXGIFactory *factory, IDXGIAdapter *adapte
     FIXME("Ignoring feature levels.\n");
 
     d3d11 = GetModuleHandleA("d3d11.dll");
-    hr = DXGID3D10CreateDevice(d3d11, factory, adapter, flags, 0, (void **)&dxgi_device);
+    hr = DXGID3D10CreateDevice(d3d11, factory, adapter, flags, &level, 1, (void **)&dxgi_device);
     if (FAILED(hr))
     {
         WARN("Failed to create device, returning %#x.\n", hr);
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h
index 9d5fd8f..a501a13 100644
--- a/dlls/d3d11/d3d11_private.h
+++ b/dlls/d3d11/d3d11_private.h
@@ -453,10 +453,12 @@ struct dxgi_device_layer
     UINT (WINAPI *get_size)(enum dxgi_device_layer_id id, struct layer_get_size_args *args, DWORD unknown0);
     HRESULT (WINAPI *create)(enum dxgi_device_layer_id id, void **layer_base, DWORD unknown0,
             void *device_object, REFIID riid, void **device_layer);
+    void (WINAPI *set_feature_level)(enum dxgi_device_layer_id id, void *device,
+            D3D_FEATURE_LEVEL feature_level);
 };
 
 HRESULT WINAPI DXGID3D10CreateDevice(HMODULE d3d10core, IDXGIFactory *factory, IDXGIAdapter *adapter,
-        UINT flags, void *unknown0, void **device);
+        unsigned int flags, const D3D_FEATURE_LEVEL *feature_levels, unsigned int level_count, void **device);
 HRESULT WINAPI DXGID3D10RegisterLayers(const struct dxgi_device_layer *layers, UINT layer_count);
 
 #endif /* __WINE_D3D11_PRIVATE_H */
diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c
index 3e58fd2..387156c 100644
--- a/dlls/dxgi/adapter.c
+++ b/dlls/dxgi/adapter.c
@@ -200,6 +200,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetDesc(IDXGIAdapter1 *iface, DXGI
 static HRESULT STDMETHODCALLTYPE dxgi_adapter_CheckInterfaceSupport(IDXGIAdapter1 *iface,
         REFGUID guid, LARGE_INTEGER *umd_version)
 {
+    static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_10_0;
     struct dxgi_adapter *adapter = impl_from_IDXGIAdapter1(iface);
     struct wined3d_adapter_identifier adapter_id;
     HRESULT hr;
@@ -214,7 +215,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_CheckInterfaceSupport(IDXGIAdapter
         return DXGI_ERROR_UNSUPPORTED;
     }
 
-    if (FAILED(hr = dxgi_check_d3d10_support(adapter->parent, adapter)))
+    if (!dxgi_check_feature_level_support(adapter->parent, adapter, &feature_level, 1))
         return DXGI_ERROR_UNSUPPORTED;
 
     if (umd_version)
diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c
index 8645b02..1caf63b 100644
--- a/dlls/dxgi/device.c
+++ b/dlls/dxgi/device.c
@@ -366,13 +366,15 @@ static const struct IWineDXGIDeviceVtbl dxgi_device_vtbl =
 };
 
 HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *layer,
-        IDXGIFactory *factory, IDXGIAdapter *adapter)
+        IDXGIFactory *factory, IDXGIAdapter *adapter,
+        const D3D_FEATURE_LEVEL *feature_levels, unsigned int level_count)
 {
     struct wined3d_device_parent *wined3d_device_parent;
     struct wined3d_swapchain_desc swapchain_desc;
     IWineDXGIDeviceParent *dxgi_device_parent;
     struct dxgi_adapter *dxgi_adapter;
     struct dxgi_factory *dxgi_factory;
+    D3D_FEATURE_LEVEL feature_level;
     void *layer_base;
     HRESULT hr;
 
@@ -416,12 +418,13 @@ HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *l
     wined3d_device_parent = IWineDXGIDeviceParent_get_wined3d_device_parent(dxgi_device_parent);
     IWineDXGIDeviceParent_Release(dxgi_device_parent);
 
-    if (FAILED(hr = dxgi_check_d3d10_support(dxgi_factory, dxgi_adapter)))
+    if (!(feature_level = dxgi_check_feature_level_support(dxgi_factory, dxgi_adapter,
+            feature_levels, level_count)))
     {
         IUnknown_Release(device->child_layer);
         wined3d_private_store_cleanup(&device->private_store);
         wined3d_mutex_unlock();
-        return hr;
+        return E_FAIL;
     }
 
     FIXME("Ignoring adapter type.\n");
@@ -437,6 +440,8 @@ HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *l
         return hr;
     }
 
+    layer->set_feature_level(layer->id, device->child_layer, feature_level);
+
     memset(&swapchain_desc, 0, sizeof(swapchain_desc));
     swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
     swapchain_desc.device_window = dxgi_factory_get_device_window(dxgi_factory);
diff --git a/dlls/dxgi/dxgi.spec b/dlls/dxgi/dxgi.spec
index 2232f88..3270a53 100644
--- a/dlls/dxgi/dxgi.spec
+++ b/dlls/dxgi/dxgi.spec
@@ -1,4 +1,4 @@
 @ stdcall CreateDXGIFactory(ptr ptr)
 @ stdcall CreateDXGIFactory1(ptr ptr)
-@ stdcall DXGID3D10CreateDevice(ptr ptr ptr long ptr ptr)
+@ stdcall DXGID3D10CreateDevice(ptr ptr ptr long ptr long ptr)
 @ stdcall DXGID3D10RegisterLayers(ptr long)
diff --git a/dlls/dxgi/dxgi_main.c b/dlls/dxgi/dxgi_main.c
index c8d049a..a4c1362 100644
--- a/dlls/dxgi/dxgi_main.c
+++ b/dlls/dxgi/dxgi_main.c
@@ -125,7 +125,7 @@ static HRESULT register_d3d10core_layers(HMODULE d3d10core)
 }
 
 HRESULT WINAPI DXGID3D10CreateDevice(HMODULE d3d10core, IDXGIFactory *factory, IDXGIAdapter *adapter,
-        UINT flags, void *unknown0, void **device)
+        unsigned int flags, const D3D_FEATURE_LEVEL *feature_levels, unsigned int level_count, void **device)
 {
     struct layer_get_size_args get_size_args;
     struct dxgi_device *dxgi_device;
@@ -134,8 +134,10 @@ HRESULT WINAPI DXGID3D10CreateDevice(HMODULE d3d10core, IDXGIFactory *factory, I
     DWORD count;
     HRESULT hr;
 
-    TRACE("d3d10core %p, factory %p, adapter %p, flags %#x, unknown0 %p, device %p.\n",
-            d3d10core, factory, adapter, flags, unknown0, device);
+    TRACE("d3d10core %p, factory %p, adapter %p, flags %#x, feature_levels %p, level_count %u, device %p.\n",
+            d3d10core, factory, adapter, flags, feature_levels, level_count, device);
+
+    FIXME("Ignoring flags.\n");
 
     hr = register_d3d10core_layers(d3d10core);
     if (FAILED(hr))
@@ -178,7 +180,7 @@ HRESULT WINAPI DXGID3D10CreateDevice(HMODULE d3d10core, IDXGIFactory *factory, I
         return E_OUTOFMEMORY;
     }
 
-    hr = dxgi_device_init(dxgi_device, &d3d10_layer, factory, adapter);
+    hr = dxgi_device_init(dxgi_device, &d3d10_layer, factory, adapter, feature_levels, level_count);
     if (FAILED(hr))
     {
         WARN("Failed to initialize device, hr %#x.\n", hr);
diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h
index 59b436b..7fc1e63 100644
--- a/dlls/dxgi/dxgi_private.h
+++ b/dlls/dxgi/dxgi_private.h
@@ -73,6 +73,8 @@ struct dxgi_device_layer
     UINT (WINAPI *get_size)(enum dxgi_device_layer_id id, struct layer_get_size_args *args, DWORD unknown0);
     HRESULT (WINAPI *create)(enum dxgi_device_layer_id id, void **layer_base, DWORD unknown0,
             void *device_object, REFIID riid, void **device_layer);
+    void (WINAPI *set_feature_level)(enum dxgi_device_layer_id id, void *device,
+            D3D_FEATURE_LEVEL feature_level);
 };
 
 /* TRACE helper functions */
@@ -120,7 +122,8 @@ struct dxgi_device
 };
 
 HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *layer,
-        IDXGIFactory *factory, IDXGIAdapter *adapter) DECLSPEC_HIDDEN;
+        IDXGIFactory *factory, IDXGIAdapter *adapter,
+        const D3D_FEATURE_LEVEL *feature_levels, unsigned int level_count) DECLSPEC_HIDDEN;
 
 /* IDXGIOutput */
 struct dxgi_output
@@ -174,6 +177,7 @@ struct dxgi_surface
 HRESULT dxgi_surface_init(struct dxgi_surface *surface, IDXGIDevice *device,
         IUnknown *outer, struct wined3d_resource *wined3d_resource) DECLSPEC_HIDDEN;
 
-HRESULT dxgi_check_d3d10_support(struct dxgi_factory *factory, struct dxgi_adapter *adapter) DECLSPEC_HIDDEN;
+D3D_FEATURE_LEVEL dxgi_check_feature_level_support(struct dxgi_factory *factory, struct dxgi_adapter *adapter,
+        const D3D_FEATURE_LEVEL *feature_levels, unsigned int level_count) DECLSPEC_HIDDEN;
 
 #endif /* __WINE_DXGI_PRIVATE_H */
diff --git a/dlls/dxgi/utils.c b/dlls/dxgi/utils.c
index dea1b69..cd8888f 100644
--- a/dlls/dxgi/utils.c
+++ b/dlls/dxgi/utils.c
@@ -27,6 +27,23 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
 #define WINE_DXGI_TO_STR(x) case x: return #x
 
+static const char *debug_feature_level(D3D_FEATURE_LEVEL feature_level)
+{
+    switch (feature_level)
+    {
+        WINE_DXGI_TO_STR(D3D_FEATURE_LEVEL_9_1);
+        WINE_DXGI_TO_STR(D3D_FEATURE_LEVEL_9_2);
+        WINE_DXGI_TO_STR(D3D_FEATURE_LEVEL_9_3);
+        WINE_DXGI_TO_STR(D3D_FEATURE_LEVEL_10_0);
+        WINE_DXGI_TO_STR(D3D_FEATURE_LEVEL_10_1);
+        WINE_DXGI_TO_STR(D3D_FEATURE_LEVEL_11_0);
+        WINE_DXGI_TO_STR(D3D_FEATURE_LEVEL_11_1);
+        default:
+            FIXME("Unrecognized D3D_FEATURE_LEVEL %#x.\n", feature_level);
+            return "unrecognized";
+    }
+}
+
 const char *debug_dxgi_format(DXGI_FORMAT format)
 {
     switch(format)
@@ -455,8 +472,26 @@ HRESULT dxgi_set_private_data_interface(struct wined3d_private_store *store,
     return hr;
 }
 
-HRESULT dxgi_check_d3d10_support(struct dxgi_factory *factory, struct dxgi_adapter *adapter)
+D3D_FEATURE_LEVEL dxgi_check_feature_level_support(struct dxgi_factory *factory, struct dxgi_adapter *adapter,
+        const D3D_FEATURE_LEVEL *feature_levels, unsigned int level_count)
 {
+    static const struct
+    {
+        D3D_FEATURE_LEVEL feature_level;
+        unsigned int sm;
+    }
+    feature_levels_sm[] =
+    {
+        {D3D_FEATURE_LEVEL_11_1, 5},
+        {D3D_FEATURE_LEVEL_11_0, 5},
+        {D3D_FEATURE_LEVEL_10_1, 4},
+        {D3D_FEATURE_LEVEL_10_0, 4},
+        {D3D_FEATURE_LEVEL_9_3,  3},
+        {D3D_FEATURE_LEVEL_9_2,  2},
+        {D3D_FEATURE_LEVEL_9_1,  2},
+    };
+    D3D_FEATURE_LEVEL selected_feature_level = 0;
+    unsigned int i, j;
     WINED3DCAPS caps;
     HRESULT hr;
 
@@ -464,15 +499,39 @@ HRESULT dxgi_check_d3d10_support(struct dxgi_factory *factory, struct dxgi_adapt
 
     wined3d_mutex_lock();
     hr = wined3d_get_device_caps(factory->wined3d, adapter->ordinal, WINED3D_DEVICE_TYPE_HAL, &caps);
-    if (FAILED(hr) || caps.VertexShaderVersion < 4 || caps.PixelShaderVersion < 4)
+    wined3d_mutex_unlock();
+
+    if (FAILED(hr))
+        level_count = 0;
+
+    for (i = 0; i < level_count; ++i)
     {
-        FIXME_(winediag)("Direct3D 10 is not supported on this GPU with the current shader backend.\n");
-        if (SUCCEEDED(hr))
-            hr = E_FAIL;
-        wined3d_mutex_unlock();
-        return hr;
+        for (j = 0; j < sizeof(feature_levels_sm) / sizeof(feature_levels_sm[0]); ++j)
+        {
+            if (feature_levels[i] == feature_levels_sm[j].feature_level)
+            {
+                if (caps.VertexShaderVersion >= feature_levels_sm[j].sm
+                        && caps.PixelShaderVersion >= feature_levels_sm[j].sm)
+                {
+                    selected_feature_level = feature_levels[i];
+                    TRACE("Choosing supported feature level %s (SM%u).\n",
+                            debug_feature_level(selected_feature_level), feature_levels_sm[j].sm);
+                }
+                break;
+            }
+        }
+        if (selected_feature_level)
+            break;
+
+        if (j == sizeof(feature_levels_sm) / sizeof(feature_levels_sm[0]))
+            FIXME("Unexpected feature level %#x.\n", feature_levels[i]);
+        else
+            TRACE("Feature level %s not supported, trying next fallback if available.\n",
+                    debug_feature_level(feature_levels[i]));
     }
-    wined3d_mutex_unlock();
+    if (!selected_feature_level)
+        FIXME_(winediag)("None of the requested D3D feature levels is supported on this GPU "
+                "with the current shader backend.\n");
 
-    return S_OK;
+    return selected_feature_level;
 }
-- 
2.4.10




More information about the wine-patches mailing list