[Mesa-dev] [PATCH 28/30] r600: add shader state suport

Dave Airlie airlied at gmail.com
Thu Mar 31 07:03:57 UTC 2016


From: Dave Airlie <airlied at redhat.com>

---
 src/gallium/drivers/r600/evergreen_state.c | 271 ++++++++++++++++++++++++++++-
 src/gallium/drivers/r600/r600_hw_context.c |   3 +
 src/gallium/drivers/r600/r600_pipe.h       |  30 +++-
 3 files changed, 300 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index 0f68499..009adf2 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -1737,6 +1737,95 @@ static void evergreen_emit_msaa_state(struct r600_context *rctx, int nr_samples,
 	}
 }
 
+static void evergreen_emit_image_state(struct r600_context *rctx, struct r600_atom *atom)
+{
+	struct r600_image_state *state = (struct r600_image_state *)atom;
+	struct pipe_framebuffer_state *fb_state = &rctx->framebuffer.state;
+	struct radeon_winsys_cs *cs = rctx->b.gfx.cs;
+	struct r600_texture *rtex;
+	struct r600_resource *resource;
+	int i;
+	int immed_id_base = R600_IMAGE_IMMED_RESOURCE_OFFSET;
+	int res_id_base = R600_IMAGE_REAL_RESOURCE_OFFSET;
+	unsigned pkt_flags = 0;
+	for (i = 0; i < R600_MAX_IMAGES; i++) {
+		struct r600_image_view *image = &state->views[i];
+		unsigned reloc, immed_reloc;
+		int idx = fb_state->nr_cbufs + (rctx->dual_src_blend ? 1 : 0) + i;
+
+		if (!image->buffer)
+			continue;
+
+		resource = (struct r600_resource *)image->buffer;
+		if (resource->b.b.target != PIPE_BUFFER)
+			rtex = (struct r600_texture *)image->buffer;
+		else
+			rtex = NULL;
+
+		reloc = radeon_add_to_buffer_list(&rctx->b,
+						  &rctx->b.gfx,
+						  (struct r600_resource*)image->buffer,
+						  RADEON_USAGE_READWRITE,
+						  RADEON_PRIO_SHADER_RW_BUFFER);
+
+		immed_reloc = radeon_add_to_buffer_list(&rctx->b,
+							&rctx->b.gfx,
+							resource->immed_buffer,
+							RADEON_USAGE_READWRITE,
+							RADEON_PRIO_SHADER_RW_BUFFER);
+
+		radeon_set_context_reg_seq(cs, R_028C60_CB_COLOR0_BASE + idx * 0x3C, 13);
+		radeon_emit(cs, image->cb_color_base);	/* R_028C60_CB_COLOR0_BASE */
+		radeon_emit(cs, image->cb_color_pitch);	/* R_028C64_CB_COLOR0_PITCH */
+		radeon_emit(cs, image->cb_color_slice);	/* R_028C68_CB_COLOR0_SLICE */
+		radeon_emit(cs, image->cb_color_view);	/* R_028C6C_CB_COLOR0_VIEW */
+		radeon_emit(cs, image->cb_color_info); /* R_028C70_CB_COLOR0_INFO */
+		radeon_emit(cs, image->cb_color_attrib);	/* R_028C74_CB_COLOR0_ATTRIB */
+		radeon_emit(cs, image->cb_color_dim);		/* R_028C78_CB_COLOR0_DIM */
+		radeon_emit(cs, rtex ? rtex->cmask.base_address_reg : image->cb_color_base);	/* R_028C7C_CB_COLOR0_CMASK */
+		radeon_emit(cs, rtex ? rtex->cmask.slice_tile_max : 0);	/* R_028C80_CB_COLOR0_CMASK_SLICE */
+		radeon_emit(cs, image->cb_color_fmask);	/* R_028C84_CB_COLOR0_FMASK */
+		radeon_emit(cs, image->cb_color_fmask_slice); /* R_028C88_CB_COLOR0_FMASK_SLICE */
+		radeon_emit(cs, rtex ? rtex->color_clear_value[0] : 0); /* R_028C8C_CB_COLOR0_CLEAR_WORD0 */
+		radeon_emit(cs, rtex ? rtex->color_clear_value[1] : 0); /* R_028C90_CB_COLOR0_CLEAR_WORD1 */
+
+		radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); /* R_028C60_CB_COLOR0_BASE */
+		radeon_emit(cs, reloc);
+
+		radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); /* R_028C74_CB_COLOR0_ATTRIB */
+		radeon_emit(cs, reloc);
+
+		radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); /* R_028C7C_CB_COLOR0_CMASK */
+		radeon_emit(cs, reloc);
+
+		radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); /* R_028C84_CB_COLOR0_FMASK */
+		radeon_emit(cs, reloc);
+
+		radeon_set_context_reg(cs, R_028B9C_CB_IMMED0_BASE + (idx * 4), 0);
+		radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); /**/
+		radeon_emit(cs, immed_reloc);
+
+		radeon_emit(cs, PKT3(PKT3_SET_RESOURCE, 8, 0) | pkt_flags);
+		radeon_emit(cs, (immed_id_base + i) * 8);
+		radeon_emit_array(cs, image->immed_resource_words, 8);
+
+		radeon_emit(cs, PKT3(PKT3_NOP, 0, 0) | pkt_flags);
+		radeon_emit(cs, immed_reloc);
+
+		radeon_emit(cs, PKT3(PKT3_SET_RESOURCE, 8, 0) | pkt_flags);
+		radeon_emit(cs, (res_id_base + i) * 8);
+		radeon_emit_array(cs, image->resource_words, 8);
+
+		radeon_emit(cs, PKT3(PKT3_NOP, 0, 0) | pkt_flags);
+		radeon_emit(cs, reloc);
+
+		if (!image->skip_mip_address_reloc) {
+			radeon_emit(cs, PKT3(PKT3_NOP, 0, 0) | pkt_flags);
+			radeon_emit(cs, reloc);
+		}
+	}
+}
+
 static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r600_atom *atom)
 {
 	struct radeon_winsys_cs *cs = rctx->b.gfx.cs;
@@ -1812,6 +1901,8 @@ static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r
 				       cb->cb_color_info | tex->cb_color_info);
 		i++;
 	}
