diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-05-30 13:19:20 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-05-30 13:25:20 +0300 |
commit | 48ceeead107e84631d89ea68efb7c04a61e3c19a (patch) | |
tree | abefea9f9860a211b12dbec0292b305e7a38c879 /source | |
parent | 10c0bba28e0ddc65594bacf6baba8371abb33dbe (diff) |
DRW: Instance Data: Replace with static allocation that can be referenced.
This mean you can store data used for drawing inside the object engine
data.
Also fixes T55243 Crash in ASAN debug builds due to use-after-free memory in draw code - instances issue?
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/draw_instance_data.c | 51 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_instance_data.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 8 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.h | 2 |
4 files changed, 15 insertions, 49 deletions
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index 6aa8da3badb..3e4f812af27 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -38,6 +38,7 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" +#include "BLI_mempool.h" #define BUFFER_CHUNK_SIZE 32 #define BUFFER_VERTS_CHUNK 32 @@ -69,18 +70,13 @@ typedef struct DRWInstanceChunk { struct DRWInstanceData { struct DRWInstanceData *next; bool used; /* If this data is used or not. */ - size_t chunk_size; /* Current size of the whole chunk. */ size_t data_size; /* Size of one instance data. */ - size_t instance_group; /* How many instance to allocate at a time. */ - size_t offset; /* Offset to the next instance data. */ - float *memchunk; /* Should be float no matter what. */ + BLI_mempool *mempool; }; struct DRWInstanceDataList { struct DRWInstanceDataList *next, *prev; /* Linked lists for all possible data pool size */ - /* Not entirely sure if we should separate them in the first place. - * This is done to minimize the reattribution misses. */ DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE]; DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE]; @@ -282,17 +278,13 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist) /** \name Instance Data (DRWInstanceData) * \{ */ -static DRWInstanceData *drw_instance_data_create( - DRWInstanceDataList *idatalist, uint attrib_size, uint instance_group) +static DRWInstanceData *drw_instance_data_create(DRWInstanceDataList *idatalist, uint attrib_size) { DRWInstanceData *idata = MEM_callocN(sizeof(DRWInstanceData), "DRWInstanceData"); idata->next = NULL; idata->used = true; idata->data_size = attrib_size; - idata->instance_group = instance_group; - idata->chunk_size = idata->data_size * instance_group; - idata->offset = 0; - idata->memchunk = MEM_mallocN(idata->chunk_size * sizeof(float), "DRWInstanceData memchunk"); + idata->mempool = BLI_mempool_create(sizeof(float) * idata->data_size, 0, 16, 0); BLI_assert(attrib_size > 0); @@ -310,35 +302,18 @@ static DRWInstanceData *drw_instance_data_create( static void DRW_instance_data_free(DRWInstanceData *idata) { - MEM_freeN(idata->memchunk); + BLI_mempool_destroy(idata->mempool); } /** * Return a pointer to the next instance data space. - * DO NOT SAVE/REUSE THIS POINTER after the next call - * to this function since the chunk may have been - * reallocated. **/ void *DRW_instance_data_next(DRWInstanceData *idata) { - idata->offset += idata->data_size; - - /* Check if chunk is large enough. realloc otherwise. */ - if (idata->offset > idata->chunk_size) { - idata->chunk_size += idata->data_size * idata->instance_group; - idata->memchunk = MEM_reallocN(idata->memchunk, idata->chunk_size * sizeof(float)); - } - - return idata->memchunk + (idata->offset - idata->data_size); + return BLI_mempool_alloc(idata->mempool); } -void *DRW_instance_data_get(DRWInstanceData *idata) -{ - return (void *)idata->memchunk; -} - -DRWInstanceData *DRW_instance_data_request( - DRWInstanceDataList *idatalist, uint attrib_size, uint instance_group) +DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attrib_size) { BLI_assert(attrib_size > 0 && attrib_size <= MAX_INSTANCE_DATA_SIZE); @@ -352,7 +327,7 @@ DRWInstanceData *DRW_instance_data_request( } } - return drw_instance_data_create(idatalist, attrib_size, instance_group); + return drw_instance_data_create(idatalist, attrib_size); } /** \} */ @@ -413,7 +388,6 @@ void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist) for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { idata->used = false; - idata->offset = 0; } } } @@ -454,14 +428,7 @@ void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist) for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { - /* Rounding up to nearest chunk size to compare. */ - size_t fac = idata->data_size * idata->instance_group; - size_t tmp = idata->offset + fac - 1; - size_t rounded_offset = tmp - tmp % fac; - if (rounded_offset < idata->chunk_size) { - idata->chunk_size = rounded_offset; - idata->memchunk = MEM_reallocN(idata->memchunk, idata->chunk_size * sizeof(float)); - } + BLI_mempool_clear_ex(idata->mempool, BLI_mempool_len(idata->mempool)); } } } diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h index bc3c0c2e04c..86c4429a091 100644 --- a/source/blender/draw/intern/draw_instance_data.h +++ b/source/blender/draw/intern/draw_instance_data.h @@ -39,9 +39,8 @@ typedef struct DRWInstanceDataList DRWInstanceDataList; struct DRWShadingGroup; void *DRW_instance_data_next(DRWInstanceData *idata); -void *DRW_instance_data_get(DRWInstanceData *idata); DRWInstanceData *DRW_instance_data_request( - DRWInstanceDataList *idatalist, uint attrib_size, uint instance_group); + DRWInstanceDataList *idatalist, uint attrib_size); void DRW_batching_buffer_request( DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_PrimType type, struct DRWShadingGroup *shgroup, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index fd233597daa..2aa24ade1b2 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -581,7 +581,7 @@ static void drw_viewport_var_init(void) DST.clipping.updated = false; - memset(DST.common_instance_data, 0x0, sizeof(DST.common_instance_data)); + memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data)); } void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) @@ -764,10 +764,10 @@ ObjectEngineData *DRW_object_engine_data_ensure( const size_t t = sizeof(float) - 1; size = (size + t) & ~t; size_t fsize = size / sizeof(float); - if (DST.common_instance_data[fsize] == NULL) { - DST.common_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize, 16); + if (DST.object_instance_data[fsize] == NULL) { + DST.object_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize); } - oed = (ObjectEngineData *)DRW_instance_data_next(DST.common_instance_data[fsize]); + oed = (ObjectEngineData *)DRW_instance_data_next(DST.object_instance_data[fsize]); memset(oed, 0, size); } else { diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 77bb37b9c8a..9faab2cc2b0 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -295,7 +295,7 @@ typedef struct DRWManager { /* Cache generation */ ViewportMemoryPool *vmempool; DRWInstanceDataList *idatalist; - DRWInstanceData *common_instance_data[MAX_INSTANCE_DATA_SIZE]; + DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE]; /* State of the object being evaluated if already allocated. */ DRWCallState *ob_state; unsigned char state_cache_id; /* Could be larger but 254 view changes is already a lot! */ |