Module: Mesa
Branch: main
Commit: 4d95b4861e1478aa98ed23c47a595f82ce2ea7d2
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=4d95b4861e1478aa98ed23c47a595f82ce2ea7d2

Author: Maíra Canal <[email protected]>
Date:   Sat Aug 12 12:40:43 2023 -0300

v3dv: implement VK_EXT_multi_draw

Implement the Vulkan extension VK_EXT_multi_draw. It was tested with
deqp-vk -n dEQP-VK.draw.*multi_draw*.

Signed-off-by: Maíra Canal <[email protected]>
Reviewed-by: Iago Toral Quiroga <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26138>

---

 docs/features.txt                     |  2 +-
 src/broadcom/compiler/nir_to_vir.c    |  4 ++
 src/broadcom/compiler/v3d_compiler.h  |  5 +++
 src/broadcom/vulkan/v3dv_cmd_buffer.c | 77 ++++++++++++++++++++++++++++++++++-
 src/broadcom/vulkan/v3dv_device.c     | 10 +++++
 src/broadcom/vulkan/v3dv_private.h    |  4 ++
 src/broadcom/vulkan/v3dv_uniforms.c   |  4 ++
 7 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/docs/features.txt b/docs/features.txt
index a7bb309c4b3..8deae04e47c 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -582,7 +582,7 @@ Khronos extensions that are not part of any Vulkan version:
   VK_EXT_memory_budget                                  DONE (anv, hasvk, lvp, 
radv, tu, v3dv, vn)
   VK_EXT_memory_priority                                DONE (lvp, radv)
   VK_EXT_mesh_shader                                    DONE (anv/gfx12.5+, 
lvp, radv)
-  VK_EXT_multi_draw                                     DONE (anv, hasvk, lvp, 
radv, tu, vn)
+  VK_EXT_multi_draw                                     DONE (anv, hasvk, lvp, 
radv, tu, vn, v3dv)
   VK_EXT_multisampled_render_to_single_sampled          DONE (lvp)
   VK_EXT_nested_command_buffer                          DONE (lvp)
   VK_EXT_non_seamless_cube_map                          DONE (anv, hasvk, lvp, 
nvk, radv, tu, vn)
diff --git a/src/broadcom/compiler/nir_to_vir.c 
b/src/broadcom/compiler/nir_to_vir.c
index 095f92c9022..48572b43a9c 100644
--- a/src/broadcom/compiler/nir_to_vir.c
+++ b/src/broadcom/compiler/nir_to_vir.c
@@ -3359,6 +3359,10 @@ ntq_emit_intrinsic(struct v3d_compile *c, 
nir_intrinsic_instr *instr)
                 ntq_store_def(c, &instr->def, 0, vir_MOV(c, c->vid));
                 break;
 
+        case nir_intrinsic_load_draw_id:
+                ntq_store_def(c, &instr->def, 0, vir_uniform(c, 
QUNIFORM_DRAW_ID, 0));
+                break;
+
         case nir_intrinsic_load_tlb_color_v3d:
                 vir_emit_tlb_color_read(c, instr);
                 break;
diff --git a/src/broadcom/compiler/v3d_compiler.h 
b/src/broadcom/compiler/v3d_compiler.h
index cb9b2ae5757..83e1a1fe438 100644
--- a/src/broadcom/compiler/v3d_compiler.h
+++ b/src/broadcom/compiler/v3d_compiler.h
@@ -345,6 +345,11 @@ enum quniform_contents {
          QUNIFORM_INLINE_UBO_1,
          QUNIFORM_INLINE_UBO_2,
          QUNIFORM_INLINE_UBO_3,
+
+        /**
+         * Current value of DrawIndex for Multidraw
+         */
+        QUNIFORM_DRAW_ID,
 };
 
 static inline uint32_t v3d_unit_data_create(uint32_t unit, uint32_t value)
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c 
b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index dc01a0fa06e..203c4c273f7 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -2336,6 +2336,7 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer 
*cmd_buffer,
    const bool has_new_push_constants = dirty_uniform_state & 
V3DV_CMD_DIRTY_PUSH_CONSTANTS;
    const bool has_new_descriptors = dirty_uniform_state & 