+
+	i += util_bitcount(rctx->fragment_images.enabled_mask);
 	for (; i < 8 ; i++)
 		radeon_set_context_reg(cs, R_028C70_CB_COLOR0_INFO + i * 0x3C, 0);
 	for (; i < 12; i++)
@@ -1909,9 +2000,9 @@ static void evergreen_emit_cb_misc_state(struct r600_context *rctx, struct r600_
 	struct r600_cb_misc_state *a = (struct r600_cb_misc_state*)atom;
 	unsigned fb_colormask = (1ULL << ((unsigned)a->nr_cbufs * 4)) - 1;
 	unsigned ps_colormask = (1ULL << ((unsigned)a->nr_ps_color_outputs * 4)) - 1;
-
+	unsigned rat_colormask = ((1ULL << ((unsigned)a->nr_rats * 4)) - 1) << (a->nr_cbufs * 4);
 	radeon_set_context_reg_seq(cs, R_028238_CB_TARGET_MASK, 2);
-	radeon_emit(cs, a->blend_colormask & fb_colormask); /* R_028238_CB_TARGET_MASK */
+	radeon_emit(cs, (a->blend_colormask & fb_colormask) | rat_colormask); /* R_028238_CB_TARGET_MASK */
 	/* This must match the used export instructions exactly.
 	 * Other values may lead to undefined behavior and hangs.
 	 */
@@ -3784,6 +3875,179 @@ static void evergreen_set_tess_state(struct pipe_context *ctx,
 	rctx->tess_state_dirty = true;
 }
 
+static void evergreen_set_shader_images(struct pipe_context *ctx,
+					unsigned shader, unsigned start_slot,
+					unsigned count,
+					struct pipe_image_view *images)
+{
+	struct r600_context *rctx = (struct r600_context *)ctx;
+	struct r600_screen *rscreen = (struct r600_screen *)ctx->screen;
+	int i;
+	struct r600_image_view *rview;
+	struct pipe_resource *image;
+	struct r600_resource *resource;
+	struct r600_tex_color_info color;
+	struct eg_buf_res_params buf_params;
+	struct eg_tex_res_params tex_params;
+	unsigned old_mask;
+	bool skip_reloc = false;
+
+	if (shader != PIPE_SHADER_FRAGMENT && count == 0)
+		return;
+
+	assert (shader == PIPE_SHADER_FRAGMENT);
+	old_mask = rctx->fragment_images.enabled_mask;
+	for (i = start_slot; i < start_slot + count; i++) {
+		unsigned res_type;
+		struct pipe_image_view *iview;
+		rview = &rctx->fragment_images.views[i];
+
+		if (!images || !images[i].resource) {
+			pipe_resource_reference((struct pipe_resource **)&rview->buffer, NULL);
+			rctx->fragment_images.enabled_mask &= ~(1 << i);
+			continue;
+		}
+
+		iview = &images[i];
+		image = iview->resource;
+		resource = (struct r600_resource *)image;
+
+		r600_context_add_resource_size(ctx, images[i].resource);
+		pipe_resource_reference((struct pipe_resource **)&rview->buffer, images[i].resource);
+
+		if (!resource->immed_buffer) {
+			int immed_size = (rscreen->b.info.max_se * 256 * 64) * util_format_get_blocksize(iview->format);
+
+			eg_resource_alloc_immed(&rscreen->b, resource, immed_size);
+		}
+
+		if (image->target != PIPE_BUFFER) {
+			struct r600_texture *rtex = (struct r600_texture *)image;
+
+			evergreen_set_color_surface_common(rctx, rtex,
+							   iview->u.tex.level,
+							   iview->u.tex.first_layer,
+							   iview->u.tex.last_layer,
+							   images[i].format,
+							   &color);
+			color.dim = S_028C78_WIDTH_MAX(u_minify(image->width0, iview->u.tex.level) - 1) |
+			  S_028C78_HEIGHT_MAX(u_minify(image->height0, iview->u.tex.level) - 1);
+		} else {
+			color.offset = 0;
+			color.view = 0;
+			evergreen_set_color_surface_buffer(rctx, resource,
+							   iview->format,
+							   iview->u.buf.first_element,
+							   iview->u.buf.last_element,
+							   &color);
+		}
+
+		switch (image->target) {
+		case PIPE_BUFFER:
+			res_type = V_028C70_BUFFER;
+			break;
+		case PIPE_TEXTURE_1D:
+			res_type = V_028C70_TEXTURE1D;
+			break;
+		case PIPE_TEXTURE_1D_ARRAY:
+			res_type = V_028C70_TEXTURE1DARRAY;
+			break;
+		case PIPE_TEXTURE_2D:
+		case PIPE_TEXTURE_RECT:
+			res_type = V_028C70_TEXTURE2D;
+			break;
+		case PIPE_TEXTURE_3D:
+			res_type = V_028C70_TEXTURE3D;
+			break;
+		case PIPE_TEXTURE_2D_ARRAY:
+		case PIPE_TEXTURE_CUBE:
+		case PIPE_TEXTURE_CUBE_ARRAY:
+			res_type = V_028C70_TEXTURE2DARRAY;
+			break;
+		default:
+			assert(0);
+			res_type = 0;
+			break;
+		}
+
+		rview->cb_color_base = color.offset;
+		rview->cb_color_dim = color.dim;
+		rview->cb_color_info = color.info |
+			S_028C70_RAT(1) |
+			S_028C70_RESOURCE_TYPE(res_type);
+		rview->cb_color_pitch = color.pitch;
+		rview->cb_color_slice = color.slice;
+		rview->cb_color_view = color.view;
+		rview->cb_color_attrib = color.attrib;
+		rview->cb_color_fmask = color.fmask;
+		rview->cb_color_fmask_slice = color.fmask_slice;
+
+		memset(&buf_params, 0, sizeof(buf_params));
+		buf_params.pipe_format = iview->format;
+		buf_params.last_element = resource->immed_buffer->b.b.width0 / util_format_get_blocksize(iview->format) - 1;
+		buf_params.swizzle[0] = PIPE_SWIZZLE_RED;
+		buf_params.swizzle[1] = PIPE_SWIZZLE_GREEN;
+		buf_params.swizzle[2] = PIPE_SWIZZLE_BLUE;
+		buf_params.swizzle[3] = PIPE_SWIZZLE_ALPHA;
+		buf_params.uncached = 1;
+		evergreen_fill_buffer_resource_words(rctx, &resource->immed_buffer->b.b,
+						     &buf_params, &skip_reloc,
+						     rview->immed_resource_words);
+
+
+		if (image->target != PIPE_BUFFER) {
+			memset(&tex_params, 0, sizeof(tex_params));
+			tex_params.pipe_format = iview->format;
+			tex_params.force_level = 0;
+			tex_params.width0 = image->width0;
+			tex_params.height0 = image->height0;
+			tex_params.first_level = iview->u.tex.level;
+			tex_params.last_level = iview->u.tex.level;
+			tex_params.first_layer = iview->u.tex.first_layer;
+			tex_params.last_layer = iview->u.tex.last_layer;
+			tex_params.target = image->target;
+			tex_params.swizzle[0] = PIPE_SWIZZLE_RED;
+			tex_params.swizzle[1] = PIPE_SWIZZLE_GREEN;
+			tex_params.swizzle[2] = PIPE_SWIZZLE_BLUE;
+			tex_params.swizzle[3] = PIPE_SWIZZLE_ALPHA;
+			evergreen_fill_tex_resource_words(rctx, &resource->b.b, &tex_params,
+							  &rview->skip_mip_address_reloc,
+							  rview->resource_words);
+
+		} else {
+			memset(&buf_params, 0, sizeof(buf_params));
+			buf_params.pipe_format = iview->format;
+			buf_params.last_element = iview->u.buf.last_element;
+			buf_params.first_element = iview->u.buf.first_element;
+			buf_params.swizzle[0] = PIPE_SWIZZLE_RED;
+			buf_params.swizzle[1] = PIPE_SWIZZLE_GREEN;
+			buf_params.swizzle[2] = PIPE_SWIZZLE_BLUE;
+			buf_params.swizzle[3] = PIPE_SWIZZLE_ALPHA;
+			evergreen_fill_buffer_resource_words(rctx, &resource->b.b,
+							     &buf_params,
+							     &rview->skip_mip_address_reloc,
+							     rview->resource_words);
+		}
+		rctx->fragment_images.enabled_mask |= (1 << i);
+	}
+
+	rctx->fragment_images.atom.num_dw = util_bitcount(rctx->fragment_images.enabled_mask) * 36;
+
+	rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE | R600_CONTEXT_FLUSH_AND_INV;
+	rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV_CB |
+		R600_CONTEXT_FLUSH_AND_INV_CB_META;
+
+	if (old_mask != rctx->fragment_images.enabled_mask)
+		r600_mark_atom_dirty(rctx, &rctx->framebuffer.atom);
+
+	if (rctx->cb_misc_state.nr_rats != util_bitcount(rctx->fragment_images.enabled_mask)) {
+		rctx->cb_misc_state.nr_rats = util_bitcount(rctx->fragment_images.enabled_mask);
+		r600_mark_atom_dirty(rctx, &rctx->cb_misc_state.atom);
+	}
+
+	r600_mark_atom_dirty(rctx, &rctx->fragment_images.atom);
+}
+
 void evergreen_init_state_functions(struct r600_context *rctx)
 {
 	unsigned id = 1;
@@ -3802,6 +4066,7 @@ void evergreen_init_state_functions(struct r600_context *rctx)
 		rctx->config_state.dyn_gpr_enabled = true;
 	}
 	r600_init_atom(rctx, &rctx->framebuffer.atom, id++, evergreen_emit_framebuffer_state, 0);
+	r600_init_atom(rctx, &rctx->fragment_images.atom, id++, evergreen_emit_image_state, 0);
 	/* shader const */
 	r600_init_atom(rctx, &rctx->constbuf_state[PIPE_SHADER_VERTEX].atom, id++, evergreen_emit_vs_constant_buffers, 0);
 	r600_init_atom(rctx, &rctx->constbuf_state[PIPE_SHADER_GEOMETRY].atom, id++, evergreen_emit_gs_constant_buffers, 0);
@@ -3870,6 +4135,8 @@ void evergreen_init_state_functions(struct r600_context *rctx)
 	rctx->b.b.set_min_samples = evergreen_set_min_samples;
 	rctx->b.b.set_scissor_states = evergreen_set_scissor_states;
 	rctx->b.b.set_tess_state = evergreen_set_tess_state;
+	rctx->b.b.set_shader_images = evergreen_set_shader_images;
+
 	if (rctx->b.chip_class == EVERGREEN)
                 rctx->b.b.get_sample_position = evergreen_get_sample_position;
         else
diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
index 7a6f957..0cbe809 100644
--- a/src/gallium/drivers/r600/r600_hw_context.c
+++ b/src/gallium/drivers/r600/r600_hw_context.c
@@ -291,6 +291,9 @@ void r600_begin_new_cs(struct r600_context *ctx)
 	r600_mark_atom_dirty(ctx, &ctx->db_misc_state.atom);
 	r600_mark_atom_dirty(ctx, &ctx->db_state.atom);
 	r600_mark_atom_dirty(ctx, &ctx->framebuffer.atom);
+	if (ctx->b.chip_class >= EVERGREEN) {
+		r600_mark_atom_dirty(ctx, &ctx->fragment_images.atom);
+	}
 	r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_PS].atom);
 	r600_mark_atom_dirty(ctx, &ctx->poly_offset_state.atom);
 	r600_mark_atom_dirty(ctx, &ctx->vgt_state.atom);
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 9133698..a83d125 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -36,10 +36,10 @@
 
 #include "tgsi/tgsi_scan.h"
 
