Home | History | Annotate | Download | only in radeonsi
      1 /*
      2  * Copyright 2012 Advanced Micro Devices, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *      Christian Knig <christian.koenig (at) amd.com>
     25  */
     26 
     27 #include "radeonsi_pipe.h"
     28 #include "si_state.h"
     29 
     30 /*
     31  * Stream out
     32  */
     33 
     34 #if 0
     35 void si_context_streamout_begin(struct r600_context *ctx)
     36 {
     37 	struct radeon_winsys_cs *cs = ctx->cs;
     38 	struct si_so_target **t = ctx->so_targets;
     39 	unsigned *strides = ctx->vs_shader_so_strides;
     40 	unsigned buffer_en, i;
     41 
     42 	buffer_en = (ctx->num_so_targets >= 1 && t[0] ? 1 : 0) |
     43 		    (ctx->num_so_targets >= 2 && t[1] ? 2 : 0) |
     44 		    (ctx->num_so_targets >= 3 && t[2] ? 4 : 0) |
     45 		    (ctx->num_so_targets >= 4 && t[3] ? 8 : 0);
     46 
     47 	ctx->num_cs_dw_streamout_end =
     48 		12 + /* flush_vgt_streamout */
     49 		util_bitcount(buffer_en) * 8 +
     50 		3;
     51 
     52 	si_need_cs_space(ctx,
     53 			   12 + /* flush_vgt_streamout */
     54 			   6 + /* enables */
     55 			   util_bitcount(buffer_en & ctx->streamout_append_bitmask) * 8 +
     56 			   util_bitcount(buffer_en & ~ctx->streamout_append_bitmask) * 6 +
     57 			   ctx->num_cs_dw_streamout_end, TRUE);
     58 
     59 	if (ctx->chip_class >= CAYMAN) {
     60 		evergreen_flush_vgt_streamout(ctx);
     61 		evergreen_set_streamout_enable(ctx, buffer_en);
     62 	}
     63 
     64 	for (i = 0; i < ctx->num_so_targets; i++) {
     65 #if 0
     66 		if (t[i]) {
     67 			t[i]->stride = strides[i];
     68 			t[i]->so_index = i;
     69 
     70 			cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 3, 0);
     71 			cs->buf[cs->cdw++] = (R_028AD0_VGT_STRMOUT_BUFFER_SIZE_0 +
     72 							16*i - SI_CONTEXT_REG_OFFSET) >> 2;
     73 			cs->buf[cs->cdw++] = (t[i]->b.buffer_offset +
     74 							t[i]->b.buffer_size) >> 2; /* BUFFER_SIZE (in DW) */
     75 			cs->buf[cs->cdw++] = strides[i] >> 2;		   /* VTX_STRIDE (in DW) */
     76 			cs->buf[cs->cdw++] = 0;			   /* BUFFER_BASE */
     77 
     78 			cs->buf[cs->cdw++] = PKT3(PKT3_NOP, 0, 0);
     79 			cs->buf[cs->cdw++] =
     80 				si_context_bo_reloc(ctx, si_resource(t[i]->b.buffer),
     81 						      RADEON_USAGE_WRITE);
     82 
     83 			if (ctx->streamout_append_bitmask & (1 << i)) {
     84 				/* Append. */
     85 				cs->buf[cs->cdw++] = PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0);
     86 				cs->buf[cs->cdw++] = STRMOUT_SELECT_BUFFER(i) |
     87 							       STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_FROM_MEM); /* control */
     88 				cs->buf[cs->cdw++] = 0; /* unused */
     89 				cs->buf[cs->cdw++] = 0; /* unused */
     90 				cs->buf[cs->cdw++] = 0; /* src address lo */
     91 				cs->buf[cs->cdw++] = 0; /* src address hi */
     92 
     93 				cs->buf[cs->cdw++] = PKT3(PKT3_NOP, 0, 0);
     94 				cs->buf[cs->cdw++] =
     95 					si_context_bo_reloc(ctx,  t[i]->filled_size,
     96 							      RADEON_USAGE_READ);
     97 			} else {
     98 				/* Start from the beginning. */
     99 				cs->buf[cs->cdw++] = PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0);
    100 				cs->buf[cs->cdw++] = STRMOUT_SELECT_BUFFER(i) |
    101 							       STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_FROM_PACKET); /* control */
    102 				cs->buf[cs->cdw++] = 0; /* unused */
    103 				cs->buf[cs->cdw++] = 0; /* unused */
    104 				cs->buf[cs->cdw++] = t[i]->b.buffer_offset >> 2; /* buffer offset in DW */
    105 				cs->buf[cs->cdw++] = 0; /* unused */
    106 			}
    107 		}
    108 #endif
    109 	}
    110 }
    111 
    112 void si_context_streamout_end(struct r600_context *ctx)
    113 {
    114 	struct radeon_winsys_cs *cs = ctx->cs;
    115 	struct si_so_target **t = ctx->so_targets;
    116 	unsigned i, flush_flags = 0;
    117 
    118 	evergreen_flush_vgt_streamout(ctx);
    119 
    120 	for (i = 0; i < ctx->num_so_targets; i++) {
    121 #if 0
    122 		if (t[i]) {
    123 			cs->buf[cs->cdw++] = PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0);
    124 			cs->buf[cs->cdw++] = STRMOUT_SELECT_BUFFER(i) |
    125 						       STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_NONE) |
    126 						       STRMOUT_STORE_BUFFER_FILLED_SIZE; /* control */
    127 			cs->buf[cs->cdw++] = 0; /* dst address lo */
    128 			cs->buf[cs->cdw++] = 0; /* dst address hi */
    129 			cs->buf[cs->cdw++] = 0; /* unused */
    130 			cs->buf[cs->cdw++] = 0; /* unused */
    131 
    132 			cs->buf[cs->cdw++] = PKT3(PKT3_NOP, 0, 0);
    133 			cs->buf[cs->cdw++] =
    134 				si_context_bo_reloc(ctx,  t[i]->filled_size,
    135 						      RADEON_USAGE_WRITE);
    136 
    137 			flush_flags |= S_0085F0_SO0_DEST_BASE_ENA(1) << i;
    138 		}
    139 #endif
    140 	}
    141 
    142 	evergreen_set_streamout_enable(ctx, 0);
    143 
    144 	ctx->atom_surface_sync.flush_flags |= flush_flags;
    145 	si_atom_dirty(ctx, &ctx->atom_surface_sync.atom);
    146 
    147 	ctx->num_cs_dw_streamout_end = 0;
    148 
    149 	/* XXX print some debug info */
    150 	for (i = 0; i < ctx->num_so_targets; i++) {
    151 		if (!t[i])
    152 			continue;
    153 
    154 		uint32_t *ptr = ctx->ws->buffer_map(t[i]->filled_size->cs_buf, ctx->cs, RADEON_USAGE_READ);
    155 		printf("FILLED_SIZE%i: %u\n", i, *ptr);
    156 		ctx->ws->buffer_unmap(t[i]->filled_size->cs_buf);
    157 	}
    158 }
    159 
    160 void evergreen_flush_vgt_streamout(struct si_context *ctx)
    161 {
    162 	struct radeon_winsys_cs *cs = ctx->cs;
    163 
    164 	cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONFIG_REG, 1, 0);
    165 	cs->buf[cs->cdw++] = (R_0084FC_CP_STRMOUT_CNTL - SI_CONFIG_REG_OFFSET) >> 2;
    166 	cs->buf[cs->cdw++] = 0;
    167 
    168 	cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 0, 0);
    169 	cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_SO_VGTSTREAMOUT_FLUSH) | EVENT_INDEX(0);
    170 
    171 	cs->buf[cs->cdw++] = PKT3(PKT3_WAIT_REG_MEM, 5, 0);
    172 	cs->buf[cs->cdw++] = WAIT_REG_MEM_EQUAL; /* wait until the register is equal to the reference value */
    173 	cs->buf[cs->cdw++] = R_0084FC_CP_STRMOUT_CNTL >> 2;  /* register */
    174 	cs->buf[cs->cdw++] = 0;
    175 	cs->buf[cs->cdw++] = S_0084FC_OFFSET_UPDATE_DONE(1); /* reference value */
    176 	cs->buf[cs->cdw++] = S_0084FC_OFFSET_UPDATE_DONE(1); /* mask */
    177 	cs->buf[cs->cdw++] = 4; /* poll interval */
    178 }
    179 
    180 void evergreen_set_streamout_enable(struct si_context *ctx, unsigned buffer_enable_bit)
    181 {
    182 	struct radeon_winsys_cs *cs = ctx->cs;
    183 
    184 	if (buffer_enable_bit) {
    185 		cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 1, 0);
    186 		cs->buf[cs->cdw++] = (R_028B94_VGT_STRMOUT_CONFIG - SI_CONTEXT_REG_OFFSET) >> 2;
    187 		cs->buf[cs->cdw++] = S_028B94_STREAMOUT_0_EN(1);
    188 
    189 		cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 1, 0);
    190 		cs->buf[cs->cdw++] = (R_028B98_VGT_STRMOUT_BUFFER_CONFIG - SI_CONTEXT_REG_OFFSET) >> 2;
    191 		cs->buf[cs->cdw++] = S_028B98_STREAM_0_BUFFER_EN(buffer_enable_bit);
    192 	} else {
    193 		cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 1, 0);
    194 		cs->buf[cs->cdw++] = (R_028B94_VGT_STRMOUT_CONFIG - SI_CONTEXT_REG_OFFSET) >> 2;
    195 		cs->buf[cs->cdw++] = S_028B94_STREAMOUT_0_EN(0);
    196 	}
    197 }
    198 
    199 #endif
    200 
    201 struct pipe_stream_output_target *
    202 si_create_so_target(struct pipe_context *ctx,
    203 		    struct pipe_resource *buffer,
    204 		    unsigned buffer_offset,
    205 		    unsigned buffer_size)
    206 {
    207 #if 0
    208 	struct si_context *rctx = (struct r600_context *)ctx;
    209 	struct si_so_target *t;
    210 	void *ptr;
    211 
    212 	t = CALLOC_STRUCT(si_so_target);
    213 	if (!t) {
    214 		return NULL;
    215 	}
    216 
    217 	t->b.reference.count = 1;
    218 	t->b.context = ctx;
    219 	pipe_resource_reference(&t->b.buffer, buffer);
    220 	t->b.buffer_offset = buffer_offset;
    221 	t->b.buffer_size = buffer_size;
    222 
    223 	t->filled_size = si_resource_create_custom(ctx->screen, PIPE_USAGE_STATIC, 4);
    224 	ptr = rctx->ws->buffer_map(t->filled_size->cs_buf, rctx->cs, PIPE_TRANSFER_WRITE);
    225 	memset(ptr, 0, t->filled_size->buf->size);
    226 	rctx->ws->buffer_unmap(t->filled_size->cs_buf);
    227 
    228 	return &t->b;
    229 #endif
    230 	return NULL;
    231 }
    232 
    233 void si_so_target_destroy(struct pipe_context *ctx,
    234 			  struct pipe_stream_output_target *target)
    235 {
    236 #if 0
    237 	struct si_so_target *t = (struct r600_so_target*)target;
    238 	pipe_resource_reference(&t->b.buffer, NULL);
    239 	si_resource_reference(&t->filled_size, NULL);
    240 	FREE(t);
    241 #endif
    242 }
    243 
    244 void si_set_so_targets(struct pipe_context *ctx,
    245 		       unsigned num_targets,
    246 		       struct pipe_stream_output_target **targets,
    247 		       unsigned append_bitmask)
    248 {
    249 	assert(num_targets == 0);
    250 #if 0
    251 	struct si_context *rctx = (struct r600_context *)ctx;
    252 	unsigned i;
    253 
    254 	/* Stop streamout. */
    255 	if (rctx->num_so_targets) {
    256 		si_context_streamout_end(rctx);
    257 	}
    258 
    259 	/* Set the new targets. */
    260 	for (i = 0; i < num_targets; i++) {
    261 		pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->so_targets[i], targets[i]);
    262 	}
    263 	for (; i < rctx->num_so_targets; i++) {
    264 		pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->so_targets[i], NULL);
    265 	}
    266 
    267 	rctx->num_so_targets = num_targets;
    268 	rctx->streamout_start = num_targets != 0;
    269 	rctx->streamout_append_bitmask = append_bitmask;
    270 #endif
    271 }
    272