|
Pixie supports the use of DSO functions. That means, you can call regular
C/C++ functions implemented in a dll/so from the shading language as if they
were built in functions. This is a very powerful mechanism allowing you to use
C/C++ functions from your shaders. The mechanism is quite simple:
In DLL / SO
You need to include shadeop.h which contains the necessary macros. For
each function you implemented as a DSO, you need to create a SHADEOP
table:
#include <shadeop.h>
//This is the shadeop dispatch table
//The renderer and the shading language compiler will
// check this table to figure out what function in the
// dll/so implements what.
//
//Each line in the table designates a function
SHADEOP_TABLE(myfun) = {
{"float myfun_f(vector)","myinit_f","mycleanup_f"},
{"vector myfun_v(float,float,float)","",""},
{""} // End the table with an empty entry
};
// This is the function that implements
// float myfun(vector)
SHADEOP(myfun_f) {
float *result = (float *) argv[0];
float *input = (float *) argv[1];
result[0] = (input[0] + input[1] + input[2]) / (float) 3;
}
// This is the init function for the previous function
SHADEOP_INIT(myiniy_f) {
return NULL;
}
// This is the cleanup function for the previous function
SHADEUP_CLEANUP(mycleanup_f) { }
// This is the function that implements
// vector myfun(float,float,float)
SHADEOP(myfun_v) {
float *result = (float *) argv[0];
float *input1 = (float *) argv[1];
float *input2 = (float *) argv[2];
float *input3 = (float *) argv[3];
result[0] = input1[0];
result[1] = input2[0];
result[2] = input3[0];
}
The macro SHADEOP_TABLE(name) defines a table that contains the
prototype for the DSO function and the names of the init and cleanup functions
for that function for each different polymorphic occurrence of the function name in the DSO. The init function is called when the dll/so is first loaded
into the memory. It must accept two arguments: a thread ID and a texture context
pointer both of which are 0 with PIXIE. These parameters are provided for
compatibility reasons. The init function must return a void
* pointer to
a transparent handle for the function. This handle will be passed to the DSO
function and the cleanup functions. The cleanup function must do any cleanup
required by the DSO (for example, de-allocating the memory that the init
function allocates). The only parameter that this cleanup function accepts is
the transparent handle that the init function returns. Finally, the actual DSO
function executes the function. This function receives 3 arguments:
- void *initdata
This is the handle that the init function returns.
- int argc
This is the number of arguments passed to the DSO. Note
that this is a redundant argument as you can clearly see the number of arguments
at the prototype of the function. For example, for float myfun(vector) it
will always be 2 (includes the return value).
- void *argv[]
This is
the array of pointers that contains the arguments. The argv[0] always
points to the return value. If there is no return value (void function), this
argument is not used.
For example, "float myfun_f(vector)","myinit_f","mycleanup_f" means that the function
myfun_f implements the function float
myfun(vector). So whenever, the renderer needs to execute this particular
function, myfun_f will be called. The init and cleanup functions for
this function are myinit_f and mycleanup. These functions are
called only once before the first usage of the myfun_f and after
the last usage of myfun_f. The code provided above also contains another
form of "myfun" which is polymorphic to the first one:
"vector myfun_v(float,float,float)","","".
This means, that myfun_v implements vector myfun(float,float,float).
This version of the function myfun does not have any init or cleanup
functions (as indicated by ""), so the initdata parameter with
be NULL all the time. The DSO shaders prepared for the PrMan, Entrophy
and RenderDotC should be compatible with Pixie although I did not test it yet.
In SL
In your shader code, you can now use vector myfun(float,float,float)
and float myfun(vector) without any trouble. The dll/so that contains the
implementation must be in the include directory (indicated by -I
parameter). Similarly, the dll/so that has the implementation must be in the
procedural search path. One important thing that you need to be careful about is
that Pixie assumes all the parameters passed to a DSO function are defined as
output. That means if DSO changes an argument, the change will stick !!!. One
last note: a single dll/so may have multiple DSO's. The Pixie will automatically
search all the dll/so's in the input directory for the correct DSO.
|