Re: [PATCH 2/6] dxgi: Add feature level support.
On Wed, Mar 2, 2016 at 12:50 AM, Matteo Bruni <mbruni(a)codeweavers.com> wrote:
Signed-off-by: Matteo Bruni <mbruni(a)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?
On 2 March 2016 at 09:36, Józef Kucia <joseph.kucia(a)gmail.com> wrote:
Not that this is necessarily bad way to implement feature levels, but have you considered exposing wined3d_d3d_level from wined3d?
We'll probably want that at some point, yeah. The main issue I see with this patch though is that I think implementing d3d10_device_GetFeatureLevel() / d3d11_device_GetFeatureLevel() on top of this looks awkward.
2016-03-02 13:44 GMT+01:00 Henri Verbeet <hverbeet(a)gmail.com>:
On 2 March 2016 at 09:36, Józef Kucia <joseph.kucia(a)gmail.com> wrote:
Not that this is necessarily bad way to implement feature levels, but have you considered exposing wined3d_d3d_level from wined3d?
Oh, good idea. I guess for that to work properly the checks in d3d_level_from_caps() should be consistent with those in shader_glsl_get_caps() though (I'm thinking about the GLSL version "hacks" for SM4 and SM5 in d3d_level_from_caps()), not sure if that's fixable for the time being without regressing the fallbacks in the GPU recognition code. I can certainly give it a try though.
We'll probably want that at some point, yeah. The main issue I see with this patch though is that I think implementing d3d10_device_GetFeatureLevel() / d3d11_device_GetFeatureLevel() on top of this looks awkward.
Eh, good point. I'll fix that.
participants (3)
-
Henri Verbeet -
Józef Kucia -
Matteo Bruni