2 * Copyright © 2014-2015 Broadcom
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:
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
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
26 * Functions for submitting VC4 render jobs to the kernel.
30 #include "vc4_context.h"
33 vc4_job_init(struct vc4_context
*vc4
)
35 vc4_init_cl(vc4
, &vc4
->bcl
);
36 vc4_init_cl(vc4
, &vc4
->shader_rec
);
37 vc4_init_cl(vc4
, &vc4
->uniforms
);
38 vc4_init_cl(vc4
, &vc4
->bo_handles
);
39 vc4_init_cl(vc4
, &vc4
->bo_pointers
);
44 vc4_job_reset(struct vc4_context
*vc4
)
46 struct vc4_bo
**referenced_bos
= vc4
->bo_pointers
.base
;
47 for (int i
= 0; i
< cl_offset(&vc4
->bo_handles
) / 4; i
++) {
48 vc4_bo_unreference(&referenced_bos
[i
]);
50 vc4_reset_cl(&vc4
->bcl
);
51 vc4_reset_cl(&vc4
->shader_rec
);
52 vc4_reset_cl(&vc4
->uniforms
);
53 vc4_reset_cl(&vc4
->bo_handles
);
54 vc4_reset_cl(&vc4
->bo_pointers
);
55 vc4
->shader_rec_count
= 0;
57 vc4
->needs_flush
= false;
58 vc4
->draw_calls_queued
= 0;
60 /* We have no hardware context saved between our draw calls, so we
61 * need to flag the next draw as needing all state emitted. Emitting
62 * all state at the start of our draws is also what ensures that we
63 * return to the state we need after a previous tile has finished.
76 vc4_submit_setup_rcl_surface(struct vc4_context
*vc4
,
77 struct drm_vc4_submit_rcl_surface
*submit_surf
,
78 struct pipe_surface
*psurf
,
79 bool is_depth
, bool is_write
)
81 struct vc4_surface
*surf
= vc4_surface(psurf
);
84 submit_surf
->hindex
= ~0;
88 struct vc4_resource
*rsc
= vc4_resource(psurf
->texture
);
89 submit_surf
->hindex
= vc4_gem_hindex(vc4
, rsc
->bo
);
90 submit_surf
->offset
= surf
->offset
;
92 if (psurf
->texture
->nr_samples
<= 1) {
95 VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_ZS
,
96 VC4_LOADSTORE_TILE_BUFFER_BUFFER
);
100 VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_COLOR
,
101 VC4_LOADSTORE_TILE_BUFFER_BUFFER
) |
102 VC4_SET_FIELD(vc4_rt_format_is_565(psurf
->format
) ?
103 VC4_LOADSTORE_TILE_BUFFER_BGR565
:
104 VC4_LOADSTORE_TILE_BUFFER_RGBA8888
,
105 VC4_LOADSTORE_TILE_BUFFER_FORMAT
);
108 VC4_SET_FIELD(surf
->tiling
,
109 VC4_LOADSTORE_TILE_BUFFER_TILING
);
112 submit_surf
->flags
|= VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES
;
120 vc4_submit_setup_rcl_render_config_surface(struct vc4_context
*vc4
,
121 struct drm_vc4_submit_rcl_surface
*submit_surf
,
122 struct pipe_surface
*psurf
)
124 struct vc4_surface
*surf
= vc4_surface(psurf
);
127 submit_surf
->hindex
= ~0;
131 struct vc4_resource
*rsc
= vc4_resource(psurf
->texture
);
132 submit_surf
->hindex
= vc4_gem_hindex(vc4
, rsc
->bo
);
133 submit_surf
->offset
= surf
->offset
;
135 if (psurf
->texture
->nr_samples
<= 1) {
137 VC4_SET_FIELD(vc4_rt_format_is_565(surf
->base
.format
) ?
138 VC4_RENDER_CONFIG_FORMAT_BGR565
:
139 VC4_RENDER_CONFIG_FORMAT_RGBA8888
,
140 VC4_RENDER_CONFIG_FORMAT
) |
141 VC4_SET_FIELD(surf
->tiling
,
142 VC4_RENDER_CONFIG_MEMORY_FORMAT
);
149 vc4_submit_setup_rcl_msaa_surface(struct vc4_context
*vc4
,
150 struct drm_vc4_submit_rcl_surface
*submit_surf
,
151 struct pipe_surface
*psurf
)
153 struct vc4_surface
*surf
= vc4_surface(psurf
);
156 submit_surf
->hindex
= ~0;
160 struct vc4_resource
*rsc
= vc4_resource(psurf
->texture
);
161 submit_surf
->hindex
= vc4_gem_hindex(vc4
, rsc
->bo
);
162 submit_surf
->offset
= surf
->offset
;
163 submit_surf
->bits
= 0;
168 * Submits the job to the kernel and then reinitializes it.
171 vc4_job_submit(struct vc4_context
*vc4
)
173 if (vc4_debug
& VC4_DEBUG_CL
) {
174 fprintf(stderr
, "BCL:\n");
175 vc4_dump_cl(vc4
->bcl
.base
, cl_offset(&vc4
->bcl
), false);
178 struct drm_vc4_submit_cl submit
;
179 memset(&submit
, 0, sizeof(submit
));
181 cl_ensure_space(&vc4
->bo_handles
, 6 * sizeof(uint32_t));
182 cl_ensure_space(&vc4
->bo_pointers
, 6 * sizeof(struct vc4_bo
*));
184 vc4_submit_setup_rcl_surface(vc4
, &submit
.color_read
,
185 vc4
->color_read
, false, false);
186 vc4_submit_setup_rcl_render_config_surface(vc4
, &submit
.color_write
,
188 vc4_submit_setup_rcl_surface(vc4
, &submit
.zs_read
,
189 vc4
->zs_read
, true, false);
190 vc4_submit_setup_rcl_surface(vc4
, &submit
.zs_write
,
191 vc4
->zs_write
, true, true);
193 vc4_submit_setup_rcl_msaa_surface(vc4
, &submit
.msaa_color_write
,
194 vc4
->msaa_color_write
);
195 vc4_submit_setup_rcl_msaa_surface(vc4
, &submit
.msaa_zs_write
,
199 /* This bit controls how many pixels the general
200 * (i.e. subsampled) loads/stores are iterating over
201 * (multisample loads replicate out to the other samples).
203 submit
.color_write
.bits
|= VC4_RENDER_CONFIG_MS_MODE_4X
;
204 /* Controls whether color_write's
205 * VC4_PACKET_STORE_MS_TILE_BUFFER does 4x decimation
207 submit
.color_write
.bits
|= VC4_RENDER_CONFIG_DECIMATE_MODE_4X
;
210 submit
.bo_handles
= (uintptr_t)vc4
->bo_handles
.base
;
211 submit
.bo_handle_count
= cl_offset(&vc4
->bo_handles
) / 4;
212 submit
.bin_cl
= (uintptr_t)vc4
->bcl
.base
;
213 submit
.bin_cl_size
= cl_offset(&vc4
->bcl
);
214 submit
.shader_rec
= (uintptr_t)vc4
->shader_rec
.base
;
215 submit
.shader_rec_size
= cl_offset(&vc4
->shader_rec
);
216 submit
.shader_rec_count
= vc4
->shader_rec_count
;
217 submit
.uniforms
= (uintptr_t)vc4
->uniforms
.base
;
218 submit
.uniforms_size
= cl_offset(&vc4
->uniforms
);
220 assert(vc4
->draw_min_x
!= ~0 && vc4
->draw_min_y
!= ~0);
221 submit
.min_x_tile
= vc4
->draw_min_x
/ vc4
->tile_width
;
222 submit
.min_y_tile
= vc4
->draw_min_y
/ vc4
->tile_height
;
223 submit
.max_x_tile
= (vc4
->draw_max_x
- 1) / vc4
->tile_width
;
224 submit
.max_y_tile
= (vc4
->draw_max_y
- 1) / vc4
->tile_height
;
225 submit
.width
= vc4
->draw_width
;
226 submit
.height
= vc4
->draw_height
;
228 submit
.flags
|= VC4_SUBMIT_CL_USE_CLEAR_COLOR
;
229 submit
.clear_color
[0] = vc4
->clear_color
[0];
230 submit
.clear_color
[1] = vc4
->clear_color
[1];
231 submit
.clear_z
= vc4
->clear_depth
;
232 submit
.clear_s
= vc4
->clear_stencil
;
235 if (!(vc4_debug
& VC4_DEBUG_NORAST
)) {
238 #ifndef USE_VC4_SIMULATOR
239 ret
= drmIoctl(vc4
->fd
, DRM_IOCTL_VC4_SUBMIT_CL
, &submit
);
241 ret
= vc4_simulator_flush(vc4
, &submit
);
243 static bool warned
= false;
244 if (ret
&& !warned
) {
245 fprintf(stderr
, "Draw call returned %s. "
246 "Expect corruption.\n", strerror(errno
));
251 vc4
->last_emit_seqno
= submit
.seqno
;
253 if (vc4_debug
& VC4_DEBUG_ALWAYS_SYNC
) {
254 if (!vc4_wait_seqno(vc4
->screen
, vc4
->last_emit_seqno
,
255 PIPE_TIMEOUT_INFINITE
, "sync")) {
256 fprintf(stderr
, "Wait failed.\n");