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