== GPU Buffers ==

This patch attempts to clean up and document the GPU buffers
code. There are a few bug fixes as well.

Patch reviewed here: http://codereview.appspot.com/4631052/

Summary:

* Bugfix: make GPU_buffer_copy_normal convert from shorts to floats
  correctly, also fixed the use of cached face normal CustomData.

* Bugfix: changed the `mat_nr' field of GPUBufferMaterial from char to
  short.

* Changed color buffer setup to not alloc a temporary copy of color
  data, just passes the MCol data in directly.

* Changed the GPU buffer pool code to make clearer what operates
  specifically on the global pool.

* Lots of refactoring for GPU_drawobject_new; should operate mostly
  the same (except got rid of one unecessary allocation), just split
  into more functions and without macros now.

* Converted some #defines into enumerations.

* Made some stuff private, pulled out of header file.

* Deleted unused function GPU_buffer_pool_free_unused().

* Removed GPU_interleaved_setup and related #defines. (I think this
  was used for editmode VBOs, but those were disabled.)

* Added lots of comments.

* Added a few comments in the code signed `--nicholas' to note places
  where I am unsure about design or usage, would be good to address
  these better.

* Code formatting changed to be more consistent with the rest of
  Blender.

* Renamed some fields and variables to be more consistent with
  Blender's naming conventions.

* Renamed some fields and variables to use more descriptive names,
  e.g. renamed `redir' to `mat_orig_to_new'.

* Removed print outs with DEBUG_VBO -- don't feel too strongly about
  this one, just not used elsewhere in Blender, could be easily added
  back if others disagree though.

* Moved the PBVH drawing code down to the bottom of the file, before
  was sitting in the middle of the other VBO code
This commit is contained in:
2011-07-08 19:58:02 +00:00
parent a6bb0f93ad
commit abdf420a6d
4 changed files with 1190 additions and 1211 deletions

View File

