Name KHR_debug Name Strings GL_KHR_debug Contact Christophe Riccio (christophe.riccio 'at' amd.com) Contributors Jaakko Konttinen, AMD Graham Sellers, AMD Mark Young, AMD Ahmet Oguz Akyuz, AMD Bruce Merry, ARM Daniel Koch, TransGaming Jon Leech, Independent Pat Brown, NVIDIA Greg Roth, NVIDIA Yaki Tebeka, Graphic Remedy Piers Daniell, NVIDIA Seth Sowerby, Apple Benj Lipchak, Apple Jean-François Roy, Apple Daniel Rakos, AMD Mark Callow, HI Notice Copyright (c) 2012-2014 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL and OpenGL ES Working Groups. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php Status Complete. Approved by the ARB on 2012/06/18. Approved by the OpenGL ES WG on 2012/06/15. Ratified by the Khronos Board of Promoters on 2012/07/27. Version Last Modified Date: July 2, 2015 Author Revision: 17 Number ARB Extension #119 OpenGL ES Extension #118 Dependencies OpenGL 1.1 is required. The extension is written against the OpenGL 4.2 Compatibility Profile specification (April 27, 2012). Overview This extension allows the GL to notify applications when various events occur that may be useful during application development, debugging and profiling. These events are represented in the form of enumerable messages with a human-readable string representation. Examples of debug events include incorrect use of the GL, warnings of undefined behavior, and performance warnings. A message is uniquely identified by a source, a type and an implementation-dependent ID within the source and type pair. A message's source identifies the origin of the message and can either describe components of the GL, the window system, third-party external sources such as external debuggers, or even the application itself. The type of the message roughly identifies the nature of the event that caused the message. Examples include errors, performance warnings, warnings about undefined behavior or notifications identifying that the application is within a specific section of the application code. A message's ID for a given source and type further distinguishes messages within namespaces. For example, an error caused by a negative parameter value or an invalid internal texture format are both errors generated by the API, but would likely have different message IDs. Each message is also assigned to a severity level that denotes roughly how "important" that message is in comparison to other messages across all sources and types. For example, notification of a GL error would likely have a higher severity than a performance warning due to redundant state changes. Furthermore, every message contains an implementation-dependent string representation that provides a useful description of the event. Messages are communicated to the application through an application- defined callback function that is called by the GL implementation on each debug message. The motivation for the callback routine is to free application developers from actively having to query whether a GL error, or any other debuggable event has happened after each call to a GL function. With a callback, developers can keep their code free of debug checks, set breakpoints in the callback function, and only have to react to messages as they occur. In situations where using a callback is not possible, a message log is also provided that stores only copies of recent messages until they are actively queried. To control the volume of debug output, messages can be disabled either individually by ID, or entire sets of messages can be turned off based on combination of source and type, through the entire application code or only section of the code encapsulated in debug groups. A debug group may also be used to annotate the command stream using descriptive texts. This extension also defines debug markers, a mechanism for the OpenGL application to annotate the command stream with markers for discrete events. When profiling or debugging an OpenGL application with a built-in or an external debugger or profiler, it is difficult to relate the commands within the command stream to the elements of the scene or parts of the program code to which they correspond. Debug markers and debug groups help obviate this by allowing applications to specify this link. For example, a debug marker can be used to identify the beginning of a frame in the command stream and a debug group can encapsulate a specific command stream to identify a rendering pass. Debug groups also allow control of the debug outputs volume per section of an application code providing an effective way to handle the massive amount of debug outputs that drivers can generate. Some existing implementations of ARB_debug_output only expose the ARB_debug_output extension string if the context was created with the debug flag {GLX|WGL}_CONTEXT_DEBUG_BIT_ARB as specified in {GLX|WGL}_ARB_create_context. The behavior is not obvious when the functionality is brought into the OpenGL core specification because the extension string and function entry points must always exist. This extension modifies the existing ARB_debug_output extension to allow implementations to always have an empty message log. The specific messages written to the message log or callback routines are already implementation defined, so this specification simply makes it explicit that it's fine for there to be zero messages generated, even when a GL error occurs, which is useful if the context is non-debug. Debug output can be enabled and disabled by changing the DEBUG_OUTPUT state. It is implementation defined how much debug output is generated if the context was created without the CONTEXT_DEBUG_BIT set. This is a new query bit added to the existing GL_CONTEXT_FLAGS state to specify whether the context was created with debug enabled. Finally, this extension defines a mechanism for OpenGL applications to label their objects (textures, buffers, shaders, etc.) with a descriptive string. When profiling or debugging an OpenGL application within an external or built-in (debut output API) debugger or profiler it is difficult to identify objects from their object names (integers). Even when the object itself is viewed it can be problematic to differentiate between similar objects. Attaching a descriptive string, a label, to an object obviates this difficulty. The intended purpose of this extension is purely to improve the user experience within OpenGL development tools and application built-in profilers and debuggers. This extension typically improves OpenGL programmers efficiency by allowing them to instantly detect issues and the reason for these issues giving him more time to focus on adding new features to an OpenGL application. IP Status No known IP claims. New Procedures and Functions NOTE: when implemented in an OpenGL ES context, all entry points defined by this extension must have a "KHR" suffix. When implemented in an OpenGL context, all entry points must have NO suffix, as shown below. void DebugMessageControl(enum source, enum type, enum severity, sizei count, const uint* ids, boolean enabled); void DebugMessageInsert(enum source, enum type, uint id, enum severity, sizei length, const char* buf); void DebugMessageCallback(DEBUGPROC callback, const void* userParam); uint GetDebugMessageLog(uint count, sizei bufSize, enum* sources, enum* types, uint* ids, enum* severities, sizei* lengths, char* messageLog); void GetPointerv(enum pname, void** params); void PushDebugGroup(enum source, uint id, sizei length, const char * message); void PopDebugGroup(void); void ObjectLabel(enum identifier, uint name, sizei length, const char *label); void GetObjectLabel(enum identifier, uint name, sizei bufSize, sizei *length, char *label); void ObjectPtrLabel(void* ptr, sizei length, const char *label); void GetObjectPtrLabel(void* ptr, sizei bufSize, sizei *length, char *label); New Types NOTE: when implemented in an OpenGL ES context, this typedef must have a "KHR" suffix (GLDEBUGPROCKHR). When implemented in an OpenGL context, thie typedef must have NO suffix, as shown below. The callback function that applications can define, and is accepted by DebugMessageCallback, is defined as: typedef void (APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); Note that this function pointer is defined as having the same calling convention as the GL functions. New Tokens NOTE: when implemented in an OpenGL ES context, all tokens defined by this extension must have a "_KHR" suffix. When implemented in an OpenGL context, all tokens must have NO suffix, as described below. Tokens accepted by the parameters of Enable, Disable, and IsEnabled: DEBUG_OUTPUT 0x92E0 DEBUG_OUTPUT_SYNCHRONOUS 0x8242 Returned by GetIntegerv when is CONTEXT_FLAGS: CONTEXT_FLAG_DEBUG_BIT 0x00000002 Tokens accepted by the parameters of GetBooleanv, GetIntegerv, GetFloatv, GetDoublev and GetInteger64v: MAX_DEBUG_MESSAGE_LENGTH 0x9143 MAX_DEBUG_LOGGED_MESSAGES 0x9144 DEBUG_LOGGED_MESSAGES 0x9145 DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 MAX_DEBUG_GROUP_STACK_DEPTH 0x826C DEBUG_GROUP_STACK_DEPTH 0x826D MAX_LABEL_LENGTH 0x82E8 Tokens accepted by the parameter of GetPointerv: DEBUG_CALLBACK_FUNCTION 0x8244 DEBUG_CALLBACK_USER_PARAM 0x8245 Tokens accepted or provided by the parameters of DebugMessageControl, DebugMessageInsert and DEBUGPROC, and the parameter of GetDebugMessageLog (some commands restrict to a subset of these parameters; see the specification body for details): DEBUG_SOURCE_API 0x8246 DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 DEBUG_SOURCE_SHADER_COMPILER 0x8248 DEBUG_SOURCE_THIRD_PARTY 0x8249 DEBUG_SOURCE_APPLICATION 0x824A DEBUG_SOURCE_OTHER 0x824B Tokens accepted or provided by the parameters of DebugMessageControl, DebugMessageInsert and DEBUGPROC, and the parameter of GetDebugMessageLog: DEBUG_TYPE_ERROR 0x824C DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E DEBUG_TYPE_PORTABILITY 0x824F DEBUG_TYPE_PERFORMANCE 0x8250 DEBUG_TYPE_OTHER 0x8251 DEBUG_TYPE_MARKER 0x8268 Tokens accepted or provided by the parameters of DebugMessageControl and DEBUGPROC, and the parameter of GetDebugMessageLog: DEBUG_TYPE_PUSH_GROUP 0x8269 DEBUG_TYPE_POP_GROUP 0x826A Tokens accepted or provided by the parameters of DebugMessageControl, DebugMessageInsert and DEBUGPROC callback functions, and the parameter of GetDebugMessageLog: DEBUG_SEVERITY_HIGH 0x9146 DEBUG_SEVERITY_MEDIUM 0x9147 DEBUG_SEVERITY_LOW 0x9148 DEBUG_SEVERITY_NOTIFICATION 0x826B Returned by GetError: STACK_UNDERFLOW 0x0504 STACK_OVERFLOW 0x0503 Tokens accepted or provided by the parameters of ObjectLabel and GetObjectLabel: BUFFER 0x82E0 SHADER 0x82E1 PROGRAM 0x82E2 VERTEX_ARRAY QUERY 0x82E3 PROGRAM_PIPELINE 0x82E4 TRANSFORM_FEEDBACK SAMPLER 0x82E6 TEXTURE RENDERBUFFER FRAMEBUFFER [[ Compatibility Profile ]] DISPLAY_LIST 0x82E7 [[ End Profile-Specific Language ]] Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, GetDoublev, and GetInteger64v: MAX_LABEL_LENGTH Additions to Chapter 2 of the OpenGL 4.2 Specification (OpenGL Operation) In section 2.5 - GL Errors: Add to the end of the section (pg 19): "When an error is generated, the GL will also generate a debug output message describing its cause (see section 5.5). The message has the source DEBUG_SOURCE_API and the type DEBUG_TYPE_ERROR, and an implementation-dependent ID." Additions to Chapter 3 of the OpenGL 4.2 Specification (Rasterization) None. Additions to Chapter 4 of the OpenGL 4.2 Specification (Per-Fragment Operations and the Frame Buffer) None. Additions to Chapter 5 of the OpenGL 4.2 Specification (Special Functions) After section 5.4 - Hints (pg. 300) (section 5.3, p 217 in OpenGL ES 3.0), add new section: "5.5 - Debug Output Application developers can obtain more information from the GL runtime in the form of debug output. This information can include details about GL errors, undefined behavior, implementation-dependent performance warnings, or other useful hints. This information is communicated through a stream of debug messages that are generated as GL commands are executed. The application can choose to receive these messages either through a callback routine, or by querying for them from a message log. Controls are provided for disabling messages that the application does not care about, and for inserting application-generated messages into the stream. The GL may provide different levels of debug output depending on how the context was created. If the context was created without the CONTEXT_FLAG_DEBUG_BIT in the CONTEXT_FLAGS state, as described in Section 6.1.12, then the GL may optionally not generate any debug messages, but the functions described below will otherwise operate without error. Debug output functionality is controlled with the DEBUG_OUTPUT enable state. If the context is created with the CONTEXT_FLAG_DEBUG_BIT set then the initial state of DEBUG_OUTPUT is TRUE, otherwise the initial state of DEBUG_OUTPUT is FALSE. In a debug context, if DEBUG_OUTPUT is disabled the GL will not generate any debug output logs or callbacks. Enabling DEBUG_OUTPUT again will enable full debug output functionality. If the context was created without the CONTEXT_FLAG_DEBUG_BIT and the DEBUG_OUTPUT is later enabled, the level of debug output logging is defined by the GL implementation, which may have zero debug output. To guarantee the full debug output support of the GL implementation the context should be created with CONTEXT_FLAG_DEBUG_BIT context flag bit set. 5.5.1 - Debug Messages A debug message is uniquely identified by the source that generated it, a type within that source, and an unsigned integer ID identifying the message within that type. The message source is one of the symbolic constants listed in Table 5.3. The message type is one of the symbolic constants listed in Table 5.4. Debug Output Message Source Messages Generated by --------------------------- --------------------- DEBUG_SOURCE_API The GL DEBUG_SOURCE_SHADER_COMPILER The GLSL shader compiler or compilers for other extension-provided languages DEBUG_SOURCE_WINDOW_SYSTEM The window system, such as WGL or GLX DEBUG_SOURCE_THIRD_PARTY External debuggers or third-party middleware libraries DEBUG_SOURCE_APPLICATION The application DEBUG_SOURCE_OTHER Sources that do not fit to any of the ones listed above ---------------------------------------------------------------------------- Table 5.3: Sources of debug output messages. Each message must originate from a source listed in this table. Debug Output Message Type Informs about ------------------------- ------------- DEBUG_TYPE_ERROR Events that generated an error DEBUG_TYPE_DEPRECATED_BEHAVIOR Behavior that has been marked for deprecation DEBUG_TYPE_UNDEFINED_BEHAVIOR Behavior that is undefined according to the specification DEBUG_TYPE_PERFORMANCE Implementation-dependent performance warnings DEBUG_TYPE_PORTABILITY Use of extensions or shaders in a way that is highly vendor-specific DEBUG_TYPE_OTHER Types of events that do not fit any of the ones listed above DEBUG_TYPE_MARKER Annotation of the command stream DEBUG_TYPE_PUSH_GROUP Entering a debug group DEBUG_TYPE_POP_GROUP Leaving a debug group ---------------------------------------------------------------------------- Table 5.4: Types of debug output messages. Each message is associated with one of these types that describes the nature of the message. Each message source and type pair contains its own namespace of messages with every message being associated with an ID. The assignment of IDs to messages within a namespace is implementation-dependent. There can potentially be overlap between the namespaces of two different pairs of source and type, so messages can only be uniquely distinguished from each other by the full combination of source, type and ID. Each message is also assigned a severity level that roughly describes its importance across all sources and types along a single global axis. The severity of a message is one of the symbolic constants defined in Table 5.5. Because messages can be disabled by their severity, this allows for quick control the global volume of debug output. Severity Level Token Suggested examples of messages -------------------- ------------------------------ DEBUG_SEVERITY_HIGH Any GL error; dangerous undefined behavior; any GLSL or ARB shader compiler and linker errors; DEBUG_SEVERITY_MEDIUM Severe performance warnings; GLSL or other shader compiler and linker warnings; use of currently deprecated behavior DEBUG_SEVERITY_LOW Performance warnings from redundant state changes; trivial undefined behavior DEBUG_SEVERITY_NOTIFICATION Any message which is not an error or performance concern ---------------------------------------------------------------------------- Table 5.5: Severity levels of messages. Each debug output message is associated with one of these severity levels. Every message also has a null-terminated string representation that is used to describe the message. The contents of the string can change slightly between different instances of the same message (e.g. which parameter value caused a specific GL error to occur). The format of a message string is left as implementation-dependent, although it should at least represent a concise description of the event that caused the message to be generated. Messages with different IDs should also have sufficiently distinguishable string representations to warrant their separation. The lengths of all messages, including their null terminators, must be guaranteed to be less or equal to the value of the implementation-dependent constant MAX_DEBUG_MESSAGE_LENGTH. Messages can be either enabled or disabled. Messages that are disabled will not be generated. All messages are initially enabled unless their assigned severity is DEBUG_SEVERITY_LOW. The enabled state of messages can be changed using the command DebugMessageControl. 5.5.2 - Debug Message Callback Applications can provide a callback function for receiving debug messages using the command void DebugMessageCallback(DEBUGPROC callback, const void* userParam); with storing the address of the callback function. This function's prototype must follow the type definition of DEBUGPROC including its platform-dependent calling convention. Anything else will result in undefined behavior. Only one debug callback can be specified for the current context, and further calls overwrite the previous callback. Specifying NULL as the value of clears the current callback and disables message output through callbacks. Applications can provide user-specified data through the pointer . The context will store this pointer and will include it as one of the parameters in each call to the callback function. If the application has specified a callback function for receiving debug output, the implementation will call that function whenever any enabled message is generated. The source, type, ID, and severity of the message are specified by the DEBUGPROC parameters , , , and , respectively. The string representation of the message is stored in and its length (excluding the null-terminator) is stored in . The parameter is the user-specified parameter that was given when calling DebugMessageCallback. Applications can query the current callback function and the current user-specified parameter by obtaining the values of DEBUG_CALLBACK_FUNCTION and DEBUG_CALLBACK_USER_PARAM, respectively. Applications that specify a callback function must be aware of certain special conditions when executing code inside a callback when it is called by the GL, regardless of the debug source. The memory for is owned and managed by the GL, and should only be considered valid for the duration of the function call. The behavior of calling any GL or window system function from within the callback function is undefined and may lead to program termination. Care must also be taken in securing debug callbacks for use with asynchronous debug output by multi-threaded GL implementations. Section 5.5.7 describes this in further detail. If the DEBUG_OUTPUT state is disabled then the GL will not call the callback function. 5.5.3 - Debug Message Log If DEBUG_CALLBACK_FUNCTION is NULL, then debug messages are instead stored in an internal message log up to some maximum number of messages as defined by the value of MAX_DEBUG_LOGGED_MESSAGES. Each context stores its own message log and will only store messages generated by commands operating in that context. If the message log fills up, then any subsequently generated messages will not be placed in the log until the message log is cleared, and will instead be discarded. Applications can query the number of messages currently in the log by obtaining the value of DEBUG_LOGGED_MESSAGES, and the string length (including its null terminator) of the oldest message in the log through the value of DEBUG_NEXT_LOGGED_MESSAGE_LENGTH. To fetch message data stored in the log, the command GetDebugMessageLog can be used as described in section 6.1.15. If DEBUG_CALLBACK_FUNCTION is not NULL, no generated messages will be stored in the log but will instead be passed to the debug callback routine as described in section 5.5.2. If the DEBUG_OUTPUT state is disabled then no messages are added to the message log. 5.5.4 - Controlling Debug Messages Applications can control the volume of debug output in the active debug group, by disabling specific or groups of messages with the command: void DebugMessageControl(enum source, enum type, enum severity, sizei count, const uint* ids, boolean enabled); If is TRUE, the referenced subset of messages will be enabled. If FALSE, then those messages will be disabled. This command can reference different subsets of messages by first considering the set of all messages, and filtering out messages based on the following ways: - If , , or is DONT_CARE, the messages from all sources, of all types, or of all severities are referenced respectively. - When values other than DONT_CARE are specified, all messages whose source, type, or severity match the specified , , or respectively will be referenced. - If is greater than zero, then is an array of message IDs for the specified combination of and . In this case, if or is DONT_CARE, or is not DONT_CARE, the error INVALID_OPERATION is generated. Unrecognized message IDs in are ignored. If is zero, the value if is ignored. In addition, if any of , , and is not DONT_CARE and is not one of the symbols from, respectively, Table 5.3, Table 5.4, and Table 5.5, the error INVALID_ENUM is generated. If is negative, the error INVALID_VALUE is generated. Although messages are grouped into an implicit hierarchy by their sources and types, there is no explicit per-source, per-type or per-severity enabled state. Instead, the enabled state is stored individually for each message. There is no difference between disabling all messages from one source in a single call, and individually disabling all messages from that source using their types and IDs. If the DEBUG_OUTPUT state is disabled the GL operates the same as if messages of every , or are disabled. 5.5.5 - Externally Generated Messages To support applications and third-party libraries generating their own messages, such as ones containing timestamp information or signals about specific render system events, the following function can be called void DebugMessageInsert(enum source, enum type, uint id, enum severity, int length, const char* buf); The value of specifies the ID for the message and indicates its severity level as defined by the caller. If is not one of the severity levels listed in Table 5.5, the error INVALID_ENUM will be generated. The value of must be one of the values from Table 5.4 and the value of must be either DEBUG_SOURCE_APPLICATION or DEBUG_SOURCE_THIRD_PARTY, or the error INVALID_ENUM will be generated. The string contains the string representation of the message. The parameter contains the number of characters in . If is negative, it is implied that contains a null terminated string. The error INVALID_VALUE will be generated if the number of characters in , excluding the null terminator when is negative, is not less than the value of MAX_DEBUG_MESSAGE_LENGTH. If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do not generate an error. 5.5.6 - Debug Groups Debug groups provide a method for annotating a command stream with discrete groups of commands using a descriptive text. Debug output messages, either generated by the implementation or inserted by the application with DebugMessageInsert are written to the active debug group, the top of the debug group stack. Debug groups are strictly hierarchical. Their sequences may be nested within other debug groups but can not overlap. If no debug group has been pushed by the application then the active debug group is the default debug group. The command void PushDebugGroup(enum source, uint id, sizei length, const char *message); pushes a debug group described by the string into the command stream. The value of specifies the ID of messages generated. The parameter contains the number of characters in . If is negative, it is implied that contains a null terminated string. The message has the specified and , DEBUG_TYPE_PUSH_GROUP, and DEBUG_SEVERITY_NOTIFICATION. The GL will put a new debug group on top of the debug group stack which inherits the control of the volume of debug output of the debug group previously residing on the top of the debug group stack. Because debug groups are strictly hierarchical, any additional control of the debug output volume will only apply within the active debug group and the debug groups pushed on top of the active debug group. An INVALID_ENUM error is generated if the value of is neither DEBUG_SOURCE_APPLICATION nor DEBUG_SOURCE_THIRD_PARTY. An INVALID_VALUE error is generated if is negative and the number of characters in , excluding the null-terminator, is not less than the value of MAX_DEBUG_MESSAGE_LENGTH. The command void PopDebugGroup(); pops the active debug group. When a debug group is popped, the GL will also generate a debug output message describing its cause based on the string, the source , and an ID submitted to the associated PushDebugGroup command. DEBUG_TYPE_PUSH_GROUP and DEBUG_TYPE_POP_GROUP share a single namespace for message . has the value DEBUG_SEVERITY_NOTIFICATION. The has the value DEBUG_TYPE_POP_GROUP. Popping a debug group restores the debug output volume control of the parent debug group. Attempting to pop the default debug group off the stack generates a STACK_UNDERFLOW error; pushing a debug group onto a stack containing MAX_DEBUG_GROUP_STACK_DEPTH minus one elements will generate a STACK_OVERFLOW error. 5.5.7 - Asynchronous and Synchronous Debug Output The behavior of how and when the GL driver is allowed to generate debug messages, and subsequently either call back to the application or place the message in the debug message log, is affected by the state DEBUG_OUTPUT_SYNCHRONOUS. This state can be modified by the Enable and Disable commands. Its initial value is FALSE. When DEBUG_OUTPUT_SYNCHRONOUS is disabled, the driver is optionally allowed to concurrently call the debug callback routine from potentially multiple threads, including threads that the context that generated the message is not currently bound to. The implementation may also call the callback routine asynchronously after the GL command that generated the message has already returned. The application is fully responsible for ensuring thread safety due to debug callbacks under these circumstances. In this situation the value may be helpful in identifying which application thread's command originally generated the debug callback. When DEBUG_OUTPUT_SYNCHRONOUS is enabled, the driver guarantees synchronous calls to the callback routine by the context. When synchronous callbacks are enabled, all calls to the callback routine will be made by the thread that owns the current context; all such calls will be made serially by the current context; and each call will be made before the GL command that generated the debug message is allowed to return. When no callback is specified and DEBUG_OUTPUT_SYNCHRONOUS is disabled, the driver can still asynchronously place messages in the debug message log, even after the context thread has returned from the GL function that generated those messages. When DEBUG_OUTPUT_SYNCHRONOUS is enabled, the driver guarantees that all messages are added to the log before the GL function returns. Enabling synchronous debug output greatly simplifies the responsibilities of the application for making its callback functions thread-safe, but may potentially result in drastically reduced driver performance. DEBUG_OUTPUT_SYNCHRONOUS only guarantees intra-context synchronization for the callbacks of messages generated by that context, and does not guarantee synchronization across multiple contexts. If multiple contexts are concurrently used by the application, it is allowed for those contexts to also concurrently call their designated callbacks, and the application is responsible for handling thread safety in that situation even if DEBUG_OUTPUT_SYNCHRONOUS is enabled in all contexts." 5.5.8 Debug Labels: Debug labels provide a method for annotating any object (texture, buffer, shader, etc.) with a descriptive text label. These labels may then be used by the debug output (see section 5.5) or an external tool such as a debugger or profiler to describe labelled objects. The command void ObjectLabel(enum identifier, uint name, sizei length, const char *label); labels the object identified by and its namespace . must be one of the tokens in table 5.1, indicating the type of the object corresponding to . Identifier Object Type --------------------------------------- BUFFER | buffer SHADER | shader PROGRAM | program VERTEX_ARRAY | vertex array QUERY | query PROGRAM_PIPELINE | program pipeline TRANSFORM_FEEDBACK| transform feedback SAMPLER | sampler TEXTURE | texture RENDERBUFFER | render buffer FRAMEBUFFER | frame buffer [[ Compatibility Profile Only]] DISPLAY_LIST | display list [[ End Profile-Specific Language ]] --------------------------------------- Table 5.1. Valid object namespace identifiers and the corresponding object type. The command void ObjectPtrLabel(void* ptr, sizei length, const char *label); labels a sync object identified by .