This is my first time using CIKernelROICallback, and while it solved the problem of only a portain of my image being processed; I am now getting what I beleive are to be GPU crashes; whereby the resulting image is corrupted and my application has to be force quit (after rendering it's still using 100% of the CPU).
I have two questions.
1. Can someone look at the code below and confirm that it looks correct please.
// called when setting up for fragment program and also calls fragment program
- (CIImage *)outputImage
{
// --- Apple's example used a float; but I tried it as a double.
double radius = [blurRadius doubleValue];
CISampler *src = [CISampler samplerWithImage:inputImage];
CISampler *envMap = [CISampler samplerWithImage:map];
CGRect mapExtent = [map extent]; // --- Grab th amp extent.
// --- This is the callback that we cannot do in Xojo.
CIKernelROICallback callback = ^(int index, CGRect rect) {
if ( index == 0 ) {
return CGRectInset( rect, -radius, -radius );
} else {
return mapExtent;
}
return rect;
};
// --- This following line was missing from Apple's example, it allows the kernel
// to process with a radius of 200, but still crashes at 500 or 1000.
CGRect dod = CGRectInset( [inputImage extent], -radius, -radius );
return [_OCIGrouperFilterKernel applyWithExtent:dod
roiCallback:callback
arguments:@[ src,
envMap,
sampleCount,
spatialWC,
rangeWC,
clampScale]];
}2. Before the image is passed to this filter; I use [CIImage imageByClampingToExtent:] and when the image is returned from the filter I call [CIImage imageByCroppingToRect:] ( using the extent before processing). Should the DOD be the inset extent of the image before it was clampped?
i.e.
CGRect dod = CGRectInset( unclampedExtent, -radius, -radius );Thanks for any help you can give; this section has been particularly painful and frustrating.
On a whim, I tried something and it fixed it (I've only tested with 3 images so far, but these 3 image made it crash). The key is that the extent *should* be the extent *before* the image has been clamped. I moved the clamping and cropping into the filter.
// called when setting up for fragment program and also calls fragment program
- (CIImage *)outputImage
{
CGRect dod = [inputImage extent];
CGRect mapExtent = [map extent];
double radius = [blurRadius doubleValue];
CISampler *src = [CISampler samplerWithImage:[inputImage imageByClampingToExtent]];
CISampler *envMap = [CISampler samplerWithImage:map];
CIKernelROICallback callback = ^(int index, CGRect rect) {
if ( index == 0 ) { return CGRectInset( rect, -radius, -radius );
} else { return mapExtent; }
};
CIImage *rValue = [_OCIGrouperFilterKernel applyWithExtent:dod
roiCallback:callback
arguments:@[ src,
envMap,
sampleCount,
spatialWC,
rangeWC,
clampScale]];
return [rValue imageByCroppingToRect:dod];
}