/** * Put a BeginQuery command into all bins. */ void lp_setup_begin_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { /* init the query to its beginning state */ assert(setup->active_query[pq->type] == NULL); set_scene_state(setup, SETUP_ACTIVE, "begin_query"); setup->active_query[pq->type] = pq; /* XXX: It is possible that a query is created before the scene * has been created. This means that setup->scene == NULL resulting * in the query not being binned and thus is ignored. */ if (setup->scene) { if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { if (!lp_setup_flush_and_restart(setup)) return; if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { return; } } } }
/** * Put a BeginQuery command into all bins. */ void lp_setup_begin_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { /* init the query to its beginning state */ assert(setup->active_query == NULL); if (setup->scene) { if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { lp_setup_flush_and_restart(setup); if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { assert(0); return; } } } setup->active_query = pq; }
/** * Put an EndQuery command into all bins. */ void lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { union lp_rast_cmd_arg dummy = { 0 }; assert(setup->active_query == pq); setup->active_query = NULL; /* Setup will automatically re-issue any query which carried over a * scene boundary, and the rasterizer automatically "ends" queries * which are active at the end of a scene, so there is no need to * retry this commands on failure. */ if (setup->scene) { /* pq->fence should be the fence of the *last* scene which * contributed to the query result. */ lp_fence_reference(&pq->fence, setup->scene->fence); if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_END_QUERY, dummy)) { lp_setup_flush(setup, 0, NULL, __FUNCTION__); } } else { lp_fence_reference(&pq->fence, setup->last_fence); } }
/** * Put an EndQuery command into all bins. */ void lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { set_scene_state(setup, SETUP_ACTIVE, "end_query"); if (pq->type != PIPE_QUERY_TIMESTAMP) { assert(setup->active_query[pq->type] == pq); setup->active_query[pq->type] = NULL; } /* Setup will automatically re-issue any query which carried over a * scene boundary, and the rasterizer automatically "ends" queries * which are active at the end of a scene, so there is no need to * retry this commands on failure. */ if (setup->scene) { /* pq->fence should be the fence of the *last* scene which * contributed to the query result. */ lp_fence_reference(&pq->fence, setup->scene->fence); if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_END_QUERY, lp_rast_arg_query(pq))) { lp_setup_flush(setup, NULL, __FUNCTION__); } } else { lp_fence_reference(&pq->fence, setup->last_fence); } }
static boolean lp_setup_try_clear_zs(struct lp_setup_context *setup, double depth, unsigned stencil, unsigned flags) { uint64_t zsmask = 0; uint64_t zsvalue = 0; uint32_t zmask32; uint8_t smask8; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); zmask32 = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; smask8 = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; zsvalue = util_pack64_z_stencil(setup->fb.zsbuf->format, depth, stencil); zsmask = util_pack64_mask_z_stencil(setup->fb.zsbuf->format, zmask32, smask8); zsvalue &= zsmask; if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; /* Add the clear to existing scene. In the unusual case where * both color and depth-stencil are being cleared when there's * already been some rendering, we could discard the currently * binned scene and start again, but I don't see that as being * a common usage. */ if (!lp_scene_bin_everywhere(scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs(zsvalue, zsmask))) return FALSE; } else { /* Put ourselves into the 'pre-clear' state, specifically to try * and accumulate multiple clears to color and depth_stencil * buffers which the app or state-tracker might issue * separately. */ set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); setup->clear.flags |= flags; setup->clear.zsmask |= zsmask; setup->clear.zsvalue = (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); } return TRUE; }
/** * Put a BeginQuery command into all bins. */ void lp_setup_begin_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { set_scene_state(setup, SETUP_ACTIVE, "begin_query"); if (!(pq->type == PIPE_QUERY_OCCLUSION_COUNTER || pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || pq->type == PIPE_QUERY_PIPELINE_STATISTICS)) return; /* init the query to its beginning state */ assert(setup->active_binned_queries < LP_MAX_ACTIVE_BINNED_QUERIES); /* exceeding list size so just ignore the query */ if (setup->active_binned_queries >= LP_MAX_ACTIVE_BINNED_QUERIES) { return; } assert(setup->active_queries[setup->active_binned_queries] == NULL); setup->active_queries[setup->active_binned_queries] = pq; setup->active_binned_queries++; assert(setup->scene); if (setup->scene) { if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { if (!lp_setup_flush_and_restart(setup)) return; if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { return; } } setup->scene->had_queries |= TRUE; } }
/* * Try to clear one color buffer of the attached fb, either by binning a clear * command or queuing up the clear for later (when binning is started). */ static boolean lp_setup_try_clear_color_buffer(struct lp_setup_context *setup, const union pipe_color_union *color, unsigned cbuf) { union lp_rast_cmd_arg clearrb_arg; union util_color uc; enum pipe_format format = setup->fb.cbufs[cbuf]->format; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); if (util_format_is_pure_integer(format)) { /* * We expect int/uint clear values here, though some APIs * might disagree (but in any case util_pack_color() * couldn't handle it)... */ if (util_format_is_pure_sint(format)) { util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1); } else { assert(util_format_is_pure_uint(format)); util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1); } } else { util_pack_color(color->f, format, &uc); } if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; /* Add the clear to existing scene. In the unusual case where * both color and depth-stencil are being cleared when there's * already been some rendering, we could discard the currently * binned scene and start again, but I don't see that as being * a common usage. */ struct lp_rast_clear_rb *cc_scene = (struct lp_rast_clear_rb *) lp_scene_alloc_aligned(scene, sizeof(struct lp_rast_clear_rb), 8); if (!cc_scene) { return FALSE; } cc_scene->cbuf = cbuf; cc_scene->color_val = uc; clearrb_arg.clear_rb = cc_scene; if (!lp_scene_bin_everywhere(scene, LP_RAST_OP_CLEAR_COLOR, clearrb_arg)) return FALSE; } else { /* Put ourselves into the 'pre-clear' state, specifically to try * and accumulate multiple clears to color and depth_stencil * buffers which the app or state-tracker might issue * separately. */ set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); assert(PIPE_CLEAR_COLOR0 == (1 << 2)); setup->clear.flags |= 1 << (cbuf + 2); setup->clear.color_val[cbuf] = uc; } return TRUE; }
static boolean begin_binning( struct lp_setup_context *setup ) { struct lp_scene *scene = setup->scene; boolean need_zsload = FALSE; boolean ok; assert(scene); assert(scene->fence == NULL); /* Always create a fence: */ scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); if (!scene->fence) return FALSE; ok = try_update_scene_state(setup); if (!ok) return FALSE; if (setup->fb.zsbuf && ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) need_zsload = TRUE; LP_DBG(DEBUG_SETUP, "%s color clear bufs: %x depth: %s\n", __FUNCTION__, setup->clear.flags >> 2, need_zsload ? "clear": "load"); if (setup->clear.flags & PIPE_CLEAR_COLOR) { unsigned cbuf; for (cbuf = 0; cbuf < setup->fb.nr_cbufs; cbuf++) { assert(PIPE_CLEAR_COLOR0 == 1 << 2); if (setup->clear.flags & (1 << (2 + cbuf))) { union lp_rast_cmd_arg clearrb_arg; struct lp_rast_clear_rb *cc_scene = (struct lp_rast_clear_rb *) lp_scene_alloc(scene, sizeof(struct lp_rast_clear_rb)); if (!cc_scene) { return FALSE; } cc_scene->cbuf = cbuf; cc_scene->color_val = setup->clear.color_val[cbuf]; clearrb_arg.clear_rb = cc_scene; if (!lp_scene_bin_everywhere(scene, LP_RAST_OP_CLEAR_COLOR, clearrb_arg)) return FALSE; } } } if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs( setup->clear.zsvalue, setup->clear.zsmask)); if (!ok) return FALSE; } } setup->clear.flags = 0; setup->clear.zsmask = 0; setup->clear.zsvalue = 0; scene->had_queries = !!setup->active_binned_queries; LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); return TRUE; }
/** * Put an EndQuery command into all bins. */ void lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { set_scene_state(setup, SETUP_ACTIVE, "end_query"); assert(setup->scene); if (setup->scene) { /* pq->fence should be the fence of the *last* scene which * contributed to the query result. */ lp_fence_reference(&pq->fence, setup->scene->fence); if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || pq->type == PIPE_QUERY_PIPELINE_STATISTICS || pq->type == PIPE_QUERY_TIMESTAMP) { if (pq->type == PIPE_QUERY_TIMESTAMP && !(setup->scene->tiles_x | setup->scene->tiles_y)) { /* * If there's a zero width/height framebuffer, there's no bins and * hence no rast task is ever run. So fill in something here instead. */ pq->end[0] = os_time_get_nano(); } if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_END_QUERY, lp_rast_arg_query(pq))) { if (!lp_setup_flush_and_restart(setup)) goto fail; if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_END_QUERY, lp_rast_arg_query(pq))) { goto fail; } } setup->scene->had_queries |= TRUE; } } else { lp_fence_reference(&pq->fence, setup->last_fence); } fail: /* Need to do this now not earlier since it still needs to be marked as * active when binning it would cause a flush. */ if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || pq->type == PIPE_QUERY_PIPELINE_STATISTICS) { unsigned i; /* remove from active binned query list */ for (i = 0; i < setup->active_binned_queries; i++) { if (setup->active_queries[i] == pq) break; } assert(i < setup->active_binned_queries); if (i == setup->active_binned_queries) return; setup->active_binned_queries--; setup->active_queries[i] = setup->active_queries[setup->active_binned_queries]; setup->active_queries[setup->active_binned_queries] = NULL; } }
static boolean lp_setup_try_clear( struct lp_setup_context *setup, const float *color, double depth, unsigned stencil, unsigned flags ) { uint32_t zsmask = 0; uint32_t zsvalue = 0; union lp_rast_cmd_arg color_arg; unsigned i; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); if (flags & PIPE_CLEAR_COLOR) { for (i = 0; i < 4; i++) color_arg.clear_color[i] = float_to_ubyte(color[i]); } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { unsigned zmask = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; unsigned smask = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; zsvalue = util_pack_z_stencil(setup->fb.zsbuf->format, depth, stencil); zsmask = util_pack_uint_z_stencil(setup->fb.zsbuf->format, zmask, smask); } if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; /* Add the clear to existing scene. In the unusual case where * both color and depth-stencil are being cleared when there's * already been some rendering, we could discard the currently * binned scene and start again, but I don't see that as being * a common usage. */ if (flags & PIPE_CLEAR_COLOR) { if (!lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_COLOR, color_arg )) return FALSE; } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { if (!lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs(zsvalue, zsmask) )) return FALSE; } } else { /* Put ourselves into the 'pre-clear' state, specifically to try * and accumulate multiple clears to color and depth_stencil * buffers which the app or state-tracker might issue * separately. */ set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); setup->clear.flags |= flags; if (flags & PIPE_CLEAR_DEPTHSTENCIL) { setup->clear.zsmask |= zsmask; setup->clear.zsvalue = (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); } if (flags & PIPE_CLEAR_COLOR) { memcpy(setup->clear.color.clear_color, &color_arg, sizeof color_arg); } } return TRUE; }
static void begin_binning( struct lp_setup_context *setup ) { struct lp_scene *scene = setup->scene; boolean need_zsload = FALSE; boolean ok; unsigned i, j; assert(scene); assert(scene->fence == NULL); /* Always create a fence: */ scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); /* Initialize the bin flags and x/y coords: */ for (i = 0; i < scene->tiles_x; i++) { for (j = 0; j < scene->tiles_y; j++) { scene->tile[i][j].x = i; scene->tile[i][j].y = j; } } ok = try_update_scene_state(setup); assert(ok); if (setup->fb.zsbuf && ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) need_zsload = TRUE; LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", need_zsload ? "clear": "load"); if (setup->fb.nr_cbufs) { if (setup->clear.flags & PIPE_CLEAR_COLOR) { ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_COLOR, setup->clear.color ); assert(ok); } } if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { if (!need_zsload) scene->has_depthstencil_clear = TRUE; ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs( setup->clear.zsvalue, setup->clear.zsmask)); assert(ok); } } if (setup->active_query) { ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(setup->active_query) ); assert(ok); } setup->clear.flags = 0; setup->clear.zsmask = 0; setup->clear.zsvalue = 0; LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); }