Henri Verbeet : wined3d: Implement vertex attribute divisors for the Vulkan adapter.

Alexandre Julliard julliard at winehq.org
Thu May 21 15:41:21 CDT 2020


Module: wine
Branch: master
Commit: b9638abe46befa416ba5b91e5faeb2b31f30c137
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b9638abe46befa416ba5b91e5faeb2b31f30c137

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Thu May 21 23:39:37 2020 +0430

wined3d: Implement vertex attribute divisors for the Vulkan adapter.

Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wined3d/adapter_vk.c      | 48 ++++++++++++++++++++++++++++++++++++------
 dlls/wined3d/context_vk.c      | 27 +++++++++++++++++++++++-
 dlls/wined3d/wined3d_private.h |  2 ++
 dlls/wined3d/wined3d_vk.h      |  1 +
 4 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 0249c4c7af..8cbd820661 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -321,8 +321,20 @@ static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_v
     return E_FAIL;
 }
 
-static void wined3d_disable_vulkan_features(VkPhysicalDeviceFeatures *features)
+struct wined3d_physical_device_info
 {
+    VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
+
+    VkPhysicalDeviceFeatures2 features2;
+};
+
+static void wined3d_disable_vulkan_features(struct wined3d_physical_device_info *info)
+{
+    VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features = &info->vertex_divisor_features;
+    VkPhysicalDeviceFeatures *features = &info->features2.features;
+
+    vertex_divisor_features->vertexAttributeInstanceRateZeroDivisor = VK_FALSE;
+
     features->depthBounds = VK_FALSE;
     features->alphaToOne = VK_FALSE;
     features->textureCompressionETC2 = VK_FALSE;
@@ -405,6 +417,7 @@ static const struct
 }
 vulkan_device_extensions[] =
 {
+    {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,    ~0u},
     {VK_KHR_MAINTENANCE1_EXTENSION_NAME,                VK_API_VERSION_1_1},
     {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,      VK_API_VERSION_1_1},
 };
@@ -472,12 +485,14 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
 {
     const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
     const char *enabled_device_extensions[ARRAY_SIZE(vulkan_device_extensions)];
+    VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features;
     const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
+    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;
-    VkPhysicalDeviceFeatures features;
     VkPhysicalDevice physical_device;
     VkDeviceCreateInfo device_info;
     uint32_t queue_family_index;
@@ -492,8 +507,28 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
 
     physical_device = adapter_vk->physical_device;
 
-    VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features));
-    wined3d_disable_vulkan_features(&features);
+    memset(&physical_device_info, 0, sizeof(physical_device_info));
+
+    vertex_divisor_features = &physical_device_info.vertex_divisor_features;
+    vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
+
+    features2 = &physical_device_info.features2;
+    features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+    features2->pNext = vertex_divisor_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)
+    {
+        WARN("Vertex attribute divisors not supported.\n");
+        hr = E_FAIL;
+        goto fail;
+    }
+
+    wined3d_disable_vulkan_features(&physical_device_info);
 
     queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
     queue_info.pNext = NULL;
@@ -503,7 +538,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 = NULL;
+    device_info.pNext = features2->pNext;
     device_info.flags = 0;
     device_info.queueCreateInfoCount = 1;
     device_info.pQueueCreateInfos = &queue_info;
@@ -516,7 +551,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
         hr = E_FAIL;
         goto fail;
     }
-    device_info.pEnabledFeatures = &features;
+    device_info.pEnabledFeatures = &features2->features;
 
     if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
     {
@@ -1914,6 +1949,7 @@ static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
     if (!vk_ops->core_pfn) \
         vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
     MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
+    MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeaturess2KHR)
 #undef MAP_INSTANCE_FUNCTION
 
     vk_info->instance = instance;
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 13d3b4c544..3a6671036e 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1440,6 +1440,12 @@ static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wi
             return a->stages[i].module - b->stages[i].module;
     }
 
