diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 45734f95880..e47953f2feb 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -347,6 +347,7 @@ void lvp_GetPhysicalDeviceFeatures2( VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2 *pFeatures) { + LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice); lvp_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); vk_foreach_struct(ext, pFeatures->pNext) { @@ -372,6 +373,19 @@ void lvp_GetPhysicalDeviceFeatures2( features->privateData = true; break; } + + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features = + (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext; + features->vertexAttributeInstanceRateZeroDivisor = false; + if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR) != 0) { + features->vertexAttributeInstanceRateDivisor = true; + } else { + features->vertexAttributeInstanceRateDivisor = false; + } + break; + } + default: break; } @@ -534,6 +548,7 @@ void lvp_GetPhysicalDeviceProperties2( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) { + LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice); lvp_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); vk_foreach_struct(ext, pProperties->pNext) { @@ -569,6 +584,15 @@ void lvp_GetPhysicalDeviceProperties2( properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: { + VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props = + (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext; + if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR) != 0) + props->maxVertexAttribDivisor = UINT32_MAX; + else + props->maxVertexAttribDivisor = 1; + break; + } default: break; } diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index f7a6aa12577..342e53b3804 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -40,6 +40,8 @@ #include "util/u_inlines.h" #include "util/format/u_format_zs.h" +#include "vk_util.h" + struct rendering_state { struct pipe_context *pctx; @@ -563,6 +565,9 @@ static void handle_graphics_pipeline(struct lvp_cmd_buffer_entry *cmd, { const VkPipelineVertexInputStateCreateInfo *vi = pipeline->graphics_create_info.pVertexInputState; int i; + const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_state = + vk_find_struct_const(vi->pNext, + PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT); for (i = 0; i < vi->vertexBindingDescriptionCount; i++) { state->vb[i].stride = vi->pVertexBindingDescriptions[i].stride; @@ -580,7 +585,17 @@ static void handle_graphics_pipeline(struct lvp_cmd_buffer_entry *cmd, state->ve[location].instance_divisor = 0; break; case VK_VERTEX_INPUT_RATE_INSTANCE: - state->ve[location].instance_divisor = 1; + if (div_state) { + for (unsigned j = 0; j < div_state->vertexBindingDivisorCount; j++) { + const VkVertexInputBindingDivisorDescriptionEXT *desc = + &div_state->pVertexBindingDivisors[j]; + if (desc->binding == state->ve[location].vertex_buffer_index) { + state->ve[location].instance_divisor = desc->divisor; + break; + } + } + } else + state->ve[location].instance_divisor = 1; break; default: assert(0); diff --git a/src/gallium/frontends/lavapipe/lvp_extensions.py b/src/gallium/frontends/lavapipe/lvp_extensions.py index 05c5c11b40e..e790aee50de 100644 --- a/src/gallium/frontends/lavapipe/lvp_extensions.py +++ b/src/gallium/frontends/lavapipe/lvp_extensions.py @@ -140,7 +140,7 @@ EXTENSIONS = [ Extension('VK_EXT_shader_subgroup_ballot', 1, False), Extension('VK_EXT_shader_subgroup_vote', 1, False), Extension('VK_EXT_transform_feedback', 1, False), - Extension('VK_EXT_vertex_attribute_divisor', 3, False), + Extension('VK_EXT_vertex_attribute_divisor', 3, True), Extension('VK_EXT_ycbcr_image_arrays', 1, False), Extension('VK_GOOGLE_decorate_string', 1, True), Extension('VK_GOOGLE_hlsl_functionality1', 1, True), diff --git a/src/gallium/frontends/lavapipe/lvp_pipeline.c b/src/gallium/frontends/lavapipe/lvp_pipeline.c index 7b36ce639e6..194c9ef9cf3 100644 --- a/src/gallium/frontends/lavapipe/lvp_pipeline.c +++ b/src/gallium/frontends/lavapipe/lvp_pipeline.c @@ -22,7 +22,7 @@ */ #include "lvp_private.h" - +#include "vk_util.h" #include "glsl_types.h" #include "spirv/nir_spirv.h" #include "nir/nir_builder.h" @@ -165,6 +165,29 @@ deep_copy_vertex_input_state(void *mem_ctx, VkVertexInputAttributeDescription, src->vertexAttributeDescriptionCount); + if (src->pNext) { + vk_foreach_struct(ext, src->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: { + VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_src = (VkPipelineVertexInputDivisorStateCreateInfoEXT *)ext;; + VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_dst = ralloc(mem_ctx, VkPipelineVertexInputDivisorStateCreateInfoEXT); + + ext_dst->sType = ext_src->sType; + ext_dst->vertexBindingDivisorCount = ext_src->vertexBindingDivisorCount; + + LVP_PIPELINE_DUP(ext_dst->pVertexBindingDivisors, + ext_src->pVertexBindingDivisors, + VkVertexInputBindingDivisorDescriptionEXT, + ext_src->vertexBindingDivisorCount); + + dst->pNext = ext_dst; + break; + } + default: + break; + } + } + } return VK_SUCCESS; }