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