vc4_context.c revision af69d88d
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#include <stdio.h>
27
28#include "pipe/p_defines.h"
29#include "util/u_inlines.h"
30#include "util/u_memory.h"
31#include "util/u_blitter.h"
32#include "indices/u_primconvert.h"
33#include "pipe/p_screen.h"
34
35#include "vc4_screen.h"
36#include "vc4_context.h"
37#include "vc4_resource.h"
38
39static void
40vc4_setup_rcl(struct vc4_context *vc4)
41{
42        struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
43        struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
44        uint32_t resolve_uncleared = vc4->resolve & ~vc4->cleared;
45        uint32_t width = vc4->framebuffer.width;
46        uint32_t height = vc4->framebuffer.height;
47        uint32_t xtiles = align(width, 64) / 64;
48        uint32_t ytiles = align(height, 64) / 64;
49
50#if 0
51        fprintf(stderr, "RCL: resolve 0x%x clear 0x%x resolve uncleared 0x%x\n",
52                vc4->resolve,
53                vc4->cleared,
54                resolve_uncleared);
55#endif
56
57        cl_u8(&vc4->rcl, VC4_PACKET_CLEAR_COLORS);
58        cl_u32(&vc4->rcl, vc4->clear_color[0]);
59        cl_u32(&vc4->rcl, vc4->clear_color[1]);
60        cl_u32(&vc4->rcl, vc4->clear_depth);
61        cl_u8(&vc4->rcl, 0);
62
63        cl_start_reloc(&vc4->rcl, 1);
64        cl_u8(&vc4->rcl, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
65        cl_reloc(vc4, &vc4->rcl, ctex->bo, csurf->offset);
66        cl_u16(&vc4->rcl, width);
67        cl_u16(&vc4->rcl, height);
68        cl_u16(&vc4->rcl, ((ctex->tiling <<
69                            VC4_RENDER_CONFIG_MEMORY_FORMAT_SHIFT) |
70                           VC4_RENDER_CONFIG_FORMAT_RGBA8888 |
71                           VC4_RENDER_CONFIG_EARLY_Z_COVERAGE_DISABLE));
72
73        /* The tile buffer normally gets cleared when the previous tile is
74         * stored.  If the clear values changed between frames, then the tile
75         * buffer has stale clear values in it, so we have to do a store in
76         * None mode (no writes) so that we trigger the tile buffer clear.
77         */
78        if (vc4->cleared & PIPE_CLEAR_COLOR0) {
79                cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
80                cl_u8(&vc4->rcl, 0);
81                cl_u8(&vc4->rcl, 0);
82
83                cl_u8(&vc4->rcl, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
84                cl_u16(&vc4->rcl, VC4_LOADSTORE_TILE_BUFFER_NONE);
85                cl_u32(&vc4->rcl, 0); /* no address, since we're in None mode */
86        }
87
88        for (int y = 0; y < ytiles; y++) {
89                for (int x = 0; x < xtiles; x++) {
90                        bool end_of_frame = (x == xtiles - 1 &&
91                                             y == ytiles - 1);
92
93                        /* Note that the load doesn't actually occur until the
94                         * tile coords packet is processed.
95                         */
96                        if (resolve_uncleared & PIPE_CLEAR_COLOR) {
97                                cl_start_reloc(&vc4->rcl, 1);
98                                cl_u8(&vc4->rcl, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
99                                cl_u8(&vc4->rcl,
100                                      VC4_LOADSTORE_TILE_BUFFER_COLOR |
101                                      (ctex->tiling <<
102                                       VC4_LOADSTORE_TILE_BUFFER_FORMAT_SHIFT));
103                                cl_u8(&vc4->rcl,
104                                      VC4_LOADSTORE_TILE_BUFFER_RGBA8888);
105                                cl_reloc(vc4, &vc4->rcl, ctex->bo,
106                                         csurf->offset);
107                        }
108
109                        cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
110                        cl_u8(&vc4->rcl, x);
111                        cl_u8(&vc4->rcl, y);
112
113                        cl_start_reloc(&vc4->rcl, 1);
114                        cl_u8(&vc4->rcl, VC4_PACKET_BRANCH_TO_SUB_LIST);
115                        cl_reloc(vc4, &vc4->rcl, vc4->tile_alloc,
116                                 (y * xtiles + x) * 32);
117
118                        if (vc4->resolve & PIPE_CLEAR_COLOR0) {
119                                if (end_of_frame) {
120                                        cl_u8(&vc4->rcl,
121                                              VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF);
122                                } else {
123                                        cl_u8(&vc4->rcl,
124                                              VC4_PACKET_STORE_MS_TILE_BUFFER);
125                                }
126                        } else {
127                                assert(!"unfinished: Need to end the frame\n");
128                        }
129                }
130        }
131}
132
133void
134vc4_flush(struct pipe_context *pctx)
135{
136        struct vc4_context *vc4 = vc4_context(pctx);
137
138        if (!vc4->needs_flush)
139                return;
140
141        cl_u8(&vc4->bcl, VC4_PACKET_FLUSH_ALL);
142        cl_u8(&vc4->bcl, VC4_PACKET_NOP);
143        cl_u8(&vc4->bcl, VC4_PACKET_HALT);
144
145        vc4_setup_rcl(vc4);
146
147        struct drm_vc4_submit_cl submit;
148        memset(&submit, 0, sizeof(submit));
149
150        submit.bo_handles = vc4->bo_handles.base;
151        submit.bo_handle_count = (vc4->bo_handles.next -
152                                  vc4->bo_handles.base) / 4;
153        submit.bin_cl = vc4->bcl.base;
154        submit.bin_cl_size = vc4->bcl.next - vc4->bcl.base;
155        submit.render_cl = vc4->rcl.base;
156        submit.render_cl_size = vc4->rcl.next - vc4->rcl.base;
157        submit.shader_rec = vc4->shader_rec.base;
158        submit.shader_rec_size = vc4->shader_rec.next - vc4->shader_rec.base;
159        submit.shader_rec_count = vc4->shader_rec_count;
160        submit.uniforms = vc4->uniforms.base;
161        submit.uniforms_size = vc4->uniforms.next - vc4->uniforms.base;
162
163        if (!(vc4_debug & VC4_DEBUG_NORAST)) {
164                int ret;
165
166#ifndef USE_VC4_SIMULATOR
167                ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit);
168#else
169                ret = vc4_simulator_flush(vc4, &submit);
170#endif
171                if (ret)
172                        errx(1, "VC4 submit failed\n");
173        }
174
175        vc4_reset_cl(&vc4->bcl);
176        vc4_reset_cl(&vc4->rcl);
177        vc4_reset_cl(&vc4->shader_rec);
178        vc4_reset_cl(&vc4->uniforms);
179        vc4_reset_cl(&vc4->bo_handles);
180        struct vc4_bo **referenced_bos = vc4->bo_pointers.base;
181        for (int i = 0; i < submit.bo_handle_count; i++)
182                vc4_bo_unreference(&referenced_bos[i]);
183        vc4_reset_cl(&vc4->bo_pointers);
184        vc4->shader_rec_count = 0;
185
186        vc4->needs_flush = false;
187        vc4->draw_call_queued = false;
188        vc4->dirty = ~0;
189        vc4->resolve = 0;
190        vc4->cleared = 0;
191}
192
193static void
194vc4_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
195               unsigned flags)
196{
197        vc4_flush(pctx);
198}
199
200/**
201 * Flushes the current command lists if they reference the given BO.
202 *
203 * This helps avoid flushing the command buffers when unnecessary.
204 */
205void
206vc4_flush_for_bo(struct pipe_context *pctx, struct vc4_bo *bo)
207{
208        struct vc4_context *vc4 = vc4_context(pctx);
209
210        if (!vc4->needs_flush)
211                return;
212
213        /* Walk all the referenced BOs in the drawing command list to see if
214         * they match.
215         */
216        struct vc4_bo **referenced_bos = vc4->bo_pointers.base;
217        for (int i = 0; i < (vc4->bo_handles.next -
218                             vc4->bo_handles.base) / 4; i++) {
219                if (referenced_bos[i] == bo) {
220                        vc4_flush(pctx);
221                        return;
222                }
223        }
224
225        /* Also check for the Z/color buffers, since the references to those
226         * are only added immediately before submit.
227         */
228        struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
229        if (csurf) {
230                struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
231                if (ctex->bo == bo) {
232                        vc4_flush(pctx);
233                        return;
234                }
235        }
236
237        struct vc4_surface *zsurf = vc4_surface(vc4->framebuffer.zsbuf);
238        if (zsurf) {
239                struct vc4_resource *ztex =
240                        vc4_resource(zsurf->base.texture);
241                if (ztex->bo == bo) {
242                        vc4_flush(pctx);
243                        return;
244                }
245        }
246}
247
248static void
249vc4_context_destroy(struct pipe_context *pctx)
250{
251        struct vc4_context *vc4 = vc4_context(pctx);
252
253        if (vc4->blitter)
254                util_blitter_destroy(vc4->blitter);
255
256        if (vc4->primconvert)
257                util_primconvert_destroy(vc4->primconvert);
258
259        util_slab_destroy(&vc4->transfer_pool);
260
261        free(vc4);
262}
263
264struct pipe_context *
265vc4_context_create(struct pipe_screen *pscreen, void *priv)
266{
267        struct vc4_screen *screen = vc4_screen(pscreen);
268        struct vc4_context *vc4;
269
270        /* Prevent dumping of the shaders built during context setup. */
271        uint32_t saved_shaderdb_flag = vc4_debug & VC4_DEBUG_SHADERDB;
272        vc4_debug &= ~VC4_DEBUG_SHADERDB;
273
274        vc4 = CALLOC_STRUCT(vc4_context);
275        if (vc4 == NULL)
276                return NULL;
277        struct pipe_context *pctx = &vc4->base;
278
279        vc4->screen = screen;
280
281        pctx->screen = pscreen;
282        pctx->priv = priv;
283        pctx->destroy = vc4_context_destroy;
284        pctx->flush = vc4_pipe_flush;
285
286        vc4_draw_init(pctx);
287        vc4_state_init(pctx);
288        vc4_program_init(pctx);
289        vc4_resource_context_init(pctx);
290
291        vc4_init_cl(vc4, &vc4->bcl);
292        vc4_init_cl(vc4, &vc4->rcl);
293        vc4_init_cl(vc4, &vc4->shader_rec);
294        vc4_init_cl(vc4, &vc4->bo_handles);
295
296        vc4->dirty = ~0;
297        vc4->fd = screen->fd;
298
299        util_slab_create(&vc4->transfer_pool, sizeof(struct pipe_transfer),
300                         16, UTIL_SLAB_SINGLETHREADED);
301        vc4->blitter = util_blitter_create(pctx);
302        if (!vc4->blitter)
303                goto fail;
304
305        vc4->primconvert = util_primconvert_create(pctx,
306                                                   (1 << PIPE_PRIM_QUADS) - 1);
307        if (!vc4->primconvert)
308                goto fail;
309
310        vc4_debug |= saved_shaderdb_flag;
311
312        return &vc4->base;
313
314fail:
315        pctx->destroy(pctx);
316        return NULL;
317}
318