void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device,
                                       MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, 
                                       MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, 
                                       list<cl_kernel> * /*clKernelsToCleanUp*/)
{
	cl_kernel defocusKernel = device->COM_clCreateKernel("defocusKernel", NULL);

	cl_int step = this->getStep();
	cl_int maxBlur;
	cl_float threshold = this->m_threshold;
	
	MemoryBuffer *sizeMemoryBuffer = this->m_inputSizeProgram->getInputMemoryBuffer(inputMemoryBuffers);

	const float max_dim = max(m_width, m_height);
	cl_float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f;

	maxBlur = (cl_int)min_ff(sizeMemoryBuffer->getMaximumValue() * scalar,
	                         (float)this->m_maxBlur);

	device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram);
	device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 1,  -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram);
	device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 2,  4, clMemToCleanUp, inputMemoryBuffers, this->m_inputSizeProgram);
	device->COM_clAttachOutputMemoryBufferToKernelParameter(defocusKernel, 3, clOutputBuffer);
	device->COM_clAttachMemoryBufferOffsetToKernelParameter(defocusKernel, 5, outputMemoryBuffer);
	clSetKernelArg(defocusKernel, 6, sizeof(cl_int), &step);
	clSetKernelArg(defocusKernel, 7, sizeof(cl_int), &maxBlur);
	clSetKernelArg(defocusKernel, 8, sizeof(cl_float), &threshold);
	clSetKernelArg(defocusKernel, 9, sizeof(cl_float), &scalar);
	device->COM_clAttachSizeToKernelParameter(defocusKernel, 10, this);
	
	device->COM_clEnqueueRange(defocusKernel, outputMemoryBuffer, 11, this);
}
float MemoryBuffer::getMaximumValue(rcti *rect)
{
	rcti rect_clamp;

	/* first clamp the rect by the bounds or we get un-initialized values */
	BLI_rcti_isect(rect, &this->m_rect, &rect_clamp);

	if (!BLI_rcti_is_empty(&rect_clamp)) {
		MemoryBuffer *temp = new MemoryBuffer(NULL, &rect_clamp);
		temp->copyContentFrom(this);
		float result = temp->getMaximumValue();
		delete temp;
		return result;
	}
	else {
		BLI_assert(0);
		return 0.0f;
	}
}