Home | History | Annotate | Download | only in a5xx
      1 /*
      2  * Copyright (C) 2016 Rob Clark <robclark (at) freedesktop.org>
      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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  *
     23  * Authors:
     24  *    Rob Clark <robclark (at) freedesktop.org>
     25  */
     26 
     27 #include "pipe/p_state.h"
     28 #include "util/u_string.h"
     29 #include "util/u_memory.h"
     30 #include "util/u_prim.h"
     31 
     32 #include "freedreno_state.h"
     33 #include "freedreno_resource.h"
     34 
     35 #include "fd5_draw.h"
     36 #include "fd5_context.h"
     37 #include "fd5_emit.h"
     38 #include "fd5_program.h"
     39 #include "fd5_format.h"
     40 #include "fd5_zsa.h"
     41 
     42 
     43 static void
     44 draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
     45 		struct fd5_emit *emit)
     46 {
     47 	const struct pipe_draw_info *info = emit->info;
     48 	enum pc_di_primtype primtype = ctx->primtypes[info->mode];
     49 
     50 	fd5_emit_state(ctx, ring, emit);
     51 
     52 	if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
     53 		fd5_emit_vertex_bufs(ring, emit);
     54 
     55 	OUT_PKT4(ring, REG_A5XX_VFD_INDEX_OFFSET, 2);
     56 	OUT_RING(ring, info->indexed ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */
     57 	OUT_RING(ring, info->start_instance);   /* ??? UNKNOWN_2209 */
     58 
     59 	OUT_PKT4(ring, REG_A5XX_PC_RESTART_INDEX, 1);
     60 	OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */
     61 			info->restart_index : 0xffffffff);
     62 
     63 	fd5_emit_render_cntl(ctx, false);
     64 	fd5_draw_emit(ctx->batch, ring, primtype,
     65 			emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY,
     66 			info);
     67 }
     68 
     69 /* fixup dirty shader state in case some "unrelated" (from the state-
     70  * tracker's perspective) state change causes us to switch to a
     71  * different variant.
     72  */
     73 static void
     74 fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key)
     75 {
     76 	struct fd5_context *fd5_ctx = fd5_context(ctx);
     77 	struct ir3_shader_key *last_key = &fd5_ctx->last_key;
     78 
     79 	if (!ir3_shader_key_equal(last_key, key)) {
     80 		if (last_key->has_per_samp || key->has_per_samp) {
     81 			if ((last_key->vsaturate_s != key->vsaturate_s) ||
     82 					(last_key->vsaturate_t != key->vsaturate_t) ||
     83 					(last_key->vsaturate_r != key->vsaturate_r) ||
     84 					(last_key->vastc_srgb != key->vastc_srgb))
     85 				ctx->dirty |= FD_SHADER_DIRTY_VP;
     86 
     87 			if ((last_key->fsaturate_s != key->fsaturate_s) ||
     88 					(last_key->fsaturate_t != key->fsaturate_t) ||
     89 					(last_key->fsaturate_r != key->fsaturate_r) ||
     90 					(last_key->fastc_srgb != key->fastc_srgb))
     91 				ctx->dirty |= FD_SHADER_DIRTY_FP;
     92 		}
     93 
     94 		if (last_key->vclamp_color != key->vclamp_color)
     95 			ctx->dirty |= FD_SHADER_DIRTY_VP;
     96 
     97 		if (last_key->fclamp_color != key->fclamp_color)
     98 			ctx->dirty |= FD_SHADER_DIRTY_FP;
     99 
    100 		if (last_key->color_two_side != key->color_two_side)
    101 			ctx->dirty |= FD_SHADER_DIRTY_FP;
    102 
    103 		if (last_key->half_precision != key->half_precision)
    104 			ctx->dirty |= FD_SHADER_DIRTY_FP;
    105 
    106 		if (last_key->rasterflat != key->rasterflat)
    107 			ctx->dirty |= FD_SHADER_DIRTY_FP;
    108 
    109 		if (last_key->ucp_enables != key->ucp_enables)
    110 			ctx->dirty |= FD_SHADER_DIRTY_FP | FD_SHADER_DIRTY_VP;
    111 
    112 		fd5_ctx->last_key = *key;
    113 	}
    114 }
    115 
    116 static bool
    117 fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info)
    118 {
    119 	struct fd5_context *fd5_ctx = fd5_context(ctx);
    120 	struct fd5_emit emit = {
    121 		.debug = &ctx->debug,
    122 		.vtx  = &ctx->vtx,
    123 		.prog = &ctx->prog,
    124 		.info = info,
    125 		.key = {
    126 			.color_two_side = ctx->rasterizer->light_twoside,
    127 			.vclamp_color = ctx->rasterizer->clamp_vertex_color,
    128 			.fclamp_color = ctx->rasterizer->clamp_fragment_color,
    129 			.rasterflat = ctx->rasterizer->flatshade,
    130 			.half_precision = ctx->in_blit &&
    131 					fd_half_precision(&ctx->batch->framebuffer),
    132 			.ucp_enables = ctx->rasterizer->clip_plane_enable,
    133 			.has_per_samp = (fd5_ctx->fsaturate || fd5_ctx->vsaturate ||
    134 					fd5_ctx->fastc_srgb || fd5_ctx->vastc_srgb),
    135 			.vsaturate_s = fd5_ctx->vsaturate_s,
    136 			.vsaturate_t = fd5_ctx->vsaturate_t,
    137 			.vsaturate_r = fd5_ctx->vsaturate_r,
    138 			.fsaturate_s = fd5_ctx->fsaturate_s,
    139 			.fsaturate_t = fd5_ctx->fsaturate_t,
    140 			.fsaturate_r = fd5_ctx->fsaturate_r,
    141 			.vastc_srgb = fd5_ctx->vastc_srgb,
    142 			.fastc_srgb = fd5_ctx->fastc_srgb,
    143 		},
    144 		.rasterflat = ctx->rasterizer->flatshade,
    145 		.sprite_coord_enable = ctx->rasterizer->sprite_coord_enable,
    146 		.sprite_coord_mode = ctx->rasterizer->sprite_coord_mode,
    147 	};
    148 
    149 	fixup_shader_state(ctx, &emit.key);
    150 
    151 	unsigned dirty = ctx->dirty;
    152 
    153 	/* do regular pass first, since that is more likely to fail compiling: */
    154 
    155 	if (!(fd5_emit_get_vp(&emit) && fd5_emit_get_fp(&emit)))
    156 		return false;
    157 
    158 	emit.key.binning_pass = false;
    159 	emit.dirty = dirty;
    160 
    161 	draw_impl(ctx, ctx->batch->draw, &emit);
    162 
    163 //	/* and now binning pass: */
    164 //	emit.key.binning_pass = true;
    165 //	emit.dirty = dirty & ~(FD_DIRTY_BLEND);
    166 //	emit.vp = NULL;   /* we changed key so need to refetch vp */
    167 //	emit.fp = NULL;
    168 //	draw_impl(ctx, ctx->batch->binning, &emit);
    169 
    170 	if (emit.streamout_mask) {
    171 		struct fd_ringbuffer *ring = ctx->batch->draw;
    172 
    173 		for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {
    174 			if (emit.streamout_mask & (1 << i)) {
    175 				OUT_PKT7(ring, CP_EVENT_WRITE, 1);
    176 				OUT_RING(ring, FLUSH_SO_0 + i);
    177 			}
    178 		}
    179 	}
    180 
    181 	return true;
    182 }
    183 
    184 static void
    185 fd5_clear(struct fd_context *ctx, unsigned buffers,
    186 		const union pipe_color_union *color, double depth, unsigned stencil)
    187 {
    188 	struct fd_ringbuffer *ring = ctx->batch->draw;
    189 	struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
    190 	struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
    191 
    192 	/* TODO handle scissor.. or fallback to slow-clear? */
    193 
    194 	ctx->batch->max_scissor.minx = MIN2(ctx->batch->max_scissor.minx, scissor->minx);
    195 	ctx->batch->max_scissor.miny = MIN2(ctx->batch->max_scissor.miny, scissor->miny);
    196 	ctx->batch->max_scissor.maxx = MAX2(ctx->batch->max_scissor.maxx, scissor->maxx);
    197 	ctx->batch->max_scissor.maxy = MAX2(ctx->batch->max_scissor.maxy, scissor->maxy);
    198 
    199 	fd5_emit_render_cntl(ctx, true);
    200 
    201 	if (buffers & PIPE_CLEAR_COLOR) {
    202 		for (int i = 0; i < pfb->nr_cbufs; i++) {
    203 			union util_color uc = {0};
    204 
    205 			if (!pfb->cbufs[i])
    206 				continue;
    207 
    208 			if (!(buffers & (PIPE_CLEAR_COLOR0 << i)))
    209 				continue;
    210 
    211 			enum pipe_format pfmt = pfb->cbufs[i]->format;
    212 
    213 			// XXX I think RB_CLEAR_COLOR_DWn wants to take into account SWAP??
    214 			union pipe_color_union swapped;
    215 			switch (fd5_pipe2swap(pfmt)) {
    216 			case WZYX:
    217 				swapped.ui[0] = color->ui[0];
    218 				swapped.ui[1] = color->ui[1];
    219 				swapped.ui[2] = color->ui[2];
    220 				swapped.ui[3] = color->ui[3];
    221 				break;
    222 			case WXYZ:
    223 				swapped.ui[2] = color->ui[0];
    224 				swapped.ui[1] = color->ui[1];
    225 				swapped.ui[0] = color->ui[2];
    226 				swapped.ui[3] = color->ui[3];
    227 				break;
    228 			case ZYXW:
    229 				swapped.ui[3] = color->ui[0];
    230 				swapped.ui[0] = color->ui[1];
    231 				swapped.ui[1] = color->ui[2];
    232 				swapped.ui[2] = color->ui[3];
    233 				break;
    234 			case XYZW:
    235 				swapped.ui[3] = color->ui[0];
    236 				swapped.ui[2] = color->ui[1];
    237 				swapped.ui[1] = color->ui[2];
    238 				swapped.ui[0] = color->ui[3];
    239 				break;
    240 			}
    241 
    242 			if (util_format_is_pure_uint(pfmt)) {
    243 				util_format_write_4ui(pfmt, swapped.ui, 0, &uc, 0, 0, 0, 1, 1);
    244 			} else if (util_format_is_pure_sint(pfmt)) {
    245 				util_format_write_4i(pfmt, swapped.i, 0, &uc, 0, 0, 0, 1, 1);
    246 			} else {
    247 				util_pack_color(swapped.f, pfmt, &uc);
    248 			}
    249 
    250 			OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
    251 			OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(BLIT_MRT0 + i));
    252 
    253 			OUT_PKT4(ring, REG_A5XX_RB_CLEAR_CNTL, 1);
    254 			OUT_RING(ring, A5XX_RB_CLEAR_CNTL_FAST_CLEAR |
    255 					A5XX_RB_CLEAR_CNTL_MASK(0xf));
    256 
    257 			OUT_PKT4(ring, REG_A5XX_RB_CLEAR_COLOR_DW0, 4);
    258 			OUT_RING(ring, uc.ui[0]);  /* RB_CLEAR_COLOR_DW0 */
    259 			OUT_RING(ring, uc.ui[1]);  /* RB_CLEAR_COLOR_DW1 */
    260 			OUT_RING(ring, uc.ui[2]);  /* RB_CLEAR_COLOR_DW2 */
    261 			OUT_RING(ring, uc.ui[3]);  /* RB_CLEAR_COLOR_DW3 */
    262 
    263 			fd5_emit_blit(ctx, ring);
    264 		}
    265 	}
    266 
    267 	if (pfb->zsbuf && (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) {
    268 		uint32_t clear =
    269 			util_pack_z_stencil(pfb->zsbuf->format, depth, stencil);
    270 		uint32_t mask = 0;
    271 
    272 		if (buffers & PIPE_CLEAR_DEPTH)
    273 			mask |= 0x1;
    274 
    275 		if (buffers & PIPE_CLEAR_STENCIL)
    276 			mask |= 0x2;
    277 
    278 		OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
    279 		OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(BLIT_ZS));
    280 
    281 		OUT_PKT4(ring, REG_A5XX_RB_CLEAR_CNTL, 1);
    282 		OUT_RING(ring, A5XX_RB_CLEAR_CNTL_FAST_CLEAR |
    283 				A5XX_RB_CLEAR_CNTL_MASK(mask));
    284 
    285 		OUT_PKT4(ring, REG_A5XX_RB_CLEAR_COLOR_DW0, 1);
    286 		OUT_RING(ring, clear);    /* RB_CLEAR_COLOR_DW0 */
    287 
    288 		fd5_emit_blit(ctx, ring);
    289 	}
    290 
    291 	/* disable fast clear to not interfere w/ gmem->mem, etc.. */
    292 	OUT_PKT4(ring, REG_A5XX_RB_CLEAR_CNTL, 1);
    293 	OUT_RING(ring, 0x00000000);   /* RB_CLEAR_CNTL */
    294 }
    295 
    296 void
    297 fd5_draw_init(struct pipe_context *pctx)
    298 {
    299 	struct fd_context *ctx = fd_context(pctx);
    300 	ctx->draw_vbo = fd5_draw_vbo;
    301 	ctx->clear = fd5_clear;
    302 }
    303