B.4. ObjectsUse glGenLists () , glGenBuffers () , and glGenTextures () to obtain unused display list, buffer object, and texture object identifiers.
When creating new display lists, buffer objects, or texture objects, OpenGL doesn't require you to pass in identifiers obtained from
glGenLists
()
,
glGenBuffers
()
, and
glGenTextures
()
. As long as you use an unused identifier, OpenGL will behave as expected. You should resist the urge to assume that an identifier is unused and hard-code it, however, even during the development phase. If you fail to remedy this situation later, the robustness of your code will be compromised. The cost to obtain an unused identifier from
glGenLists
()
,
glGenBuffers
()
, and
glGenTextures
()
is very small and greatly
|
Appendix C. Performance
OpenGL
Distilled
intentionally doesn't cover
Nonetheless, most professional developers profile their code and optimize it for maximum performance. This is
Before tuning, be familiar with the capabilities of your graphics card and computer system so that you'll know what performance to expect. |
C.1. Measure PerformanceBefore you optimize your code, you need a way to measure performance objectively so that you'll know when you've made an improvement. GLUT provides glutGet ( GLUT_ELAPSED_TIME ) , which applications can use to obtain platform-independent timing information. It returns an integer count of milliseconds elapsed since the application started. Many platforms, however, provide platform-specific routines for obtaining time information, which might provide more precision. If you choose to use GLUT_ELAPSED_TIME , you'll need to measure several frames to obtain an accurate measurement on such a coarse timer. Because OpenGL supports a client-server model, OpenGL often buffers commands internally. As a result, some OpenGL commands return to the application before they execute. This behavior can skew performance measurements if you attempt to time such a command. You can block until OpenGL executes all commands by using glFinish () , however. Because glFinish () has a nonzero cost, you'll want to measure several rendered framespossibly hundredsand then use a single glFinish () call before obtaining time information. This amortizes the expense of the glFinish () call over all rendered frames, increasing the accuracy of the timing measurement.
Although many end-users might not know what it means to synchronize buffer swaps to the monitor refresh rate (or vertical sync ), as an OpenGL developer, you must disable vertical sync to obtain an accurate performance measurement. Don't measure performance with vertical sync enabled. How you disable it depends on your development platform and graphics card. Some devices control vertical sync with an environment variable; others, with a device-driver control application. Some OpenGL implementations also support an extension to disable vertical sync, [1] which allows your application to disable it programmatically.
To obtain an accurate measurement of frames rendered per second, instrument your application as shown in the following pseudocode:
glFinish(); const int start = glutGet( GLUT_ELAPSED_TIME ); Render N frames, where N is large. glFinish(); const int end = glutGet( GLUT_ELAPSED_TIME ); const float fps = (float)( end start ) / (float)N; The larger the value of N (the more frames you include in the timing measurement), the more accurate your result will be, as large values of N amortize the cost of the final glFinish () call and also compensate for the coarse GLUT timing value. Rather than take timing measurements manually by inserting code to measure the elapsed time, professional software developers often use thirdparty optimization tools, such as Intel's VTune or the GNU gprof profiler. Some OpenGL development tools, such as Apple's OpenGL Profiler, contain both debugging and optimization features. |