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

Author: Faith Ekstrand <faith.ekstr...@collabora.com>
Date:   Tue Dec 12 19:27:42 2023 -0600

nvk: Implement VK_EXT_multi_draw

Zink uses this to let it skip a bunch of the per-draw validation and, in
the case of NVK, redundant root descriptor uploads.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9642
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26660>

---

 src/nouveau/vulkan/nvk_cmd_draw.c        | 89 ++++++++++++++++++++++++++++++--
 src/nouveau/vulkan/nvk_physical_device.c |  7 +++
 2 files changed, 92 insertions(+), 4 deletions(-)

diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c 
b/src/nouveau/vulkan/nvk_cmd_draw.c
index e2d48af682f..1f1c6c8a137 100644
--- a/src/nouveau/vulkan/nvk_cmd_draw.c
+++ b/src/nouveau/vulkan/nvk_cmd_draw.c
@@ -1994,8 +1994,9 @@ void
 nvk_mme_draw(struct mme_builder *b)
 {
    nvk_mme_load_to_scratch(b, DRAW_BEGIN);
+   struct mme_value draw_idx = mme_load(b);
 
-   nvk_mme_build_draw(b, mme_zero());
+   nvk_mme_build_draw(b, draw_idx);
 }
 
 VKAPI_ATTR void VKAPI_CALL
@@ -2019,15 +2020,52 @@ nvk_CmdDraw(VkCommandBuffer commandBuffer,
       .split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
    });
 
-   struct nv_push *p = nvk_cmd_buffer_push(cmd, 6);
+   struct nv_push *p = nvk_cmd_buffer_push(cmd, 7);
    P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW));
    P_INLINE_DATA(p, begin);
+   P_INLINE_DATA(p, 0 /* draw_idx */);
    P_INLINE_DATA(p, vertexCount);
    P_INLINE_DATA(p, instanceCount);
    P_INLINE_DATA(p, firstVertex);
    P_INLINE_DATA(p, firstInstance);
 }
 
+VKAPI_ATTR void VKAPI_CALL
+nvk_CmdDrawMultiEXT(VkCommandBuffer commandBuffer,
+                    uint32_t drawCount,
+                    const VkMultiDrawInfoEXT *pVertexInfo,
+                    uint32_t instanceCount,
+                    uint32_t firstInstance,
+                    uint32_t stride)
+{
+   VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
+   const struct vk_dynamic_graphics_state *dyn =
+      &cmd->vk.dynamic_graphics_state;
+
+   nvk_flush_gfx_state(cmd);
+
+   uint32_t begin;
+   V_NV9097_BEGIN(begin, {
+      .op = vk_to_nv9097_primitive_topology(dyn->ia.primitive_topology),
+      .primitive_id = NV9097_BEGIN_PRIMITIVE_ID_FIRST,
+      .instance_id = NV9097_BEGIN_INSTANCE_ID_FIRST,
+      .split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
+   });
+
+   for (uint32_t draw_idx = 0; draw_idx < drawCount; draw_idx++) {
+      struct nv_push *p = nvk_cmd_buffer_push(cmd, 7);
+      P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW));
+      P_INLINE_DATA(p, begin);
+      P_INLINE_DATA(p, draw_idx);
+      P_INLINE_DATA(p, pVertexInfo->vertexCount);
+      P_INLINE_DATA(p, instanceCount);
+      P_INLINE_DATA(p, pVertexInfo->firstVertex);
+      P_INLINE_DATA(p, firstInstance);
+
+      pVertexInfo = ((void *)pVertexInfo) + stride;
+   }
+}
+
 static void
 nvk_mme_build_draw_indexed_loop(struct mme_builder *b,
                                 struct mme_value instance_count,
@@ -2119,8 +2157,9 @@ void
 nvk_mme_draw_indexed(struct mme_builder *b)
 {
    nvk_mme_load_to_scratch(b, DRAW_BEGIN);
+   struct mme_value draw_idx = mme_load(b);
 
-   nvk_mme_build_draw_indexed(b, mme_zero());
+   nvk_mme_build_draw_indexed(b, draw_idx);
 }
 
 VKAPI_ATTR void VKAPI_CALL
@@ -2145,9 +2184,10 @@ nvk_CmdDrawIndexed(VkCommandBuffer commandBuffer,
       .split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
    });
 
