summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2008-04-15 15:41:08 +0900
committerJosé Fonseca <[email protected]>2008-04-15 15:41:08 +0900
commit95aeeb6d746e57473116ef4d72c05330902f68a5 (patch)
treee51ff6826baebf02ced7f0e77f37b563964f24ab
parentd005befcb9e191ae90619fbdd3c37e262ae3b03e (diff)
gallium: Several fixes to buffer caching.
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer.h11
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c67
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c15
3 files changed, 68 insertions, 25 deletions
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer.h b/src/gallium/auxiliary/pipebuffer/pb_buffer.h
index 4b09c80b2a1..49705cb8627 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_buffer.h
+++ b/src/gallium/auxiliary/pipebuffer/pb_buffer.h
@@ -193,6 +193,17 @@ pb_reference(struct pb_buffer **dst,
/**
+ * Utility function to check whether a requested alignment is consistent with
+ * the provided alignment or not.
+ */
+static INLINE int
+pb_check_alignment(size_t requested, size_t provided)
+{
+ return requested <= provided && (provided % requested) == 0;
+}
+
+
+/**
* Malloc-based buffer to store data that can't be used by the graphics
* hardware.
*/
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
index 06de0bb6c37..543fd51253c 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
@@ -136,7 +136,7 @@ _pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr)
while(curr != &mgr->delayed) {
buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
- if(util_time_timeout(&buf->start, &buf->end, &now) != 0)
+ if(!util_time_timeout(&buf->start, &buf->end, &now))
break;
_pb_cache_buffer_destroy(buf);
@@ -202,6 +202,24 @@ pb_cache_buffer_vtbl = {
};
+static INLINE boolean
+pb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
+ size_t size,
+ const struct pb_desc *desc)
+{
+ /* TODO: be more lenient with size */
+ if(buf->base.base.size != size)
+ return FALSE;
+
+ if(!pb_check_alignment(desc->alignment, buf->base.base.alignment))
+ return FALSE;
+
+ /* XXX: check usage too? */
+
+ return TRUE;
+}
+
+
static struct pb_buffer *
pb_cache_manager_create_buffer(struct pb_manager *_mgr,
size_t size,
@@ -209,29 +227,45 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr,
{
struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
struct pb_cache_buffer *buf;
+ struct pb_cache_buffer *curr_buf;
struct list_head *curr, *next;
struct util_time now;
- util_time_get(&now);
+ _glthread_LOCK_MUTEX(mgr->mutex);
+
+ buf = NULL;
curr = mgr->delayed.next;
next = curr->next;
+
+ /* search in the expired buffers, freeing them in the process */
+ util_time_get(&now);
while(curr != &mgr->delayed) {
- buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
-
- if(buf->base.base.size == size &&
- buf->base.base.alignment >= desc->alignment &&
- (buf->base.base.alignment % desc->alignment) == 0 &&
- /* buf->base.base.usage == usage */ 1) {
- ++buf->base.base.refcount;
- return &buf->base;
- }
-
- if(util_time_timeout(&buf->start, &buf->end, &now) != 0)
- _pb_cache_buffer_destroy(buf);
+ curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+ if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc))
+ buf = curr_buf;
+ else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now))
+ _pb_cache_buffer_destroy(curr_buf);
+ curr = next;
+ next = curr->next;
+ }
+ /* keep searching in the hot buffers */
+ while(!buf && curr != &mgr->delayed) {
+ curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+ if(pb_cache_is_buffer_compat(curr_buf, size, desc))
+ buf = curr_buf;
curr = next;
next = curr->next;
}
+
+ if(buf) {
+ LIST_DEL(&buf->head);
+ _glthread_UNLOCK_MUTEX(mgr->mutex);
+ ++buf->base.base.refcount;
+ return &buf->base;
+ }
+
+ _glthread_UNLOCK_MUTEX(mgr->mutex);
buf = CALLOC_STRUCT(pb_cache_buffer);
if(!buf)
@@ -243,6 +277,11 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr,
return NULL;
}
+ assert(buf->buffer->base.refcount >= 1);
+ assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment));
+ assert((buf->buffer->base.usage & desc->usage) == desc->usage);
+ assert(buf->buffer->base.size >= size);
+
buf->base.base.refcount = 1;
buf->base.base.alignment = buf->buffer->base.alignment;
buf->base.base.usage = buf->buffer->base.usage;
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c
index 9506ac9ae10..b931455056e 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c
@@ -304,13 +304,6 @@ out_err0:
}
-static int
-check_alignment(size_t requested, size_t provided)
-{
- return requested <= provided && (provided % requested) == 0;
-}
-
-
static struct pb_buffer *
pb_slab_manager_create_buffer(struct pb_manager *_mgr,
size_t size,
@@ -328,11 +321,11 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr,
return NULL;
/* check if we can provide the requested alignment */
- assert(check_alignment(desc->alignment, mgr->desc.alignment));
- if(!check_alignment(desc->alignment, mgr->desc.alignment))
+ assert(pb_check_alignment(desc->alignment, mgr->desc.alignment));
+ if(!pb_check_alignment(desc->alignment, mgr->desc.alignment))
return NULL;
- assert(check_alignment(desc->alignment, mgr->bufSize));
- if(!check_alignment(desc->alignment, mgr->bufSize))
+ assert(pb_check_alignment(desc->alignment, mgr->bufSize));
+ if(!pb_check_alignment(desc->alignment, mgr->bufSize))
return NULL;
/* XXX: check for compatible buffer usage too? */