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"); }
