vc4: Fill out the stencil clear field.
[mesa.git] / src / gallium / drivers / vc4 / vc4_context.c
1 /*
2 * Copyright © 2014 Broadcom
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
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <xf86drm.h>
25 #include <err.h>
26
27 #include "pipe/p_defines.h"
28 #include "util/u_inlines.h"
29 #include "util/u_memory.h"
30 #include "util/u_blitter.h"
31 #include "indices/u_primconvert.h"
32 #include "pipe/p_screen.h"
33
34 #include "vc4_screen.h"
35 #include "vc4_context.h"
36 #include "vc4_resource.h"
37
38 static void
39 vc4_setup_rcl(struct vc4_context *vc4)
40 {
41 struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
42 struct vc4_resource *ctex = csurf ? vc4_resource(csurf->base.texture) : NULL;
43 struct vc4_surface *zsurf = vc4_surface(vc4->framebuffer.zsbuf);
44 struct vc4_resource *ztex = zsurf ? vc4_resource(zsurf->base.texture) : NULL;
45 uint32_t resolve_uncleared = vc4->resolve & ~vc4->cleared;
46 uint32_t width = vc4->framebuffer.width;
47 uint32_t height = vc4->framebuffer.height;
48 uint32_t xtiles = align(width, 64) / 64;
49 uint32_t ytiles = align(height, 64) / 64;
50
51 #if 0
52 fprintf(stderr, "RCL: resolve 0x%x clear 0x%x resolve uncleared 0x%x\n",
53 vc4->resolve,
54 vc4->cleared,
55 resolve_uncleared);
56 #endif
57
58 cl_u8(&vc4->rcl, VC4_PACKET_CLEAR_COLORS);
59 cl_u32(&vc4->rcl, vc4->clear_color[0]);
60 cl_u32(&vc4->rcl, vc4->clear_color[1]);
61 cl_u32(&vc4->rcl, vc4->clear_depth);
62 cl_u8(&vc4->rcl, vc4->clear_stencil);
63
64 cl_start_reloc(&vc4->rcl, 1);
65 cl_u8(&vc4->rcl, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
66 cl_reloc(vc4, &vc4->rcl, ctex->bo, csurf->offset);
67 cl_u16(&vc4->rcl, width);
68 cl_u16(&vc4->rcl, height);
69 cl_u16(&vc4->rcl, ((csurf->tiling <<
70 VC4_RENDER_CONFIG_MEMORY_FORMAT_SHIFT) |
71 (vc4_rt_format_is_565(csurf->base.format) ?
72 VC4_RENDER_CONFIG_FORMAT_BGR565 :
73 VC4_RENDER_CONFIG_FORMAT_RGBA8888) |
74 VC4_RENDER_CONFIG_EARLY_Z_COVERAGE_DISABLE));
75
76 /* The tile buffer normally gets cleared when the previous tile is
77 * stored. If the clear values changed between frames, then the tile
78 * buffer has stale clear values in it, so we have to do a store in
79 * None mode (no writes) so that we trigger the tile buffer clear.
80 *
81 * Excess clearing is only a performance cost, since per-tile contents
82 * will be loaded/stored in the loop below.
83 */
84 if (vc4->cleared & (PIPE_CLEAR_COLOR0 |
85 PIPE_CLEAR_DEPTH |
86 PIPE_CLEAR_STENCIL)) {
87 cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
88 cl_u8(&vc4->rcl, 0);
89 cl_u8(&vc4->rcl, 0);
90
91 cl_u8(&vc4->rcl, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
92 cl_u16(&vc4->rcl, VC4_LOADSTORE_TILE_BUFFER_NONE);
93 cl_u32(&vc4->rcl, 0); /* no address, since we're in None mode */
94 }
95
96 for (int y = 0; y < ytiles; y++) {
97 for (int x = 0; x < xtiles; x++) {
98 bool end_of_frame = (x == xtiles - 1 &&
99 y == ytiles - 1);
100 bool coords_emitted = false;
101
102 /* Note that the load doesn't actually occur until the
103 * tile coords packet is processed.
104 */
105 if (csurf && (resolve_uncleared & PIPE_CLEAR_COLOR)) {
106 cl_start_reloc(&vc4->rcl, 1);
107 cl_u8(&vc4->rcl, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
108 cl_u8(&vc4->rcl,
109 VC4_LOADSTORE_TILE_BUFFER_COLOR |
110 (csurf->tiling <<
111 VC4_LOADSTORE_TILE_BUFFER_FORMAT_SHIFT));
112 cl_u8(&vc4->rcl,
113 vc4_rt_format_is_565(csurf->base.format) ?
114 VC4_LOADSTORE_TILE_BUFFER_BGR565 :
115 VC4_LOADSTORE_TILE_BUFFER_RGBA8888);
116 cl_reloc(vc4, &vc4->rcl, ctex->bo,
117 csurf->offset);
118
119 cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
120 cl_u8(&vc4->rcl, x);
121 cl_u8(&vc4->rcl, y);
122 coords_emitted = true;
123 }
124
125 if (zsurf && (resolve_uncleared & (PIPE_CLEAR_DEPTH |
126 PIPE_CLEAR_STENCIL))) {
127 cl_start_reloc(&vc4->rcl, 1);
128 cl_u8(&vc4->rcl, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
129 cl_u8(&vc4->rcl,
130 VC4_LOADSTORE_TILE_BUFFER_ZS |
131 (zsurf->tiling <<
132 VC4_LOADSTORE_TILE_BUFFER_FORMAT_SHIFT));
133 cl_u8(&vc4->rcl, 0);
134 cl_reloc(vc4, &vc4->rcl, ztex->bo,
135 zsurf->offset);
136
137 cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
138 cl_u8(&vc4->rcl, x);
139 cl_u8(&vc4->rcl, y);
140 coords_emitted = true;
141 }
142
143 /* Clipping depends on tile coordinates having been
144 * emitted, so make sure it's happened even if
145 * everything was cleared to start.
146 */
147 if (!coords_emitted) {
148 cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
149 cl_u8(&vc4->rcl, x);
150 cl_u8(&vc4->rcl, y);
151 }
152
153 cl_start_reloc(&vc4->rcl, 1);
154 cl_u8(&vc4->rcl, VC4_PACKET_BRANCH_TO_SUB_LIST);
155 cl_reloc(vc4, &vc4->rcl, vc4->tile_alloc,
156 (y * xtiles + x) * 32);
157
158 if (zsurf && (vc4->resolve & (PIPE_CLEAR_DEPTH |
159 PIPE_CLEAR_STENCIL))) {
160 cl_start_reloc(&vc4->rcl, 1);
161 cl_u8(&vc4->rcl, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
162 cl_u8(&vc4->rcl,
163 VC4_LOADSTORE_TILE_BUFFER_Z |
164 (zsurf->tiling <<
165 VC4_LOADSTORE_TILE_BUFFER_FORMAT_SHIFT));
166 cl_u8(&vc4->rcl,
167 VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR);
168 cl_reloc(vc4, &vc4->rcl, ztex->bo,
169 zsurf->offset |
170 ((end_of_frame &&
171 !(vc4->resolve & PIPE_CLEAR_COLOR0)) ?
172 VC4_LOADSTORE_TILE_BUFFER_EOF : 0));
173 }
174
175 if (vc4->resolve & PIPE_CLEAR_COLOR0) {
176 if (end_of_frame) {
177 cl_u8(&vc4->rcl,
178 VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF);
179 } else {
180 cl_u8(&vc4->rcl,
181 VC4_PACKET_STORE_MS_TILE_BUFFER);
182 }
183 }
184
185 /* One of the bits needs to have been set that would
186 * have triggered an EOFq
187 */
188 assert(vc4->resolve & (PIPE_CLEAR_COLOR0 |
189 PIPE_CLEAR_DEPTH |
190 PIPE_CLEAR_STENCIL));
191 }
192 }
193 }
194
195 void
196 vc4_flush(struct pipe_context *pctx)
197 {
198 struct vc4_context *vc4 = vc4_context(pctx);
199
200 if (!vc4->needs_flush)
201 return;
202
203 cl_u8(&vc4->bcl, VC4_PACKET_FLUSH_ALL);
204 cl_u8(&vc4->bcl, VC4_PACKET_NOP);
205 cl_u8(&vc4->bcl, VC4_PACKET_HALT);
206
207 vc4_setup_rcl(vc4);
208
209 struct drm_vc4_submit_cl submit;
210 memset(&submit, 0, sizeof(submit));
211
212 submit.bo_handles = vc4->bo_handles.base;
213 submit.bo_handle_count = (vc4->bo_handles.next -
214 vc4->bo_handles.base) / 4;
215 submit.bin_cl = vc4->bcl.base;
216 submit.bin_cl_size = vc4->bcl.next - vc4->bcl.base;
217 submit.render_cl = vc4->rcl.base;
218 submit.render_cl_size = vc4->rcl.next - vc4->rcl.base;
219 submit.shader_rec = vc4->shader_rec.base;
220 submit.shader_rec_size = vc4->shader_rec.next - vc4->shader_rec.base;
221 submit.shader_rec_count = vc4->shader_rec_count;
222 submit.uniforms = vc4->uniforms.base;
223 submit.uniforms_size = vc4->uniforms.next - vc4->uniforms.base;
224
225 if (!(vc4_debug & VC4_DEBUG_NORAST)) {
226 int ret;
227
228 #ifndef USE_VC4_SIMULATOR
229 ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit);
230 #else
231 ret = vc4_simulator_flush(vc4, &submit);
232 #endif
233 if (ret)
234 errx(1, "VC4 submit failed\n");
235 }
236
237 vc4_reset_cl(&vc4->bcl);
238 vc4_reset_cl(&vc4->rcl);
239 vc4_reset_cl(&vc4->shader_rec);
240 vc4_reset_cl(&vc4->uniforms);
241 vc4_reset_cl(&vc4->bo_handles);
242 struct vc4_bo **referenced_bos = vc4->bo_pointers.base;
243 for (int i = 0; i < submit.bo_handle_count; i++)
244 vc4_bo_unreference(&referenced_bos[i]);
245 vc4_reset_cl(&vc4->bo_pointers);
246 vc4->shader_rec_count = 0;
247
248 vc4->needs_flush = false;
249 vc4->draw_call_queued = false;
250 vc4->dirty = ~0;
251 vc4->resolve = 0;
252 vc4->cleared = 0;
253 }
254
255 static void
256 vc4_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
257 unsigned flags)
258 {
259 vc4_flush(pctx);
260 }
261
262 /**
263 * Flushes the current command lists if they reference the given BO.
264 *
265 * This helps avoid flushing the command buffers when unnecessary.
266 */
267 void
268 vc4_flush_for_bo(struct pipe_context *pctx, struct vc4_bo *bo)
269 {
270 struct vc4_context *vc4 = vc4_context(pctx);
271
272 if (!vc4->needs_flush)
273 return;
274
275 /* Walk all the referenced BOs in the drawing command list to see if
276 * they match.
277 */
278 struct vc4_bo **referenced_bos = vc4->bo_pointers.base;
279 for (int i = 0; i < (vc4->bo_handles.next -
280 vc4->bo_handles.base) / 4; i++) {
281 if (referenced_bos[i] == bo) {
282 vc4_flush(pctx);
283 return;
284 }
285 }
286
287 /* Also check for the Z/color buffers, since the references to those
288 * are only added immediately before submit.
289 */
290 struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
291 if (csurf) {
292 struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
293 if (ctex->bo == bo) {
294 vc4_flush(pctx);
295 return;
296 }
297 }
298
299 struct vc4_surface *zsurf = vc4_surface(vc4->framebuffer.zsbuf);
300 if (zsurf) {
301 struct vc4_resource *ztex =
302 vc4_resource(zsurf->base.texture);
303 if (ztex->bo == bo) {
304 vc4_flush(pctx);
305 return;
306 }
307 }
308 }
309
310 static void
311 vc4_context_destroy(struct pipe_context *pctx)
312 {
313 struct vc4_context *vc4 = vc4_context(pctx);
314
315 if (vc4->blitter)
316 util_blitter_destroy(vc4->blitter);
317
318 if (vc4->primconvert)
319 util_primconvert_destroy(vc4->primconvert);
320
321 util_slab_destroy(&vc4->transfer_pool);
322
323 free(vc4);
324 }
325
326 struct pipe_context *
327 vc4_context_create(struct pipe_screen *pscreen, void *priv)
328 {
329 struct vc4_screen *screen = vc4_screen(pscreen);
330 struct vc4_context *vc4;
331
332 /* Prevent dumping of the shaders built during context setup. */
333 uint32_t saved_shaderdb_flag = vc4_debug & VC4_DEBUG_SHADERDB;
334 vc4_debug &= ~VC4_DEBUG_SHADERDB;
335
336 vc4 = CALLOC_STRUCT(vc4_context);
337 if (vc4 == NULL)
338 return NULL;
339 struct pipe_context *pctx = &vc4->base;
340
341 vc4->screen = screen;
342
343 pctx->screen = pscreen;
344 pctx->priv = priv;
345 pctx->destroy = vc4_context_destroy;
346 pctx->flush = vc4_pipe_flush;
347
348 vc4_draw_init(pctx);
349 vc4_state_init(pctx);
350 vc4_program_init(pctx);
351 vc4_resource_context_init(pctx);
352
353 vc4_init_cl(vc4, &vc4->bcl);
354 vc4_init_cl(vc4, &vc4->rcl);
355 vc4_init_cl(vc4, &vc4->shader_rec);
356 vc4_init_cl(vc4, &vc4->bo_handles);
357
358 vc4->dirty = ~0;
359 vc4->fd = screen->fd;
360
361 util_slab_create(&vc4->transfer_pool, sizeof(struct vc4_transfer),
362 16, UTIL_SLAB_SINGLETHREADED);
363 vc4->blitter = util_blitter_create(pctx);
364 if (!vc4->blitter)
365 goto fail;
366
367 vc4->primconvert = util_primconvert_create(pctx,
368 (1 << PIPE_PRIM_QUADS) - 1);
369 if (!vc4->primconvert)
370 goto fail;
371
372 vc4_debug |= saved_shaderdb_flag;
373
374 return &vc4->base;
375
376 fail:
377 pctx->destroy(pctx);
378 return NULL;
379 }