freedreno/a6xx: add helper for various CP_EVENT_WRITE
[mesa.git] / src / gallium / drivers / freedreno / a6xx / fd6_gmem.c
1 /*
2 * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
3 * Copyright © 2018 Google, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 * Rob Clark <robclark@freedesktop.org>
26 */
27
28 #include <stdio.h>
29
30 #include "pipe/p_state.h"
31 #include "util/u_string.h"
32 #include "util/u_memory.h"
33 #include "util/u_inlines.h"
34 #include "util/u_format.h"
35
36 #include "freedreno_draw.h"
37 #include "freedreno_state.h"
38 #include "freedreno_resource.h"
39
40 #include "fd6_gmem.h"
41 #include "fd6_context.h"
42 #include "fd6_draw.h"
43 #include "fd6_emit.h"
44 #include "fd6_program.h"
45 #include "fd6_format.h"
46 #include "fd6_zsa.h"
47
48 /* some bits in common w/ a4xx: */
49 #include "a4xx/fd4_draw.h"
50
51 static void
52 emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
53 struct pipe_surface **bufs, struct fd_gmem_stateobj *gmem)
54 {
55 enum a6xx_tile_mode tile_mode;
56 unsigned srgb_cntl = 0;
57 unsigned i;
58
59 for (i = 0; i < nr_bufs; i++) {
60 enum a6xx_color_fmt format = 0;
61 enum a3xx_color_swap swap = WZYX;
62 bool sint = false, uint = false;
63 struct fd_resource *rsc = NULL;
64 struct fd_resource_slice *slice = NULL;
65 uint32_t stride = 0;
66 uint32_t offset = 0;
67
68 if (gmem) {
69 tile_mode = TILE6_2;
70 } else {
71 tile_mode = TILE6_LINEAR;
72 }
73
74 if (!bufs[i])
75 continue;
76
77 struct pipe_surface *psurf = bufs[i];
78 enum pipe_format pformat = psurf->format;
79 rsc = fd_resource(psurf->texture);
80 if (!rsc->bo)
81 continue;
82
83 uint32_t base = gmem ? gmem->cbuf_base[i] : 0;
84 slice = fd_resource_slice(rsc, psurf->u.tex.level);
85 format = fd6_pipe2color(pformat);
86 swap = fd6_pipe2swap(pformat);
87 sint = util_format_is_pure_sint(pformat);
88 uint = util_format_is_pure_uint(pformat);
89
90 if (util_format_is_srgb(pformat))
91 srgb_cntl |= (1 << i);
92
93 offset = fd_resource_offset(rsc, psurf->u.tex.level,
94 psurf->u.tex.first_layer);
95
96 stride = slice->pitch * rsc->cpp;
97
98 debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
99 debug_assert((offset + slice->size0) <= fd_bo_size(rsc->bo));
100
101 OUT_PKT4(ring, REG_A6XX_RB_MRT_BUF_INFO(i), 6);
102 OUT_RING(ring, A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
103 A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(rsc->tile_mode) |
104 A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
105 OUT_RING(ring, A6XX_RB_MRT_PITCH(stride));
106 OUT_RING(ring, A6XX_RB_MRT_ARRAY_PITCH(slice->size0));
107 OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* BASE_LO/HI */
108 OUT_RING(ring, base); /* RB_MRT[i].BASE_GMEM */
109 OUT_PKT4(ring, REG_A6XX_SP_FS_MRT_REG(i), 1);
110 OUT_RING(ring, A6XX_SP_FS_MRT_REG_COLOR_FORMAT(format) |
111 COND(sint, A6XX_SP_FS_MRT_REG_COLOR_SINT) |
112 COND(uint, A6XX_SP_FS_MRT_REG_COLOR_UINT));
113
114 #if 0
115 /* when we support UBWC, these would be the system memory
116 * addr/pitch/etc:
117 */
118 OUT_PKT4(ring, REG_A6XX_RB_MRT_FLAG_BUFFER(i), 4);
119 OUT_RING(ring, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
120 OUT_RING(ring, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
121 OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH(0));
122 OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(0));
123 #endif
124 }
125
126 OUT_PKT4(ring, REG_A6XX_RB_SRGB_CNTL, 1);
127 OUT_RING(ring, srgb_cntl);
128
129 OUT_PKT4(ring, REG_A6XX_SP_SRGB_CNTL, 1);
130 OUT_RING(ring, srgb_cntl);
131 }
132
133 static void
134 emit_zs(struct fd_ringbuffer *ring, struct pipe_surface *zsbuf,
135 struct fd_gmem_stateobj *gmem)
136 {
137 if (zsbuf) {
138 struct fd_resource *rsc = fd_resource(zsbuf->texture);
139 enum a6xx_depth_format fmt = fd6_pipe2depth(zsbuf->format);
140 struct fd_resource_slice *slice = fd_resource_slice(rsc, 0);
141 uint32_t stride = slice->pitch * rsc->cpp;
142 uint32_t size = slice->size0;
143 uint32_t base = gmem ? gmem->zsbuf_base[0] : 0;
144
145 OUT_PKT4(ring, REG_A6XX_RB_DEPTH_BUFFER_INFO, 6);
146 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
147 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_PITCH(stride));
148 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_ARRAY_PITCH(size));
149 OUT_RELOCW(ring, rsc->bo, 0, 0, 0); /* RB_DEPTH_BUFFER_BASE_LO/HI */
150 OUT_RING(ring, base); /* RB_DEPTH_BUFFER_BASE_GMEM */
151
152 OUT_PKT4(ring, REG_A6XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
153 OUT_RING(ring, A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
154
155 OUT_PKT4(ring, REG_A6XX_RB_DEPTH_FLAG_BUFFER_BASE_LO, 3);
156 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
157 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
158 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_PITCH */
159
160 if (rsc->lrz) {
161 OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO, 5);
162 OUT_RELOCW(ring, rsc->lrz, 0x1000, 0, 0);
163 OUT_RING(ring, A6XX_GRAS_LRZ_BUFFER_PITCH_PITCH(rsc->lrz_pitch));
164 OUT_RELOCW(ring, rsc->lrz, 0, 0, 0); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO/HI */
165 } else {
166 OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO, 5);
167 OUT_RING(ring, 0x00000000);
168 OUT_RING(ring, 0x00000000);
169 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_BUFFER_PITCH */
170 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO */
171 OUT_RING(ring, 0x00000000);
172 }
173
174 if (rsc->stencil) {
175 struct fd_resource_slice *slice = fd_resource_slice(rsc->stencil, 0);
176 stride = slice->pitch * rsc->cpp;
177 size = slice->size0;
178 uint32_t base = gmem ? gmem->zsbuf_base[1] : 0;
179
180 OUT_PKT4(ring, REG_A6XX_RB_STENCIL_INFO, 6);
181 OUT_RING(ring, A6XX_RB_STENCIL_INFO_SEPARATE_STENCIL);
182 OUT_RING(ring, A6XX_RB_STENCIL_BUFFER_PITCH(stride));
183 OUT_RING(ring, A6XX_RB_STENCIL_BUFFER_ARRAY_PITCH(size));
184 OUT_RELOCW(ring, rsc->stencil->bo, 0, 0, 0); /* RB_STENCIL_BASE_LO/HI */
185 OUT_RING(ring, base); /* RB_STENCIL_BASE_LO */
186 } else {
187 OUT_PKT4(ring, REG_A6XX_RB_STENCIL_INFO, 1);
188 OUT_RING(ring, 0x00000000); /* RB_STENCIL_INFO */
189 }
190 } else {
191 OUT_PKT4(ring, REG_A6XX_RB_DEPTH_BUFFER_INFO, 6);
192 OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH6_NONE));
193 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_PITCH */
194 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_ARRAY_PITCH */
195 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_LO */
196 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_HI */
197 OUT_RING(ring, 0x00000000); /* RB_DEPTH_BUFFER_BASE_GMEM */
198
199 OUT_PKT4(ring, REG_A6XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
200 OUT_RING(ring, A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH6_NONE));
201
202 OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO, 5);
203 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
204 OUT_RING(ring, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
205 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_BUFFER_PITCH */
206 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO */
207 OUT_RING(ring, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_HI */
208
209 OUT_PKT4(ring, REG_A6XX_RB_STENCIL_INFO, 1);
210 OUT_RING(ring, 0x00000000); /* RB_STENCIL_INFO */
211 }
212 }
213
214 static bool
215 use_hw_binning(struct fd_batch *batch)
216 {
217 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
218
219 // TODO figure out hw limits for binning
220
221 return fd_binning_enabled && ((gmem->nbins_x * gmem->nbins_y) > 2) &&
222 (batch->num_draws > 0);
223 }
224
225 static void
226 patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
227 {
228 unsigned i;
229 for (i = 0; i < fd_patch_num_elements(&batch->draw_patches); i++) {
230 struct fd_cs_patch *patch = fd_patch_element(&batch->draw_patches, i);
231 *patch->cs = patch->val | DRAW4(0, 0, 0, vismode);
232 }
233 util_dynarray_resize(&batch->draw_patches, 0);
234 }
235
236 static void
237 patch_gmem_bases(struct fd_batch *batch)
238 {
239 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
240 unsigned i;
241
242 for (i = 0; i < fd_patch_num_elements(&batch->gmem_patches); i++) {
243 struct fd_cs_patch *patch = fd_patch_element(&batch->gmem_patches, i);
244 if (patch->val < MAX_RENDER_TARGETS)
245 *patch->cs = gmem->cbuf_base[patch->val];
246 else
247 *patch->cs = gmem->zsbuf_base[0];
248 }
249 util_dynarray_resize(&batch->gmem_patches, 0);
250 }
251
252 static void
253 update_render_cntl(struct fd_batch *batch, bool binning)
254 {
255 struct fd_ringbuffer *ring = batch->gmem;
256 uint32_t cntl = 0;
257
258 cntl |= A6XX_RB_RENDER_CNTL_UNK4;
259 if (binning)
260 cntl |= A6XX_RB_RENDER_CNTL_BINNING;
261
262 OUT_PKT7(ring, CP_REG_WRITE, 3);
263 OUT_RING(ring, 0x2);
264 OUT_RING(ring, REG_A6XX_RB_RENDER_CNTL);
265 OUT_RING(ring, cntl);
266 }
267
268 static void
269 update_vsc_pipe(struct fd_batch *batch)
270 {
271 struct fd_context *ctx = batch->ctx;
272 struct fd6_context *fd6_ctx = fd6_context(ctx);
273 struct fd_gmem_stateobj *gmem = &ctx->gmem;
274 struct fd_ringbuffer *ring = batch->gmem;
275 unsigned n = gmem->nbins_x * gmem->nbins_y;
276 int i;
277
278 OUT_PKT4(ring, REG_A6XX_VSC_BIN_SIZE, 3);
279 OUT_RING(ring, A6XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
280 A6XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));
281 OUT_RELOCW(ring, fd6_ctx->vsc_data,
282 n * A6XX_VSC_DATA_PITCH, 0, 0); /* VSC_SIZE_ADDRESS_LO/HI */
283
284 OUT_PKT4(ring, REG_A6XX_VSC_BIN_COUNT, 1);
285 OUT_RING(ring, A6XX_VSC_BIN_COUNT_NX(gmem->nbins_x) |
286 A6XX_VSC_BIN_COUNT_NY(gmem->nbins_y));
287
288 OUT_PKT4(ring, REG_A6XX_VSC_PIPE_CONFIG_REG(0), 32);
289 for (i = 0; i < 32; i++) {
290 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[i];
291 OUT_RING(ring, A6XX_VSC_PIPE_CONFIG_REG_X(pipe->x) |
292 A6XX_VSC_PIPE_CONFIG_REG_Y(pipe->y) |
293 A6XX_VSC_PIPE_CONFIG_REG_W(pipe->w) |
294 A6XX_VSC_PIPE_CONFIG_REG_H(pipe->h));
295 }
296
297 OUT_PKT4(ring, REG_A6XX_VSC_PIPE_DATA2_ADDRESS_LO, 4);
298 OUT_RELOCW(ring, fd6_ctx->vsc_data2, 0, 0, 0);
299 OUT_RING(ring, A6XX_VSC_DATA2_PITCH);
300 OUT_RING(ring, fd_bo_size(fd6_ctx->vsc_data2));
301
302 OUT_PKT4(ring, REG_A6XX_VSC_PIPE_DATA_ADDRESS_LO, 4);
303 OUT_RELOCW(ring, fd6_ctx->vsc_data, 0, 0, 0);
304 OUT_RING(ring, A6XX_VSC_DATA_PITCH);
305 OUT_RING(ring, fd_bo_size(fd6_ctx->vsc_data));
306 }
307
308 static void
309 set_scissor(struct fd_ringbuffer *ring, uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
310 {
311 OUT_PKT4(ring, REG_A6XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
312 OUT_RING(ring, A6XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1) |
313 A6XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1));
314 OUT_RING(ring, A6XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2) |
315 A6XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2));
316
317 OUT_PKT4(ring, REG_A6XX_GRAS_RESOLVE_CNTL_1, 2);
318 OUT_RING(ring, A6XX_GRAS_RESOLVE_CNTL_1_X(x1) |
319 A6XX_GRAS_RESOLVE_CNTL_1_Y(y1));
320 OUT_RING(ring, A6XX_GRAS_RESOLVE_CNTL_2_X(x2) |
321 A6XX_GRAS_RESOLVE_CNTL_2_Y(y2));
322 }
323
324 static void
325 set_bin_size(struct fd_ringbuffer *ring, uint32_t w, uint32_t h, uint32_t flag)
326 {
327 OUT_PKT4(ring, REG_A6XX_GRAS_BIN_CONTROL, 1);
328 OUT_RING(ring, A6XX_GRAS_BIN_CONTROL_BINW(w) |
329 A6XX_GRAS_BIN_CONTROL_BINH(h) | flag);
330
331 OUT_PKT4(ring, REG_A6XX_RB_BIN_CONTROL, 1);
332 OUT_RING(ring, A6XX_RB_BIN_CONTROL_BINW(w) |
333 A6XX_RB_BIN_CONTROL_BINH(h) | flag);
334
335 /* no flag for RB_BIN_CONTROL2... */
336 OUT_PKT4(ring, REG_A6XX_RB_BIN_CONTROL2, 1);
337 OUT_RING(ring, A6XX_RB_BIN_CONTROL2_BINW(w) |
338 A6XX_RB_BIN_CONTROL2_BINH(h));
339 }
340
341 static void
342 emit_binning_pass(struct fd_batch *batch)
343 {
344 struct fd_context *ctx = batch->ctx;
345 struct fd_ringbuffer *ring = batch->gmem;
346 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
347
348 uint32_t x1 = gmem->minx;
349 uint32_t y1 = gmem->miny;
350 uint32_t x2 = gmem->minx + gmem->width - 1;
351 uint32_t y2 = gmem->miny + gmem->height - 1;
352
353 set_scissor(ring, x1, y1, x2, y2);
354
355 emit_marker6(ring, 7);
356 OUT_PKT7(ring, CP_SET_MARKER, 1);
357 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_BINNING));
358 emit_marker6(ring, 7);
359
360 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
361 OUT_RING(ring, 0x1);
362
363 OUT_PKT7(ring, CP_SET_MODE, 1);
364 OUT_RING(ring, 0x1);
365
366 OUT_WFI5(ring);
367
368 OUT_PKT4(ring, REG_A6XX_VFD_MODE_CNTL, 1);
369 OUT_RING(ring, A6XX_VFD_MODE_CNTL_BINNING_PASS);
370
371 update_vsc_pipe(batch);
372
373 OUT_PKT4(ring, REG_A6XX_PC_UNKNOWN_9805, 1);
374 OUT_RING(ring, 0x1);
375
376 OUT_PKT4(ring, REG_A6XX_SP_UNKNOWN_A0F8, 1);
377 OUT_RING(ring, 0x1);
378
379 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
380 OUT_RING(ring, UNK_2C);
381
382 OUT_PKT4(ring, REG_A6XX_RB_WINDOW_OFFSET, 1);
383 OUT_RING(ring, A6XX_RB_WINDOW_OFFSET_X(0) |
384 A6XX_RB_WINDOW_OFFSET_Y(0));
385
386 OUT_PKT4(ring, REG_A6XX_SP_TP_WINDOW_OFFSET, 1);
387 OUT_RING(ring, A6XX_SP_TP_WINDOW_OFFSET_X(0) |
388 A6XX_SP_TP_WINDOW_OFFSET_Y(0));
389
390 /* emit IB to binning drawcmds: */
391 ctx->emit_ib(ring, batch->binning);
392
393 fd_reset_wfi(batch);
394
395 OUT_PKT7(ring, CP_SET_DRAW_STATE, 3);
396 OUT_RING(ring, CP_SET_DRAW_STATE__0_COUNT(0) |
397 CP_SET_DRAW_STATE__0_DISABLE_ALL_GROUPS |
398 CP_SET_DRAW_STATE__0_GROUP_ID(0));
399 OUT_RING(ring, CP_SET_DRAW_STATE__1_ADDR_LO(0));
400 OUT_RING(ring, CP_SET_DRAW_STATE__2_ADDR_HI(0));
401
402 OUT_PKT7(ring, CP_EVENT_WRITE, 1);
403 OUT_RING(ring, UNK_2D);
404
405 OUT_PKT7(ring, CP_EVENT_WRITE, 4);
406 OUT_RING(ring, CACHE_FLUSH_TS);
407 OUT_RELOCW(ring, fd6_context(ctx)->blit_mem, 0, 0, 0); /* ADDR_LO/HI */
408 OUT_RING(ring, 0x00000000);
409
410 fd_wfi(batch, ring);
411 }
412
413 static void
414 disable_msaa(struct fd_ringbuffer *ring)
415 {
416 // TODO MSAA
417 OUT_PKT4(ring, REG_A6XX_SP_TP_RAS_MSAA_CNTL, 2);
418 OUT_RING(ring, A6XX_SP_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
419 OUT_RING(ring, A6XX_SP_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
420 A6XX_SP_TP_DEST_MSAA_CNTL_MSAA_DISABLE);
421
422 OUT_PKT4(ring, REG_A6XX_GRAS_RAS_MSAA_CNTL, 2);
423 OUT_RING(ring, A6XX_GRAS_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
424 OUT_RING(ring, A6XX_GRAS_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
425 A6XX_GRAS_DEST_MSAA_CNTL_MSAA_DISABLE);
426
427 OUT_PKT4(ring, REG_A6XX_RB_RAS_MSAA_CNTL, 2);
428 OUT_RING(ring, A6XX_RB_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
429 OUT_RING(ring, A6XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
430 A6XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE);
431 }
432
433 /* before first tile */
434 static void
435 fd6_emit_tile_init(struct fd_batch *batch)
436 {
437 struct fd_context *ctx = batch->ctx;
438 struct fd_ringbuffer *ring = batch->gmem;
439 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
440 struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
441
442 fd6_emit_restore(batch, ring);
443
444 if (batch->lrz_clear)
445 ctx->emit_ib(ring, batch->lrz_clear);
446
447 fd6_emit_lrz_flush(ring);
448
449 fd6_cache_flush(batch, ring);
450
451 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
452 OUT_RING(ring, 0x0);
453
454 /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
455 fd_wfi(batch, ring);
456 OUT_PKT4(ring, REG_A6XX_RB_CCU_CNTL, 1);
457 OUT_RING(ring, 0x7c400004); /* RB_CCU_CNTL */
458
459 emit_zs(ring, pfb->zsbuf, &ctx->gmem);
460 emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, &ctx->gmem);
461
462 patch_gmem_bases(batch);
463
464 disable_msaa(ring);
465
466 if (use_hw_binning(batch)) {
467 set_bin_size(ring, gmem->bin_w, gmem->bin_h,
468 A6XX_RB_BIN_CONTROL_BINNING_PASS | 0x6000000);
469 update_render_cntl(batch, true);
470 emit_binning_pass(batch);
471 fd6_emit_lrz_flush(ring);
472 patch_draws(batch, USE_VISIBILITY);
473
474 set_bin_size(ring, gmem->bin_w, gmem->bin_h,
475 A6XX_RB_BIN_CONTROL_USE_VIZ | 0x6000000);
476
477 OUT_PKT4(ring, REG_A6XX_VFD_MODE_CNTL, 1);
478 OUT_RING(ring, 0x0);
479 } else {
480 set_bin_size(ring, gmem->bin_w, gmem->bin_h, 0x6000000);
481 patch_draws(batch, IGNORE_VISIBILITY);
482 }
483
484 update_render_cntl(batch, false);
485 }
486
487 static void
488 set_window_offset(struct fd_ringbuffer *ring, uint32_t x1, uint32_t y1)
489 {
490 OUT_PKT4(ring, REG_A6XX_RB_WINDOW_OFFSET, 1);
491 OUT_RING(ring, A6XX_RB_WINDOW_OFFSET_X(x1) |
492 A6XX_RB_WINDOW_OFFSET_Y(y1));
493
494 OUT_PKT4(ring, REG_A6XX_RB_WINDOW_OFFSET2, 1);
495 OUT_RING(ring, A6XX_RB_WINDOW_OFFSET2_X(x1) |
496 A6XX_RB_WINDOW_OFFSET2_Y(y1));
497
498 OUT_PKT4(ring, REG_A6XX_SP_WINDOW_OFFSET, 1);
499 OUT_RING(ring, A6XX_SP_WINDOW_OFFSET_X(x1) |
500 A6XX_SP_WINDOW_OFFSET_Y(y1));
501
502 OUT_PKT4(ring, REG_A6XX_SP_TP_WINDOW_OFFSET, 1);
503 OUT_RING(ring, A6XX_SP_TP_WINDOW_OFFSET_X(x1) |
504 A6XX_SP_TP_WINDOW_OFFSET_Y(y1));
505 }
506
507 /* before mem2gmem */
508 static void
509 fd6_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile)
510 {
511 struct fd_context *ctx = batch->ctx;
512 struct fd6_context *fd6_ctx = fd6_context(ctx);
513 struct fd_ringbuffer *ring = batch->gmem;
514
515 OUT_PKT7(ring, CP_SET_MARKER, 1);
516 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(0x7));
517
518 emit_marker6(ring, 7);
519 OUT_PKT7(ring, CP_SET_MARKER, 1);
520 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_GMEM) | 0x10);
521 emit_marker6(ring, 7);
522
523 uint32_t x1 = tile->xoff;
524 uint32_t y1 = tile->yoff;
525 uint32_t x2 = tile->xoff + tile->bin_w - 1;
526 uint32_t y2 = tile->yoff + tile->bin_h - 1;
527
528 set_scissor(ring, x1, y1, x2, y2);
529
530 set_window_offset(ring, x1, y1);
531
532 OUT_PKT4(ring, REG_A6XX_VPC_SO_OVERRIDE, 1);
533 OUT_RING(ring, A6XX_VPC_SO_OVERRIDE_SO_DISABLE);
534
535 if (use_hw_binning(batch)) {
536 struct fd_gmem_stateobj *gmem = &ctx->gmem;
537 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[tile->p];
538 unsigned n = gmem->nbins_x * gmem->nbins_y;
539
540 OUT_PKT7(ring, CP_WAIT_FOR_ME, 0);
541
542 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
543 OUT_RING(ring, 0x0);
544
545 OUT_PKT7(ring, CP_SET_MODE, 1);
546 OUT_RING(ring, 0x0);
547
548 OUT_PKT7(ring, CP_SET_BIN_DATA5, 7);
549 OUT_RING(ring, CP_SET_BIN_DATA5_0_VSC_SIZE(pipe->w * pipe->h) |
550 CP_SET_BIN_DATA5_0_VSC_N(tile->n));
551 OUT_RELOC(ring, fd6_ctx->vsc_data, /* VSC_PIPE[p].DATA_ADDRESS */
552 (tile->p * A6XX_VSC_DATA_PITCH), 0, 0);
553 OUT_RELOC(ring, fd6_ctx->vsc_data, /* VSC_SIZE_ADDRESS + (p * 4) */
554 (tile->p * 4) + (n * A6XX_VSC_DATA_PITCH), 0, 0);
555 OUT_RELOC(ring, fd6_ctx->vsc_data2,
556 (tile->p * A6XX_VSC_DATA2_PITCH), 0, 0);
557 } else {
558 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
559 OUT_RING(ring, 0x1);
560
561 OUT_PKT7(ring, CP_SET_MODE, 1);
562 OUT_RING(ring, 0x0);
563 }
564 }
565
566 static void
567 set_blit_scissor(struct fd_batch *batch)
568 {
569 struct fd_ringbuffer *ring = batch->gmem;
570 struct pipe_scissor_state blit_scissor;
571 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
572
573 blit_scissor.minx = batch->max_scissor.minx;
574 blit_scissor.miny = batch->max_scissor.miny;
575 blit_scissor.maxx = MIN2(pfb->width - 1, batch->max_scissor.maxx);
576 blit_scissor.maxy = MIN2(pfb->height - 1, batch->max_scissor.maxy);
577
578 OUT_PKT4(ring, REG_A6XX_RB_BLIT_SCISSOR_TL, 2);
579 OUT_RING(ring,
580 A6XX_RB_BLIT_SCISSOR_TL_X(blit_scissor.minx) |
581 A6XX_RB_BLIT_SCISSOR_TL_Y(blit_scissor.miny));
582 OUT_RING(ring,
583 A6XX_RB_BLIT_SCISSOR_BR_X(blit_scissor.maxx - 1) |
584 A6XX_RB_BLIT_SCISSOR_BR_Y(blit_scissor.maxy - 1));
585 }
586
587 static void
588 emit_blit(struct fd_batch *batch, uint32_t base,
589 struct pipe_surface *psurf,
590 struct fd_resource *rsc)
591 {
592 struct fd_ringbuffer *ring = batch->gmem;
593 struct fd_resource_slice *slice;
594 uint32_t offset;
595
596 slice = fd_resource_slice(rsc, psurf->u.tex.level);
597 offset = fd_resource_offset(rsc, psurf->u.tex.level,
598 psurf->u.tex.first_layer);
599
600 debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
601
602 enum pipe_format pfmt = psurf->format;
603 enum a6xx_color_fmt format = fd6_pipe2color(pfmt);
604 uint32_t stride = slice->pitch * rsc->cpp;
605 uint32_t size = slice->size0;
606 enum a3xx_color_swap swap = fd6_pipe2swap(pfmt);
607
608 // TODO: tile mode
609 // bool tiled;
610 // tiled = rsc->tile_mode &&
611 // !fd_resource_level_linear(psurf->texture, psurf->u.tex.level);
612
613 OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 5);
614 OUT_RING(ring,
615 A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
616 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) |
617 A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap));
618 OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* RB_BLIT_DST_LO/HI */
619 OUT_RING(ring, A6XX_RB_BLIT_DST_PITCH(stride));
620 OUT_RING(ring, A6XX_RB_BLIT_DST_ARRAY_PITCH(size));
621
622 OUT_PKT4(ring, REG_A6XX_RB_BLIT_BASE_GMEM, 1);
623 OUT_RING(ring, base);
624
625 fd6_emit_blit(batch, ring);
626 }
627
628 static void
629 emit_restore_blit(struct fd_batch *batch, uint32_t base,
630 struct pipe_surface *psurf,
631 struct fd_resource *rsc,
632 unsigned buffer)
633 {
634 struct fd_ringbuffer *ring = batch->gmem;
635 uint32_t info = 0;
636
637 switch (buffer) {
638 case FD_BUFFER_COLOR:
639 info |= A6XX_RB_BLIT_INFO_UNK0;
640 break;
641 case FD_BUFFER_STENCIL:
642 info |= A6XX_RB_BLIT_INFO_UNK0;
643 break;
644 case FD_BUFFER_DEPTH:
645 info |= A6XX_RB_BLIT_INFO_DEPTH | A6XX_RB_BLIT_INFO_UNK0;
646 break;
647 }
648
649 if (util_format_is_pure_integer(psurf->format))
650 info |= A6XX_RB_BLIT_INFO_INTEGER;
651
652 OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
653 OUT_RING(ring, info | A6XX_RB_BLIT_INFO_GMEM);
654
655 emit_blit(batch, base, psurf, rsc);
656 }
657
658 /*
659 * transfer from system memory to gmem
660 */
661 static void
662 fd6_emit_tile_mem2gmem(struct fd_batch *batch, struct fd_tile *tile)
663 {
664 struct fd_context *ctx = batch->ctx;
665 struct fd_gmem_stateobj *gmem = &ctx->gmem;
666 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
667
668 set_blit_scissor(batch);
669
670 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_COLOR)) {
671 unsigned i;
672 for (i = 0; i < pfb->nr_cbufs; i++) {
673 if (!pfb->cbufs[i])
674 continue;
675 if (!(batch->restore & (PIPE_CLEAR_COLOR0 << i)))
676 continue;
677 emit_restore_blit(batch, gmem->cbuf_base[i], pfb->cbufs[i],
678 fd_resource(pfb->cbufs[i]->texture),
679 FD_BUFFER_COLOR);
680 }
681 }
682
683 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
684 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
685
686 if (!rsc->stencil || fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH)) {
687 emit_restore_blit(batch, gmem->zsbuf_base[0], pfb->zsbuf, rsc,
688 FD_BUFFER_DEPTH);
689 }
690 if (rsc->stencil && fd_gmem_needs_restore(batch, tile, FD_BUFFER_STENCIL)) {
691 emit_restore_blit(batch, gmem->zsbuf_base[1], pfb->zsbuf, rsc->stencil,
692 FD_BUFFER_STENCIL);
693 }
694 }
695 }
696
697 /* before IB to rendering cmds: */
698 static void
699 fd6_emit_tile_renderprep(struct fd_batch *batch, struct fd_tile *tile)
700 {
701 }
702
703 static void
704 emit_resolve_blit(struct fd_batch *batch, uint32_t base,
705 struct pipe_surface *psurf,
706 struct fd_resource *rsc,
707 unsigned buffer)
708 {
709 struct fd_ringbuffer *ring = batch->gmem;
710 uint32_t info = 0;
711
712 if (!rsc->valid)
713 return;
714
715 switch (buffer) {
716 case FD_BUFFER_COLOR:
717 break;
718 case FD_BUFFER_STENCIL:
719 info |= A6XX_RB_BLIT_INFO_UNK0;
720 break;
721 case FD_BUFFER_DEPTH:
722 info |= A6XX_RB_BLIT_INFO_DEPTH;
723 break;
724 }
725
726 if (util_format_is_pure_integer(psurf->format))
727 info |= A6XX_RB_BLIT_INFO_INTEGER;
728
729 OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
730 OUT_RING(ring, info);
731
732 emit_blit(batch, base, psurf, rsc);
733 }
734
735 /*
736 * transfer from gmem to system memory (ie. normal RAM)
737 */
738
739 static void
740 fd6_emit_tile_gmem2mem(struct fd_batch *batch, struct fd_tile *tile)
741 {
742 struct fd_context *ctx = batch->ctx;
743 struct fd_gmem_stateobj *gmem = &ctx->gmem;
744 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
745 struct fd_ringbuffer *ring = batch->gmem;
746
747 if (use_hw_binning(batch)) {
748 OUT_PKT7(ring, CP_SET_MARKER, 1);
749 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(0x5) | 0x10);
750 }
751
752 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
753 OUT_RING(ring, 0x0);
754
755 emit_marker6(ring, 7);
756 OUT_PKT7(ring, CP_SET_MARKER, 1);
757 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_RESOLVE) | 0x10);
758 emit_marker6(ring, 7);
759
760 set_blit_scissor(batch);
761
762 if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
763 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
764
765 if (!rsc->stencil || (batch->resolve & FD_BUFFER_DEPTH)) {
766 emit_resolve_blit(batch, gmem->zsbuf_base[0], pfb->zsbuf, rsc,
767 FD_BUFFER_DEPTH);
768 }
769 if (rsc->stencil && (batch->resolve & FD_BUFFER_STENCIL)) {
770 emit_resolve_blit(batch, gmem->zsbuf_base[1], pfb->zsbuf, rsc->stencil,
771 FD_BUFFER_STENCIL);
772 }
773 }
774
775 if (batch->resolve & FD_BUFFER_COLOR) {
776 unsigned i;
777 for (i = 0; i < pfb->nr_cbufs; i++) {
778 if (!pfb->cbufs[i])
779 continue;
780 if (!(batch->resolve & (PIPE_CLEAR_COLOR0 << i)))
781 continue;
782 emit_resolve_blit(batch, gmem->cbuf_base[i], pfb->cbufs[i],
783 fd_resource(pfb->cbufs[i]->texture),
784 FD_BUFFER_COLOR);
785 }
786 }
787 }
788
789 static void
790 fd6_emit_tile_fini(struct fd_batch *batch)
791 {
792 struct fd_ringbuffer *ring = batch->gmem;
793
794 fd6_emit_lrz_flush(ring);
795
796 fd6_event_write(batch, ring, CACHE_FLUSH_TS, true);
797 }
798
799 static void
800 fd6_emit_sysmem_prep(struct fd_batch *batch)
801 {
802 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
803 struct fd_ringbuffer *ring = batch->gmem;
804
805 fd6_emit_restore(batch, ring);
806
807 fd6_emit_lrz_flush(ring);
808
809 emit_marker6(ring, 7);
810 OUT_PKT7(ring, CP_SET_MARKER, 1);
811 OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_BYPASS) | 0x10); /* | 0x10 ? */
812 emit_marker6(ring, 7);
813
814 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
815 OUT_RING(ring, 0x0);
816
817 fd6_event_write(batch, ring, PC_CCU_INVALIDATE_COLOR, false);
818 fd6_cache_flush(batch, ring);
819
820 #if 0
821 OUT_PKT4(ring, REG_A6XX_PC_POWER_CNTL, 1);
822 OUT_RING(ring, 0x00000003); /* PC_POWER_CNTL */
823 #endif
824
825 #if 0
826 OUT_PKT4(ring, REG_A6XX_VFD_POWER_CNTL, 1);
827 OUT_RING(ring, 0x00000003); /* VFD_POWER_CNTL */
828 #endif
829
830 /* 0x10000000 for BYPASS.. 0x7c13c080 for GMEM: */
831 fd_wfi(batch, ring);
832 OUT_PKT4(ring, REG_A6XX_RB_CCU_CNTL, 1);
833 OUT_RING(ring, 0x10000000); /* RB_CCU_CNTL */
834
835 set_scissor(ring, 0, 0, pfb->width - 1, pfb->height - 1);
836
837 set_window_offset(ring, 0, 0);
838
839 set_bin_size(ring, 0, 0, 0xc00000); /* 0xc00000 = BYPASS? */
840
841 OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
842 OUT_RING(ring, 0x1);
843
844 patch_draws(batch, IGNORE_VISIBILITY);
845
846 emit_zs(ring, pfb->zsbuf, NULL);
847 emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL);
848
849 disable_msaa(ring);
850 }
851
852 static void
853 fd6_emit_sysmem_fini(struct fd_batch *batch)
854 {
855 struct fd_ringbuffer *ring = batch->gmem;
856
857 OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
858 OUT_RING(ring, 0x0);
859
860 fd6_emit_lrz_flush(ring);
861
862 fd6_event_write(batch, ring, UNK_1D, true);
863 }
864
865 void
866 fd6_gmem_init(struct pipe_context *pctx)
867 {
868 struct fd_context *ctx = fd_context(pctx);
869
870 ctx->emit_tile_init = fd6_emit_tile_init;
871 ctx->emit_tile_prep = fd6_emit_tile_prep;
872 ctx->emit_tile_mem2gmem = fd6_emit_tile_mem2gmem;
873 ctx->emit_tile_renderprep = fd6_emit_tile_renderprep;
874 ctx->emit_tile_gmem2mem = fd6_emit_tile_gmem2mem;
875 ctx->emit_tile_fini = fd6_emit_tile_fini;
876 ctx->emit_sysmem_prep = fd6_emit_sysmem_prep;
877 ctx->emit_sysmem_fini = fd6_emit_sysmem_fini;
878 }