Showing posts with label optimization. Show all posts
Showing posts with label optimization. Show all posts

Sunday, December 10, 2006

Streaming texture updates

It is possible to stream updates to a texture, often skipping a costly data copy, using the GL_ARB_pixel_buffer_object extension which was promoted to core in OpenGL 2.1

To do this, you must bind a buffer to GL_PIXEL_UNPACK_BUFFER_ARB, map it, write your texture data into the mapped buffer, unmap it, and call glTexSubImage2D referencing into the buffer.

// Bind buffer
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, myBuffer);

// Null existing data
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * bytesPerPixel, NULL, GL_STREAM_DRAW);

// Map buffer. Returns pointer to buffer memory
void *pboMemory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);

writeImage(pboMemory); // Writes data into pboMemory

// Unmaps buffer, indicating we are done writing data to it
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (char *)NULL);

// Unbind buffer
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);


Normally the driver must copy the data you pass into glTexSubImage2D. However, by storing the data in a buffer, which is memory managed by the driver, we can avoid this copy. Furthermore, by using a universally hardware accelerated texture format (see this tip) we prevent any data processing, ensuring the fastest possible download to the GPU.


References:

GL_ARB_pixel_buffer_object specification

Wednesday, December 6, 2006

What is the fastest way to draw geometry?

Ideally, you should use a static vertex buffer object, with a stride of 32 bytes (or a multiple of 32). The most optimal draw call is glDrawRangeElements. Indices should be unsigned shorts.

Vertex data should be stored as GLfloat, GLshort, or GLubyte, as these formats are supported by most GPUs.

References:

ATI performance tuning(page 10)
Using VBOs(page 14)

UNCONFIRMED: Internally on all GPUs, vertices contain four values: xyzw. By default, if a w value is not provided, it is set to 1. Theoretically, if you perform this padding in your application before sending the data to OpenGL, you can improve performance.

Shaders expect all data to be float, thus it is expected that on programmable GPUs specifying all vertex data as float will improve performance by limiting data conversion.

What is the optimal 32 bit texture format?

The optimal texture format on all systems, regardless of endianness or operating system, is an internal format of GL_RGBA8, a type of GL_UNSIGNED_INT_8_8_8_8_REV, and a format of GL_BGRA. An optimal call to glTexImage2D would thus be this:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, border, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);

Remember that because this is a packed integer format, you are responsible for taking endianness into account when packing the pixels.

References:
GL_NV_pixel_data_range (look at NVIDIA Implementation Details).
Mac OpenGL mailing list