/* * Copyright (C) 2009-2012 Samuel Audet * * Licensed either under the Apache License, Version 2.0, or (at your option) * under the terms of the GNU General Public License as published by * the Free Software Foundation (subject to the "Classpath" exception), * either version 2, or any later version (collectively, the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * http://www.gnu.org/licenses/ * http://www.gnu.org/software/classpath/license.html * * or as provided in the LICENSE.txt file that accompanied this code. * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bytedeco.javacv; import com.jogamp.common.os.Platform; import com.jogamp.opencl.CLBuffer; import com.jogamp.opencl.CLEventList; import com.jogamp.opencl.CLImage2d; import com.jogamp.opencl.CLImageFormat; import com.jogamp.opencl.CLKernel; import com.jogamp.opencl.CLMemory; import java.nio.FloatBuffer; import static org.bytedeco.javacpp.opencv_core.*; /** * * @author Samuel Audet */ public class ProCamTransformerCL extends ProCamTransformer implements ImageTransformerCL { public ProCamTransformerCL(JavaCVCL context, double[] referencePoints, CameraDevice camera, ProjectorDevice projector) { this(context, referencePoints, camera, projector, null); } public ProCamTransformerCL(JavaCVCL context, double[] referencePoints, CameraDevice camera, ProjectorDevice projector, CvMat n) { super(referencePoints, camera, projector, n); final int dotSize = createParameters().size(); this.context = context; this.nullSize = Platform.is32Bit() ? 4 : 8; this.H1Buffer = surfaceTransformer == null ? null : context.getCLContext().createFloatBuffer(dotSize*9, CLBuffer.Mem.READ_ONLY); this.H2Buffer = context.getCLContext().createFloatBuffer(dotSize*9, CLBuffer.Mem.READ_ONLY); this.XBuffer = context.getCLContext().createFloatBuffer(dotSize*16, CLBuffer.Mem.READ_ONLY); if (getClass() == ProCamTransformerCL.class) { CLKernel[] kernels = context.buildKernels( JavaCVCL.fastCompilerOptions + " -cl-nv-maxrregcount=32 -DDOT_SIZE=" + dotSize, //JavaCVCL.fastCompilerOptions + " -DDOT_SIZE=" + dotSize, "ImageTransformer.cl:ProCamTransformer.cl", "transformOne", "transformSub", "transformDot", "reduceOutputData"); oneKernel = kernels[0]; subKernel = kernels[1]; dotKernel = kernels[2]; reduceKernel = kernels[3]; } } private static final ThreadLocal<CvMat> H13x3 = CvMat.createThreadLocal(3, 3), H23x3 = CvMat.createThreadLocal(3, 3), X4x4 = CvMat.createThreadLocal(4, 4); protected final JavaCVCL context; protected final int nullSize; protected final CLBuffer<FloatBuffer> H1Buffer, H2Buffer, XBuffer; protected CLImage2d[] projectorImageCL = null, surfaceImageCL = null; private CLKernel oneKernel, subKernel, dotKernel, reduceKernel; public JavaCVCL getContext() { return context; } public ProjectiveColorTransformerCL getSurfaceTransformerCL() { return (ProjectiveColorTransformerCL)surfaceTransformer; } public ProjectiveColorTransformerCL getProjectorTransformerCL() { return (ProjectiveColorTransformerCL)projectorTransformer; } public CLImage2d getProjectorImageCL(int pyramidLevel) { return projectorImageCL[pyramidLevel]; } public void setProjectorImageCL(CLImage2d projectorImage0, int minPyramidLevel, int maxPyramidLevel) { if (projectorImageCL == null || projectorImageCL.length != maxPyramidLevel+1) { projectorImageCL = new CLImage2d[maxPyramidLevel+1]; } projectorImageCL[minPyramidLevel] = projectorImage0; for (int i = minPyramidLevel+1; i <= maxPyramidLevel; i++) { if (projectorImageCL[i] == null) { int w = projectorImageCL[i-1].width/2; int h = projectorImageCL[i-1].height/2; CLImageFormat format = new CLImageFormat(CLImageFormat.ChannelOrder.RGBA, CLImageFormat.ChannelType.FLOAT); projectorImageCL[i] = context.getCLContext().createImage2d(w, h, format); } context.pyrDown(projectorImageCL[i-1], projectorImageCL[i]); } } public CLImage2d getSurfaceImageCL(int pyramidLevel) { return surfaceImageCL[pyramidLevel]; } public void setSurfaceImageCL(CLImage2d surfaceImage0, int pyramidLevels) { if (surfaceImageCL == null || surfaceImageCL.length != pyramidLevels) { surfaceImageCL = new CLImage2d[pyramidLevels]; } surfaceImageCL[0] = surfaceImage0; for (int i = 1; i < pyramidLevels; i++) { if (surfaceImageCL[i] == null) { int w = surfaceImageCL[i-1].width/2; int h = surfaceImageCL[i-1].height/2; CLImageFormat format = new CLImageFormat(CLImageFormat.ChannelOrder.RGBA, CLImageFormat.ChannelType.FLOAT); surfaceImageCL[i] = context.getCLContext().createImage2d(w, h, format); } context.pyrDown(surfaceImageCL[i-1], surfaceImageCL[i]); } } protected void prepareTransforms(CLBuffer H1Buffer, CLBuffer H2Buffer, CLBuffer XBuffer, int pyramidLevel, ImageTransformer.Parameters[] parameters) { FloatBuffer floatH1 = surfaceTransformer == null ? null : (FloatBuffer)H1Buffer.getBuffer().rewind(); FloatBuffer floatH2 = (FloatBuffer)H2Buffer.getBuffer().rewind(); FloatBuffer floatX = (FloatBuffer) XBuffer.getBuffer().rewind(); CvMat H1 = H13x3.get(); CvMat H2 = H23x3.get(); CvMat X = X4x4.get(); for (int i = 0; i < parameters.length; i++) { prepareTransforms(surfaceTransformer == null ? null : H1, H2, X, pyramidLevel, (ProCamTransformer.Parameters)parameters[i]); for (int j = 0; j < 9; j++) { if (surfaceTransformer != null) { floatH1.put((float)H1.get(j)); } floatH2.put((float)H2.get(j)); } for (int j = 0; j < 16; j++) { floatX.put((float)X.get(j)); } } if (surfaceTransformer != null) { floatH1.rewind(); } floatH2.rewind(); floatX.rewind(); } @Override public void transform(CLImage2d srcImg, CLImage2d subImg, CLImage2d srcDotImg, CLImage2d transImg, CLImage2d dstImg, CLImage2d maskImg, ImageTransformer.Parameters[] parameters, boolean[] inverses, InputData inputData, OutputData outputData) { if (inverses != null) { for (int i = 0; i < inverses.length; i++) { if (inverses[i]) { throw new UnsupportedOperationException("Inverse transform not supported."); } } } prepareTransforms(H1Buffer, H2Buffer, XBuffer, inputData.pyramidLevel, parameters); final int dotSize = parameters[0].size(); final int localSize = parameters.length > 1 ? parameters.length : (inputData.roiWidth > 32 ? 64 : 32); final int globalSize = JavaCVCL.alignCeil(inputData.roiWidth, localSize); final int reduceSize = globalSize/localSize; // allocate buffers if necessary CLBuffer inputBuffer = inputData.getBuffer(context); CLBuffer outputBuffer = outputData.getBuffer(context, dotSize, reduceSize); CLEventList list = new CLEventList(1); // setup kernel if (surfaceTransformer != null) { context.writeBuffer(H1Buffer, false); // upload H1 } context.writeBuffer(H2Buffer, false); // upload H2 context.writeBuffer(XBuffer, false); // upload X if (inputData.autoWrite) { inputData.writeBuffer(context); } CLImage2d srcImg2 = projectorImageCL[inputData.pyramidLevel]; CLKernel kernel = null; if (subImg == null) { assert parameters.length == 1; kernel = oneKernel.putArg(srcImg2).putArg(srcImg).putArg(dstImg == null ? transImg : dstImg).putArg(maskImg).putArg(H2Buffer); } else if (srcDotImg == null) { assert parameters.length == 1; kernel = subKernel.putArg(srcImg2).putArg(srcImg).putArg(subImg).putArg(transImg).putArg(dstImg).putArg(maskImg).putArg(H2Buffer); } else { assert parameters.length == dotSize; kernel = dotKernel.putArg(srcImg2).putArg(srcImg).putArg(subImg).putArg(srcDotImg).putArg(maskImg).putArg(H2Buffer); //System.out.println(kernel.getWorkGroupSize(context.getCLCommandQueue().getDevice())); } if (H1Buffer != null) { kernel.putArg(H1Buffer); } else { kernel.putNullArg(nullSize); } kernel.putArg(XBuffer).putArg(inputBuffer).putArg(outputBuffer).rewind(); context.executeKernel(kernel, inputData.roiX, 0, 0, globalSize, 1, parameters.length, localSize, 1, parameters.length, list); // execute program if (reduceSize > 1) { reduceKernel.putArg(outputBuffer).rewind(); context.executeKernel(reduceKernel, 0, reduceSize, reduceSize); } if (outputData.autoRead) { outputData.readBuffer(context); } // CLEvent event = list.getEvent(0); // System.out.println((event.getProfilingInfo(CLEvent.ProfilingCommand.END) - // event.getProfilingInfo(CLEvent.ProfilingCommand.START))/1000000.0); // long res = q.getDevice().getProfilingTimerResolution(); // System.out.println(res); } }