From BlenderWiki

Jump to: navigation, search

The aim of this project is to increase the viewport responsiveness by reducing rendering time of meshes by utilizing OpenGL features, such as Vertex Arrays and Vertex Buffer Objects (VBOs). They allow rendering the same meshes, but using significantly less OpenGL API calls and, in case of VBOs, storing most of the data in video memory for future access.

Buffer

Assembly of buffers when rendering using GLSL mode. One vertex buffer, one normal buffer and one interleaved buffer with two vertex attributes are bound.

GPUBuffer structure, defined in gpu_buffers.h, stores either a pointer in system memory for vertex arrays or an ID of an OpenGL Vertex Buffer Object with a list of some per-vertex parameters (f.e. position, normal vector, texture coordinates and so on).

Buffers can contain interleaved or non-interleaved data. Using interleaved buffers makes sense when all the data in the buffer changes at once, when streaming (reuploading all the data to the GPU each time it's needed). This happens in edit mode and in GLSL mode when non-standard (neither position nor normal vector) vertex attributes are required.

When rendering, several buffers can be setup together. This is helpful when some additional data is required, for example when switching from solid to textured mode. In that case, texture coordinates must be also setup and can be easily provided without requiring to reupload position and normal vector data.

When not using the automatically generated buffers, data to the allocated buffers can be uploaded using GPU_buffer_lock or GPU_buffer_lock_stream functions. They return a pointer to the buffer and then values can be assigned. The later function can be used when streaming (reuploading new data each frame) for a speed increase, since the GPU can discard previous data. Values can not be read from the buffer and only one buffer can be locked at a time. After uploading, GPU_buffer_unlock must be called. Vertex colors can also be uploaded using the GPU_color3_upload or GPU_color4_upload functions.

Buffer Pool

GPUBufferPool stores buffers that were freed. MAX_FREE_GPU_BUFFERS (which equals 8 at the time of writing) defines the maximum number of free buffers stored in the pool and when there is not enough room, the last buffer used is completely released. The pool serves the purpose of speeding up memory allocation, since all the buffers are freed everytime DerivedMesh structure is destroyed. When editing a mesh, this can cause a serious speed hit, because DerivedMesh is constantly being destroyed and recreated, usually with the same amount of faces.

Any amount of buffer pools can be constructed using GPU_buffer_pool_new, but by default one global pool, defined in gpu_buffer.c as globalPool, is used and is initialized the first time it is required.

Draw Object

GPUDrawObject stores all the buffers, associated with a particular Mesh and some other useful information, such as:

  • whether the mesh should be rendered using the old code (GPUDrawObject::legacy)
  • the list of materials associated with the faces (GPUDrawObject::materials)
  • the list of faces in which each vertex index is used (GPUDrawObject::indices). Mainly used in sculpting code to easily find the faces that need to be updated.
  • since quads are split into triangles, the index of original face for each new face (GPUDrawObject::faceRemap)
  • number of elements, number of loose vertices, number of edges and so on...

Interface

Various buffers can be setup by a single function call. The list includes:

  • GPU_vertex_setup - used to setup vertex position buffer
  • GPU_normal_setup - used to setup normal vector buffer
  • GPU_uv_setup - used to setup texture coordinates
  • GPU_color_setup - used to setup vertex colors
  • GPU_edge_setup - used to setup vertex position buffer and an index buffer with the list of edges (including loose edges)
  • GPU_interleaved_setup - used to setup an interleaved buffer you provide with the format you define. Mainly used in edit mode code, because the data is reuploaded every frame and can be easily fit into one buffer. This may improve performance, comparing to the case where each data type would be fit into a different buffer.
  • GPU_interleaved_attrib_setup - used to setup an interleaved buffer you provide with the format you define. Mainly used in GLSL rendering code, because custom vertex attributes are reuploaded every frame.

The first five functions generate the buffers on demand when called for the first time. Then the mesh is rendered using normal OpenGL functions and glDrawArrays, or, in the case of edges, GPU_buffer_draw_elements. Note that the faces may be reordered from the ones stored in DerivedMesh to minimize the amount of material switches. After rendering, call GPU_buffer_unbind to reset the OpenGL state.

Benchmarks

These benchmarks were performed on a Windows Vista 32bit machine with Intel Core 2 Duo E4500 processor clocked at 2.42GHz, 4GB of RAM and Nvidia Geforce 8800GTS 512MB video card.

The test case was a standard cube with Subdivide Smooth tool applied 8 times and rendered in solid mode. An average of five runs was used.

Time taken to render the viewport 10 times in two builds of blender 2.5

Mode Blender 2.5 svn r21880 Blender 2.5 GSoC branch
Object Mode 812ms 123ms
Edit Mode 5600ms 4648ms

The much smaller improvement in edit mode is due to the fact that all the data is reuploaded each frame.