diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index bbd67c444f1..6a75cac8015 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -107,6 +107,7 @@ const struct radv_dynamic_state default_dynamic_state = { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, }, .depth_bias_enable = 0u, + .primitive_restart_enable = 0u, }; static void @@ -305,6 +306,13 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, const struct radv_dy } } + if (copy_mask & RADV_DYNAMIC_PRIMITIVE_RESTART_ENABLE) { + if (dest->primitive_restart_enable != src->primitive_restart_enable) { + dest->primitive_restart_enable = src->primitive_restart_enable; + dest_mask |= RADV_DYNAMIC_PRIMITIVE_RESTART_ENABLE; + } + } + cmd_buffer->state.dirty |= dest_mask; } @@ -1273,7 +1281,8 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) if (!cmd_buffer->state.emitted_pipeline) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY | RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS | - RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS; + RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS | + RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE; if (!cmd_buffer->state.emitted_pipeline || cmd_buffer->state.emitted_pipeline->graphics.db_depth_control != @@ -1584,6 +1593,20 @@ radv_emit_fragment_shading_rate(struct radv_cmd_buffer *cmd_buffer) radeon_set_context_reg(cmd_buffer->cs, R_028848_PA_CL_VRS_CNTL, pa_cl_vrs_cntl); } +static void +radv_emit_primitive_restart_enable(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 >= GFX9) { + radeon_set_uconfig_reg(cmd_buffer->cs, R_03092C_VGT_MULTI_PRIM_IB_RESET_EN, + d->primitive_restart_enable); + } else { + radeon_set_context_reg(cmd_buffer->cs, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, + d->primitive_restart_enable); + } +} + static void radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer, int index, struct radv_color_buffer_info *cb, struct radv_image_view *iview, @@ -2581,6 +2604,9 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer) if (states & RADV_CMD_DIRTY_DYNAMIC_FRAGMENT_SHADING_RATE) radv_emit_fragment_shading_rate(cmd_buffer); + if (states & RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE) + radv_emit_primitive_restart_enable(cmd_buffer); + cmd_buffer->state.dirty &= ~states; } @@ -3070,12 +3096,13 @@ si_emit_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, bool instanced_dr 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; + bool prim_restart_enable = state->dynamic.primitive_restart_enable; struct radeon_cmdbuf *cs = cmd_buffer->cs; unsigned ia_multi_vgt_param; ia_multi_vgt_param = si_get_ia_multi_vgt_param(cmd_buffer, instanced_draw, indirect_draw, count_from_stream_output, - draw_vertex_count, topology); + draw_vertex_count, topology, prim_restart_enable); if (state->last_ia_multi_vgt_param != ia_multi_vgt_param) { if (info->chip_class == GFX9) { @@ -3096,7 +3123,6 @@ radv_emit_draw_registers(struct radv_cmd_buffer *cmd_buffer, const struct radv_d struct radeon_info *info = &cmd_buffer->device->physical_device->rad_info; struct radv_cmd_state *state = &cmd_buffer->state; struct radeon_cmdbuf *cs = cmd_buffer->cs; - int32_t primitive_reset_en; /* Draw state. */ if (info->chip_class < GFX10) { @@ -3105,19 +3131,7 @@ radv_emit_draw_registers(struct radv_cmd_buffer *cmd_buffer, const struct radv_d draw_info->indirect ? 0 : draw_info->count); } - /* Primitive restart. */ - primitive_reset_en = draw_info->indexed && state->pipeline->graphics.prim_restart_enable; - - if (primitive_reset_en != state->last_primitive_reset_en) { - state->last_primitive_reset_en = primitive_reset_en; - if (info->chip_class >= GFX9) { - radeon_set_uconfig_reg(cs, R_03092C_VGT_MULTI_PRIM_IB_RESET_EN, primitive_reset_en); - } else { - radeon_set_context_reg(cs, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, primitive_reset_en); - } - } - - if (primitive_reset_en) { + if (state->dynamic.primitive_restart_enable) { uint32_t primitive_reset_index = radv_get_primitive_reset_index(cmd_buffer); if (primitive_reset_index != state->last_primitive_reset_index) { @@ -4762,6 +4776,20 @@ radv_CmdSetDepthBiasEnableEXT(VkCommandBuffer commandBuffer, VkBool32 depthBiasE state->dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE; } +void +radv_CmdSetPrimitiveRestartEnableEXT(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + if (state->dynamic.primitive_restart_enable == primitiveRestartEnable) + return; + + state->dynamic.primitive_restart_enable = primitiveRestartEnable; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE; +} + void radv_CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCmdBuffers) @@ -5373,7 +5401,7 @@ radv_need_late_scissor_emission(struct radv_cmd_buffer *cmd_buffer, uint32_t primitive_reset_index = radv_get_primitive_reset_index(cmd_buffer); - if (info->indexed && state->pipeline->graphics.prim_restart_enable && + if (info->indexed && state->dynamic.primitive_restart_enable && primitive_reset_index != state->last_primitive_reset_index) return true; diff --git a/src/amd/vulkan/radv_meta.c b/src/amd/vulkan/radv_meta.c index 094f9fa1af1..7bc6cd3c5eb 100644 --- a/src/amd/vulkan/radv_meta.c +++ b/src/amd/vulkan/radv_meta.c @@ -93,6 +93,8 @@ radv_meta_save(struct radv_meta_saved_state *state, struct radv_cmd_buffer *cmd_ cmd_buffer->state.dynamic.fragment_shading_rate.combiner_ops[1]; state->depth_bias_enable = cmd_buffer->state.dynamic.depth_bias_enable; + + state->primitive_restart_enable = cmd_buffer->state.dynamic.primitive_restart_enable; } if (state->flags & RADV_META_SAVE_SAMPLE_LOCATIONS) { @@ -178,6 +180,8 @@ radv_meta_restore(const struct radv_meta_saved_state *state, struct radv_cmd_buf cmd_buffer->state.dynamic.depth_bias_enable = state->depth_bias_enable; + cmd_buffer->state.dynamic.primitive_restart_enable = state->primitive_restart_enable; + 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 | @@ -185,7 +189,8 @@ radv_meta_restore(const struct radv_meta_saved_state *state, struct radv_cmd_buf RADV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE | RADV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP | RADV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE | RADV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | RADV_CMD_DIRTY_DYNAMIC_STENCIL_OP | - RADV_CMD_DIRTY_DYNAMIC_FRAGMENT_SHADING_RATE | RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE; + RADV_CMD_DIRTY_DYNAMIC_FRAGMENT_SHADING_RATE | RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE | + RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE; } 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 1aa7e895992..d6519231a2b 100644 --- a/src/amd/vulkan/radv_meta.h +++ b/src/amd/vulkan/radv_meta.h @@ -92,6 +92,7 @@ struct radv_meta_saved_state { } fragment_shading_rate; bool depth_bias_enable; + bool primitive_restart_enable; }; 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 e282e1fa431..a14b8afd918 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -1382,10 +1382,12 @@ radv_pipeline_needed_dynamic_state(const VkGraphicsPipelineCreateInfo *pCreateIn /* If rasterization is disabled we do not care about any of the * dynamic states, since they are all rasterization related only, - * except primitive topology and vertex binding stride. + * except primitive topology, primitive restart enable and vertex + * binding stride. */ if (pCreateInfo->pRasterizationState->rasterizerDiscardEnable) - return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY | RADV_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE; + return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY | RADV_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE | + RADV_DYNAMIC_PRIMITIVE_RESTART_ENABLE; if (!pCreateInfo->pRasterizationState->depthBiasEnable && !radv_is_state_dynamic(pCreateInfo, VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT)) @@ -1515,7 +1517,6 @@ radv_pipeline_init_input_assembly_state(struct radv_pipeline *pipeline, struct radv_shader_variant *tes = pipeline->shaders[MESA_SHADER_TESS_EVAL]; struct radv_shader_variant *gs = pipeline->shaders[MESA_SHADER_GEOMETRY]; - pipeline->graphics.prim_restart_enable = !!ia_state->primitiveRestartEnable; pipeline->graphics.can_use_guardband = radv_prim_can_use_guardband(ia_state->topology); if (radv_pipeline_has_gs(pipeline)) { @@ -1735,6 +1736,11 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, dynamic->depth_bias_enable = pCreateInfo->pRasterizationState->depthBiasEnable; } + if (states & RADV_DYNAMIC_PRIMITIVE_RESTART_ENABLE) { + dynamic->primitive_restart_enable = + !!pCreateInfo->pInputAssemblyState->primitiveRestartEnable; + } + pipeline->dynamic_state.mask = states; } diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 7cd0493af11..87ede4c5781 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1214,6 +1214,7 @@ struct radv_dynamic_state { } fragment_shading_rate; bool depth_bias_enable; + bool primitive_restart_enable; }; extern const struct radv_dynamic_state default_dynamic_state; @@ -1490,7 +1491,8 @@ void si_write_scissors(struct radeon_cmdbuf *cs, int first, int count, const VkR const VkViewport *viewports, bool can_use_guardband); 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, unsigned topology); + uint32_t draw_vertex_count, unsigned topology, + bool prim_restart_enable); void si_cs_emit_write_event_eop(struct radeon_cmdbuf *cs, enum chip_class chip_class, bool is_mec, unsigned event, unsigned event_flags, unsigned dst_sel, unsigned data_sel, uint64_t va, uint32_t new_fence, @@ -1706,7 +1708,6 @@ struct radv_pipeline { struct radv_binning_state binning; struct radv_vrs_state vrs; uint32_t spi_baryc_cntl; - bool prim_restart_enable; unsigned esgs_ring_size; unsigned gsvs_ring_size; uint32_t vtx_base_sgpr; diff --git a/src/amd/vulkan/si_cmd_buffer.c b/src/amd/vulkan/si_cmd_buffer.c index 19dbc313adc..993f6c32861 100644 --- a/src/amd/vulkan/si_cmd_buffer.c +++ b/src/amd/vulkan/si_cmd_buffer.c @@ -792,7 +792,7 @@ static const struct radv_prim_vertex_count prim_size_table[] = { 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, unsigned topology) + uint32_t draw_vertex_count, unsigned topology, bool prim_restart_enable) { 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; @@ -831,7 +831,7 @@ si_get_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, bool instanced_dra if (cmd_buffer->device->physical_device->rad_info.max_se < 4 || topology == V_008958_DI_PT_POLYGON || topology == V_008958_DI_PT_LINELOOP || topology == V_008958_DI_PT_TRIFAN || topology == V_008958_DI_PT_TRISTRIP_ADJ || - (cmd_buffer->state.pipeline->graphics.prim_restart_enable && + (prim_restart_enable && (cmd_buffer->device->physical_device->rad_info.family < CHIP_POLARIS10 || (topology != V_008958_DI_PT_POINTLIST && topology != V_008958_DI_PT_LINESTRIP)))) wd_switch_on_eop = true; @@ -899,7 +899,7 @@ si_get_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, bool instanced_dra /* Workaround for a VGT hang when strip primitive types are used with * primitive restart. */ - if (cmd_buffer->state.pipeline->graphics.prim_restart_enable && + if (prim_restart_enable && (topology == V_008958_DI_PT_LINESTRIP || topology == V_008958_DI_PT_TRISTRIP || topology == V_008958_DI_PT_LINESTRIP_ADJ || topology == V_008958_DI_PT_TRISTRIP_ADJ)) { partial_vs_wave = true;