diff options
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_setup.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 244 |
1 files changed, 146 insertions, 98 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 4cb6166badd..f653dd5f0bb 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -42,7 +42,6 @@ #include "lp_context.h" #include "lp_memory.h" #include "lp_scene.h" -#include "lp_scene_queue.h" #include "lp_texture.h" #include "lp_debug.h" #include "lp_fence.h" @@ -57,16 +56,31 @@ #include "draw/draw_vbuf.h" -static void set_scene_state( struct lp_setup_context *, enum setup_state ); +static void set_scene_state( struct lp_setup_context *, enum setup_state, + const char *reason); +static boolean try_update_scene_state( struct lp_setup_context *setup ); -struct lp_scene * -lp_setup_get_current_scene(struct lp_setup_context *setup) +static void +lp_setup_get_empty_scene(struct lp_setup_context *setup) { - if (!setup->scene) { - set_scene_state( setup, SETUP_EMPTY ); + assert(setup->scene == NULL); + + setup->scene_idx++; + setup->scene_idx %= Elements(setup->scenes); + + setup->scene = setup->scenes[setup->scene_idx]; + + if (setup->scene->fence) { + if (LP_DEBUG & DEBUG_SETUP) + debug_printf("%s: wait for scene %d\n", + __FUNCTION__, setup->scene->fence->id); + + lp_fence_wait(setup->scene->fence); } - return setup->scene; + + lp_scene_begin_binning(setup->scene, &setup->fb); + } @@ -76,7 +90,7 @@ first_triangle( struct lp_setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { - set_scene_state( setup, SETUP_ACTIVE ); + assert(setup->state == SETUP_ACTIVE); lp_setup_choose_triangle( setup ); setup->triangle( setup, v0, v1, v2 ); } @@ -86,7 +100,7 @@ first_line( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { - set_scene_state( setup, SETUP_ACTIVE ); + assert(setup->state == SETUP_ACTIVE); lp_setup_choose_line( setup ); setup->line( setup, v0, v1 ); } @@ -95,12 +109,12 @@ static void first_point( struct lp_setup_context *setup, const float (*v0)[4]) { - set_scene_state( setup, SETUP_ACTIVE ); + assert(setup->state == SETUP_ACTIVE); lp_setup_choose_point( setup ); setup->point( setup, v0 ); } -static void reset_context( struct lp_setup_context *setup ) +static void lp_setup_reset( struct lp_setup_context *setup ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -130,19 +144,23 @@ static void reset_context( struct lp_setup_context *setup ) static void lp_setup_rasterize_scene( struct lp_setup_context *setup ) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); + struct lp_scene *scene = setup->scene; struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen); + lp_scene_end_binning(scene); + lp_fence_reference(&setup->last_fence, scene->fence); if (setup->last_fence) setup->last_fence->issued = TRUE; pipe_mutex_lock(screen->rast_mutex); - lp_scene_rasterize(scene, screen->rast); + lp_rast_queue_scene(screen->rast, scene); + lp_rast_finish(screen->rast); pipe_mutex_unlock(screen->rast_mutex); - reset_context( setup ); + lp_scene_end_rasterization(setup->scene); + lp_setup_reset( setup ); LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); } @@ -152,8 +170,10 @@ lp_setup_rasterize_scene( struct lp_setup_context *setup ) static void begin_binning( struct lp_setup_context *setup ) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); + struct lp_scene *scene = setup->scene; boolean need_zsload = FALSE; + boolean ok; + unsigned i, j; assert(scene); assert(scene->fence == NULL); @@ -162,6 +182,17 @@ begin_binning( struct lp_setup_context *setup ) */ 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) && @@ -175,7 +206,7 @@ begin_binning( struct lp_setup_context *setup ) if (setup->fb.nr_cbufs) { if (setup->clear.flags & PIPE_CLEAR_COLOR) { ok = lp_scene_bin_everywhere( scene, - lp_rast_clear_color, + LP_RAST_OP_CLEAR_COLOR, setup->clear.color ); assert(ok); } @@ -186,22 +217,26 @@ begin_binning( struct lp_setup_context *setup ) if (!need_zsload) scene->has_depthstencil_clear = TRUE; ok = lp_scene_bin_everywhere( scene, - lp_rast_clear_zstencil, + LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs( - setup->clear.zsmask, - setup->clear.zsvalue)); + setup->clear.zsvalue, + setup->clear.zsmask)); assert(ok); } } if (setup->active_query) { ok = lp_scene_bin_everywhere( scene, - lp_rast_begin_query, + 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__); } @@ -217,50 +252,53 @@ execute_clears( struct lp_setup_context *setup ) LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); begin_binning( setup ); - lp_setup_rasterize_scene( setup ); } +const char *states[] = { + "FLUSHED", + "EMPTY ", + "CLEARED", + "ACTIVE " +}; + static void set_scene_state( struct lp_setup_context *setup, - enum setup_state new_state ) + enum setup_state new_state, + const char *reason) { unsigned old_state = setup->state; if (old_state == new_state) return; - - LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state); - - switch (new_state) { - case SETUP_EMPTY: - assert(old_state == SETUP_FLUSHED); - assert(setup->scene == NULL); + + if (LP_DEBUG & DEBUG_SETUP) { + debug_printf("%s old %s new %s%s%s\n", + __FUNCTION__, + states[old_state], + states[new_state], + (new_state == SETUP_FLUSHED) ? ": " : "", + (new_state == SETUP_FLUSHED) ? reason : ""); + } - /* wait for a free/empty scene - */ - setup->scene = lp_scene_dequeue(setup->empty_scenes, TRUE); - lp_scene_begin_binning(setup->scene, - &setup->fb ); - break; + /* wait for a free/empty scene + */ + if (old_state == SETUP_FLUSHED) + lp_setup_get_empty_scene(setup); + switch (new_state) { case SETUP_CLEARED: - assert(old_state == SETUP_EMPTY); - assert(setup->scene != NULL); break; case SETUP_ACTIVE: - assert(old_state == SETUP_EMPTY || - old_state == SETUP_CLEARED); - assert(setup->scene != NULL); begin_binning( setup ); break; case SETUP_FLUSHED: if (old_state == SETUP_CLEARED) execute_clears( setup ); - else - lp_setup_rasterize_scene( setup ); + + lp_setup_rasterize_scene( setup ); assert(setup->scene == NULL); break; @@ -281,9 +319,7 @@ lp_setup_flush( struct lp_setup_context *setup, struct pipe_fence_handle **fence, const char *reason) { - LP_DBG(DEBUG_SETUP, "%s %s\n", __FUNCTION__, reason); - - set_scene_state( setup, SETUP_FLUSHED ); + set_scene_state( setup, SETUP_FLUSHED, reason ); if (fence) { lp_fence_reference((struct lp_fence **)fence, setup->last_fence); @@ -299,7 +335,7 @@ lp_setup_bind_framebuffer( struct lp_setup_context *setup, /* Flush any old scene. */ - set_scene_state( setup, SETUP_FLUSHED ); + set_scene_state( setup, SETUP_FLUSHED, __FUNCTION__ ); /* * Ensure the old scene is not reused. @@ -325,30 +361,34 @@ lp_setup_try_clear( struct lp_setup_context *setup, unsigned stencil, unsigned flags ) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); uint32_t zsmask = 0; uint32_t zsvalue = 0; - uint8_t clear_color[4]; + 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++) - clear_color[i] = float_to_ubyte(color[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, - 0xffffffff, - 0xff); + 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 @@ -357,15 +397,15 @@ lp_setup_try_clear( struct lp_setup_context *setup, */ if (flags & PIPE_CLEAR_COLOR) { if (!lp_scene_bin_everywhere( scene, - lp_rast_clear_color, - setup->clear.color )) + LP_RAST_OP_CLEAR_COLOR, + color_arg )) return FALSE; } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { if (!lp_scene_bin_everywhere( scene, - lp_rast_clear_zstencil, - lp_rast_arg_clearzs(zsmask, zsvalue) )) + LP_RAST_OP_CLEAR_ZSTENCIL, + lp_rast_arg_clearzs(zsvalue, zsmask) )) return FALSE; } } @@ -375,7 +415,7 @@ lp_setup_try_clear( struct lp_setup_context *setup, * buffers which the app or state-tracker might issue * separately. */ - set_scene_state( setup, SETUP_CLEARED ); + set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); setup->clear.flags |= flags; @@ -387,11 +427,11 @@ lp_setup_try_clear( struct lp_setup_context *setup, if (flags & PIPE_CLEAR_COLOR) { memcpy(setup->clear.color.clear_color, - clear_color, - sizeof clear_color); + &color_arg, + sizeof color_arg); } } - + return TRUE; } @@ -677,21 +717,20 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup, static boolean try_update_scene_state( struct lp_setup_context *setup ) { - struct lp_scene *scene; - - LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - - scene = lp_setup_get_current_scene(setup); + boolean new_scene = (setup->fs.stored == NULL); + struct lp_scene *scene = setup->scene; - assert(setup->fs.current.variant); + assert(scene); if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { uint8_t *stored; unsigned i, j; stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); - if (!stored) + if (!stored) { + assert(!new_scene); return FALSE; + } /* smear each blend color component across 16 ubyte elements */ for (i = 0; i < 4; ++i) { @@ -722,8 +761,10 @@ try_update_scene_state( struct lp_setup_context *setup ) void *stored; stored = lp_scene_alloc(scene, current_size); - if (!stored) + if (!stored) { + assert(!new_scene); return FALSE; + } memcpy(stored, current_data, @@ -756,8 +797,10 @@ try_update_scene_state( struct lp_setup_context *setup ) * and append it to the bin's setup data buffer. */ stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); - if (!stored) + if (!stored) { + assert(!new_scene); return FALSE; + } memcpy(stored, &setup->fs.current, @@ -770,8 +813,11 @@ try_update_scene_state( struct lp_setup_context *setup ) for (i = 0; i < Elements(setup->fs.current_tex); i++) { if (setup->fs.current_tex[i]) { if (!lp_scene_add_resource_reference(scene, - setup->fs.current_tex[i])) + setup->fs.current_tex[i], + new_scene)) { + assert(!new_scene); return FALSE; + } } } } @@ -792,7 +838,8 @@ try_update_scene_state( struct lp_setup_context *setup ) } void -lp_setup_update_state( struct lp_setup_context *setup ) +lp_setup_update_state( struct lp_setup_context *setup, + boolean update_scene ) { /* Some of the 'draw' pipeline stages may have changed some driver state. * Make sure we've processed those state changes before anything else. @@ -814,13 +861,19 @@ lp_setup_update_state( struct lp_setup_context *setup ) assert(lp->dirty == 0); } - /* XXX: only call into update_scene_state() if we already have a + if (update_scene) + set_scene_state( setup, SETUP_ACTIVE, __FUNCTION__ ); + + /* Only call into update_scene_state() if we already have a * scene: */ - if (!try_update_scene_state(setup)) { - set_scene_state( setup, SETUP_FLUSHED ); - if (!try_update_scene_state(setup)) - assert(0); + if (update_scene && setup->scene) { + assert(setup->state == SETUP_ACTIVE); + if (!try_update_scene_state(setup)) { + lp_setup_flush_and_restart(setup); + if (!try_update_scene_state(setup)) + assert(0); + } } } @@ -833,7 +886,7 @@ lp_setup_destroy( struct lp_setup_context *setup ) { uint i; - reset_context( setup ); + lp_setup_reset( setup ); util_unreference_framebuffer_state(&setup->fb); @@ -844,15 +897,15 @@ lp_setup_destroy( struct lp_setup_context *setup ) pipe_resource_reference(&setup->constants.current, NULL); /* free the scenes in the 'empty' queue */ - while (1) { - struct lp_scene *scene = lp_scene_dequeue(setup->empty_scenes, FALSE); - if (!scene) - break; + for (i = 0; i < Elements(setup->scenes); i++) { + struct lp_scene *scene = setup->scenes[i]; + + if (scene->fence) + lp_fence_wait(scene->fence); + lp_scene_destroy(scene); } - lp_scene_queue_destroy(setup->empty_scenes); - FREE( setup ); } @@ -879,9 +932,6 @@ lp_setup_create( struct pipe_context *pipe, */ setup->pipe = pipe; - setup->empty_scenes = lp_scene_queue_create(); - if (!setup->empty_scenes) - goto fail; setup->num_threads = screen->num_threads; setup->vbuf = draw_vbuf_stage(draw, &setup->base); @@ -893,9 +943,7 @@ lp_setup_create( struct pipe_context *pipe, /* create some empty scenes */ for (i = 0; i < MAX_SCENES; i++) { - setup->scenes[i] = lp_scene_create( pipe, setup->empty_scenes ); - - lp_scene_enqueue(setup->empty_scenes, setup->scenes[i]); + setup->scenes[i] = lp_scene_create( pipe ); } setup->triangle = first_triangle; @@ -910,9 +958,6 @@ fail: if (setup->vbuf) ; - if (setup->empty_scenes) - lp_scene_queue_destroy(setup->empty_scenes); - FREE(setup); return NULL; } @@ -930,12 +975,13 @@ lp_setup_begin_query(struct lp_setup_context *setup, if (setup->scene) { if (!lp_scene_bin_everywhere(setup->scene, - lp_rast_begin_query, + 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_begin_query, + LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { assert(0); return; @@ -969,7 +1015,9 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) */ lp_fence_reference(&pq->fence, setup->scene->fence); - if (!lp_scene_bin_everywhere(setup->scene, lp_rast_end_query, dummy)) { + if (!lp_scene_bin_everywhere(setup->scene, + LP_RAST_OP_END_QUERY, + dummy)) { lp_setup_flush(setup, 0, NULL, __FUNCTION__); } } @@ -985,8 +1033,8 @@ lp_setup_flush_and_restart(struct lp_setup_context *setup) if (0) debug_printf("%s\n", __FUNCTION__); assert(setup->state == SETUP_ACTIVE); - set_scene_state(setup, SETUP_FLUSHED); - set_scene_state(setup, SETUP_EMPTY); - set_scene_state(setup, SETUP_ACTIVE); - lp_setup_update_state(setup); + set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__); + lp_setup_update_state(setup, TRUE); } + + |