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,