wined3d: Implement vertex attribute divisors for the Vulkan adapter.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2020-05-21 23:21:37 +04:30 committed by Alexandre Julliard
parent 5e7dd9d73e
commit b9638abe46
4 changed files with 71 additions and 7 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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() \