Radeon ProRender

Combining Filters

Reading and writing textures are expensive operations that significantly reduce the performance of computationally simple filters. Consider an example in which we perform local tone mapping, color space changing and gamma correction.

rif_image_filter toneMapFilter = nullptr;
rif_image_filter colorSpaceFilter = nullptr;
rif_image_filter gammaFilter= nullptr;

rifContextCreateImageFilter(context, RIF_IMAGE_FILTER_FILMIC_TONEMAP, &toneMapFilter );
rifContextCreateImageFilter(context, RIF_IMAGE_FILTER_COLOR_SPACE, &colorSpaceFilter );
rifContextCreateImageFilter(context, RIF_IMAGE_FILTER_GAMMA_CORRECTION, &gammaFilter);

rifCommandQueueAttachImageFilter(queue, toneMapFilter, inputImage, outputImage);
rifCommandQueueAttachImageFilter(queue, colorSpaceFilter, outputImage, inputImage);
rifCommandQueueAttachImageFilter(queue, gammaFilter, inputImage, outputImage);
rifContextExecuteCommandQueue(context, queue, nullptr, nullptr, nullptr);

The calculation time for each of these operations is almost completely determined by the time of reading and writing from the texture. There is a natural desire to combine all these operations into one filter, and avoid use intermediate writings/readings from textures. The library provides a mechanism for combining filters.

To combine filters, it is sufficient to set another filter as the filter input:

rif_image_filter toneMapFilter = nullptr;
rif_image_filter colorSpaceFilter = nullptr;
rif_image_filter gammaFilter= nullptr;

rifContextCreateImageFilter(context, RIF_IMAGE_FILTER_FILMIC_TONEMAP, &toneMapFilter );
rifContextCreateImageFilter(context, RIF_IMAGE_FILTER_COLOR_SPACE, &colorSpaceFilter );
rifContextCreateImageFilter(context, RIF_IMAGE_FILTER_GAMMA_CORRECTION, &gammaFilter);

rifImageFilterSetParameterImage(toneMapFilter, "srcBuffer", inputImage);
rifImageFilterSetParameterImage(colorSpaceFilter, "srcBuffer", toneMapFilter);
rifCommandQueueAttachImageFilter(queue, gammaFilter, colorSpaceFilter, outputImage);
rifContextExecuteCommandQueue(context, queue, nullptr, nullptr, nullptr);

Add only the last filter to the queue. Such a technique allows one to obtain an acceleration proportional to the number of combined filters. In this example, the expected acceleration is 3 times.