0,0 → 1,356 |
Name |
|
MESA_program_debug |
|
Name Strings |
|
GL_MESA_program_debug |
|
Contact |
|
Brian Paul (brian.paul 'at' tungstengraphics.com) |
|
Status |
|
XXX - Not complete yet!!! |
|
Version |
|
Last Modified Date: July 20, 2003 |
Author Revision: 1.0 |
|
Number |
|
TBD |
|
Dependencies |
|
OpenGL 1.4 is required |
The extension is written against the OpenGL 1.4 specification. |
ARB_vertex_program or ARB_fragment_program or NV_vertex_program |
or NV_fragment_program is required. |
|
Overview |
|
The extension provides facilities for implementing debuggers for |
vertex and fragment programs. |
|
The concept is that vertex and fragment program debuggers will be |
implemented outside of the GL as a utility package. This extension |
only provides the minimal hooks required to implement a debugger. |
|
There are facilities to do the following: |
1. Have the GL call a user-specified function prior to executing |
each vertex or fragment instruction. |
2. Query the current program string's execution position. |
3. Query the current values of intermediate program values. |
|
The main feature is the ProgramCallbackMESA function. It allows the |
user to register a callback function with the GL. The callback will |
be called prior to executing each vertex or fragment program instruction. |
|
From within the callback, the user may issue Get* commands to |
query current GL state. The GetProgramRegisterfvMESA function allows |
current program values to be queried (such as temporaries, input |
attributes, and result registers). |
|
There are flags for enabling/disabling the program callbacks. |
|
The current execution position (as an offset from the start of the |
program string) can be queried with |
GetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos) or |
GetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos). |
|
|
IP Status |
|
None |
|
Issues |
|
1. Is this the right model for a debugger? |
|
It seems prudent to minimize the scope of this extension and leave |
it up to the developer (or developer community) to write debuggers |
that layer on top of this extension. |
|
If the debugger were fully implemented within the GL it's not |
clear how terminal and GUI-based interfaces would work, for |
example. |
|
2. There aren't any other extensions that register callbacks with |
the GL. Isn't there another solution? |
|
If we want to be able to single-step through vertex/fragment |
programs I don't see another way to do it. |
|
3. How do we prevent the user from doing something crazy in the |
callback function, like trying to call glBegin (leading to |
recursion)? |
|
The rule is that the callback function can only issue glGet*() |
functions and no other GL commands. It could be difficult to |
enforce this, however. Therefore, calling any non-get GL |
command from within the callback will result in undefined |
results. |
|
4. Is this extension amenable to hardware implementation? |
|
Hopefully, but if not, the GL implementation will have to fall |
back to a software path when debugging. This may be acceptable |
for debugging. |
|
5. What's the <data> parameter to ProgramCallbackMESA for? |
|
It's a common programming practice to associate a user-supplied |
value with callback functions. |
|
6. Debuggers often allow one to modify intermediate program values, |
then continue. Does this extension support that? |
|
No. |
|
|
New Procedures and Functions (and datatypes) |
|
typedef void (*programcallbackMESA)(enum target, void *data) |
|
void ProgramCallbackMESA(enum target, programcallbackMESA callback, |
void *data) |
|
void GetProgramRegisterfvMESA(enum target, sizei len, |
const ubyte *registerName, float *v) |
|
New Tokens |
|
Accepted by the <cap> parameter of Enable, Disable, IsEnabled, |
GetBooleanv, GetDoublev, GetFloatv and GetIntegerv: |
|
FRAGMENT_PROGRAM_CALLBACK_MESA 0x8bb1 |
VERTEX_PROGRAM_CALLBACK_MESA 0x8bb4 |
|
Accepted by the <pname> parameter GetBooleanv, GetDoublev, |
GetFloatv and GetIntegerv: |
|
FRAGMENT_PROGRAM_POSITION_MESA 0x8bb0 |
VERTEX_PROGRAM_POSITION_MESA 0x8bb4 |
|
Accepted by the <pname> parameter of GetPointerv: |
|
FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA 0x8bb2 |
FRAGMENT_PROGRAM_CALLBACK_DATA_MESA 0x8bb3 |
VERTEX_PROGRAM_CALLBACK_FUNC_MESA 0x8bb6 |
VERTEX_PROGRAM_CALLBACK_DATA_MESA 0x8bb7 |
|
Additions to Chapter 2 of the OpenGL 1.4 Specification (OpenGL Operation) |
|
None. |
|
Additions to Chapter 3 of the OpenGL 1.4 Specification (Rasterization) |
|
None. |
|
Additions to Chapter 4 of the OpenGL 1.4 Specification (Per-Fragment |
Operations and the Frame Buffer) |
|
None. |
|
Additions to Chapter 5 of the OpenGL 1.4 Specification (Special Functions) |
|
In section 5.4 "Display Lists", page 202, add the following command |
to the list of those that are not compiled into display lists: |
|
ProgramCallbackMESA. |
|
|
Add a new section 5.7 "Callback Functions" |
|
The function |
|
void ProgramCallbackMESA(enum target, programcallbackMESA callback, |
void *data) |
|
registers a user-defined callback function with the GL. <target> |
may be FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB. The enabled |
callback functions registered with these targets will be called |
prior to executing each instruction in the current fragment or |
vertex program, respectively. The callbacks are enabled and |
disabled by calling Enable or Disable with <cap> |
FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB. |
|
The callback function's signature must match the typedef |
|
typedef void (*programcallbackMESA)(enum target, void *data) |
|
When the callback function is called, <target> will either be |
FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB to indicate which |
program is currently executing and <data> will be the value |
specified when ProgramCallbackMESA was called. |
|
From within the callback function, only the following GL commands |
may be called: |
|
GetBooleanv |
GetDoublev |
GetFloatv |
GetIntegerv |
GetProgramLocalParameter |
GetProgramEnvParameter |
GetProgramRegisterfvMESA |
GetProgramivARB |
GetProgramStringARB |
GetError |
|
Calling any other command from within the callback results in |
undefined behaviour. |
|
|
Additions to Chapter 6 of the OpenGL 1.4 Specification (State and |
State Requests) |
|
Add a new section 6.1.3 "Program Value Queries": |
|
The command |
|
void GetProgramRegisterfvMESA(enum target, sizei len, |
const ubyte *registerName, |
float *v) |
|
Is used to query the value of program variables and registers |
during program execution. GetProgramRegisterfvMESA may only be |
called from within a callback function registered with |
ProgramCallbackMESA. |
|
<registerName> and <len> specify the name a variable, input |
attribute, temporary, or result register in the program string. |
The current value of the named variable is returned as four |
values in <v>. If <name> doesn't exist in the program string, |
the error INVALID_OPERATION is generated. |
|
Additions to Appendix A of the OpenGL 1.4 Specification (Invariance) |
|
None. |
|
Additions to the AGL/GLX/WGL Specifications |
|
None. |
|
GLX Protocol |
|
XXX TBD |
|
Dependencies on NV_vertex_program and NV_fragment_program |
|
If NV_vertex_program and/or NV_fragment_program are supported, |
vertex and/or fragment programs defined by those extensions may |
be debugged as well. Register queries will use the syntax used |
by those extensions (i.e. "v[X]" to query vertex attributes, |
"o[X]" for vertex outputs, etc.) |
|
Errors |
|
INVALID_OPERATION is generated if ProgramCallbackMESA is called |
between Begin and End. |
|
INVALID_ENUM is generated by ProgramCallbackMESA if <target> is not |
a supported vertex or fragment program type. |
|
Note: INVALID_OPERAION IS NOT generated by GetProgramRegisterfvMESA, |
GetBooleanv, GetDoublev, GetFloatv, or GetIntegerv if called between |
Begin and End when a vertex or fragment program is currently executing. |
|
INVALID_ENUM is generated by ProgramCallbackMESA, |
GetProgramRegisterfvMESA if <target> is not a program target supported |
by ARB_vertex_program, ARB_fragment_program (or NV_vertex_program or |
NV_fragment_program). |
|
INVALID_VALUE is generated by GetProgramRegisterfvMESA if <registerName> |
does not name a known program register or variable. |
|
INVALID_OPERATION is generated by GetProgramRegisterfvMESA when a |
register query is attempted for a program target that's not currently |
being executed. |
|
|
New State |
|
XXX finish |
|
(table 6.N, p. ###) |
Initial |
Get Value Type Get Command Value Description Sec. Attribute |
--------- ---- ----------- ----- ----------- ---- --------- |
FRAGMENT_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable |
VERTEX_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable |
FRAGMENT_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX - |
VERTEX_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX - |
FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX - |
VERTEX_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX - |
FRAGMENT_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX - |
VERTEX_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX - |
|
XXX more? |
|
New Implementation Dependent State |
|
None. |
|
Revision History |
|
8 July 2003 |
Initial draft. (Brian Paul) |
11 July 2003 |
Second draft. (Brian Paul) |
20 July 2003 |
Third draft. Lots of fundamental changes. (Brian Paul) |
23 July 2003 |
Added chapter 5 and 6 spec language. (Brian Paul) |
|
Example Usage |
|
The following is a very simple example of how this extension may |
be used to print the values of R0, R1, R2 and R3 while executing |
vertex programs. |
|
|
/* This is called by the GL when the vertex program is executing. |
* We can only make glGet* calls from within this function! |
*/ |
void DebugCallback(GLenum target, GLvoid *data) |
{ |
GLint pos; |
GLuint i; |
|
/* Get PC and current instruction string */ |
glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_ARB, &pos); |
|
printf("Current position: %d\n", pos); |
|
printf("Current temporary registers:\n"); |
for (i = 0; i < 4; i++) { |
GLfloat v[4]; |
char s[10]; |
sprintf(s, "R%d", i); |
glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_ARB, strlen(s), s, v); |
printf("R%d = %g, %g, %g, %g\n", i, v[0], v[1], v[2], v[3]); |
} |
} |
|
|
/* |
* elsewhere... |
*/ |
|
/* Register our debugger callback function */ |
glProgramCallbackMESA(GL_VERTEX_PROGRAM_ARB, DebugCallback, NULL); |
glEnable(GL_VERTEX_PROGRAM_CALLBACK_MESA); |
|
/* define/bind a vertex program */ |
|
glEnable(GL_VERTEX_PROGRAM); |
|
/* render something */ |
glBegin(GL_POINTS); |
glVertex2f(0, 0); |
glEnd(); |
|