From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 90ffec4b1f7..adbf7234e38 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2260,13 +2260,22 @@ static enum wined3d_feature_level feature_level_from_caps(const struct shader_ca shader_model = min(shader_model, max(shader_caps->hs_version, 4)); shader_model = min(shader_model, max(shader_caps->ds_version, 4));
- if (shader_model >= 5) - return WINED3D_FEATURE_LEVEL_11_1; + if (!shader_model) + return WINED3D_FEATURE_LEVEL_7;
- if (shader_model >= 4) + if (shader_model <= 1) + return WINED3D_FEATURE_LEVEL_8; + + if (shader_model <= 2) + return WINED3D_FEATURE_LEVEL_9_2; + + if (shader_model <= 3) + return WINED3D_FEATURE_LEVEL_9_3; + + if (shader_model <= 4) return WINED3D_FEATURE_LEVEL_10_1;
- return WINED3D_FEATURE_LEVEL_NONE; + return WINED3D_FEATURE_LEVEL_11_1; }
static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_vk, uint32_t wined3d_creation_flags)
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 84 +++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 39 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index adbf7234e38..d8395273cf8 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;
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index d8395273cf8..289b01440aa 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2246,6 +2246,12 @@ 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 bool feature_level_9_3_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model) +{ + return shader_model >= 3 + && info->features2.features.independentBlend; +} + static bool feature_level_10_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model) { return shader_model >= 4 @@ -2269,7 +2275,7 @@ static enum wined3d_feature_level feature_level_from_caps(const struct wined3d_p if (shader_model <= 1) return WINED3D_FEATURE_LEVEL_8;
- if (shader_model <= 2) + if (!feature_level_9_3_supported(info, shader_model)) return WINED3D_FEATURE_LEVEL_9_2;
if (!feature_level_10_supported(info, shader_model))
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 4 ++ dlls/wined3d/context_vk.c | 92 ++++++++++++++++++++++------------ dlls/wined3d/wined3d_private.h | 4 +- dlls/wined3d/wined3d_vk.h | 2 + 4 files changed, 67 insertions(+), 35 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 289b01440aa..4043e91ef77 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2255,6 +2255,7 @@ static bool feature_level_9_3_supported(const struct wined3d_physical_device_inf static bool feature_level_10_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model) { return shader_model >= 4 + && info->features2.features.multiViewport && info->vertex_divisor_features.vertexAttributeInstanceRateDivisor && info->vertex_divisor_features.vertexAttributeInstanceRateZeroDivisor; } @@ -2290,6 +2291,7 @@ static enum wined3d_feature_level feature_level_from_caps(const struct wined3d_p 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_vk_info *vk_info = &adapter_vk->vk_info; struct wined3d_physical_device_info device_info; struct wined3d_vertex_caps vertex_caps; struct fragment_caps fragment_caps; @@ -2356,6 +2358,8 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_ d3d_info->filling_convention_offset = 0.0f;
d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB; + + vk_info->multiple_viewports = device_info.features2.features.multiViewport; }
static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk *adapter_vk) diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 13700c6dfb9..769e5347cc5 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1985,10 +1985,9 @@ static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wi if ((ret = wined3d_uint32_compare(a->ts_desc.patchControlPoints, b->ts_desc.patchControlPoints))) return ret;
- if ((ret = memcmp(&a->viewport, &b->viewport, sizeof(a->viewport)))) + if ((ret = memcmp(a->viewports, b->viewports, sizeof(a->viewports)))) return ret; - - if ((ret = memcmp(&a->scissor, &b->scissor, sizeof(a->scissor)))) + if ((ret = memcmp(a->scissors, b->scissors, sizeof(a->scissors)))) return ret;
if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc)))) @@ -2066,10 +2065,8 @@ static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - key->vp_desc.viewportCount = 1; - key->vp_desc.pViewports = &key->viewport; - key->vp_desc.scissorCount = 1; - key->vp_desc.pScissors = &key->scissor; + key->vp_desc.pViewports = key->viewports; + key->vp_desc.pScissors = key->scissors;
key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; key->rs_desc.lineWidth = 1.0f; @@ -2418,36 +2415,65 @@ static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_conte || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT) || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)) { - key->viewport.x = state->viewports[0].x; - key->viewport.y = state->viewports[0].y; - key->viewport.width = state->viewports[0].width; - key->viewport.height = state->viewports[0].height; - key->viewport.minDepth = state->viewports[0].min_z; - key->viewport.maxDepth = state->viewports[0].max_z; + key->vp_desc.viewportCount = (context_vk->vk_info->multiple_viewports ? WINED3D_MAX_VIEWPORTS : 1); + key->vp_desc.scissorCount = key->vp_desc.viewportCount;
- if (state->rasterizer_state && state->rasterizer_state->desc.scissor) + for (i = 0; i < key->vp_desc.viewportCount; ++i) { - const RECT *r = &state->scissor_rects[0]; + const struct wined3d_viewport *src_viewport = &state->viewports[i]; + VkViewport *viewport = &key->viewports[i]; + VkRect2D *scissor = &key->scissors[i];
- key->scissor.offset.x = r->left; - key->scissor.offset.y = r->top; - key->scissor.extent.width = r->right - r->left; - key->scissor.extent.height = r->bottom - r->top; - } - else - { - key->scissor.offset.x = key->viewport.x; - key->scissor.offset.y = key->viewport.y; - key->scissor.extent.width = key->viewport.width; - key->scissor.extent.height = key->viewport.height; + if (i >= state->viewport_count) + { + viewport->x = 0.0f; + viewport->y = 0.0f; + viewport->width = 1.0f; + viewport->height = 1.0f; + viewport->minDepth = 0.0f; + viewport->maxDepth = 0.0f; + + memset(scissor, 0, sizeof(*scissor)); + continue; + } + + viewport->x = src_viewport->x; + viewport->y = src_viewport->y; + viewport->width = src_viewport->width; + viewport->height = src_viewport->height; + viewport->minDepth = src_viewport->min_z; + viewport->maxDepth = src_viewport->max_z; + + if (state->rasterizer_state && state->rasterizer_state->desc.scissor) + { + const RECT *r = &state->scissor_rects[i]; + + if (i >= state->scissor_rect_count) + { + memset(scissor, 0, sizeof(*scissor)); + continue; + } + + scissor->offset.x = r->left; + scissor->offset.y = r->top; + scissor->extent.width = r->right - r->left; + scissor->extent.height = r->bottom - r->top; + } + else + { + scissor->offset.x = viewport->x; + scissor->offset.y = viewport->y; + scissor->extent.width = viewport->width; + scissor->extent.height = viewport->height; + } + /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */ + if (scissor->offset.x < 0) + scissor->offset.x = 0; + if (scissor->offset.y < 0) + scissor->offset.y = 0; + viewport->y += viewport->height; + viewport->height = -viewport->height; } - /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */ - if (key->scissor.offset.x < 0) - key->scissor.offset.x = 0; - if (key->scissor.offset.y < 0) - key->scissor.offset.y = 0; - key->viewport.y += key->viewport.height; - key->viewport.height = -key->viewport.height;
update = true; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a76dc7407cc..12dc08da352 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2608,8 +2608,8 @@ struct wined3d_graphics_pipeline_key_vk VkVertexInputBindingDivisorDescriptionEXT divisors[MAX_ATTRIBS]; VkVertexInputAttributeDescription attributes[MAX_ATTRIBS]; VkVertexInputBindingDescription bindings[MAX_ATTRIBS]; - VkViewport viewport; - VkRect2D scissor; + VkViewport viewports[WINED3D_MAX_VIEWPORTS]; + VkRect2D scissors[WINED3D_MAX_VIEWPORTS]; VkSampleMask sample_mask; VkPipelineColorBlendAttachmentState blend_attachments[WINED3D_MAX_RENDER_TARGETS];
diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index 00818f98b81..9135cff9143 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -223,6 +223,8 @@ struct wined3d_vk_info
BOOL supported[WINED3D_VK_EXT_COUNT]; HMODULE vulkan_lib; + + unsigned int multiple_viewports : 1; };
#define VK_CALL(f) (vk_info->vk_ops.f)
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 4043e91ef77..a83b1c70283 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2256,6 +2256,7 @@ static bool feature_level_10_supported(const struct wined3d_physical_device_info { return shader_model >= 4 && info->features2.features.multiViewport + && info->features2.features.geometryShader && info->vertex_divisor_features.vertexAttributeInstanceRateDivisor && info->vertex_divisor_features.vertexAttributeInstanceRateZeroDivisor; }
From patch 3/5:
+static bool feature_level_9_3_supported(const struct wined3d_physical_device_info *info, unsigned int shader_model) +{ + return shader_model >= 3 + && info->features2.features.independentBlend; +}
This is probably fine for simplicity, but note the existence of WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS (and "NumSimultaneousRTs" more generally); this is not strictly a requirement for D3D 9.3.
This merge request was approved by Jan Sikorski.