From 20d1fdf7ebdf46f946b3c380c3e33a5b15163e52 Mon Sep 17 00:00:00 2001 From: squidbus <1249084-squidbus@users.noreply.gitlab.freedesktop.org> Date: Wed, 6 May 2026 03:52:20 -0700 Subject: [PATCH] kk: Enable VK_EXT_multi_draw Issues a draw for each entry, reusing as much setup as possible. Reviewed-by: Aitor Camacho Part-of: --- docs/features.txt | 2 +- src/kosmickrisp/vulkan/kk_cmd_draw.c | 96 +++++++++++++++++++++ src/kosmickrisp/vulkan/kk_physical_device.c | 4 + 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/docs/features.txt b/docs/features.txt index c39a247d827..77ea3bb4eb9 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -662,7 +662,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_memory_budget DONE (anv, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn) VK_EXT_memory_priority DONE (lvp, radv) VK_EXT_mesh_shader DONE (anv/gfx12.5+, lvp, radv, vn) - VK_EXT_multi_draw DONE (anv, hasvk, hk, lvp, nvk, radv, tu, vn, v3dv) + VK_EXT_multi_draw DONE (anv, hasvk, hk, kk, lvp, nvk, radv, tu, vn, v3dv) VK_EXT_multisampled_render_to_single_sampled DONE (lvp, vn, panvk, tu) VK_EXT_mutable_descriptor_type DONE (anv, hk, kk, lvp, nvk, panvk/v9+, radv, tu, vn) VK_EXT_nested_command_buffer DONE (anv, lvp, nvk, panvk/v10+, radv, tu, vn) diff --git a/src/kosmickrisp/vulkan/kk_cmd_draw.c b/src/kosmickrisp/vulkan/kk_cmd_draw.c index 47ac7b94a0c..578555e6c2e 100644 --- a/src/kosmickrisp/vulkan/kk_cmd_draw.c +++ b/src/kosmickrisp/vulkan/kk_cmd_draw.c @@ -1092,6 +1092,50 @@ kk_CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, kk_draw(cmd, data); } +VKAPI_ATTR void VKAPI_CALL +kk_CmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, + const VkMultiDrawInfoEXT *pVertexInfo, + uint32_t instanceCount, uint32_t firstInstance, + uint32_t stride) +{ + /* Metal validation dislikes empty calls */ + if (instanceCount == 0) + return; + + VK_FROM_HANDLE(kk_cmd_buffer, cmd, commandBuffer); + + const struct vk_dynamic_graphics_state *dyn = + &cmd->vk.dynamic_graphics_state; + + struct kk_draw_data data = { + .count[1] = instanceCount, + .first_instance = firstInstance, + .prim = vk_topology_to_mesa(dyn->ia.primitive_topology), + }; + + for (uint32_t i = 0; i < drawCount; ++i) { + /* Metal validation dislikes empty calls */ + if (pVertexInfo->vertexCount > 0) { + /* TODO_KOSMICKRISP + * Move this to a separate buffer from the root so we don't have to upload + * it every single loop. Pass it to the kk_draw call as a parameter that + * will later be uploaded. + */ + cmd->state.gfx.descriptors.root_dirty = true; + cmd->state.gfx.descriptors.root.draw.draw_id = i; + + data.count[0] = pVertexInfo->vertexCount; + data.first_vertex = pVertexInfo->firstVertex; + kk_draw(cmd, data); + } + + pVertexInfo = ((void *)pVertexInfo) + stride; + } + /* TODO_KOSMICKRISP Remove once above is done */ + cmd->state.gfx.descriptors.root_dirty = true; + cmd->state.gfx.descriptors.root.draw.draw_id = 0; +} + VKAPI_ATTR void VKAPI_CALL kk_CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, @@ -1124,6 +1168,58 @@ kk_CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, kk_draw(cmd, data); } +VKAPI_ATTR void VKAPI_CALL +kk_CmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT *pIndexInfo, + uint32_t instanceCount, uint32_t firstInstance, + uint32_t stride, const int32_t *pVertexOffset) +{ + /* Metal validation dislikes empty calls */ + if (instanceCount == 0) + return; + + VK_FROM_HANDLE(kk_cmd_buffer, cmd, commandBuffer); + + const struct vk_dynamic_graphics_state *dyn = + &cmd->vk.dynamic_graphics_state; + + struct kk_draw_data data = { + .count[1] = instanceCount, + .index_buffer = cmd->state.gfx.index.handle, + .index_buffer_offset = cmd->state.gfx.index.offset, + .index_buffer_range_B = + cmd->state.gfx.index.size - cmd->state.gfx.index.offset, + .first_instance = firstInstance, + .prim = vk_topology_to_mesa(dyn->ia.primitive_topology), + .index_size = cmd->state.gfx.index.bytes_per_index, + .indexed = true, + }; + + for (uint32_t i = 0; i < drawCount; ++i) { + /* Metal validation dislikes empty calls */ + if (pIndexInfo->indexCount > 0) { + /* TODO_KOSMICKRISP + * Move this to a separate buffer from the root so we don't have to upload + * it every single loop. Pass it to the kk_draw call as a parameter that + * will later be uploaded. + */ + cmd->state.gfx.descriptors.root_dirty = true; + cmd->state.gfx.descriptors.root.draw.draw_id = i; + + data.count[0] = pIndexInfo->indexCount; + data.first_index = pIndexInfo->firstIndex; + data.first_vertex = pVertexOffset != NULL ? *pVertexOffset : + pIndexInfo->vertexOffset; + kk_draw(cmd, data); + } + + pIndexInfo = ((void *)pIndexInfo) + stride; + } + /* TODO_KOSMICKRISP Remove once above is done */ + cmd->state.gfx.descriptors.root_dirty = true; + cmd->state.gfx.descriptors.root.draw.draw_id = 0; +} + VKAPI_ATTR void VKAPI_CALL kk_CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer _buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) diff --git a/src/kosmickrisp/vulkan/kk_physical_device.c b/src/kosmickrisp/vulkan/kk_physical_device.c index f9cfd293e12..7a19bf8ff2b 100644 --- a/src/kosmickrisp/vulkan/kk_physical_device.c +++ b/src/kosmickrisp/vulkan/kk_physical_device.c @@ -145,6 +145,7 @@ kk_get_device_extensions(const struct kk_instance *instance, .EXT_external_memory_metal = true, .EXT_image_2d_view_of_3d = true, .EXT_load_store_op_none = true, + .EXT_multi_draw = true, .EXT_mutable_descriptor_type = true, .EXT_shader_atomic_float = true, .EXT_shader_replicated_composites = true, @@ -325,6 +326,9 @@ kk_get_device_features( .image2DViewOf3D = true, .sampler2DViewOf3D = true, + /* VK_EXT_multi_draw */ + .multiDraw = true, + /* VK_EXT_shader_replicated_composites */ .shaderReplicatedComposites = true,