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

Józef Kucia joseph.kucia at gmail.com
Wed Mar 2 02:36:08 CST 2016


On Wed, Mar 2, 2016 at 12:50 AM, Matteo Bruni <mbruni at codeweavers.com> wrote:
> Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
> ---
>  dlls/d3d11/d3d11_main.c    | 21 +++++++++++---
>  dlls/d3d11/d3d11_private.h |  5 +++-
>  dlls/dxgi/adapter.c        |  3 +-
>  dlls/dxgi/device.c         | 10 +++++--
>  dlls/dxgi/dxgi.spec        |  2 +-
>  dlls/dxgi/dxgi_main.c      | 10 ++++---
>  dlls/dxgi/dxgi_private.h   |  7 +++--
>  dlls/dxgi/utils.c          | 71 ++++++++++++++++++++++++++++++++++++++++------
>  8 files changed, 104 insertions(+), 25 deletions(-)
>
> diff --git a/dlls/d3d11/d3d11_main.c b/dlls/d3d11/d3d11_main.c
> index 8602f00..0eeaf9f 100644
> --- a/dlls/d3d11/d3d11_main.c
> +++ b/dlls/d3d11/d3d11_main.c
> @@ -101,11 +101,26 @@ static HRESULT WINAPI layer_create(enum dxgi_device_layer_id id, void **layer_ba
>      return S_OK;
>  }
>
> +static void WINAPI layer_set_max_sm(enum dxgi_device_layer_id id, void *device, unsigned int max_sm)
> +{
> +    struct d3d_device *d3d_device = device;
> +
> +    TRACE("id %#x, device %p, max_sm %u.\n", id, device, max_sm);
> +
> +    if (id != DXGI_DEVICE_LAYER_D3D10_DEVICE)
> +    {
> +        WARN("Unknown layer id %#x.\n", id);
> +        return;
> +    }
> +
> +    d3d_device->max_sm = max_sm;
> +}
> +
>  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_max_sm},
>      };
>
>      DXGID3D10RegisterLayers(layers, sizeof(layers)/sizeof(*layers));
> @@ -123,10 +138,8 @@ HRESULT WINAPI D3D11CoreCreateDevice(IDXGIFactory *factory, IDXGIAdapter *adapte
>      TRACE("factory %p, adapter %p, flags %#x, feature_levels %p, levels %u, device %p.\n",
>              factory, adapter, flags, feature_levels, levels, device);
>
> -    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, feature_levels, levels, (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..606d84a 100644
> --- a/dlls/d3d11/d3d11_private.h
> +++ b/dlls/d3d11/d3d11_private.h
> @@ -394,6 +394,8 @@ struct d3d_device
>      IUnknown *outer_unk;
>      LONG refcount;
>
> +    unsigned int max_sm;
> +
>      struct d3d11_immediate_context immediate_context;
>
>      struct wined3d_device_parent device_parent;
> @@ -453,10 +455,11 @@ 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_max_sm)(enum dxgi_device_layer_id id, void *device, unsigned int max_sm);
>  };
>
>  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..91a8048 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 (FAILED(hr = 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..9929c22 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;
> +    unsigned int max_sm;
>      void *layer_base;
>      HRESULT hr;
>
> @@ -416,12 +418,12 @@ 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 (!(max_sm = 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 +439,8 @@ HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *l
>          return hr;
>      }
>
> +    layer->set_max_sm(layer->id, device->child_layer, max_sm);
> +
>      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..22910cf 100644
> --- a/dlls/dxgi/dxgi_private.h
> +++ b/dlls/dxgi/dxgi_private.h
> @@ -73,6 +73,7 @@ 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_max_sm)(enum dxgi_device_layer_id id, void *device, unsigned int max_sm);
>  };
>
>  /* TRACE helper functions */
> @@ -120,7 +121,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 +176,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;
> +HRESULT 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 92a049f..d71eb31 100644
> --- a/dlls/dxgi/utils.c
> +++ b/dlls/dxgi/utils.c
> @@ -434,24 +434,77 @@ 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)
> +HRESULT 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},
> +    };
> +    static const D3D_FEATURE_LEVEL default_feature_levels[] =
> +    {
> +        D3D_FEATURE_LEVEL_11_0,
> +        D3D_FEATURE_LEVEL_10_1,
> +        D3D_FEATURE_LEVEL_10_0,
> +        D3D_FEATURE_LEVEL_9_3,
> +        D3D_FEATURE_LEVEL_9_2,
> +        D3D_FEATURE_LEVEL_9_1,
> +    };
> +    unsigned int selected_sm = 0;
> +    unsigned int i, j;
>      WINED3DCAPS caps;
>      HRESULT hr;
>
>      FIXME("Ignoring adapter type.\n");
>
> +    if (!feature_levels)
> +    {
> +        feature_levels = default_feature_levels;
> +        level_count = sizeof(default_feature_levels) / sizeof(default_feature_levels[0]);
> +    }
> +
>      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_sm = feature_levels_sm[j].sm;
> +                    TRACE("Choosing supported feature level %#x (SM%u).\n", feature_levels[i], selected_sm);
> +                }
> +                break;
> +            }
> +        }
> +        if (selected_sm)
> +            break;
> +
> +        if (j == sizeof(feature_levels_sm) / sizeof(feature_levels_sm[0]))
> +            FIXME("Unexpected feature level %#x.\n", feature_levels[i]);
>      }
> -    wined3d_mutex_unlock();
> +    if (!selected_sm)
> +        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_sm;
>  }
> --
> 2.4.10
>
>
>

Not that this is necessarily bad way to implement feature levels, but
have you considered exposing wined3d_d3d_level from wined3d?



More information about the wine-devel mailing list