Render Pass Preprocessing Shaders

Pass preprocessing shaders (prep shaders) access only a single pass file for reading and another for writing, but have access to all sample locations. Prep shaders are intended for "preparing" a pass file for later merging, by reading an existing pass file and writing a new one for later processing. For example, a prep shader may motion-blur on a subpixel sample level.

Here is an example of a simple prep shader that replaces nonblank samples with a red-blue gradation:

    typedef struct {miColor color; miScalar depth;} Sample;

    DLLEXPORT int myprep_version(void) {return(1);}

    DLLEXPORT miBoolean myprep(
        miColor         *dummy,
        miState         *state,
        void            *paras)
    {   
        int             xl, yl, xs, ys, xres, yres, x, y;
        Sample          s;
    
        mi_renderpass_resolution(&xl, &yl, &xs, &ys, &xres, &yres, state, 0,0);
        mi_info("pos %d %d, size %d %d, res %d %d", xl, yl, xs, ys, xres,yres);

        for (y=0; y < yres; y++) {
            for (x=0; x < xres; x++) {
                if (!mi_renderpass_sample_get(&s, sizeof(s), state, 0, x, y)) {
                    mi_error("%4d %4d: PREP READ ERROR", x, y);
                    continue;
                }
                s.color.r = 1.0 * y / yres;
                s.color.b = 1.0 * x / xres;
                s.color.g = 0;
                s.color.a = 1;
                if (!mi_renderpass_sample_put(&s, sizeof(s), state, 0, x, y))
                    mi_error("%4d %4d: PREP WRITE ERROR", x, y);
            }
            if (!((y+1) % ys))
                for (x=0; x < xres+xs-1; x+=xs) {
                    mi_renderpass_samplerect_flush(state, 0, x, y - y%ys);
                    mi_renderpass_samplerect_flush(state, 1, x, y - y%ys);
                }
        }
        return(miTRUE);                             
    }                                                   

The shader loops over all samples in order. Ordering is not required, and useful prep shaders will generally have some unordered access patterns, but performance and memory behavior improves if accesses, especially write accesses (mi_renderpass_sample_put) roughly work by rectangle. Rectangles are the rectangular raster space units that can be seen when attaching the imf_disp viewer to a running mental ray. (Rectangles overlap.) Samples are stored in pass files in rectangle blocks.

Normally mental ray will read and write entire rectangles, and keep them in memory until the prep shader returns. If the pass file is very large, this can require a lot of memory. The mi_renderpass_samplerect_flush function is available to remove rectangles from memory. It can be applied to the pass file being read (second argument is 0) and to the pass file being written (second argument is 1). Flushed read rectangles can be re-read, but flushed write rectangles can never be altered again. This is why prep shaders should prefer ordering their write accesses over ordering their read accesses.

Copyright © 1986-2010 by mental images GmbH