From f99f7c06e71d6194d4206bde58a8acb5a42d90ed Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 25 Mar 2021 14:06:41 -0400 Subject: [PATCH] lavapipe: implement multidraw ext Reviewed-by: Dave Airlie Part-of: --- .../frontends/lavapipe/lvp_cmd_buffer.c | 66 +++++++++++++++++++ src/gallium/frontends/lavapipe/lvp_device.c | 11 ++++ src/gallium/frontends/lavapipe/lvp_execute.c | 1 + src/gallium/frontends/lavapipe/lvp_private.h | 1 + 4 files changed, 79 insertions(+) diff --git a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c index aac580fc443..39148241248 100644 --- a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c +++ b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c @@ -498,6 +498,36 @@ VKAPI_ATTR void VKAPI_CALL lvp_CmdDraw( cmd_buf_queue(cmd_buffer, cmd); } +VKAPI_ATTR void VKAPI_CALL lvp_CmdDrawMultiEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawInfoEXT *pVertexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride) +{ + LVP_FROM_HANDLE(lvp_cmd_buffer, cmd_buffer, commandBuffer); + struct lvp_cmd_buffer_entry *cmd; + + uint32_t cmd_size = drawCount * sizeof(struct pipe_draw_start_count_bias); + cmd = cmd_buf_entry_alloc_size(cmd_buffer, cmd_size, LVP_CMD_DRAW); + if (!cmd) + return; + + cmd->u.draw.instance_count = instanceCount; + cmd->u.draw.first_instance = firstInstance; + cmd->u.draw.draw_count = drawCount; + if (stride == sizeof(struct pipe_draw_start_count_bias)) + memcpy(cmd->u.draw.draws, pVertexInfo, cmd_size); + else { + unsigned i = 0; + vk_foreach_multi_draw(draw, i, pVertexInfo, drawCount, stride) + memcpy(cmd->u.draw.draws, draw, sizeof(struct pipe_draw_start_count_bias)); + } + + cmd_buf_queue(cmd_buffer, cmd); +} + VKAPI_ATTR void VKAPI_CALL lvp_CmdEndRenderPass2( VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo) @@ -752,6 +782,42 @@ VKAPI_ATTR void VKAPI_CALL lvp_CmdDrawIndexed( cmd_buf_queue(cmd_buffer, cmd); } +VKAPI_ATTR void VKAPI_CALL lvp_CmdDrawMultiIndexedEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT *pIndexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride, + const int32_t *pVertexOffset) +{ + LVP_FROM_HANDLE(lvp_cmd_buffer, cmd_buffer, commandBuffer); + struct lvp_cmd_buffer_entry *cmd; + + uint32_t cmd_size = drawCount * sizeof(struct pipe_draw_start_count_bias); + cmd = cmd_buf_entry_alloc_size(cmd_buffer, cmd_size, LVP_CMD_DRAW_INDEXED); + if (!cmd) + return; + + cmd->u.draw_indexed.instance_count = instanceCount; + cmd->u.draw_indexed.first_instance = firstInstance; + cmd->u.draw_indexed.draw_count = drawCount; + cmd->u.draw_indexed.vertex_offset_changes = !pVertexOffset; + if (stride == sizeof(struct pipe_draw_start_count_bias)) + memcpy(cmd->u.draw_indexed.draws, pIndexInfo, cmd_size); + else { + unsigned i = 0; + vk_foreach_multi_draw_indexed(draw, i, pIndexInfo, drawCount, stride) + memcpy(cmd->u.draw_indexed.draws, draw, sizeof(struct pipe_draw_start_count_bias)); + } + /* only the first member is read if vertex_offset_changes is true */ + if (pVertexOffset) + cmd->u.draw_indexed.draws[0].index_bias = *pVertexOffset; + cmd->u.draw_indexed.calc_start = true; + + cmd_buf_queue(cmd_buffer, cmd); +} + VKAPI_ATTR void VKAPI_CALL lvp_CmdDrawIndirect( VkCommandBuffer commandBuffer, VkBuffer _buffer, diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 7b6859507a4..33f3f30043b 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -128,6 +128,7 @@ static const struct vk_device_extension_table lvp_device_extensions_supported = .EXT_extended_dynamic_state = true, .EXT_host_query_reset = true, .EXT_index_type_uint8 = true, + .EXT_multi_draw = true, .EXT_post_depth_coverage = true, .EXT_private_data = true, .EXT_sampler_filter_minmax = true, @@ -644,6 +645,11 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures2( features->transformFeedbackPreservesProvokingVertex = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: { + VkPhysicalDeviceMultiDrawFeaturesEXT *features = (VkPhysicalDeviceMultiDrawFeaturesEXT *)ext; + features->multiDraw = true; + break; + } default: break; } @@ -968,6 +974,11 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties2( properties->transformFeedbackPreservesTriangleFanProvokingVertex = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: { + VkPhysicalDeviceMultiDrawPropertiesEXT *props = (VkPhysicalDeviceMultiDrawPropertiesEXT *)ext; + props->maxMultiDrawCount = 2048; + break; + } default: break; } diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index 6987a43a8c8..4a119c09f19 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -2127,6 +2127,7 @@ static void handle_draw_indexed(struct lvp_cmd_buffer_entry *cmd, cmd->u.draw_indexed.draws[i].start = (state->index_offset / state->index_size) + cmd->u.draw_indexed.draws[i].start; cmd->u.draw_indexed.calc_start = false; } + state->info.index_bias_varies = cmd->u.draw_indexed.vertex_offset_changes; state->pctx->draw_vbo(state->pctx, &state->info, 0, NULL, cmd->u.draw_indexed.draws, cmd->u.draw_indexed.draw_count); } diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 86004ba4be6..e3aeab01cc0 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -755,6 +755,7 @@ struct lvp_cmd_draw_indexed { uint32_t first_instance; bool calc_start; uint32_t draw_count; + bool vertex_offset_changes; struct pipe_draw_start_count_bias draws[0]; };