@@ -284,8 +284,10 @@ static void cdDM_drawVerts(DerivedMesh *dm)
else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
GPU_vertex_setup(dm);
if( !GPU_buffer_legacy(dm) ) {
if(dm->drawObject->nelements) glDrawArrays(GL_POINTS,0, dm->drawObject->nelements);
else glDrawArrays(GL_POINTS,0, dm->drawObject->nlooseverts);
if(dm->drawObject->tot_triangle_point)
glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
else
glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
}
GPU_buffer_unbind();
}
@@ -547,9 +549,10 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
GPU_normal_setup( dm );
if( !GPU_buffer_legacy(dm) ) {
glShadeModel(GL_SMOOTH);
for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
for( a = 0; a < dm->drawObject->totmaterial; a++ ) {
if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
dm->drawObject->materials[a].totpoint);
}
}
GPU_buffer_unbind( );
@@ -629,13 +632,13 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha
GPU_color_setup(dm);
if( !GPU_buffer_legacy(dm) ) {
glShadeModel(GL_SMOOTH);
glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
if( useTwoSided ) {
GPU_color4_upload(dm,cp2);
GPU_color_setup(dm);
glCullFace(GL_FRONT);
glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
glCullFace(GL_BACK);
}
}
@@ -787,8 +790,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
glShadeModel( GL_SMOOTH );
lastFlag = 0;
for(i = 0; i < dm->drawObject->nelements/3; i++) {
int actualFace = dm->drawObject->faceRemap[i];
for(i = 0; i < dm->drawObject->tot_triangle_point/3; i++) {
int actualFace = dm->drawObject->triangle_to_mface[i];
int flag = 1;
if(drawParams) {
@@ -819,13 +822,13 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
startFace = i;
}
}
if( startFace < dm->drawObject->nelements/3 ) {
if( startFace < dm->drawObject->tot_triangle_point/3 ) {
if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
if (lastFlag==1 && col)
GPU_color_switch(1);
else
GPU_color_switch(0);
glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
glDrawArrays(GL_TRIANGLES, startFace*3, dm->drawObject->tot_triangle_point - startFace*3);
}
}
}
@@ -935,7 +938,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
if( useColors && mc )
GPU_color_setup(dm);
if( !GPU_buffer_legacy(dm) ) {
int tottri = dm->drawObject->nelements/3;
int tottri = dm->drawObject->tot_triangle_point/3;
glShadeModel(GL_SMOOTH);
if(tottri == 0) {
@@ -947,17 +950,17 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
}
else {
/* we need to check if the next material changes */
int next_actualFace= dm->drawObject->faceRemap[0];
int next_actualFace= dm->drawObject->triangle_to_mface[0];
for( i = 0; i < tottri; i++ ) {
//int actualFace = dm->drawObject->faceRemap[i];
//int actualFace = dm->drawObject->triangle_to_mface[i];
int actualFace = next_actualFace;
MFace *mface= mf + actualFace;
int drawSmooth= (mface->flag & ME_SMOOTH);
int draw = 1;
if(i != tottri-1)
next_actualFace= dm->drawObject->faceRemap[i+1];
next_actualFace= dm->drawObject->triangle_to_mface[i+1];
orig= (index==NULL) ? actualFace : index[actualFace];
@@ -1129,9 +1132,9 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
GPU_normal_setup(dm);
if( !GPU_buffer_legacy(dm) ) {
for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
a = dm->drawObject->faceRemap[i];
a = dm->drawObject->triangle_to_mface[i];
mface = mf + a;
new_matnr = mface->mat_nr + 1;
@@ -1153,7 +1156,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
if( numdata != 0 ) {
GPU_buffer_free(buffer, NULL);
GPU_buffer_free(buffer);
buffer = NULL;
}
@@ -1193,7 +1196,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
if( numdata != 0 ) {
elementsize = GPU_attrib_element_size( datatypes, numdata );
buffer = GPU_buffer_alloc( elementsize*dm->drawObject->nelements, NULL );
buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
if( buffer == NULL ) {
GPU_buffer_unbind();
dm->drawObject->legacy = 1;
@@ -1202,7 +1205,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
varray = GPU_buffer_lock_stream(buffer);
if( varray == NULL ) {
GPU_buffer_unbind();
GPU_buffer_free(buffer, NULL);
GPU_buffer_free(buffer);
dm->drawObject->legacy = 1;
return;
}
@@ -1341,7 +1344,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
}
GPU_buffer_unbind();
}
GPU_buffer_free( buffer, NULL );
GPU_buffer_free(buffer);
}
glShadeModel(GL_FLAT);

View File

@@ -37,8 +37,6 @@
#ifndef __GPU_BUFFERS_H__
#define __GPU_BUFFERS_H__
#define MAX_FREE_GPU_BUFFERS 8
#ifdef _DEBUG
/*#define DEBUG_VBO(X) printf(X)*/
#define DEBUG_VBO(X)
@@ -46,112 +44,92 @@
#define DEBUG_VBO(X)
#endif
#ifdef _DEBUG
#define ERROR_VBO(X) printf(X)
#else
#define ERROR_VBO(X)
#endif
struct DerivedMesh;
struct DMGridData;
struct GHash;
struct DMGridData;
struct GPUVertPointLink;
/* V - vertex, N - normal, T - uv, C - color
F - float, UB - unsigned byte */
#define GPU_BUFFER_INTER_V3F 1
#define GPU_BUFFER_INTER_N3F 2
#define GPU_BUFFER_INTER_T2F 3
#define GPU_BUFFER_INTER_C3UB 4
#define GPU_BUFFER_INTER_C4UB 5
#define GPU_BUFFER_INTER_END -1
typedef struct GPUBuffer
{
typedef struct GPUBuffer {
int size; /* in bytes */
void *pointer; /* used with vertex arrays */
unsigned int id; /* used with vertex buffer objects */
} GPUBuffer;
/* stores deleted buffers so that new buffers wouldn't have to
be recreated that often. */
typedef struct GPUBufferPool
{
int size; /* number of allocated buffers stored */
int maxsize; /* size of the array */
GPUBuffer **buffers;
} GPUBufferPool;
typedef struct GPUBufferMaterial {
/* range of points used for this material */
int start;
int totpoint;
typedef struct GPUBufferMaterial
{
int start; /* at which vertex in the buffer the material starts */
int end; /* at which vertex it ends */
char mat_nr;
/* original material index */
short mat_nr;
} GPUBufferMaterial;
typedef struct IndexLink {
int element;
struct IndexLink *next;
} IndexLink;
/* meshes are split up by material since changing materials requires
GL state changes that can't occur in the middle of drawing an
array.
typedef struct GPUDrawObject
{
GPUBuffer *vertices;
some simplifying assumptions are made:
* all quads are treated as two triangles.
* no vertex sharing is used; each triangle gets its own copy of the
vertices it uses (this makes it easy to deal with a vertex used
by faces with different properties, such as smooth/solid shading,
different MCols, etc.)
to avoid confusion between the original MVert vertices and the
arrays of OpenGL vertices, the latter are referred to here and in
the source as `points'. similarly, the OpenGL triangles generated
for MFaces are referred to as triangles rather than faces.
*/
typedef struct GPUDrawObject {
GPUBuffer *points;
GPUBuffer *normals;
GPUBuffer *uv;
GPUBuffer *colors;
GPUBuffer *edges;
GPUBuffer *uvedges;
int *faceRemap; /* at what index was the face originally in DerivedMesh */
IndexLink *indices; /* given an index, find all elements using it */
IndexLink *indexMem; /* for faster memory allocation/freeing */
int indexMemUsage; /* how many are already allocated */
/* for each triangle, the original MFace index */
int *triangle_to_mface;
/* for each original vertex, the list of related points */
struct GPUVertPointLink *vert_points;
/* storage for the vert_points lists */
struct GPUVertPointLink *vert_points_mem;
int vert_points_usage;
int colType;
GPUBufferMaterial *materials;
int totmaterial;
int tot_triangle_point;
int tot_loose_point;
/* caches of the original DerivedMesh values */
int totvert;
int totedge;
int nmaterials;
int nelements; /* (number of faces) * 3 */
int nlooseverts;
int nedges;
int nindices;
int legacy; /* if there was a failure allocating some buffer, use old rendering code */
/* if there was a failure allocating some buffer, use old
rendering code */
int legacy;
} GPUDrawObject;
/* used for GLSL materials */
typedef struct GPUAttrib
{
typedef struct GPUAttrib {
int index;
int size;
int type;
} GPUAttrib;
GPUBufferPool *GPU_buffer_pool_new(void);
void GPU_buffer_pool_free( GPUBufferPool *pool );
void GPU_buffer_pool_free_unused( GPUBufferPool *pool );
void GPU_global_buffer_pool_free(void);
GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool );
void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool );
GPUBuffer *GPU_buffer_alloc(int size);
void GPU_buffer_free(GPUBuffer *buffer);
GPUDrawObject *GPU_drawobject_new( struct DerivedMesh *dm );
void GPU_drawobject_free( struct DerivedMesh *dm );
/* Buffers for non-DerivedMesh drawing */
void *GPU_build_mesh_buffers(struct GHash *map, struct MVert *mvert,
struct MFace *mface, int *face_indices,
int totface, int *vert_indices, int uniq_verts,
int totvert);
void GPU_update_mesh_buffers(void *buffers, struct MVert *mvert,
int *vert_indices, int totvert);
void *GPU_build_grid_buffers(struct DMGridData **grids,
int *grid_indices, int totgrid, int gridsize);
void GPU_update_grid_buffers(void *buffers_v, struct DMGridData **grids,
int *grid_indices, int totgrid, int gridsize, int smooth);
void GPU_draw_buffers(void *buffers);
void GPU_free_buffers(void *buffers);
/* called before drawing */
void GPU_vertex_setup( struct DerivedMesh *dm );
void GPU_normal_setup( struct DerivedMesh *dm );
@@ -175,6 +153,7 @@ void GPU_color4_upload( struct DerivedMesh *dm, unsigned char *data );
/* switch color rendering on=1/off=0 */
void GPU_color_switch( int mode );
/* used for drawing edges */
void GPU_buffer_draw_elements( GPUBuffer *elements, unsigned int mode, int start, int count );
/* called after drawing */
@@ -183,4 +162,18 @@ void GPU_buffer_unbind(void);
/* used to check whether to use the old (without buffers) code */
int GPU_buffer_legacy( struct DerivedMesh *dm );
/* Buffers for non-DerivedMesh drawing */
void *GPU_build_mesh_buffers(struct GHash *map, struct MVert *mvert,
struct MFace *mface, int *face_indices,
int totface, int *vert_indices, int uniq_verts,
int totvert);
void GPU_update_mesh_buffers(void *buffers, struct MVert *mvert,
int *vert_indices, int totvert);
void *GPU_build_grid_buffers(struct DMGridData **grids,
int *grid_indices, int totgrid, int gridsize);
void GPU_update_grid_buffers(void *buffers_v, struct DMGridData **grids,
int *grid_indices, int totgrid, int gridsize, int smooth);
void GPU_draw_buffers(void *buffers);
void GPU_free_buffers(void *buffers);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -416,7 +416,7 @@ void WM_exit(bContext *C)
BPY_python_end();
#endif
GPU_buffer_pool_free(NULL);
GPU_global_buffer_pool_free();
GPU_free_unused_buffers();
GPU_extensions_exit();