DRW: Use pseudo persistent memory pool for the rendering data structure.
This gets rid of the bottleneck of allocation / free of thousands of elements every frame. Cache time (Eevee) (test scene is default file with cube duplicated 3241 times) pre-patch: 23ms post-patch: 14ms
This commit is contained in:
parent
5d70e847dd
commit
ed555750eb
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "BLI_dynstr.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_mempool.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
|
@ -130,13 +131,6 @@
|
|||
/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
|
||||
#define USE_GPU_SELECT
|
||||
|
||||
/* Use BLI_memiter */
|
||||
#define USE_MEM_ITER
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
#include "BLI_memiter.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_GPU_SELECT
|
||||
# include "ED_view3d.h"
|
||||
# include "ED_armature.h"
|
||||
|
@ -147,6 +141,7 @@
|
|||
|
||||
|
||||
#define MAX_ATTRIB_NAME 32
|
||||
#define MAX_ATTRIB_COUNT 6 /* Can be adjusted for more */
|
||||
#define MAX_PASS_NAME 32
|
||||
#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
|
||||
|
||||
|
@ -177,7 +172,7 @@ typedef enum {
|
|||
} DRWAttribType;
|
||||
|
||||
struct DRWUniform {
|
||||
struct DRWUniform *next, *prev;
|
||||
struct DRWUniform *next;
|
||||
DRWUniformType type;
|
||||
int location;
|
||||
int length;
|
||||
|
@ -186,7 +181,7 @@ struct DRWUniform {
|
|||
};
|
||||
|
||||
typedef struct DRWAttrib {
|
||||
struct DRWAttrib *next, *prev;
|
||||
struct DRWAttrib *prev;
|
||||
char name[MAX_ATTRIB_NAME];
|
||||
int location;
|
||||
int format_id;
|
||||
|
@ -195,8 +190,9 @@ typedef struct DRWAttrib {
|
|||
} DRWAttrib;
|
||||
|
||||
struct DRWInterface {
|
||||
ListBase uniforms; /* DRWUniform */
|
||||
ListBase attribs; /* DRWAttrib */
|
||||
DRWUniform *uniforms; /* DRWUniform, single-linked list */
|
||||
DRWAttrib *attribs; /* DRWAttrib, single-linked list */
|
||||
DRWAttrib *attribs_first; /* First added attrib to traverse in the right order */
|
||||
int attribs_count;
|
||||
int attribs_stride;
|
||||
int attribs_size[16];
|
||||
|
@ -227,15 +223,16 @@ struct DRWInterface {
|
|||
};
|
||||
|
||||
struct DRWPass {
|
||||
ListBase shgroups; /* DRWShadingGroup */
|
||||
/* Single linked list with last member to append */
|
||||
DRWShadingGroup *shgroups;
|
||||
DRWShadingGroup *shgroups_last;
|
||||
|
||||
DRWState state;
|
||||
char name[MAX_PASS_NAME];
|
||||
};
|
||||
|
||||
typedef struct DRWCallHeader {
|
||||
#ifndef USE_MEM_ITER
|
||||
void *next, *prev;
|
||||
#endif
|
||||
void *prev;
|
||||
|
||||
#ifdef USE_GPU_SELECT
|
||||
int select_id;
|
||||
|
@ -265,21 +262,18 @@ typedef struct DRWCallGenerate {
|
|||
typedef struct DRWCallDynamic {
|
||||
DRWCallHeader head;
|
||||
|
||||
const void *data[];
|
||||
const void *data[MAX_ATTRIB_COUNT];
|
||||
} DRWCallDynamic;
|
||||
|
||||
struct DRWShadingGroup {
|
||||
struct DRWShadingGroup *next, *prev;
|
||||
struct DRWShadingGroup *next;
|
||||
|
||||
GPUShader *shader; /* Shader to bind */
|
||||
DRWInterface *interface; /* Uniforms pointers */
|
||||
DRWInterface interface; /* Uniforms pointers */
|
||||
|
||||
/* DRWCall or DRWCallDynamic depending of type */
|
||||
#ifdef USE_MEM_ITER
|
||||
BLI_memiter *calls;
|
||||
#else
|
||||
ListBase calls;
|
||||
#endif
|
||||
void *calls;
|
||||
void *calls_first; /* To be able to traverse the list in the order of addition */
|
||||
|
||||
DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */
|
||||
DRWState state_extra_disable; /* State changes for this batch only (and'd with the pass's state) */
|
||||
|
@ -322,6 +316,15 @@ enum {
|
|||
|
||||
/** Render State: No persistent data between draw calls. */
|
||||
static struct DRWGlobalState {
|
||||
/* Cache generation */
|
||||
ViewportMemoryPool *vmempool;
|
||||
DRWUniform *last_uniform;
|
||||
DRWAttrib *last_attrib;
|
||||
DRWCall *last_call;
|
||||
DRWCallGenerate *last_callgenerate;
|
||||
DRWCallDynamic *last_calldynamic;
|
||||
DRWShadingGroup *last_shgroup;
|
||||
|
||||
/* Rendering state */
|
||||
GPUShader *shader;
|
||||
|
||||
|
@ -652,10 +655,8 @@ void DRW_shader_free(GPUShader *shader)
|
|||
/** \name Interface (DRW_interface)
|
||||
* \{ */
|
||||
|
||||
static DRWInterface *DRW_interface_create(GPUShader *shader)
|
||||
static void DRW_interface_create(DRWInterface *interface, GPUShader *shader)
|
||||
{
|
||||
DRWInterface *interface = MEM_mallocN(sizeof(DRWInterface), "DRWInterface");
|
||||
|
||||
interface->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL);
|
||||
interface->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV);
|
||||
interface->modelview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW);
|
||||
|
@ -681,21 +682,11 @@ static DRWInterface *DRW_interface_create(GPUShader *shader)
|
|||
|
||||
memset(&interface->vbo_format, 0, sizeof(Gwn_VertFormat));
|
||||
|
||||
BLI_listbase_clear(&interface->uniforms);
|
||||
BLI_listbase_clear(&interface->attribs);
|
||||
|
||||
return interface;
|
||||
interface->uniforms = NULL;
|
||||
interface->attribs = NULL;
|
||||
interface->attribs_first = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_GPU_SELECT
|
||||
static DRWInterface *DRW_interface_duplicate(DRWInterface *interface_src)
|
||||
{
|
||||
DRWInterface *interface_dst = MEM_dupallocN(interface_src);
|
||||
BLI_duplicatelist(&interface_dst->uniforms, &interface_src->uniforms);
|
||||
BLI_duplicatelist(&interface_dst->attribs, &interface_src->attribs);
|
||||
return interface_dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
|
||||
DRWUniformType type, const void *value, int length, int arraysize)
|
||||
|
@ -716,7 +707,7 @@ static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
|
|||
return;
|
||||
}
|
||||
|
||||
DRWUniform *uni = MEM_mallocN(sizeof(DRWUniform), "DRWUniform");
|
||||
DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms);
|
||||
|
||||
BLI_assert(arraysize > 0);
|
||||
|
||||
|
@ -726,12 +717,14 @@ static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
|
|||
uni->length = length;
|
||||
uni->arraysize = arraysize;
|
||||
|
||||
BLI_addtail(&shgroup->interface->uniforms, uni);
|
||||
/* Prepend */
|
||||
uni->next = shgroup->interface.uniforms;
|
||||
shgroup->interface.uniforms = uni;
|
||||
}
|
||||
|
||||
static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType type, int size, bool dummy)
|
||||
{
|
||||
DRWAttrib *attrib = MEM_mallocN(sizeof(DRWAttrib), "DRWAttrib");
|
||||
DRWAttrib *attrib = BLI_mempool_alloc(DST.vmempool->attribs);
|
||||
GLuint program = GPU_shader_get_program(shgroup->shader);
|
||||
|
||||
attrib->location = glGetAttribLocation(program, name);
|
||||
|
@ -755,9 +748,19 @@ static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRW
|
|||
BLI_assert(BLI_strnlen(name, 32) < 32);
|
||||
BLI_strncpy(attrib->name, name, 32);
|
||||
|
||||
shgroup->interface->attribs_count += 1;
|
||||
shgroup->interface.attribs_count += 1;
|
||||
BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
|
||||
|
||||
BLI_addtail(&shgroup->interface->attribs, attrib);
|
||||
/* Prepend */
|
||||
if (shgroup->interface.attribs == NULL) {
|
||||
shgroup->interface.attribs = attrib;
|
||||
shgroup->interface.attribs_first = attrib;
|
||||
}
|
||||
else {
|
||||
shgroup->interface.attribs->prev = attrib;
|
||||
shgroup->interface.attribs = attrib;
|
||||
}
|
||||
attrib->prev = NULL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -770,23 +773,30 @@ static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRW
|
|||
|
||||
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
|
||||
{
|
||||
DRWShadingGroup *shgroup = MEM_mallocN(sizeof(DRWShadingGroup), "DRWShadingGroup");
|
||||
BLI_addtail(&pass->shgroups, shgroup);
|
||||
DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
|
||||
|
||||
/* Append */
|
||||
if (pass->shgroups != NULL) {
|
||||
pass->shgroups_last->next = shgroup;
|
||||
}
|
||||
else {
|
||||
pass->shgroups = shgroup;
|
||||
}
|
||||
pass->shgroups_last = shgroup;
|
||||
shgroup->next = NULL;
|
||||
|
||||
DRW_interface_create(&shgroup->interface, shader);
|
||||
|
||||
shgroup->type = DRW_SHG_NORMAL;
|
||||
shgroup->shader = shader;
|
||||
shgroup->interface = DRW_interface_create(shader);
|
||||
shgroup->state_extra = 0;
|
||||
shgroup->state_extra_disable = ~0x0;
|
||||
shgroup->batch_geom = NULL;
|
||||
shgroup->instance_geom = NULL;
|
||||
shgroup->instance_data = NULL;
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
shgroup->calls = BLI_memiter_create(BLI_MEMITER_DEFAULT_SIZE);
|
||||
#else
|
||||
BLI_listbase_clear(&shgroup->calls);
|
||||
#endif
|
||||
shgroup->calls = NULL;
|
||||
shgroup->calls_first = NULL;
|
||||
|
||||
#ifdef USE_GPU_SELECT
|
||||
shgroup->pass_parent = pass;
|
||||
|
@ -885,7 +895,7 @@ DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(
|
|||
|
||||
if (shgroup) {
|
||||
shgroup->type = DRW_SHG_TRIANGLE_BATCH;
|
||||
shgroup->interface->instance_count = size * 3;
|
||||
shgroup->interface.instance_count = size * 3;
|
||||
DRW_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
|
||||
}
|
||||
|
||||
|
@ -930,7 +940,7 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR
|
|||
DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
|
||||
|
||||
shgroup->type = DRW_SHG_TRIANGLE_BATCH;
|
||||
shgroup->interface->instance_count = size * 3;
|
||||
shgroup->interface.instance_count = size * 3;
|
||||
DRW_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
|
||||
|
||||
return shgroup;
|
||||
|
@ -938,46 +948,43 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR
|
|||
|
||||
void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
|
||||
{
|
||||
#ifdef USE_MEM_ITER
|
||||
BLI_memiter_destroy(shgroup->calls);
|
||||
#else
|
||||
BLI_freelistN(&shgroup->calls);
|
||||
#endif
|
||||
|
||||
BLI_freelistN(&shgroup->interface->uniforms);
|
||||
BLI_freelistN(&shgroup->interface->attribs);
|
||||
|
||||
if (shgroup->interface->instance_vbo &&
|
||||
(shgroup->interface->instance_batch == 0))
|
||||
if (shgroup->interface.instance_vbo &&
|
||||
(shgroup->interface.instance_batch == 0))
|
||||
{
|
||||
glDeleteBuffers(1, &shgroup->interface->instance_vbo);
|
||||
glDeleteBuffers(1, &shgroup->interface.instance_vbo);
|
||||
}
|
||||
|
||||
MEM_freeN(shgroup->interface);
|
||||
|
||||
GWN_BATCH_DISCARD_SAFE(shgroup->batch_geom);
|
||||
}
|
||||
|
||||
void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances)
|
||||
{
|
||||
BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
|
||||
BLI_assert(shgroup->interface->instance_batch == NULL);
|
||||
BLI_assert(shgroup->interface.instance_batch == NULL);
|
||||
|
||||
shgroup->interface->instance_batch = instances;
|
||||
shgroup->interface.instance_batch = instances;
|
||||
}
|
||||
|
||||
#define CALL_PREPEND(shgroup, call) { \
|
||||
if (shgroup->calls == NULL) { \
|
||||
shgroup->calls = call; \
|
||||
shgroup->calls_first = call; \
|
||||
} \
|
||||
else { \
|
||||
((typeof(call))shgroup->calls)->head.prev = call; \
|
||||
shgroup->calls = call; \
|
||||
} \
|
||||
call->head.prev = NULL; \
|
||||
} ((void)0)
|
||||
|
||||
|
||||
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
|
||||
{
|
||||
BLI_assert(geom != NULL);
|
||||
|
||||
DRWCall *call;
|
||||
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
call = BLI_memiter_calloc(shgroup->calls, sizeof(DRWCall));
|
||||
#else
|
||||
call = MEM_callocN(sizeof(DRWCall), "DRWCall");
|
||||
BLI_addtail(&shgroup->calls, call);
|
||||
#endif
|
||||
CALL_PREPEND(shgroup, call);
|
||||
|
||||
call->head.type = DRW_CALL_SINGLE;
|
||||
#ifdef USE_GPU_SELECT
|
||||
|
@ -989,20 +996,16 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm
|
|||
}
|
||||
|
||||
call->geometry = geom;
|
||||
call->ob_data = NULL;
|
||||
}
|
||||
|
||||
void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob)
|
||||
{
|
||||
BLI_assert(geom != NULL);
|
||||
|
||||
DRWCall *call;
|
||||
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
call = BLI_memiter_calloc(shgroup->calls, sizeof(DRWCall));
|
||||
#else
|
||||
call = MEM_callocN(sizeof(DRWCall), "DRWCall");
|
||||
BLI_addtail(&shgroup->calls, call);
|
||||
#endif
|
||||
CALL_PREPEND(shgroup, call);
|
||||
|
||||
call->head.type = DRW_CALL_SINGLE;
|
||||
#ifdef USE_GPU_SELECT
|
||||
|
@ -1021,14 +1024,9 @@ void DRW_shgroup_call_generate_add(
|
|||
{
|
||||
BLI_assert(geometry_fn != NULL);
|
||||
|
||||
DRWCallGenerate *call;
|
||||
DRWCallGenerate *call = BLI_mempool_alloc(DST.vmempool->calls_generate);
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
call = BLI_memiter_calloc(shgroup->calls, sizeof(DRWCallGenerate));
|
||||
#else
|
||||
call = MEM_callocN(sizeof(DRWCallGenerate), "DRWCallGenerate");
|
||||
BLI_addtail(&shgroup->calls, call);
|
||||
#endif
|
||||
CALL_PREPEND(shgroup, call);
|
||||
|
||||
call->head.type = DRW_CALL_GENERATE;
|
||||
#ifdef USE_GPU_SELECT
|
||||
|
@ -1065,38 +1063,35 @@ void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, Object *ob, float (*o
|
|||
|
||||
void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], unsigned int attr_len)
|
||||
{
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
DRWInterface *interface = &shgroup->interface;
|
||||
|
||||
#ifdef USE_GPU_SELECT
|
||||
if ((G.f & G_PICKSEL) && (interface->instance_count > 0)) {
|
||||
shgroup = MEM_dupallocN(shgroup);
|
||||
DRWShadingGroup *original_shgroup = shgroup;
|
||||
shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
|
||||
memcpy(shgroup, original_shgroup, sizeof(DRWShadingGroup));
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
shgroup->calls = BLI_memiter_create(BLI_MEMITER_DEFAULT_SIZE);
|
||||
#else
|
||||
BLI_listbase_clear(&shgroup->calls);
|
||||
#endif
|
||||
shgroup->calls = NULL;
|
||||
shgroup->calls_first = NULL;
|
||||
|
||||
shgroup->interface = interface = DRW_interface_duplicate(interface);
|
||||
interface = &shgroup->interface;
|
||||
interface->instance_count = 0;
|
||||
|
||||
BLI_addtail(&shgroup->pass_parent->shgroups, shgroup);
|
||||
/* Append */
|
||||
if (shgroup->pass_parent->shgroups != NULL) {
|
||||
shgroup->pass_parent->shgroups_last->next = shgroup;
|
||||
}
|
||||
else {
|
||||
shgroup->pass_parent->shgroups = shgroup;
|
||||
}
|
||||
shgroup->pass_parent->shgroups_last = shgroup;
|
||||
shgroup->next = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int data_size = sizeof(void *) * interface->attribs_count;
|
||||
int size = sizeof(DRWCallDynamic) + data_size;
|
||||
DRWCallDynamic *call = BLI_mempool_alloc(DST.vmempool->calls_dynamic);
|
||||
|
||||
DRWCallDynamic *call;
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
call = BLI_memiter_alloc(shgroup->calls, size);
|
||||
#else
|
||||
call = MEM_mallocN(size, "DRWCallDynamic");
|
||||
BLI_addtail(&shgroup->calls, call);
|
||||
#endif
|
||||
|
||||
memset(call, 0x0, sizeof(DRWCallDynamic));
|
||||
CALL_PREPEND(shgroup, call);
|
||||
|
||||
BLI_assert(attr_len == interface->attribs_count);
|
||||
UNUSED_VARS_NDEBUG(attr_len);
|
||||
|
@ -1106,8 +1101,8 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
|
|||
call->head.select_id = g_DRW_select_id;
|
||||
#endif
|
||||
|
||||
if (data_size != 0) {
|
||||
memcpy((void *)call->data, attr, data_size);
|
||||
if (interface->attribs_count != 0) {
|
||||
memcpy((void *)call->data, attr, sizeof(void *) * interface->attribs_count);
|
||||
}
|
||||
|
||||
interface->instance_count += 1;
|
||||
|
@ -1116,7 +1111,7 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
|
|||
/* Used for instancing with no attributes */
|
||||
void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count)
|
||||
{
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
DRWInterface *interface = &shgroup->interface;
|
||||
|
||||
BLI_assert(interface->attribs_count == 0);
|
||||
|
||||
|
@ -1220,7 +1215,7 @@ void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const
|
|||
/* Creates a VBO containing OGL primitives for all DRWCallDynamic */
|
||||
static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
|
||||
{
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
DRWInterface *interface = &shgroup->interface;
|
||||
int nbr = interface->instance_count;
|
||||
|
||||
Gwn_PrimType type = (shgroup->type == DRW_SHG_POINT_BATCH) ? GWN_PRIM_POINTS :
|
||||
|
@ -1231,7 +1226,7 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
|
|||
|
||||
/* Upload Data */
|
||||
if (interface->vbo_format.attrib_ct == 0) {
|
||||
for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next) {
|
||||
for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev) {
|
||||
BLI_assert(attrib->size <= 4); /* matrices have no place here for now */
|
||||
if (attrib->type == DRW_ATTRIB_FLOAT) {
|
||||
attrib->format_id = GWN_vertformat_attr_add(
|
||||
|
@ -1251,16 +1246,9 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
|
|||
GWN_vertbuf_data_alloc(vbo, nbr);
|
||||
|
||||
int j = 0;
|
||||
#ifdef USE_MEM_ITER
|
||||
BLI_memiter_handle calls_iter;
|
||||
BLI_memiter_iter_init(shgroup->calls, &calls_iter);
|
||||
for (DRWCallDynamic *call; (call = BLI_memiter_iter_step(&calls_iter)); j++)
|
||||
#else
|
||||
for (DRWCallDynamic *call = shgroup->calls.first; call; call = call->head.next, j++)
|
||||
#endif
|
||||
{
|
||||
for (DRWCallDynamic *call = shgroup->calls_first; call; call = call->head.prev, j++) {
|
||||
int i = 0;
|
||||
for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next, i++) {
|
||||
for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev, i++) {
|
||||
GWN_vertbuf_attr_set(vbo, attrib->format_id, j, call->data[i]);
|
||||
}
|
||||
}
|
||||
|
@ -1276,7 +1264,7 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
|
|||
{
|
||||
int i = 0;
|
||||
int offset = 0;
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
DRWInterface *interface = &shgroup->interface;
|
||||
int buffer_size = 0;
|
||||
|
||||
if (interface->instance_batch != NULL) {
|
||||
|
@ -1294,7 +1282,7 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
|
|||
|
||||
/* only once */
|
||||
if (interface->attribs_stride == 0) {
|
||||
for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next, i++) {
|
||||
for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev, i++) {
|
||||
BLI_assert(attrib->type == DRW_ATTRIB_FLOAT); /* Only float for now */
|
||||
interface->attribs_stride += attrib->size;
|
||||
interface->attribs_size[i] = attrib->size;
|
||||
|
@ -1306,14 +1294,7 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
|
|||
buffer_size = sizeof(float) * interface->attribs_stride * interface->instance_count;
|
||||
float *data = MEM_mallocN(buffer_size, "Instance VBO data");
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
BLI_memiter_handle calls_iter;
|
||||
BLI_memiter_iter_init(shgroup->calls, &calls_iter);
|
||||
for (DRWCallDynamic *call; (call = BLI_memiter_iter_step(&calls_iter)); )
|
||||
#else
|
||||
for (DRWCallDynamic *call = shgroup->calls.first; call; call = call->head.next)
|
||||
#endif
|
||||
{
|
||||
for (DRWCallDynamic *call = shgroup->calls_first; call; call = call->head.prev) {
|
||||
for (int j = 0; j < interface->attribs_count; ++j) {
|
||||
memcpy(data + offset, call->data[j], sizeof(float) * interface->attribs_size[j]);
|
||||
offset += interface->attribs_size[j];
|
||||
|
@ -1335,7 +1316,7 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
|
|||
|
||||
static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
|
||||
{
|
||||
if ((shgroup->interface->instance_vbo || shgroup->batch_geom) &&
|
||||
if ((shgroup->interface.instance_vbo || shgroup->batch_geom) &&
|
||||
(G.debug_value == 667))
|
||||
{
|
||||
return;
|
||||
|
@ -1359,27 +1340,29 @@ static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
|
|||
|
||||
DRWPass *DRW_pass_create(const char *name, DRWState state)
|
||||
{
|
||||
DRWPass *pass = MEM_callocN(sizeof(DRWPass), name);
|
||||
DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes);
|
||||
pass->state = state;
|
||||
BLI_strncpy(pass->name, name, MAX_PASS_NAME);
|
||||
|
||||
BLI_listbase_clear(&pass->shgroups);
|
||||
pass->shgroups = NULL;
|
||||
pass->shgroups_last = NULL;
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
void DRW_pass_free(DRWPass *pass)
|
||||
{
|
||||
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
|
||||
for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
|
||||
DRW_shgroup_free(shgroup);
|
||||
}
|
||||
|
||||
BLI_freelistN(&pass->shgroups);
|
||||
pass->shgroups = NULL;
|
||||
pass->shgroups_last = NULL;
|
||||
}
|
||||
|
||||
void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData)
|
||||
{
|
||||
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
|
||||
for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
|
||||
callback(userData, shgroup);
|
||||
}
|
||||
}
|
||||
|
@ -1398,13 +1381,8 @@ static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
|
|||
const DRWCall *call_a;
|
||||
const DRWCall *call_b;
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
call_a = BLI_memiter_elem_first(shgrp_a->calls);
|
||||
call_b = BLI_memiter_elem_first(shgrp_b->calls);
|
||||
#else
|
||||
call_a = shgrp_a->calls.first;
|
||||
call_b = shgrp_b->calls.first;
|
||||
#endif
|
||||
call_a = shgrp_a->calls_first;
|
||||
call_b = shgrp_b->calls_first;
|
||||
|
||||
if (call_a == NULL) return -1;
|
||||
if (call_b == NULL) return -1;
|
||||
|
@ -1429,6 +1407,18 @@ static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------ Shading group sorting --------------------- */
|
||||
|
||||
#define SORT_IMPL_LINKTYPE DRWShadingGroup
|
||||
|
||||
#define SORT_IMPL_USE_THUNK
|
||||
#define SORT_IMPL_FUNC shgroup_sort_fn_r
|
||||
#include "../../blenlib/intern/list_sort_impl.h"
|
||||
#undef SORT_IMPL_FUNC
|
||||
#undef SORT_IMPL_USE_THUNK
|
||||
|
||||
#undef SORT_IMPL_LINKTYPE
|
||||
|
||||
/**
|
||||
* Sort Shading groups by decreasing Z of their first draw call.
|
||||
* This is usefull for order dependant effect such as transparency.
|
||||
|
@ -1442,7 +1432,17 @@ void DRW_pass_sort_shgroup_z(DRWPass *pass)
|
|||
? viewport_matrix_override.mat[DRW_MAT_VIEWINV] : rv3d->viewinv;
|
||||
|
||||
ZSortData zsortdata = {viewinv[2], viewinv[3]};
|
||||
BLI_listbase_sort_r(&pass->shgroups, pass_shgroup_dist_sort, &zsortdata);
|
||||
|
||||
if (pass->shgroups && pass->shgroups->next) {
|
||||
pass->shgroups = shgroup_sort_fn_r(pass->shgroups, pass_shgroup_dist_sort, &zsortdata);
|
||||
|
||||
/* Find the next last */
|
||||
DRWShadingGroup *last = pass->shgroups;
|
||||
while ((last = last->next)) {
|
||||
/* Do nothing */
|
||||
};
|
||||
pass->shgroups_last = last;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1722,7 +1722,7 @@ static void draw_geometry_prepare(
|
|||
DRWShadingGroup *shgroup, const float (*obmat)[4], const float *texcoloc, const float *texcosize)
|
||||
{
|
||||
RegionView3D *rv3d = DST.draw_ctx.rv3d;
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
DRWInterface *interface = &shgroup->interface;
|
||||
|
||||
float mvp[4][4], mv[4][4], mi[4][4], mvi[4][4], pi[4][4], n[3][3], wn[3][3];
|
||||
float orcofacs[2][3] = {{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
|
||||
|
@ -1827,7 +1827,7 @@ static void draw_geometry_prepare(
|
|||
|
||||
static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
|
||||
{
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
DRWInterface *interface = &shgroup->interface;
|
||||
/* step 2 : bind vertex array & draw */
|
||||
GWN_batch_program_set(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
|
||||
if (interface->instance_batch) {
|
||||
|
@ -1918,9 +1918,8 @@ static void release_ubo_slots(void)
|
|||
static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
|
||||
{
|
||||
BLI_assert(shgroup->shader);
|
||||
BLI_assert(shgroup->interface);
|
||||
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
DRWInterface *interface = &shgroup->interface;
|
||||
GPUTexture *tex;
|
||||
GPUUniformBuffer *ubo;
|
||||
int val;
|
||||
|
@ -1946,7 +1945,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
|
|||
|
||||
/* Binding Uniform */
|
||||
/* Don't check anything, Interface should already contain the least uniform as possible */
|
||||
for (DRWUniform *uni = interface->uniforms.first; uni; uni = uni->next) {
|
||||
for (DRWUniform *uni = interface->uniforms; uni; uni = uni->next) {
|
||||
switch (uni->type) {
|
||||
case DRW_UNIFORM_SHORT_TO_INT:
|
||||
val = (int)*((short *)uni->value);
|
||||
|
@ -1999,26 +1998,15 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
|
|||
GPU_select_load_id((_call)->head.select_id); \
|
||||
} ((void)0)
|
||||
|
||||
#ifdef USE_MEM_ITER
|
||||
# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_call_ls) \
|
||||
if (G.f & G_PICKSEL) { \
|
||||
DRWCall *call_test = BLI_memiter_elem_first(*(_call_ls)); \
|
||||
if (call_test != NULL) { \
|
||||
BLI_assert(BLI_memiter_count(*(_call_ls)) == 1); \
|
||||
GPU_select_load_id(call_test->head.select_id); \
|
||||
} \
|
||||
# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_call_last, _call_first) \
|
||||
if ((G.f & G_PICKSEL) && _call_first) { \
|
||||
BLI_assert(_call_first && (_call_first == _call_last)); \
|
||||
GPU_select_load_id(((DRWCall *)_call_first)->head.select_id); \
|
||||
} ((void)0)
|
||||
#else
|
||||
# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_call_ls) \
|
||||
if ((G.f & G_PICKSEL) && (_call_ls)->first) { \
|
||||
BLI_assert(BLI_listbase_is_single(_call_ls)); \
|
||||
GPU_select_load_id(((DRWCall *)(_call_ls)->first)->head.select_id); \
|
||||
} ((void)0)
|
||||
#endif
|
||||
|
||||
#else
|
||||
# define GPU_SELECT_LOAD_IF_PICKSEL(call)
|
||||
# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(call)
|
||||
# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(call, _call_first)
|
||||
#endif
|
||||
|
||||
/* Rendering Calls */
|
||||
|
@ -2030,25 +2018,19 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
|
|||
if (shgroup->type == DRW_SHG_INSTANCE &&
|
||||
(interface->instance_count > 0 || interface->instance_batch != NULL))
|
||||
{
|
||||
GPU_SELECT_LOAD_IF_PICKSEL_LIST(&shgroup->calls);
|
||||
GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup->calls, shgroup->calls_first);
|
||||
draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data);
|
||||
}
|
||||
else {
|
||||
/* Some dynamic batch can have no geom (no call to aggregate) */
|
||||
if (shgroup->batch_geom) {
|
||||
GPU_SELECT_LOAD_IF_PICKSEL_LIST(&shgroup->calls);
|
||||
GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup->calls, shgroup->calls_first);
|
||||
draw_geometry(shgroup, shgroup->batch_geom, obmat, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef USE_MEM_ITER
|
||||
BLI_memiter_handle calls_iter;
|
||||
BLI_memiter_iter_init(shgroup->calls, &calls_iter);
|
||||
for (DRWCall *call; (call = BLI_memiter_iter_step(&calls_iter)); )
|
||||
#else
|
||||
for (DRWCall *call = shgroup->calls.first; call; call = call->head.next)
|
||||
#endif
|
||||
for (DRWCall *call = shgroup->calls_first; call; call = call->head.prev)
|
||||
{
|
||||
bool neg_scale = is_negative_m4(call->obmat);
|
||||
|
||||
|
@ -2115,7 +2097,7 @@ static void DRW_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWSha
|
|||
|
||||
void DRW_draw_pass(DRWPass *pass)
|
||||
{
|
||||
DRW_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
|
||||
DRW_draw_pass_ex(pass, pass->shgroups, pass->shgroups_last);
|
||||
}
|
||||
|
||||
/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
|
||||
|
@ -2537,6 +2519,22 @@ const float *DRW_viewport_pixelsize_get(void)
|
|||
return &DST.pixsize;
|
||||
}
|
||||
|
||||
static void DRW_viewport_cache_resize(void)
|
||||
{
|
||||
/* Release the memiter before clearing the mempools that references them */
|
||||
GPU_viewport_cache_release(DST.viewport);
|
||||
|
||||
if (DST.vmempool != NULL) {
|
||||
BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_count(DST.vmempool->calls));
|
||||
BLI_mempool_clear_ex(DST.vmempool->calls_generate, BLI_mempool_count(DST.vmempool->calls_generate));
|
||||
BLI_mempool_clear_ex(DST.vmempool->calls_dynamic, BLI_mempool_count(DST.vmempool->calls_dynamic));
|
||||
BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_count(DST.vmempool->shgroups));
|
||||
BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_count(DST.vmempool->uniforms));
|
||||
BLI_mempool_clear_ex(DST.vmempool->attribs, BLI_mempool_count(DST.vmempool->attribs));
|
||||
BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_count(DST.vmempool->passes));
|
||||
}
|
||||
}
|
||||
|
||||
/* It also stores viewport variable to an immutable place: DST
|
||||
* This is because a cache uniform only store reference
|
||||
* to its value. And we don't want to invalidate the cache
|
||||
|
@ -2554,12 +2552,37 @@ static void DRW_viewport_var_init(void)
|
|||
|
||||
DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(DST.viewport);
|
||||
DST.default_framebuffer = fbl->default_fb;
|
||||
|
||||
DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
|
||||
|
||||
if (DST.vmempool->calls == NULL) {
|
||||
DST.vmempool->calls = BLI_mempool_create(sizeof(DRWCall), 0, 512, 0);
|
||||
}
|
||||
if (DST.vmempool->calls_generate == NULL) {
|
||||
DST.vmempool->calls_generate = BLI_mempool_create(sizeof(DRWCallGenerate), 0, 512, 0);
|
||||
}
|
||||
if (DST.vmempool->calls_dynamic == NULL) {
|
||||
DST.vmempool->calls_dynamic = BLI_mempool_create(sizeof(DRWCallDynamic), 0, 512, 0);
|
||||
}
|
||||
if (DST.vmempool->shgroups == NULL) {
|
||||
DST.vmempool->shgroups = BLI_mempool_create(sizeof(DRWShadingGroup), 0, 256, 0);
|
||||
}
|
||||
if (DST.vmempool->uniforms == NULL) {
|
||||
DST.vmempool->uniforms = BLI_mempool_create(sizeof(DRWUniform), 0, 512, 0);
|
||||
}
|
||||
if (DST.vmempool->attribs == NULL) {
|
||||
DST.vmempool->attribs = BLI_mempool_create(sizeof(DRWAttrib), 0, 256, 0);
|
||||
}
|
||||
if (DST.vmempool->passes == NULL) {
|
||||
DST.vmempool->passes = BLI_mempool_create(sizeof(DRWPass), 0, 64, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DST.size[0] = 0;
|
||||
DST.size[1] = 0;
|
||||
|
||||
DST.default_framebuffer = NULL;
|
||||
DST.vmempool = NULL;
|
||||
}
|
||||
/* Refresh DST.screenvecs */
|
||||
copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
|
||||
|
@ -3258,12 +3281,11 @@ void DRW_draw_render_loop_ex(
|
|||
|
||||
DST.draw_ctx.evil_C = evil_C;
|
||||
|
||||
bool cache_is_dirty;
|
||||
DST.viewport = rv3d->viewport;
|
||||
v3d->zbuf = true;
|
||||
|
||||
/* Setup viewport */
|
||||
cache_is_dirty = GPU_viewport_cache_validate(DST.viewport, DRW_engines_get_hash());
|
||||
GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash());
|
||||
|
||||
DST.draw_ctx = (DRWContextState){
|
||||
ar, rv3d, v3d, scene, scene_layer, OBACT_NEW(scene_layer), engine,
|
||||
|
@ -3286,7 +3308,7 @@ void DRW_draw_render_loop_ex(
|
|||
/* TODO : tag to refresh by the deps graph */
|
||||
/* ideally only refresh when objects are added/removed */
|
||||
/* or render properties / materials change */
|
||||
if (cache_is_dirty) {
|
||||
{
|
||||
PROFILE_START(stime);
|
||||
DRW_engines_cache_init();
|
||||
|
||||
|
@ -3366,6 +3388,8 @@ void DRW_draw_render_loop_ex(
|
|||
DRW_state_reset();
|
||||
DRW_engines_disable();
|
||||
|
||||
DRW_viewport_cache_resize();
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Avoid accidental reuse. */
|
||||
memset(&DST, 0xFF, sizeof(DST));
|
||||
|
|
|
@ -43,6 +43,17 @@
|
|||
|
||||
typedef struct GPUViewport GPUViewport;
|
||||
|
||||
/* Contains memory pools informations */
|
||||
typedef struct ViewportMemoryPool {
|
||||
struct BLI_mempool *calls;
|
||||
struct BLI_mempool *calls_generate;
|
||||
struct BLI_mempool *calls_dynamic;
|
||||
struct BLI_mempool *shgroups;
|
||||
struct BLI_mempool *uniforms;
|
||||
struct BLI_mempool *attribs;
|
||||
struct BLI_mempool *passes;
|
||||
} ViewportMemoryPool;
|
||||
|
||||
/* All FramebufferLists are just the same pointers with different names */
|
||||
typedef struct FramebufferList {
|
||||
struct GPUFrameBuffer *framebuffers[0];
|
||||
|
@ -94,6 +105,8 @@ void GPU_viewport_free(GPUViewport *viewport);
|
|||
GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
|
||||
void GPU_viewport_clear_from_offscreen(GPUViewport *viewport);
|
||||
|
||||
ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport);
|
||||
|
||||
void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type);
|
||||
void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type);
|
||||
void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport);
|
||||
|
@ -107,7 +120,8 @@ bool GPU_viewport_do_update(GPUViewport *viewport);
|
|||
/* Texture pool */
|
||||
GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int channels, int format);
|
||||
|
||||
bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash);
|
||||
bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash);
|
||||
void GPU_viewport_cache_release(GPUViewport *viewport);
|
||||
|
||||
/* debug */
|
||||
bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_mempool.h"
|
||||
|
||||
#include "DNA_vec_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
@ -82,6 +83,8 @@ struct GPUViewport {
|
|||
DefaultFramebufferList *fbl;
|
||||
DefaultTextureList *txl;
|
||||
|
||||
ViewportMemoryPool vmempool; /* Used for rendering data structure. */
|
||||
|
||||
ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */
|
||||
};
|
||||
|
||||
|
@ -202,6 +205,11 @@ void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport)
|
||||
{
|
||||
return &viewport->vmempool;
|
||||
}
|
||||
|
||||
void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport)
|
||||
{
|
||||
return viewport->fbl;
|
||||
|
@ -296,21 +304,10 @@ static void gpu_viewport_texture_pool_free(GPUViewport *viewport)
|
|||
BLI_freelistN(&viewport->tex_pool);
|
||||
}
|
||||
|
||||
bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash)
|
||||
bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash)
|
||||
{
|
||||
bool dirty = false;
|
||||
|
||||
/* TODO for testing only, we need proper cache invalidation */
|
||||
if (ELEM(G.debug_value, 666, 667) == false) {
|
||||
for (LinkData *link = viewport->data.first; link; link = link->next) {
|
||||
ViewportEngineData *data = link->data;
|
||||
int psl_len;
|
||||
DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL);
|
||||
gpu_viewport_passes_free(data->psl, psl_len);
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (viewport->data_hash != hash) {
|
||||
gpu_viewport_engines_data_free(viewport);
|
||||
dirty = true;
|
||||
|
@ -321,6 +318,16 @@ bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash)
|
|||
return dirty;
|
||||
}
|
||||
|
||||
void GPU_viewport_cache_release(GPUViewport *viewport)
|
||||
{
|
||||
for (LinkData *link = viewport->data.first; link; link = link->next) {
|
||||
ViewportEngineData *data = link->data;
|
||||
int psl_len;
|
||||
DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL);
|
||||
gpu_viewport_passes_free(data->psl, psl_len);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
|
||||
{
|
||||
DefaultFramebufferList *dfbl = viewport->fbl;
|
||||
|
@ -551,7 +558,6 @@ static void gpu_viewport_passes_free(PassList *psl, int psl_len)
|
|||
struct DRWPass *pass = psl->passes[i];
|
||||
if (pass) {
|
||||
DRW_pass_free(pass);
|
||||
MEM_freeN(pass);
|
||||
psl->passes[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -570,6 +576,28 @@ void GPU_viewport_free(GPUViewport *viewport)
|
|||
MEM_freeN(viewport->fbl);
|
||||
MEM_freeN(viewport->txl);
|
||||
|
||||
if (viewport->vmempool.calls != NULL) {
|
||||
BLI_mempool_destroy(viewport->vmempool.calls);
|
||||
}
|
||||
if (viewport->vmempool.calls_generate != NULL) {
|
||||
BLI_mempool_destroy(viewport->vmempool.calls_generate);
|
||||
}
|
||||
if (viewport->vmempool.calls_dynamic != NULL) {
|
||||
BLI_mempool_destroy(viewport->vmempool.calls_dynamic);
|
||||
}
|
||||
if (viewport->vmempool.shgroups != NULL) {
|
||||
BLI_mempool_destroy(viewport->vmempool.shgroups);
|
||||
}
|
||||
if (viewport->vmempool.uniforms != NULL) {
|
||||
BLI_mempool_destroy(viewport->vmempool.uniforms);
|
||||
}
|
||||
if (viewport->vmempool.attribs != NULL) {
|
||||
BLI_mempool_destroy(viewport->vmempool.attribs);
|
||||
}
|
||||
if (viewport->vmempool.passes != NULL) {
|
||||
BLI_mempool_destroy(viewport->vmempool.passes);
|
||||
}
|
||||
|
||||
GPU_viewport_debug_depth_free(viewport);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue