Commit: 107e34407d0ae4120cc7a12fdb208986a0b47d8e
Author: Antony Riakiotakis
Date:   Tue Jul 14 16:48:23 2015 +0200
Branches: master
https://developer.blender.org/rB107e34407d0ae4120cc7a12fdb208986a0b47d8e

Display optimizations part 1.

This patch changes the way we draw meshes by introducing
indexed drawing. This makes it possible to easily
upload and rearrange faces ad lib according to any criteria.

Currently we use material sorting but textured sorting and
hiding will be added to optimize textured drawing and skip
per face testing.

It also adds support for vertex buffers for subsurf
modifiers (Except from GLSL drawing), making drawing of
subsurf much faster without need for bogus modifiers.

Tests show that we gain approximately 20-25% performance
by that for solid mode drawing with up to 50% gains for
material drawing. Textured drawing should also have a
small performance gain, but more substantial optimizations
are possible there.

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D1406

===================================================================

M       source/blender/blenkernel/BKE_DerivedMesh.h
M       source/blender/blenkernel/BKE_pbvh.h
M       source/blender/blenkernel/intern/cdderivedmesh.c
M       source/blender/blenkernel/intern/pbvh.c
M       source/blender/blenkernel/intern/subsurf_ccg.c
M       source/blender/gpu/GPU_buffers.h
M       source/blender/gpu/intern/gpu_buffers.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h 
b/source/blender/blenkernel/BKE_DerivedMesh.h
index 984147d..881b233 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -463,6 +463,9 @@ struct DerivedMesh {
                                   void (*setMaterial)(void *userData, int 
matnr, void *attribs),
                                   bool (*setFace)(void *userData, int index), 
void *userData);
 
+       struct GPUDrawObject *(*gpuObjectNew)(DerivedMesh *dm);
+       void (*copy_gpu_data)(DerivedMesh *dm, int type, float *varray, int 
*mat_orig_to_new, void *user_data);
+
        /** Release reference to the DerivedMesh. This function decides 
internally
         * if the DerivedMesh will be freed, or cached for later use. */
        void (*release)(DerivedMesh *dm);
diff --git a/source/blender/blenkernel/BKE_pbvh.h 
b/source/blender/blenkernel/BKE_pbvh.h
index 0832e24..fbaf91d 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -112,7 +112,7 @@ void BKE_pbvh_raycast_project_ray_root(
 
 void BKE_pbvh_node_draw(PBVHNode *node, void *data);
 void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
-                   int (*setMaterial)(int matnr, void *attribs), bool 
wireframe);
+                   int (*setMaterial)(int matnr, void *attribs), bool 
wireframe, bool fast);
 
 /* PBVH Access */
 typedef enum {
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c 
b/source/blender/blenkernel/intern/cdderivedmesh.c
index 37c3376..4752332 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -341,8 +341,8 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
 static void cdDM_drawVerts(DerivedMesh *dm)
 {
        GPU_vertex_setup(dm);
-       if (dm->drawObject->tot_triangle_point)
-               glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point);
+       if (dm->drawObject->tot_loop_verts)
+               glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loop_verts);
        else
                glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point);
        GPU_buffer_unbind();
@@ -391,7 +391,7 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool 
drawLooseEdges, bool drawAllEdg
        if (cddm->pbvh && cddm->pbvh_draw &&
            BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
        {
-               BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true);
+               BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true, false);
 
                return;
        }
@@ -442,7 +442,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
                        float (*face_nors)[3] = 
CustomData_get_layer(&dm->faceData, CD_NORMAL);
 
                        BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, 
face_nors,
-                                     setMaterial, false);
+                                     setMaterial, false, false);
                        glShadeModel(GL_FLAT);
                }
 
@@ -451,11 +451,11 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
        
        GPU_vertex_setup(dm);
        GPU_normal_setup(dm);
