Mesa (master): llvmpipe: implement max scene size

Brian Paul brianp at kemper.freedesktop.org
Tue Apr 27 17:50:43 UTC 2010


Module: Mesa
Branch: master
Commit: bb527c0af6c53b335330da1063979f5ac3a19174
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=bb527c0af6c53b335330da1063979f5ac3a19174

Author: Brian Paul <brianp at vmware.com>
Date:   Tue Apr 27 11:44:33 2010 -0600

llvmpipe: implement max scene size

When the size of the scene (binned data plus referenced resources/textures)
exceeds LP_MAX_SCENE_SIZE flush/render the scene.  This could be improved
in various ways but is a good start.

Fixes piglit streaming-texture-leak test.

---

 src/gallium/drivers/llvmpipe/lp_limits.h |    6 ++++++
 src/gallium/drivers/llvmpipe/lp_scene.c  |   13 ++++++++++++-
 src/gallium/drivers/llvmpipe/lp_scene.h  |   18 ++++++++++++++++++
 src/gallium/drivers/llvmpipe/lp_setup.c  |   26 +++++++++++++++++++++++++-
 4 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_limits.h b/src/gallium/drivers/llvmpipe/lp_limits.h
index c7c5a1e..4102a9d 100644
--- a/src/gallium/drivers/llvmpipe/lp_limits.h
+++ b/src/gallium/drivers/llvmpipe/lp_limits.h
@@ -61,4 +61,10 @@
 #define LP_MAX_THREADS 8
 
 
+/**
+ * Max bytes per scene.  This may be replaced by a runtime parameter.
+ */
+#define LP_MAX_SCENE_SIZE (512 * 1024 * 1024)
+
+
 #endif /* LP_LIMITS_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index 71d9529..7a94116 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.c
+++ b/src/gallium/drivers/llvmpipe/lp_scene.c
@@ -43,6 +43,10 @@ struct texture_ref {
 
 
 
+/**
+ * Create a new scene object.
+ * \param queue  the queue to put newly rendered/emptied scenes into
+ */
 struct lp_scene *
 lp_scene_create( struct pipe_context *pipe,
                  struct lp_scene_queue *queue )
@@ -195,6 +199,8 @@ lp_scene_reset(struct lp_scene *scene )
       make_empty_list(ref_list);
    }
 
+   scene->scene_size = 0;
+
    scene->has_color_clear = FALSE;
    scene->has_depth_clear = FALSE;
 }
@@ -226,7 +232,10 @@ lp_bin_new_data_block( struct data_block_list *list )
 }
 
 
-/** Return number of bytes used for all bin data within a scene */
+/**
+ * Return number of bytes used for all bin data within a scene.
+ * This does not include resources (textures) referenced by the scene.
+ */
 unsigned
 lp_scene_data_size( const struct lp_scene *scene )
 {
@@ -267,6 +276,8 @@ lp_scene_add_resource_reference(struct lp_scene *scene,
       pipe_resource_reference(&ref->resource, resource);
       insert_at_tail(ref_list, ref);
    }
+
+   scene->scene_size += llvmpipe_resource_size(resource);
 }
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h
index 3e2bd0e..d3a8586 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.h
+++ b/src/gallium/drivers/llvmpipe/lp_scene.h
@@ -119,6 +119,11 @@ struct lp_scene {
    /** list of resources referenced by the scene commands */
    struct resource_ref resources;
 
+   /** Approx memory used by the scene (in bytes).  This includes the
+    * shared and per-tile bins plus any referenced resources/textures.
+    */
+   unsigned scene_size;
+
    boolean write_depth;
    boolean has_color_clear;
    boolean has_depth_clear;
@@ -182,6 +187,8 @@ lp_scene_alloc( struct lp_scene *scene, unsigned size)
       lp_bin_new_data_block( list );
    }
 
+   scene->scene_size += size;
+
    {
       struct data_block *tail = list->tail;
       ubyte *data = tail->data + tail->used;
@@ -204,6 +211,8 @@ lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size,
       lp_bin_new_data_block( list );
    }
 
+   scene->scene_size += size;
+
    {
       struct data_block *tail = list->tail;
       ubyte *data = tail->data + tail->used;
@@ -220,6 +229,7 @@ static INLINE void
 lp_scene_putback_data( struct lp_scene *scene, unsigned size)
 {
    struct data_block_list *list = &scene->data;
+   scene->scene_size -= size;
    assert(list->tail->used >= size);
    list->tail->used -= size;
 }
@@ -309,4 +319,12 @@ void
 lp_scene_begin_binning( struct lp_scene *scene,
                         struct pipe_framebuffer_state *fb );
 
+
+static INLINE unsigned
+lp_scene_get_size(const struct lp_scene *scene)
+{
+   return scene->scene_size;
+}
+
+
 #endif /* LP_BIN_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index abc659c..649752c 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -74,6 +74,26 @@ lp_setup_get_current_scene(struct lp_setup_context *setup)
 }
 
 
+/**
+ * Check if the size of the current scene has exceeded the limit.
+ * If so, flush/render it.
+ */
+static void
+setup_check_scene_size_and_flush(struct lp_setup_context *setup)
+{
+   if (setup->scene) {
+      struct lp_scene *scene = lp_setup_get_current_scene(setup);
+      unsigned size = lp_scene_get_size(scene);
+
+      if (size > LP_MAX_SCENE_SIZE) {
+         /*printf("LLVMPIPE: scene size = %u, flushing.\n", size);*/
+         set_scene_state( setup, SETUP_FLUSHED );
+         /*assert(lp_scene_get_size(scene) == 0);*/
+      }
+   }
+}
+
+
 static void
 first_triangle( struct lp_setup_context *setup,
                 const float (*v0)[4],
@@ -596,10 +616,14 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup,
 void
 lp_setup_update_state( struct lp_setup_context *setup )
 {
-   struct lp_scene *scene = lp_setup_get_current_scene(setup);
+   struct lp_scene *scene;
 
    LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 
+   setup_check_scene_size_and_flush(setup);
+
+   scene = lp_setup_get_current_scene(setup);
+
    assert(setup->fs.current.jit_function);
 
    /* Some of the 'draw' pipeline stages may have changed some driver state.




More information about the mesa-commit mailing list