lavapipe: support instance rate zero for VK_EXT_vertex_attribute_divisor

gallium can't directly support vertex attribute instance rate zero, since
the instance rate is also used to determine if the data is per-vertex or
per-instance in the first place (hence divisor zero meaning the data is
per vertex).
While it's an optional feature for VK_EXT_vertex_attribute_divisor, some
apps require it to work (it's a standard d3d10 feature and widely
supported), hence translate it away as MAX_UINT32 divisor instead (which
at this point probably makes more sense than to change the gallium
interface), which should work all the same.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16526>
This commit is contained in:
Jonathan Weinstein 2022-05-16 15:13:00 +02:00 committed by Roland Scheidegger
parent fa67f119f2
commit 2b844aab6a
4 changed files with 24 additions and 13 deletions

View file

@ -3,3 +3,4 @@ d3d12 ARB_robust_buffer_access_behavior
VK_EXT_robustness2 for lavapipe
VK_EXT_image_2d_view_of_3d on RADV
zink GL_EXT_memory_object_win32 and GL_EXT_semaphore_win32 support
vertexAttributeInstanceRateZeroDivisor support for lavapipe

View file

@ -780,11 +780,12 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures2(
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->vertexAttributeInstanceRateZeroDivisor = true;
features->vertexAttributeInstanceRateDivisor = true;
} else {
features->vertexAttributeInstanceRateDivisor = false;
features->vertexAttributeInstanceRateZeroDivisor = false;
}
break;
}

View file

@ -3495,13 +3495,13 @@ static void handle_set_vertex_input(struct vk_cmd_queue_entry *cmd,
state->velem.velems[location].vertex_buffer_index = attrs[i].binding;
state->velem.velems[location].src_format = lvp_vk_format_to_pipe_format(attrs[i].format);
state->vb[attrs[i].binding].stride = binding->stride;
uint32_t d = binding->divisor;
switch (binding->inputRate) {
case VK_VERTEX_INPUT_RATE_VERTEX:
state->velem.velems[location].instance_divisor = 0;
break;
case VK_VERTEX_INPUT_RATE_INSTANCE:
state->velem.velems[location].instance_divisor = binding->divisor;
state->velem.velems[location].instance_divisor = d ? d : UINT32_MAX;
break;
default:
assert(0);

View file

@ -143,17 +143,26 @@ deep_copy_vertex_input_state(void *mem_ctx,
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);
const VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_src = (VkPipelineVertexInputDivisorStateCreateInfoEXT *)ext;
unsigned n = ext_src->vertexBindingDivisorCount;
if (!n)
continue;
size_t offset = sizeof(VkPipelineVertexInputDivisorStateCreateInfoEXT);
char *p = (char *) ralloc_size(mem_ctx, offset + n * sizeof(VkVertexInputBindingDivisorDescriptionEXT));
if (!p)
return VK_ERROR_OUT_OF_HOST_MEMORY;
VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_dst = (VkPipelineVertexInputDivisorStateCreateInfoEXT *)p;
VkVertexInputBindingDivisorDescriptionEXT *dst_divisors = (VkVertexInputBindingDivisorDescriptionEXT *)(p + offset);
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);
ext_dst->pNext = NULL;
ext_dst->vertexBindingDivisorCount = n;
ext_dst->pVertexBindingDivisors = dst_divisors;
const VkVertexInputBindingDivisorDescriptionEXT *src_divisors = ext_src->pVertexBindingDivisors;
for (unsigned i = 0; i < n; ++i) {
uint32_t d = src_divisors[i].divisor;
dst_divisors[i].divisor = d ? d : UINT32_MAX;
dst_divisors[i].binding = src_divisors[i].binding;
}
dst->pNext = ext_dst;
break;
}