-   struct nv_push *p = nvk_cmd_buffer_push(cmd, 7);
+   struct nv_push *p = nvk_cmd_buffer_push(cmd, 8);
    P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW_INDEXED));
    P_INLINE_DATA(p, begin);
+   P_INLINE_DATA(p, 0 /* draw_idx */);
    P_INLINE_DATA(p, indexCount);
    P_INLINE_DATA(p, instanceCount);
    P_INLINE_DATA(p, firstIndex);
@@ -2155,6 +2195,47 @@ nvk_CmdDrawIndexed(VkCommandBuffer commandBuffer,
    P_INLINE_DATA(p, firstInstance);
 }
 
+VKAPI_ATTR void VKAPI_CALL
+nvk_CmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer,
+                           uint32_t drawCount,
+                           const VkMultiDrawIndexedInfoEXT *pIndexInfo,
+                           uint32_t instanceCount,
+                           uint32_t firstInstance,
+                           uint32_t stride,
+                           const int32_t *pVertexOffset)
+{
+   VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
+   const struct vk_dynamic_graphics_state *dyn =
+      &cmd->vk.dynamic_graphics_state;
+
+   nvk_flush_gfx_state(cmd);
+
+   uint32_t begin;
+   V_NV9097_BEGIN(begin, {
+      .op = vk_to_nv9097_primitive_topology(dyn->ia.primitive_topology),
+      .primitive_id = NV9097_BEGIN_PRIMITIVE_ID_FIRST,
+      .instance_id = NV9097_BEGIN_INSTANCE_ID_FIRST,
+      .split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
+   });
+
+   for (uint32_t draw_idx = 0; draw_idx < drawCount; draw_idx++) {
+      const uint32_t vertex_offset =
+         pVertexOffset != NULL ? *pVertexOffset : pIndexInfo->vertexOffset;
+
+      struct nv_push *p = nvk_cmd_buffer_push(cmd, 8);
+      P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW_INDEXED));
+      P_INLINE_DATA(p, begin);
+      P_INLINE_DATA(p, draw_idx);
+      P_INLINE_DATA(p, pIndexInfo->indexCount);
+      P_INLINE_DATA(p, instanceCount);
+      P_INLINE_DATA(p, pIndexInfo->firstIndex);
+      P_INLINE_DATA(p, vertex_offset);
+      P_INLINE_DATA(p, firstInstance);
+
+      pIndexInfo = ((void *)pIndexInfo) + stride;
+   }
+}
+
 void
 nvk_mme_draw_indirect(struct mme_builder *b)
 {
diff --git a/src/nouveau/vulkan/nvk_physical_device.c 
b/src/nouveau/vulkan/nvk_physical_device.c
index 739e8137237..1bd97bd1860 100644
--- a/src/nouveau/vulkan/nvk_physical_device.c
+++ b/src/nouveau/vulkan/nvk_physical_device.c
@@ -159,6 +159,7 @@ nvk_get_device_extensions(const struct nv_device_info *info,
       .EXT_inline_uniform_block = true,
       .EXT_line_rasterization = true,
       .EXT_load_store_op_none = true,
+      .EXT_multi_draw = true,
       .EXT_mutable_descriptor_type = true,
       .EXT_non_seamless_cube_map = true,
       .EXT_pci_bus_info = info->type == NV_DEVICE_TYPE_DIS,
@@ -437,6 +438,9 @@ nvk_get_device_features(const struct nv_device_info *info,
       .stippledBresenhamLines = true,
       .stippledSmoothLines = true,
 
+      /* VK_EXT_multi_draw */
+      .multiDraw = true,
+
       /* VK_EXT_non_seamless_cube_map */
       .nonSeamlessCubeMap = true,
 
@@ -738,6 +742,9 @@ nvk_get_device_properties(const struct nvk_instance 
*instance,
       /* VK_EXT_line_rasterization */
       .lineSubPixelPrecisionBits = 8,
 
+      /* VK_EXT_multi_draw */
+      .maxMultiDrawCount = UINT32_MAX,
+
       /* VK_EXT_pci_bus_info */
       .pciDomain   = info->pci.domain,
       .pciBus      = info->pci.bus,

Reply via email to