vc4_job.c revision f473348468ae1c68e7ef8eaf29f2cc51d17fbec7
1/* 2 * Copyright © 2014-2015 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/** @file vc4_job.c 25 * 26 * Functions for submitting VC4 render jobs to the kernel. 27 */ 28 29#include <xf86drm.h> 30#include "vc4_context.h" 31 32void 33vc4_job_init(struct vc4_job *job) 34{ 35 vc4_init_cl(job, &job->bcl); 36 vc4_init_cl(job, &job->shader_rec); 37 vc4_init_cl(job, &job->uniforms); 38 vc4_init_cl(job, &job->bo_handles); 39 vc4_init_cl(job, &job->bo_pointers); 40 vc4_job_reset(job); 41} 42 43void 44vc4_job_reset(struct vc4_job *job) 45{ 46 struct vc4_bo **referenced_bos = job->bo_pointers.base; 47 for (int i = 0; i < cl_offset(&job->bo_handles) / 4; i++) { 48 vc4_bo_unreference(&referenced_bos[i]); 49 } 50 vc4_reset_cl(&job->bcl); 51 vc4_reset_cl(&job->shader_rec); 52 vc4_reset_cl(&job->uniforms); 53 vc4_reset_cl(&job->bo_handles); 54 vc4_reset_cl(&job->bo_pointers); 55 job->shader_rec_count = 0; 56 57 job->needs_flush = false; 58 job->draw_calls_queued = 0; 59 60 job->resolve = 0; 61 job->cleared = 0; 62 63 job->draw_min_x = ~0; 64 job->draw_min_y = ~0; 65 job->draw_max_x = 0; 66 job->draw_max_y = 0; 67 68 pipe_surface_reference(&job->color_write, NULL); 69 pipe_surface_reference(&job->color_read, NULL); 70 pipe_surface_reference(&job->msaa_color_write, NULL); 71 pipe_surface_reference(&job->zs_write, NULL); 72 pipe_surface_reference(&job->zs_read, NULL); 73 pipe_surface_reference(&job->msaa_zs_write, NULL); 74} 75 76static void 77vc4_submit_setup_rcl_surface(struct vc4_job *job, 78 struct drm_vc4_submit_rcl_surface *submit_surf, 79 struct pipe_surface *psurf, 80 bool is_depth, bool is_write) 81{ 82 struct vc4_surface *surf = vc4_surface(psurf); 83 84 if (!surf) 85 return; 86 87 struct vc4_resource *rsc = vc4_resource(psurf->texture); 88 submit_surf->hindex = vc4_gem_hindex(job, rsc->bo); 89 submit_surf->offset = surf->offset; 90 91 if (psurf->texture->nr_samples <= 1) { 92 if (is_depth) { 93 submit_surf->bits = 94 VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_ZS, 95 VC4_LOADSTORE_TILE_BUFFER_BUFFER); 96 97 } else { 98 submit_surf->bits = 99 VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_COLOR, 100 VC4_LOADSTORE_TILE_BUFFER_BUFFER) | 101 VC4_SET_FIELD(vc4_rt_format_is_565(psurf->format) ? 102 VC4_LOADSTORE_TILE_BUFFER_BGR565 : 103 VC4_LOADSTORE_TILE_BUFFER_RGBA8888, 104 VC4_LOADSTORE_TILE_BUFFER_FORMAT); 105 } 106 submit_surf->bits |= 107 VC4_SET_FIELD(surf->tiling, 108 VC4_LOADSTORE_TILE_BUFFER_TILING); 109 } else { 110 assert(!is_write); 111 submit_surf->flags |= VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES; 112 } 113 114 if (is_write) 115 rsc->writes++; 116} 117 118static void 119vc4_submit_setup_rcl_render_config_surface(struct vc4_job *job, 120 struct drm_vc4_submit_rcl_surface *submit_surf, 121 struct pipe_surface *psurf) 122{ 123 struct vc4_surface *surf = vc4_surface(psurf); 124 125 if (!surf) 126 return; 127 128 struct vc4_resource *rsc = vc4_resource(psurf->texture); 129 submit_surf->hindex = vc4_gem_hindex(job, rsc->bo); 130 submit_surf->offset = surf->offset; 131 132 if (psurf->texture->nr_samples <= 1) { 133 submit_surf->bits = 134 VC4_SET_FIELD(vc4_rt_format_is_565(surf->base.format) ? 135 VC4_RENDER_CONFIG_FORMAT_BGR565 : 136 VC4_RENDER_CONFIG_FORMAT_RGBA8888, 137 VC4_RENDER_CONFIG_FORMAT) | 138 VC4_SET_FIELD(surf->tiling, 139 VC4_RENDER_CONFIG_MEMORY_FORMAT); 140 } 141 142 rsc->writes++; 143} 144 145static void 146vc4_submit_setup_rcl_msaa_surface(struct vc4_job *job, 147 struct drm_vc4_submit_rcl_surface *submit_surf, 148 struct pipe_surface *psurf) 149{ 150 struct vc4_surface *surf = vc4_surface(psurf); 151 152 if (!surf) 153 return; 154 155 struct vc4_resource *rsc = vc4_resource(psurf->texture); 156 submit_surf->hindex = vc4_gem_hindex(job, rsc->bo); 157 submit_surf->offset = surf->offset; 158 submit_surf->bits = 0; 159 rsc->writes++; 160} 161 162/** 163 * Submits the job to the kernel and then reinitializes it. 164 */ 165void 166vc4_job_submit(struct vc4_context *vc4, struct vc4_job *job) 167{ 168 if (!job->needs_flush) 169 return; 170 171 /* The RCL setup would choke if the draw bounds cause no drawing, so 172 * just drop the drawing if that's the case. 173 */ 174 if (job->draw_max_x <= job->draw_min_x || 175 job->draw_max_y <= job->draw_min_y) { 176 vc4_job_reset(job); 177 return; 178 } 179 180 if (vc4_debug & VC4_DEBUG_CL) { 181 fprintf(stderr, "BCL:\n"); 182 vc4_dump_cl(job->bcl.base, cl_offset(&job->bcl), false); 183 } 184 185 if (cl_offset(&job->bcl) > 0) { 186 /* Increment the semaphore indicating that binning is done and 187 * unblocking the render thread. Note that this doesn't act 188 * until the FLUSH completes. 189 */ 190 cl_ensure_space(&job->bcl, 8); 191 struct vc4_cl_out *bcl = cl_start(&job->bcl); 192 cl_u8(&bcl, VC4_PACKET_INCREMENT_SEMAPHORE); 193 /* The FLUSH caps all of our bin lists with a 194 * VC4_PACKET_RETURN. 195 */ 196 cl_u8(&bcl, VC4_PACKET_FLUSH); 197 cl_end(&job->bcl, bcl); 198 } 199 struct drm_vc4_submit_cl submit = { 200 .color_read.hindex = ~0, 201 .zs_read.hindex = ~0, 202 .color_write.hindex = ~0, 203 .msaa_color_write.hindex = ~0, 204 .zs_write.hindex = ~0, 205 .msaa_zs_write.hindex = ~0, 206 }; 207 208 cl_ensure_space(&job->bo_handles, 6 * sizeof(uint32_t)); 209 cl_ensure_space(&job->bo_pointers, 6 * sizeof(struct vc4_bo *)); 210 211 if (job->resolve & PIPE_CLEAR_COLOR) { 212 if (!(job->cleared & PIPE_CLEAR_COLOR)) { 213 vc4_submit_setup_rcl_surface(job, &submit.color_read, 214 job->color_read, 215 false, false); 216 } 217 vc4_submit_setup_rcl_render_config_surface(job, 218 &submit.color_write, 219 job->color_write); 220 vc4_submit_setup_rcl_msaa_surface(job, 221 &submit.msaa_color_write, 222 job->msaa_color_write); 223 } 224 if (job->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) { 225 if (!(job->cleared & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) { 226 vc4_submit_setup_rcl_surface(job, &submit.zs_read, 227 job->zs_read, true, false); 228 } 229 vc4_submit_setup_rcl_surface(job, &submit.zs_write, 230 job->zs_write, true, true); 231 vc4_submit_setup_rcl_msaa_surface(job, &submit.msaa_zs_write, 232 job->msaa_zs_write); 233 } 234 235 if (job->msaa) { 236 /* This bit controls how many pixels the general 237 * (i.e. subsampled) loads/stores are iterating over 238 * (multisample loads replicate out to the other samples). 239 */ 240 submit.color_write.bits |= VC4_RENDER_CONFIG_MS_MODE_4X; 241 /* Controls whether color_write's 242 * VC4_PACKET_STORE_MS_TILE_BUFFER does 4x decimation 243 */ 244 submit.color_write.bits |= VC4_RENDER_CONFIG_DECIMATE_MODE_4X; 245 } 246 247 submit.bo_handles = (uintptr_t)job->bo_handles.base; 248 submit.bo_handle_count = cl_offset(&job->bo_handles) / 4; 249 submit.bin_cl = (uintptr_t)job->bcl.base; 250 submit.bin_cl_size = cl_offset(&job->bcl); 251 submit.shader_rec = (uintptr_t)job->shader_rec.base; 252 submit.shader_rec_size = cl_offset(&job->shader_rec); 253 submit.shader_rec_count = job->shader_rec_count; 254 submit.uniforms = (uintptr_t)job->uniforms.base; 255 submit.uniforms_size = cl_offset(&job->uniforms); 256 257 assert(job->draw_min_x != ~0 && job->draw_min_y != ~0); 258 submit.min_x_tile = job->draw_min_x / job->tile_width; 259 submit.min_y_tile = job->draw_min_y / job->tile_height; 260 submit.max_x_tile = (job->draw_max_x - 1) / job->tile_width; 261 submit.max_y_tile = (job->draw_max_y - 1) / job->tile_height; 262 submit.width = job->draw_width; 263 submit.height = job->draw_height; 264 if (job->cleared) { 265 submit.flags |= VC4_SUBMIT_CL_USE_CLEAR_COLOR; 266 submit.clear_color[0] = job->clear_color[0]; 267 submit.clear_color[1] = job->clear_color[1]; 268 submit.clear_z = job->clear_depth; 269 submit.clear_s = job->clear_stencil; 270 } 271 272 if (!(vc4_debug & VC4_DEBUG_NORAST)) { 273 int ret; 274 275#ifndef USE_VC4_SIMULATOR 276 ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit); 277#else 278 ret = vc4_simulator_flush(vc4, &submit); 279#endif 280 static bool warned = false; 281 if (ret && !warned) { 282 fprintf(stderr, "Draw call returned %s. " 283 "Expect corruption.\n", strerror(errno)); 284 warned = true; 285 } else if (!ret) { 286 vc4->last_emit_seqno = submit.seqno; 287 } 288 } 289 290 if (vc4->last_emit_seqno - vc4->screen->finished_seqno > 5) { 291 if (!vc4_wait_seqno(vc4->screen, 292 vc4->last_emit_seqno - 5, 293 PIPE_TIMEOUT_INFINITE, 294 "job throttling")) { 295 fprintf(stderr, "Job throttling failed\n"); 296 } 297 } 298 299 if (vc4_debug & VC4_DEBUG_ALWAYS_SYNC) { 300 if (!vc4_wait_seqno(vc4->screen, vc4->last_emit_seqno, 301 PIPE_TIMEOUT_INFINITE, "sync")) { 302 fprintf(stderr, "Wait failed.\n"); 303 abort(); 304 } 305 } 306 307 vc4_job_reset(vc4->job); 308} 309