diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 364798f79b3..12d02538351 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -3399,6 +3399,14 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine struct wined3d_swapchain *wined3d_swapchain; HRESULT hr; + static const enum wined3d_feature_level feature_levels[] = + { + WINED3D_FEATURE_LEVEL_8, + WINED3D_FEATURE_LEVEL_7, + WINED3D_FEATURE_LEVEL_6, + WINED3D_FEATURE_LEVEL_5, + }; + device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl; device->device_parent.ops = &d3d8_wined3d_device_parent_ops; device->ref = 1; @@ -3413,9 +3421,9 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); wined3d_mutex_lock(); - hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4, - &device->device_parent, &device->wined3d_device); - if (FAILED(hr)) + if (FAILED(hr = wined3d_device_create(wined3d, adapter, device_type, + focus_window, flags, 4, feature_levels, ARRAY_SIZE(feature_levels), + &device->device_parent, &device->wined3d_device))) { WARN("Failed to create wined3d device, hr %#x.\n", hr); wined3d_mutex_unlock(); diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index a8dc7097c48..a31360886b6 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -4230,6 +4230,17 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine unsigned i, count = 1; HRESULT hr; + static const enum wined3d_feature_level feature_levels[] = + { + WINED3D_FEATURE_LEVEL_9_SM3, + WINED3D_FEATURE_LEVEL_9_SM2, + WINED3D_FEATURE_LEVEL_9_1, + WINED3D_FEATURE_LEVEL_8, + WINED3D_FEATURE_LEVEL_7, + WINED3D_FEATURE_LEVEL_6, + WINED3D_FEATURE_LEVEL_5, + }; + if (mode) FIXME("Ignoring display mode.\n"); @@ -4240,7 +4251,8 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); wined3d_mutex_lock(); - if (FAILED(hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4, + if (FAILED(hr = wined3d_device_create(wined3d, adapter, device_type, + focus_window, flags, 4, feature_levels, ARRAY_SIZE(feature_levels), &device->device_parent, &device->wined3d_device))) { WARN("Failed to create wined3d device, hr %#x.\n", hr); diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index c83d0ca1568..56a74cb3285 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -4986,6 +4986,13 @@ HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type de struct wined3d_caps caps; HRESULT hr; + static const enum wined3d_feature_level feature_levels[] = + { + WINED3D_FEATURE_LEVEL_7, + WINED3D_FEATURE_LEVEL_6, + WINED3D_FEATURE_LEVEL_5, + }; + ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl; ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl; ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl; @@ -5023,7 +5030,8 @@ HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type de } if (FAILED(hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, - NULL, 0, DDRAW_STRIDE_ALIGNMENT, &ddraw->device_parent, &ddraw->wined3d_device))) + NULL, 0, DDRAW_STRIDE_ALIGNMENT, feature_levels, ARRAY_SIZE(feature_levels), + &ddraw->device_parent, &ddraw->wined3d_device))) { WARN("Failed to create a wined3d device, hr %#x.\n", hr); wined3d_decref(ddraw->wined3d); diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index 67cadd5a3f8..deb07ca0d82 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -464,9 +464,10 @@ HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *l return E_FAIL; } - hr = wined3d_device_create(dxgi_factory->wined3d, dxgi_adapter->ordinal, WINED3D_DEVICE_TYPE_HAL, - NULL, 0, 4, wined3d_device_parent, &device->wined3d_device); - if (FAILED(hr)) + if (FAILED(hr = wined3d_device_create(dxgi_factory->wined3d, + dxgi_adapter->ordinal, WINED3D_DEVICE_TYPE_HAL, NULL, 0, 4, + (const enum wined3d_feature_level *)feature_levels, level_count, + wined3d_device_parent, &device->wined3d_device))) { WARN("Failed to create a wined3d device, returning %#x.\n", hr); IUnknown_Release(device->child_layer); diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index f74514f0d32..3a59196e1ab 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -97,6 +97,7 @@ DXGI_USAGE dxgi_usage_from_wined3d_usage(DWORD wined3d_usage) DECLSPEC_HIDDEN; DWORD wined3d_usage_from_dxgi_usage(DXGI_USAGE usage) DECLSPEC_HIDDEN; unsigned int dxgi_swapchain_flags_from_wined3d(unsigned int wined3d_flags) DECLSPEC_HIDDEN; unsigned int wined3d_swapchain_flags_from_dxgi(unsigned int flags) DECLSPEC_HIDDEN; + HRESULT dxgi_get_private_data(struct wined3d_private_store *store, REFGUID guid, UINT *data_size, void *data) DECLSPEC_HIDDEN; HRESULT dxgi_set_private_data(struct wined3d_private_store *store, diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 3fc3ae557dc..38c37d4c536 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5158,16 +5158,43 @@ static int wined3d_sampler_compare(const void *key, const struct wine_rb_entry * return memcmp(&sampler->desc, key, sizeof(sampler->desc)); } +static BOOL wined3d_select_feature_level(const struct wined3d_adapter *adapter, + const enum wined3d_feature_level *levels, unsigned int level_count, + enum wined3d_feature_level *selected_level) +{ + const struct wined3d_d3d_info *d3d_info = &adapter->d3d_info; + unsigned int i; + + for (i = 0; i < level_count; ++i) + { + if (levels[i] && d3d_info->feature_level >= levels[i]) + { + *selected_level = levels[i]; + return TRUE; + } + } + + FIXME_(winediag)("None of the requested D3D feature levels is supported on this GPU " + "with the current shader backend.\n"); + return FALSE; +} + HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, UINT adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD flags, - BYTE surface_alignment, struct wined3d_device_parent *device_parent) + BYTE surface_alignment, const enum wined3d_feature_level *levels, unsigned int level_count, + struct wined3d_device_parent *device_parent) { struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx]; - const struct fragment_pipeline *fragment_pipeline; const struct wined3d_vertex_pipe_ops *vertex_pipeline; + const struct fragment_pipeline *fragment_pipeline; unsigned int i; HRESULT hr; + if (!wined3d_select_feature_level(adapter, levels, level_count, &device->feature_level)) + return E_FAIL; + + TRACE("Device feature level %s.\n", wined3d_debug_feature_level(device->feature_level)); + device->ref = 1; device->wined3d = wined3d; wined3d_incref(device->wined3d); diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index a8986b06b82..925a5bc9eb8 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2416,16 +2416,18 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte return WINED3D_OK; } -HRESULT CDECL wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, enum wined3d_device_type device_type, - HWND focus_window, DWORD flags, BYTE surface_alignment, struct wined3d_device_parent *device_parent, - struct wined3d_device **device) +HRESULT CDECL wined3d_device_create(struct wined3d *wined3d, unsigned int adapter_idx, + enum wined3d_device_type device_type, HWND focus_window, DWORD flags, BYTE surface_alignment, + const enum wined3d_feature_level *feature_levels, unsigned int feature_level_count, + struct wined3d_device_parent *device_parent, struct wined3d_device **device) { struct wined3d_device *object; HRESULT hr; - TRACE("wined3d %p, adapter_idx %u, device_type %#x, focus_window %p, " - "flags %#x, surface_alignment %u, device_parent %p, device %p.\n", - wined3d, adapter_idx, device_type, focus_window, flags, surface_alignment, device_parent, device); + TRACE("wined3d %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x, " + "surface_alignment %u, feature_levels %p, feature_level_count %u, device_parent %p, device %p.\n", + wined3d, adapter_idx, device_type, focus_window, flags, surface_alignment, + feature_levels, feature_level_count, device_parent, device); if (adapter_idx >= wined3d->adapter_count) return WINED3DERR_INVALIDCALL; @@ -2433,9 +2435,9 @@ HRESULT CDECL wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, e if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; - hr = device_init(object, wined3d, adapter_idx, device_type, - focus_window, flags, surface_alignment, device_parent); - if (FAILED(hr)) + if (FAILED(hr = device_init(object, wined3d, adapter_idx, + device_type, focus_window, flags, surface_alignment, + feature_levels, feature_level_count, device_parent))) { WARN("Failed to initialize device, hr %#x.\n", hr); heap_free(object); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 055d546ccba..05579db5b2b 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -6311,6 +6311,28 @@ const char *wined3d_debug_location(DWORD location) return wine_dbg_sprintf("%s%s%s", prefix, buffer.str, suffix); } +const char *wined3d_debug_feature_level(enum wined3d_feature_level level) +{ + switch (level) + { +#define LEVEL_TO_STR(level) case level: return #level + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_5); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_6); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_7); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_8); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_9_1); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_9_SM2); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_9_SM3); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_10); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_10_1); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_11); + LEVEL_TO_STR(WINED3D_FEATURE_LEVEL_11_1); +#undef LEVEL_TO_STR + default: + return wine_dbg_sprintf("%#x", level); + } +} + /* Print a floating point value with the %.8e format specifier, always using * '.' as decimal separator. */ void wined3d_ftoa(float value, char *s) diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 93cecf0d3bb..a401e04dcf3 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -42,7 +42,7 @@ @ cdecl wined3d_device_copy_resource(ptr ptr ptr) @ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr long) @ cdecl wined3d_device_copy_uav_counter(ptr ptr long ptr) -@ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr) +@ cdecl wined3d_device_create(ptr long long ptr long long ptr long ptr ptr) @ cdecl wined3d_device_decref(ptr) @ cdecl wined3d_device_dispatch_compute(ptr long long long) @ cdecl wined3d_device_dispatch_compute_indirect(ptr ptr long) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 4c5d73f677e..40a27ffcf26 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2982,6 +2982,8 @@ struct wined3d_device WORD padding2 : 16; + enum wined3d_feature_level feature_level; + struct wined3d_state state; struct wined3d_state *update_state; struct wined3d_stateblock *recording; @@ -3037,7 +3039,8 @@ BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *c void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, UINT adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD flags, - BYTE surface_alignment, struct wined3d_device_parent *device_parent) DECLSPEC_HIDDEN; + BYTE surface_alignment, const enum wined3d_feature_level *levels, unsigned int level_count, + struct wined3d_device_parent *device_parent) DECLSPEC_HIDDEN; LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode, UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN; void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; @@ -3914,6 +3917,7 @@ const char *debug_ivec4(const struct wined3d_ivec4 *v) DECLSPEC_HIDDEN; const char *debug_uvec4(const struct wined3d_uvec4 *v) DECLSPEC_HIDDEN; const char *debug_shader_type(enum wined3d_shader_type shader_type) DECLSPEC_HIDDEN; const char *debug_vec4(const struct wined3d_vec4 *v) DECLSPEC_HIDDEN; +const char *wined3d_debug_feature_level(enum wined3d_feature_level level) DECLSPEC_HIDDEN; void dump_color_fixup_desc(struct color_fixup_desc fixup) DECLSPEC_HIDDEN; BOOL is_invalid_op(const struct wined3d_state *state, int stage, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 17b0fd4c456..6b81b3ab1df 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2248,8 +2248,9 @@ HRESULT __cdecl wined3d_device_copy_sub_resource_region(struct wined3d_device *d unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, unsigned int flags); void __cdecl wined3d_device_copy_uav_counter(struct wined3d_device *device, struct wined3d_buffer *dst_buffer, unsigned int offset, struct wined3d_unordered_access_view *uav); -HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, +HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, unsigned int adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD behaviour_flags, BYTE surface_alignment, + const enum wined3d_feature_level *feature_levels, unsigned int feature_level_count, struct wined3d_device_parent *device_parent, struct wined3d_device **device); ULONG __cdecl wined3d_device_decref(struct wined3d_device *device); void __cdecl wined3d_device_dispatch_compute(struct wined3d_device *device,