From 2b844aab6a7ab916b1b8d4af233666f80ead5df7 Mon Sep 17 00:00:00 2001 From: Jonathan Weinstein Date: Mon, 16 May 2022 15:13:00 +0200 Subject: [PATCH] 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 Reviewed-By: Mike Blumenkrantz Part-of: --- docs/relnotes/new_features.txt | 1 + src/gallium/frontends/lavapipe/lvp_device.c | 3 +- src/gallium/frontends/lavapipe/lvp_execute.c | 4 +-- src/gallium/frontends/lavapipe/lvp_pipeline.c | 29 ++++++++++++------- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index d5a1d479de3..42b757822c0 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -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 diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index a963c38bc1d..333674bc208 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -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; } diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index 73f8c17d2dc..2253744778f 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -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); diff --git a/src/gallium/frontends/lavapipe/lvp_pipeline.c b/src/gallium/frontends/lavapipe/lvp_pipeline.c index edf3e59a27e..738411f6c8b 100644 --- a/src/gallium/frontends/lavapipe/lvp_pipeline.c +++ b/src/gallium/frontends/lavapipe/lvp_pipeline.c @@ -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; }