diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 167 |
1 files changed, 100 insertions, 67 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 072ff5235bf..370841327aa 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -53,8 +53,6 @@ #include "BKE_mesh.h" #include "BKE_pbvh.h" -#include "DNA_userdef_types.h" - #include "GPU_buffers.h" #include "GPU_draw.h" #include "GPU_basic_shader.h" @@ -107,10 +105,12 @@ static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } }; static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER; /* multires global buffer, can be used for many grids having the same grid size */ -static GPUBuffer *mres_glob_buffer = NULL; -static int mres_prev_gridsize = -1; -static GLenum mres_prev_index_type = 0; -static unsigned mres_prev_totquad = 0; +typedef struct GridCommonGPUBuffer { + GPUBuffer *mres_buffer; + int mres_prev_gridsize; + GLenum mres_prev_index_type; + unsigned mres_prev_totquad; +} GridCommonGPUBuffer; void GPU_buffer_material_finalize(GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat) { @@ -407,33 +407,6 @@ void GPU_buffer_free(GPUBuffer *buffer) BLI_mutex_unlock(&buffer_mutex); } -void GPU_buffer_multires_free(bool force) -{ - if (!mres_glob_buffer) { - /* Early output, no need to lock in this case, */ - return; - } - - if (force && BLI_thread_is_main()) { - if (mres_glob_buffer) { - if (mres_glob_buffer->id) - glDeleteBuffers(1, &mres_glob_buffer->id); - MEM_freeN(mres_glob_buffer); - } - } - else { - BLI_mutex_lock(&buffer_mutex); - gpu_buffer_free_intern(mres_glob_buffer); - BLI_mutex_unlock(&buffer_mutex); - } - - mres_glob_buffer = NULL; - mres_prev_gridsize = -1; - mres_prev_index_type = 0; - mres_prev_totquad = 0; -} - - void GPU_drawobject_free(DerivedMesh *dm) { GPUDrawObject *gdo; @@ -822,8 +795,14 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda for (i = 0; i < numdata; i++) { glEnableVertexAttribArray(data[i].index); + int info = 0; + if (data[i].type == GL_UNSIGNED_BYTE) { + info |= GPU_ATTR_INFO_SRGB; + } + glUniform1i(data[i].info_index, info); + glVertexAttribPointer(data[i].index, data[i].size, data[i].type, - GL_FALSE, elementsize, BUFFER_OFFSET(offset)); + GL_TRUE, elementsize, BUFFER_OFFSET(offset)); offset += data[i].size * GPU_typesize(data[i].type); attribData[i].index = data[i].index; @@ -937,7 +916,7 @@ void GPU_buffer_unlock(GPUBuffer *UNUSED(buffer), GPUBindingType binding) { int bindtypegl = gpu_binding_type_gl[binding]; /* note: this operation can fail, could return - * an error code from this function? */ + * an error code from this function? */ glUnmapBuffer(bindtypegl); glBindBuffer(bindtypegl, 0); } @@ -1003,6 +982,7 @@ struct GPU_PBVH_Buffers { const int *grid_indices; int totgrid; bool has_hidden; + bool is_index_buf_global; /* Means index_buf uses global bvh's grid_common_gpu_buffer, **DO NOT** free it! */ bool use_bmesh; @@ -1053,7 +1033,7 @@ static void gpu_color_from_mask_quad_copy(const CCGKey *key, void GPU_update_mesh_pbvh_buffers( GPU_PBVH_Buffers *buffers, const MVert *mvert, const int *vert_indices, int totvert, const float *vmask, - const int (*face_vert_indices)[4], bool show_diffuse_color) + const int (*face_vert_indices)[3], bool show_diffuse_color) { VertexBufferFormat *vert_data; int i, j; @@ -1181,7 +1161,7 @@ void GPU_update_mesh_pbvh_buffers( } GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( - const int (*face_vert_indices)[4], + const int (*face_vert_indices)[3], const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri, const MVert *mvert, const int *face_indices, @@ -1220,8 +1200,10 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( /* An element index buffer is used for smooth shading, but flat * shading requires separate vertex normals so an index buffer is * can't be used there. */ - if (buffers->smooth) + if (buffers->smooth) { buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3); + buffers->is_index_buf_global = false; + } if (buffers->index_buf) { /* Fill the triangle buffer */ @@ -1242,8 +1224,11 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX); } else { - GPU_buffer_free(buffers->index_buf); + if (!buffers->is_index_buf_global) { + GPU_buffer_free(buffers->index_buf); + } buffers->index_buf = NULL; + buffers->is_index_buf_global = false; } } @@ -1410,22 +1395,33 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, } (void)0 /* end FILL_QUAD_BUFFER */ -static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad) +static GPUBuffer *gpu_get_grid_buffer( + int gridsize, GLenum *index_type, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer) { /* used in the FILL_QUAD_BUFFER macro */ BLI_bitmap * const *grid_hidden = NULL; const int *grid_indices = NULL; int totgrid = 1; + GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer; + + if (gridbuff == NULL) { + *grid_common_gpu_buffer = gridbuff = MEM_mallocN(sizeof(GridCommonGPUBuffer), __func__); + gridbuff->mres_buffer = NULL; + gridbuff->mres_prev_gridsize = -1; + gridbuff->mres_prev_index_type = 0; + gridbuff->mres_prev_totquad = 0; + } + /* VBO is already built */ - if (mres_glob_buffer && mres_prev_gridsize == gridsize) { - *index_type = mres_prev_index_type; - *totquad = mres_prev_totquad; - return mres_glob_buffer; + if (gridbuff->mres_buffer && gridbuff->mres_prev_gridsize == gridsize) { + *index_type = gridbuff->mres_prev_index_type; + *totquad = gridbuff->mres_prev_totquad; + return gridbuff->mres_buffer; } /* we can't reuse old, delete the existing buffer */ - else if (mres_glob_buffer) { - GPU_buffer_free(mres_glob_buffer); + else if (gridbuff->mres_buffer) { + GPU_buffer_free(gridbuff->mres_buffer); } /* Build new VBO */ @@ -1433,17 +1429,17 @@ static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned if (gridsize * gridsize < USHRT_MAX) { *index_type = GL_UNSIGNED_SHORT; - FILL_QUAD_BUFFER(unsigned short, *totquad, mres_glob_buffer); + FILL_QUAD_BUFFER(unsigned short, *totquad, gridbuff->mres_buffer); } else { *index_type = GL_UNSIGNED_INT; - FILL_QUAD_BUFFER(unsigned int, *totquad, mres_glob_buffer); + FILL_QUAD_BUFFER(unsigned int, *totquad, gridbuff->mres_buffer); } - mres_prev_gridsize = gridsize; - mres_prev_index_type = *index_type; - mres_prev_totquad = *totquad; - return mres_glob_buffer; + gridbuff->mres_prev_gridsize = gridsize; + gridbuff->mres_prev_index_type = *index_type; + gridbuff->mres_prev_totquad = *totquad; + return gridbuff->mres_buffer; } #define FILL_FAST_BUFFER(type_) \ @@ -1470,8 +1466,9 @@ static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned } \ } (void)0 -GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, - BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key) +GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers( + int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key, + GridCommonGPUBuffer **grid_common_gpu_buffer) { GPU_PBVH_Buffers *buffers; int totquad; @@ -1500,8 +1497,10 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, } if (totquad == fully_visible_totquad) { - buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad); + buffers->index_buf = gpu_get_grid_buffer( + gridsize, &buffers->index_type, &buffers->tot_quad, grid_common_gpu_buffer); buffers->has_hidden = false; + buffers->is_index_buf_global = true; } else { buffers->tot_quad = totquad; @@ -1516,6 +1515,7 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, } buffers->has_hidden = true; + buffers->is_index_buf_global = false; } /* Build coord/normal VBO */ @@ -1740,8 +1740,9 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, const int use_short = (maxvert < USHRT_MAX); /* Initialize triangle index buffer */ - if (buffers->index_buf) + if (buffers->index_buf && !buffers->is_index_buf_global) GPU_buffer_free(buffers->index_buf); + buffers->is_index_buf_global = false; buffers->index_buf = GPU_buffer_alloc((use_short ? sizeof(unsigned short) : sizeof(unsigned int)) * 3 * tottri); @@ -1786,12 +1787,19 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, } else { /* Memory map failed */ - GPU_buffer_free(buffers->index_buf); + if (!buffers->is_index_buf_global) { + GPU_buffer_free(buffers->index_buf); + } buffers->index_buf = NULL; + buffers->is_index_buf_global = false; } } else if (buffers->index_buf) { - GPU_buffer_free(buffers->index_buf); + if (!buffers->is_index_buf_global) { + GPU_buffer_free(buffers->index_buf); + } + buffers->index_buf = NULL; + buffers->is_index_buf_global = false; } } @@ -1835,15 +1843,15 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, if (buffers->vert_buf) { char *base = NULL; char *index_base = NULL; - int bound_options = 0; + /* weak inspection of bound options, should not be necessary ideally */ + const int bound_options_old = GPU_basic_shader_bound_options(); + int bound_options_new = 0; glEnableClientState(GL_VERTEX_ARRAY); if (!wireframe) { glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - /* weak inspection of bound options, should not be necessary ideally */ - bound_options = GPU_basic_shader_bound_options(); - GPU_basic_shader_bind(bound_options | GPU_SHADER_USE_COLOR); + bound_options_new |= GPU_SHADER_USE_COLOR; } GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY); @@ -1855,10 +1863,18 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX); } - if (wireframe) + if (wireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - else - glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT); + } + else { + if ((buffers->smooth == false) && (buffers->face_indices_len == 0)) { + bound_options_new |= GPU_SHADER_FLAT_NORMAL; + } + } + + if (bound_options_new & ~bound_options_old) { + GPU_basic_shader_bind(bound_options_old | bound_options_new); + } if (buffers->tot_quad) { const char *offset = base; @@ -1932,7 +1948,10 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, if (!wireframe) { glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - GPU_basic_shader_bind(bound_options); + } + + if (bound_options_new & ~bound_options_old) { + GPU_basic_shader_bind(bound_options_old); } } } @@ -1985,7 +2004,7 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers) if (buffers) { if (buffers->vert_buf) GPU_buffer_free(buffers->vert_buf); - if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden)) + if (buffers->index_buf && !buffers->is_index_buf_global) GPU_buffer_free(buffers->index_buf); if (buffers->index_buf_fast) GPU_buffer_free(buffers->index_buf_fast); @@ -1998,6 +2017,20 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers) } } +void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer) +{ + GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer; + + if (gridbuff) { + if (gridbuff->mres_buffer) { + BLI_mutex_lock(&buffer_mutex); + gpu_buffer_free_intern(gridbuff->mres_buffer); + BLI_mutex_unlock(&buffer_mutex); + } + MEM_freeN(gridbuff); + *grid_common_gpu_buffer = NULL; + } +} /* debug function, draws the pbvh BB */ void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf) |