From d5dedecfe7ee90cf220da75b5ac21d9f651294bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= Date: Sat, 30 Apr 2022 13:09:53 +0200 Subject: [PATCH] anv: implement draw calls for EXT_mesh_shader Reviewed-by: Caio Oliveira Part-of: --- src/intel/vulkan/genX_cmd_buffer.c | 164 +++++++++++++++++++++++++++-- 1 file changed, 157 insertions(+), 7 deletions(-) diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 05855e021b3..cf8f0d66183 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -4570,16 +4570,42 @@ genX(CmdDrawMeshTasksNV)( } } +void +genX(CmdDrawMeshTasksEXT)( + VkCommandBuffer commandBuffer, + uint32_t x, + uint32_t y, + uint32_t z) +{ + ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + + if (anv_batch_has_error(&cmd_buffer->batch)) + return; + + /* TODO(mesh): Check if this is not emitting more packets than we need. */ + genX(cmd_buffer_flush_state)(cmd_buffer); + + if (cmd_buffer->state.conditional_render_enabled) + genX(cmd_emit_conditional_render_predicate)(cmd_buffer); + + anv_batch_emit(&cmd_buffer->batch, GENX(3DMESH_3D), m) { + m.PredicateEnable = cmd_buffer->state.conditional_render_enabled; + m.ThreadGroupCountX = x; + m.ThreadGroupCountY = y; + m.ThreadGroupCountZ = z; + } +} + #define GFX125_3DMESH_TG_COUNT 0x26F0 #define GFX125_3DMESH_STARTING_TGID 0x26F4 #define GFX10_3DPRIM_XP(n) (0x2690 + (n) * 4) /* n = { 0, 1, 2 } */ static void -mesh_load_indirect_parameters(struct anv_cmd_buffer *cmd_buffer, - struct mi_builder *b, - struct anv_address addr, - bool emit_xp0, - uint32_t xp0) +mesh_load_indirect_parameters_3dmesh_1d(struct anv_cmd_buffer *cmd_buffer, + struct mi_builder *b, + struct anv_address addr, + bool emit_xp0, + uint32_t xp0) { const size_t taskCountOff = offsetof(VkDrawMeshTasksIndirectCommandNV, taskCount); const size_t firstTaskOff = offsetof(VkDrawMeshTasksIndirectCommandNV, firstTask); @@ -4608,6 +4634,44 @@ emit_indirect_3dmesh_1d(struct anv_batch *batch, dw[len - 1] = 0; } +static void +mesh_load_indirect_parameters_3dmesh_3d(struct anv_cmd_buffer *cmd_buffer, + struct mi_builder *b, + struct anv_address addr, + bool emit_xp0, + uint32_t xp0) +{ + const size_t groupCountXOff = offsetof(VkDrawMeshTasksIndirectCommandEXT, groupCountX); + const size_t groupCountYOff = offsetof(VkDrawMeshTasksIndirectCommandEXT, groupCountY); + const size_t groupCountZOff = offsetof(VkDrawMeshTasksIndirectCommandEXT, groupCountZ); + + mi_store(b, mi_reg32(GFX125_3DMESH_TG_COUNT), + mi_mem32(anv_address_add(addr, groupCountXOff))); + + mi_store(b, mi_reg32(GFX10_3DPRIM_XP(1)), + mi_mem32(anv_address_add(addr, groupCountYOff))); + + mi_store(b, mi_reg32(GFX10_3DPRIM_XP(2)), + mi_mem32(anv_address_add(addr, groupCountZOff))); + + if (emit_xp0) + mi_store(b, mi_reg32(GFX10_3DPRIM_XP(0)), mi_imm(xp0)); +} + +static void +emit_indirect_3dmesh_3d(struct anv_batch *batch, + bool predicate_enable, + bool uses_drawid) +{ + uint32_t len = GENX(3DMESH_3D_length) + uses_drawid; + uint32_t *dw = anv_batch_emitn(batch, len, GENX(3DMESH_3D), + .PredicateEnable = predicate_enable, + .IndirectParameterEnable = true, + .ExtendedParameter0Present = uses_drawid); + if (uses_drawid) + dw[len - 1] = 0; +} + void genX(CmdDrawMeshTasksIndirectNV)( VkCommandBuffer commandBuffer, @@ -4639,7 +4703,7 @@ genX(CmdDrawMeshTasksIndirectNV)( for (uint32_t i = 0; i < drawCount; i++) { struct anv_address draw = anv_address_add(buffer->address, offset); - mesh_load_indirect_parameters(cmd_buffer, &b, draw, uses_drawid, i); + mesh_load_indirect_parameters_3dmesh_1d(cmd_buffer, &b, draw, uses_drawid, i); emit_indirect_3dmesh_1d(&cmd_buffer->batch, cmd_state->conditional_render_enabled, uses_drawid); @@ -4648,6 +4712,46 @@ genX(CmdDrawMeshTasksIndirectNV)( } } +void +genX(CmdDrawMeshTasksIndirectEXT)( + VkCommandBuffer commandBuffer, + VkBuffer _buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride) +{ + ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + ANV_FROM_HANDLE(anv_buffer, buffer, _buffer); + struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; + const struct brw_task_prog_data *task_prog_data = get_task_prog_data(pipeline); + const struct brw_mesh_prog_data *mesh_prog_data = get_mesh_prog_data(pipeline); + struct anv_cmd_state *cmd_state = &cmd_buffer->state; + + if (anv_batch_has_error(&cmd_buffer->batch)) + return; + + genX(cmd_buffer_flush_state)(cmd_buffer); + + if (cmd_state->conditional_render_enabled) + genX(cmd_emit_conditional_render_predicate)(cmd_buffer); + + bool uses_drawid = (task_prog_data && task_prog_data->uses_drawid) || + mesh_prog_data->uses_drawid; + struct mi_builder b; + mi_builder_init(&b, cmd_buffer->device->info, &cmd_buffer->batch); + + for (uint32_t i = 0; i < drawCount; i++) { + struct anv_address draw = anv_address_add(buffer->address, offset); + + mesh_load_indirect_parameters_3dmesh_3d(cmd_buffer, &b, draw, uses_drawid, i); + + emit_indirect_3dmesh_3d(&cmd_buffer->batch, + cmd_state->conditional_render_enabled, uses_drawid); + + offset += stride; + } +} + void genX(CmdDrawMeshTasksIndirectCountNV)( VkCommandBuffer commandBuffer, @@ -4685,13 +4789,59 @@ genX(CmdDrawMeshTasksIndirectCountNV)( emit_draw_count_predicate_cond(cmd_buffer, &b, i, max); - mesh_load_indirect_parameters(cmd_buffer, &b, draw, uses_drawid, i); + mesh_load_indirect_parameters_3dmesh_1d(cmd_buffer, &b, draw, uses_drawid, i); emit_indirect_3dmesh_1d(&cmd_buffer->batch, true, uses_drawid); offset += stride; } } + +void +genX(CmdDrawMeshTasksIndirectCountEXT)( + VkCommandBuffer commandBuffer, + VkBuffer _buffer, + VkDeviceSize offset, + VkBuffer _countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride) +{ + ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + ANV_FROM_HANDLE(anv_buffer, buffer, _buffer); + ANV_FROM_HANDLE(anv_buffer, count_buffer, _countBuffer); + struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; + const struct brw_task_prog_data *task_prog_data = get_task_prog_data(pipeline); + const struct brw_mesh_prog_data *mesh_prog_data = get_mesh_prog_data(pipeline); + + if (anv_batch_has_error(&cmd_buffer->batch)) + return; + + genX(cmd_buffer_flush_state)(cmd_buffer); + + bool uses_drawid = (task_prog_data && task_prog_data->uses_drawid) || + mesh_prog_data->uses_drawid; + + struct mi_builder b; + mi_builder_init(&b, cmd_buffer->device->info, &cmd_buffer->batch); + + struct mi_value max = + prepare_for_draw_count_predicate(cmd_buffer, &b, + count_buffer, countBufferOffset); + + for (uint32_t i = 0; i < maxDrawCount; i++) { + struct anv_address draw = anv_address_add(buffer->address, offset); + + emit_draw_count_predicate_cond(cmd_buffer, &b, i, max); + + mesh_load_indirect_parameters_3dmesh_3d(cmd_buffer, &b, draw, uses_drawid, i); + + emit_indirect_3dmesh_3d(&cmd_buffer->batch, true, uses_drawid); + + offset += stride; + } +} + #endif /* GFX_VERx10 >= 125 */ void