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:
parent
5e7dd9d73e
commit
b9638abe46
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() \
|
||||
|
|
Loading…
Reference in New Issue