void RAS_InstancingBuffer::Realloc(unsigned int size) { if (m_vbo) { GPU_buffer_free(m_vbo); } m_vbo = GPU_buffer_alloc(m_stride * size); }
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, int vector_size, int size, GLenum target, void *user, GPUBufferCopyFunc copy_f) { GPUBufferPool *pool; GPUBuffer *buffer; float *varray; int mat_orig_to_new[MAX_MATERIALS]; int *cur_index_per_mat; int i; int success; GLboolean uploaded; pool = gpu_get_global_buffer_pool(); /* alloc a GPUBuffer; fall back to legacy mode on failure */ if(!(buffer = GPU_buffer_alloc(size))) dm->drawObject->legacy = 1; /* nothing to do for legacy mode */ if(dm->drawObject->legacy) return 0; cur_index_per_mat = MEM_mallocN(sizeof(int)*object->totmaterial, "GPU_buffer_setup.cur_index_per_mat"); for(i = 0; i < object->totmaterial; i++) { /* for each material, the current index to copy data to */ cur_index_per_mat[i] = object->materials[i].start * vector_size; /* map from original material index to new GPUBufferMaterial index */ mat_orig_to_new[object->materials[i].mat_nr] = i; } if(useVBOs) { success = 0; while(!success) { /* bind the buffer and discard previous data, avoids stalling gpu */ glBindBufferARB(target, buffer->id); glBufferDataARB(target, buffer->size, 0, GL_STATIC_DRAW_ARB); /* attempt to map the buffer */ if(!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) { /* failed to map the buffer; delete it */ GPU_buffer_free(buffer); gpu_buffer_pool_delete_last(pool); buffer= NULL; /* try freeing an entry from the pool and reallocating the buffer */ if(pool->totbuf > 0) { gpu_buffer_pool_delete_last(pool); buffer = GPU_buffer_alloc(size); } /* allocation still failed; fall back to legacy mode */ if(!buffer) { dm->drawObject->legacy = 1; success = 1; } } else { success = 1; } } /* check legacy fallback didn't happen */ if(dm->drawObject->legacy == 0) { uploaded = GL_FALSE; /* attempt to upload the data to the VBO */ while(uploaded == GL_FALSE) { (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user); /* glUnmapBuffer returns GL_FALSE if the data store is corrupted; retry in that case */ uploaded = glUnmapBufferARB(target); } } glBindBufferARB(target, 0); } else { /* VBO not supported, use vertex array fallback */ if(buffer->pointer) { varray = buffer->pointer; (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user); } else { dm->drawObject->legacy = 1; } } MEM_freeN(cur_index_per_mat); return buffer; }