1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * © Copyright 2018 Alyssa Rosenzweig 3bf215546Sopenharmony_ci * Copyright (C) 2019 Collabora, Ltd. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "agx_bo.h" 27bf215546Sopenharmony_ci#include "agx_device.h" 28bf215546Sopenharmony_ci#include "pool.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci/* Transient command stream pooling: command stream uploads try to simply copy 31bf215546Sopenharmony_ci * into whereever we left off. If there isn't space, we allocate a new entry 32bf215546Sopenharmony_ci * into the pool and copy there */ 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#define POOL_SLAB_SIZE (256 * 1024) 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_cistatic struct agx_bo * 37bf215546Sopenharmony_ciagx_pool_alloc_backing(struct agx_pool *pool, size_t bo_sz) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci struct agx_bo *bo = agx_bo_create(pool->dev, bo_sz, 40bf215546Sopenharmony_ci pool->create_flags); 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci util_dynarray_append(&pool->bos, struct agx_bo *, bo); 43bf215546Sopenharmony_ci pool->transient_bo = bo; 44bf215546Sopenharmony_ci pool->transient_offset = 0; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci return bo; 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_civoid 50bf215546Sopenharmony_ciagx_pool_init(struct agx_pool *pool, struct agx_device *dev, 51bf215546Sopenharmony_ci unsigned create_flags, bool prealloc) 52bf215546Sopenharmony_ci{ 53bf215546Sopenharmony_ci memset(pool, 0, sizeof(*pool)); 54bf215546Sopenharmony_ci pool->dev = dev; 55bf215546Sopenharmony_ci pool->create_flags = create_flags; 56bf215546Sopenharmony_ci util_dynarray_init(&pool->bos, dev->memctx); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci if (prealloc) 59bf215546Sopenharmony_ci agx_pool_alloc_backing(pool, POOL_SLAB_SIZE); 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_civoid 63bf215546Sopenharmony_ciagx_pool_cleanup(struct agx_pool *pool) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci util_dynarray_foreach(&pool->bos, struct agx_bo *, bo) { 66bf215546Sopenharmony_ci agx_bo_unreference(*bo); 67bf215546Sopenharmony_ci } 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci util_dynarray_fini(&pool->bos); 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_civoid 73bf215546Sopenharmony_ciagx_pool_get_bo_handles(struct agx_pool *pool, uint32_t *handles) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci unsigned idx = 0; 76bf215546Sopenharmony_ci util_dynarray_foreach(&pool->bos, struct agx_bo *, bo) { 77bf215546Sopenharmony_ci handles[idx++] = (*bo)->handle; 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistruct agx_ptr 82bf215546Sopenharmony_ciagx_pool_alloc_aligned(struct agx_pool *pool, size_t sz, unsigned alignment) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci alignment = MAX2(alignment, 4096); 85bf215546Sopenharmony_ci assert(alignment == util_next_power_of_two(alignment)); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci /* Find or create a suitable BO */ 88bf215546Sopenharmony_ci struct agx_bo *bo = pool->transient_bo; 89bf215546Sopenharmony_ci unsigned offset = ALIGN_POT(pool->transient_offset, alignment); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci /* If we don't fit, allocate a new backing */ 92bf215546Sopenharmony_ci if (unlikely(bo == NULL || (offset + sz) >= POOL_SLAB_SIZE)) { 93bf215546Sopenharmony_ci bo = agx_pool_alloc_backing(pool, 94bf215546Sopenharmony_ci ALIGN_POT(MAX2(POOL_SLAB_SIZE, sz), 4096)); 95bf215546Sopenharmony_ci offset = 0; 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci pool->transient_offset = offset + sz; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci struct agx_ptr ret = { 101bf215546Sopenharmony_ci .cpu = bo->ptr.cpu + offset, 102bf215546Sopenharmony_ci .gpu = bo->ptr.gpu + offset, 103bf215546Sopenharmony_ci }; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci return ret; 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ciuint64_t 109bf215546Sopenharmony_ciagx_pool_upload(struct agx_pool *pool, const void *data, size_t sz) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci return agx_pool_upload_aligned(pool, data, sz, util_next_power_of_two(sz)); 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ciuint64_t 115bf215546Sopenharmony_ciagx_pool_upload_aligned(struct agx_pool *pool, const void *data, size_t sz, unsigned alignment) 116bf215546Sopenharmony_ci{ 117bf215546Sopenharmony_ci alignment = MAX2(alignment, 4096); 118bf215546Sopenharmony_ci struct agx_ptr transfer = agx_pool_alloc_aligned(pool, sz, alignment); 119bf215546Sopenharmony_ci memcpy(transfer.cpu, data, sz); 120bf215546Sopenharmony_ci return transfer.gpu; 121bf215546Sopenharmony_ci} 122