[Mesa-dev] [PATCH 08/12] radeonsi: use new VS blit shaders (VS inputs in SGPRs)

Marek Olšák maraeo at gmail.com
Fri Oct 6 14:10:11 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/drivers/radeonsi/si_blit.c          |  6 ++
 src/gallium/drivers/radeonsi/si_pipe.h          |  2 +
 src/gallium/drivers/radeonsi/si_state.h         |  5 ++
 src/gallium/drivers/radeonsi/si_state_draw.c    | 94 ++++++++++---------------
 src/gallium/drivers/radeonsi/si_state_shaders.c |  1 +
 5 files changed, 51 insertions(+), 57 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 4b7cca6..0a0528a 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -88,20 +88,26 @@ static void si_blitter_begin(struct pipe_context *ctx, enum si_blitter_op op)
 
 	if (op & SI_DISABLE_RENDER_COND)
 		sctx->b.render_cond_force_off = true;
 }
 
 static void si_blitter_end(struct pipe_context *ctx)
 {
 	struct si_context *sctx = (struct si_context *)ctx;
 
 	sctx->b.render_cond_force_off = false;
+
+	/* Restore shader pointers because the VS blit shader changed all
+	 * non-global VS user SGPRs. */
+	sctx->shader_pointers_dirty |= SI_VS_SHADER_POINTER_MASK;
+	sctx->vertex_buffer_pointer_dirty = true;
+	si_mark_atom_dirty(sctx, &sctx->shader_pointers.atom);
 }
 
 static unsigned u_max_sample(struct pipe_resource *r)
 {
 	return r->nr_samples ? r->nr_samples - 1 : 0;
 }
 
 static unsigned
 si_blit_dbcb_copy(struct si_context *sctx,
 		  struct r600_texture *src,
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index c45cc2d..4186c75 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -395,20 +395,22 @@ struct si_context {
 	/* other shader resources */
 	struct pipe_constant_buffer	null_const_buf; /* used for set_constant_buffer(NULL) on CIK */
 	struct pipe_resource		*esgs_ring;
 	struct pipe_resource		*gsvs_ring;
 	struct pipe_resource		*tf_ring;
 	struct pipe_resource		*tess_offchip_ring;
 	union pipe_color_union		*border_color_table; /* in CPU memory, any endian */
 	struct r600_resource		*border_color_buffer;
 	union pipe_color_union		*border_color_map; /* in VRAM (slow access), little endian */
 	unsigned			border_color_count;
+	unsigned			num_vs_blit_sgprs;
+	uint32_t			vs_blit_sh_data[SI_VS_BLIT_SGPRS_POS_TEXCOORD];
 
 	/* Vertex and index buffers. */
 	bool				vertex_buffers_dirty;
 	bool				vertex_buffer_pointer_dirty;
 	struct pipe_vertex_buffer	vertex_buffer[SI_NUM_VERTEX_BUFFERS];
 
 	/* MSAA config state. */
 	int				ps_iter_samples;
 	bool				smoothing_enabled;
 
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index fa2c147..03e2a17 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -240,20 +240,25 @@ enum {
 	SI_NUM_SHADER_DESCS,
 };
 
 #define SI_DESCS_RW_BUFFERS            0
 #define SI_DESCS_FIRST_SHADER          1
 #define SI_DESCS_FIRST_COMPUTE         (SI_DESCS_FIRST_SHADER + \
                                         PIPE_SHADER_COMPUTE * SI_NUM_SHADER_DESCS)
 #define SI_NUM_DESCS                   (SI_DESCS_FIRST_SHADER + \
                                         SI_NUM_SHADERS * SI_NUM_SHADER_DESCS)
 
+#define SI_VS_SHADER_POINTER_MASK \
+	u_bit_consecutive(SI_DESCS_FIRST_SHADER + \
+			  PIPE_SHADER_VERTEX * SI_NUM_SHADER_DESCS, \
+			  SI_NUM_SHADER_DESCS)
+
 /* This represents descriptors in memory, such as buffer resources,
  * image resources, and sampler states.
  */
 struct si_descriptors {
 	/* The list of descriptors in malloc'd memory. */
 	uint32_t *list;
 	/* The list in mapped GPU memory. */
 	uint32_t *gpu_list;
 
 	/* The buffer where the descriptors have been uploaded. */
diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c
index 9cb4274..8e54151 100644
--- a/src/gallium/drivers/radeonsi/si_state_draw.c
+++ b/src/gallium/drivers/radeonsi/si_state_draw.c
@@ -556,20 +556,26 @@ static void si_emit_rasterizer_prim_state(struct si_context *sctx)
 	sctx->last_rast_prim = rast_prim;
 	sctx->last_sc_line_stipple = rs->pa_sc_line_stipple;
 }
 
 static void si_emit_vs_state(struct si_context *sctx,
 			     const struct pipe_draw_info *info)
 {
 	sctx->current_vs_state &= C_VS_STATE_INDEXED;
 	sctx->current_vs_state |= S_VS_STATE_INDEXED(!!info->index_size);
 
+	if (sctx->num_vs_blit_sgprs) {
+		/* Re-emit the state after we leave u_blitter. */
+		sctx->last_vs_state = ~0;
+		return;
+	}
+
 	if (sctx->current_vs_state != sctx->last_vs_state) {
 		struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
 
 		radeon_set_sh_reg(cs,
 			sctx->shader_pointers.sh_base[PIPE_SHADER_VERTEX] +
 			SI_SGPR_VS_STATE_BITS * 4,
 			sctx->current_vs_state);
 
 		sctx->last_vs_state = sctx->current_vs_state;
 	}
@@ -788,25 +794,34 @@ static void si_emit_draw_packets(struct si_context *sctx,
 		}
 	} else {
 		int base_vertex;
 
 		radeon_emit(cs, PKT3(PKT3_NUM_INSTANCES, 0, 0));
 		radeon_emit(cs, info->instance_count);
 
 		/* Base vertex and start instance. */
 		base_vertex = index_size ? info->index_bias : info->start;
 
-		if (base_vertex != sctx->last_base_vertex ||
-		    sctx->last_base_vertex == SI_BASE_VERTEX_UNKNOWN ||
-		    info->start_instance != sctx->last_start_instance ||
-		    info->drawid != sctx->last_drawid ||
-		    sh_base_reg != sctx->last_sh_base_reg) {
+		if (sctx->num_vs_blit_sgprs) {
+			/* Re-emit draw constants after we leave u_blitter. */
+			si_invalidate_draw_sh_constants(sctx);
+
+			/* Blit VS doesn't use BASE_VERTEX, START_INSTANCE, and DRAWID. */
+			radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_VS_BLIT_DATA * 4,
+					      sctx->num_vs_blit_sgprs);
+			radeon_emit_array(cs, sctx->vs_blit_sh_data,
+					  sctx->num_vs_blit_sgprs);
+		} else if (base_vertex != sctx->last_base_vertex ||
+			   sctx->last_base_vertex == SI_BASE_VERTEX_UNKNOWN ||
+			   info->start_instance != sctx->last_start_instance ||
+			   info->drawid != sctx->last_drawid ||
+			   sh_base_reg != sctx->last_sh_base_reg) {
 			radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 3);
 			radeon_emit(cs, base_vertex);
 			radeon_emit(cs, info->start_instance);
 			radeon_emit(cs, info->drawid);
 
 			sctx->last_base_vertex = base_vertex;
 			sctx->last_start_instance = info->start_instance;
 			sctx->last_drawid = info->drawid;
 			sctx->last_sh_base_reg = sh_base_reg;
 		}
