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