-#define R600_NUM_ATOMS 52
+#define R600_NUM_ATOMS 53
 
 #define R600_MAX_VIEWPORTS 16
-
+#define R600_MAX_IMAGES 8
 /*
  * ranges reserved for images on evergreen
  * first set for the immediate buffers,
@@ -146,6 +146,7 @@ struct r600_cb_misc_state {
 	unsigned blend_colormask; /* 8*4 bits for 8 RGBA colorbuffers */
 	unsigned nr_cbufs;
 	unsigned nr_ps_color_outputs;
+	unsigned nr_rats;
 	bool multiwrite;
 	bool dual_src_blend;
 };
@@ -439,6 +440,29 @@ struct r600_shader_state {
 	struct r600_pipe_shader *shader;
 };
 
+struct r600_image_view {
+	struct r600_resource *buffer;
+	uint32_t cb_color_base;
+	uint32_t cb_color_pitch;
+	uint32_t cb_color_slice;
+	uint32_t cb_color_view;
+	uint32_t cb_color_info;
+	uint32_t cb_color_attrib;
+	uint32_t cb_color_dim;
+	uint32_t cb_color_fmask;
+	uint32_t cb_color_fmask_slice;
+	uint32_t immed_resource_words[8];
+	uint32_t resource_words[8];
+	bool skip_mip_address_reloc;
+};
+
+struct r600_image_state {
+	struct r600_atom atom;
+	uint32_t                        enabled_mask;
+	uint32_t                        dirty_mask;
+	struct r600_image_view views[R600_MAX_IMAGES];
+};
+
 struct r600_context {
 	struct r600_common_context	b;
 	struct r600_screen		*screen;
@@ -495,6 +519,8 @@ struct r600_context {
 	struct r600_stencil_ref_state	stencil_ref;
 	struct r600_vgt_state		vgt_state;
 	struct r600_viewport_state	viewport;
+	/* only have images on fragment shader */
+	struct r600_image_state         fragment_images;
 	/* Shaders and shader resources. */
 	struct r600_cso_state		vertex_fetch_shader;
 	struct r600_shader_state        hw_shader_stages[EG_NUM_HW_STAGES];
-- 
2.5.0



More information about the mesa-dev mailing list