@@ -1494,97 +1509,62 @@ void si_draw_rectangle(struct blitter_context *blitter,
 		       void *vertex_elements_cso,
 		       blitter_get_vs_func get_vs,
 		       int x1, int y1, int x2, int y2,
 		       float depth, unsigned num_instances,
 		       enum blitter_attrib_type type,
 		       const union blitter_attrib *attrib)
 {
 	struct pipe_context *pipe = util_blitter_get_pipe(blitter);
 	struct si_context *sctx = (struct si_context*)pipe;
 	struct pipe_viewport_state viewport;
-	struct pipe_resource *buf = NULL;
-	unsigned offset = 0;
-	float *vb;
 
 	/* setup viewport */
 	viewport.scale[0] = 1.0f;
 	viewport.scale[1] = 1.0f;
 	viewport.scale[2] = 1.0f;
 	viewport.translate[0] = 0.0f;
 	viewport.translate[1] = 0.0f;
 	viewport.translate[2] = 0.0f;
 	pipe->set_viewport_states(pipe, 0, 1, &viewport);
 
-	/* Upload vertices. The hw rectangle has only 3 vertices,
-	 * The 4th one is derived from the first 3.
-	 * The vertex specification should match u_blitter's vertex element state. */
-	u_upload_alloc(pipe->stream_uploader, 0, sizeof(float) * 24,
-		       sctx->screen->b.info.tcc_cache_line_size,
-                       &offset, &buf, (void**)&vb);
-	if (!buf)
-		return;
-
-	vb[0] = x1;
-	vb[1] = y1;
-	vb[2] = depth;
-	vb[3] = 1;
-
-	vb[8] = x1;
-	vb[9] = y2;
-	vb[10] = depth;
-	vb[11] = 1;
-
-	vb[16] = x2;
-	vb[17] = y1;
-	vb[18] = depth;
-	vb[19] = 1;
+	/* Pack position coordinates as signed int16. */
+	sctx->vs_blit_sh_data[0] = (uint32_t)(x1 & 0xffff) |
+				   ((uint32_t)(y1 & 0xffff) << 16);
+	sctx->vs_blit_sh_data[1] = (uint32_t)(x2 & 0xffff) |
+				   ((uint32_t)(y2 & 0xffff) << 16);
+	sctx->vs_blit_sh_data[2] = fui(depth);
 
 	switch (type) {
 	case UTIL_BLITTER_ATTRIB_COLOR:
-		memcpy(vb+4, attrib->color, sizeof(float)*4);
-		memcpy(vb+12, attrib->color, sizeof(float)*4);
-		memcpy(vb+20, attrib->color, sizeof(float)*4);
+		memcpy(&sctx->vs_blit_sh_data[3], attrib->color,
+		       sizeof(float)*4);
 		break;
-	case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW:
 	case UTIL_BLITTER_ATTRIB_TEXCOORD_XY:
-		vb[6] = vb[14] = vb[22] = attrib->texcoord.z;
-		vb[7] = vb[15] = vb[23] = attrib->texcoord.w;
-		/* fall through */
-		vb[4] = attrib->texcoord.x1;
-		vb[5] = attrib->texcoord.y1;
-		vb[12] = attrib->texcoord.x1;
-		vb[13] = attrib->texcoord.y2;
-		vb[20] = attrib->texcoord.x2;
-		vb[21] = attrib->texcoord.y1;
+	case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW:
+		memcpy(&sctx->vs_blit_sh_data[3], &attrib->texcoord,
+		       sizeof(attrib->texcoord));
 		break;
-	default:; /* Nothing to do. */
+	case UTIL_BLITTER_ATTRIB_NONE:;
 	}
 
-	/* draw */
-	struct pipe_vertex_buffer vbuffer = {};
-	vbuffer.buffer.resource = buf;
-	vbuffer.stride = 2 * 4 * sizeof(float); /* vertex size */
-	vbuffer.buffer_offset = offset;
-
-	pipe->set_vertex_buffers(pipe, blitter->vb_slot, 1, &vbuffer);
-	pipe->bind_vs_state(pipe, get_vs(blitter));
-
-	if (sctx->vertex_elements != vertex_elements_cso)
-		pipe->bind_vertex_elements_state(pipe, vertex_elements_cso);
+	pipe->bind_vs_state(pipe, si_get_blit_vs(sctx, type, num_instances));
 
 	struct pipe_draw_info info = {};
 	info.mode = R600_PRIM_RECTANGLE_LIST;
 	info.count = 3;
 	info.instance_count = num_instances;
 
+	/* Don't set per-stage shader pointers for VS. */
+	sctx->shader_pointers_dirty &= ~SI_VS_SHADER_POINTER_MASK;
+	sctx->vertex_buffer_pointer_dirty = false;
+
 	si_draw_vbo(pipe, &info);
-	pipe_resource_reference(&buf, NULL);
 }
 
 void si_trace_emit(struct si_context *sctx)
 {
 	struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
 	uint64_t va = sctx->current_saved_cs->trace_buf->gpu_address;
 	uint32_t trace_id = ++sctx->current_saved_cs->trace_id;
 
 	radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 3, 0));
 	radeon_emit(cs, S_370_DST_SEL(V_370_MEMORY_SYNC) |
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index d3b5dd5..2e636f5 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -2299,20 +2299,21 @@ static void si_bind_vs_shader(struct pipe_context *ctx, void *state)
 	struct si_context *sctx = (struct si_context *)ctx;
 	struct si_shader_selector *old_hw_vs = si_get_vs(sctx)->cso;
 	struct si_shader *old_hw_vs_variant = si_get_vs_state(sctx);
 	struct si_shader_selector *sel = state;
 
 	if (sctx->vs_shader.cso == sel)
 		return;
 
 	sctx->vs_shader.cso = sel;
 	sctx->vs_shader.current = sel ? sel->first_variant : NULL;
+	sctx->num_vs_blit_sgprs = sel ? sel->info.properties[TGSI_PROPERTY_VS_BLIT_SGPRS] : 0;
 
 	si_update_common_shader_state(sctx);
 	si_update_vs_writes_viewport_index(sctx);
 	si_set_active_descriptors_for_shader(sctx, sel);
 	si_update_streamout_state(sctx);
 	si_update_clip_regs(sctx, old_hw_vs, old_hw_vs_variant,
 			    si_get_vs(sctx)->cso, si_get_vs_state(sctx));
 }
 
 static void si_update_tess_uses_prim_id(struct si_context *sctx)
-- 
2.7.4



More information about the mesa-dev mailing list