diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 552a89075f0..c76b5b1e503 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -376,19 +376,43 @@ static const struct wined3d_allocator_ops wined3d_allocator_vk_ops = .allocator_destroy_chunk = wined3d_allocator_vk_destroy_chunk, }; +static void get_physical_device_info(const struct wined3d_adapter_vk *adapter_vk, struct wined3d_physical_device_info *info) +{ + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features = &info->vertex_divisor_features; + VkPhysicalDeviceHostQueryResetFeatures *host_query_reset_features = &info->host_query_reset_features; + VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features = &info->xfb_features; + VkPhysicalDevice physical_device = adapter_vk->physical_device; + const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; + VkPhysicalDeviceFeatures2 *features2 = &info->features2; + + memset(info, 0, sizeof(*info)); + + xfb_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + + vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; + vertex_divisor_features->pNext = xfb_features; + + host_query_reset_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES; + host_query_reset_features->pNext = vertex_divisor_features; + + features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + features2->pNext = host_query_reset_features; + + if (vk_info->vk_ops.vkGetPhysicalDeviceFeatures2) + VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device, features2)); + else + VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features2->features)); +} + static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter, enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment, const enum wined3d_feature_level *levels, unsigned int level_count, struct wined3d_device_parent *device_parent, struct wined3d_device **device) { const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter); - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features; - VkPhysicalDeviceHostQueryResetFeatures *host_query_reset_features; const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; - VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features; struct wined3d_physical_device_info physical_device_info; static const float priorities[] = {1.0f}; - VkPhysicalDeviceFeatures2 *features2; struct wined3d_device_vk *device_vk; VkDevice vk_device = VK_NULL_HANDLE; VkDeviceQueueCreateInfo queue_info; @@ -407,36 +431,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi physical_device = adapter_vk->physical_device; - memset(&physical_device_info, 0, sizeof(physical_device_info)); - - xfb_features = &physical_device_info.xfb_features; - xfb_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; - - vertex_divisor_features = &physical_device_info.vertex_divisor_features; - vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; - vertex_divisor_features->pNext = xfb_features; - - host_query_reset_features = &physical_device_info.host_query_reset_features; - host_query_reset_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES; - host_query_reset_features->pNext = vertex_divisor_features; - - features2 = &physical_device_info.features2; - features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - features2->pNext = host_query_reset_features; - - if (vk_info->vk_ops.vkGetPhysicalDeviceFeatures2) - VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device, features2)); - else - VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features2->features)); - - if (!vertex_divisor_features->vertexAttributeInstanceRateDivisor - || !vertex_divisor_features->vertexAttributeInstanceRateZeroDivisor) - { - WARN("Vertex attribute divisors not supported.\n"); - hr = E_FAIL; - goto fail; - } - + get_physical_device_info(adapter_vk, &physical_device_info); wined3d_disable_vulkan_features(&physical_device_info); queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; @@ -447,7 +442,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi queue_info.pQueuePriorities = priorities; device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_info.pNext = features2->pNext; + device_info.pNext = physical_device_info.features2.pNext; device_info.flags = 0; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &queue_info; @@ -455,7 +450,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi device_info.ppEnabledLayerNames = NULL; device_info.enabledExtensionCount = adapter_vk->device_extension_count; device_info.ppEnabledExtensionNames = adapter_vk->device_extensions; - device_info.pEnabledFeatures = &features2->features; + device_info.pEnabledFeatures = &physical_device_info.features2.features; if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0) { @@ -2251,7 +2246,15 @@ static bool adapter_vk_init_driver_info(struct wined3d_adapter_vk *adapter_vk, adapter_vk->a.d3d_info.feature_level, vram_bytes, sysmem_bytes); } -static enum wined3d_feature_level feature_level_from_caps(const struct shader_caps *shader_caps) +static bool feature_level_10_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model) +{ + return shader_model >= 4 + && info->vertex_divisor_features.vertexAttributeInstanceRateDivisor + && info->vertex_divisor_features.vertexAttributeInstanceRateZeroDivisor; +} + +static enum wined3d_feature_level feature_level_from_caps(const struct wined3d_physical_device_info *info, + const struct shader_caps *shader_caps) { unsigned int shader_model; @@ -2269,7 +2272,7 @@ static enum wined3d_feature_level feature_level_from_caps(const struct shader_ca if (shader_model <= 2) return WINED3D_FEATURE_LEVEL_9_2; - if (shader_model <= 3) + if (!feature_level_10_supported(info, shader_model)) return WINED3D_FEATURE_LEVEL_9_3; if (shader_model <= 4) @@ -2281,10 +2284,13 @@ static enum wined3d_feature_level feature_level_from_caps(const struct shader_ca static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_vk, uint32_t wined3d_creation_flags) { struct wined3d_d3d_info *d3d_info = &adapter_vk->a.d3d_info; + struct wined3d_physical_device_info device_info; struct wined3d_vertex_caps vertex_caps; struct fragment_caps fragment_caps; struct shader_caps shader_caps; + get_physical_device_info(adapter_vk, &device_info); + adapter_vk->a.shader_backend->shader_get_caps(&adapter_vk->a, &shader_caps); adapter_vk->a.vertex_pipe->vp_get_caps(&adapter_vk->a, &vertex_caps); adapter_vk->a.fragment_pipe->get_caps(&adapter_vk->a, &fragment_caps); @@ -2330,7 +2336,7 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_ d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS); d3d_info->scaled_resolve = false; d3d_info->pbo = true; - d3d_info->feature_level = feature_level_from_caps(&shader_caps); + d3d_info->feature_level = feature_level_from_caps(&device_info, &shader_caps); d3d_info->subpixel_viewport = true; d3d_info->fences = true; d3d_info->persistent_map = true;