+    if (a->divisor_desc.vertexBindingDivisorCount != b->divisor_desc.vertexBindingDivisorCount)
+        return a->divisor_desc.vertexBindingDivisorCount - b->divisor_desc.vertexBindingDivisorCount;
+    if ((ret = memcmp(a->divisors, b->divisors,
+            a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
+        return ret;
+
     if (a->input_desc.vertexAttributeDescriptionCount != b->input_desc.vertexAttributeDescriptionCount)
         return a->input_desc.vertexAttributeDescriptionCount - b->input_desc.vertexAttributeDescriptionCount;
     if ((ret = memcmp(a->attributes, b->attributes,
@@ -1526,6 +1532,9 @@ static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context
     key->input_desc.pVertexBindingDescriptions = key->bindings;
     key->input_desc.pVertexAttributeDescriptions = key->attributes;
 
+    key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
+    key->divisor_desc.pVertexBindingDivisors = key->divisors;
+
     key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
 
     key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
@@ -1706,8 +1715,8 @@ static void wined3d_context_vk_update_blend_state(const struct wined3d_context_v
 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
         const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout)
 {
+    unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
     const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
-    unsigned int i, attribute_count, binding_count, stage_count;
     struct wined3d_graphics_pipeline_key_vk *key;
     VkPipelineShaderStageCreateInfo *stage;
     struct wined3d_stream_info stream_info;
@@ -1741,8 +1750,10 @@ static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_conte
             || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
     {
         wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
+        divisor_count = 0;
         for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
         {
+            VkVertexInputBindingDivisorDescriptionEXT *d;
             struct wined3d_stream_info_element *e;
             VkVertexInputAttributeDescription *a;
             VkVertexInputBindingDescription *b;
@@ -1768,11 +1779,25 @@ static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_conte
             b->binding = binding;
             b->stride = e->stride;
             b->inputRate = e->divisor ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
+
+            if (e->divisor > 1)
+            {
+                d = &key->divisors[divisor_count++];
+                d->binding = binding;
+                d->divisor = e->divisor;
+            }
         }
 
+        key->input_desc.pNext = NULL;
         key->input_desc.vertexBindingDescriptionCount = binding_count;
         key->input_desc.vertexAttributeDescriptionCount = attribute_count;
 
+        if (divisor_count)
+        {
+            key->input_desc.pNext = &key->divisor_desc;
+            key->divisor_desc.vertexBindingDivisorCount = divisor_count;
+        }
+
         update = true;
     }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ab5df330e7..e9081e5d17 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2323,12 +2323,14 @@ struct wined3d_pipeline_layout_vk
 struct wined3d_graphics_pipeline_key_vk
 {
     VkPipelineShaderStageCreateInfo stages[WINED3D_SHADER_TYPE_GRAPHICS_COUNT];
+    VkVertexInputBindingDivisorDescriptionEXT divisors[MAX_ATTRIBS];
     VkVertexInputAttributeDescription attributes[MAX_ATTRIBS];
     VkVertexInputBindingDescription bindings[MAX_ATTRIBS];
     VkViewport viewport;
     VkRect2D scissor;
     VkPipelineColorBlendAttachmentState blend_attachments[WINED3D_MAX_RENDER_TARGETS];
 
+    VkPipelineVertexInputDivisorStateCreateInfoEXT divisor_desc;
     VkPipelineVertexInputStateCreateInfo input_desc;
     VkPipelineInputAssemblyStateCreateInfo ia_desc;
     VkPipelineTessellationStateCreateInfo ts_desc;
diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h
index 0c0c1e16cd..4a872bcdaa 100644
--- a/dlls/wined3d/wined3d_vk.h
+++ b/dlls/wined3d/wined3d_vk.h
@@ -40,6 +40,7 @@
     VK_INSTANCE_PFN(vkGetPhysicalDeviceQueueFamilyProperties) \
     VK_INSTANCE_PFN(vkGetPhysicalDeviceSparseImageFormatProperties) \
     /* Vulkan 1.1 */ \
+    VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceFeatures2) \
     VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2)
 
 #define VK_DEVICE_FUNCS() \




More information about the wine-cvs mailing list