star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

commit 71014d55ed7358feeb153a39196cc5fba14abafa
parent e72f4b9c0e670b0b9e5bdae9dc11528098534245
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 26 Mar 2015 16:01:30 +0100

Ref count the internal mesh representation

Diffstat:
Msrc/s3d_instance.c | 2+-
Msrc/s3d_mesh.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/s3d_mesh.h | 17+++++++++++++----
Msrc/s3d_scene.c | 45++++++++++++++++++++-------------------------
Msrc/s3d_shape.c | 38+++++++++++++++++++++++++++-----------
Msrc/s3d_shape_c.h | 2+-
6 files changed, 118 insertions(+), 50 deletions(-)

diff --git a/src/s3d_instance.c b/src/s3d_instance.c @@ -41,7 +41,7 @@ /******************************************************************************* * Helper functions ******************************************************************************/ -void +static void instance_release(ref_T* ref) { struct instance* inst; diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c @@ -31,6 +31,7 @@ * knowledge of the CeCILL license and that you accept its terms. */ #include "s3d_c.h" +#include "s3d_device_c.h" #include "s3d_mesh.h" /******************************************************************************* @@ -70,7 +71,7 @@ mesh_setup_indices } /* Allocate the new index buffer */ - res = index_buffer_create(mesh->allocator, &mesh->indices); + res = index_buffer_create(mesh->dev->allocator, &mesh->indices); if(res != RES_OK) FATAL("Unsufficient memory\n"); res = darray_u32_resize(&mesh->indices->data, ntris * 3/*# triangle ids*/); if(res != RES_OK) FATAL("Unsufficient memory\n"); @@ -123,7 +124,7 @@ mesh_setup_positions } /* Allocate vertex positions */ - res = vertex_buffer_create(mesh->allocator, &mesh->attribs[S3D_POSITION]); + res = vertex_buffer_create(mesh->dev->allocator, &mesh->attribs[S3D_POSITION]); if(res != RES_OK) FATAL("Insufficient memory\n"); res = darray_float_resize(&mesh->attribs[S3D_POSITION]->data, nverts*3); if(res != RES_OK) FATAL("Insufficient memory\n"); @@ -190,7 +191,7 @@ mesh_setup_attribs } /* Allocate the new vertex buffer */ - res = vertex_buffer_create(mesh->allocator, &mesh->attribs[attr->usage]); + res = vertex_buffer_create(mesh->dev->allocator, &mesh->attribs[attr->usage]); if(res != RES_OK) FATAL("Insufficient memory\n"); res = darray_float_resize(&mesh->attribs[attr->usage]->data, nverts * dim); if(res != RES_OK) FATAL("Insufficient memory\n"); @@ -204,16 +205,63 @@ mesh_setup_attribs } } +static void +mesh_release(ref_T* ref) +{ + struct mesh* mesh; + struct s3d_device* dev; + ASSERT(ref); + + mesh = CONTAINER_OF(ref, struct mesh, ref); + mesh_clear(mesh); + dev = mesh->dev; + MEM_FREE(dev->allocator, mesh); + S3D(device_ref_put(dev)); +} + /******************************************************************************* * Local functions ******************************************************************************/ -void -mesh_init(struct mem_allocator* allocator, struct mesh* mesh) +res_T +mesh_create(struct s3d_device* dev, struct mesh** out_mesh) { - ASSERT(allocator && mesh); - memset(mesh, 0, sizeof(struct mesh)); - mesh->allocator = allocator; + struct mesh* mesh = NULL; + res_T res = RES_OK; + ASSERT(dev && out_mesh); + + mesh = (struct mesh*)MEM_CALLOC(dev->allocator, 1, sizeof(struct mesh)); + if(!mesh) { + res = RES_MEM_ERR; + goto error; + } mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; + ref_init(&mesh->ref); + S3D(device_ref_get(dev)); + mesh->dev = dev; + +exit: + *out_mesh = mesh; + return res; +error: + if(!mesh) { + mesh_ref_put(mesh); + mesh = NULL; + } + goto exit; +} + +void +mesh_ref_get(struct mesh* mesh) +{ + ASSERT(mesh); + ref_get(&mesh->ref); +} + +void +mesh_ref_put(struct mesh* mesh) +{ + ASSERT(mesh); + ref_put(&mesh->ref, mesh_release); } void diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h @@ -66,13 +66,22 @@ struct mesh { /* Triangular mesh */ unsigned rtc_geom; /* Embree geometry */ - struct mem_allocator* allocator; + struct s3d_device* dev; + ref_T ref; }; +extern LOCAL_SYM res_T +mesh_create + (struct s3d_device* dev, + struct mesh** mesh); + +extern LOCAL_SYM void +mesh_ref_get + (struct mesh* mesh); + extern LOCAL_SYM void -mesh_init - (struct mem_allocator* allocator, - struct mesh* mesh); +mesh_ref_put + (struct mesh* mesh); extern LOCAL_SYM void mesh_clear diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -131,18 +131,14 @@ scene_setup_shape_mesh if(pmesh) { mesh = *pmesh; } else { - mesh = (struct mesh*)MEM_ALLOC(scn->dev->allocator, sizeof(struct mesh)); - if(!mesh) { - res = RES_MEM_ERR; - goto error; - } - mesh_init(scn->dev->allocator, mesh); + res = mesh_create(scn->dev, &mesh); + if(res != RES_OK) goto error; res = htable_mesh_set(&scn->meshes, &shape, &mesh); if(res != RES_OK) goto error; } /* Discard the shape mesh that is not geometrically valid */ - if(!shape->data.mesh.indices || !shape->data.mesh.attribs[S3D_POSITION]) { + if(!shape->data.mesh->indices || !shape->data.mesh->attribs[S3D_POSITION]) { if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) scene_delete_mesh_rtc_geometry(scn, mesh); mesh_clear(mesh); @@ -150,41 +146,41 @@ scene_setup_shape_mesh } /* Define which Embree geometry buffer must be updated */ - upd_ids = mesh->indices != shape->data.mesh.indices - || ((shape->data.mesh.update_mask & INDEX_BUFFER) != 0); - upd_pos = mesh->attribs[S3D_POSITION] != shape->data.mesh.attribs[S3D_POSITION] - || ((shape->data.mesh.update_mask == VERTEX_BUFFER) != 0); + upd_ids = mesh->indices != shape->data.mesh->indices + || ((shape->data.mesh->update_mask & INDEX_BUFFER) != 0); + upd_pos = mesh->attribs[S3D_POSITION] != shape->data.mesh->attribs[S3D_POSITION] + || ((shape->data.mesh->update_mask == VERTEX_BUFFER) != 0); /* Get a reference onto the shape mesh indices */ - if(mesh->indices != shape->data.mesh.indices) { + if(mesh->indices != shape->data.mesh->indices) { if(mesh->indices) { index_buffer_ref_put(mesh->indices); mesh->indices = NULL; } - ASSERT(shape->data.mesh.indices); - index_buffer_ref_get(shape->data.mesh.indices); - mesh->indices = shape->data.mesh.indices; + ASSERT(shape->data.mesh->indices); + index_buffer_ref_get(shape->data.mesh->indices); + mesh->indices = shape->data.mesh->indices; } /* Get the reference onto the shape mesh attribs */ FOR_EACH(iattr, 0, S3D_ATTRIBS_COUNT__) { - if(mesh->attribs[iattr] == shape->data.mesh.attribs[iattr]) + if(mesh->attribs[iattr] == shape->data.mesh->attribs[iattr]) continue; if(mesh->attribs[iattr]) { vertex_buffer_ref_put(mesh->attribs[iattr]); mesh->attribs[iattr] = NULL; } - if(!shape->data.mesh.attribs[iattr]) + if(!shape->data.mesh->attribs[iattr]) continue; - vertex_buffer_ref_get(shape->data.mesh.attribs[iattr]); - mesh->attribs[iattr] = shape->data.mesh.attribs[iattr]; - mesh->attribs_type[iattr] = shape->data.mesh.attribs_type[iattr]; + vertex_buffer_ref_get(shape->data.mesh->attribs[iattr]); + mesh->attribs[iattr] = shape->data.mesh->attribs[iattr]; + mesh->attribs_type[iattr] = shape->data.mesh->attribs_type[iattr]; } /* The shape mesh was resize => the Embree geometry is no more valid */ - if(shape->data.mesh.resize_mask && mesh->rtc_geom!=RTC_INVALID_GEOMETRY_ID) { + if(shape->data.mesh->resize_mask && mesh->rtc_geom!=RTC_INVALID_GEOMETRY_ID) { scene_delete_mesh_rtc_geometry(scn, mesh); } @@ -208,8 +204,8 @@ scene_setup_shape_mesh } /* Flush the shape mesh states */ - shape->data.mesh.resize_mask = 0; - shape->data.mesh.update_mask = 0; + shape->data.mesh->resize_mask = 0; + shape->data.mesh->update_mask = 0; exit: return res; @@ -286,8 +282,7 @@ scene_detach_shape_mesh(struct s3d_scene* scn, struct s3d_shape* shape) struct mesh* mesh = *pmesh; if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) /* Rm the Embree geometry */ scene_delete_mesh_rtc_geometry(scn, mesh); - mesh_clear(mesh); /* Release the mesh buffers */ - MEM_FREE(scn->dev->allocator, mesh); + mesh_ref_put(mesh); htable_mesh_erase(&scn->meshes, &shape); } list_del(&shape->scene_attachment); diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -46,11 +46,14 @@ shape_release_data(struct s3d_shape* shape) { ASSERT(shape); switch(shape->type) { - case SHAPE_MESH: mesh_clear(&shape->data.mesh); break; + case SHAPE_MESH: + if(shape->data.mesh) + mesh_ref_put(shape->data.mesh); + break; case SHAPE_NONE: /* Do nothing */ break; - case SHAPE_INSTANCE: + case SHAPE_INSTANCE: if(shape->data.instance) - instance_ref_put(shape->data.instance); + instance_ref_put(shape->data.instance); break; default: FATAL("Unreachable code\n"); break; } @@ -116,20 +119,33 @@ res_T s3d_shape_create_mesh (struct s3d_device* dev, struct s3d_shape** out_shape) { - struct s3d_shape* shape; + struct s3d_shape* shape = NULL; res_T res = RES_OK; - if(!dev || !out_shape) - return RES_BAD_ARG; + if(!dev || !out_shape) { + res = RES_BAD_ARG; + goto error; + } res = shape_create(dev, &shape); if(res != RES_OK) - return res; + goto error; + + res = mesh_create(dev, &shape->data.mesh); + if(res != RES_OK) + goto error; - mesh_init(dev->allocator, &shape->data.mesh); shape->type = SHAPE_MESH; - *out_shape = shape; - return RES_OK; +exit: + if(out_shape) + *out_shape = shape; + return res; +error: + if(shape) { + S3D(shape_ref_put(shape)); + shape = NULL; + } + goto exit; } res_T @@ -228,6 +244,6 @@ s3d_mesh_setup_indexed_vertices if(!shape || shape->type != SHAPE_MESH) return RES_BAD_ARG; return mesh_setup_indexed_vertices - (&shape->data.mesh, ntris, get_indices, nverts, attribs, data); + (shape->data.mesh, ntris, get_indices, nverts, attribs, data); } diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h @@ -57,7 +57,7 @@ struct s3d_shape { union { struct instance* instance; - struct mesh mesh; + struct mesh* mesh; } data; struct s3d_device* dev;