On Thu, May 4, 2017 at 9:26 AM, Juan A. Suarez Romero <jasua...@igalia.com> wrote:
> On Thu, 2017-05-04 at 07:49 -0700, Jason Ekstrand wrote: > > On Thu, May 4, 2017 at 1:00 AM, Juan A. Suarez Romero < > jasua...@igalia.com> wrote: > > > On Wed, 2017-04-26 at 07:35 -0700, Jason Ekstrand wrote: > > > > Previously, the maximum size of a state that could be allocated from > a > > > > state pool was a block. However, this has caused us various issues > > > > particularly with shaders which are potentially very large. We've > also > > > > hit issues with render passes with a large number of attachments > when we > > > > go to allocate the block of surface state. This effectively removes > the > > > > restriction on the maximum size of a single state. (There's still a > > > > limit of 1MB imposed by a fixed-length bucket array.) > > > > > > > > For states larger than the block size, we just grab a large block > off of > > > > the block pool rather than sub-allocating. When we go to allocate > some > > > > chunk of state and the current bucket does not have state, we try to > > > > pull a chunk from some larger bucket and split it up. This should > > > > improve memory usage if a client occasionally allocates a large > block of > > > > state. > > > > > > > > This commit is inspired by some similar work done by Juan A. Suarez > > > > Romero <jasua...@igalia.com>. > > > > --- > > > > src/intel/vulkan/anv_allocator.c | 43 > ++++++++++++++++++++++++++++++++++++++++ > > > > 1 file changed, 43 insertions(+) > > > > > > > > diff --git a/src/intel/vulkan/anv_allocator.c > b/src/intel/vulkan/anv_allocator.c > > > > index 7a687b7..68c389c 100644 > > > > --- a/src/intel/vulkan/anv_allocator.c > > > > +++ b/src/intel/vulkan/anv_allocator.c > > > > @@ -650,6 +650,12 @@ anv_fixed_size_state_pool_alloc_new(struct > anv_fixed_size_state_pool *pool, > > > > struct anv_block_state block, old, new; > > > > uint32_t offset; > > > > > > > > + /* If our state is large, we don't need any sub-allocation from > a block. > > > > + * Instead, we just grab whole (potentially large) blocks. > > > > + */ > > > > + if (state_size >= block_size) > > > > + return anv_block_pool_alloc(block_pool, state_size); > > > > + > > > > restart: > > > > block.u64 = __sync_fetch_and_add(&pool->block.u64, state_size); > > > > > > > > @@ -702,6 +708,43 @@ anv_state_pool_alloc_no_vg(struct > anv_state_pool *pool, > > > > goto done; > > > > } > > > > > > > > + /* Try to grab a chunk from some larger bucket and split it up */ > > > > + for (unsigned b = bucket + 1; b < ANV_STATE_BUCKETS; b++) { > > > > + int32_t chunk_offset; > > > > + if (anv_free_list_pop(&pool->buckets[b].free_list, > > > > + &pool->block_pool.map, &chunk_offset)) { > > > > + unsigned chunk_size = anv_state_pool_get_bucket_size(b); > > > > + > > > > + if (chunk_size > pool->block_size && > > > > + state.alloc_size < pool->block_size) { > > > > + assert(chunk_size % pool->block_size == 0); > > > > + /* We don't want to split giant chunks into tiny > chunks. Instead, > > > > + * break anything bigger than a block into block-sized > chunks and > > > > + * then break it down into bucket-sized chunks from > there. Return > > > > + * all but the first block of the chunk to the block > bucket. > > > > + */ > > > > + const uint32_t block_bucket = > > > > + anv_state_pool_get_bucket(pool->block_size); > > > > + anv_free_list_push(&pool->buckets[block_bucket].free_ > list, > > > > + pool->block_pool.map, > > > > + chunk_offset + pool->block_size, > > > > + pool->block_size, > > > > + (chunk_size / pool->block_size) - 1); > > > > + chunk_size = pool->block_size; > > > > + } > > > > + > > > > + assert(chunk_size % state.alloc_size == 0); > > > > + anv_free_list_push(&pool->buckets[bucket].free_list, > > > > + pool->block_pool.map, > > > > + chunk_offset + state.alloc_size, > > > > + state.alloc_size, > > > > + (chunk_size / state.alloc_size) - 1); > > > > + > > > > + state.offset = chunk_offset; > > > > + goto done; > > > > + } > > > > > > > > > Wouldn't it better to split the bucket just in two parts, one to be > > > used for our request, and the other with the available free space, but > > > in on single bucket, instead of splitting it in various parts? > > > > > > This way, if we later get a new request that can potentially required > > > the full (or part of) free single bucket we can assign it entirely (or > > > splitting it again). > > > > Would you mind rephrasing that? I'm not really sure what you mean. > There are two other options in my mind: > > After re-thinking, I think what I wanted to do is a non-sense. > > In the example below, I was thinking on using 16B out of 2MB for the > request, and put the remaining space (2MB-16B) in *one* bucket. Which, > of course, is a non sense. > > > > > 1. Fully split the chunk. This would mean that allocating a 16B state > could potentially split a 2MB chunk into 512K smaller chunks. I'm trying > to avoid that quantity of fragmentation. > > > > 2. Scatter the chunk through the buckets. If you got a 2MB chunk, it > would generate one of each: 2MB, 1MB, 512KB, 256KB, ..., 128B, 128B, 64B, > and 32B and two 16B states. The issue here is that you end up doing > log2(chunk_size / state_size) atomics and it's very likely that you'll > allocate more 16B states soon and every other one will have to go at least > one bucket up. Under the assumption that we tend to allocate > identically-sized states, I think this is likely to perform worse than > splitting a block_size thing into into block_size / state_size many chunks. > > > > What I did is an attempt to split the difference by splitting it at two > levels rather than one or all. > > > > > I see now. Thanks for the explanation! > No problem. I'll make that a comment. > Reviewed-by: Juan A. Suarez Romero <jasua...@igalia.com> > Thanks! > > > > --Jason > > > > > J.A. > > > > > > > > > > > > > + } > > > > + > > > > state.offset = anv_fixed_size_state_pool_ > alloc_new(&pool->buckets[bucket], > > > > > &pool->block_pool, > > > > > state.alloc_size, > > > _______________________________________________ > > > mesa-dev mailing list > > > mesa-dev@lists.freedesktop.org > > > https://lists.freedesktop.org/mailman/listinfo/mesa-dev > > > > > > > >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev