Shaders are written as C or C++ subroutines, stored in files with the extension ``.c''. To use these shaders in a scene, they must be dynamically linked into mental ray at runtime. mental ray accepts shaders in three forms:
To create a DSO, first compile the shader source to object format using cc as described above, then run the Unix command ``ld -shared source.o'', again assuming that the object file is called source.o. This ld command applies to SGI IRIX; refer to ``man ld'' on other platforms. Using DSOs is the fastest way to load shaders, there is very little overhead. DSOs, like object files, are loaded using link statements or -link options.
The commands to create a DSO depend on the operating system type. To create a DSO named example.so from a source file example.c, use the following commands. Insert the -g command line option after -c to insert debugging information, or insert -O to compile an optimized version. On most systems -g and -O cannot be combined. Refer to the compiler documentation for details.
Compiling and creating DSOs requires that a C development environment is installed on the system. If the cc and ld commands are not found, make sure that a development environment exists. On most platforms, it is a separate product that must be purchased separately. Dynamically loading a DSO does not require compilers or development options.
SGI offers a range of processors, with later processors having more instruction set features than earlier ones. While newer processors and newer operating system versions can execute older programs (as long as they all use the ELF object format), programs and shaders should be compiled for newer instruction sets to improve performance. Four instruction sets have been defined by MIPS, called mips1 through mips4. mips3 is about 30% faster than mips2 on the same system. mips4 should be used if a very large virtual address space (4 terabytes) is required to keep large numbers of large textures. Choose the opt options string according to the following table:
IRIX | instruction set | CPU | word size | opt |
5.x | mips2 | R4000 and up | 32 bits | |
6.x | mips2 | R4000 and up | 32 bits | -32 |
6.x | mips3 | R4400 and up | 32 bits | -n32 |
6.x | mips4 | R8000 and up | 64 bits | -64 |
In any case, the options must agree with the version of mental ray. See the abi(5) manual page for more details. Use the Unix file command on mental ray and the shader library and make sure that they both report the same number of bits and the same MIPS version. If there is a mismatch, the run-time linker will print a message like:
/my/shader.so: 1234:ray: rld: Fatal Error: cannot successfully map soname '/my/shader.so' under any of the filenames /my/shader.so
The run-time linker always tries to match executables and libraries, which allows multiple ABIs to reside on the same system without conflicts. If the filename of the DSO given as an absolute pathname mental ray only tries to load that particular file. If it is given as a relative path, mental ray searches the DSO in a list of paths that can be supplied via the command line parameter (-ld_path) or the environment variable (MI_LIBRARY_PATH). There is also a default search path (/usr/local/mi/lib;.). A search list is a colon-separated (Unix) or semicolon-separated (Unix or Windows NT) list of paths to be searched. (Windows NT uses colons for drive letters.)
Note that source code (.c extension) is normally portable, unless nonportable system features (such as fsqrt on SGIs) are used. This means that the shader will run on all other vendors' systems unchanged. If the compilation fails and the shaders therefore are undefined, mental ray will -- when calls of the undefined shaders are attempted -- return miFALSE, which will generally leave the pixel sample black.
Neither object files (.o extension) nor DSOs (.so extension) are portable. They must be compiled separately for each platform and, usually, for each major operating system release. For example, a Hewlett-Packard object file will not run on an SGI system, and an SGI IRIX 4.x object file cannot be used on an IRIX 6.x system, and vice versa. Also note that pointers are 32-bit values on some systems and 64-bit values on others, and that most but not all (IBM) processors require that 64-bit values such as doubles are stored at memory addresses evenly divisible by 8.
On SGI systems, a shader can be debugged after it has been called for the first time, which attaches it to the program and makes its symbols available to the debugger. For this to work, the -g option must be given to the cc and ld commands in all stages -- compilation, linking, and shared-library building. Also, only DSO shaders are debuggable, not shaders loaded in object (.o) or source (.c) form.
On non-SGI systems, debugging shaders is, unfortunately, difficult. The reason is that most debuggers cannot deal with parts of a program that have been dynamically linked. In general, the debugger will refuse to set breakpoints in dynamically linked shaders, and will step over calls to these shaders as if they were a single operating system call. Some vendors are working on fixing these problems, but at this time the only option on non-SGI systems is using mi_info or mi_debug statements in the shader sources. Avoid printf because it is lost on server hosts and because it can cause problems at runtime.
Windows NT shader libraries must use at least one shader interface call (any true C function beginning with mi_), or an error message ``DLL_SetModuleHandle not found'' will occur.
When a shared library is loaded that contains a function module_init, that function is called just after the library was loaded, before the first shader in it is called. Conversely, if it contains a function module_exit, that function is called just before the library is unloaded, after the last call to a shader in this library. Note that in the case of irrecoverable errors at any time after the library was loaded module_exit is not guaranteed to be called. Neither module_init nor module_exit may rely on any shader interface services that assume that a rendering operation is in progress. Message functions such as mi_info are available. Note: this feature is not supported on IBM systems and should not be used for portable shaders.