V3DV_CMD_DIRTY_DESCRIPTOR_SETS;
    const bool has_new_view_index = dirty_uniform_state & 
V3DV_CMD_DIRTY_VIEW_INDEX;
+   const bool has_new_draw_id = dirty_uniform_state & V3DV_CMD_DIRTY_DRAW_ID;
 
    /* VK_SHADER_STAGE_FRAGMENT_BIT */
    const bool has_new_descriptors_fs =
@@ -2403,6 +2404,7 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer 
*cmd_buffer,
 
    const bool needs_vs_update = has_new_viewport ||
                                 has_new_view_index ||
+                                has_new_draw_id ||
                                 has_new_pipeline ||
                                 has_new_push_constants_vs ||
                                 has_new_descriptors_vs;
@@ -2422,6 +2424,7 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer 
*cmd_buffer,
    }
 
    cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_VIEW_INDEX;
+   cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_DRAW_ID;
 }
 
 /* This stores command buffer state that we might be about to stomp for
@@ -2913,7 +2916,8 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer 
*cmd_buffer,
                 V3DV_CMD_DIRTY_PUSH_CONSTANTS |
                 V3DV_CMD_DIRTY_DESCRIPTOR_SETS |
                 V3DV_CMD_DIRTY_VIEWPORT |
-                V3DV_CMD_DIRTY_VIEW_INDEX);
+                V3DV_CMD_DIRTY_VIEW_INDEX |
+                V3DV_CMD_DIRTY_DRAW_ID);
 
    if (dirty_uniform_state)
       update_gfx_uniform_state(cmd_buffer, dirty_uniform_state);
@@ -3030,6 +3034,35 @@ v3dv_CmdDraw(VkCommandBuffer commandBuffer,
    cmd_buffer_draw(cmd_buffer, &info);
 }
 
+VKAPI_ATTR void VKAPI_CALL
+v3dv_CmdDrawMultiEXT(VkCommandBuffer commandBuffer,
+                     uint32_t drawCount,
+                     const VkMultiDrawInfoEXT *pVertexInfo,
+                     uint32_t instanceCount,
+                     uint32_t firstInstance,
+                     uint32_t stride)
+
+{
+   if (drawCount == 0 || instanceCount == 0)
+      return;
+
+   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
+
+   uint32_t i = 0;
+   vk_foreach_multi_draw(draw, i, pVertexInfo, drawCount, stride) {
+      cmd_buffer->state.draw_id = i;
+      cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DRAW_ID;
+
+      struct v3dv_draw_info info = {};
+      info.vertex_count = draw->vertexCount;
+      info.instance_count = instanceCount;
+      info.first_instance = firstInstance;
+      info.first_vertex = draw->firstVertex;
+
+      cmd_buffer_draw(cmd_buffer, &info);
+   }
+}
+
 VKAPI_ATTR void VKAPI_CALL
 v3dv_CmdDrawIndexed(VkCommandBuffer commandBuffer,
                     uint32_t indexCount,
@@ -3064,6 +3097,48 @@ v3dv_CmdDrawIndexed(VkCommandBuffer commandBuffer,
    }
 }
 
+VKAPI_ATTR void VKAPI_CALL
+v3dv_CmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer,
+                            uint32_t drawCount,
+                            const VkMultiDrawIndexedInfoEXT *pIndexInfo,
+                            uint32_t instanceCount,
+                            uint32_t firstInstance,
+                            uint32_t stride,
+                            const int32_t *pVertexOffset)
+{
+   if (drawCount == 0 || instanceCount == 0)
+      return;
+
+   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
+
+   uint32_t i = 0;
+   vk_foreach_multi_draw_indexed(draw, i, pIndexInfo, drawCount, stride) {
+      uint32_t vertex_count = draw->indexCount * instanceCount;
+      int32_t vertexOffset = pVertexOffset ? *pVertexOffset : 
draw->vertexOffset;
+
+      cmd_buffer->state.draw_id = i;
+      cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DRAW_ID;
+
+      struct v3dv_render_pass *pass = cmd_buffer->state.pass;
+      if (likely(!pass->multiview_enabled)) {
+         v3dv_cmd_buffer_emit_pre_draw(cmd_buffer, true, false, vertex_count);
+         v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indexed)
+            (cmd_buffer, draw->indexCount, instanceCount,
+             draw->firstIndex, vertexOffset, firstInstance);
+         continue;
+      }
+
+      uint32_t view_mask = 
pass->subpasses[cmd_buffer->state.subpass_idx].view_mask;
+      while (view_mask) {
+         cmd_buffer_set_view_index(cmd_buffer, u_bit_scan(&view_mask));
+         v3dv_cmd_buffer_emit_pre_draw(cmd_buffer, true, false, vertex_count);
+         v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indexed)
+            (cmd_buffer, draw->indexCount, instanceCount,
+             draw->firstIndex, vertexOffset, firstInstance);
+      }
+   }
+}
+
 VKAPI_ATTR void VKAPI_CALL
 v3dv_CmdDrawIndirect(VkCommandBuffer commandBuffer,
                      VkBuffer _buffer,
diff --git a/src/broadcom/vulkan/v3dv_device.c 
b/src/broadcom/vulkan/v3dv_device.c
index 48fcf40bbf5..d29fbe265fe 100644
--- a/src/broadcom/vulkan/v3dv_device.c
+++ b/src/broadcom/vulkan/v3dv_device.c
@@ -195,6 +195,7 @@ get_device_extensions(const struct v3dv_physical_device 
*device,
       .EXT_index_type_uint8                 = true,
       .EXT_line_rasterization               = true,
       .EXT_memory_budget                    = true,
+      .EXT_multi_draw                       = true,
       .EXT_physical_device_drm              = true,
       .EXT_pipeline_creation_cache_control  = true,
       .EXT_pipeline_creation_feedback       = true,
@@ -436,6 +437,9 @@ get_features(const struct v3dv_physical_device 
*physical_device,
 
       /* VK_EXT_pipeline_robustness */
       .pipelineRobustness = true,
