1Name 2 3 AMD_debug_output 4 5Name Strings 6 7 GL_AMD_debug_output 8 9Contact 10 11 Jaakko Konttinen (jaakko.konttinen 'at' amd.com) 12 13Contributors 14 15 Graham Sellers, AMD 16 Mark Young, AMD 17 Ahmet Oguz Akyuz, AMD 18 19Status 20 21 Experimental 22 23Version 24 25 Last Modified Date: May 7, 2010 26 Author Revision: 9 27 28Number 29 30 395 31 32Dependencies 33 34 OpenGL 1.1 is required. 35 36 WGL_ARB_create_context or GLX_ARB_create_context is required. 37 38 The extension is written against the OpenGL 3.0 specification. 39 40 This extension trivially interacts with ARB_vertex_program and 41 ARB_fragment_program. 42 43Overview 44 45 This extension allows the GL to notify applications when various 46 debug events occur in contexts that have been created with the debug 47 flag, as provided by WGL_ARB_create_context and GLX_ARB_create_context. 48 49 These events are represented in the form of enumerable messages with an 50 included human-readable translation. Examples of debug events include 51 incorrect use of the GL, warnings of undefined behavior, and performance 52 warnings. 53 54 A message is uniquely identified by a category and an implementation- 55 dependent ID within that category. Message categories are general and are 56 used to organize large groups of similar messages together. Examples of 57 categories include GL errors, performance warnings, and deprecated 58 functionality warnings. Each message is also assigned a severity level 59 that denotes roughly how "important" that message is in comparison to 60 other messages across all categories. For example, notification of a GL 61 error would have a higher severity than a performance warning due to 62 redundant state changes. 63 64 Messages are communicated to the application through an application-defined 65 callback function that is called by the GL implementation on each debug 66 message. The motivation for the callback routine is to free application 67 developers from actively having to query whether any GL error or other 68 debuggable event has happened after each call to a GL function. With a 69 callback, developers can keep their code free of debug checks, and only have 70 to react to messages as they occur. In order to support indirect rendering, 71 a message log is also provided that stores copies of recent messages until 72 they are actively queried. 73 74 To control the volume of debug output, messages can be disabled either 75 individually by ID, or entire groups of messages can be turned off based 76 on category or severity. 77 78 The only requirement on the minimum quantity and type of messages that 79 implementations of this extension must support is that a message must be 80 sent notifying the application whenever any GL error occurs. Any further 81 messages are left to the implementation. Implementations do not have 82 to output messages from all categories listed by this extension 83 in order to support this extension, and new categories can be added by 84 other extensions. 85 86 This extension places no restrictions or requirements on any additional 87 functionality provided by the debug context flag through other extensions. 88 89IP Status 90 91 No known IP claims. 92 93New Procedures and Functions 94 95 void DebugMessageEnableAMD(enum category, 96 enum severity, 97 sizei count, 98 const uint* ids, 99 boolean enabled); 100 101 void DebugMessageInsertAMD(enum category, 102 enum severity, 103 uint id, 104 sizei length, 105 const char* buf); 106 107 void DebugMessageCallbackAMD(DEBUGPROCAMD callback, 108 void* userParam); 109 110 uint GetDebugMessageLogAMD(uint count, 111 sizei bufsize, 112 enum* categories, 113 uint* severities, 114 uint* ids, 115 sizei* lengths, 116 char* message); 117 118New Types 119 120 The callback function that applications can define, and 121 is accepted by DebugMessageCallbackAMD, is defined as: 122 123 typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, 124 GLenum category, 125 GLenum severity, 126 GLsizei length, 127 const GLchar* message, 128 GLvoid* userParam); 129 130 Note that this function pointer is defined as having the 131 same calling convention as the GL functions. 132 133New Tokens 134 135 Tokens accepted by GetIntegerv: 136 137 MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143 138 MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 139 DEBUG_LOGGED_MESSAGES_AMD 0x9145 140 141 Tokens accepted by DebugMessageEnableAMD, GetDebugMessageLogAMD, 142 DebugMessageInsertAMD, and DEBUGPROCAMD callback function 143 for <severity>: 144 145 DEBUG_SEVERITY_HIGH_AMD 0x9146 146 DEBUG_SEVERITY_MEDIUM_AMD 0x9147 147 DEBUG_SEVERITY_LOW_AMD 0x9148 148 149 Tokens accepted by DebugMessageEnableAMD, GetDebugMessageLogAMD, 150 and DEBUGPROCAMD callback function for <category>: 151 152 DEBUG_CATEGORY_API_ERROR_AMD 0x9149 153 DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A 154 DEBUG_CATEGORY_DEPRECATION_AMD 0x914B 155 DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C 156 DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D 157 DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E 158 DEBUG_CATEGORY_APPLICATION_AMD 0x914F 159 DEBUG_CATEGORY_OTHER_AMD 0x9150 160 161Additions to Chapter 2 of the OpenGL 3.0 Specification (OpenGL Operation) 162 163 In section 2.5 - GL Errors: 164 Add to the end of the section (pg 19): "If an error is generated by a debug 165 GL context (Section 2.20), the context will send a message to the application 166 that a GL error has occurred. This message may contain more information 167 about the nature of the error." 168 169 After section 2.19 - Primitive Clipping: 170 Add new section: 2.20 - Debug Contexts 171 172 Application developers can obtain more information from the GL runtime using 173 a debug-enabled context. This information can include details about 174 GL errors, undefined behavior, implementation-dependent performance warnings, 175 or other useful hints. This information is communicated through the 176 generation of debug messages when GL commands are executed. The application 177 can choose to either actively query for these messages, or allow the GL to 178 call back to the application on each message via a function pointer. 179 180 2.20.1 - Debug Messages 181 182 A debug message is uniquely identified by its category and an unsigned 183 integer message ID within that category. The category must be one of the 184 symbolic constants listed in Table 2.12. Although every distinct message 185 must have a unique number within a category, there is no enforcement by this 186 extension for how GL implementations assign numbers to specific messages. 187 188 Each message also has a severity level that roughly describes its 189 significance across all categories. The severity level of a message is 190 one of the symbolic constants defined in Table 2.13. Because messages 191 can be disabled across all categories by severity level, this feature can 192 be used to quickly control the volume of debug output by the application. 193 194 Category Token Informs about 195 -------------- ------------- 196 DEBUG_CATEGORY_API_ERROR_AMD GL errors caused by invalid API use 197 198 DEBUG_CATEGORY_WINDOW_SYSTEM_AMD Errors and notices from the 199 windowing layer 200 201 DEBUG_CATEGORY_DEPRECATION_AMD Use of functionality that is either 202 deprecated or marked for future 203 deprecation 204 205 DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD Behavior undefined according to 206 specification 207 208 DEBUG_CATEGORY_PERFORMANCE_AMD Implementation-dependent performance 209 warnings 210 211 DEBUG_CATEGORY_SHADER_COMPILER_AMD Information from the GLSL or ARB 212 shader compiler and linker 213 214 DEBUG_CATEGORY_APPLICATION_AMD Application-generated messages 215 216 DEBUG_CATEGORY_OTHER_AMD Messages that do not fit in any of 217 the other categories 218 ---------------------------------------------------------------------------- 219 Table 2.12: Categories of debug messages. Each message is associated with 220 one of these categories. 221 222 223 Severity Level Token Suggested examples of messages 224 -------------------- ------------------------------ 225 226 DEBUG_SEVERITY_HIGH_AMD Any GL error; any undefined behavior; 227 any GLSL or ARB shader compiler and 228 linker errors; 229 230 DEBUG_SEVERITY_MEDIUM_AMD Severe performance warnings; GLSL 231 or ARB shader compiler and linker 232 warnings; use of currently deprecated 233 behavior 234 235 DEBUG_SEVERITY_LOW_AMD Performance warnings from redundant 236 state changes 237 ---------------------------------------------------------------------------- 238 Table 2.13: Severity levels of messagse. Each debug message is associated 239 with one of these severity levels. 240 241 242 Every message also has a null-terminated string representation that is used 243 to describe the message. The contents of the string can change slightly 244 between different instances of the same message (e.g. which parameter value 245 caused a specific GL error to occur). The formatting of a message string is 246 left as implementation-dependent, although it should give a concise and 247 legible description of the message's purpose. Messages with different IDs 248 should also have sufficiently distinguishable string representations to 249 warrant their separation. 250 251 2.20.2 - Receiving Messages 252 253 Applications can listen for messages by providing the GL with a callback 254 function pointer by calling: 255 256 void DebugMessageCallbackAMD(DEBUGPROCAMD callback, 257 void* userParam); 258 259 With <callback> storing the address of the callback function. This 260 function's signature must follow the type definition of DEBUGPROCAMD, and 261 its calling convention must be the same as the calling convention of GL 262 functions. Anything else will result in undefined behavior. Only one 263 debug callback can be specified for the current context, and further calls 264 overwrite the previous callback. Specifying zero as the value of <callback> 265 clears the current callback and disables message output through callbacks. 266 Applications can specify user-specified data through the pointer 267 <userParam>. The context will store this pointer and will include it 268 as one of the parameters of each call to the callback function. The error 269 INVALID_OPERATION will be generated if this function is called for contexts 270 created without the debug flag. 271 272 If the application has specified a callback function in a debug context, 273 the implementation will call that function whenever any unfiltered message 274 is generated. The ID, category, and severity of the message are specified 275 by the callback parameters <id>, <category> and <severity>, respectively. 276 The string representation of the message is stored in <message> and its length 277 (excluding the null-terminator) is stored in <length>. The parameter 278 <userParam> is the user-specified value that was passed when calling 279 DebugMessageCallbackAMD. The memory for <message> is allocated, owned and 280 released by the implementation, and should only be considered valid for 281 the duration of the callback function call. While it is allowed to 282 concurrently use multiple debug contexts with the same debug callback function, 283 note that it is the application's responsibility to ensure that any work that 284 occurs inside the debug callback function is thread-safe. Furthermore, 285 calling any GL or window layer function from within the callback function 286 results in undefined behavior. 287 288 If no callback is set, then messages are instead stored in an internal 289 message log up to some maximum number of strings as defined by the 290 implementation-dependent constant MAX_DEBUG_LOGGED_MESSAGES_AMD. Each 291 context stores its own message log and will only store messages generated by 292 commands operating in that context. If the message log is full, then the 293 oldest messages will be removed from the log to make room for newer ones. 294 The application can query the number of messages currently in the log by 295 obtaining the value of DEBUG_LOGGED_MESSAGES_AMD, and can get the contents 296 of those messages using the command: 297 298 uint GetDebugMessageLogAMD(uint count, 299 sizei logSize, 300 enum* categories, 301 enum* severities, 302 uint* ids, 303 sizei* lengths, 304 char* messageLog); 305 306 This function will fetch as many messages as possible from the message 307 log up to <count> in order from oldest to newest, and will return the 308 number of messages fetched. Those messages that were fetched will be 309 removed from the log. The value of <count> must be greater than zero and 310 less than MAX_DEBUG_LOGGED_MESSAGES_AMD or otherwise the error 311 INVALID_VALUE will be generated. The value of <count> can be larger than 312 the actual number of messages currently in the log. If <messageLog> is not 313 a null pointer, then the string representations of all fetched messages will 314 be stored in the buffer <messageLog> and will be separated by null- 315 terminators. The maximum size of the buffer (including all null- 316 terminators) is denoted by <logSize>, and strings of messages within <count> 317 that do not fit in the buffer will not be fetched. If <logSize> is less 318 than zero, the error INVALID_VALUE will be generated. If <messageLog> 319 is a null pointer, then the value of <logSize> is ignored. The 320 categories, severity levels, IDs, and string representation lengths of all 321 (up to <count>) removed messages will be stored in the arrays <categories>, 322 <severities>, <ids>, and <lengths>, respectively. The counts stored in the 323 array <lengths> include the null-terminator of each string. Any and all of 324 the output arrays, including <messageLog>, are optional, and no data is returned 325 for those arrays that are specified with a null pointer. To simply delete up 326 to <count> messages from the message log and ignoring, the application can call 327 the function with null pointers for all output arrays. The error 328 INVALID_OPERATION will be generated by GetDebugMessageLogAMD if it is 329 called in a non-debug context. 330 331 2.20.3 - Controlling Debug Messages 332 333 Applications can control which messages are generated by calling 334 335 void DebugMessageEnableAMD(enum category, 336 enum severity, 337 sizei count, 338 const uint* ids, 339 boolean enabled); 340 341 This command allows disabling or enabling generation of subsets of 342 messages. If <enabled> is TRUE, the referenced subset of messages 343 is enabled. If FALSE, then those messages are disabled. This 344 command can reference different subsets of messages by 345 varying its parameter values in the following ways: 346 347 1. To reference all messages, let <category>, <severity>, 348 and <count> all be zero. The value of <ids> is ignored 349 in this case. 350 351 2. To reference all messages across all categories with 352 a specific severity level, let <category> and <count> 353 be zero and let <severity> identify the severity level. 354 The value of <ids> is ignored in this case. 355 356 3. To reference all messages within a single category, let 357 <category> identify the referenced category and let 358 <severity> and <count> be zero. The value of <ids> is 359 ignored in this case. 360 361 4. To reference all messages within a single category and 362 at a specific severity level, let <category> identify the 363 category and <severity> identify the severity level, 364 and let <count> be zero. The value of <ids> is ignored 365 in this case. 366 367 5. To reference specific messages by ID within a single 368 category, let <category> identify the category, let 369 <severity> be zero, let <count> be greater than zero 370 and let <ids> identify the IDs of <count> messages within 371 the identified category. Operations on message IDs that 372 are not valid within the category are silently ignored. 373 374 In all of the above cases, if <category> is non-zero and specifies 375 an invalid category, the error INVALID_ENUM is generated. 376 Similarly if <severity> is non-zero and is an invalid severity level, 377 the error INVALID_ENUM is generated. If <count> is less than 378 zero, the error INVALID_VALUE is generated. If the parameters do 379 not fall into one of the cases defined above, the error INVALID_VALUE 380 is generated. The error INVALID_OPERATION is generated if this 381 command is called in a non-debug context. 382 383 Although messages are grouped into categories and severities, 384 and entire groups of messages can be turned off with a single 385 call, there is no explicit per-category or per-severity enabled state. 386 Instead the enabled state is stored individually for each message. 387 There is no difference between disabling a category of messages with a 388 single call, and enumerating all messages of that category and individually 389 disabling each of them by their ID. 390 391 All messages of severity level DEBUG_SEVERITY_MEDIUM_AMD and 392 DEBUG_SEVERITY_HIGH_AMD in all categories are initially enabled, and 393 all messages at DEBUG_SEVERITY_LOW_AMD are initially disabled. 394 395 2.20.4 - Application Messages 396 397 To easily support custom application timestamps, applications can inject 398 their own messages to the debug message stream through the command 399 400 void DebugMessageInsertAMD(enum category, 401 enum severity, 402 uint id, 403 sizei length, 404 const char* buf); 405 406 The value of <id> specifies the ID for the message and <severity> indicates 407 its severity level as defined by the application. If <severity> is not a 408 valid severity level, the error INVALID_ENUM will be generated. The value 409 of <category> must be DEBUG_CATEGORY_APPLICATION_AMD, or the error 410 INVALID_ENUM will be generated. The string <buf> contains the string 411 representation of the message. The parameter <length> contains the size of 412 the message's string representation, excluding the null-terminator. If 413 <length> is zero, then its value is derived from the string-length of <buf> 414 and <buf> must contain a null-terminated string. The error INVALID_VALUE 415 will be generated if <length> is less than zero or its derived value is 416 larger than or equal to MAX_DEBUG_MESSAGE_LENGTH_AMD. The error 417 INVALID_OPERATION will be generated if this function is called in a 418 non-debug context. 419 420Additions to the OpenGL / GLX / GLX Protocol Specifications 421 422 None. 423 424Additions to the WGL Specification 425 426 None. 427 428Errors 429 430 The error INVALID_OPERATION will be generated by DebugMessageCallbackAMD if 431 the function is called in a non-debug context. 432 433 The error INVALID_ENUM will be generated by DebugMessageEnableAMD if 434 <category> is non-zero and specifies an invalid category. 435 436 The error INVALID_ENUM will be generated by DebugMessageEnableAMD if 437 <severity> is non-zero and an invalid severity level. 438 439 The error INVALID_VALUE will be generated by DebugMessageEnableAMD if 440 if <count> is less than zero. 441 442 The error INVALID_VALUE will be generated by DebugMessageEnableAMD if 443 if the combination of values for <category>, <severity> and <count> do not 444 fall within one of the accepted combinations for referencing a subset of 445 messages. 446 447 The error INVALID_OPERATION will be generated by GetDebugMessageLogAMD if 448 it is called in a non-debug context. 449 450 The error INVALID_VALUE will be generated by GetDebugMessageLogAMD if the 451 value of <count> is zero or greater than the value of 452 MAX_DEBUG_LOGGED_MESSAGES_AMD. 453 454 The error INVALID_VALUE will be generated by GetDebugMessageLogAMD if 455 <logSize> is less than zero. 456 457 The error INVALID_ENUM will be generated by DebugMessageInsertAMD if 458 <severity> is not a valid debug severity level. 459 460 The error INVALID_ENUM will be generated by DebugMessageInsertAMD if the 461 value of <category> is not DEBUG_CATEGORY_APPLICATION_AMD. 462 463 The error INVALID_VALUE will be generated by DebugMessageInsertAMD 464 if <length> is less than zero. 465 466 The error INVALID_VALUE will be generated by DebugMessageInsertAMD 467 if <length> or its derived value is larger than 468 MAX_DEBUG_MESSAGE_LENGTH_AMD. 469 470 The error INVALID_OPERATION will be generated by DebugMessageInsertAMD if 471 this function is called in a non-debug context. 472 473New State 474 Initial 475 Get Value Type Get Command Value Description Sec Attribute 476 -------------------------- ---- ----------- ----- ------------------------- ------ --------- 477 DEBUG_LOGGED_MESSAGES_AMD Z+ GetIntegerv 0 The number of messages 2.20.2 - 478 currently in the debug 479 message log 480 481New Implementation Dependent State 482 Minimum 483 Get Value Type Get Command Value Description Sec Attribute 484 -------------------------------- -- ----------- ----- ------------------------- ------ ---------- 485 MAX_DEBUG_MESSAGE_LENGTH_AMD Z+ GetIntegerv 80 The maximum length of a 2.20.2 - 486 debug message string 487 488 MAX_DEBUG_LOGGED_MESSAGES_AMD Z+ GetIntegerv 1 The maximum number of 2.20.2 - 489 messages stored in the 490 debug message log 491 492Issues 493 494 01) Should we reserve tokens for arbitrary vendor-specific categories (e.g. 495 DEBUG_CATEGORY_VENDOR0)? 496 497 RESOLVED: No. Since this is an AMD extension, there is no 498 reason to do this now in the current version. 499 500 02) Should we allow explicit controls for printing to stderr or through 501 OutputDebugString instead of the callback? 502 503 RESOLVED: No. It is up to the application to setup this 504 behavior itself using the provided functionality. 505 506 507 03) How do the different filtering rules interact? If a category is 508 filtered, but a message in that same category is set to be unfiltered by 509 ID or severity level, should that message still be filtered? If I 510 specifically filter a category and then unfilter all messages globally 511 with a later command, should that category still be filtered? 512 513 RESOLVED: Message enable state is stored individually for each 514 message. There is no explicit group-wise enable state 515 or different ordered levels of "enabledness" in the 516 implied hierarchy of messages. Operations on groups 517 of messages affect all messages within 518 that group individually, and overwrite the previous 519 and individual state of those messages. 520 521 04) Should applications be allowed to insert their own messages through 522 a custom category? How would this be done? 523 524 RESOLVED: Yes. A new category will be provided for application- 525 specific messages and an entry point will be provided to 526 write messages in that category. 527 528 529 530Revision History 531 532 (v9, 2010-05-07, jkontti) 533 - Removed inconsistent language from New Tokens category for tokens 534 that are no longer accepted by DebugMessageEnableAMD since 535 revision v5. 536 - Cleaned up some language and formatting issues. 537 538 (v8, 2010-04-09, jkontti) 539 - Renamed extension string from AMDX to AMD. 540 - Renamed new function, type and token suffixes from AMDX to AMD. 541 - No changes in functionality between AMDX and AMD versions. 542 543 (v7, 2010-01-21, jkontti) 544 - Added user-specifiable parameter to debug message callback function 545 546 (v6, 2010-01-15, jkontti) 547 - Updated contact section 548 - Updated contributor section 549 - Updated status section 550 - Updated enums 551 552 (v5, 2009-09-17, jkontti) 553 - Message ID namespaces are now contained within categories instead of 554 being in a single global namespace 555 - Reworked DebugMessageEnable to allow disabling/enabling more 556 combinations of messages 557 - Resolved issue 01 558 - Resolved issue 03 559 560 (v4, 2009-09-16, jkontti) 561 - Added category as a parameter to DebugMessageInsert for 562 future-proofing purposes 563 - Added missing errors to DebugMessageInsert and GetDebugMessageLog 564 - Added missing tokens to New Tokens 565 - Renamed DebugMessageFilter to DebugMessageEnable 566 567 (v3, 2009-09-15, myoung) 568 - Cleaned up some language 569 - Added values using AMD reserved ranges. Values do not overlap so can 570 be re-used. 571 572 (v2, 2009-09-15, jkontti) 573 - Application-generated messages 574 - More categories (window system, deprecation, profile, application) 575 576 (v1, 2009-09-09, jkontti) 577 - Initial revision 578