From d6c1e5051eb93ce05fe44f64c1772159b3a3f318 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Mon, 13 Apr 2020 13:14:59 +0200 Subject: [PATCH] radv: add support for dynamic primitive topology Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 54 +++++++++++++++++++++++-- src/amd/vulkan/radv_meta.c | 7 +++- src/amd/vulkan/radv_meta.h | 2 + src/amd/vulkan/radv_pipeline.c | 69 +++++++++----------------------- src/amd/vulkan/radv_private.h | 36 ++++++++++++++++- src/amd/vulkan/si_cmd_buffer.c | 4 +- 6 files changed, 115 insertions(+), 57 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 8ad1a86f5ce..6e188a42185 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -98,6 +98,7 @@ const struct radv_dynamic_state default_dynamic_state = { }, .cull_mode = 0u, .front_face = 0u, + .primitive_topology = 0u, }; static void @@ -237,6 +238,13 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, } } + if (copy_mask & RADV_DYNAMIC_PRIMITIVE_TOPOLOGY) { + if (dest->primitive_topology != src->primitive_topology) { + dest->primitive_topology = src->primitive_topology; + dest_mask |= RADV_DYNAMIC_PRIMITIVE_TOPOLOGY; + } + } + cmd_buffer->state.dirty |= dest_mask; } @@ -1210,6 +1218,9 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_CULL_MODE | RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE; + if (!cmd_buffer->state.emitted_pipeline) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; + radeon_emit_array(cmd_buffer->cs, pipeline->cs.buf, pipeline->cs.cdw); if (!cmd_buffer->state.emitted_pipeline || @@ -1348,10 +1359,9 @@ static void radv_emit_line_stipple(struct radv_cmd_buffer *cmd_buffer) { struct radv_dynamic_state *d = &cmd_buffer->state.dynamic; - struct radv_pipeline *pipeline = cmd_buffer->state.pipeline; uint32_t auto_reset_cntl = 1; - if (pipeline->graphics.topology == V_008958_DI_PT_LINESTRIP) + if (d->primitive_topology == V_008958_DI_PT_LINESTRIP) auto_reset_cntl = 2; radeon_set_context_reg(cmd_buffer->cs, R_028A0C_PA_SC_LINE_STIPPLE, @@ -1383,6 +1393,23 @@ radv_emit_culling(struct radv_cmd_buffer *cmd_buffer, uint32_t states) pa_su_sc_mode_cntl); } +static void +radv_emit_primitive_topology(struct radv_cmd_buffer *cmd_buffer) +{ + struct radv_dynamic_state *d = &cmd_buffer->state.dynamic; + + if (cmd_buffer->device->physical_device->rad_info.chip_class >= GFX7) { + radeon_set_uconfig_reg_idx(cmd_buffer->device->physical_device, + cmd_buffer->cs, + R_030908_VGT_PRIMITIVE_TYPE, 1, + d->primitive_topology); + } else { + radeon_set_config_reg(cmd_buffer->cs, + R_008958_VGT_PRIMITIVE_TYPE, + d->primitive_topology); + } +} + static void radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer, int index, @@ -2291,6 +2318,9 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer) RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE)) radv_emit_culling(cmd_buffer, states); + if (states & RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) + radv_emit_primitive_topology(cmd_buffer); + cmd_buffer->state.dirty &= ~states; } @@ -2790,6 +2820,7 @@ si_emit_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, { struct radeon_info *info = &cmd_buffer->device->physical_device->rad_info; struct radv_cmd_state *state = &cmd_buffer->state; + unsigned topology = state->dynamic.primitive_topology; struct radeon_cmdbuf *cs = cmd_buffer->cs; unsigned ia_multi_vgt_param; @@ -2797,7 +2828,8 @@ si_emit_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, si_get_ia_multi_vgt_param(cmd_buffer, instanced_draw, indirect_draw, count_from_stream_output, - draw_vertex_count); + draw_vertex_count, + topology); if (state->last_ia_multi_vgt_param != ia_multi_vgt_param) { if (info->chip_class == GFX9) { @@ -4270,6 +4302,22 @@ void radv_CmdSetFrontFaceEXT( state->dirty |= RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE; } +void radv_CmdSetPrimitiveTopologyEXT( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + unsigned primitive_topology = si_translate_prim(primitiveTopology); + + if (state->dynamic.primitive_topology == primitive_topology) + return; + + state->dynamic.primitive_topology = primitive_topology; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; +} + void radv_CmdExecuteCommands( VkCommandBuffer commandBuffer, uint32_t commandBufferCount, diff --git a/src/amd/vulkan/radv_meta.c b/src/amd/vulkan/radv_meta.c index 2f56c92374c..0b482b51b2c 100644 --- a/src/amd/vulkan/radv_meta.c +++ b/src/amd/vulkan/radv_meta.c @@ -65,6 +65,8 @@ radv_meta_save(struct radv_meta_saved_state *state, state->cull_mode = cmd_buffer->state.dynamic.cull_mode; state->front_face = cmd_buffer->state.dynamic.front_face; + + state->primitive_topology = cmd_buffer->state.dynamic.primitive_topology; } if (state->flags & RADV_META_SAVE_SAMPLE_LOCATIONS) { @@ -129,10 +131,13 @@ radv_meta_restore(const struct radv_meta_saved_state *state, cmd_buffer->state.dynamic.cull_mode = state->cull_mode; cmd_buffer->state.dynamic.front_face = state->front_face; + cmd_buffer->state.dynamic.primitive_topology = state->primitive_topology; + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_VIEWPORT | RADV_CMD_DIRTY_DYNAMIC_SCISSOR | RADV_CMD_DIRTY_DYNAMIC_CULL_MODE | - RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE; + RADV_CMD_DIRTY_DYNAMIC_FRONT_FACE | + RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; } if (state->flags & RADV_META_SAVE_SAMPLE_LOCATIONS) { diff --git a/src/amd/vulkan/radv_meta.h b/src/amd/vulkan/radv_meta.h index c3b4d9c72ea..cd4d1d64f63 100644 --- a/src/amd/vulkan/radv_meta.h +++ b/src/amd/vulkan/radv_meta.h @@ -61,6 +61,8 @@ struct radv_meta_saved_state { VkCullModeFlags cull_mode; VkFrontFace front_face; + + unsigned primitive_topology; }; VkResult radv_device_init_meta_clear_state(struct radv_device *device, bool on_demand); diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index c03e0f43c75..edcff4a83ef 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -1192,38 +1192,6 @@ radv_prim_can_use_guardband(enum VkPrimitiveTopology topology) } } -static uint32_t -si_translate_prim(enum VkPrimitiveTopology topology) -{ - switch (topology) { - case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: - return V_008958_DI_PT_POINTLIST; - case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: - return V_008958_DI_PT_LINELIST; - case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: - return V_008958_DI_PT_LINESTRIP; - case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: - return V_008958_DI_PT_TRILIST; - case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: - return V_008958_DI_PT_TRISTRIP; - case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: - return V_008958_DI_PT_TRIFAN; - case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: - return V_008958_DI_PT_LINELIST_ADJ; - case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: - return V_008958_DI_PT_LINESTRIP_ADJ; - case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: - return V_008958_DI_PT_TRILIST_ADJ; - case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: - return V_008958_DI_PT_TRISTRIP_ADJ; - case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: - return V_008958_DI_PT_PATCH; - default: - assert(0); - return 0; - } -} - static uint32_t si_conv_gl_prim_to_gs_out(unsigned gl_prim) { @@ -1302,6 +1270,8 @@ static unsigned radv_dynamic_state_mask(VkDynamicState state) return RADV_DYNAMIC_CULL_MODE; case VK_DYNAMIC_STATE_FRONT_FACE_EXT: return RADV_DYNAMIC_FRONT_FACE; + case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT: + return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY; default: unreachable("Unhandled dynamic state"); } @@ -1311,10 +1281,12 @@ static uint32_t radv_pipeline_needed_dynamic_state(const VkGraphicsPipelineCreat { uint32_t states = RADV_DYNAMIC_ALL; - /* If rasterization is disabled we do not care about any of the dynamic states, - * since they are all rasterization related only. */ + /* If rasterization is disabled we do not care about any of the + * dynamic states, since they are all rasterization related only, + * except primitive topology. + */ if (pCreateInfo->pRasterizationState->rasterizerDiscardEnable) - return 0; + return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY; if (!pCreateInfo->pRasterizationState->depthBiasEnable) states &= ~RADV_DYNAMIC_DEPTH_BIAS; @@ -1350,7 +1322,8 @@ static uint32_t radv_pipeline_needed_dynamic_state(const VkGraphicsPipelineCreat static void radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, - const VkGraphicsPipelineCreateInfo *pCreateInfo) + const VkGraphicsPipelineCreateInfo *pCreateInfo, + const struct radv_graphics_pipeline_create_info *extra) { uint32_t needed_states = radv_pipeline_needed_dynamic_state(pCreateInfo); uint32_t states = needed_states; @@ -1426,6 +1399,14 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, pCreateInfo->pRasterizationState->frontFace; } + if (states & RADV_DYNAMIC_PRIMITIVE_TOPOLOGY) { + dynamic->primitive_topology = + si_translate_prim(pCreateInfo->pInputAssemblyState->topology); + if (extra && extra->use_rectlist) { + dynamic->primitive_topology = V_008958_DI_PT_RECTLIST; + } + } + /* If there is no depthstencil attachment, then don't read * pDepthStencilState. The Vulkan spec states that pDepthStencilState may * be NULL in this case. Even if pDepthStencilState is non-NULL, there is @@ -4615,7 +4596,7 @@ radv_pipeline_generate_pm4(struct radv_pipeline *pipeline, const struct radv_graphics_pipeline_create_info *extra, const struct radv_blend_state *blend, const struct radv_tessellation_state *tess, - unsigned prim, unsigned gs_out) + unsigned gs_out) { struct radeon_cmdbuf *ctx_cs = &pipeline->ctx_cs; struct radeon_cmdbuf *cs = &pipeline->cs; @@ -4642,13 +4623,6 @@ radv_pipeline_generate_pm4(struct radv_pipeline *pipeline, gfx10_pipeline_generate_ge_cntl(ctx_cs, pipeline, tess); radeon_set_context_reg(ctx_cs, R_028B54_VGT_SHADER_STAGES_EN, radv_compute_vgt_shader_stages_en(pipeline)); - - if (pipeline->device->physical_device->rad_info.chip_class >= GFX7) { - radeon_set_uconfig_reg_idx(pipeline->device->physical_device, - cs, R_030908_VGT_PRIMITIVE_TYPE, 1, prim); - } else { - radeon_set_config_reg(cs, R_008958_VGT_PRIMITIVE_TYPE, prim); - } radeon_set_context_reg(ctx_cs, R_028A6C_VGT_GS_OUT_PRIM_TYPE, gs_out); radeon_set_context_reg(ctx_cs, R_02820C_PA_SC_CLIPRECT_RULE, radv_compute_cliprect_rule(pCreateInfo)); @@ -4834,9 +4808,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline, pipeline->graphics.spi_baryc_cntl = S_0286E0_FRONT_FACE_ALL_BITS(1); radv_pipeline_init_multisample_state(pipeline, &blend, pCreateInfo); uint32_t gs_out; - uint32_t prim = si_translate_prim(pCreateInfo->pInputAssemblyState->topology); - pipeline->graphics.topology = si_translate_prim(pCreateInfo->pInputAssemblyState->topology); pipeline->graphics.can_use_guardband = radv_prim_can_use_guardband(pCreateInfo->pInputAssemblyState->topology); if (radv_pipeline_has_gs(pipeline)) { @@ -4852,7 +4824,6 @@ radv_pipeline_init(struct radv_pipeline *pipeline, gs_out = si_conv_prim_to_gs_out(pCreateInfo->pInputAssemblyState->topology); } if (extra && extra->use_rectlist) { - prim = V_008958_DI_PT_RECTLIST; gs_out = V_028A6C_OUTPRIM_TYPE_TRISTRIP; pipeline->graphics.can_use_guardband = true; if (radv_pipeline_has_ngg(pipeline)) @@ -4860,7 +4831,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline, } pipeline->graphics.prim_restart_enable = !!pCreateInfo->pInputAssemblyState->primitiveRestartEnable; - radv_pipeline_init_dynamic_state(pipeline, pCreateInfo); + radv_pipeline_init_dynamic_state(pipeline, pCreateInfo, extra); /* Ensure that some export memory is always allocated, for two reasons: * @@ -4942,7 +4913,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline, pipeline->streamout_shader = radv_pipeline_get_streamout_shader(pipeline); result = radv_pipeline_scratch_init(device, pipeline); - radv_pipeline_generate_pm4(pipeline, pCreateInfo, extra, &blend, &tess, prim, gs_out); + radv_pipeline_generate_pm4(pipeline, pCreateInfo, extra, &blend, &tess, gs_out); return result; } diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 6286a67962a..bc6a46c5aa5 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1135,6 +1135,7 @@ struct radv_dynamic_state { VkCullModeFlags cull_mode; VkFrontFace front_face; + unsigned primitive_topology; }; extern const struct radv_dynamic_state default_dynamic_state; @@ -1395,7 +1396,8 @@ void si_write_scissors(struct radeon_cmdbuf *cs, int first, uint32_t si_get_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, bool instanced_draw, bool indirect_draw, bool count_from_stream_output, - uint32_t draw_vertex_count); + uint32_t draw_vertex_count, + unsigned topology); void si_cs_emit_write_event_eop(struct radeon_cmdbuf *cs, enum chip_class chip_class, bool is_mec, @@ -1651,7 +1653,6 @@ struct radv_pipeline { bool can_use_guardband; uint32_t needed_dynamic_state; bool disable_out_of_order_rast_for_occlusion; - uint8_t topology; unsigned tess_patch_control_points; unsigned pa_su_sc_mode_cntl; @@ -2490,6 +2491,37 @@ void radv_cmd_buffer_begin_render_pass(struct radv_cmd_buffer *cmd_buffer, const VkRenderPassBeginInfo *pRenderPassBegin); void radv_cmd_buffer_end_render_pass(struct radv_cmd_buffer *cmd_buffer); +static inline uint32_t si_translate_prim(unsigned topology) +{ + switch (topology) { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return V_008958_DI_PT_POINTLIST; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + return V_008958_DI_PT_LINELIST; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return V_008958_DI_PT_LINESTRIP; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + return V_008958_DI_PT_TRILIST; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + return V_008958_DI_PT_TRISTRIP; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + return V_008958_DI_PT_TRIFAN; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + return V_008958_DI_PT_LINELIST_ADJ; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return V_008958_DI_PT_LINESTRIP_ADJ; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + return V_008958_DI_PT_TRILIST_ADJ; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return V_008958_DI_PT_TRISTRIP_ADJ; + case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: + return V_008958_DI_PT_PATCH; + default: + assert(0); + return 0; + } +} + #define RADV_DEFINE_HANDLE_CASTS(__radv_type, __VkType) \ \ static inline struct __radv_type * \ diff --git a/src/amd/vulkan/si_cmd_buffer.c b/src/amd/vulkan/si_cmd_buffer.c index 68cd3d6865b..553ea2dfa83 100644 --- a/src/amd/vulkan/si_cmd_buffer.c +++ b/src/amd/vulkan/si_cmd_buffer.c @@ -711,7 +711,8 @@ uint32_t si_get_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, bool instanced_draw, bool indirect_draw, bool count_from_stream_output, - uint32_t draw_vertex_count) + uint32_t draw_vertex_count, + unsigned topology) { enum chip_class chip_class = cmd_buffer->device->physical_device->rad_info.chip_class; enum radeon_family family = cmd_buffer->device->physical_device->rad_info.family; @@ -723,7 +724,6 @@ si_get_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, bool ia_switch_on_eoi = false; bool partial_vs_wave = false; bool partial_es_wave = cmd_buffer->state.pipeline->graphics.ia_multi_vgt_param.partial_es_wave; - unsigned topology = cmd_buffer->state.pipeline->graphics.topology; bool multi_instances_smaller_than_primgroup; struct radv_prim_vertex_count prim_vertex_count = prim_size_table[topology]; -- 2.30.2