+
+      /* VK_EXT_multi_draw */
+      .multiDraw = true,
    };
 }
 
@@ -1736,6 +1740,12 @@ v3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice 
physicalDevice,
             VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT;
          break;
       }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: {
+         VkPhysicalDeviceMultiDrawPropertiesEXT *properties =
+            (VkPhysicalDeviceMultiDrawPropertiesEXT *)ext;
+         properties->maxMultiDrawCount = 2048;
+         break;
+      }
       default:
          v3dv_debug_ignored_stype(ext->sType);
          break;
diff --git a/src/broadcom/vulkan/v3dv_private.h 
b/src/broadcom/vulkan/v3dv_private.h
index 8d9914938e2..048d886a30c 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -1091,6 +1091,7 @@ enum v3dv_cmd_dirty_bits {
    V3DV_CMD_DIRTY_VIEW_INDEX                = 1 << 17,
    V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE        = 1 << 18,
    V3DV_CMD_DIRTY_DEPTH_BOUNDS              = 1 << 19,
+   V3DV_CMD_DIRTY_DRAW_ID                   = 1 << 20,
 };
 
 struct v3dv_dynamic_state {
@@ -1530,6 +1531,9 @@ struct v3dv_cmd_buffer_state {
    /* Current view index for multiview rendering */
    uint32_t view_index;
 
+   /* Current draw ID for multidraw */
+   uint32_t draw_id;
+
    /* Used to flag OOM conditions during command buffer recording */
    bool oom;
 
diff --git a/src/broadcom/vulkan/v3dv_uniforms.c 
b/src/broadcom/vulkan/v3dv_uniforms.c
index 3e311eb76ec..e2783ee9c35 100644
--- a/src/broadcom/vulkan/v3dv_uniforms.c
+++ b/src/broadcom/vulkan/v3dv_uniforms.c
@@ -657,6 +657,10 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer 
*cmd_buffer,
          cl_aligned_u32(&uniforms, pipeline->spill.size_per_thread);
          break;
 
+      case QUNIFORM_DRAW_ID:
+         cl_aligned_u32(&uniforms, job->cmd_buffer->state.draw_id);
+         break;
+
       default:
          unreachable("unsupported quniform_contents uniform type\n");
       }

Reply via email to