diff options
Diffstat (limited to 'source/blender/draw/intern/draw_instance_data.c')
-rw-r--r-- | source/blender/draw/intern/draw_instance_data.c | 600 |
1 files changed, 305 insertions, 295 deletions
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index 718518643e0..27e03a3495a 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -41,44 +41,44 @@ #define BUFFER_VERTS_CHUNK 32 typedef struct DRWBatchingBuffer { - struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ - GPUVertFormat *format; /* Identifier. */ - GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */ - GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */ + struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ + GPUVertFormat *format; /* Identifier. */ + GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */ + GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */ } DRWBatchingBuffer; typedef struct DRWInstancingBuffer { - struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ - GPUVertFormat *format; /* Identifier. */ - GPUBatch *instance; /* Identifier. */ - GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */ - GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */ + struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ + GPUVertFormat *format; /* Identifier. */ + GPUBatch *instance; /* Identifier. */ + GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */ + GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */ } DRWInstancingBuffer; typedef struct DRWInstanceChunk { - size_t cursor; /* Offset to the next instance data. */ - size_t alloc_size; /* Number of DRWBatchingBuffer/Batches alloc'd in ibufs/btchs. */ - union { - DRWBatchingBuffer *bbufs; - DRWInstancingBuffer *ibufs; - }; + size_t cursor; /* Offset to the next instance data. */ + size_t alloc_size; /* Number of DRWBatchingBuffer/Batches alloc'd in ibufs/btchs. */ + union { + DRWBatchingBuffer *bbufs; + DRWInstancingBuffer *ibufs; + }; } DRWInstanceChunk; struct DRWInstanceData { - struct DRWInstanceData *next; - bool used; /* If this data is used or not. */ - size_t data_size; /* Size of one instance data. */ - BLI_mempool *mempool; + struct DRWInstanceData *next; + bool used; /* If this data is used or not. */ + size_t data_size; /* Size of one instance data. */ + BLI_mempool *mempool; }; struct DRWInstanceDataList { - struct DRWInstanceDataList *next, *prev; - /* Linked lists for all possible data pool size */ - DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE]; - DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE]; + struct DRWInstanceDataList *next, *prev; + /* Linked lists for all possible data pool size */ + DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE]; + DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE]; - DRWInstanceChunk instancing; - DRWInstanceChunk batching; + DRWInstanceChunk instancing; + DRWInstanceChunk batching; }; static ListBase g_idatalists = {NULL, NULL}; @@ -97,184 +97,192 @@ static ListBase g_idatalists = {NULL, NULL}; */ static void instance_batch_free(GPUBatch *batch, void *UNUSED(user_data)) { - if (batch->verts[0] == NULL) { - /** XXX This is a false positive case. - * The batch has been requested but not init yet - * and there is a chance that it might become init. - */ - return; - } - /* Free all batches that have the same key before they are reused. */ - /* TODO: Make it thread safe! Batch freeing can happen from another thread. */ - /* XXX we need to iterate over all idatalists unless we make some smart - * data structure to store the locations to update. */ - for (DRWInstanceDataList *idatalist = g_idatalists.first; idatalist; idatalist = idatalist->next) { - DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; - for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { - if (ibuf->instance == batch) { - BLI_assert(ibuf->shgroup == NULL); /* Make sure it has no other users. */ - GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); - GPU_BATCH_DISCARD_SAFE(ibuf->batch); - /* Tag as non alloced. */ - ibuf->format = NULL; - } - } - } + if (batch->verts[0] == NULL) { + /** XXX This is a false positive case. + * The batch has been requested but not init yet + * and there is a chance that it might become init. + */ + return; + } + /* Free all batches that have the same key before they are reused. */ + /* TODO: Make it thread safe! Batch freeing can happen from another thread. */ + /* XXX we need to iterate over all idatalists unless we make some smart + * data structure to store the locations to update. */ + for (DRWInstanceDataList *idatalist = g_idatalists.first; idatalist; + idatalist = idatalist->next) { + DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; + for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { + if (ibuf->instance == batch) { + BLI_assert(ibuf->shgroup == NULL); /* Make sure it has no other users. */ + GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); + GPU_BATCH_DISCARD_SAFE(ibuf->batch); + /* Tag as non alloced. */ + ibuf->format = NULL; + } + } + } } -void DRW_batching_buffer_request( - DRWInstanceDataList *idatalist, GPUVertFormat *format, GPUPrimType type, struct DRWShadingGroup *shgroup, - GPUBatch **r_batch, GPUVertBuf **r_vert) +void DRW_batching_buffer_request(DRWInstanceDataList *idatalist, + GPUVertFormat *format, + GPUPrimType type, + struct DRWShadingGroup *shgroup, + GPUBatch **r_batch, + GPUVertBuf **r_vert) { - DRWInstanceChunk *chunk = &idatalist->batching; - DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; - BLI_assert(format); - /* Search for an unused batch. */ - for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { - if (bbuf->shgroup == NULL) { - if (bbuf->format == format) { - bbuf->shgroup = shgroup; - *r_batch = bbuf->batch; - *r_vert = bbuf->vert; - return; - } - } - } - int new_id = 0; /* Find insertion point. */ - for (; new_id < chunk->alloc_size; ++new_id) { - if (chunk->bbufs[new_id].format == NULL) { - break; - } - } - /* If there is no batch left. Allocate more. */ - if (new_id == chunk->alloc_size) { - new_id = chunk->alloc_size; - chunk->alloc_size += BUFFER_CHUNK_SIZE; - chunk->bbufs = MEM_reallocN(chunk->bbufs, chunk->alloc_size * sizeof(DRWBatchingBuffer)); - memset(chunk->bbufs + new_id, 0, sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE); - } - /* Create the batch. */ - bbuf = chunk->bbufs + new_id; - bbuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC); - bbuf->batch = *r_batch = GPU_batch_create_ex(type, bbuf->vert, NULL, 0); - bbuf->format = format; - bbuf->shgroup = shgroup; - GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); + DRWInstanceChunk *chunk = &idatalist->batching; + DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; + BLI_assert(format); + /* Search for an unused batch. */ + for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { + if (bbuf->shgroup == NULL) { + if (bbuf->format == format) { + bbuf->shgroup = shgroup; + *r_batch = bbuf->batch; + *r_vert = bbuf->vert; + return; + } + } + } + int new_id = 0; /* Find insertion point. */ + for (; new_id < chunk->alloc_size; ++new_id) { + if (chunk->bbufs[new_id].format == NULL) { + break; + } + } + /* If there is no batch left. Allocate more. */ + if (new_id == chunk->alloc_size) { + new_id = chunk->alloc_size; + chunk->alloc_size += BUFFER_CHUNK_SIZE; + chunk->bbufs = MEM_reallocN(chunk->bbufs, chunk->alloc_size * sizeof(DRWBatchingBuffer)); + memset(chunk->bbufs + new_id, 0, sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE); + } + /* Create the batch. */ + bbuf = chunk->bbufs + new_id; + bbuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC); + bbuf->batch = *r_batch = GPU_batch_create_ex(type, bbuf->vert, NULL, 0); + bbuf->format = format; + bbuf->shgroup = shgroup; + GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); } -void DRW_instancing_buffer_request( - DRWInstanceDataList *idatalist, GPUVertFormat *format, GPUBatch *instance, struct DRWShadingGroup *shgroup, - GPUBatch **r_batch, GPUVertBuf **r_vert) +void DRW_instancing_buffer_request(DRWInstanceDataList *idatalist, + GPUVertFormat *format, + GPUBatch *instance, + struct DRWShadingGroup *shgroup, + GPUBatch **r_batch, + GPUVertBuf **r_vert) { - DRWInstanceChunk *chunk = &idatalist->instancing; - DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; - BLI_assert(format); - /* Search for an unused batch. */ - for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { - if (ibuf->shgroup == NULL) { - if (ibuf->format == format) { - if (ibuf->instance == instance) { - ibuf->shgroup = shgroup; - *r_batch = ibuf->batch; - *r_vert = ibuf->vert; - return; - } - } - } - } - int new_id = 0; /* Find insertion point. */ - for (; new_id < chunk->alloc_size; ++new_id) { - if (chunk->ibufs[new_id].format == NULL) { - break; - } - } - /* If there is no batch left. Allocate more. */ - if (new_id == chunk->alloc_size) { - new_id = chunk->alloc_size; - chunk->alloc_size += BUFFER_CHUNK_SIZE; - chunk->ibufs = MEM_reallocN(chunk->ibufs, chunk->alloc_size * sizeof(DRWInstancingBuffer)); - memset(chunk->ibufs + new_id, 0, sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE); - } - /* Create the batch. */ - ibuf = chunk->ibufs + new_id; - ibuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC); - ibuf->batch = *r_batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch"); - ibuf->format = format; - ibuf->shgroup = shgroup; - ibuf->instance = instance; - GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); - /* Make sure to free this ibuf if the instance batch gets free. */ - GPU_batch_callback_free_set(instance, &instance_batch_free, NULL); + DRWInstanceChunk *chunk = &idatalist->instancing; + DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; + BLI_assert(format); + /* Search for an unused batch. */ + for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { + if (ibuf->shgroup == NULL) { + if (ibuf->format == format) { + if (ibuf->instance == instance) { + ibuf->shgroup = shgroup; + *r_batch = ibuf->batch; + *r_vert = ibuf->vert; + return; + } + } + } + } + int new_id = 0; /* Find insertion point. */ + for (; new_id < chunk->alloc_size; ++new_id) { + if (chunk->ibufs[new_id].format == NULL) { + break; + } + } + /* If there is no batch left. Allocate more. */ + if (new_id == chunk->alloc_size) { + new_id = chunk->alloc_size; + chunk->alloc_size += BUFFER_CHUNK_SIZE; + chunk->ibufs = MEM_reallocN(chunk->ibufs, chunk->alloc_size * sizeof(DRWInstancingBuffer)); + memset(chunk->ibufs + new_id, 0, sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE); + } + /* Create the batch. */ + ibuf = chunk->ibufs + new_id; + ibuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC); + ibuf->batch = *r_batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch"); + ibuf->format = format; + ibuf->shgroup = shgroup; + ibuf->instance = instance; + GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); + /* Make sure to free this ibuf if the instance batch gets free. */ + GPU_batch_callback_free_set(instance, &instance_batch_free, NULL); } void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist) { - size_t realloc_size = 1; /* Avoid 0 size realloc. */ - /* Resize down buffers in use and send data to GPU & free unused buffers. */ - DRWInstanceChunk *batching = &idatalist->batching; - DRWBatchingBuffer *bbuf = batching->bbufs; - for (int i = 0; i < batching->alloc_size; i++, bbuf++) { - if (bbuf->shgroup != NULL) { - realloc_size = i + 1; - uint vert_len = DRW_shgroup_get_instance_count(bbuf->shgroup); - vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ - if (vert_len + BUFFER_VERTS_CHUNK <= bbuf->vert->vertex_len) { - uint size = vert_len + BUFFER_VERTS_CHUNK - 1; - size = size - size % BUFFER_VERTS_CHUNK; - GPU_vertbuf_data_resize(bbuf->vert, size); - } - GPU_vertbuf_use(bbuf->vert); /* Send data. */ - bbuf->shgroup = NULL; /* Set as non used for the next round. */ - } - else { - GPU_VERTBUF_DISCARD_SAFE(bbuf->vert); - GPU_BATCH_DISCARD_SAFE(bbuf->batch); - bbuf->format = NULL; /* Tag as non alloced. */ - } - } - /* Rounding up to nearest chunk size. */ - realloc_size += BUFFER_CHUNK_SIZE - 1; - realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; - /* Resize down if necessary. */ - if (realloc_size < batching->alloc_size) { - batching->alloc_size = realloc_size; - batching->ibufs = MEM_reallocN(batching->ibufs, realloc_size * sizeof(DRWBatchingBuffer)); - } - - realloc_size = 1; - /* Resize down buffers in use and send data to GPU & free unused buffers. */ - DRWInstanceChunk *instancing = &idatalist->instancing; - DRWInstancingBuffer *ibuf = instancing->ibufs; - for (int i = 0; i < instancing->alloc_size; i++, ibuf++) { - if (ibuf->shgroup != NULL) { - realloc_size = i + 1; - uint vert_len = DRW_shgroup_get_instance_count(ibuf->shgroup); - vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ - if (vert_len + BUFFER_VERTS_CHUNK <= ibuf->vert->vertex_len) { - uint size = vert_len + BUFFER_VERTS_CHUNK - 1; - size = size - size % BUFFER_VERTS_CHUNK; - GPU_vertbuf_data_resize(ibuf->vert, size); - } - GPU_vertbuf_use(ibuf->vert); /* Send data. */ - /* Setup batch now that we are sure ibuf->instance is setup. */ - GPU_batch_copy(ibuf->batch, ibuf->instance); - GPU_batch_instbuf_set(ibuf->batch, ibuf->vert, false); - ibuf->shgroup = NULL; /* Set as non used for the next round. */ - } - else { - GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); - GPU_BATCH_DISCARD_SAFE(ibuf->batch); - ibuf->format = NULL; /* Tag as non alloced. */ - } - } - /* Rounding up to nearest chunk size. */ - realloc_size += BUFFER_CHUNK_SIZE - 1; - realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; - /* Resize down if necessary. */ - if (realloc_size < instancing->alloc_size) { - instancing->alloc_size = realloc_size; - instancing->ibufs = MEM_reallocN(instancing->ibufs, realloc_size * sizeof(DRWInstancingBuffer)); - } + size_t realloc_size = 1; /* Avoid 0 size realloc. */ + /* Resize down buffers in use and send data to GPU & free unused buffers. */ + DRWInstanceChunk *batching = &idatalist->batching; + DRWBatchingBuffer *bbuf = batching->bbufs; + for (int i = 0; i < batching->alloc_size; i++, bbuf++) { + if (bbuf->shgroup != NULL) { + realloc_size = i + 1; + uint vert_len = DRW_shgroup_get_instance_count(bbuf->shgroup); + vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ + if (vert_len + BUFFER_VERTS_CHUNK <= bbuf->vert->vertex_len) { + uint size = vert_len + BUFFER_VERTS_CHUNK - 1; + size = size - size % BUFFER_VERTS_CHUNK; + GPU_vertbuf_data_resize(bbuf->vert, size); + } + GPU_vertbuf_use(bbuf->vert); /* Send data. */ + bbuf->shgroup = NULL; /* Set as non used for the next round. */ + } + else { + GPU_VERTBUF_DISCARD_SAFE(bbuf->vert); + GPU_BATCH_DISCARD_SAFE(bbuf->batch); + bbuf->format = NULL; /* Tag as non alloced. */ + } + } + /* Rounding up to nearest chunk size. */ + realloc_size += BUFFER_CHUNK_SIZE - 1; + realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; + /* Resize down if necessary. */ + if (realloc_size < batching->alloc_size) { + batching->alloc_size = realloc_size; + batching->ibufs = MEM_reallocN(batching->ibufs, realloc_size * sizeof(DRWBatchingBuffer)); + } + + realloc_size = 1; + /* Resize down buffers in use and send data to GPU & free unused buffers. */ + DRWInstanceChunk *instancing = &idatalist->instancing; + DRWInstancingBuffer *ibuf = instancing->ibufs; + for (int i = 0; i < instancing->alloc_size; i++, ibuf++) { + if (ibuf->shgroup != NULL) { + realloc_size = i + 1; + uint vert_len = DRW_shgroup_get_instance_count(ibuf->shgroup); + vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ + if (vert_len + BUFFER_VERTS_CHUNK <= ibuf->vert->vertex_len) { + uint size = vert_len + BUFFER_VERTS_CHUNK - 1; + size = size - size % BUFFER_VERTS_CHUNK; + GPU_vertbuf_data_resize(ibuf->vert, size); + } + GPU_vertbuf_use(ibuf->vert); /* Send data. */ + /* Setup batch now that we are sure ibuf->instance is setup. */ + GPU_batch_copy(ibuf->batch, ibuf->instance); + GPU_batch_instbuf_set(ibuf->batch, ibuf->vert, false); + ibuf->shgroup = NULL; /* Set as non used for the next round. */ + } + else { + GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); + GPU_BATCH_DISCARD_SAFE(ibuf->batch); + ibuf->format = NULL; /* Tag as non alloced. */ + } + } + /* Rounding up to nearest chunk size. */ + realloc_size += BUFFER_CHUNK_SIZE - 1; + realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; + /* Resize down if necessary. */ + if (realloc_size < instancing->alloc_size) { + instancing->alloc_size = realloc_size; + instancing->ibufs = MEM_reallocN(instancing->ibufs, + realloc_size * sizeof(DRWInstancingBuffer)); + } } /** \} */ @@ -285,29 +293,29 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist) static DRWInstanceData *drw_instance_data_create(DRWInstanceDataList *idatalist, uint attr_size) { - DRWInstanceData *idata = MEM_callocN(sizeof(DRWInstanceData), "DRWInstanceData"); - idata->next = NULL; - idata->used = true; - idata->data_size = attr_size; - idata->mempool = BLI_mempool_create(sizeof(float) * idata->data_size, 0, 16, 0); - - BLI_assert(attr_size > 0); - - /* Push to linked list. */ - if (idatalist->idata_head[attr_size - 1] == NULL) { - idatalist->idata_head[attr_size - 1] = idata; - } - else { - idatalist->idata_tail[attr_size - 1]->next = idata; - } - idatalist->idata_tail[attr_size - 1] = idata; - - return idata; + DRWInstanceData *idata = MEM_callocN(sizeof(DRWInstanceData), "DRWInstanceData"); + idata->next = NULL; + idata->used = true; + idata->data_size = attr_size; + idata->mempool = BLI_mempool_create(sizeof(float) * idata->data_size, 0, 16, 0); + + BLI_assert(attr_size > 0); + + /* Push to linked list. */ + if (idatalist->idata_head[attr_size - 1] == NULL) { + idatalist->idata_head[attr_size - 1] = idata; + } + else { + idatalist->idata_tail[attr_size - 1]->next = idata; + } + idatalist->idata_tail[attr_size - 1] = idata; + + return idata; } static void DRW_instance_data_free(DRWInstanceData *idata) { - BLI_mempool_destroy(idata->mempool); + BLI_mempool_destroy(idata->mempool); } /** @@ -315,24 +323,24 @@ static void DRW_instance_data_free(DRWInstanceData *idata) */ void *DRW_instance_data_next(DRWInstanceData *idata) { - return BLI_mempool_alloc(idata->mempool); + return BLI_mempool_alloc(idata->mempool); } DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attr_size) { - BLI_assert(attr_size > 0 && attr_size <= MAX_INSTANCE_DATA_SIZE); + BLI_assert(attr_size > 0 && attr_size <= MAX_INSTANCE_DATA_SIZE); - DRWInstanceData *idata = idatalist->idata_head[attr_size - 1]; + DRWInstanceData *idata = idatalist->idata_head[attr_size - 1]; - /* Search for an unused data chunk. */ - for (; idata; idata = idata->next) { - if (idata->used == false) { - idata->used = true; - return idata; - } - } + /* Search for an unused data chunk. */ + for (; idata; idata = idata->next) { + if (idata->used == false) { + idata->used = true; + return idata; + } + } - return drw_instance_data_create(idatalist, attr_size); + return drw_instance_data_create(idatalist, attr_size); } /** \} */ @@ -343,98 +351,100 @@ DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint DRWInstanceDataList *DRW_instance_data_list_create(void) { - DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList"); - idatalist->batching.bbufs = MEM_callocN(sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE, "DRWBatchingBuffers"); - idatalist->batching.alloc_size = BUFFER_CHUNK_SIZE; - idatalist->instancing.ibufs = MEM_callocN(sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE, "DRWInstancingBuffers"); - idatalist->instancing.alloc_size = BUFFER_CHUNK_SIZE; + DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList"); + idatalist->batching.bbufs = MEM_callocN(sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE, + "DRWBatchingBuffers"); + idatalist->batching.alloc_size = BUFFER_CHUNK_SIZE; + idatalist->instancing.ibufs = MEM_callocN(sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE, + "DRWInstancingBuffers"); + idatalist->instancing.alloc_size = BUFFER_CHUNK_SIZE; - BLI_addtail(&g_idatalists, idatalist); + BLI_addtail(&g_idatalists, idatalist); - return idatalist; + return idatalist; } void DRW_instance_data_list_free(DRWInstanceDataList *idatalist) { - DRWInstanceData *idata, *next_idata; - - for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { - for (idata = idatalist->idata_head[i]; idata; idata = next_idata) { - next_idata = idata->next; - DRW_instance_data_free(idata); - MEM_freeN(idata); - } - idatalist->idata_head[i] = NULL; - idatalist->idata_tail[i] = NULL; - } - - DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; - for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { - GPU_VERTBUF_DISCARD_SAFE(bbuf->vert); - GPU_BATCH_DISCARD_SAFE(bbuf->batch); - } - MEM_freeN(idatalist->batching.bbufs); - - DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; - for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { - GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); - GPU_BATCH_DISCARD_SAFE(ibuf->batch); - } - MEM_freeN(idatalist->instancing.ibufs); - - BLI_remlink(&g_idatalists, idatalist); + DRWInstanceData *idata, *next_idata; + + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + for (idata = idatalist->idata_head[i]; idata; idata = next_idata) { + next_idata = idata->next; + DRW_instance_data_free(idata); + MEM_freeN(idata); + } + idatalist->idata_head[i] = NULL; + idatalist->idata_tail[i] = NULL; + } + + DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; + for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { + GPU_VERTBUF_DISCARD_SAFE(bbuf->vert); + GPU_BATCH_DISCARD_SAFE(bbuf->batch); + } + MEM_freeN(idatalist->batching.bbufs); + + DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; + for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { + GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); + GPU_BATCH_DISCARD_SAFE(ibuf->batch); + } + MEM_freeN(idatalist->instancing.ibufs); + + BLI_remlink(&g_idatalists, idatalist); } void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist) { - DRWInstanceData *idata; + DRWInstanceData *idata; - for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { - for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { - idata->used = false; - } - } + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { + idata->used = false; + } + } } void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist) { - DRWInstanceData *idata, *next_idata; - - /* Remove unused data blocks and sanitize each list. */ - for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { - idatalist->idata_tail[i] = NULL; - for (idata = idatalist->idata_head[i]; idata; idata = next_idata) { - next_idata = idata->next; - if (idata->used == false) { - if (idatalist->idata_head[i] == idata) { - idatalist->idata_head[i] = next_idata; - } - else { - /* idatalist->idata_tail[i] is guaranteed not to be null in this case. */ - idatalist->idata_tail[i]->next = next_idata; - } - DRW_instance_data_free(idata); - MEM_freeN(idata); - } - else { - if (idatalist->idata_tail[i] != NULL) { - idatalist->idata_tail[i]->next = idata; - } - idatalist->idata_tail[i] = idata; - } - } - } + DRWInstanceData *idata, *next_idata; + + /* Remove unused data blocks and sanitize each list. */ + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + idatalist->idata_tail[i] = NULL; + for (idata = idatalist->idata_head[i]; idata; idata = next_idata) { + next_idata = idata->next; + if (idata->used == false) { + if (idatalist->idata_head[i] == idata) { + idatalist->idata_head[i] = next_idata; + } + else { + /* idatalist->idata_tail[i] is guaranteed not to be null in this case. */ + idatalist->idata_tail[i]->next = next_idata; + } + DRW_instance_data_free(idata); + MEM_freeN(idata); + } + else { + if (idatalist->idata_tail[i] != NULL) { + idatalist->idata_tail[i]->next = idata; + } + idatalist->idata_tail[i] = idata; + } + } + } } void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist) { - DRWInstanceData *idata; + DRWInstanceData *idata; - for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { - for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { - BLI_mempool_clear_ex(idata->mempool, BLI_mempool_len(idata->mempool)); - } - } + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { + BLI_mempool_clear_ex(idata->mempool, BLI_mempool_len(idata->mempool)); + } + } } /** \} */ |