+       GPU_triangle_setup(dm);
        glShadeModel(GL_SMOOTH);
        for (a = 0; a < dm->drawObject->totmaterial; a++) {
                if (!setMaterial || 
setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
-                       glDrawArrays(GL_TRIANGLES, 
dm->drawObject->materials[a].start,
-                                    dm->drawObject->materials[a].totpoint);
+                       GPU_buffer_draw_elements(dm->drawObject->triangles, 
GL_TRIANGLES, dm->drawObject->materials[a].start, 
dm->drawObject->materials[a].totelements);
                }
        }
        GPU_buffer_unbind();
@@ -473,12 +473,13 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
        const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
        MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
        MCol *mcol;
-       int i;
-       int colType, startFace = 0;
+       int i, orig;
+       int colType, start_element;
        bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
-       int tottri;
+       int totpoly;
        int next_actualFace;
-       
+       int mat_index;
+       int tot_element;
 
        /* double lookup */
        const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, 
CD_ORIGINDEX);
@@ -497,7 +498,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
        if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == 
PBVH_BMESH) {
                if (BKE_pbvh_has_faces(cddm->pbvh)) {
                        GPU_set_tpage(NULL, false, false);
-                       BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+                       BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, 
false);
                }
 
                return;
@@ -518,6 +519,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
        
        GPU_vertex_setup(dm);
        GPU_normal_setup(dm);
+       GPU_triangle_setup(dm);
        if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
                GPU_texpaint_uv_setup(dm);
        else
@@ -525,76 +527,84 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
        if (mcol) {
                GPU_color_setup(dm, colType);
        }
-       
-       tottri = dm->drawObject->tot_triangle_point / 3;
-       next_actualFace = dm->drawObject->triangle_to_mface[0];
-       
+               
        glShadeModel(GL_SMOOTH);
        /* lastFlag = 0; */ /* UNUSED */
