BLI_memblock: Add more options
- Use int instead of uint for safety and less conversions. - Add free callback - Add cleared alloc option
This commit is contained in:
@@ -33,16 +33,18 @@ extern "C" {
|
|||||||
struct BLI_memblock;
|
struct BLI_memblock;
|
||||||
|
|
||||||
typedef struct BLI_memblock BLI_memblock;
|
typedef struct BLI_memblock BLI_memblock;
|
||||||
|
typedef void (*MemblockValFreeFP)(void *val);
|
||||||
|
|
||||||
BLI_memblock *BLI_memblock_create(uint elem_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
|
BLI_memblock *BLI_memblock_create(uint elem_size,
|
||||||
|
const bool clear_alloc) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
|
||||||
void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||||
void BLI_memblock_clear(BLI_memblock *mblk) ATTR_NONNULL(1);
|
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP valfreefp) ATTR_NONNULL(1);
|
||||||
void BLI_memblock_destroy(BLI_memblock *mblk) ATTR_NONNULL(1);
|
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1);
|
||||||
|
|
||||||
typedef struct BLI_memblock_iter {
|
typedef struct BLI_memblock_iter {
|
||||||
BLI_memblock *mblk;
|
BLI_memblock *mblk;
|
||||||
uint current_index;
|
int current_index;
|
||||||
uint elem_per_chunk;
|
int elem_per_chunk;
|
||||||
} BLI_memblock_iter;
|
} BLI_memblock_iter;
|
||||||
|
|
||||||
void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL();
|
void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL();
|
||||||
|
|||||||
@@ -44,31 +44,51 @@ struct BLI_memblock {
|
|||||||
void **chunk_list;
|
void **chunk_list;
|
||||||
|
|
||||||
/** Element size in bytes. */
|
/** Element size in bytes. */
|
||||||
uint elem_size;
|
int elem_size;
|
||||||
/** First unused element index. */
|
/** First unused element index. */
|
||||||
uint elem_next;
|
int elem_next;
|
||||||
|
/** Last "touched" element. */
|
||||||
|
int elem_last;
|
||||||
/** Chunck size in bytes. */
|
/** Chunck size in bytes. */
|
||||||
uint chunk_size;
|
int chunk_size;
|
||||||
/** Number of allocated chunck. */
|
/** Number of allocated chunck. */
|
||||||
uint chunk_len;
|
int chunk_len;
|
||||||
|
/** Clear newly allocated chuncks. */
|
||||||
|
bool clear_alloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
BLI_memblock *BLI_memblock_create(uint elem_size)
|
/**
|
||||||
|
* /clear_alloc will clear the memory the first time a chunck is allocated.
|
||||||
|
*/
|
||||||
|
BLI_memblock *BLI_memblock_create(uint elem_size, const bool clear_alloc)
|
||||||
{
|
{
|
||||||
BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE);
|
BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE);
|
||||||
|
|
||||||
BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock");
|
BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock");
|
||||||
mblk->elem_size = elem_size;
|
mblk->elem_size = (int)elem_size;
|
||||||
mblk->elem_next = 0;
|
mblk->elem_next = 0;
|
||||||
|
mblk->elem_last = -1;
|
||||||
mblk->chunk_size = BLI_MEM_BLOCK_CHUNK_SIZE;
|
mblk->chunk_size = BLI_MEM_BLOCK_CHUNK_SIZE;
|
||||||
mblk->chunk_len = CHUNK_LIST_SIZE;
|
mblk->chunk_len = CHUNK_LIST_SIZE;
|
||||||
mblk->chunk_list = MEM_callocN(sizeof(void *) * mblk->chunk_len, "BLI_memblock chunk list");
|
mblk->chunk_list = MEM_callocN(sizeof(void *) * (uint)mblk->chunk_len, "chunk list");
|
||||||
|
mblk->clear_alloc = clear_alloc;
|
||||||
return mblk;
|
return mblk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLI_memblock_destroy(BLI_memblock *mblk)
|
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < mblk->chunk_len; i++) {
|
if (free_callback) {
|
||||||
|
int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
|
||||||
|
|
||||||
|
for (int i = mblk->elem_last; i >= 0; i--) {
|
||||||
|
int chunk_idx = i / elem_per_chunk;
|
||||||
|
int elem_idx = i - elem_per_chunk * chunk_idx;
|
||||||
|
void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
|
||||||
|
free_callback(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < mblk->chunk_len; i++) {
|
||||||
MEM_SAFE_FREE(mblk->chunk_list[i]);
|
MEM_SAFE_FREE(mblk->chunk_list[i]);
|
||||||
}
|
}
|
||||||
MEM_SAFE_FREE(mblk->chunk_list);
|
MEM_SAFE_FREE(mblk->chunk_list);
|
||||||
@@ -77,37 +97,57 @@ void BLI_memblock_destroy(BLI_memblock *mblk)
|
|||||||
|
|
||||||
/* Reset elem count to 0 but keep as much memory allocated needed for at least the previous elem
|
/* Reset elem count to 0 but keep as much memory allocated needed for at least the previous elem
|
||||||
* count. */
|
* count. */
|
||||||
void BLI_memblock_clear(BLI_memblock *mblk)
|
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback)
|
||||||
{
|
{
|
||||||
uint elem_per_chunk = mblk->chunk_size / mblk->elem_size;
|
int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
|
||||||
uint last_used_chunk = (mblk->elem_next - 1) / elem_per_chunk;
|
int last_used_chunk = (mblk->elem_next - 1) / elem_per_chunk;
|
||||||
|
|
||||||
for (uint i = last_used_chunk + 1; i < mblk->chunk_len; i++) {
|
if (free_callback) {
|
||||||
|
for (int i = mblk->elem_last; i >= mblk->elem_next; i--) {
|
||||||
|
int chunk_idx = i / elem_per_chunk;
|
||||||
|
int elem_idx = i - elem_per_chunk * chunk_idx;
|
||||||
|
void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
|
||||||
|
free_callback(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = last_used_chunk + 1; i < mblk->chunk_len; i++) {
|
||||||
MEM_SAFE_FREE(mblk->chunk_list[i]);
|
MEM_SAFE_FREE(mblk->chunk_list[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(last_used_chunk + 1 < mblk->chunk_len - CHUNK_LIST_SIZE)) {
|
if (UNLIKELY(last_used_chunk + 1 < mblk->chunk_len - CHUNK_LIST_SIZE)) {
|
||||||
mblk->chunk_len -= CHUNK_LIST_SIZE;
|
mblk->chunk_len -= CHUNK_LIST_SIZE;
|
||||||
mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * mblk->chunk_len);
|
mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mblk->elem_last = mblk->elem_next - 1;
|
||||||
mblk->elem_next = 0;
|
mblk->elem_next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *BLI_memblock_alloc(BLI_memblock *mblk)
|
void *BLI_memblock_alloc(BLI_memblock *mblk)
|
||||||
{
|
{
|
||||||
uint elem_per_chunk = mblk->chunk_size / mblk->elem_size;
|
int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
|
||||||
uint chunk_idx = mblk->elem_next / elem_per_chunk;
|
int chunk_idx = mblk->elem_next / elem_per_chunk;
|
||||||
uint elem_idx = mblk->elem_next - elem_per_chunk * chunk_idx;
|
int elem_idx = mblk->elem_next - elem_per_chunk * chunk_idx;
|
||||||
|
|
||||||
|
if (mblk->elem_last < mblk->elem_next) {
|
||||||
|
mblk->elem_last = mblk->elem_next;
|
||||||
|
}
|
||||||
|
|
||||||
mblk->elem_next++;
|
mblk->elem_next++;
|
||||||
|
|
||||||
if (UNLIKELY(chunk_idx >= mblk->chunk_len)) {
|
if (UNLIKELY(chunk_idx >= mblk->chunk_len)) {
|
||||||
mblk->chunk_len += CHUNK_LIST_SIZE;
|
mblk->chunk_len += CHUNK_LIST_SIZE;
|
||||||
mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * mblk->chunk_len);
|
mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(mblk->chunk_list[chunk_idx] == NULL)) {
|
if (UNLIKELY(mblk->chunk_list[chunk_idx] == NULL)) {
|
||||||
mblk->chunk_list[chunk_idx] = MEM_mallocN(mblk->chunk_size, "BLI_memblock chunk");
|
if (mblk->clear_alloc) {
|
||||||
|
mblk->chunk_list[chunk_idx] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mblk->chunk_list[chunk_idx] = MEM_mallocN((uint)mblk->chunk_size, "BLI_memblock chunk");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
|
return (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
|
||||||
@@ -126,8 +166,8 @@ void *BLI_memblock_iterstep(BLI_memblock_iter *iter)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint chunk_idx = iter->current_index / iter->elem_per_chunk;
|
int chunk_idx = iter->current_index / iter->elem_per_chunk;
|
||||||
uint elem_idx = iter->current_index - iter->elem_per_chunk * chunk_idx;
|
int elem_idx = iter->current_index - iter->elem_per_chunk * chunk_idx;
|
||||||
iter->current_index++;
|
iter->current_index++;
|
||||||
|
|
||||||
return (char *)(iter->mblk->chunk_list[chunk_idx]) + iter->mblk->elem_size * elem_idx;
|
return (char *)(iter->mblk->chunk_list[chunk_idx]) + iter->mblk->elem_size * elem_idx;
|
||||||
|
|||||||
@@ -535,12 +535,12 @@ static void drw_viewport_cache_resize(void)
|
|||||||
GPU_texture_free(*tex);
|
GPU_texture_free(*tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_memblock_clear(DST.vmempool->calls);
|
BLI_memblock_clear(DST.vmempool->calls, NULL);
|
||||||
BLI_memblock_clear(DST.vmempool->states);
|
BLI_memblock_clear(DST.vmempool->states, NULL);
|
||||||
BLI_memblock_clear(DST.vmempool->shgroups);
|
BLI_memblock_clear(DST.vmempool->shgroups, NULL);
|
||||||
BLI_memblock_clear(DST.vmempool->uniforms);
|
BLI_memblock_clear(DST.vmempool->uniforms, NULL);
|
||||||
BLI_memblock_clear(DST.vmempool->passes);
|
BLI_memblock_clear(DST.vmempool->passes, NULL);
|
||||||
BLI_memblock_clear(DST.vmempool->images);
|
BLI_memblock_clear(DST.vmempool->images, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRW_instance_data_list_free_unused(DST.idatalist);
|
DRW_instance_data_list_free_unused(DST.idatalist);
|
||||||
@@ -605,22 +605,22 @@ static void drw_viewport_var_init(void)
|
|||||||
DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
|
DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
|
||||||
|
|
||||||
if (DST.vmempool->calls == NULL) {
|
if (DST.vmempool->calls == NULL) {
|
||||||
DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall));
|
DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall), false);
|
||||||
}
|
}
|
||||||
if (DST.vmempool->states == NULL) {
|
if (DST.vmempool->states == NULL) {
|
||||||
DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState));
|
DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState), false);
|
||||||
}
|
}
|
||||||
if (DST.vmempool->shgroups == NULL) {
|
if (DST.vmempool->shgroups == NULL) {
|
||||||
DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup));
|
DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup), false);
|
||||||
}
|
}
|
||||||
if (DST.vmempool->uniforms == NULL) {
|
if (DST.vmempool->uniforms == NULL) {
|
||||||
DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform));
|
DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform), false);
|
||||||
}
|
}
|
||||||
if (DST.vmempool->passes == NULL) {
|
if (DST.vmempool->passes == NULL) {
|
||||||
DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass));
|
DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass), false);
|
||||||
}
|
}
|
||||||
if (DST.vmempool->images == NULL) {
|
if (DST.vmempool->images == NULL) {
|
||||||
DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
|
DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
|
DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
|
||||||
|
|||||||
@@ -620,19 +620,19 @@ void GPU_viewport_free(GPUViewport *viewport)
|
|||||||
MEM_freeN(viewport->txl);
|
MEM_freeN(viewport->txl);
|
||||||
|
|
||||||
if (viewport->vmempool.calls != NULL) {
|
if (viewport->vmempool.calls != NULL) {
|
||||||
BLI_memblock_destroy(viewport->vmempool.calls);
|
BLI_memblock_destroy(viewport->vmempool.calls, NULL);
|
||||||
}
|
}
|
||||||
if (viewport->vmempool.states != NULL) {
|
if (viewport->vmempool.states != NULL) {
|
||||||
BLI_memblock_destroy(viewport->vmempool.states);
|
BLI_memblock_destroy(viewport->vmempool.states, NULL);
|
||||||
}
|
}
|
||||||
if (viewport->vmempool.shgroups != NULL) {
|
if (viewport->vmempool.shgroups != NULL) {
|
||||||
BLI_memblock_destroy(viewport->vmempool.shgroups);
|
BLI_memblock_destroy(viewport->vmempool.shgroups, NULL);
|
||||||
}
|
}
|
||||||
if (viewport->vmempool.uniforms != NULL) {
|
if (viewport->vmempool.uniforms != NULL) {
|
||||||
BLI_memblock_destroy(viewport->vmempool.uniforms);
|
BLI_memblock_destroy(viewport->vmempool.uniforms, NULL);
|
||||||
}
|
}
|
||||||
if (viewport->vmempool.passes != NULL) {
|
if (viewport->vmempool.passes != NULL) {
|
||||||
BLI_memblock_destroy(viewport->vmempool.passes);
|
BLI_memblock_destroy(viewport->vmempool.passes, NULL);
|
||||||
}
|
}
|
||||||
if (viewport->vmempool.images != NULL) {
|
if (viewport->vmempool.images != NULL) {
|
||||||
BLI_memblock_iter iter;
|
BLI_memblock_iter iter;
|
||||||
@@ -641,7 +641,7 @@ void GPU_viewport_free(GPUViewport *viewport)
|
|||||||
while ((tex = BLI_memblock_iterstep(&iter))) {
|
while ((tex = BLI_memblock_iterstep(&iter))) {
|
||||||
GPU_texture_free(*tex);
|
GPU_texture_free(*tex);
|
||||||
}
|
}
|
||||||
BLI_memblock_destroy(viewport->vmempool.images);
|
BLI_memblock_destroy(viewport->vmempool.images, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRW_instance_data_list_free(viewport->idatalist);
|
DRW_instance_data_list_free(viewport->idatalist);
|
||||||
|
|||||||
Reference in New Issue
Block a user