llvmpipe: move fences from per-bin to per-thread
Rather than inserting an lp_rast_fence command at the end of each bin, have each rasterizer thread call this function directly once it has run out of work to do on a particular scene. This results in fewer calls to the mutex & related functions, but more importantly makes it easier to recognize empty bins.
This commit is contained in:

committed by
José Fonseca

parent
6d17f00600
commit
3bd9aedbac
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "pipe/p_screen.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "lp_debug.h"
|
||||
#include "lp_fence.h"
|
||||
|
||||
@@ -59,7 +58,7 @@ lp_fence_create(unsigned rank)
|
||||
|
||||
|
||||
/** Destroy a fence. Called when refcount hits zero. */
|
||||
static void
|
||||
void
|
||||
lp_fence_destroy(struct lp_fence *fence)
|
||||
{
|
||||
pipe_mutex_destroy(fence->mutex);
|
||||
@@ -77,12 +76,10 @@ llvmpipe_fence_reference(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle **ptr,
|
||||
struct pipe_fence_handle *fence)
|
||||
{
|
||||
struct lp_fence *old = (struct lp_fence *) *ptr;
|
||||
struct lp_fence **old = (struct lp_fence **) ptr;
|
||||
struct lp_fence *f = (struct lp_fence *) fence;
|
||||
|
||||
if (pipe_reference(&old->reference, &f->reference)) {
|
||||
lp_fence_destroy(old);
|
||||
}
|
||||
lp_fence_reference(old, f);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "os/os_thread.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
|
||||
struct pipe_screen;
|
||||
@@ -61,4 +62,21 @@ void
|
||||
llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen);
|
||||
|
||||
|
||||
void
|
||||
lp_fence_destroy(struct lp_fence *fence);
|
||||
|
||||
static INLINE void
|
||||
lp_fence_reference(struct lp_fence **ptr,
|
||||
struct lp_fence *f)
|
||||
{
|
||||
struct lp_fence *old = *ptr;
|
||||
|
||||
if (pipe_reference(&old->reference, &f->reference)) {
|
||||
lp_fence_destroy(old);
|
||||
}
|
||||
|
||||
*ptr = f;
|
||||
}
|
||||
|
||||
|
||||
#endif /* LP_FENCE_H */
|
||||
|
@@ -51,16 +51,8 @@ llvmpipe_flush( struct pipe_context *pipe,
|
||||
|
||||
draw_flush(llvmpipe->draw);
|
||||
|
||||
if (fence) {
|
||||
/* if we're going to flush the setup/rasterization modules, emit
|
||||
* a fence.
|
||||
* XXX this (and the code below) may need fine tuning...
|
||||
*/
|
||||
*fence = lp_setup_fence( llvmpipe->setup );
|
||||
}
|
||||
|
||||
/* ask the setup module to flush */
|
||||
lp_setup_flush(llvmpipe->setup, flags);
|
||||
lp_setup_flush(llvmpipe->setup, flags, fence);
|
||||
|
||||
/* Enable to dump BMPs of the color/depth buffers each frame */
|
||||
if (0) {
|
||||
|
@@ -815,6 +815,10 @@ rasterize_scene(struct lp_rasterizer_task *task,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scene->fence) {
|
||||
lp_rast_fence(task, lp_rast_arg_fence(scene->fence));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "util/u_simple_list.h"
|
||||
#include "lp_scene.h"
|
||||
#include "lp_scene_queue.h"
|
||||
#include "lp_fence.h"
|
||||
|
||||
|
||||
/** List of texture references */
|
||||
@@ -198,6 +199,8 @@ lp_scene_reset(struct lp_scene *scene )
|
||||
make_empty_list(ref_list);
|
||||
}
|
||||
|
||||
lp_fence_reference(&scene->fence, NULL);
|
||||
|
||||
scene->scene_size = 0;
|
||||
|
||||
scene->has_color_clear = FALSE;
|
||||
|
@@ -112,6 +112,7 @@ struct resource_ref {
|
||||
*/
|
||||
struct lp_scene {
|
||||
struct pipe_context *pipe;
|
||||
struct lp_fence *fence;
|
||||
|
||||
/** the framebuffer to render the scene into */
|
||||
struct pipe_framebuffer_state fb;
|
||||
|
@@ -271,7 +271,8 @@ set_scene_state( struct lp_setup_context *setup,
|
||||
*/
|
||||
void
|
||||
lp_setup_flush( struct lp_setup_context *setup,
|
||||
unsigned flags )
|
||||
unsigned flags,
|
||||
struct pipe_fence_handle **fence)
|
||||
{
|
||||
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
|
||||
|
||||
@@ -288,6 +289,15 @@ lp_setup_flush( struct lp_setup_context *setup,
|
||||
*/
|
||||
lp_scene_bin_everywhere(scene, lp_rast_store_color, dummy);
|
||||
}
|
||||
|
||||
|
||||
if (fence) {
|
||||
/* if we're going to flush the setup/rasterization modules, emit
|
||||
* a fence.
|
||||
*/
|
||||
*fence = lp_setup_fence( setup );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set_scene_state( setup, SETUP_FLUSHED );
|
||||
@@ -433,24 +443,27 @@ lp_setup_clear( struct lp_setup_context *setup,
|
||||
struct pipe_fence_handle *
|
||||
lp_setup_fence( struct lp_setup_context *setup )
|
||||
{
|
||||
if (setup->num_threads == 0) {
|
||||
if (setup->scene == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
else if (setup->num_threads == 0)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
struct lp_scene *scene = lp_setup_get_current_scene(setup);
|
||||
const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */
|
||||
struct lp_fence *fence = lp_fence_create(rank);
|
||||
const unsigned rank = setup->num_threads;
|
||||
|
||||
set_scene_state( setup, SETUP_ACTIVE );
|
||||
|
||||
assert(scene->fence == NULL);
|
||||
|
||||
/* The caller gets a reference, we keep a copy too, so need to
|
||||
* bump the refcount:
|
||||
*/
|
||||
lp_fence_reference(&scene->fence, lp_fence_create(rank));
|
||||
|
||||
LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank);
|
||||
|
||||
set_scene_state( setup, SETUP_ACTIVE );
|
||||
|
||||
/* insert the fence into all command bins */
|
||||
lp_scene_bin_everywhere( scene,
|
||||
lp_rast_fence,
|
||||
lp_rast_arg_fence(fence) );
|
||||
|
||||
return (struct pipe_fence_handle *) fence;
|
||||
return (struct pipe_fence_handle *) scene->fence;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -84,7 +84,8 @@ lp_setup_fence( struct lp_setup_context *setup );
|
||||
|
||||
void
|
||||
lp_setup_flush( struct lp_setup_context *setup,
|
||||
unsigned flags );
|
||||
unsigned flags,
|
||||
struct pipe_fence_handle **fence);
|
||||
|
||||
|
||||
void
|
||||
|
Reference in New Issue
Block a user