1Name 2 3 MESA_program_debug 4 5Name Strings 6 7 GL_MESA_program_debug 8 9Contact 10 11 Brian Paul (brian.paul 'at' tungstengraphics.com) 12 13Status 14 15 XXX - Not complete yet!!! 16 17Version 18 19 Last Modified Date: July 20, 2003 20 Author Revision: 1.0 21 22Number 23 24 TBD 25 26Dependencies 27 28 OpenGL 1.4 is required 29 The extension is written against the OpenGL 1.4 specification. 30 ARB_vertex_program or ARB_fragment_program or NV_vertex_program 31 or NV_fragment_program is required. 32 33Overview 34 35 The extension provides facilities for implementing debuggers for 36 vertex and fragment programs. 37 38 The concept is that vertex and fragment program debuggers will be 39 implemented outside of the GL as a utility package. This extension 40 only provides the minimal hooks required to implement a debugger. 41 42 There are facilities to do the following: 43 1. Have the GL call a user-specified function prior to executing 44 each vertex or fragment instruction. 45 2. Query the current program string's execution position. 46 3. Query the current values of intermediate program values. 47 48 The main feature is the ProgramCallbackMESA function. It allows the 49 user to register a callback function with the GL. The callback will 50 be called prior to executing each vertex or fragment program instruction. 51 52 From within the callback, the user may issue Get* commands to 53 query current GL state. The GetProgramRegisterfvMESA function allows 54 current program values to be queried (such as temporaries, input 55 attributes, and result registers). 56 57 There are flags for enabling/disabling the program callbacks. 58 59 The current execution position (as an offset from the start of the 60 program string) can be queried with 61 GetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos) or 62 GetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos). 63 64 65IP Status 66 67 None 68 69Issues 70 71 1. Is this the right model for a debugger? 72 73 It seems prudent to minimize the scope of this extension and leave 74 it up to the developer (or developer community) to write debuggers 75 that layer on top of this extension. 76 77 If the debugger were fully implemented within the GL it's not 78 clear how terminal and GUI-based interfaces would work, for 79 example. 80 81 2. There aren't any other extensions that register callbacks with 82 the GL. Isn't there another solution? 83 84 If we want to be able to single-step through vertex/fragment 85 programs I don't see another way to do it. 86 87 3. How do we prevent the user from doing something crazy in the 88 callback function, like trying to call glBegin (leading to 89 recursion)? 90 91 The rule is that the callback function can only issue glGet*() 92 functions and no other GL commands. It could be difficult to 93 enforce this, however. Therefore, calling any non-get GL 94 command from within the callback will result in undefined 95 results. 96 97 4. Is this extension amenable to hardware implementation? 98 99 Hopefully, but if not, the GL implementation will have to fall 100 back to a software path when debugging. This may be acceptable 101 for debugging. 102 103 5. What's the <data> parameter to ProgramCallbackMESA for? 104 105 It's a common programming practice to associate a user-supplied 106 value with callback functions. 107 108 6. Debuggers often allow one to modify intermediate program values, 109 then continue. Does this extension support that? 110 111 No. 112 113 114New Procedures and Functions (and datatypes) 115 116 typedef void (*programcallbackMESA)(enum target, void *data) 117 118 void ProgramCallbackMESA(enum target, programcallbackMESA callback, 119 void *data) 120 121 void GetProgramRegisterfvMESA(enum target, sizei len, 122 const ubyte *registerName, float *v) 123 124New Tokens 125 126 Accepted by the <cap> parameter of Enable, Disable, IsEnabled, 127 GetBooleanv, GetDoublev, GetFloatv and GetIntegerv: 128 129 FRAGMENT_PROGRAM_CALLBACK_MESA 0x8bb1 130 VERTEX_PROGRAM_CALLBACK_MESA 0x8bb4 131 132 Accepted by the <pname> parameter GetBooleanv, GetDoublev, 133 GetFloatv and GetIntegerv: 134 135 FRAGMENT_PROGRAM_POSITION_MESA 0x8bb0 136 VERTEX_PROGRAM_POSITION_MESA 0x8bb4 137 138 Accepted by the <pname> parameter of GetPointerv: 139 140 FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA 0x8bb2 141 FRAGMENT_PROGRAM_CALLBACK_DATA_MESA 0x8bb3 142 VERTEX_PROGRAM_CALLBACK_FUNC_MESA 0x8bb6 143 VERTEX_PROGRAM_CALLBACK_DATA_MESA 0x8bb7 144 145Additions to Chapter 2 of the OpenGL 1.4 Specification (OpenGL Operation) 146 147 None. 148 149Additions to Chapter 3 of the OpenGL 1.4 Specification (Rasterization) 150 151 None. 152 153Additions to Chapter 4 of the OpenGL 1.4 Specification (Per-Fragment 154Operations and the Frame Buffer) 155 156 None. 157 158Additions to Chapter 5 of the OpenGL 1.4 Specification (Special Functions) 159 160 In section 5.4 "Display Lists", page 202, add the following command 161 to the list of those that are not compiled into display lists: 162 163 ProgramCallbackMESA. 164 165 166 Add a new section 5.7 "Callback Functions" 167 168 The function 169 170 void ProgramCallbackMESA(enum target, programcallbackMESA callback, 171 void *data) 172 173 registers a user-defined callback function with the GL. <target> 174 may be FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB. The enabled 175 callback functions registered with these targets will be called 176 prior to executing each instruction in the current fragment or 177 vertex program, respectively. The callbacks are enabled and 178 disabled by calling Enable or Disable with <cap> 179 FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB. 180 181 The callback function's signature must match the typedef 182 183 typedef void (*programcallbackMESA)(enum target, void *data) 184 185 When the callback function is called, <target> will either be 186 FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB to indicate which 187 program is currently executing and <data> will be the value 188 specified when ProgramCallbackMESA was called. 189 190 From within the callback function, only the following GL commands 191 may be called: 192 193 GetBooleanv 194 GetDoublev 195 GetFloatv 196 GetIntegerv 197 GetProgramLocalParameter 198 GetProgramEnvParameter 199 GetProgramRegisterfvMESA 200 GetProgramivARB 201 GetProgramStringARB 202 GetError 203 204 Calling any other command from within the callback results in 205 undefined behaviour. 206 207 208Additions to Chapter 6 of the OpenGL 1.4 Specification (State and 209State Requests) 210 211 Add a new section 6.1.3 "Program Value Queries": 212 213 The command 214 215 void GetProgramRegisterfvMESA(enum target, sizei len, 216 const ubyte *registerName, 217 float *v) 218 219 Is used to query the value of program variables and registers 220 during program execution. GetProgramRegisterfvMESA may only be 221 called from within a callback function registered with 222 ProgramCallbackMESA. 223 224 <registerName> and <len> specify the name a variable, input 225 attribute, temporary, or result register in the program string. 226 The current value of the named variable is returned as four 227 values in <v>. If <name> doesn't exist in the program string, 228 the error INVALID_OPERATION is generated. 229 230Additions to Appendix A of the OpenGL 1.4 Specification (Invariance) 231 232 None. 233 234Additions to the AGL/GLX/WGL Specifications 235 236 None. 237 238GLX Protocol 239 240 XXX TBD 241 242Dependencies on NV_vertex_program and NV_fragment_program 243 244 If NV_vertex_program and/or NV_fragment_program are supported, 245 vertex and/or fragment programs defined by those extensions may 246 be debugged as well. Register queries will use the syntax used 247 by those extensions (i.e. "v[X]" to query vertex attributes, 248 "o[X]" for vertex outputs, etc.) 249 250Errors 251 252 INVALID_OPERATION is generated if ProgramCallbackMESA is called 253 between Begin and End. 254 255 INVALID_ENUM is generated by ProgramCallbackMESA if <target> is not 256 a supported vertex or fragment program type. 257 258 Note: INVALID_OPERAION IS NOT generated by GetProgramRegisterfvMESA, 259 GetBooleanv, GetDoublev, GetFloatv, or GetIntegerv if called between 260 Begin and End when a vertex or fragment program is currently executing. 261 262 INVALID_ENUM is generated by ProgramCallbackMESA, 263 GetProgramRegisterfvMESA if <target> is not a program target supported 264 by ARB_vertex_program, ARB_fragment_program (or NV_vertex_program or 265 NV_fragment_program). 266 267 INVALID_VALUE is generated by GetProgramRegisterfvMESA if <registerName> 268 does not name a known program register or variable. 269 270 INVALID_OPERATION is generated by GetProgramRegisterfvMESA when a 271 register query is attempted for a program target that's not currently 272 being executed. 273 274 275New State 276 277 XXX finish 278 279(table 6.N, p. ###) 280 Initial 281 Get Value Type Get Command Value Description Sec. Attribute 282 --------- ---- ----------- ----- ----------- ---- --------- 283 FRAGMENT_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable 284 VERTEX_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable 285 FRAGMENT_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX - 286 VERTEX_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX - 287 FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX - 288 VERTEX_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX - 289 FRAGMENT_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX - 290 VERTEX_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX - 291 292 XXX more? 293 294New Implementation Dependent State 295 296 None. 297 298Revision History 299 300 8 July 2003 301 Initial draft. (Brian Paul) 302 11 July 2003 303 Second draft. (Brian Paul) 304 20 July 2003 305 Third draft. Lots of fundamental changes. (Brian Paul) 306 23 July 2003 307 Added chapter 5 and 6 spec language. (Brian Paul) 308 309Example Usage 310 311 The following is a very simple example of how this extension may 312 be used to print the values of R0, R1, R2 and R3 while executing 313 vertex programs. 314 315 316 /* This is called by the GL when the vertex program is executing. 317 * We can only make glGet* calls from within this function! 318 */ 319 void DebugCallback(GLenum target, GLvoid *data) 320 { 321 GLint pos; 322 GLuint i; 323 324 /* Get PC and current instruction string */ 325 glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_ARB, &pos); 326 327 printf("Current position: %d\n", pos); 328 329 printf("Current temporary registers:\n"); 330 for (i = 0; i < 4; i++) { 331 GLfloat v[4]; 332 char s[10]; 333 sprintf(s, "R%d", i); 334 glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_ARB, strlen(s), s, v); 335 printf("R%d = %g, %g, %g, %g\n", i, v[0], v[1], v[2], v[3]); 336 } 337 } 338 339 340 /* 341 * elsewhere... 342 */ 343 344 /* Register our debugger callback function */ 345 glProgramCallbackMESA(GL_VERTEX_PROGRAM_ARB, DebugCallback, NULL); 346 glEnable(GL_VERTEX_PROGRAM_CALLBACK_MESA); 347 348 /* define/bind a vertex program */ 349 350 glEnable(GL_VERTEX_PROGRAM); 351 352 /* render something */ 353 glBegin(GL_POINTS); 354 glVertex2f(0, 0); 355 glEnd(); 356 357