Mesa (master): radv: add support for dynamic primitive topology

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jul 13 08:45:58 UTC 2020


Module: Mesa
Branch: master
Commit: d6c1e5051eb93ce05fe44f64c1772159b3a3f318
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d6c1e5051eb93ce05fe44f64c1772159b3a3f318

Author: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Date:   Mon Apr 13 13:14:59 2020 +0200

radv: add support for dynamic primitive topology

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5718>

---

 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];
 



More information about the mesa-commit mailing list