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?
This commit is contained in:
Clément Foucault 2018-05-30 12:19:20 +02:00
parent 10c0bba28e
commit 48ceeead10
Notes: blender-bot 2023-02-14 10:35:28 +01:00
Referenced by issue #55243, Crash in ASAN debug builds due to use-after-free memory in draw code - instances issue?
4 changed files with 15 additions and 49 deletions

View File

@ -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));
}
}
}

View File

@ -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,

View File

@ -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 {

View File

@ -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! */