From 50a46a5973d90787eaa37ea959b9035918a071af Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Sat, 25 Jul 2015 13:17:37 +0200 Subject: [PATCH] GPU buffer materials: Separate and reuse some shared code. Also avoid counting for information we already know, such as total loop triangles etc. --- .../blender/blenkernel/intern/cdderivedmesh.c | 47 +++-------------- .../blender/blenkernel/intern/subsurf_ccg.c | 50 ++++--------------- source/blender/gpu/GPU_buffers.h | 3 ++ source/blender/gpu/intern/gpu_buffers.c | 30 +++++++++++ 4 files changed, 51 insertions(+), 79 deletions(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 4c94fe33ae3..060ffff5a12 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1652,12 +1652,6 @@ static void cdDM_drawobject_init_vert_points( MEM_freeN(mat_orig_to_new); } -typedef struct { - int elements; - int loops; - int polys; -} GPUMaterialInfo; - /* see GPUDrawObject's structure definition for a description of the * data being initialized here */ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm) @@ -1666,8 +1660,8 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm) const MPoly *mpoly; const MLoop *mloop; int totmat = dm->totmat; - GPUMaterialInfo *mat_info; - int i, curmat, totelements, totloops, totpolys; + GPUBufferMaterial *mat_info; + int i, totloops, totpolys; /* object contains at least one material (default included) so zero means uninitialized dm */ BLI_assert(totmat != 0); @@ -1676,6 +1670,7 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm) mloop = dm->getLoopArray(dm); totpolys = dm->getNumPolys(dm); + totloops = dm->getNumLoops(dm); /* get the number of points used by each material, treating * each quad as two triangles */ @@ -1683,49 +1678,23 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm) for (i = 0; i < totpolys; i++) { const int mat_nr = mpoly[i].mat_nr; - mat_info[mat_nr].polys++; - mat_info[mat_nr].elements += 3 * ME_POLY_TRI_TOT(&mpoly[i]); - mat_info[mat_nr].loops += mpoly[i].totloop; + mat_info[mat_nr].totpolys++; + mat_info[mat_nr].totelements += 3 * ME_POLY_TRI_TOT(&mpoly[i]); + mat_info[mat_nr].totloops += mpoly[i].totloop; } /* create the GPUDrawObject */ gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject"); gdo->totvert = dm->getNumVerts(dm); gdo->totedge = dm->getNumEdges(dm); - /* count the number of materials used by this DerivedMesh */ - for (i = 0; i < totmat; i++) { - if (mat_info[i].elements > 0) - gdo->totmaterial++; - } - - /* allocate an array of materials used by this DerivedMesh */ - gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial, - "GPUDrawObject.materials"); - - /* initialize the materials array */ - for (i = 0, curmat = 0, totelements = 0, totloops = 0; i < totmat; i++) { - if (mat_info[i].elements > 0) { - gdo->materials[curmat].start = totelements; - /* can set it to points now but used in cdDM_drawobject_init_vert_points as counter */ - gdo->materials[curmat].totelements = mat_info[i].elements; - gdo->materials[curmat].totloops = mat_info[i].loops; - gdo->materials[curmat].mat_nr = i; - gdo->materials[curmat].totpolys = mat_info[i].polys; - gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * mat_info[i].polys, "GPUBufferMaterial.polys"); - - totelements += mat_info[i].elements; - totloops += mat_info[i].loops; - curmat++; - } - } + GPU_buffer_material_finalize(gdo, mat_info, totmat); gdo->tot_loop_verts = totloops; /* store total number of points used for triangles */ - gdo->tot_triangle_point = totelements; + gdo->tot_triangle_point = dm->getNumLoopTri(dm) * 3; cdDM_drawobject_init_vert_points(gdo, mpoly, mloop, totpolys, totmat); - MEM_freeN(mat_info); return gdo; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 7e5d00af9e2..2a69ba4c21b 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2458,12 +2458,6 @@ static void ccgDM_copy_gpu_data( } } -typedef struct { - int elements; - int loops; - int polys; -} GPUMaterialInfo; - static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) { GPUBufferMaterial *mat; @@ -2474,8 +2468,8 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) DMFlagMat *faceFlags = ccgdm->faceFlags; int gridFaces = ccgSubSurf_getGridSize(ss) - 1; int totmat = (faceFlags) ? dm->totmat : 1; - GPUMaterialInfo *matinfo; - int i, curmat, curelement; + GPUBufferMaterial *matinfo; + int i; unsigned int tot_internal_edges = 0; int edgeVerts = ccgSubSurf_getEdgeSize(ss); int edgeSize = edgeVerts - 1; @@ -2494,9 +2488,9 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) int numVerts = ccgSubSurf_getFaceNumVerts(f); int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); int new_matnr = faceFlags[index].mat_nr; - matinfo[new_matnr].elements += numVerts * gridFaces * gridFaces * 6; - matinfo[new_matnr].loops += numVerts * gridFaces * gridFaces * 4; - matinfo[new_matnr].polys++; + matinfo[new_matnr].totelements += numVerts * gridFaces * gridFaces * 6; + matinfo[new_matnr].totloops += numVerts * gridFaces * gridFaces * 4; + matinfo[new_matnr].totpolys++; tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1); } } @@ -2504,9 +2498,9 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) for (i = 0; i < totface; i++) { CCGFace *f = ccgdm->faceMap[i].face; int numVerts = ccgSubSurf_getFaceNumVerts(f); - matinfo[0].elements += numVerts * gridFaces * gridFaces * 6; - matinfo[0].loops += numVerts * gridFaces * gridFaces * 4; - matinfo[0].polys++; + matinfo[0].totelements += numVerts * gridFaces * gridFaces * 6; + matinfo[0].totloops += numVerts * gridFaces * gridFaces * 4; + matinfo[0].totpolys++; tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1); } } @@ -2516,33 +2510,10 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) gdo->totvert = 0; /* used to count indices, doesn't really matter for ccgsubsurf */ gdo->totedge = (totedge * edgeSize + tot_internal_edges); - /* count the number of materials used by this DerivedMesh */ - for (i = 0; i < totmat; i++) { - if (matinfo[i].elements > 0) - gdo->totmaterial++; - } - - /* allocate an array of materials used by this DerivedMesh */ - gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial, - "GPUDrawObject.materials"); - - /* initialize the materials array */ - for (i = 0, curmat = 0, curelement = 0; i < totmat; i++) { - if (matinfo[i].elements > 0) { - gdo->materials[curmat].start = curelement; - gdo->materials[curmat].totelements = matinfo[i].elements; - gdo->materials[curmat].totloops = matinfo[i].loops; - gdo->materials[curmat].mat_nr = i; - gdo->materials[curmat].totpolys = matinfo[i].polys; - gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * matinfo[i].polys, "GPUBufferMaterial.polys"); - - curelement += matinfo[i].elements; - curmat++; - } - } + GPU_buffer_material_finalize(gdo, matinfo, totmat); /* store total number of points used for triangles */ - gdo->tot_triangle_point = curelement; + gdo->tot_triangle_point = ccgSubSurf_getNumFinalFaces(ss) * 6; gdo->tot_loop_verts = ccgSubSurf_getNumFinalFaces(ss) * 4; @@ -2582,7 +2553,6 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) } MEM_freeN(mat_orig_to_new); - MEM_freeN(matinfo); return gdo; } diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index a50d63d89ec..8bb3ef4a3bc 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -48,6 +48,7 @@ struct DMFlagMat; struct DerivedMesh; struct GSet; struct GPUVertPointLink; +struct GPUDrawObject; struct PBVH; struct MVert; @@ -71,6 +72,8 @@ typedef struct GPUBufferMaterial { short mat_nr; } GPUBufferMaterial; +void GPU_buffer_material_finalize(struct GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat); + /* meshes are split up by material since changing materials requires * GL state changes that can't occur in the middle of drawing an * array. diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index b2bfb0b47b8..bbffa5a53c2 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -114,6 +114,36 @@ static int mres_prev_gridsize = -1; static GLenum mres_prev_index_type = 0; static unsigned mres_prev_totquad = 0; +void GPU_buffer_material_finalize(GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat) +{ + int i, curmat, curelement; + + /* count the number of materials used by this DerivedMesh */ + for (i = 0; i < totmat; i++) { + if (matinfo[i].totelements > 0) + gdo->totmaterial++; + } + + /* allocate an array of materials used by this DerivedMesh */ + gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial, + "GPUDrawObject.materials"); + + /* initialize the materials array */ + for (i = 0, curmat = 0, curelement = 0; i < totmat; i++) { + if (matinfo[i].totelements > 0) { + gdo->materials[curmat] = matinfo[i]; + gdo->materials[curmat].start = curelement; + gdo->materials[curmat].mat_nr = i; + gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * matinfo[i].totpolys, "GPUBufferMaterial.polys"); + + curelement += matinfo[i].totelements; + curmat++; + } + } + + MEM_freeN(matinfo); +} + /* stores recently-deleted buffers so that new buffers won't have to * be recreated as often