static void parse_sublists(void) { list_for_each_entry(struct vc4_mem_area_rec, rec, &dump.mem_areas, link) { switch (rec->type) { case VC4_MEM_AREA_SUB_LIST: printf("Sublist at 0x%08x:\n", rec->paddr); if (!rec->addr) { printf(" No mapping found\n"); continue; } vc4_dump_cl(rec->paddr, rec->paddr + rec->size, true, false, rec->prim_mode); printf("\n"); break; case VC4_MEM_AREA_COMPRESSED_PRIM_LIST: printf("Compressed list at 0x%08x:\n", rec->paddr); if (!rec->addr) { printf(" No mapping found\n"); continue; } vc4_dump_cl(rec->paddr, rec->paddr + rec->size, true, true, rec->prim_mode); printf("\n"); break; default: break; } } }
/** * Submits the job to the kernel and then reinitializes it. */ void vc4_job_submit(struct vc4_context *vc4) { if (vc4_debug & VC4_DEBUG_CL) { fprintf(stderr, "BCL:\n"); vc4_dump_cl(vc4->bcl.base, vc4->bcl.next - vc4->bcl.base, false); fprintf(stderr, "RCL:\n"); vc4_dump_cl(vc4->rcl.base, vc4->rcl.next - vc4->rcl.base, true); } struct drm_vc4_submit_cl submit; memset(&submit, 0, sizeof(submit)); submit.bo_handles = (uintptr_t)vc4->bo_handles.base; submit.bo_handle_count = (vc4->bo_handles.next - vc4->bo_handles.base) / 4; submit.bin_cl = (uintptr_t)vc4->bcl.base; submit.bin_cl_size = vc4->bcl.next - vc4->bcl.base; submit.render_cl = (uintptr_t)vc4->rcl.base; submit.render_cl_size = vc4->rcl.next - vc4->rcl.base; submit.shader_rec = (uintptr_t)vc4->shader_rec.base; submit.shader_rec_size = vc4->shader_rec.next - vc4->shader_rec.base; submit.shader_rec_count = vc4->shader_rec_count; submit.uniforms = (uintptr_t)vc4->uniforms.base; submit.uniforms_size = vc4->uniforms.next - vc4->uniforms.base; if (!(vc4_debug & VC4_DEBUG_NORAST)) { int ret; #ifndef USE_VC4_SIMULATOR ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit); #else ret = vc4_simulator_flush(vc4, &submit); #endif if (ret) { fprintf(stderr, "VC4 submit failed\n"); abort(); } } vc4->last_emit_seqno = submit.seqno; if (vc4_debug & VC4_DEBUG_ALWAYS_SYNC) { if (!vc4_wait_seqno(vc4->screen, vc4->last_emit_seqno, PIPE_TIMEOUT_INFINITE)) { fprintf(stderr, "Wait failed.\n"); abort(); } } vc4_job_reset(vc4); }
static void parse_cls(void) { if (dump.state->start_bin != dump.state->ct0ea) { printf("Bin CL at 0x%08x\n", dump.state->start_bin); vc4_dump_cl(dump.state->start_bin, dump.state->ct0ea, false, false, ~0); } printf("Render CL at 0x%08x\n", dump.state->start_render); vc4_dump_cl(dump.state->start_render, dump.state->ct1ea, true, false, ~0); }
/** * Submits the job to the kernel and then reinitializes it. */ void vc4_job_submit(struct vc4_context *vc4) { if (vc4_debug & VC4_DEBUG_CL) { fprintf(stderr, "BCL:\n"); vc4_dump_cl(vc4->bcl.base, cl_offset(&vc4->bcl), false); } struct drm_vc4_submit_cl submit; memset(&submit, 0, sizeof(submit)); cl_ensure_space(&vc4->bo_handles, 6 * sizeof(uint32_t)); cl_ensure_space(&vc4->bo_pointers, 6 * sizeof(struct vc4_bo *)); vc4_submit_setup_rcl_surface(vc4, &submit.color_read, vc4->color_read, false, false); vc4_submit_setup_rcl_render_config_surface(vc4, &submit.color_write, vc4->color_write); vc4_submit_setup_rcl_surface(vc4, &submit.zs_read, vc4->zs_read, true, false); vc4_submit_setup_rcl_surface(vc4, &submit.zs_write, vc4->zs_write, true, true); vc4_submit_setup_rcl_msaa_surface(vc4, &submit.msaa_color_write, vc4->msaa_color_write); vc4_submit_setup_rcl_msaa_surface(vc4, &submit.msaa_zs_write, vc4->msaa_zs_write); if (vc4->msaa) { /* This bit controls how many pixels the general * (i.e. subsampled) loads/stores are iterating over * (multisample loads replicate out to the other samples). */ submit.color_write.bits |= VC4_RENDER_CONFIG_MS_MODE_4X; /* Controls whether color_write's * VC4_PACKET_STORE_MS_TILE_BUFFER does 4x decimation */ submit.color_write.bits |= VC4_RENDER_CONFIG_DECIMATE_MODE_4X; } submit.bo_handles = (uintptr_t)vc4->bo_handles.base; submit.bo_handle_count = cl_offset(&vc4->bo_handles) / 4; submit.bin_cl = (uintptr_t)vc4->bcl.base; submit.bin_cl_size = cl_offset(&vc4->bcl); submit.shader_rec = (uintptr_t)vc4->shader_rec.base; submit.shader_rec_size = cl_offset(&vc4->shader_rec); submit.shader_rec_count = vc4->shader_rec_count; submit.uniforms = (uintptr_t)vc4->uniforms.base; submit.uniforms_size = cl_offset(&vc4->uniforms); assert(vc4->draw_min_x != ~0 && vc4->draw_min_y != ~0); submit.min_x_tile = vc4->draw_min_x / vc4->tile_width; submit.min_y_tile = vc4->draw_min_y / vc4->tile_height; submit.max_x_tile = (vc4->draw_max_x - 1) / vc4->tile_width; submit.max_y_tile = (vc4->draw_max_y - 1) / vc4->tile_height; submit.width = vc4->draw_width; submit.height = vc4->draw_height; if (vc4->cleared) { submit.flags |= VC4_SUBMIT_CL_USE_CLEAR_COLOR; submit.clear_color[0] = vc4->clear_color[0]; submit.clear_color[1] = vc4->clear_color[1]; submit.clear_z = vc4->clear_depth; submit.clear_s = vc4->clear_stencil; } if (!(vc4_debug & VC4_DEBUG_NORAST)) { int ret; #ifndef USE_VC4_SIMULATOR ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit); #else ret = vc4_simulator_flush(vc4, &submit); #endif static bool warned = false; if (ret && !warned) { fprintf(stderr, "Draw call returned %s. " "Expect corruption.\n", strerror(errno)); warned = true; } } vc4->last_emit_seqno = submit.seqno; if (vc4_debug & VC4_DEBUG_ALWAYS_SYNC) { if (!vc4_wait_seqno(vc4->screen, vc4->last_emit_seqno, PIPE_TIMEOUT_INFINITE, "sync")) { fprintf(stderr, "Wait failed.\n"); abort(); } } vc4_job_reset(vc4); }
/** * Submits the job to the kernel and then reinitializes it. */ void vc4_job_submit(struct vc4_context *vc4) { if (vc4_debug & VC4_DEBUG_CL) { fprintf(stderr, "BCL:\n"); vc4_dump_cl(vc4->bcl.base, cl_offset(&vc4->bcl), false); } struct drm_vc4_submit_cl submit; memset(&submit, 0, sizeof(submit)); cl_ensure_space(&vc4->bo_handles, 4 * sizeof(uint32_t)); cl_ensure_space(&vc4->bo_pointers, 4 * sizeof(struct vc4_bo *)); vc4_submit_setup_rcl_surface(vc4, &submit.color_read, vc4->color_read, false, false); vc4_submit_setup_ms_rcl_surface(vc4, &submit.color_ms_write, vc4->color_write); vc4_submit_setup_rcl_surface(vc4, &submit.zs_read, vc4->zs_read, true, false); vc4_submit_setup_rcl_surface(vc4, &submit.zs_write, vc4->zs_write, true, true); submit.bo_handles = (uintptr_t)vc4->bo_handles.base; submit.bo_handle_count = cl_offset(&vc4->bo_handles) / 4; submit.bin_cl = (uintptr_t)vc4->bcl.base; submit.bin_cl_size = cl_offset(&vc4->bcl); submit.shader_rec = (uintptr_t)vc4->shader_rec.base; submit.shader_rec_size = cl_offset(&vc4->shader_rec); submit.shader_rec_count = vc4->shader_rec_count; submit.uniforms = (uintptr_t)vc4->uniforms.base; submit.uniforms_size = cl_offset(&vc4->uniforms); assert(vc4->draw_min_x != ~0 && vc4->draw_min_y != ~0); submit.min_x_tile = vc4->draw_min_x / 64; submit.min_y_tile = vc4->draw_min_y / 64; submit.max_x_tile = (vc4->draw_max_x - 1) / 64; submit.max_y_tile = (vc4->draw_max_y - 1) / 64; submit.width = vc4->draw_width; submit.height = vc4->draw_height; if (vc4->cleared) { submit.flags |= VC4_SUBMIT_CL_USE_CLEAR_COLOR; submit.clear_color[0] = vc4->clear_color[0]; submit.clear_color[1] = vc4->clear_color[1]; submit.clear_z = vc4->clear_depth; submit.clear_s = vc4->clear_stencil; } if (!(vc4_debug & VC4_DEBUG_NORAST)) { int ret; #ifndef USE_VC4_SIMULATOR ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit); #else ret = vc4_simulator_flush(vc4, &submit); #endif if (ret) { fprintf(stderr, "VC4 submit failed\n"); abort(); } } vc4->last_emit_seqno = submit.seqno; if (vc4_debug & VC4_DEBUG_ALWAYS_SYNC) { if (!vc4_wait_seqno(vc4->screen, vc4->last_emit_seqno, PIPE_TIMEOUT_INFINITE, "sync")) { fprintf(stderr, "Wait failed.\n"); abort(); } } vc4_job_reset(vc4); }
int vc4_simulator_flush(struct vc4_context *vc4, struct drm_vc4_submit_cl *args) { struct vc4_screen *screen = vc4->screen; struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]); struct vc4_resource *ctex = csurf ? vc4_resource(csurf->base.texture) : NULL; uint32_t winsys_stride = ctex ? ctex->bo->simulator_winsys_stride : 0; uint32_t sim_stride = ctex ? ctex->slices[0].stride : 0; uint32_t row_len = MIN2(sim_stride, winsys_stride); struct exec_info exec; struct drm_device local_dev = { .vc4 = vc4, .simulator_mem_next = OVERFLOW_SIZE, }; struct drm_device *dev = &local_dev; int ret; memset(&exec, 0, sizeof(exec)); if (ctex && ctex->bo->simulator_winsys_map) { #if 0 fprintf(stderr, "%dx%d %d %d %d\n", ctex->base.b.width0, ctex->base.b.height0, winsys_stride, sim_stride, ctex->bo->size); #endif for (int y = 0; y < ctex->base.b.height0; y++) { memcpy(ctex->bo->map + y * sim_stride, ctex->bo->simulator_winsys_map + y * winsys_stride, row_len); } } exec.args = args; ret = vc4_simulator_pin_bos(dev, &exec); if (ret) return ret; ret = vc4_cl_validate(dev, &exec); if (ret) return ret; int bfc = simpenrose_do_binning(exec.ct0ca, exec.ct0ea); if (bfc != 1) { fprintf(stderr, "Binning returned %d flushes, should be 1.\n", bfc); fprintf(stderr, "Relocated binning command list:\n"); vc4_dump_cl(screen->simulator_mem_base + exec.ct0ca, exec.ct0ea - exec.ct0ca, false); abort(); } int rfc = simpenrose_do_rendering(exec.ct1ca, exec.ct1ea); if (rfc != 1) { fprintf(stderr, "Rendering returned %d frames, should be 1.\n", rfc); fprintf(stderr, "Relocated render command list:\n"); vc4_dump_cl(screen->simulator_mem_base + exec.ct1ca, exec.ct1ea - exec.ct1ca, true); abort(); } ret = vc4_simulator_unpin_bos(&exec); if (ret) return ret; vc4_bo_unreference(&exec.exec_bo->bo); free(exec.exec_bo); if (ctex && ctex->bo->simulator_winsys_map) { for (int y = 0; y < ctex->base.b.height0; y++) { memcpy(ctex->bo->simulator_winsys_map + y * winsys_stride, ctex->bo->map + y * sim_stride, row_len); } } return 0; }
void vc4_flush(struct pipe_context *pctx) { struct vc4_context *vc4 = vc4_context(pctx); if (!vc4->needs_flush) return; /* The FLUSH caps all of our bin lists with a VC4_PACKET_RETURN. */ cl_u8(&vc4->bcl, VC4_PACKET_FLUSH); cl_u8(&vc4->bcl, VC4_PACKET_NOP); cl_u8(&vc4->bcl, VC4_PACKET_HALT); vc4_setup_rcl(vc4); if (vc4_debug & VC4_DEBUG_CL) { fprintf(stderr, "BCL:\n"); vc4_dump_cl(vc4->bcl.base, vc4->bcl.end - vc4->bcl.base, false); fprintf(stderr, "RCL:\n"); vc4_dump_cl(vc4->rcl.base, vc4->rcl.end - vc4->rcl.base, true); } struct drm_vc4_submit_cl submit; memset(&submit, 0, sizeof(submit)); submit.bo_handles = vc4->bo_handles.base; submit.bo_handle_count = (vc4->bo_handles.next - vc4->bo_handles.base) / 4; submit.bin_cl = vc4->bcl.base; submit.bin_cl_size = vc4->bcl.next - vc4->bcl.base; submit.render_cl = vc4->rcl.base; submit.render_cl_size = vc4->rcl.next - vc4->rcl.base; submit.shader_rec = vc4->shader_rec.base; submit.shader_rec_size = vc4->shader_rec.next - vc4->shader_rec.base; submit.shader_rec_count = vc4->shader_rec_count; submit.uniforms = vc4->uniforms.base; submit.uniforms_size = vc4->uniforms.next - vc4->uniforms.base; if (!(vc4_debug & VC4_DEBUG_NORAST)) { int ret; #ifndef USE_VC4_SIMULATOR ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit); #else ret = vc4_simulator_flush(vc4, &submit); #endif if (ret) { fprintf(stderr, "VC4 submit failed\n"); abort(); } } vc4_reset_cl(&vc4->bcl); vc4_reset_cl(&vc4->rcl); vc4_reset_cl(&vc4->shader_rec); vc4_reset_cl(&vc4->uniforms); vc4_reset_cl(&vc4->bo_handles); struct vc4_bo **referenced_bos = vc4->bo_pointers.base; for (int i = 0; i < submit.bo_handle_count; i++) vc4_bo_unreference(&referenced_bos[i]); vc4_reset_cl(&vc4->bo_pointers); vc4->shader_rec_count = 0; vc4->needs_flush = false; vc4->draw_call_queued = false; /* We have no hardware context saved between our draw calls, so we * need to flag the next draw as needing all state emitted. Emitting * all state at the start of our draws is also what ensures that we * return to the state we need after a previous tile has finished. */ vc4->dirty = ~0; vc4->resolve = 0; vc4->cleared = 0; }