#include "DDImage/PlanarIop.h"
#include "DDImage/Knobs.h"
#include "DDImage/NukeWrapper.h"
#include "DDImage/Blink.h"
#include "Blink/Blink.h"
#include "blurAndGainExampleKernels.h"
static const char* const CLASS = "BlinkBlurAndGain";
static const char* const HELP = "Example of a simple box blur and gain operator that uses the Blink API.";
{
protected:
Blink::ComputeDevice _gpuDevice;
bool _useGPUIfAvailable;
int _radius;
float _gain;
Blink::ProgramSource _blurProgram;
Blink::ProgramSource _gainProgram;
public:
: PlanarIop(node)
, _gpuDevice(
Blink::ComputeDevice::CurrentGPUDevice())
, _useGPUIfAvailable(true)
, _blurProgram(BlurKernel)
, _gainProgram(GainKernel)
{
_radius = 3;
_gain = 2.0f;
}
void knobs(DD::Image::Knob_Callback f);
void _validate(bool);
void getRequests(const DD::Image::Box& box, const DD::Image::ChannelSet& channels, int count, DD::Image::RequestOutput &reqData) const;
virtual bool useStripes() const;
virtual size_t stripeHeight() const;
void renderStripe(DD::Image::ImagePlane& outputPlane);
const char* Class() const { return CLASS; }
const char* node_help() const { return HELP; }
static const Iop::Description description;
};
void BlinkBlurAndGain::knobs(DD::Image::Knob_Callback f)
{
Newline(f, "Local GPU: ");
const bool hasGPU = _gpuDevice.available();
std::string gpuName = hasGPU ? _gpuDevice.name() : "Not available";
Named_Text_knob(f, "gpuName", gpuName.c_str());
Newline(f);
Bool_knob(f, &_useGPUIfAvailable, "use_gpu", "Use GPU if available");
Divider(f);
Int_knob(f, &_radius, "radius");
Tooltip(f, "The radius of the blur.");
Float_knob(f, &_gain, DD::Image::IRange(0, 10), "gain");
Tooltip(f, "The amount of gain to apply.");
}
void BlinkBlurAndGain::_validate(bool for_real)
{
copy_info();
info_.pad(_radius);
}
void BlinkBlurAndGain::getRequests(const DD::Image::Box& box, const DD::Image::ChannelSet& channels, int count, DD::Image::RequestOutput &reqData) const
{
DD::Image::Box inputBox = box;
inputBox.expand(_radius);
reqData.request(&input0(), inputBox, channels, count);
}
void BlinkBlurAndGain::renderStripe(DD::Image::ImagePlane& outputPlane)
{
try {
DD::Image::Box inputBox = outputPlane.bounds();
inputBox.expand(_radius);
inputBox.intersect(input0().info());
DD::Image::ImagePlane inputPlane(inputBox,
outputPlane.packed(),
outputPlane.channels(),
outputPlane.nComps());
input0().fetchPlane(inputPlane);
if (aborted()) {
return;
}
outputPlane.makeWritable();
Blink::Image outputPlaneAsImage;
Blink::Image inputPlaneAsImage;
bool success = (DD::Image::Blink::ImagePlaneAsBlinkImage(outputPlane, outputPlaneAsImage) &&
DD::Image::Blink::ImagePlaneAsBlinkImage(inputPlane, inputPlaneAsImage));
if (!success) {
error("Unable to fetch Blink image for image plane.");
return;
}
bool usingGPU = _useGPUIfAvailable && _gpuDevice.available() && !_forceCPU;
Blink::ComputeDevice computeDevice = usingGPU ? _gpuDevice : Blink::ComputeDevice::CurrentCPUDevice();
Blink::Image intermediateImage = inputPlaneAsImage.makeLike(computeDevice);
Blink::Image inputImageOnComputeDevice = inputPlaneAsImage.distributeTo(computeDevice);
Blink::ComputeDeviceBinder binder(computeDevice);
std::vector<Blink::Image> images;
images.push_back(inputImageOnComputeDevice);
images.push_back(intermediateImage);
Blink::Kernel horizontalBlurKernel(_blurProgram,
computeDevice,
images,
kBlinkCodegenDefault);
horizontalBlurKernel.setParamValue("Radius", _radius);
horizontalBlurKernel.setParamValue("Horizontal", true);
horizontalBlurKernel.iterate();
Blink::Image outputImage = usingGPU ? outputPlaneAsImage.makeLike(_gpuDevice) : outputPlaneAsImage;
images.clear();
images.push_back(intermediateImage);
images.push_back(outputImage);
Blink::Kernel verticalBlurKernel(_blurProgram,
computeDevice,
images,
kBlinkCodegenDefault);
verticalBlurKernel.setParamValue("Radius", _radius);
verticalBlurKernel.setParamValue("Horizontal", false);
verticalBlurKernel.iterate();
images.clear();
images.push_back(outputImage);
Blink::Kernel gainKernel(_gainProgram,
computeDevice,
images,
kBlinkCodegenDefault);
gainKernel.setParamValue("Gain", _gain);
gainKernel.iterate();
if (usingGPU) {
outputPlaneAsImage.copyFrom(outputImage);
}
}
catch (Blink::Exception &ex) {
error(ex.userMessage().c_str());
}
}
bool BlinkBlurAndGain::useStripes() const
{
return true;
}
size_t BlinkBlurAndGain::stripeHeight() const
{
return 256;
}
static DD::Image::Iop* BlinkBlurAndGainCreate(Node* node)
{
}
const DD::Image::Iop::Description BlinkBlurAndGain::description(CLASS, "Filter/BlinkBlurAndGain",
BlinkBlurAndGainCreate);