[Mesa-dev] [PATCH v2] radv: Disable primitive restart for non-indexed draws

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Wed Apr 12 19:00:00 UTC 2017


Thanks. Pushed.

On Wed, Apr 12, 2017 at 10:20 AM, Alex Smith
<asmith at feralinteractive.com> wrote:
> According to the Vulkan spec, VkPipelineInputAssemblyStateCreateInfo's
> primitiveRestartEnable flag should only apply to indexed draws, however
> it was being enabled regardless of the type of draw. This could cause
> problems for non-indexed draws with >=65535 vertices if the previous
> indexed draw used 16-bit indices.
>
> Fixes corruption of the credits text in Mad Max.
>
> v2: Reset primitive restart state after executing a secondary command
>     buffer.
>
> Signed-off-by: Alex Smith <asmith at feralinteractive.com>
> Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
> ---
>  src/amd/vulkan/radv_cmd_buffer.c | 55 ++++++++++++++++++++++++----------------
>  src/amd/vulkan/radv_private.h    |  1 +
>  2 files changed, 34 insertions(+), 22 deletions(-)
>
> diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c
> index dbe8bf1..998b656 100644
> --- a/src/amd/vulkan/radv_cmd_buffer.c
> +++ b/src/amd/vulkan/radv_cmd_buffer.c
> @@ -855,9 +855,6 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer,
>         radv_emit_fragment_shader(cmd_buffer, pipeline);
>         polaris_set_vgt_vertex_reuse(cmd_buffer, pipeline);
>
> -       radeon_set_context_reg(cmd_buffer->cs, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN,
> -                              pipeline->graphics.prim_restart_enable);
> -
>         cmd_buffer->scratch_size_needed =
>                                   MAX2(cmd_buffer->scratch_size_needed,
>                                        pipeline->max_waves * pipeline->scratch_bytes_per_wave);
> @@ -1394,9 +1391,32 @@ radv_flush_constants(struct radv_cmd_buffer *cmd_buffer,
>         cmd_buffer->push_constant_stages &= ~stages;
>  }
>
> +static void radv_emit_primitive_reset_state(struct radv_cmd_buffer *cmd_buffer,
> +                                           bool indexed_draw)
> +{
> +       int32_t primitive_reset_en = indexed_draw && cmd_buffer->state.pipeline->graphics.prim_restart_enable;
> +
> +       if (primitive_reset_en != cmd_buffer->state.last_primitive_reset_en) {
> +               cmd_buffer->state.last_primitive_reset_en = primitive_reset_en;
> +               radeon_set_context_reg(cmd_buffer->cs, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN,
> +                                      primitive_reset_en);
> +       }
> +
> +       if (primitive_reset_en) {
> +               uint32_t primitive_reset_index = cmd_buffer->state.index_type ? 0xffffffffu : 0xffffu;
> +
> +               if (primitive_reset_index != cmd_buffer->state.last_primitive_reset_index) {
> +                       cmd_buffer->state.last_primitive_reset_index = primitive_reset_index;
> +                       radeon_set_context_reg(cmd_buffer->cs, R_02840C_VGT_MULTI_PRIM_IB_RESET_INDX,
> +                                              primitive_reset_index);
> +               }
> +       }
> +}
> +
>  static void
>  radv_cmd_buffer_flush_state(struct radv_cmd_buffer *cmd_buffer,
> -                           bool instanced_draw, bool indirect_draw,
> +                           bool indexed_draw, bool instanced_draw,
> +                           bool indirect_draw,
>                             uint32_t draw_vertex_count)
>  {
>         struct radv_pipeline *pipeline = cmd_buffer->state.pipeline;
> @@ -1482,6 +1502,8 @@ radv_cmd_buffer_flush_state(struct radv_cmd_buffer *cmd_buffer,
>
>         radv_cmd_buffer_flush_dynamic_state(cmd_buffer);
>
> +       radv_emit_primitive_reset_state(cmd_buffer, indexed_draw);
> +
>         radv_flush_descriptors(cmd_buffer, cmd_buffer->state.pipeline,
>                                VK_SHADER_STAGE_ALL_GRAPHICS);
>         radv_flush_constants(cmd_buffer, cmd_buffer->state.pipeline,
> @@ -1802,6 +1824,7 @@ VkResult radv_BeginCommandBuffer(
>         radv_reset_cmd_buffer(cmd_buffer);
>
>         memset(&cmd_buffer->state, 0, sizeof(cmd_buffer->state));
> +       cmd_buffer->state.last_primitive_reset_en = -1;
>
>         /* setup initial configuration into command buffer */
>         if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
> @@ -2309,6 +2332,8 @@ void radv_CmdExecuteCommands(
>                 primary->state.emitted_compute_pipeline = NULL;
>                 primary->state.dirty |= RADV_CMD_DIRTY_PIPELINE;
>                 primary->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_ALL;
> +               primary->state.last_primitive_reset_en = -1;
> +               primary->state.last_primitive_reset_index = 0;
>         }
>  }
>
> @@ -2444,7 +2469,7 @@ void radv_CmdDraw(
>  {
>         RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
>
> -       radv_cmd_buffer_flush_state(cmd_buffer, (instanceCount > 1), false, vertexCount);
> +       radv_cmd_buffer_flush_state(cmd_buffer, false, (instanceCount > 1), false, vertexCount);
>
>         MAYBE_UNUSED unsigned cdw_max = radeon_check_space(cmd_buffer->device->ws, cmd_buffer->cs, 10);
>
> @@ -2471,18 +2496,6 @@ void radv_CmdDraw(
>         radv_cmd_buffer_trace_emit(cmd_buffer);
>  }
>
> -static void radv_emit_primitive_reset_index(struct radv_cmd_buffer *cmd_buffer)
> -{
> -       uint32_t primitive_reset_index = cmd_buffer->state.index_type ? 0xffffffffu : 0xffffu;
> -
> -       if (cmd_buffer->state.pipeline->graphics.prim_restart_enable &&
> -           primitive_reset_index != cmd_buffer->state.last_primitive_reset_index) {
> -               cmd_buffer->state.last_primitive_reset_index = primitive_reset_index;
> -               radeon_set_context_reg(cmd_buffer->cs, R_02840C_VGT_MULTI_PRIM_IB_RESET_INDX,
> -                                      primitive_reset_index);
> -       }
> -}
> -
>  void radv_CmdDrawIndexed(
>         VkCommandBuffer                             commandBuffer,
>         uint32_t                                    indexCount,
> @@ -2496,8 +2509,7 @@ void radv_CmdDrawIndexed(
>         uint32_t index_max_size = (cmd_buffer->state.index_buffer->size - cmd_buffer->state.index_offset) / index_size;
>         uint64_t index_va;
>
> -       radv_cmd_buffer_flush_state(cmd_buffer, (instanceCount > 1), false, indexCount);
> -       radv_emit_primitive_reset_index(cmd_buffer);
> +       radv_cmd_buffer_flush_state(cmd_buffer, true, (instanceCount > 1), false, indexCount);
>
>         MAYBE_UNUSED unsigned cdw_max = radeon_check_space(cmd_buffer->device->ws, cmd_buffer->cs, 15);
>
> @@ -2596,7 +2608,7 @@ radv_cmd_draw_indirect_count(VkCommandBuffer                             command
>                               uint32_t                                    stride)
>  {
>         RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
> -       radv_cmd_buffer_flush_state(cmd_buffer, false, true, 0);
> +       radv_cmd_buffer_flush_state(cmd_buffer, false, false, true, 0);
>
>         MAYBE_UNUSED unsigned cdw_max = radeon_check_space(cmd_buffer->device->ws,
>                                                            cmd_buffer->cs, 14);
> @@ -2621,8 +2633,7 @@ radv_cmd_draw_indexed_indirect_count(
>         int index_size = cmd_buffer->state.index_type ? 4 : 2;
>         uint32_t index_max_size = (cmd_buffer->state.index_buffer->size - cmd_buffer->state.index_offset) / index_size;
>         uint64_t index_va;
> -       radv_cmd_buffer_flush_state(cmd_buffer, false, true, 0);
> -       radv_emit_primitive_reset_index(cmd_buffer);
> +       radv_cmd_buffer_flush_state(cmd_buffer, true, false, true, 0);
>
>         index_va = cmd_buffer->device->ws->buffer_get_va(cmd_buffer->state.index_buffer->bo);
>         index_va += cmd_buffer->state.index_buffer->offset + cmd_buffer->state.index_offset;
> diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
> index 719cc02..00190e7 100644
> --- a/src/amd/vulkan/radv_private.h
> +++ b/src/amd/vulkan/radv_private.h
> @@ -744,6 +744,7 @@ struct radv_cmd_state {
>         struct radv_buffer *                         index_buffer;
>         uint32_t                                     index_type;
>         uint32_t                                     index_offset;
> +       int32_t                                      last_primitive_reset_en;
>         uint32_t                                     last_primitive_reset_index;
>         enum radv_cmd_flush_bits                     flush_bits;
>         unsigned                                     active_occlusion_queries;
> --
> 2.9.3
>


More information about the mesa-dev mailing list