1848b8605SmrgName 2848b8605Smrg 3848b8605Smrg MESA_program_debug 4848b8605Smrg 5848b8605SmrgName Strings 6848b8605Smrg 7848b8605Smrg GL_MESA_program_debug 8848b8605Smrg 9848b8605SmrgContact 10848b8605Smrg 11848b8605Smrg Brian Paul (brian.paul 'at' tungstengraphics.com) 12848b8605Smrg 13848b8605SmrgStatus 14848b8605Smrg 15b8e80941Smrg Obsolete. 16848b8605Smrg 17848b8605SmrgVersion 18848b8605Smrg 19848b8605Smrg Last Modified Date: July 20, 2003 20848b8605Smrg Author Revision: 1.0 21848b8605Smrg 22848b8605SmrgNumber 23848b8605Smrg 24848b8605Smrg TBD 25848b8605Smrg 26848b8605SmrgDependencies 27848b8605Smrg 28848b8605Smrg OpenGL 1.4 is required 29848b8605Smrg The extension is written against the OpenGL 1.4 specification. 30848b8605Smrg ARB_vertex_program or ARB_fragment_program or NV_vertex_program 31848b8605Smrg or NV_fragment_program is required. 32848b8605Smrg 33848b8605SmrgOverview 34848b8605Smrg 35848b8605Smrg The extension provides facilities for implementing debuggers for 36848b8605Smrg vertex and fragment programs. 37848b8605Smrg 38848b8605Smrg The concept is that vertex and fragment program debuggers will be 39848b8605Smrg implemented outside of the GL as a utility package. This extension 40848b8605Smrg only provides the minimal hooks required to implement a debugger. 41848b8605Smrg 42848b8605Smrg There are facilities to do the following: 43848b8605Smrg 1. Have the GL call a user-specified function prior to executing 44848b8605Smrg each vertex or fragment instruction. 45848b8605Smrg 2. Query the current program string's execution position. 46848b8605Smrg 3. Query the current values of intermediate program values. 47848b8605Smrg 48848b8605Smrg The main feature is the ProgramCallbackMESA function. It allows the 49848b8605Smrg user to register a callback function with the GL. The callback will 50848b8605Smrg be called prior to executing each vertex or fragment program instruction. 51848b8605Smrg 52848b8605Smrg From within the callback, the user may issue Get* commands to 53848b8605Smrg query current GL state. The GetProgramRegisterfvMESA function allows 54848b8605Smrg current program values to be queried (such as temporaries, input 55848b8605Smrg attributes, and result registers). 56848b8605Smrg 57848b8605Smrg There are flags for enabling/disabling the program callbacks. 58848b8605Smrg 59848b8605Smrg The current execution position (as an offset from the start of the 60848b8605Smrg program string) can be queried with 61848b8605Smrg GetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos) or 62848b8605Smrg GetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos). 63848b8605Smrg 64848b8605Smrg 65848b8605SmrgIP Status 66848b8605Smrg 67848b8605Smrg None 68848b8605Smrg 69848b8605SmrgIssues 70848b8605Smrg 71848b8605Smrg 1. Is this the right model for a debugger? 72848b8605Smrg 73848b8605Smrg It seems prudent to minimize the scope of this extension and leave 74848b8605Smrg it up to the developer (or developer community) to write debuggers 75848b8605Smrg that layer on top of this extension. 76848b8605Smrg 77848b8605Smrg If the debugger were fully implemented within the GL it's not 78848b8605Smrg clear how terminal and GUI-based interfaces would work, for 79848b8605Smrg example. 80848b8605Smrg 81848b8605Smrg 2. There aren't any other extensions that register callbacks with 82848b8605Smrg the GL. Isn't there another solution? 83848b8605Smrg 84848b8605Smrg If we want to be able to single-step through vertex/fragment 85848b8605Smrg programs I don't see another way to do it. 86848b8605Smrg 87848b8605Smrg 3. How do we prevent the user from doing something crazy in the 88848b8605Smrg callback function, like trying to call glBegin (leading to 89848b8605Smrg recursion)? 90848b8605Smrg 91848b8605Smrg The rule is that the callback function can only issue glGet*() 92848b8605Smrg functions and no other GL commands. It could be difficult to 93848b8605Smrg enforce this, however. Therefore, calling any non-get GL 94848b8605Smrg command from within the callback will result in undefined 95848b8605Smrg results. 96848b8605Smrg 97848b8605Smrg 4. Is this extension amenable to hardware implementation? 98848b8605Smrg 99848b8605Smrg Hopefully, but if not, the GL implementation will have to fall 100848b8605Smrg back to a software path when debugging. This may be acceptable 101848b8605Smrg for debugging. 102848b8605Smrg 103848b8605Smrg 5. What's the <data> parameter to ProgramCallbackMESA for? 104848b8605Smrg 105848b8605Smrg It's a common programming practice to associate a user-supplied 106848b8605Smrg value with callback functions. 107848b8605Smrg 108848b8605Smrg 6. Debuggers often allow one to modify intermediate program values, 109848b8605Smrg then continue. Does this extension support that? 110848b8605Smrg 111848b8605Smrg No. 112848b8605Smrg 113848b8605Smrg 114848b8605SmrgNew Procedures and Functions (and datatypes) 115848b8605Smrg 116848b8605Smrg typedef void (*programcallbackMESA)(enum target, void *data) 117848b8605Smrg 118848b8605Smrg void ProgramCallbackMESA(enum target, programcallbackMESA callback, 119848b8605Smrg void *data) 120848b8605Smrg 121848b8605Smrg void GetProgramRegisterfvMESA(enum target, sizei len, 122848b8605Smrg const ubyte *registerName, float *v) 123848b8605Smrg 124848b8605SmrgNew Tokens 125848b8605Smrg 126848b8605Smrg Accepted by the <cap> parameter of Enable, Disable, IsEnabled, 127848b8605Smrg GetBooleanv, GetDoublev, GetFloatv and GetIntegerv: 128848b8605Smrg 129848b8605Smrg FRAGMENT_PROGRAM_CALLBACK_MESA 0x8bb1 130848b8605Smrg VERTEX_PROGRAM_CALLBACK_MESA 0x8bb4 131848b8605Smrg 132848b8605Smrg Accepted by the <pname> parameter GetBooleanv, GetDoublev, 133848b8605Smrg GetFloatv and GetIntegerv: 134848b8605Smrg 135848b8605Smrg FRAGMENT_PROGRAM_POSITION_MESA 0x8bb0 136b8e80941Smrg VERTEX_PROGRAM_POSITION_MESA 0x8bb5 137848b8605Smrg 138848b8605Smrg Accepted by the <pname> parameter of GetPointerv: 139848b8605Smrg 140848b8605Smrg FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA 0x8bb2 141848b8605Smrg FRAGMENT_PROGRAM_CALLBACK_DATA_MESA 0x8bb3 142848b8605Smrg VERTEX_PROGRAM_CALLBACK_FUNC_MESA 0x8bb6 143848b8605Smrg VERTEX_PROGRAM_CALLBACK_DATA_MESA 0x8bb7 144848b8605Smrg 145848b8605SmrgAdditions to Chapter 2 of the OpenGL 1.4 Specification (OpenGL Operation) 146848b8605Smrg 147848b8605Smrg None. 148848b8605Smrg 149848b8605SmrgAdditions to Chapter 3 of the OpenGL 1.4 Specification (Rasterization) 150848b8605Smrg 151848b8605Smrg None. 152848b8605Smrg 153848b8605SmrgAdditions to Chapter 4 of the OpenGL 1.4 Specification (Per-Fragment 154848b8605SmrgOperations and the Frame Buffer) 155848b8605Smrg 156848b8605Smrg None. 157848b8605Smrg 158848b8605SmrgAdditions to Chapter 5 of the OpenGL 1.4 Specification (Special Functions) 159848b8605Smrg 160848b8605Smrg In section 5.4 "Display Lists", page 202, add the following command 161848b8605Smrg to the list of those that are not compiled into display lists: 162848b8605Smrg 163848b8605Smrg ProgramCallbackMESA. 164848b8605Smrg 165848b8605Smrg 166848b8605Smrg Add a new section 5.7 "Callback Functions" 167848b8605Smrg 168848b8605Smrg The function 169848b8605Smrg 170848b8605Smrg void ProgramCallbackMESA(enum target, programcallbackMESA callback, 171848b8605Smrg void *data) 172848b8605Smrg 173848b8605Smrg registers a user-defined callback function with the GL. <target> 174848b8605Smrg may be FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB. The enabled 175848b8605Smrg callback functions registered with these targets will be called 176848b8605Smrg prior to executing each instruction in the current fragment or 177848b8605Smrg vertex program, respectively. The callbacks are enabled and 178848b8605Smrg disabled by calling Enable or Disable with <cap> 179848b8605Smrg FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB. 180848b8605Smrg 181848b8605Smrg The callback function's signature must match the typedef 182848b8605Smrg 183848b8605Smrg typedef void (*programcallbackMESA)(enum target, void *data) 184848b8605Smrg 185848b8605Smrg When the callback function is called, <target> will either be 186848b8605Smrg FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB to indicate which 187848b8605Smrg program is currently executing and <data> will be the value 188848b8605Smrg specified when ProgramCallbackMESA was called. 189848b8605Smrg 190848b8605Smrg From within the callback function, only the following GL commands 191848b8605Smrg may be called: 192848b8605Smrg 193848b8605Smrg GetBooleanv 194848b8605Smrg GetDoublev 195848b8605Smrg GetFloatv 196848b8605Smrg GetIntegerv 197848b8605Smrg GetProgramLocalParameter 198848b8605Smrg GetProgramEnvParameter 199848b8605Smrg GetProgramRegisterfvMESA 200848b8605Smrg GetProgramivARB 201848b8605Smrg GetProgramStringARB 202848b8605Smrg GetError 203848b8605Smrg 204848b8605Smrg Calling any other command from within the callback results in 205848b8605Smrg undefined behaviour. 206848b8605Smrg 207848b8605Smrg 208848b8605SmrgAdditions to Chapter 6 of the OpenGL 1.4 Specification (State and 209848b8605SmrgState Requests) 210848b8605Smrg 211848b8605Smrg Add a new section 6.1.3 "Program Value Queries": 212848b8605Smrg 213848b8605Smrg The command 214848b8605Smrg 215848b8605Smrg void GetProgramRegisterfvMESA(enum target, sizei len, 216848b8605Smrg const ubyte *registerName, 217848b8605Smrg float *v) 218848b8605Smrg 219848b8605Smrg Is used to query the value of program variables and registers 220848b8605Smrg during program execution. GetProgramRegisterfvMESA may only be 221848b8605Smrg called from within a callback function registered with 222848b8605Smrg ProgramCallbackMESA. 223848b8605Smrg 224848b8605Smrg <registerName> and <len> specify the name a variable, input 225848b8605Smrg attribute, temporary, or result register in the program string. 226848b8605Smrg The current value of the named variable is returned as four 227848b8605Smrg values in <v>. If <name> doesn't exist in the program string, 228848b8605Smrg the error INVALID_OPERATION is generated. 229848b8605Smrg 230848b8605SmrgAdditions to Appendix A of the OpenGL 1.4 Specification (Invariance) 231848b8605Smrg 232848b8605Smrg None. 233848b8605Smrg 234848b8605SmrgAdditions to the AGL/GLX/WGL Specifications 235848b8605Smrg 236848b8605Smrg None. 237848b8605Smrg 238848b8605SmrgGLX Protocol 239848b8605Smrg 240848b8605Smrg XXX TBD 241848b8605Smrg 242848b8605SmrgDependencies on NV_vertex_program and NV_fragment_program 243848b8605Smrg 244848b8605Smrg If NV_vertex_program and/or NV_fragment_program are supported, 245848b8605Smrg vertex and/or fragment programs defined by those extensions may 246848b8605Smrg be debugged as well. Register queries will use the syntax used 247848b8605Smrg by those extensions (i.e. "v[X]" to query vertex attributes, 248848b8605Smrg "o[X]" for vertex outputs, etc.) 249848b8605Smrg 250848b8605SmrgErrors 251848b8605Smrg 252848b8605Smrg INVALID_OPERATION is generated if ProgramCallbackMESA is called 253848b8605Smrg between Begin and End. 254848b8605Smrg 255848b8605Smrg INVALID_ENUM is generated by ProgramCallbackMESA if <target> is not 256848b8605Smrg a supported vertex or fragment program type. 257848b8605Smrg 258848b8605Smrg Note: INVALID_OPERAION IS NOT generated by GetProgramRegisterfvMESA, 259848b8605Smrg GetBooleanv, GetDoublev, GetFloatv, or GetIntegerv if called between 260848b8605Smrg Begin and End when a vertex or fragment program is currently executing. 261848b8605Smrg 262848b8605Smrg INVALID_ENUM is generated by ProgramCallbackMESA, 263848b8605Smrg GetProgramRegisterfvMESA if <target> is not a program target supported 264848b8605Smrg by ARB_vertex_program, ARB_fragment_program (or NV_vertex_program or 265848b8605Smrg NV_fragment_program). 266848b8605Smrg 267848b8605Smrg INVALID_VALUE is generated by GetProgramRegisterfvMESA if <registerName> 268848b8605Smrg does not name a known program register or variable. 269848b8605Smrg 270848b8605Smrg INVALID_OPERATION is generated by GetProgramRegisterfvMESA when a 271848b8605Smrg register query is attempted for a program target that's not currently 272848b8605Smrg being executed. 273848b8605Smrg 274848b8605Smrg 275848b8605SmrgNew State 276848b8605Smrg 277848b8605Smrg XXX finish 278848b8605Smrg 279848b8605Smrg(table 6.N, p. ###) 280848b8605Smrg Initial 281848b8605Smrg Get Value Type Get Command Value Description Sec. Attribute 282848b8605Smrg --------- ---- ----------- ----- ----------- ---- --------- 283848b8605Smrg FRAGMENT_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable 284848b8605Smrg VERTEX_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable 285848b8605Smrg FRAGMENT_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX - 286848b8605Smrg VERTEX_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX - 287848b8605Smrg FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX - 288848b8605Smrg VERTEX_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX - 289848b8605Smrg FRAGMENT_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX - 290848b8605Smrg VERTEX_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX - 291848b8605Smrg 292848b8605Smrg XXX more? 293848b8605Smrg 294848b8605SmrgNew Implementation Dependent State 295848b8605Smrg 296848b8605Smrg None. 297848b8605Smrg 298848b8605SmrgRevision History 299848b8605Smrg 300848b8605Smrg 8 July 2003 301848b8605Smrg Initial draft. (Brian Paul) 302848b8605Smrg 11 July 2003 303848b8605Smrg Second draft. (Brian Paul) 304848b8605Smrg 20 July 2003 305848b8605Smrg Third draft. Lots of fundamental changes. (Brian Paul) 306848b8605Smrg 23 July 2003 307848b8605Smrg Added chapter 5 and 6 spec language. (Brian Paul) 308848b8605Smrg 309848b8605SmrgExample Usage 310848b8605Smrg 311848b8605Smrg The following is a very simple example of how this extension may 312848b8605Smrg be used to print the values of R0, R1, R2 and R3 while executing 313848b8605Smrg vertex programs. 314848b8605Smrg 315848b8605Smrg 316848b8605Smrg /* This is called by the GL when the vertex program is executing. 317848b8605Smrg * We can only make glGet* calls from within this function! 318848b8605Smrg */ 319848b8605Smrg void DebugCallback(GLenum target, GLvoid *data) 320848b8605Smrg { 321848b8605Smrg GLint pos; 322848b8605Smrg GLuint i; 323848b8605Smrg 324848b8605Smrg /* Get PC and current instruction string */ 325848b8605Smrg glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_ARB, &pos); 326848b8605Smrg 327848b8605Smrg printf("Current position: %d\n", pos); 328848b8605Smrg 329848b8605Smrg printf("Current temporary registers:\n"); 330848b8605Smrg for (i = 0; i < 4; i++) { 331848b8605Smrg GLfloat v[4]; 332848b8605Smrg char s[10]; 333848b8605Smrg sprintf(s, "R%d", i); 334848b8605Smrg glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_ARB, strlen(s), s, v); 335848b8605Smrg printf("R%d = %g, %g, %g, %g\n", i, v[0], v[1], v[2], v[3]); 336848b8605Smrg } 337848b8605Smrg } 338848b8605Smrg 339848b8605Smrg 340848b8605Smrg /* 341848b8605Smrg * elsewhere... 342848b8605Smrg */ 343848b8605Smrg 344848b8605Smrg /* Register our debugger callback function */ 345848b8605Smrg glProgramCallbackMESA(GL_VERTEX_PROGRAM_ARB, DebugCallback, NULL); 346848b8605Smrg glEnable(GL_VERTEX_PROGRAM_CALLBACK_MESA); 347848b8605Smrg 348848b8605Smrg /* define/bind a vertex program */ 349848b8605Smrg 350848b8605Smrg glEnable(GL_VERTEX_PROGRAM); 351848b8605Smrg 352848b8605Smrg /* render something */ 353848b8605Smrg glBegin(GL_POINTS); 354848b8605Smrg glVertex2f(0, 0); 355848b8605Smrg glEnd(); 356848b8605Smrg 357