== 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:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user