From 5edaf081cdbdadfd027c2ba9ee5095f49b274f81 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 1 Jul 2020 15:57:43 -0400 Subject: [PATCH] zink: basic primitive restart support for strip/fan topologies this conditionally handles rewriting the index buffer to use vk-compatible restart indexes and then enables it in the pipeline for supported draw modes fixes #3174 Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/zink/zink_draw.c | 35 +++++++++++++++++++++++--------- src/gallium/drivers/zink/zink_pipeline.c | 15 +++++++++++++- src/gallium/drivers/zink/zink_pipeline.h | 2 ++ 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c index a9d6bcb..32a1ea2 100644 --- a/src/gallium/drivers/zink/zink_draw.c +++ b/src/gallium/drivers/zink/zink_draw.c @@ -11,6 +11,7 @@ #include "util/u_helpers.h" #include "util/u_inlines.h" #include "util/u_prim.h" +#include "util/u_prim_restart.h" static VkDescriptorSet allocate_descriptor_set(struct zink_screen *screen, @@ -206,6 +207,7 @@ zink_draw_vbo(struct pipe_context *pctx, struct zink_so_target *so_target = zink_so_target(dinfo->count_from_stream_output); VkBuffer counter_buffers[PIPE_MAX_SO_OUTPUTS]; VkDeviceSize counter_buffer_offsets[PIPE_MAX_SO_OUTPUTS] = {}; + bool need_index_buffer_unref = false; if (dinfo->mode >= PIPE_PRIM_QUADS || dinfo->mode == PIPE_PRIM_LINE_LOOP || @@ -222,6 +224,9 @@ zink_draw_vbo(struct pipe_context *pctx, if (!gfx_program) return; + /* this is broken for anything requiring primconvert atm */ + ctx->gfx_pipeline_state.primitive_restart = !!dinfo->primitive_restart; + VkPipeline pipeline = zink_get_gfx_pipeline(screen, gfx_program, &ctx->gfx_pipeline_state, dinfo->mode); @@ -249,13 +254,19 @@ zink_draw_vbo(struct pipe_context *pctx, unsigned index_offset = 0; struct pipe_resource *index_buffer = NULL; if (dinfo->index_size > 0) { - if (dinfo->has_user_indices) { - if (!util_upload_index_buffer(pctx, dinfo, &index_buffer, &index_offset, 4)) { - debug_printf("util_upload_index_buffer() failed\n"); - return; - } - } else - index_buffer = dinfo->index.resource; + uint32_t restart_index = util_prim_restart_index_from_size(dinfo->index_size); + if ((dinfo->primitive_restart && (dinfo->restart_index != restart_index))) { + util_translate_prim_restart_ib(pctx, dinfo, &index_buffer); + need_index_buffer_unref = true; + } else { + if (dinfo->has_user_indices) { + if (!util_upload_index_buffer(pctx, dinfo, &index_buffer, &index_offset, 4)) { + debug_printf("util_upload_index_buffer() failed\n"); + return; + } + } else + index_buffer = dinfo->index.resource; + } } VkWriteDescriptorSet wds[PIPE_SHADER_TYPES * PIPE_MAX_CONSTANT_BUFFERS + PIPE_SHADER_TYPES * PIPE_MAX_SHADER_SAMPLER_VIEWS]; @@ -424,7 +435,11 @@ zink_draw_vbo(struct pipe_context *pctx, if (dinfo->index_size > 0) { VkIndexType index_type; - switch (dinfo->index_size) { + unsigned index_size = dinfo->index_size; + if (need_index_buffer_unref) + /* index buffer will have been promoted from uint8 to uint16 in this case */ + index_size = MAX2(index_size, 2); + switch (index_size) { case 1: assert(screen->have_EXT_index_type_uint8); index_type = VK_INDEX_TYPE_UINT8_EXT; @@ -443,7 +458,7 @@ zink_draw_vbo(struct pipe_context *pctx, zink_batch_reference_resoure(batch, res); vkCmdDrawIndexed(batch->cmdbuf, dinfo->count, dinfo->instance_count, - dinfo->start, dinfo->index_bias, dinfo->start_instance); + need_index_buffer_unref ? 0 : dinfo->start, dinfo->index_bias, dinfo->start_instance); } else { if (so_target && screen->tf_props.transformFeedbackDraw) { zink_batch_reference_resoure(batch, zink_resource(so_target->counter_buffer)); @@ -455,7 +470,7 @@ zink_draw_vbo(struct pipe_context *pctx, vkCmdDraw(batch->cmdbuf, dinfo->count, dinfo->instance_count, dinfo->start, dinfo->start_instance); } - if (dinfo->index_size > 0 && dinfo->has_user_indices) + if (dinfo->index_size > 0 && (dinfo->has_user_indices || need_index_buffer_unref)) pipe_resource_reference(&index_buffer, NULL); if (ctx->num_so_targets) { diff --git a/src/gallium/drivers/zink/zink_pipeline.c b/src/gallium/drivers/zink/zink_pipeline.c index 261bdde..70f859f 100644 --- a/src/gallium/drivers/zink/zink_pipeline.c +++ b/src/gallium/drivers/zink/zink_pipeline.c @@ -49,7 +49,20 @@ zink_create_gfx_pipeline(struct zink_screen *screen, VkPipelineInputAssemblyStateCreateInfo primitive_state = {}; primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; primitive_state.topology = primitive_topology; - primitive_state.primitiveRestartEnable = VK_FALSE; + switch (primitive_topology) { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: + if (state->primitive_restart) + debug_printf("restart_index set with unsupported primitive topology %u\n", primitive_topology); + primitive_state.primitiveRestartEnable = VK_FALSE; + break; + default: + primitive_state.primitiveRestartEnable = state->primitive_restart ? VK_TRUE : VK_FALSE; + } VkPipelineColorBlendStateCreateInfo blend_state = {}; blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; diff --git a/src/gallium/drivers/zink/zink_pipeline.h b/src/gallium/drivers/zink/zink_pipeline.h index d65bce2..757bae6 100644 --- a/src/gallium/drivers/zink/zink_pipeline.h +++ b/src/gallium/drivers/zink/zink_pipeline.h @@ -51,6 +51,8 @@ struct zink_gfx_pipeline_state { VkSampleMask sample_mask; uint8_t rast_samples; + + bool primitive_restart; }; VkPipeline -- 2.7.4