-       for (i = 0; i < tottri; i++) {
-               int actualFace = next_actualFace;
-               DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
-               int flush = 0;
-               
-               if (i != tottri - 1)
-                       next_actualFace = dm->drawObject->triangle_to_mface[i + 
1];
-
-               if (drawParams) {
-                       MTexPoly *tp = NULL;
-                       if (use_tface && mtexpoly && index_mf_to_mpoly) {
-                               int actualFace_poly = 
index_mf_to_mpoly[actualFace];
-                               if (actualFace_poly != ORIGINDEX_NONE) {
-                                       tp = &mtexpoly[actualFace_poly];
+       for (mat_index = 0; mat_index < dm->drawObject->totmaterial; 
mat_index++) {
+               GPUBufferMaterial *bufmat = dm->drawObject->materials + 
mat_index;
+               next_actualFace = bufmat->polys[0];
+               totpoly = bufmat->totpolys;
+
+               tot_element = 0;
+               start_element = bufmat->start;
+
+               for (i = 0; i < totpoly; i++) {
+                       int actualFace = bufmat->polys[i];
+                       DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+                       int flush = 0;
+
+                       if (i != totpoly - 1)
+                               next_actualFace = bufmat->polys[i + 1];
+
+                       if (drawParams) {
+                               MTexPoly *tp = NULL;
+                               if (use_tface && mtexpoly && index_mf_to_mpoly) 
{
+                                       int actualFace_poly = 
index_mf_to_mpoly[actualFace];
+                                       if (actualFace_poly != ORIGINDEX_NONE) {
+                                               tp = &mtexpoly[actualFace_poly];
+                                       }
                                }
-                       }
 
-                       draw_option = drawParams(tp, (mcol != NULL), 
mf[actualFace].mat_nr);
-               }
-               else {
-                       if (index_mf_to_mpoly) {
-                               const int orig = 
DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
-                               if (orig == ORIGINDEX_NONE) {
-                                       /* XXX, this is not really correct
-                                                        * it will draw the 
previous faces context for this one when we don't know its settings.
-                                                        * but better then 
skipping it altogether. - campbell */
-                                       draw_option = DM_DRAW_OPTION_NORMAL;
+                               draw_option = drawParams(tp, (mcol != NULL), 
mf[actualFace].mat_nr);
+                       }
+                       else {
+                               if (index_mf_to_mpoly) {
+                                       orig = 
DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
+                                       if (orig == ORIGINDEX_NONE) {
+                                               /* XXX, this is not really 
correct
+                                                * it will draw the previous 
faces context for this one when we don't know its settings.
+                                                * but better then skipping it 
altogether. - campbell */
+                                               draw_option = 
DM_DRAW_OPTION_NORMAL;
+                                       }
+                                       else if (drawParamsMapped) {
+                                               draw_option = 
drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+                                       }
                                }
                                else if (drawParamsMapped) {
-                                       draw_option = 
drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+                                       draw_option = 
drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
                                }
                        }
-                       else if (drawParamsMapped) {
-                               draw_option = drawParamsMapped(userData, 
actualFace, mf[actualFace].mat_nr);
+
+                       /* flush buffer if current triangle isn't drawable or 
it's last triangle */
+                       flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == 
totpoly - 1);
+
+                       if (!flush && compareDrawOptions) {
+                               /* also compare draw options and flush buffer 
if they're different
+                                * need for face selection highlight in edit 
mode */
+                               flush |= compareDrawOptions(userData, 
actualFace, next_actualFace) == 0;
                        }
-               }
-               
-               /* flush buffer if current triangle isn't drawable or it's last 
triangle */
-               flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 
1);
-               
-               if (!flush && compareDrawOptions) {
-                       /* also compare draw options and flush buffer if 
they're different
-                                        * need for face selection highlight in 
edit mode */
-                       flush |= compareDrawOptions(userData, actualFace, 
next_actualFace) == 0;
-               }
-               
-               if (flush) {
-                       int first = startFace * 3;
-                       /* Add one to the length if we're drawing at the end of 
the array */
-                       int count = (i - startFace + (draw_option != 
DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
-                       
-                       if (count) {
-                               if (mcol && draw_option != 
DM_DRAW_OPTION_NO_MCOL)
-                                       GPU_color_switch(1);
-                               else
-                                       GPU_color_switch(0);
-                               
-                               glDrawArrays(GL_TRIANGLES, first, count);
+
+                       if (flush) {
+                               if (draw_option != DM_DRAW_OPTION_SKIP)
+                                       tot_element += mf[actualFace].v4 ? 6 : 
3;
+
+                               if (tot_element) {
+                                       if (mcol && draw_option != 
DM_DRAW_OPTION_NO_MCOL)
+                                               GPU_color_switch(1);
+                                       else
+                                               GPU_color_switch(0);
+
+                                       
GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, 
start_element, tot_element);
+                               }
+
+                               start_element = tot_element;
+                       }
+                       else {
+                               tot_element += mf[actualFace].v4 ? 6 : 3;
                        }
-                       
-                       startFace = i + 1;
                }
        }
-       
+
        GPU_buffer_unbind();
        glShadeModel(GL_FLAT);
        
@@ -747,87 +757,92 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
                }
        }
        else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster 
rendering */
-               int prevstart = 0;
+               int start_element = 0, tot_element;
+               int totpoly;
                int tottri;
+               int mat_index;
                
                GPU_vertex_setup(dm);
                GPU_normal_setup(dm);
+               GPU_triangle_setup(dm);
                if (useColors && mcol) {
                        GPU_color_setup(dm, colType);
                }
-               tottri = dm->drawObject->tot_triangle_point / 3;
                glShadeModel(GL_SMOOTH);
                
+               tottri = dm->drawObject->tot_triangle_point / 3;
+
                if (tottri == 0) {
                        /* avoid buffer problems in following code */
                }
                else if (setDrawOptions == NULL) {
                        /* just draw the entire face array */
-                       glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
+                       GPU_buffer_draw_elements(dm->drawObject->triangles, 
GL_TRIANGLES, 0, 3 * tottri);
                }
-               else {
-                       /* we need to check if the

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to