2 * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
3 * Copyright © 2018 Google, Inc.
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:
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
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
25 * Rob Clark <robclark@freedesktop.org>
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/format/u_format.h"
36 #include "freedreno_draw.h"
37 #include "freedreno_state.h"
38 #include "freedreno_resource.h"
40 #include "fd6_blitter.h"
42 #include "fd6_context.h"
45 #include "fd6_program.h"
46 #include "fd6_format.h"
47 #include "fd6_resource.h"
50 /* some bits in common w/ a4xx: */
51 #include "a4xx/fd4_draw.h"
54 * Emits the flags registers, suitable for RB_MRT_FLAG_BUFFER,
55 * RB_DEPTH_FLAG_BUFFER, SP_PS_2D_SRC_FLAGS, and RB_BLIT_FLAG_DST.
58 fd6_emit_flag_reference(struct fd_ringbuffer
*ring
, struct fd_resource
*rsc
,
61 if (fd_resource_ubwc_enabled(rsc
, level
)) {
62 OUT_RELOCW(ring
, rsc
->bo
, fd_resource_ubwc_offset(rsc
, level
, layer
), 0, 0);
64 A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(rsc
->layout
.ubwc_slices
[level
].pitch
) |
65 A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(rsc
->layout
.ubwc_size
));
67 OUT_RING(ring
, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
68 OUT_RING(ring
, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
69 OUT_RING(ring
, 0x00000000);
74 emit_mrt(struct fd_ringbuffer
*ring
, struct pipe_framebuffer_state
*pfb
,
75 struct fd_gmem_stateobj
*gmem
)
77 unsigned char mrt_comp
[A6XX_MAX_RENDER_TARGETS
] = {0};
78 unsigned srgb_cntl
= 0;
84 for (i
= 0; i
< pfb
->nr_cbufs
; i
++) {
85 enum a6xx_color_fmt format
= 0;
86 enum a3xx_color_swap swap
= WZYX
;
87 bool sint
= false, uint
= false;
88 struct fd_resource
*rsc
= NULL
;
89 struct fdl_slice
*slice
= NULL
;
99 struct pipe_surface
*psurf
= pfb
->cbufs
[i
];
100 enum pipe_format pformat
= psurf
->format
;
101 rsc
= fd_resource(psurf
->texture
);
105 uint32_t base
= gmem
? gmem
->cbuf_base
[i
] : 0;
106 slice
= fd_resource_slice(rsc
, psurf
->u
.tex
.level
);
107 format
= fd6_pipe2color(pformat
);
108 sint
= util_format_is_pure_sint(pformat
);
109 uint
= util_format_is_pure_uint(pformat
);
111 if (util_format_is_srgb(pformat
))
112 srgb_cntl
|= (1 << i
);
114 offset
= fd_resource_offset(rsc
, psurf
->u
.tex
.level
,
115 psurf
->u
.tex
.first_layer
);
117 stride
= slice
->pitch
* rsc
->layout
.cpp
* pfb
->samples
;
118 swap
= rsc
->layout
.tile_mode
? WZYX
: fd6_pipe2swap(pformat
);
120 tile_mode
= fd_resource_tile_mode(psurf
->texture
, psurf
->u
.tex
.level
);
122 if (psurf
->u
.tex
.first_layer
< psurf
->u
.tex
.last_layer
) {
124 if (psurf
->texture
->target
== PIPE_TEXTURE_2D_ARRAY
&& psurf
->texture
->nr_samples
> 0)
125 type
= LAYER_MULTISAMPLE_ARRAY
;
126 else if (psurf
->texture
->target
== PIPE_TEXTURE_2D_ARRAY
)
127 type
= LAYER_2D_ARRAY
;
128 else if (psurf
->texture
->target
== PIPE_TEXTURE_CUBE
)
129 type
= LAYER_CUBEMAP
;
130 else if (psurf
->texture
->target
== PIPE_TEXTURE_3D
)
133 stride
/= pfb
->samples
;
136 debug_assert((offset
+ slice
->size0
) <= fd_bo_size(rsc
->bo
));
138 OUT_PKT4(ring
, REG_A6XX_RB_MRT_BUF_INFO(i
), 6);
139 OUT_RING(ring
, A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format
) |
140 A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode
) |
141 A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap
));
142 OUT_RING(ring
, A6XX_RB_MRT_PITCH(stride
));
143 OUT_RING(ring
, A6XX_RB_MRT_ARRAY_PITCH(slice
->size0
));
144 OUT_RELOCW(ring
, rsc
->bo
, offset
, 0, 0); /* BASE_LO/HI */
145 OUT_RING(ring
, base
); /* RB_MRT[i].BASE_GMEM */
146 OUT_PKT4(ring
, REG_A6XX_SP_FS_MRT_REG(i
), 1);
147 OUT_RING(ring
, A6XX_SP_FS_MRT_REG_COLOR_FORMAT(format
) |
148 COND(sint
, A6XX_SP_FS_MRT_REG_COLOR_SINT
) |
149 COND(uint
, A6XX_SP_FS_MRT_REG_COLOR_UINT
));
151 OUT_PKT4(ring
, REG_A6XX_RB_MRT_FLAG_BUFFER(i
), 3);
152 fd6_emit_flag_reference(ring
, rsc
,
153 psurf
->u
.tex
.level
, psurf
->u
.tex
.first_layer
);
156 OUT_PKT4(ring
, REG_A6XX_RB_SRGB_CNTL
, 1);
157 OUT_RING(ring
, srgb_cntl
);
159 OUT_PKT4(ring
, REG_A6XX_SP_SRGB_CNTL
, 1);
160 OUT_RING(ring
, srgb_cntl
);
162 OUT_PKT4(ring
, REG_A6XX_RB_RENDER_COMPONENTS
, 1);
163 OUT_RING(ring
, A6XX_RB_RENDER_COMPONENTS_RT0(mrt_comp
[0]) |
164 A6XX_RB_RENDER_COMPONENTS_RT1(mrt_comp
[1]) |
165 A6XX_RB_RENDER_COMPONENTS_RT2(mrt_comp
[2]) |
166 A6XX_RB_RENDER_COMPONENTS_RT3(mrt_comp
[3]) |
167 A6XX_RB_RENDER_COMPONENTS_RT4(mrt_comp
[4]) |
168 A6XX_RB_RENDER_COMPONENTS_RT5(mrt_comp
[5]) |
169 A6XX_RB_RENDER_COMPONENTS_RT6(mrt_comp
[6]) |
170 A6XX_RB_RENDER_COMPONENTS_RT7(mrt_comp
[7]));
172 OUT_PKT4(ring
, REG_A6XX_SP_FS_RENDER_COMPONENTS
, 1);
174 A6XX_SP_FS_RENDER_COMPONENTS_RT0(mrt_comp
[0]) |
175 A6XX_SP_FS_RENDER_COMPONENTS_RT1(mrt_comp
[1]) |
176 A6XX_SP_FS_RENDER_COMPONENTS_RT2(mrt_comp
[2]) |
177 A6XX_SP_FS_RENDER_COMPONENTS_RT3(mrt_comp
[3]) |
178 A6XX_SP_FS_RENDER_COMPONENTS_RT4(mrt_comp
[4]) |
179 A6XX_SP_FS_RENDER_COMPONENTS_RT5(mrt_comp
[5]) |
180 A6XX_SP_FS_RENDER_COMPONENTS_RT6(mrt_comp
[6]) |
181 A6XX_SP_FS_RENDER_COMPONENTS_RT7(mrt_comp
[7]));
183 OUT_PKT4(ring
, REG_A6XX_GRAS_LAYER_CNTL
, 1);
184 OUT_RING(ring
, COND(layered
, A6XX_GRAS_LAYER_CNTL_LAYERED
|
185 A6XX_GRAS_LAYER_CNTL_TYPE(type
)));
189 emit_zs(struct fd_ringbuffer
*ring
, struct pipe_surface
*zsbuf
,
190 struct fd_gmem_stateobj
*gmem
)
193 struct fd_resource
*rsc
= fd_resource(zsbuf
->texture
);
194 enum a6xx_depth_format fmt
= fd6_pipe2depth(zsbuf
->format
);
195 struct fdl_slice
*slice
= fd_resource_slice(rsc
, 0);
196 uint32_t stride
= slice
->pitch
* rsc
->layout
.cpp
;
197 uint32_t size
= slice
->size0
;
198 uint32_t base
= gmem
? gmem
->zsbuf_base
[0] : 0;
199 uint32_t offset
= fd_resource_offset(rsc
, zsbuf
->u
.tex
.level
,
200 zsbuf
->u
.tex
.first_layer
);
202 OUT_PKT4(ring
, REG_A6XX_RB_DEPTH_BUFFER_INFO
, 6);
203 OUT_RING(ring
, A6XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt
));
204 OUT_RING(ring
, A6XX_RB_DEPTH_BUFFER_PITCH(stride
));
205 OUT_RING(ring
, A6XX_RB_DEPTH_BUFFER_ARRAY_PITCH(size
));
206 OUT_RELOCW(ring
, rsc
->bo
, offset
, 0, 0); /* RB_DEPTH_BUFFER_BASE_LO/HI */
207 OUT_RING(ring
, base
); /* RB_DEPTH_BUFFER_BASE_GMEM */
209 OUT_PKT4(ring
, REG_A6XX_GRAS_SU_DEPTH_BUFFER_INFO
, 1);
210 OUT_RING(ring
, A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt
));
212 OUT_PKT4(ring
, REG_A6XX_RB_DEPTH_FLAG_BUFFER_BASE_LO
, 3);
213 fd6_emit_flag_reference(ring
, rsc
,
214 zsbuf
->u
.tex
.level
, zsbuf
->u
.tex
.first_layer
);
217 OUT_PKT4(ring
, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO
, 5);
218 OUT_RELOCW(ring
, rsc
->lrz
, 0, 0, 0);
219 OUT_RING(ring
, A6XX_GRAS_LRZ_BUFFER_PITCH_PITCH(rsc
->lrz_pitch
));
220 //OUT_RELOCW(ring, rsc->lrz, 0, 0, 0); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO/HI */
221 // XXX a6xx seems to use a different buffer here.. not sure what for..
222 OUT_RING(ring
, 0x00000000);
223 OUT_RING(ring
, 0x00000000);
225 OUT_PKT4(ring
, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO
, 5);
226 OUT_RING(ring
, 0x00000000);
227 OUT_RING(ring
, 0x00000000);
228 OUT_RING(ring
, 0x00000000); /* GRAS_LRZ_BUFFER_PITCH */
229 OUT_RING(ring
, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO */
230 OUT_RING(ring
, 0x00000000);
233 /* NOTE: blob emits GRAS_LRZ_CNTL plus GRAZ_LRZ_BUFFER_BASE
234 * plus this CP_EVENT_WRITE at the end in it's own IB..
236 OUT_PKT7(ring
, CP_EVENT_WRITE
, 1);
237 OUT_RING(ring
, CP_EVENT_WRITE_0_EVENT(UNK_25
));
240 struct fdl_slice
*slice
= fd_resource_slice(rsc
->stencil
, 0);
241 stride
= slice
->pitch
* rsc
->stencil
->layout
.cpp
;
243 uint32_t base
= gmem
? gmem
->zsbuf_base
[1] : 0;
245 OUT_PKT4(ring
, REG_A6XX_RB_STENCIL_INFO
, 6);
246 OUT_RING(ring
, A6XX_RB_STENCIL_INFO_SEPARATE_STENCIL
);
247 OUT_RING(ring
, A6XX_RB_STENCIL_BUFFER_PITCH(stride
));
248 OUT_RING(ring
, A6XX_RB_STENCIL_BUFFER_ARRAY_PITCH(size
));
249 OUT_RELOCW(ring
, rsc
->stencil
->bo
, 0, 0, 0); /* RB_STENCIL_BASE_LO/HI */
250 OUT_RING(ring
, base
); /* RB_STENCIL_BASE_LO */
252 OUT_PKT4(ring
, REG_A6XX_RB_STENCIL_INFO
, 1);
253 OUT_RING(ring
, 0x00000000); /* RB_STENCIL_INFO */
256 OUT_PKT4(ring
, REG_A6XX_RB_DEPTH_BUFFER_INFO
, 6);
257 OUT_RING(ring
, A6XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH6_NONE
));
258 OUT_RING(ring
, 0x00000000); /* RB_DEPTH_BUFFER_PITCH */
259 OUT_RING(ring
, 0x00000000); /* RB_DEPTH_BUFFER_ARRAY_PITCH */
260 OUT_RING(ring
, 0x00000000); /* RB_DEPTH_BUFFER_BASE_LO */
261 OUT_RING(ring
, 0x00000000); /* RB_DEPTH_BUFFER_BASE_HI */
262 OUT_RING(ring
, 0x00000000); /* RB_DEPTH_BUFFER_BASE_GMEM */
264 OUT_PKT4(ring
, REG_A6XX_GRAS_SU_DEPTH_BUFFER_INFO
, 1);
265 OUT_RING(ring
, A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(DEPTH6_NONE
));
267 OUT_PKT4(ring
, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO
, 5);
268 OUT_RING(ring
, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
269 OUT_RING(ring
, 0x00000000); /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
270 OUT_RING(ring
, 0x00000000); /* GRAS_LRZ_BUFFER_PITCH */
271 OUT_RING(ring
, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO */
272 OUT_RING(ring
, 0x00000000); /* GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_HI */
274 OUT_PKT4(ring
, REG_A6XX_RB_STENCIL_INFO
, 1);
275 OUT_RING(ring
, 0x00000000); /* RB_STENCIL_INFO */
280 use_hw_binning(struct fd_batch
*batch
)
282 struct fd_gmem_stateobj
*gmem
= &batch
->ctx
->gmem
;
284 // TODO figure out hw limits for binning
286 return fd_binning_enabled
&& ((gmem
->nbins_x
* gmem
->nbins_y
) >= 2) &&
287 (batch
->num_draws
> 0);
291 patch_fb_read(struct fd_batch
*batch
)
293 struct fd_gmem_stateobj
*gmem
= &batch
->ctx
->gmem
;
295 for (unsigned i
= 0; i
< fd_patch_num_elements(&batch
->fb_read_patches
); i
++) {
296 struct fd_cs_patch
*patch
= fd_patch_element(&batch
->fb_read_patches
, i
);
297 *patch
->cs
= patch
->val
| A6XX_TEX_CONST_2_PITCH(gmem
->bin_w
* gmem
->cbuf_cpp
[0]);
299 util_dynarray_clear(&batch
->fb_read_patches
);
303 update_render_cntl(struct fd_batch
*batch
, struct pipe_framebuffer_state
*pfb
, bool binning
)
305 struct fd_ringbuffer
*ring
= batch
->gmem
;
307 bool depth_ubwc_enable
= false;
308 uint32_t mrts_ubwc_enable
= 0;
312 struct fd_resource
*rsc
= fd_resource(pfb
->zsbuf
->texture
);
313 depth_ubwc_enable
= fd_resource_ubwc_enabled(rsc
, pfb
->zsbuf
->u
.tex
.level
);
316 for (i
= 0; i
< pfb
->nr_cbufs
; i
++) {
320 struct pipe_surface
*psurf
= pfb
->cbufs
[i
];
321 struct fd_resource
*rsc
= fd_resource(psurf
->texture
);
325 if (fd_resource_ubwc_enabled(rsc
, psurf
->u
.tex
.level
))
326 mrts_ubwc_enable
|= 1 << i
;
329 cntl
|= A6XX_RB_RENDER_CNTL_UNK4
;
331 cntl
|= A6XX_RB_RENDER_CNTL_BINNING
;
333 OUT_PKT7(ring
, CP_REG_WRITE
, 3);
335 OUT_RING(ring
, REG_A6XX_RB_RENDER_CNTL
);
336 OUT_RING(ring
, cntl
|
337 COND(depth_ubwc_enable
, A6XX_RB_RENDER_CNTL_FLAG_DEPTH
) |
338 A6XX_RB_RENDER_CNTL_FLAG_MRTS(mrts_ubwc_enable
));
341 #define VSC_DATA_SIZE(pitch) ((pitch) * 32 + 0x100) /* extra size to store VSC_SIZE */
342 #define VSC_DATA2_SIZE(pitch) ((pitch) * 32)
345 update_vsc_pipe(struct fd_batch
*batch
)
347 struct fd_context
*ctx
= batch
->ctx
;
348 struct fd6_context
*fd6_ctx
= fd6_context(ctx
);
349 struct fd_gmem_stateobj
*gmem
= &ctx
->gmem
;
350 struct fd_ringbuffer
*ring
= batch
->gmem
;
354 if (!fd6_ctx
->vsc_data
) {
355 fd6_ctx
->vsc_data
= fd_bo_new(ctx
->screen
->dev
,
356 VSC_DATA_SIZE(fd6_ctx
->vsc_data_pitch
),
357 DRM_FREEDRENO_GEM_TYPE_KMEM
, "vsc_data");
360 if (!fd6_ctx
->vsc_data2
) {
361 fd6_ctx
->vsc_data2
= fd_bo_new(ctx
->screen
->dev
,
362 VSC_DATA2_SIZE(fd6_ctx
->vsc_data2_pitch
),
363 DRM_FREEDRENO_GEM_TYPE_KMEM
, "vsc_data2");
366 OUT_PKT4(ring
, REG_A6XX_VSC_BIN_SIZE
, 3);
367 OUT_RING(ring
, A6XX_VSC_BIN_SIZE_WIDTH(gmem
->bin_w
) |
368 A6XX_VSC_BIN_SIZE_HEIGHT(gmem
->bin_h
));
369 OUT_RELOCW(ring
, fd6_ctx
->vsc_data
,
370 32 * fd6_ctx
->vsc_data_pitch
, 0, 0); /* VSC_SIZE_ADDRESS_LO/HI */
372 OUT_PKT4(ring
, REG_A6XX_VSC_BIN_COUNT
, 1);
373 OUT_RING(ring
, A6XX_VSC_BIN_COUNT_NX(gmem
->nbins_x
) |
374 A6XX_VSC_BIN_COUNT_NY(gmem
->nbins_y
));
376 OUT_PKT4(ring
, REG_A6XX_VSC_PIPE_CONFIG_REG(0), 32);
377 for (i
= 0; i
< 32; i
++) {
378 struct fd_vsc_pipe
*pipe
= &ctx
->vsc_pipe
[i
];
379 OUT_RING(ring
, A6XX_VSC_PIPE_CONFIG_REG_X(pipe
->x
) |
380 A6XX_VSC_PIPE_CONFIG_REG_Y(pipe
->y
) |
381 A6XX_VSC_PIPE_CONFIG_REG_W(pipe
->w
) |
382 A6XX_VSC_PIPE_CONFIG_REG_H(pipe
->h
));
385 OUT_PKT4(ring
, REG_A6XX_VSC_PIPE_DATA2_ADDRESS_LO
, 4);
386 OUT_RELOCW(ring
, fd6_ctx
->vsc_data2
, 0, 0, 0);
387 OUT_RING(ring
, fd6_ctx
->vsc_data2_pitch
);
388 OUT_RING(ring
, fd_bo_size(fd6_ctx
->vsc_data2
));
390 OUT_PKT4(ring
, REG_A6XX_VSC_PIPE_DATA_ADDRESS_LO
, 4);
391 OUT_RELOCW(ring
, fd6_ctx
->vsc_data
, 0, 0, 0);
392 OUT_RING(ring
, fd6_ctx
->vsc_data_pitch
);
393 OUT_RING(ring
, fd_bo_size(fd6_ctx
->vsc_data
));
396 /* TODO we probably have more than 8 scratch regs.. although the first
397 * 8 is what kernel dumps, and it is kinda useful to be able to see
398 * the value in kernel traces
400 #define OVERFLOW_FLAG_REG REG_A6XX_CP_SCRATCH_REG(0)
403 * If overflow is detected, either 0x1 (VSC_DATA overflow) or 0x3
404 * (VSC_DATA2 overflow) plus the size of the overflowed buffer is
405 * written to control->vsc_overflow. This allows the CPU to
406 * detect which buffer overflowed (and, since the current size is
407 * encoded as well, this protects against already-submitted but
408 * not executed batches from fooling the CPU into increasing the
409 * size again unnecessarily).
411 * To conditionally use VSC data in draw pass only if there is no
412 * overflow, we use a scratch reg (OVERFLOW_FLAG_REG) to hold 1
413 * if no overflow, or 0 in case of overflow. The value is inverted
414 * to make the CP_COND_REG_EXEC stuff easier.
417 emit_vsc_overflow_test(struct fd_batch
*batch
)
419 struct fd_ringbuffer
*ring
= batch
->gmem
;
420 struct fd_gmem_stateobj
*gmem
= &batch
->ctx
->gmem
;
421 struct fd6_context
*fd6_ctx
= fd6_context(batch
->ctx
);
423 debug_assert((fd6_ctx
->vsc_data_pitch
& 0x3) == 0);
424 debug_assert((fd6_ctx
->vsc_data2_pitch
& 0x3) == 0);
426 /* Clear vsc_scratch: */
427 OUT_PKT7(ring
, CP_MEM_WRITE
, 3);
428 OUT_RELOCW(ring
, control_ptr(fd6_ctx
, vsc_scratch
));
431 /* Check for overflow, write vsc_scratch if detected: */
432 for (int i
= 0; i
< gmem
->num_vsc_pipes
; i
++) {
433 OUT_PKT7(ring
, CP_COND_WRITE5
, 8);
434 OUT_RING(ring
, CP_COND_WRITE5_0_FUNCTION(WRITE_GE
) |
435 CP_COND_WRITE5_0_WRITE_MEMORY
);
436 OUT_RING(ring
, CP_COND_WRITE5_1_POLL_ADDR_LO(REG_A6XX_VSC_SIZE_REG(i
)));
437 OUT_RING(ring
, CP_COND_WRITE5_2_POLL_ADDR_HI(0));
438 OUT_RING(ring
, CP_COND_WRITE5_3_REF(fd6_ctx
->vsc_data_pitch
));
439 OUT_RING(ring
, CP_COND_WRITE5_4_MASK(~0));
440 OUT_RELOCW(ring
, control_ptr(fd6_ctx
, vsc_scratch
)); /* WRITE_ADDR_LO/HI */
441 OUT_RING(ring
, CP_COND_WRITE5_7_WRITE_DATA(1 + fd6_ctx
->vsc_data_pitch
));
443 OUT_PKT7(ring
, CP_COND_WRITE5
, 8);
444 OUT_RING(ring
, CP_COND_WRITE5_0_FUNCTION(WRITE_GE
) |
445 CP_COND_WRITE5_0_WRITE_MEMORY
);
446 OUT_RING(ring
, CP_COND_WRITE5_1_POLL_ADDR_LO(REG_A6XX_VSC_SIZE2_REG(i
)));
447 OUT_RING(ring
, CP_COND_WRITE5_2_POLL_ADDR_HI(0));
448 OUT_RING(ring
, CP_COND_WRITE5_3_REF(fd6_ctx
->vsc_data2_pitch
));
449 OUT_RING(ring
, CP_COND_WRITE5_4_MASK(~0));
450 OUT_RELOCW(ring
, control_ptr(fd6_ctx
, vsc_scratch
)); /* WRITE_ADDR_LO/HI */
451 OUT_RING(ring
, CP_COND_WRITE5_7_WRITE_DATA(3 + fd6_ctx
->vsc_data2_pitch
));
454 OUT_PKT7(ring
, CP_WAIT_MEM_WRITES
, 0);
456 OUT_PKT7(ring
, CP_WAIT_FOR_ME
, 0);
458 OUT_PKT7(ring
, CP_MEM_TO_REG
, 3);
459 OUT_RING(ring
, CP_MEM_TO_REG_0_REG(OVERFLOW_FLAG_REG
) |
460 CP_MEM_TO_REG_0_CNT(1 - 1));
461 OUT_RELOC(ring
, control_ptr(fd6_ctx
, vsc_scratch
)); /* SRC_LO/HI */
464 * This is a bit awkward, we really want a way to invert the
465 * CP_REG_TEST/CP_COND_REG_EXEC logic, so that we can conditionally
466 * execute cmds to use hwbinning when a bit is *not* set. This
467 * dance is to invert OVERFLOW_FLAG_REG
469 * A CP_NOP packet is used to skip executing the 'else' clause
473 BEGIN_RING(ring
, 10); /* ensure if/else doesn't get split */
475 /* b0 will be set if VSC_DATA or VSC_DATA2 overflow: */
476 OUT_PKT7(ring
, CP_REG_TEST
, 1);
477 OUT_RING(ring
, A6XX_CP_REG_TEST_0_REG(OVERFLOW_FLAG_REG
) |
478 A6XX_CP_REG_TEST_0_BIT(0) |
479 A6XX_CP_REG_TEST_0_UNK25
);
481 OUT_PKT7(ring
, CP_COND_REG_EXEC
, 2);
482 OUT_RING(ring
, 0x10000000);
483 OUT_RING(ring
, 7); /* conditionally execute next 7 dwords */
487 * On overflow, mirror the value to control->vsc_overflow
488 * which CPU is checking to detect overflow (see
489 * check_vsc_overflow())
491 OUT_PKT7(ring
, CP_REG_TO_MEM
, 3);
492 OUT_RING(ring
, CP_REG_TO_MEM_0_REG(OVERFLOW_FLAG_REG
) |
493 CP_REG_TO_MEM_0_CNT(1 - 1));
494 OUT_RELOCW(ring
, control_ptr(fd6_ctx
, vsc_overflow
));
496 OUT_PKT4(ring
, OVERFLOW_FLAG_REG
, 1);
499 OUT_PKT7(ring
, CP_NOP
, 2); /* skip 'else' when 'if' is taken */
501 OUT_PKT4(ring
, OVERFLOW_FLAG_REG
, 1);
507 check_vsc_overflow(struct fd_context
*ctx
)
509 struct fd6_context
*fd6_ctx
= fd6_context(ctx
);
510 struct fd6_control
*control
= fd_bo_map(fd6_ctx
->control_mem
);
511 uint32_t vsc_overflow
= control
->vsc_overflow
;
516 /* clear overflow flag: */
517 control
->vsc_overflow
= 0;
519 unsigned buffer
= vsc_overflow
& 0x3;
520 unsigned size
= vsc_overflow
& ~0x3;
523 /* VSC_PIPE_DATA overflow: */
525 if (size
< fd6_ctx
->vsc_data_pitch
) {
526 /* we've already increased the size, this overflow is
527 * from a batch submitted before resize, but executed
533 fd_bo_del(fd6_ctx
->vsc_data
);
534 fd6_ctx
->vsc_data
= NULL
;
535 fd6_ctx
->vsc_data_pitch
*= 2;
537 debug_printf("resized VSC_DATA_PITCH to: 0x%x\n", fd6_ctx
->vsc_data_pitch
);
539 } else if (buffer
== 0x3) {
540 /* VSC_PIPE_DATA2 overflow: */
542 if (size
< fd6_ctx
->vsc_data2_pitch
) {
543 /* we've already increased the size */
547 fd_bo_del(fd6_ctx
->vsc_data2
);
548 fd6_ctx
->vsc_data2
= NULL
;
549 fd6_ctx
->vsc_data2_pitch
*= 2;
551 debug_printf("resized VSC_DATA2_PITCH to: 0x%x\n", fd6_ctx
->vsc_data2_pitch
);
554 /* NOTE: it's possible, for example, for overflow to corrupt the
555 * control page. I mostly just see this hit if I set initial VSC
556 * buffer size extremely small. Things still seem to recover,
557 * but maybe we should pre-emptively realloc vsc_data/vsc_data2
558 * and hope for different memory placement?
560 DBG("invalid vsc_overflow value: 0x%08x", vsc_overflow
);
565 * Emit conditional CP_INDIRECT_BRANCH based on VSC_STATE[p], ie. the IB
566 * is skipped for tiles that have no visible geometry.
569 emit_conditional_ib(struct fd_batch
*batch
, struct fd_tile
*tile
,
570 struct fd_ringbuffer
*target
)
572 struct fd_ringbuffer
*ring
= batch
->gmem
;
574 if (target
->cur
== target
->start
)
577 emit_marker6(ring
, 6);
579 unsigned count
= fd_ringbuffer_cmd_count(target
);
581 BEGIN_RING(ring
, 5 + 4 * count
); /* ensure conditional doesn't get split */
583 OUT_PKT7(ring
, CP_REG_TEST
, 1);
584 OUT_RING(ring
, A6XX_CP_REG_TEST_0_REG(REG_A6XX_VSC_STATE_REG(tile
->p
)) |
585 A6XX_CP_REG_TEST_0_BIT(tile
->n
) |
586 A6XX_CP_REG_TEST_0_UNK25
);
588 OUT_PKT7(ring
, CP_COND_REG_EXEC
, 2);
589 OUT_RING(ring
, 0x10000000);
590 OUT_RING(ring
, 4 * count
); /* conditionally execute next 4*count dwords */
592 for (unsigned i
= 0; i
< count
; i
++) {
594 OUT_PKT7(ring
, CP_INDIRECT_BUFFER
, 3);
595 dwords
= fd_ringbuffer_emit_reloc_ring_full(ring
, target
, i
) / 4;
597 OUT_RING(ring
, dwords
);
600 emit_marker6(ring
, 6);
604 set_scissor(struct fd_ringbuffer
*ring
, uint32_t x1
, uint32_t y1
, uint32_t x2
, uint32_t y2
)
606 OUT_PKT4(ring
, REG_A6XX_GRAS_SC_WINDOW_SCISSOR_TL
, 2);
607 OUT_RING(ring
, A6XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1
) |
608 A6XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1
));
609 OUT_RING(ring
, A6XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2
) |
610 A6XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2
));
612 OUT_PKT4(ring
, REG_A6XX_GRAS_RESOLVE_CNTL_1
, 2);
613 OUT_RING(ring
, A6XX_GRAS_RESOLVE_CNTL_1_X(x1
) |
614 A6XX_GRAS_RESOLVE_CNTL_1_Y(y1
));
615 OUT_RING(ring
, A6XX_GRAS_RESOLVE_CNTL_2_X(x2
) |
616 A6XX_GRAS_RESOLVE_CNTL_2_Y(y2
));
620 set_bin_size(struct fd_ringbuffer
*ring
, uint32_t w
, uint32_t h
, uint32_t flag
)
622 OUT_PKT4(ring
, REG_A6XX_GRAS_BIN_CONTROL
, 1);
623 OUT_RING(ring
, A6XX_GRAS_BIN_CONTROL_BINW(w
) |
624 A6XX_GRAS_BIN_CONTROL_BINH(h
) | flag
);
626 OUT_PKT4(ring
, REG_A6XX_RB_BIN_CONTROL
, 1);
627 OUT_RING(ring
, A6XX_RB_BIN_CONTROL_BINW(w
) |
628 A6XX_RB_BIN_CONTROL_BINH(h
) | flag
);
630 /* no flag for RB_BIN_CONTROL2... */
631 OUT_PKT4(ring
, REG_A6XX_RB_BIN_CONTROL2
, 1);
632 OUT_RING(ring
, A6XX_RB_BIN_CONTROL2_BINW(w
) |
633 A6XX_RB_BIN_CONTROL2_BINH(h
));
637 emit_binning_pass(struct fd_batch
*batch
)
639 struct fd_ringbuffer
*ring
= batch
->gmem
;
640 struct fd_gmem_stateobj
*gmem
= &batch
->ctx
->gmem
;
641 struct fd6_context
*fd6_ctx
= fd6_context(batch
->ctx
);
643 uint32_t x1
= gmem
->minx
;
644 uint32_t y1
= gmem
->miny
;
645 uint32_t x2
= gmem
->minx
+ gmem
->width
- 1;
646 uint32_t y2
= gmem
->miny
+ gmem
->height
- 1;
648 debug_assert(!batch
->tessellation
);
650 set_scissor(ring
, x1
, y1
, x2
, y2
);
652 emit_marker6(ring
, 7);
653 OUT_PKT7(ring
, CP_SET_MARKER
, 1);
654 OUT_RING(ring
, A6XX_CP_SET_MARKER_0_MODE(RM6_BINNING
));
655 emit_marker6(ring
, 7);
657 OUT_PKT7(ring
, CP_SET_VISIBILITY_OVERRIDE
, 1);
660 OUT_PKT7(ring
, CP_SET_MODE
, 1);
665 OUT_PKT4(ring
, REG_A6XX_VFD_MODE_CNTL
, 1);
666 OUT_RING(ring
, A6XX_VFD_MODE_CNTL_BINNING_PASS
);
668 update_vsc_pipe(batch
);
670 OUT_PKT4(ring
, REG_A6XX_PC_UNKNOWN_9805
, 1);
671 OUT_RING(ring
, fd6_ctx
->magic
.PC_UNKNOWN_9805
);
673 OUT_PKT4(ring
, REG_A6XX_SP_UNKNOWN_A0F8
, 1);
674 OUT_RING(ring
, fd6_ctx
->magic
.SP_UNKNOWN_A0F8
);
676 OUT_PKT7(ring
, CP_EVENT_WRITE
, 1);
677 OUT_RING(ring
, UNK_2C
);
679 OUT_PKT4(ring
, REG_A6XX_RB_WINDOW_OFFSET
, 1);
680 OUT_RING(ring
, A6XX_RB_WINDOW_OFFSET_X(0) |
681 A6XX_RB_WINDOW_OFFSET_Y(0));
683 OUT_PKT4(ring
, REG_A6XX_SP_TP_WINDOW_OFFSET
, 1);
684 OUT_RING(ring
, A6XX_SP_TP_WINDOW_OFFSET_X(0) |
685 A6XX_SP_TP_WINDOW_OFFSET_Y(0));
687 /* emit IB to binning drawcmds: */
688 fd6_emit_ib(ring
, batch
->draw
);
692 OUT_PKT7(ring
, CP_SET_DRAW_STATE
, 3);
693 OUT_RING(ring
, CP_SET_DRAW_STATE__0_COUNT(0) |
694 CP_SET_DRAW_STATE__0_DISABLE_ALL_GROUPS
|
695 CP_SET_DRAW_STATE__0_GROUP_ID(0));
696 OUT_RING(ring
, CP_SET_DRAW_STATE__1_ADDR_LO(0));
697 OUT_RING(ring
, CP_SET_DRAW_STATE__2_ADDR_HI(0));
699 OUT_PKT7(ring
, CP_EVENT_WRITE
, 1);
700 OUT_RING(ring
, UNK_2D
);
702 fd6_cache_inv(batch
, ring
);
703 fd6_cache_flush(batch
, ring
);
706 OUT_PKT7(ring
, CP_WAIT_FOR_ME
, 0);
708 emit_vsc_overflow_test(batch
);
710 OUT_PKT7(ring
, CP_SET_VISIBILITY_OVERRIDE
, 1);
713 OUT_PKT7(ring
, CP_SET_MODE
, 1);
718 OUT_PKT4(ring
, REG_A6XX_RB_CCU_CNTL
, 1);
719 OUT_RING(ring
, fd6_ctx
->magic
.RB_CCU_CNTL_gmem
);
723 emit_msaa(struct fd_ringbuffer
*ring
, unsigned nr
)
725 enum a3xx_msaa_samples samples
= fd_msaa_samples(nr
);
727 OUT_PKT4(ring
, REG_A6XX_SP_TP_RAS_MSAA_CNTL
, 2);
728 OUT_RING(ring
, A6XX_SP_TP_RAS_MSAA_CNTL_SAMPLES(samples
));
729 OUT_RING(ring
, A6XX_SP_TP_DEST_MSAA_CNTL_SAMPLES(samples
) |
730 COND(samples
== MSAA_ONE
, A6XX_SP_TP_DEST_MSAA_CNTL_MSAA_DISABLE
));
732 OUT_PKT4(ring
, REG_A6XX_GRAS_RAS_MSAA_CNTL
, 2);
733 OUT_RING(ring
, A6XX_GRAS_RAS_MSAA_CNTL_SAMPLES(samples
));
734 OUT_RING(ring
, A6XX_GRAS_DEST_MSAA_CNTL_SAMPLES(samples
) |
735 COND(samples
== MSAA_ONE
, A6XX_GRAS_DEST_MSAA_CNTL_MSAA_DISABLE
));
737 OUT_PKT4(ring
, REG_A6XX_RB_RAS_MSAA_CNTL
, 2);
738 OUT_RING(ring
, A6XX_RB_RAS_MSAA_CNTL_SAMPLES(samples
));
739 OUT_RING(ring
, A6XX_RB_DEST_MSAA_CNTL_SAMPLES(samples
) |
740 COND(samples
== MSAA_ONE
, A6XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE
));
742 OUT_PKT4(ring
, REG_A6XX_RB_MSAA_CNTL
, 1);
743 OUT_RING(ring
, A6XX_RB_MSAA_CNTL_SAMPLES(samples
));
746 static void prepare_tile_setup_ib(struct fd_batch
*batch
);
747 static void prepare_tile_fini_ib(struct fd_batch
*batch
);
749 /* before first tile */
751 fd6_emit_tile_init(struct fd_batch
*batch
)
753 struct fd_context
*ctx
= batch
->ctx
;
754 struct fd_ringbuffer
*ring
= batch
->gmem
;
755 struct pipe_framebuffer_state
*pfb
= &batch
->framebuffer
;
756 struct fd_gmem_stateobj
*gmem
= &batch
->ctx
->gmem
;
758 fd6_emit_restore(batch
, ring
);
760 fd6_emit_lrz_flush(ring
);
762 if (batch
->lrz_clear
)
763 fd6_emit_ib(ring
, batch
->lrz_clear
);
765 fd6_cache_inv(batch
, ring
);
767 prepare_tile_setup_ib(batch
);
768 prepare_tile_fini_ib(batch
);
770 OUT_PKT7(ring
, CP_SKIP_IB2_ENABLE_GLOBAL
, 1);
774 OUT_PKT4(ring
, REG_A6XX_RB_CCU_CNTL
, 1);
775 OUT_RING(ring
, fd6_context(ctx
)->magic
.RB_CCU_CNTL_gmem
);
777 emit_zs(ring
, pfb
->zsbuf
, &ctx
->gmem
);
778 emit_mrt(ring
, pfb
, &ctx
->gmem
);
779 emit_msaa(ring
, pfb
->samples
);
780 patch_fb_read(batch
);
782 if (use_hw_binning(batch
)) {
783 /* enable stream-out during binning pass: */
784 OUT_PKT4(ring
, REG_A6XX_VPC_SO_OVERRIDE
, 1);
787 set_bin_size(ring
, gmem
->bin_w
, gmem
->bin_h
,
788 A6XX_RB_BIN_CONTROL_BINNING_PASS
| 0x6000000);
789 update_render_cntl(batch
, pfb
, true);
790 emit_binning_pass(batch
);
792 /* and disable stream-out for draw pass: */
793 OUT_PKT4(ring
, REG_A6XX_VPC_SO_OVERRIDE
, 1);
794 OUT_RING(ring
, A6XX_VPC_SO_OVERRIDE_SO_DISABLE
);
797 * NOTE: even if we detect VSC overflow and disable use of
798 * visibility stream in draw pass, it is still safe to execute
799 * the reset of these cmds:
802 // NOTE a618 not setting .USE_VIZ .. from a quick check on a630, it
803 // does not appear that this bit changes much (ie. it isn't actually
804 // .USE_VIZ like previous gens)
805 set_bin_size(ring
, gmem
->bin_w
, gmem
->bin_h
,
806 A6XX_RB_BIN_CONTROL_USE_VIZ
| 0x6000000);
808 OUT_PKT4(ring
, REG_A6XX_VFD_MODE_CNTL
, 1);
811 OUT_PKT4(ring
, REG_A6XX_PC_UNKNOWN_9805
, 1);
812 OUT_RING(ring
, fd6_context(ctx
)->magic
.PC_UNKNOWN_9805
);
814 OUT_PKT4(ring
, REG_A6XX_SP_UNKNOWN_A0F8
, 1);
815 OUT_RING(ring
, fd6_context(ctx
)->magic
.SP_UNKNOWN_A0F8
);
817 OUT_PKT7(ring
, CP_SKIP_IB2_ENABLE_GLOBAL
, 1);
820 /* no binning pass, so enable stream-out for draw pass:: */
821 OUT_PKT4(ring
, REG_A6XX_VPC_SO_OVERRIDE
, 1);
824 set_bin_size(ring
, gmem
->bin_w
, gmem
->bin_h
, 0x6000000);
827 update_render_cntl(batch
, pfb
, false);
831 set_window_offset(struct fd_ringbuffer
*ring
, uint32_t x1
, uint32_t y1
)
833 OUT_PKT4(ring
, REG_A6XX_RB_WINDOW_OFFSET
, 1);
834 OUT_RING(ring
, A6XX_RB_WINDOW_OFFSET_X(x1
) |
835 A6XX_RB_WINDOW_OFFSET_Y(y1
));
837 OUT_PKT4(ring
, REG_A6XX_RB_WINDOW_OFFSET2
, 1);
838 OUT_RING(ring
, A6XX_RB_WINDOW_OFFSET2_X(x1
) |
839 A6XX_RB_WINDOW_OFFSET2_Y(y1
));
841 OUT_PKT4(ring
, REG_A6XX_SP_WINDOW_OFFSET
, 1);
842 OUT_RING(ring
, A6XX_SP_WINDOW_OFFSET_X(x1
) |
843 A6XX_SP_WINDOW_OFFSET_Y(y1
));
845 OUT_PKT4(ring
, REG_A6XX_SP_TP_WINDOW_OFFSET
, 1);
846 OUT_RING(ring
, A6XX_SP_TP_WINDOW_OFFSET_X(x1
) |
847 A6XX_SP_TP_WINDOW_OFFSET_Y(y1
));
850 /* before mem2gmem */
852 fd6_emit_tile_prep(struct fd_batch
*batch
, struct fd_tile
*tile
)
854 struct fd_context
*ctx
= batch
->ctx
;
855 struct fd6_context
*fd6_ctx
= fd6_context(ctx
);
856 struct fd_ringbuffer
*ring
= batch
->gmem
;
858 emit_marker6(ring
, 7);
859 OUT_PKT7(ring
, CP_SET_MARKER
, 1);
860 OUT_RING(ring
, A6XX_CP_SET_MARKER_0_MODE(RM6_GMEM
) | 0x10);
861 emit_marker6(ring
, 7);
863 uint32_t x1
= tile
->xoff
;
864 uint32_t y1
= tile
->yoff
;
865 uint32_t x2
= tile
->xoff
+ tile
->bin_w
- 1;
866 uint32_t y2
= tile
->yoff
+ tile
->bin_h
- 1;
868 set_scissor(ring
, x1
, y1
, x2
, y2
);
870 if (use_hw_binning(batch
)) {
871 struct fd_vsc_pipe
*pipe
= &ctx
->vsc_pipe
[tile
->p
];
873 OUT_PKT7(ring
, CP_WAIT_FOR_ME
, 0);
875 OUT_PKT7(ring
, CP_SET_MODE
, 1);
879 * Conditionally execute if no VSC overflow:
882 BEGIN_RING(ring
, 18); /* ensure if/else doesn't get split */
884 OUT_PKT7(ring
, CP_REG_TEST
, 1);
885 OUT_RING(ring
, A6XX_CP_REG_TEST_0_REG(OVERFLOW_FLAG_REG
) |
886 A6XX_CP_REG_TEST_0_BIT(0) |
887 A6XX_CP_REG_TEST_0_UNK25
);
889 OUT_PKT7(ring
, CP_COND_REG_EXEC
, 2);
890 OUT_RING(ring
, 0x10000000);
891 OUT_RING(ring
, 11); /* conditionally execute next 11 dwords */
893 /* if (no overflow) */ {
894 OUT_PKT7(ring
, CP_SET_BIN_DATA5
, 7);
895 OUT_RING(ring
, CP_SET_BIN_DATA5_0_VSC_SIZE(pipe
->w
* pipe
->h
) |
896 CP_SET_BIN_DATA5_0_VSC_N(tile
->n
));
897 OUT_RELOC(ring
, fd6_ctx
->vsc_data
, /* VSC_PIPE[p].DATA_ADDRESS */
898 (tile
->p
* fd6_ctx
->vsc_data_pitch
), 0, 0);
899 OUT_RELOC(ring
, fd6_ctx
->vsc_data
, /* VSC_SIZE_ADDRESS + (p * 4) */
900 (tile
->p
* 4) + (32 * fd6_ctx
->vsc_data_pitch
), 0, 0);
901 OUT_RELOC(ring
, fd6_ctx
->vsc_data2
,
902 (tile
->p
* fd6_ctx
->vsc_data2_pitch
), 0, 0);
904 OUT_PKT7(ring
, CP_SET_VISIBILITY_OVERRIDE
, 1);
907 /* use a NOP packet to skip over the 'else' side: */
908 OUT_PKT7(ring
, CP_NOP
, 2);
910 OUT_PKT7(ring
, CP_SET_VISIBILITY_OVERRIDE
, 1);
914 set_window_offset(ring
, x1
, y1
);
916 struct fd_gmem_stateobj
*gmem
= &batch
->ctx
->gmem
;
917 set_bin_size(ring
, gmem
->bin_w
, gmem
->bin_h
, 0x6000000);
919 OUT_PKT7(ring
, CP_SET_MODE
, 1);
922 OUT_PKT4(ring
, REG_A6XX_RB_UNKNOWN_8804
, 1);
925 OUT_PKT4(ring
, REG_A6XX_SP_TP_UNKNOWN_B304
, 1);
928 OUT_PKT4(ring
, REG_A6XX_GRAS_UNKNOWN_80A4
, 1);
931 set_window_offset(ring
, x1
, y1
);
933 OUT_PKT7(ring
, CP_SET_VISIBILITY_OVERRIDE
, 1);
936 OUT_PKT7(ring
, CP_SET_MODE
, 1);
942 set_blit_scissor(struct fd_batch
*batch
, struct fd_ringbuffer
*ring
)
944 struct pipe_scissor_state blit_scissor
;
945 struct pipe_framebuffer_state
*pfb
= &batch
->framebuffer
;
947 blit_scissor
.minx
= 0;
948 blit_scissor
.miny
= 0;
949 blit_scissor
.maxx
= align(pfb
->width
, batch
->ctx
->screen
->gmem_alignw
);
950 blit_scissor
.maxy
= align(pfb
->height
, batch
->ctx
->screen
->gmem_alignh
);
952 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_SCISSOR_TL
, 2);
954 A6XX_RB_BLIT_SCISSOR_TL_X(blit_scissor
.minx
) |
955 A6XX_RB_BLIT_SCISSOR_TL_Y(blit_scissor
.miny
));
957 A6XX_RB_BLIT_SCISSOR_BR_X(blit_scissor
.maxx
- 1) |
958 A6XX_RB_BLIT_SCISSOR_BR_Y(blit_scissor
.maxy
- 1));
962 emit_blit(struct fd_batch
*batch
,
963 struct fd_ringbuffer
*ring
,
965 struct pipe_surface
*psurf
,
968 struct fdl_slice
*slice
;
969 struct fd_resource
*rsc
= fd_resource(psurf
->texture
);
970 enum pipe_format pfmt
= psurf
->format
;
974 debug_assert(psurf
->u
.tex
.first_layer
== psurf
->u
.tex
.last_layer
);
976 /* separate stencil case: */
979 pfmt
= rsc
->base
.format
;
982 slice
= fd_resource_slice(rsc
, psurf
->u
.tex
.level
);
983 offset
= fd_resource_offset(rsc
, psurf
->u
.tex
.level
,
984 psurf
->u
.tex
.first_layer
);
985 ubwc_enabled
= fd_resource_ubwc_enabled(rsc
, psurf
->u
.tex
.level
);
987 debug_assert(psurf
->u
.tex
.first_layer
== psurf
->u
.tex
.last_layer
);
989 enum a6xx_color_fmt format
= fd6_pipe2color(pfmt
);
990 uint32_t stride
= slice
->pitch
* rsc
->layout
.cpp
;
991 uint32_t size
= slice
->size0
;
992 enum a3xx_color_swap swap
= rsc
->layout
.tile_mode
? WZYX
: fd6_pipe2swap(pfmt
);
993 enum a3xx_msaa_samples samples
=
994 fd_msaa_samples(rsc
->base
.nr_samples
);
995 uint32_t tile_mode
= fd_resource_tile_mode(&rsc
->base
, psurf
->u
.tex
.level
);
997 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_DST_INFO
, 5);
999 A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode
) |
1000 A6XX_RB_BLIT_DST_INFO_SAMPLES(samples
) |
1001 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format
) |
1002 A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap
) |
1003 COND(ubwc_enabled
, A6XX_RB_BLIT_DST_INFO_FLAGS
));
1004 OUT_RELOCW(ring
, rsc
->bo
, offset
, 0, 0); /* RB_BLIT_DST_LO/HI */
1005 OUT_RING(ring
, A6XX_RB_BLIT_DST_PITCH(stride
));
1006 OUT_RING(ring
, A6XX_RB_BLIT_DST_ARRAY_PITCH(size
));
1008 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_BASE_GMEM
, 1);
1009 OUT_RING(ring
, base
);
1012 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_FLAG_DST_LO
, 3);
1013 fd6_emit_flag_reference(ring
, rsc
,
1014 psurf
->u
.tex
.level
, psurf
->u
.tex
.first_layer
);
1017 fd6_emit_blit(batch
, ring
);
1021 emit_restore_blit(struct fd_batch
*batch
,
1022 struct fd_ringbuffer
*ring
,
1024 struct pipe_surface
*psurf
,
1028 bool stencil
= false;
1031 case FD_BUFFER_COLOR
:
1032 info
|= A6XX_RB_BLIT_INFO_UNK0
;
1034 case FD_BUFFER_STENCIL
:
1035 info
|= A6XX_RB_BLIT_INFO_UNK0
;
1038 case FD_BUFFER_DEPTH
:
1039 info
|= A6XX_RB_BLIT_INFO_DEPTH
| A6XX_RB_BLIT_INFO_UNK0
;
1043 if (util_format_is_pure_integer(psurf
->format
))
1044 info
|= A6XX_RB_BLIT_INFO_INTEGER
;
1046 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_INFO
, 1);
1047 OUT_RING(ring
, info
| A6XX_RB_BLIT_INFO_GMEM
);
1049 emit_blit(batch
, ring
, base
, psurf
, stencil
);
1053 emit_clears(struct fd_batch
*batch
, struct fd_ringbuffer
*ring
)
1055 struct pipe_framebuffer_state
*pfb
= &batch
->framebuffer
;
1056 struct fd_gmem_stateobj
*gmem
= &batch
->ctx
->gmem
;
1057 enum a3xx_msaa_samples samples
= fd_msaa_samples(pfb
->samples
);
1059 uint32_t buffers
= batch
->fast_cleared
;
1061 if (buffers
& PIPE_CLEAR_COLOR
) {
1063 for (int i
= 0; i
< pfb
->nr_cbufs
; i
++) {
1064 union pipe_color_union
*color
= &batch
->clear_color
[i
];
1065 union util_color uc
= {0};
1070 if (!(buffers
& (PIPE_CLEAR_COLOR0
<< i
)))
1073 enum pipe_format pfmt
= pfb
->cbufs
[i
]->format
;
1075 // XXX I think RB_CLEAR_COLOR_DWn wants to take into account SWAP??
1076 union pipe_color_union swapped
;
1077 switch (fd6_pipe2swap(pfmt
)) {
1079 swapped
.ui
[0] = color
->ui
[0];
1080 swapped
.ui
[1] = color
->ui
[1];
1081 swapped
.ui
[2] = color
->ui
[2];
1082 swapped
.ui
[3] = color
->ui
[3];
1085 swapped
.ui
[2] = color
->ui
[0];
1086 swapped
.ui
[1] = color
->ui
[1];
1087 swapped
.ui
[0] = color
->ui
[2];
1088 swapped
.ui
[3] = color
->ui
[3];
1091 swapped
.ui
[3] = color
->ui
[0];
1092 swapped
.ui
[0] = color
->ui
[1];
1093 swapped
.ui
[1] = color
->ui
[2];
1094 swapped
.ui
[2] = color
->ui
[3];
1097 swapped
.ui
[3] = color
->ui
[0];
1098 swapped
.ui
[2] = color
->ui
[1];
1099 swapped
.ui
[1] = color
->ui
[2];
1100 swapped
.ui
[0] = color
->ui
[3];
1104 if (util_format_is_pure_uint(pfmt
)) {
1105 util_format_write_4ui(pfmt
, swapped
.ui
, 0, &uc
, 0, 0, 0, 1, 1);
1106 } else if (util_format_is_pure_sint(pfmt
)) {
1107 util_format_write_4i(pfmt
, swapped
.i
, 0, &uc
, 0, 0, 0, 1, 1);
1109 util_pack_color(swapped
.f
, pfmt
, &uc
);
1112 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_DST_INFO
, 1);
1113 OUT_RING(ring
, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR
) |
1114 A6XX_RB_BLIT_DST_INFO_SAMPLES(samples
) |
1115 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(fd6_pipe2color(pfmt
)));
1117 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_INFO
, 1);
1118 OUT_RING(ring
, A6XX_RB_BLIT_INFO_GMEM
|
1119 A6XX_RB_BLIT_INFO_CLEAR_MASK(0xf));
1121 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_BASE_GMEM
, 1);
1122 OUT_RING(ring
, gmem
->cbuf_base
[i
]);
1124 OUT_PKT4(ring
, REG_A6XX_RB_UNKNOWN_88D0
, 1);
1127 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0
, 4);
1128 OUT_RING(ring
, uc
.ui
[0]);
1129 OUT_RING(ring
, uc
.ui
[1]);
1130 OUT_RING(ring
, uc
.ui
[2]);
1131 OUT_RING(ring
, uc
.ui
[3]);
1133 fd6_emit_blit(batch
, ring
);
1137 const bool has_depth
= pfb
->zsbuf
;
1138 const bool has_separate_stencil
=
1139 has_depth
&& fd_resource(pfb
->zsbuf
->texture
)->stencil
;
1141 /* First clear depth or combined depth/stencil. */
1142 if ((has_depth
&& (buffers
& PIPE_CLEAR_DEPTH
)) ||
1143 (!has_separate_stencil
&& (buffers
& PIPE_CLEAR_STENCIL
))) {
1144 enum pipe_format pfmt
= pfb
->zsbuf
->format
;
1145 uint32_t clear_value
;
1148 if (has_separate_stencil
) {
1149 pfmt
= util_format_get_depth_only(pfb
->zsbuf
->format
);
1150 clear_value
= util_pack_z(pfmt
, batch
->clear_depth
);
1152 pfmt
= pfb
->zsbuf
->format
;
1153 clear_value
= util_pack_z_stencil(pfmt
, batch
->clear_depth
,
1154 batch
->clear_stencil
);
1157 if (buffers
& PIPE_CLEAR_DEPTH
)
1160 if (!has_separate_stencil
&& (buffers
& PIPE_CLEAR_STENCIL
))
1163 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_DST_INFO
, 1);
1164 OUT_RING(ring
, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR
) |
1165 A6XX_RB_BLIT_DST_INFO_SAMPLES(samples
) |
1166 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(fd6_pipe2color(pfmt
)));
1168 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_INFO
, 1);
1169 OUT_RING(ring
, A6XX_RB_BLIT_INFO_GMEM
|
1170 // XXX UNK0 for separate stencil ??
1171 A6XX_RB_BLIT_INFO_DEPTH
|
1172 A6XX_RB_BLIT_INFO_CLEAR_MASK(mask
));
1174 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_BASE_GMEM
, 1);
1175 OUT_RING(ring
, gmem
->zsbuf_base
[0]);
1177 OUT_PKT4(ring
, REG_A6XX_RB_UNKNOWN_88D0
, 1);
1180 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0
, 1);
1181 OUT_RING(ring
, clear_value
);
1183 fd6_emit_blit(batch
, ring
);
1186 /* Then clear the separate stencil buffer in case of 32 bit depth
1187 * formats with separate stencil. */
1188 if (has_separate_stencil
&& (buffers
& PIPE_CLEAR_STENCIL
)) {
1189 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_DST_INFO
, 1);
1190 OUT_RING(ring
, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR
) |
1191 A6XX_RB_BLIT_DST_INFO_SAMPLES(samples
) |
1192 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(RB6_R8_UINT
));
1194 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_INFO
, 1);
1195 OUT_RING(ring
, A6XX_RB_BLIT_INFO_GMEM
|
1196 //A6XX_RB_BLIT_INFO_UNK0 |
1197 A6XX_RB_BLIT_INFO_DEPTH
|
1198 A6XX_RB_BLIT_INFO_CLEAR_MASK(0x1));
1200 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_BASE_GMEM
, 1);
1201 OUT_RING(ring
, gmem
->zsbuf_base
[1]);
1203 OUT_PKT4(ring
, REG_A6XX_RB_UNKNOWN_88D0
, 1);
1206 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0
, 1);
1207 OUT_RING(ring
, batch
->clear_stencil
& 0xff);
1209 fd6_emit_blit(batch
, ring
);
1214 * transfer from system memory to gmem
1217 emit_restore_blits(struct fd_batch
*batch
, struct fd_ringbuffer
*ring
)
1219 struct fd_context
*ctx
= batch
->ctx
;
1220 struct fd_gmem_stateobj
*gmem
= &ctx
->gmem
;
1221 struct pipe_framebuffer_state
*pfb
= &batch
->framebuffer
;
1223 if (batch
->restore
& FD_BUFFER_COLOR
) {
1225 for (i
= 0; i
< pfb
->nr_cbufs
; i
++) {
1228 if (!(batch
->restore
& (PIPE_CLEAR_COLOR0
<< i
)))
1230 emit_restore_blit(batch
, ring
, gmem
->cbuf_base
[i
], pfb
->cbufs
[i
],
1235 if (batch
->restore
& (FD_BUFFER_DEPTH
| FD_BUFFER_STENCIL
)) {
1236 struct fd_resource
*rsc
= fd_resource(pfb
->zsbuf
->texture
);
1238 if (!rsc
->stencil
|| (batch
->restore
& FD_BUFFER_DEPTH
)) {
1239 emit_restore_blit(batch
, ring
, gmem
->zsbuf_base
[0], pfb
->zsbuf
,
1242 if (rsc
->stencil
&& (batch
->restore
& FD_BUFFER_STENCIL
)) {
1243 emit_restore_blit(batch
, ring
, gmem
->zsbuf_base
[1], pfb
->zsbuf
,
1250 prepare_tile_setup_ib(struct fd_batch
*batch
)
1252 batch
->tile_setup
= fd_submit_new_ringbuffer(batch
->submit
, 0x1000,
1253 FD_RINGBUFFER_STREAMING
);
1255 set_blit_scissor(batch
, batch
->tile_setup
);
1257 emit_restore_blits(batch
, batch
->tile_setup
);
1258 emit_clears(batch
, batch
->tile_setup
);
1262 * transfer from system memory to gmem
1265 fd6_emit_tile_mem2gmem(struct fd_batch
*batch
, struct fd_tile
*tile
)
1269 /* before IB to rendering cmds: */
1271 fd6_emit_tile_renderprep(struct fd_batch
*batch
, struct fd_tile
*tile
)
1273 if (batch
->fast_cleared
|| !use_hw_binning(batch
)) {
1274 fd6_emit_ib(batch
->gmem
, batch
->tile_setup
);
1276 emit_conditional_ib(batch
, tile
, batch
->tile_setup
);
1281 emit_resolve_blit(struct fd_batch
*batch
,
1282 struct fd_ringbuffer
*ring
,
1284 struct pipe_surface
*psurf
,
1288 bool stencil
= false;
1290 if (!fd_resource(psurf
->texture
)->valid
)
1294 case FD_BUFFER_COLOR
:
1296 case FD_BUFFER_STENCIL
:
1297 info
|= A6XX_RB_BLIT_INFO_UNK0
;
1300 case FD_BUFFER_DEPTH
:
1301 info
|= A6XX_RB_BLIT_INFO_DEPTH
;
1305 if (util_format_is_pure_integer(psurf
->format
))
1306 info
|= A6XX_RB_BLIT_INFO_INTEGER
;
1308 OUT_PKT4(ring
, REG_A6XX_RB_BLIT_INFO
, 1);
1309 OUT_RING(ring
, info
);
1311 emit_blit(batch
, ring
, base
, psurf
, stencil
);
1315 * transfer from gmem to system memory (ie. normal RAM)
1319 prepare_tile_fini_ib(struct fd_batch
*batch
)
1321 struct fd_context
*ctx
= batch
->ctx
;
1322 struct fd_gmem_stateobj
*gmem
= &ctx
->gmem
;
1323 struct pipe_framebuffer_state
*pfb
= &batch
->framebuffer
;
1324 struct fd_ringbuffer
*ring
;
1326 batch
->tile_fini
= fd_submit_new_ringbuffer(batch
->submit
, 0x1000,
1327 FD_RINGBUFFER_STREAMING
);
1328 ring
= batch
->tile_fini
;
1330 set_blit_scissor(batch
, ring
);
1332 if (batch
->resolve
& (FD_BUFFER_DEPTH
| FD_BUFFER_STENCIL
)) {
1333 struct fd_resource
*rsc
= fd_resource(pfb
->zsbuf
->texture
);
1335 if (!rsc
->stencil
|| (batch
->resolve
& FD_BUFFER_DEPTH
)) {
1336 emit_resolve_blit(batch
, ring
,
1337 gmem
->zsbuf_base
[0], pfb
->zsbuf
,
1340 if (rsc
->stencil
&& (batch
->resolve
& FD_BUFFER_STENCIL
)) {
1341 emit_resolve_blit(batch
, ring
,
1342 gmem
->zsbuf_base
[1], pfb
->zsbuf
,
1347 if (batch
->resolve
& FD_BUFFER_COLOR
) {
1349 for (i
= 0; i
< pfb
->nr_cbufs
; i
++) {
1352 if (!(batch
->resolve
& (PIPE_CLEAR_COLOR0
<< i
)))
1354 emit_resolve_blit(batch
, ring
, gmem
->cbuf_base
[i
], pfb
->cbufs
[i
],
1361 fd6_emit_tile(struct fd_batch
*batch
, struct fd_tile
*tile
)
1363 if (!use_hw_binning(batch
)) {
1364 fd6_emit_ib(batch
->gmem
, batch
->draw
);
1366 emit_conditional_ib(batch
, tile
, batch
->draw
);
1371 fd6_emit_tile_gmem2mem(struct fd_batch
*batch
, struct fd_tile
*tile
)
1373 struct fd_ringbuffer
*ring
= batch
->gmem
;
1375 if (use_hw_binning(batch
)) {
1376 /* Conditionally execute if no VSC overflow: */
1378 BEGIN_RING(ring
, 7); /* ensure if/else doesn't get split */
1380 OUT_PKT7(ring
, CP_REG_TEST
, 1);
1381 OUT_RING(ring
, A6XX_CP_REG_TEST_0_REG(OVERFLOW_FLAG_REG
) |
1382 A6XX_CP_REG_TEST_0_BIT(0) |
1383 A6XX_CP_REG_TEST_0_UNK25
);
1385 OUT_PKT7(ring
, CP_COND_REG_EXEC
, 2);
1386 OUT_RING(ring
, 0x10000000);
1387 OUT_RING(ring
, 2); /* conditionally execute next 2 dwords */
1389 /* if (no overflow) */ {
1390 OUT_PKT7(ring
, CP_SET_MARKER
, 1);
1391 OUT_RING(ring
, A6XX_CP_SET_MARKER_0_MODE(0x5) | 0x10);
1395 OUT_PKT7(ring
, CP_SET_DRAW_STATE
, 3);
1396 OUT_RING(ring
, CP_SET_DRAW_STATE__0_COUNT(0) |
1397 CP_SET_DRAW_STATE__0_DISABLE_ALL_GROUPS
|
1398 CP_SET_DRAW_STATE__0_GROUP_ID(0));
1399 OUT_RING(ring
, CP_SET_DRAW_STATE__1_ADDR_LO(0));
1400 OUT_RING(ring
, CP_SET_DRAW_STATE__2_ADDR_HI(0));
1402 OUT_PKT7(ring
, CP_SKIP_IB2_ENABLE_LOCAL
, 1);
1403 OUT_RING(ring
, 0x0);
1405 emit_marker6(ring
, 7);
1406 OUT_PKT7(ring
, CP_SET_MARKER
, 1);
1407 OUT_RING(ring
, A6XX_CP_SET_MARKER_0_MODE(RM6_RESOLVE
) | 0x10);
1408 emit_marker6(ring
, 7);
1410 if (batch
->fast_cleared
|| !use_hw_binning(batch
)) {
1411 fd6_emit_ib(batch
->gmem
, batch
->tile_fini
);
1413 emit_conditional_ib(batch
, tile
, batch
->tile_fini
);
1416 OUT_PKT7(ring
, CP_SET_MARKER
, 1);
1417 OUT_RING(ring
, A6XX_CP_SET_MARKER_0_MODE(0x7));
1421 fd6_emit_tile_fini(struct fd_batch
*batch
)
1423 struct fd_ringbuffer
*ring
= batch
->gmem
;
1425 OUT_PKT4(ring
, REG_A6XX_GRAS_LRZ_CNTL
, 1);
1426 OUT_RING(ring
, A6XX_GRAS_LRZ_CNTL_ENABLE
| A6XX_GRAS_LRZ_CNTL_UNK3
);
1428 fd6_emit_lrz_flush(ring
);
1430 fd6_event_write(batch
, ring
, CACHE_FLUSH_TS
, true);
1432 if (use_hw_binning(batch
)) {
1433 check_vsc_overflow(batch
->ctx
);
1438 emit_sysmem_clears(struct fd_batch
*batch
, struct fd_ringbuffer
*ring
)
1440 struct fd_context
*ctx
= batch
->ctx
;
1441 struct pipe_framebuffer_state
*pfb
= &batch
->framebuffer
;
1443 uint32_t buffers
= batch
->fast_cleared
;
1445 if (buffers
& PIPE_CLEAR_COLOR
) {
1446 for (int i
= 0; i
< pfb
->nr_cbufs
; i
++) {
1447 union pipe_color_union
*color
= &batch
->clear_color
[i
];
1452 if (!(buffers
& (PIPE_CLEAR_COLOR0
<< i
)))
1455 fd6_clear_surface(ctx
, ring
,
1456 pfb
->cbufs
[i
], pfb
->width
, pfb
->height
, color
);
1459 if (buffers
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) {
1460 union pipe_color_union value
= {};
1462 const bool has_depth
= pfb
->zsbuf
;
1463 struct pipe_resource
*separate_stencil
=
1464 has_depth
&& fd_resource(pfb
->zsbuf
->texture
)->stencil
?
1465 &fd_resource(pfb
->zsbuf
->texture
)->stencil
->base
: NULL
;
1467 if ((has_depth
&& (buffers
& PIPE_CLEAR_DEPTH
)) ||
1468 (!separate_stencil
&& (buffers
& PIPE_CLEAR_STENCIL
))) {
1469 value
.f
[0] = batch
->clear_depth
;
1470 value
.ui
[1] = batch
->clear_stencil
;
1471 fd6_clear_surface(ctx
, ring
,
1472 pfb
->zsbuf
, pfb
->width
, pfb
->height
, &value
);
1475 if (separate_stencil
&& (buffers
& PIPE_CLEAR_STENCIL
)) {
1476 value
.ui
[0] = batch
->clear_stencil
;
1478 struct pipe_surface stencil_surf
= *pfb
->zsbuf
;
1479 stencil_surf
.texture
= separate_stencil
;
1481 fd6_clear_surface(ctx
, ring
,
1482 &stencil_surf
, pfb
->width
, pfb
->height
, &value
);
1486 fd6_event_write(batch
, ring
, 0x1d, true);
1490 setup_tess_buffers(struct fd_batch
*batch
, struct fd_ringbuffer
*ring
)
1492 struct fd_context
*ctx
= batch
->ctx
;
1494 batch
->tessfactor_bo
= fd_bo_new(ctx
->screen
->dev
,
1495 batch
->tessfactor_size
,
1496 DRM_FREEDRENO_GEM_TYPE_KMEM
, "tessfactor");
1498 batch
->tessparam_bo
= fd_bo_new(ctx
->screen
->dev
,
1499 batch
->tessparam_size
,
1500 DRM_FREEDRENO_GEM_TYPE_KMEM
, "tessparam");
1502 OUT_PKT4(ring
, REG_A6XX_PC_TESSFACTOR_ADDR_LO
, 2);
1503 OUT_RELOCW(ring
, batch
->tessfactor_bo
, 0, 0, 0);
1505 batch
->tess_addrs_constobj
->cur
= batch
->tess_addrs_constobj
->start
;
1506 OUT_RELOCW(batch
->tess_addrs_constobj
, batch
->tessparam_bo
, 0, 0, 0);
1507 OUT_RELOCW(batch
->tess_addrs_constobj
, batch
->tessfactor_bo
, 0, 0, 0);
1511 fd6_emit_sysmem_prep(struct fd_batch
*batch
)
1513 struct pipe_framebuffer_state
*pfb
= &batch
->framebuffer
;
1514 struct fd_ringbuffer
*ring
= batch
->gmem
;
1516 fd6_emit_restore(batch
, ring
);
1518 set_scissor(ring
, 0, 0, pfb
->width
- 1, pfb
->height
- 1);
1520 set_window_offset(ring
, 0, 0);
1522 set_bin_size(ring
, 0, 0, 0xc00000); /* 0xc00000 = BYPASS? */
1524 emit_sysmem_clears(batch
, ring
);
1526 fd6_emit_lrz_flush(ring
);
1528 emit_marker6(ring
, 7);
1529 OUT_PKT7(ring
, CP_SET_MARKER
, 1);
1530 OUT_RING(ring
, A6XX_CP_SET_MARKER_0_MODE(RM6_BYPASS
) | 0x10); /* | 0x10 ? */
1531 emit_marker6(ring
, 7);
1533 if (batch
->tessellation
)
1534 setup_tess_buffers(batch
, ring
);
1536 OUT_PKT7(ring
, CP_SKIP_IB2_ENABLE_GLOBAL
, 1);
1537 OUT_RING(ring
, 0x0);
1539 fd6_event_write(batch
, ring
, PC_CCU_INVALIDATE_COLOR
, false);
1540 fd6_cache_inv(batch
, ring
);
1542 fd_wfi(batch
, ring
);
1543 OUT_PKT4(ring
, REG_A6XX_RB_CCU_CNTL
, 1);
1544 OUT_RING(ring
, fd6_context(batch
->ctx
)->magic
.RB_CCU_CNTL_bypass
);
1546 /* enable stream-out, with sysmem there is only one pass: */
1547 OUT_PKT4(ring
, REG_A6XX_VPC_SO_OVERRIDE
, 1);
1550 OUT_PKT7(ring
, CP_SET_VISIBILITY_OVERRIDE
, 1);
1551 OUT_RING(ring
, 0x1);
1553 emit_zs(ring
, pfb
->zsbuf
, NULL
);
1554 emit_mrt(ring
, pfb
, NULL
);
1555 emit_msaa(ring
, pfb
->samples
);
1557 update_render_cntl(batch
, pfb
, false);
1561 fd6_emit_sysmem_fini(struct fd_batch
*batch
)
1563 struct fd_ringbuffer
*ring
= batch
->gmem
;
1565 OUT_PKT7(ring
, CP_SKIP_IB2_ENABLE_GLOBAL
, 1);
1566 OUT_RING(ring
, 0x0);
1568 fd6_emit_lrz_flush(ring
);
1570 fd6_event_write(batch
, ring
, UNK_1D
, true);
1574 fd6_gmem_init(struct pipe_context
*pctx
)
1576 struct fd_context
*ctx
= fd_context(pctx
);
1578 ctx
->emit_tile_init
= fd6_emit_tile_init
;
1579 ctx
->emit_tile_prep
= fd6_emit_tile_prep
;
1580 ctx
->emit_tile_mem2gmem
= fd6_emit_tile_mem2gmem
;
1581 ctx
->emit_tile_renderprep
= fd6_emit_tile_renderprep
;
1582 ctx
->emit_tile
= fd6_emit_tile
;
1583 ctx
->emit_tile_gmem2mem
= fd6_emit_tile_gmem2mem
;
1584 ctx
->emit_tile_fini
= fd6_emit_tile_fini
;
1585 ctx
->emit_sysmem_prep
= fd6_emit_sysmem_prep
;
1586 ctx
->emit_sysmem_fini
= fd6_emit_sysmem_fini
;