/*
* Copyright (C) 2010-2014 Peter Fischer
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/
package edu.stanford.rsl.conrad.opencl.shapes;
import java.nio.FloatBuffer;
import com.jogamp.opencl.CLBuffer;
import com.jogamp.opencl.CLCommandQueue;
import com.jogamp.opencl.CLContext;
import com.jogamp.opencl.CLDevice;
import com.jogamp.opencl.CLKernel;
import com.jogamp.opencl.CLMemory.Mem;
import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
import edu.stanford.rsl.conrad.geometry.shapes.simple.Sphere;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.opencl.OpenCLEvaluatable;
import edu.stanford.rsl.conrad.opencl.OpenCLUtil;
public class OpenCLSphere extends Sphere implements OpenCLEvaluatable {
/**
*
*/
private static final long serialVersionUID = 2607437298428367616L;
protected CLContext context;
protected CLDevice device;
protected CLBuffer<FloatBuffer> parameter;
public OpenCLSphere(double radius, PointND surfaceOrigin, CLDevice device) {
super(radius, surfaceOrigin);
this.context = device.getContext();
this.device = device;
OpenCLUtil.initSimpleObjectEvaluator(context);
handleParameter(radius);
}
public OpenCLSphere(Sphere s, CLDevice device) {
this(s.getRadius(), s.getCenter(), device);
this.transform = s.getTransform();
}
protected void handleParameter(double radius){
this.parameter = context.createFloatBuffer(1, Mem.READ_ONLY);
this.parameter.getBuffer().put((float)radius);
this.parameter.getBuffer().rewind();
device.createCommandQueue().putWriteBuffer(this.parameter, true);
}
@Override
public void evaluate(CLBuffer<FloatBuffer> samplingPoints, CLBuffer<FloatBuffer> outputBuffer, int elementCountU, int elementCountV){
int elementCount = samplingPoints.getBuffer().capacity()/2; // Length of arrays to process
int localWorkSize = Math.min(device.getMaxWorkGroupSize(), 256); // Local work size dimensions
int globalWorkSize = OpenCLUtil.roundUp(localWorkSize, elementCount); // rounded up to the nearest multiple of the localWorkSize
CLKernel kernel = OpenCLUtil.simpleObjects.createCLKernel("evaluateSphere");
kernel.putArgs(parameter, samplingPoints, outputBuffer)
.putArg(elementCountU).putArg(elementCountV);
CLCommandQueue clc = device.createCommandQueue();
clc.put1DRangeKernel(kernel, 0, globalWorkSize, localWorkSize).finish();
kernel.release();
clc.release();
SimpleMatrix transform = SimpleMatrix.I_4.clone();
transform.setSubMatrixValue(0, 0, this.transform.getRotation(3));
transform.setSubColValue(0, 3, this.transform.getTranslation(3));
OpenCLUtil.transformPoints(outputBuffer, transform, context, device);
}
@Override
public void evaluate(CLBuffer<FloatBuffer> samplingPoints, CLBuffer<FloatBuffer> outputBuffer) {
int elementCount = samplingPoints.getBuffer().capacity()/2;
// assume equal length of elementCountU and elementCountV
evaluate(samplingPoints, outputBuffer, (int) Math.sqrt(elementCount), (int) Math.sqrt(elementCount));
}
@Override
public boolean isClockwise() {
return false;
}
@Override
public boolean isTimeVariant() {
return false;
}
}