| Name |
| |
| AMD_debug_output |
| |
| Name Strings |
| |
| GL_AMD_debug_output |
| |
| Contact |
| |
| Jaakko Konttinen (jaakko.konttinen 'at' amd.com) |
| |
| Contributors |
| |
| Graham Sellers, AMD |
| Mark Young, AMD |
| Ahmet Oguz Akyuz, AMD |
| |
| Status |
| |
| Experimental |
| |
| Version |
| |
| Last Modified Date: May 7, 2010 |
| Author Revision: 9 |
| |
| Number |
| |
| 395 |
| |
| Dependencies |
| |
| OpenGL 1.1 is required. |
| |
| WGL_ARB_create_context or GLX_ARB_create_context is required. |
| |
| The extension is written against the OpenGL 3.0 specification. |
| |
| This extension trivially interacts with ARB_vertex_program and |
| ARB_fragment_program. |
| |
| Overview |
| |
| This extension allows the GL to notify applications when various |
| debug events occur in contexts that have been created with the debug |
| flag, as provided by WGL_ARB_create_context and GLX_ARB_create_context. |
| |
| These events are represented in the form of enumerable messages with an |
| included human-readable translation. Examples of debug events include |
| incorrect use of the GL, warnings of undefined behavior, and performance |
| warnings. |
| |
| A message is uniquely identified by a category and an implementation- |
| dependent ID within that category. Message categories are general and are |
| used to organize large groups of similar messages together. Examples of |
| categories include GL errors, performance warnings, and deprecated |
| functionality warnings. Each message is also assigned a severity level |
| that denotes roughly how "important" that message is in comparison to |
| other messages across all categories. For example, notification of a GL |
| error would have a higher severity than a performance warning due to |
| redundant state changes. |
| |
| 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 any GL error or other |
| debuggable event has happened after each call to a GL function. With a |
| callback, developers can keep their code free of debug checks, and only have |
| to react to messages as they occur. In order to support indirect rendering, |
| a message log is also provided that stores 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 groups of messages can be turned off based |
| on category or severity. |
| |
| The only requirement on the minimum quantity and type of messages that |
| implementations of this extension must support is that a message must be |
| sent notifying the application whenever any GL error occurs. Any further |
| messages are left to the implementation. Implementations do not have |
| to output messages from all categories listed by this extension |
| in order to support this extension, and new categories can be added by |
| other extensions. |
| |
| This extension places no restrictions or requirements on any additional |
| functionality provided by the debug context flag through other extensions. |
| |
| IP Status |
| |
| No known IP claims. |
| |
| New Procedures and Functions |
| |
| void DebugMessageEnableAMD(enum category, |
| enum severity, |
| sizei count, |
| const uint* ids, |
| boolean enabled); |
| |
| void DebugMessageInsertAMD(enum category, |
| enum severity, |
| uint id, |
| sizei length, |
| const char* buf); |
| |
| void DebugMessageCallbackAMD(DEBUGPROCAMD callback, |
| void* userParam); |
| |
| uint GetDebugMessageLogAMD(uint count, |
| sizei bufsize, |
| enum* categories, |
| uint* severities, |
| uint* ids, |
| sizei* lengths, |
| char* message); |
| |
| New Types |
| |
| The callback function that applications can define, and |
| is accepted by DebugMessageCallbackAMD, is defined as: |
| |
| typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, |
| GLenum category, |
| GLenum severity, |
| GLsizei length, |
| const GLchar* message, |
| GLvoid* userParam); |
| |
| Note that this function pointer is defined as having the |
| same calling convention as the GL functions. |
| |
| New Tokens |
| |
| Tokens accepted by GetIntegerv: |
| |
| MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143 |
| MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 |
| DEBUG_LOGGED_MESSAGES_AMD 0x9145 |
| |
| Tokens accepted by DebugMessageEnableAMD, GetDebugMessageLogAMD, |
| DebugMessageInsertAMD, and DEBUGPROCAMD callback function |
| for <severity>: |
| |
| DEBUG_SEVERITY_HIGH_AMD 0x9146 |
| DEBUG_SEVERITY_MEDIUM_AMD 0x9147 |
| DEBUG_SEVERITY_LOW_AMD 0x9148 |
| |
| Tokens accepted by DebugMessageEnableAMD, GetDebugMessageLogAMD, |
| and DEBUGPROCAMD callback function for <category>: |
| |
| DEBUG_CATEGORY_API_ERROR_AMD 0x9149 |
| DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A |
| DEBUG_CATEGORY_DEPRECATION_AMD 0x914B |
| DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C |
| DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D |
| DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E |
| DEBUG_CATEGORY_APPLICATION_AMD 0x914F |
| DEBUG_CATEGORY_OTHER_AMD 0x9150 |
| |
| Additions to Chapter 2 of the OpenGL 3.0 Specification (OpenGL Operation) |
| |
| In section 2.5 - GL Errors: |
| Add to the end of the section (pg 19): "If an error is generated by a debug |
| GL context (Section 2.20), the context will send a message to the application |
| that a GL error has occurred. This message may contain more information |
| about the nature of the error." |
| |
| After section 2.19 - Primitive Clipping: |
| Add new section: 2.20 - Debug Contexts |
| |
| Application developers can obtain more information from the GL runtime using |
| a debug-enabled context. This information can include details about |
| GL errors, undefined behavior, implementation-dependent performance warnings, |
| or other useful hints. This information is communicated through the |
| generation of debug messages when GL commands are executed. The application |
| can choose to either actively query for these messages, or allow the GL to |
| call back to the application on each message via a function pointer. |
| |
| 2.20.1 - Debug Messages |
| |
| A debug message is uniquely identified by its category and an unsigned |
| integer message ID within that category. The category must be one of the |
| symbolic constants listed in Table 2.12. Although every distinct message |
| must have a unique number within a category, there is no enforcement by this |
| extension for how GL implementations assign numbers to specific messages. |
| |
| Each message also has a severity level that roughly describes its |
| significance across all categories. The severity level of a message is |
| one of the symbolic constants defined in Table 2.13. Because messages |
| can be disabled across all categories by severity level, this feature can |
| be used to quickly control the volume of debug output by the application. |
| |
| Category Token Informs about |
| -------------- ------------- |
| DEBUG_CATEGORY_API_ERROR_AMD GL errors caused by invalid API use |
| |
| DEBUG_CATEGORY_WINDOW_SYSTEM_AMD Errors and notices from the |
| windowing layer |
| |
| DEBUG_CATEGORY_DEPRECATION_AMD Use of functionality that is either |
| deprecated or marked for future |
| deprecation |
| |
| DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD Behavior undefined according to |
| specification |
| |
| DEBUG_CATEGORY_PERFORMANCE_AMD Implementation-dependent performance |
| warnings |
| |
| DEBUG_CATEGORY_SHADER_COMPILER_AMD Information from the GLSL or ARB |
| shader compiler and linker |
| |
| DEBUG_CATEGORY_APPLICATION_AMD Application-generated messages |
| |
| DEBUG_CATEGORY_OTHER_AMD Messages that do not fit in any of |
| the other categories |
| ---------------------------------------------------------------------------- |
| Table 2.12: Categories of debug messages. Each message is associated with |
| one of these categories. |
| |
| |
| Severity Level Token Suggested examples of messages |
| -------------------- ------------------------------ |
| |
| DEBUG_SEVERITY_HIGH_AMD Any GL error; any undefined behavior; |
| any GLSL or ARB shader compiler and |
| linker errors; |
| |
| DEBUG_SEVERITY_MEDIUM_AMD Severe performance warnings; GLSL |
| or ARB shader compiler and linker |
| warnings; use of currently deprecated |
| behavior |
| |
| DEBUG_SEVERITY_LOW_AMD Performance warnings from redundant |
| state changes |
| ---------------------------------------------------------------------------- |
| Table 2.13: Severity levels of messagse. Each debug 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 formatting of a message string is |
| left as implementation-dependent, although it should give a concise and |
| legible description of the message's purpose. Messages with different IDs |
| should also have sufficiently distinguishable string representations to |
| warrant their separation. |
| |
| 2.20.2 - Receiving Messages |
| |
| Applications can listen for messages by providing the GL with a callback |
| function pointer by calling: |
| |
| void DebugMessageCallbackAMD(DEBUGPROCAMD callback, |
| void* userParam); |
| |
| With <callback> storing the address of the callback function. This |
| function's signature must follow the type definition of DEBUGPROCAMD, and |
| its calling convention must be the same as the calling convention of GL |
| functions. 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 zero as the value of <callback> |
| clears the current callback and disables message output through callbacks. |
| Applications can specify user-specified data through the pointer |
| <userParam>. The context will store this pointer and will include it |
| as one of the parameters of each call to the callback function. The error |
| INVALID_OPERATION will be generated if this function is called for contexts |
| created without the debug flag. |
| |
| If the application has specified a callback function in a debug context, |
| the implementation will call that function whenever any unfiltered message |
| is generated. The ID, category, and severity of the message are specified |
| by the callback parameters <id>, <category> and <severity>, respectively. |
| The string representation of the message is stored in <message> and its length |
| (excluding the null-terminator) is stored in <length>. The parameter |
| <userParam> is the user-specified value that was passed when calling |
| DebugMessageCallbackAMD. The memory for <message> is allocated, owned and |
| released by the implementation, and should only be considered valid for |
| the duration of the callback function call. While it is allowed to |
| concurrently use multiple debug contexts with the same debug callback function, |
| note that it is the application's responsibility to ensure that any work that |
| occurs inside the debug callback function is thread-safe. Furthermore, |
| calling any GL or window layer function from within the callback function |
| results in undefined behavior. |
| |
| If no callback is set, then messages are instead stored in an internal |
| message log up to some maximum number of strings as defined by the |
| implementation-dependent constant MAX_DEBUG_LOGGED_MESSAGES_AMD. Each |
| context stores its own message log and will only store messages generated by |
| commands operating in that context. If the message log is full, then the |
| oldest messages will be removed from the log to make room for newer ones. |
| The application can query the number of messages currently in the log by |
| obtaining the value of DEBUG_LOGGED_MESSAGES_AMD, and can get the contents |
| of those messages using the command: |
| |
| uint GetDebugMessageLogAMD(uint count, |
| sizei logSize, |
| enum* categories, |
| enum* severities, |
| uint* ids, |
| sizei* lengths, |
| char* messageLog); |
| |
| This function will fetch as many messages as possible from the message |
| log up to <count> in order from oldest to newest, and will return the |
| number of messages fetched. Those messages that were fetched will be |
| removed from the log. The value of <count> must be greater than zero and |
| less than MAX_DEBUG_LOGGED_MESSAGES_AMD or otherwise the error |
| INVALID_VALUE will be generated. The value of <count> can be larger than |
| the actual number of messages currently in the log. If <messageLog> is not |
| a null pointer, then the string representations of all fetched messages will |
| be stored in the buffer <messageLog> and will be separated by null- |
| terminators. The maximum size of the buffer (including all null- |
| terminators) is denoted by <logSize>, and strings of messages within <count> |
| that do not fit in the buffer will not be fetched. If <logSize> is less |
| than zero, the error INVALID_VALUE will be generated. If <messageLog> |
| is a null pointer, then the value of <logSize> is ignored. The |
| categories, severity levels, IDs, and string representation lengths of all |
| (up to <count>) removed messages will be stored in the arrays <categories>, |
| <severities>, <ids>, and <lengths>, respectively. The counts stored in the |
| array <lengths> include the null-terminator of each string. Any and all of |
| the output arrays, including <messageLog>, are optional, and no data is returned |
| for those arrays that are specified with a null pointer. To simply delete up |
| to <count> messages from the message log and ignoring, the application can call |
| the function with null pointers for all output arrays. The error |
| INVALID_OPERATION will be generated by GetDebugMessageLogAMD if it is |
| called in a non-debug context. |
| |
| 2.20.3 - Controlling Debug Messages |
| |
| Applications can control which messages are generated by calling |
| |
| void DebugMessageEnableAMD(enum category, |
| enum severity, |
| sizei count, |
| const uint* ids, |
| boolean enabled); |
| |
| This command allows disabling or enabling generation of subsets of |
| messages. If <enabled> is TRUE, the referenced subset of messages |
| is enabled. If FALSE, then those messages are disabled. This |
| command can reference different subsets of messages by |
| varying its parameter values in the following ways: |
| |
| 1. To reference all messages, let <category>, <severity>, |
| and <count> all be zero. The value of <ids> is ignored |
| in this case. |
| |
| 2. To reference all messages across all categories with |
| a specific severity level, let <category> and <count> |
| be zero and let <severity> identify the severity level. |
| The value of <ids> is ignored in this case. |
| |
| 3. To reference all messages within a single category, let |
| <category> identify the referenced category and let |
| <severity> and <count> be zero. The value of <ids> is |
| ignored in this case. |
| |
| 4. To reference all messages within a single category and |
| at a specific severity level, let <category> identify the |
| category and <severity> identify the severity level, |
| and let <count> be zero. The value of <ids> is ignored |
| in this case. |
| |
| 5. To reference specific messages by ID within a single |
| category, let <category> identify the category, let |
| <severity> be zero, let <count> be greater than zero |
| and let <ids> identify the IDs of <count> messages within |
| the identified category. Operations on message IDs that |
| are not valid within the category are silently ignored. |
| |
| In all of the above cases, if <category> is non-zero and specifies |
| an invalid category, the error INVALID_ENUM is generated. |
| Similarly if <severity> is non-zero and is an invalid severity level, |
| the error INVALID_ENUM is generated. If <count> is less than |
| zero, the error INVALID_VALUE is generated. If the parameters do |
| not fall into one of the cases defined above, the error INVALID_VALUE |
| is generated. The error INVALID_OPERATION is generated if this |
| command is called in a non-debug context. |
| |
| Although messages are grouped into categories and severities, |
| and entire groups of messages can be turned off with a single |
| call, there is no explicit per-category or per-severity enabled state. |
| Instead the enabled state is stored individually for each message. |
| There is no difference between disabling a category of messages with a |
| single call, and enumerating all messages of that category and individually |
| disabling each of them by their ID. |
| |
| All messages of severity level DEBUG_SEVERITY_MEDIUM_AMD and |
| DEBUG_SEVERITY_HIGH_AMD in all categories are initially enabled, and |
| all messages at DEBUG_SEVERITY_LOW_AMD are initially disabled. |
| |
| 2.20.4 - Application Messages |
| |
| To easily support custom application timestamps, applications can inject |
| their own messages to the debug message stream through the command |
| |
| void DebugMessageInsertAMD(enum category, |
| enum severity, |
| uint id, |
| sizei length, |
| const char* buf); |
| |
| The value of <id> specifies the ID for the message and <severity> indicates |
| its severity level as defined by the application. If <severity> is not a |
| valid severity level, the error INVALID_ENUM will be generated. The value |
| of <category> must be DEBUG_CATEGORY_APPLICATION_AMD, or the error |
| INVALID_ENUM will be generated. The string <buf> contains the string |
| representation of the message. The parameter <length> contains the size of |
| the message's string representation, excluding the null-terminator. If |
| <length> is zero, then its value is derived from the string-length of <buf> |
| and <buf> must contain a null-terminated string. The error INVALID_VALUE |
| will be generated if <length> is less than zero or its derived value is |
| larger than or equal to MAX_DEBUG_MESSAGE_LENGTH_AMD. The error |
| INVALID_OPERATION will be generated if this function is called in a |
| non-debug context. |
| |
| Additions to the OpenGL / GLX / GLX Protocol Specifications |
| |
| None. |
| |
| Additions to the WGL Specification |
| |
| None. |
| |
| Errors |
| |
| The error INVALID_OPERATION will be generated by DebugMessageCallbackAMD if |
| the function is called in a non-debug context. |
| |
| The error INVALID_ENUM will be generated by DebugMessageEnableAMD if |
| <category> is non-zero and specifies an invalid category. |
| |
| The error INVALID_ENUM will be generated by DebugMessageEnableAMD if |
| <severity> is non-zero and an invalid severity level. |
| |
| The error INVALID_VALUE will be generated by DebugMessageEnableAMD if |
| if <count> is less than zero. |
| |
| The error INVALID_VALUE will be generated by DebugMessageEnableAMD if |
| if the combination of values for <category>, <severity> and <count> do not |
| fall within one of the accepted combinations for referencing a subset of |
| messages. |
| |
| The error INVALID_OPERATION will be generated by GetDebugMessageLogAMD if |
| it is called in a non-debug context. |
| |
| The error INVALID_VALUE will be generated by GetDebugMessageLogAMD if the |
| value of <count> is zero or greater than the value of |
| MAX_DEBUG_LOGGED_MESSAGES_AMD. |
| |
| The error INVALID_VALUE will be generated by GetDebugMessageLogAMD if |
| <logSize> is less than zero. |
| |
| The error INVALID_ENUM will be generated by DebugMessageInsertAMD if |
| <severity> is not a valid debug severity level. |
| |
| The error INVALID_ENUM will be generated by DebugMessageInsertAMD if the |
| value of <category> is not DEBUG_CATEGORY_APPLICATION_AMD. |
| |
| The error INVALID_VALUE will be generated by DebugMessageInsertAMD |
| if <length> is less than zero. |
| |
| The error INVALID_VALUE will be generated by DebugMessageInsertAMD |
| if <length> or its derived value is larger than |
| MAX_DEBUG_MESSAGE_LENGTH_AMD. |
| |
| The error INVALID_OPERATION will be generated by DebugMessageInsertAMD if |
| this function is called in a non-debug context. |
| |
| New State |
| Initial |
| Get Value Type Get Command Value Description Sec Attribute |
| -------------------------- ---- ----------- ----- ------------------------- ------ --------- |
| DEBUG_LOGGED_MESSAGES_AMD Z+ GetIntegerv 0 The number of messages 2.20.2 - |
| currently in the debug |
| message log |
| |
| New Implementation Dependent State |
| Minimum |
| Get Value Type Get Command Value Description Sec Attribute |
| -------------------------------- -- ----------- ----- ------------------------- ------ ---------- |
| MAX_DEBUG_MESSAGE_LENGTH_AMD Z+ GetIntegerv 80 The maximum length of a 2.20.2 - |
| debug message string |
| |
| MAX_DEBUG_LOGGED_MESSAGES_AMD Z+ GetIntegerv 1 The maximum number of 2.20.2 - |
| messages stored in the |
| debug message log |
| |
| Issues |
| |
| 01) Should we reserve tokens for arbitrary vendor-specific categories (e.g. |
| DEBUG_CATEGORY_VENDOR0)? |
| |
| RESOLVED: No. Since this is an AMD extension, there is no |
| reason to do this now in the current version. |
| |
| 02) Should we allow explicit controls for printing to stderr or through |
| OutputDebugString instead of the callback? |
| |
| RESOLVED: No. It is up to the application to setup this |
| behavior itself using the provided functionality. |
| |
| |
| 03) How do the different filtering rules interact? If a category is |
| filtered, but a message in that same category is set to be unfiltered by |
| ID or severity level, should that message still be filtered? If I |
| specifically filter a category and then unfilter all messages globally |
| with a later command, should that category still be filtered? |
| |
| RESOLVED: Message enable state is stored individually for each |
| message. There is no explicit group-wise enable state |
| or different ordered levels of "enabledness" in the |
| implied hierarchy of messages. Operations on groups |
| of messages affect all messages within |
| that group individually, and overwrite the previous |
| and individual state of those messages. |
| |
| 04) Should applications be allowed to insert their own messages through |
| a custom category? How would this be done? |
| |
| RESOLVED: Yes. A new category will be provided for application- |
| specific messages and an entry point will be provided to |
| write messages in that category. |
| |
| |
| |
| Revision History |
| |
| (v9, 2010-05-07, jkontti) |
| - Removed inconsistent language from New Tokens category for tokens |
| that are no longer accepted by DebugMessageEnableAMD since |
| revision v5. |
| - Cleaned up some language and formatting issues. |
| |
| (v8, 2010-04-09, jkontti) |
| - Renamed extension string from AMDX to AMD. |
| - Renamed new function, type and token suffixes from AMDX to AMD. |
| - No changes in functionality between AMDX and AMD versions. |
| |
| (v7, 2010-01-21, jkontti) |
| - Added user-specifiable parameter to debug message callback function |
| |
| (v6, 2010-01-15, jkontti) |
| - Updated contact section |
| - Updated contributor section |
| - Updated status section |
| - Updated enums |
| |
| (v5, 2009-09-17, jkontti) |
| - Message ID namespaces are now contained within categories instead of |
| being in a single global namespace |
| - Reworked DebugMessageEnable to allow disabling/enabling more |
| combinations of messages |
| - Resolved issue 01 |
| - Resolved issue 03 |
| |
| (v4, 2009-09-16, jkontti) |
| - Added category as a parameter to DebugMessageInsert for |
| future-proofing purposes |
| - Added missing errors to DebugMessageInsert and GetDebugMessageLog |
| - Added missing tokens to New Tokens |
| - Renamed DebugMessageFilter to DebugMessageEnable |
| |
| (v3, 2009-09-15, myoung) |
| - Cleaned up some language |
| - Added values using AMD reserved ranges. Values do not overlap so can |
| be re-used. |
| |
| (v2, 2009-09-15, jkontti) |
| - Application-generated messages |
| - More categories (window system, deprecation, profile, application) |
| |
| (v1, 2009-09-09, jkontti) |
| - Initial revision |