From 47187fa538dff1f5619d17dad07f54088edc5f18 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Tue, 28 Jun 2011 00:14:11 +0000 Subject: [PATCH 01/46] JavaCL: moved JNA implementation to OpenCL-JNA directory tree --- .settings/org.eclipse.jdt.core.prefs | 5 + .settings/org.maven.ide.eclipse.prefs | 9 + CHANGELOG | 159 ++ Common/.classpath | 9 + Common/.project | 29 + Common/.settings/org.eclipse.jdt.core.prefs | 5 + Common/.settings/org.maven.ide.eclipse.prefs | 9 + Common/pom.xml | 32 + .../java/com/nativelibs4java/util/Cache.java | 30 + .../com/nativelibs4java/util/EnumValue.java | 24 + .../com/nativelibs4java/util/EnumValues.java | 111 ++ .../com/nativelibs4java/util/IOUtils.java | 56 + .../com/nativelibs4java/util/ImageUtils.java | 72 + .../com/nativelibs4java/util/NIOUtils.java | 376 +++++ .../com/nativelibs4java/util/ValuedEnum.java | 14 + .../com/nativelibs4java/util/ValuedEnums.java | 34 + .../nativelibs4java/util/package-info.java | 5 + .../BinaryKernelTest - issue 30.java | 58 + .../CreateBinaryProgram - issue 30.README | 8 + .../CreateBinaryProgram - issue 30.diff | 82 + Core/.classpath | 13 + Core/.project | 29 + Core/.settings/org.eclipse.jdt.core.prefs | 5 + Core/.settings/org.maven.ide.eclipse.prefs | 9 + Core/nb-configuration.xml | 18 + Core/nbactions.xml | 1 + Core/pom.xml | 75 + .../opencl/CLAbstractEntity.java | 110 ++ .../opencl/CLAbstractUserProgram.java | 127 ++ .../opencl/CLBuildException.java | 50 + .../nativelibs4java/opencl/CLByteBuffer.java | 51 + .../nativelibs4java/opencl/CLCharBuffer.java | 49 + .../com/nativelibs4java/opencl/CLDevice.java | 986 +++++++++++ .../opencl/CLDoubleBuffer.java | 49 + .../com/nativelibs4java/opencl/CLEvent.java | 380 +++++ .../nativelibs4java/opencl/CLException.java | 258 +++ .../nativelibs4java/opencl/CLFloatBuffer.java | 50 + .../com/nativelibs4java/opencl/CLImage.java | 192 +++ .../com/nativelibs4java/opencl/CLImage2D.java | 153 ++ .../com/nativelibs4java/opencl/CLImage3D.java | 93 + .../nativelibs4java/opencl/CLImageFormat.java | 284 ++++ .../nativelibs4java/opencl/CLInfoGetter.java | 148 ++ .../nativelibs4java/opencl/CLIntBuffer.java | 49 + .../com/nativelibs4java/opencl/CLKernel.java | 427 +++++ .../nativelibs4java/opencl/CLLongBuffer.java | 49 + .../com/nativelibs4java/opencl/CLMem.java | 256 +++ .../nativelibs4java/opencl/CLPlatform.java | 516 ++++++ .../com/nativelibs4java/opencl/CLProgram.java | 768 +++++++++ .../com/nativelibs4java/opencl/CLQueue.java | 194 +++ .../com/nativelibs4java/opencl/CLSampler.java | 135 ++ .../nativelibs4java/opencl/CLShortBuffer.java | 49 + .../nativelibs4java/opencl/CLUserEvent.java | 61 + .../nativelibs4java/opencl/ImageIOUtils.java | 474 ++++++ .../com/nativelibs4java/opencl/InfoName.java | 46 + .../com/nativelibs4java/opencl/JavaCL.java | 244 +++ .../nativelibs4java/opencl/package-info.java | 35 + .../com/nativelibs4java/util/JNAUtils.java | 121 ++ Core/src/main/javadoc/overview.html | 75 + Core/src/main/jnlp/HardwareReport.jnlp | 30 + .../jnlp/InteractiveImageTransformDemo.jnlp | 34 + Core/src/main/jnlp/JavaCL.jnlp | 23 + Core/src/main/jnlp/MandelbrotDemo.jnlp | 32 + Core/src/main/jnlp/OpenCL4Java.jnlp | 25 + Core/src/main/jnlp/ParticlesDemo.jnlp | 35 + Core/src/main/jnlp/ScalaCL.jnlp | 22 + .../com/nativelibs4java/opencl/CLBuffer.java | 370 ++++ .../com/nativelibs4java/opencl/CLContext.java | 726 ++++++++ .../opencl/AbstractCommon.java | 62 + .../opencl/BinaryKernelTest.java | 62 + .../opencl/BufferReadTest.java | 120 ++ .../nativelibs4java/opencl/BufferTest.java | 117 ++ .../nativelibs4java/opencl/CLTestUtils.java | 96 ++ .../com/nativelibs4java/opencl/ImageTest.java | 394 +++++ .../opencl/InfoGettersTest.java | 133 ++ .../com/nativelibs4java/opencl/JOGLTest.java | 226 +++ .../opencl/OpenCL4JavaBasicTest.java | 98 ++ .../opencl/OpenCL4JavaBenchmarkTest.java | 317 ++++ .../nativelibs4java/test/BenchmarkUtils.java | 22 + .../nativelibs4java/test/MiscTestUtils.java | 66 + .../nativelibs4java/opencl/BufferReadTest.c | 6 + Demos/.classpath | 13 + Demos/.project | 29 + Demos/.settings/org.eclipse.jdt.core.prefs | 5 + Demos/.settings/org.maven.ide.eclipse.prefs | 9 + Demos/pom.xml | 73 + .../opencl/demos/SetupUtils.java | 102 ++ .../opencl/demos/hardware/HardwareReport.java | 243 +++ .../demos/mandelbrot/MandelbrotDemo.java | 180 ++ .../demos/random/ParallelRandomDemo.java | 159 ++ .../demos/sobelfilter/SobelFilterDemo.java | 186 ++ .../opencl/demos/vectoradd/VectorAdd.java | 55 + .../opencl/demos/mandelbrot/Mandelbrot.cl | 34 + .../opencl/demos/sobelfilter/SimpleSobel.cl | 76 + .../opencl/demos/TestReport.java | 26 + Generator/.classpath | 9 + Generator/.project | 29 + .../.settings/org.eclipse.jdt.core.prefs | 5 + .../.settings/org.maven.ide.eclipse.prefs | 9 + Generator/pom.xml | 85 + .../opencl/generator/JavaCLGenerator.java | 542 ++++++ .../opencl/generator/JavaCLGeneratorMojo.java | 220 +++ InteractiveImageDemo/pom.xml | 79 + InteractiveImageDemo/project/build.properties | 8 + .../build/InteractiveImageDemoProject.scala | 12 + .../InteractiveImageDemo.java | 554 ++++++ .../opencl/demos/interactiveimage/Utils.java | 155 ++ .../src/main/resources/examples/Blur.cl | 65 + .../main/resources/examples/Convolution.cl | 45 + .../resources/examples/DesaturateColors.cl | 44 + .../main/resources/examples/DummySample.cl | 33 + .../src/main/resources/examples/Identity.cl | 32 + .../resources/examples/LuminanceThreshold.cl | 33 + .../main/resources/examples/NaiveDenoising.cl | 52 + .../main/resources/examples/QueryFormat.cl | 35 + .../examples/RichardsonLucyDeconvolution.cl | 40 + .../main/resources/examples/SobelFilter.cl | 45 + .../src/main/resources/images/lena.jpg | Bin 0 -> 29338 bytes .../src/main/resources/images/mandrill.jpg | Bin 0 -> 50717 bytes JavaCL/pom.xml | 89 + .../opencl/util/LinearAlgebraUtils.java | 140 ++ .../opencl/util/OpenCLType.java | 37 + .../opencl/util/ParallelMath.java | 238 +++ .../opencl/util/ParallelRandom.java | 265 +++ .../opencl/util/ReductionUtils.java | 214 +++ .../opencl/util/Transformer.java | 67 + .../opencl/util/fft/AbstractDFT.java | 21 + .../opencl/util/fft/AbstractFFTPow2.java | 88 + .../opencl/util/fft/DoubleDFT.java | 29 + .../opencl/util/fft/DoubleFFTPow2.java | 31 + .../opencl/util/fft/FloatDFT.java | 26 + .../opencl/util/fft/FloatFFTPow2.java | 30 + .../opencl/util/fft/package-info.java | 34 + .../opencl/util/package-info.java | 34 + .../opencl/util/LinearAlgebraKernels.c | 46 + .../opencl/util/XORShiftRandom.c | 67 + .../opencl/util/fft/DoubleDFTProgram.cl | 44 + .../opencl/util/fft/DoubleFFTProgram.cl | 95 ++ .../opencl/util/fft/FloatDFTProgram.cl | 40 + .../opencl/util/fft/FloatFFTProgram.cl | 55 + .../nativelibs4java/opencl/util/Reduction.c | 41 + .../util/DiscreteFourierTransformTest.java | 174 ++ .../opencl/util/ParallelRandomTest.java | 70 + .../opencl/util/ReductionTest.java | 134 ++ JavaCLTutorial/pom.xml | 123 ++ .../src/main/java/tutorial/DFT.java | 102 ++ .../src/main/java/tutorial/DFT2.java | 38 + .../DiscreteFourierTransformProgram.c | 33 + .../DiscreteFourierTransformProgram.cl | 44 + LICENSE.header | 19 + LibCL/pom.xml | 26 + LibCL/src/main/resources/LibCL/Bits.cl | 15 + LibCL/src/main/resources/LibCL/Gaussian7x7.cl | 16 + .../src/main/resources/LibCL/ImageConvert.cl | 19 + .../main/resources/LibCL/ImageConvolution.cl | 208 +++ .../LibCL/RichardsonLucyImageDeconvolution.cl | 77 + .../src/main/resources/LibCL/SobelOperator.cl | 63 + LibCL/src/main/resources/LibCL/hsla2rgba.cl | 44 + LibCL/src/main/resources/LibCL/rgba2hsla.cl | 36 + LibCL/src/main/resources/LibCL/stdlib.h | 21 + LibCL/src/main/resources/LibCL/strstr.c | 5 + LibCL/src/main/resources/LibCL/strtod.c | 268 +++ LibCL/src/main/resources/LibCL/strtof.c | 302 ++++ NumericalBenchmark/pom.xml | 124 ++ .../src/main/java/fft/FFTBench.java | 217 +++ .../src/main/scala/fft/FFTScala.scala | 292 ++++ OpenCL4Java/.classpath | 10 + OpenCL4Java/.project | 29 + .../.settings/org.eclipse.jdt.core.prefs | 5 + .../.settings/org.maven.ide.eclipse.prefs | 9 + OpenCL4Java/pom.xml | 58 + OpenCL4Java/regenerate.cmd | 3 + OpenCL4Java/src/main/headers/1.0/CL/cl.h | 872 ++++++++++ OpenCL4Java/src/main/headers/1.0/CL/cl_gl.h | 124 ++ .../src/main/headers/1.0/CL/cl_platform.h | 302 ++++ OpenCL4Java/src/main/headers/1.1/CL/cl.h | 997 +++++++++++ OpenCL4Java/src/main/headers/1.1/CL/cl_ext.h | 213 +++ OpenCL4Java/src/main/headers/1.1/CL/cl_gl.h | 155 ++ .../src/main/headers/1.1/CL/cl_gl_ext.h | 69 + .../src/main/headers/1.1/CL/cl_platform.h | 1175 +++++++++++++ OpenCL4Java/src/main/headers/1.1/CL/opencl.h | 54 + .../opencl/library/OpenCLLibrary.java | 1496 +++++++++++++++++ .../opencl/library/OpenGLContextUtils.java | 43 + .../opencl/library/cl_buffer_region.java | 32 + .../opencl/library/cl_image_format.java | 37 + .../opencl/library/package-info.java | 4 + .../main/jnaerator/OpenCL.MacOSX.jnaerator | 11 + .../jnaerator/OpenCL.OtherPlatforms.jnaerator | 1 + .../jnaerator/OpenCL.Win32ATIStream.jnaerator | 11 + .../src/main/jnaerator/OpenCL.base.jnaerator | 1 + .../src/main/jnaerator/config.jnaerator | 36 + OpenGLDemos/pom.xml | 65 + .../opencl/demos/JavaCLSettingsPanel.form | 196 +++ .../opencl/demos/JavaCLSettingsPanel.java | 385 +++++ .../opencl/demos/particles/ParticlesDemo.java | 656 ++++++++ .../opencl/demos/particles/HSVtoRGB.c | 55 + .../demos/particles/ParticlesDemoProgram.c | 105 ++ Parent/.classpath | 6 + Parent/.project | 23 + Parent/.settings/org.eclipse.jdt.core.prefs | 5 + Parent/.settings/org.maven.ide.eclipse.prefs | 9 + Parent/pom.xml | 69 + ScalaCL.svg | 235 +++ getJOGL | 37 + pom.xml | 54 + runComp | 2 + runComp.cmd | 9 + 206 files changed, 25952 insertions(+) create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.maven.ide.eclipse.prefs create mode 100644 CHANGELOG create mode 100644 Common/.classpath create mode 100644 Common/.project create mode 100644 Common/.settings/org.eclipse.jdt.core.prefs create mode 100644 Common/.settings/org.maven.ide.eclipse.prefs create mode 100644 Common/pom.xml create mode 100644 Common/src/main/java/com/nativelibs4java/util/Cache.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/EnumValue.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/EnumValues.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/IOUtils.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/ImageUtils.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/NIOUtils.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/ValuedEnum.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/ValuedEnums.java create mode 100644 Common/src/main/java/com/nativelibs4java/util/package-info.java create mode 100644 Contributions/Kazo Csaba/BinaryKernelTest - issue 30.java create mode 100644 Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.README create mode 100644 Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.diff create mode 100644 Core/.classpath create mode 100644 Core/.project create mode 100644 Core/.settings/org.eclipse.jdt.core.prefs create mode 100644 Core/.settings/org.maven.ide.eclipse.prefs create mode 100644 Core/nb-configuration.xml create mode 100644 Core/nbactions.xml create mode 100644 Core/pom.xml create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLAbstractEntity.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLAbstractUserProgram.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLBuildException.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLByteBuffer.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLCharBuffer.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLDevice.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLDoubleBuffer.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLEvent.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLException.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLFloatBuffer.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLImage.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLImage2D.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLImage3D.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLImageFormat.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLInfoGetter.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLIntBuffer.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLKernel.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLLongBuffer.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLMem.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLPlatform.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLProgram.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLQueue.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLSampler.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLShortBuffer.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/CLUserEvent.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/ImageIOUtils.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/InfoName.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/JavaCL.java create mode 100644 Core/src/main/java/com/nativelibs4java/opencl/package-info.java create mode 100644 Core/src/main/java/com/nativelibs4java/util/JNAUtils.java create mode 100644 Core/src/main/javadoc/overview.html create mode 100644 Core/src/main/jnlp/HardwareReport.jnlp create mode 100644 Core/src/main/jnlp/InteractiveImageTransformDemo.jnlp create mode 100644 Core/src/main/jnlp/JavaCL.jnlp create mode 100644 Core/src/main/jnlp/MandelbrotDemo.jnlp create mode 100644 Core/src/main/jnlp/OpenCL4Java.jnlp create mode 100644 Core/src/main/jnlp/ParticlesDemo.jnlp create mode 100644 Core/src/main/jnlp/ScalaCL.jnlp create mode 100644 Core/src/main/velocity/com/nativelibs4java/opencl/CLBuffer.java create mode 100644 Core/src/main/velocity/com/nativelibs4java/opencl/CLContext.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/AbstractCommon.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/BinaryKernelTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/BufferReadTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/BufferTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/CLTestUtils.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/ImageTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/InfoGettersTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/JOGLTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/OpenCL4JavaBasicTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/opencl/OpenCL4JavaBenchmarkTest.java create mode 100644 Core/src/test/java/com/nativelibs4java/test/BenchmarkUtils.java create mode 100644 Core/src/test/java/com/nativelibs4java/test/MiscTestUtils.java create mode 100644 Core/src/test/resources/com/nativelibs4java/opencl/BufferReadTest.c create mode 100644 Demos/.classpath create mode 100644 Demos/.project create mode 100644 Demos/.settings/org.eclipse.jdt.core.prefs create mode 100644 Demos/.settings/org.maven.ide.eclipse.prefs create mode 100644 Demos/pom.xml create mode 100644 Demos/src/main/java/com/nativelibs4java/opencl/demos/SetupUtils.java create mode 100644 Demos/src/main/java/com/nativelibs4java/opencl/demos/hardware/HardwareReport.java create mode 100644 Demos/src/main/java/com/nativelibs4java/opencl/demos/mandelbrot/MandelbrotDemo.java create mode 100644 Demos/src/main/java/com/nativelibs4java/opencl/demos/random/ParallelRandomDemo.java create mode 100644 Demos/src/main/java/com/nativelibs4java/opencl/demos/sobelfilter/SobelFilterDemo.java create mode 100644 Demos/src/main/java/com/nativelibs4java/opencl/demos/vectoradd/VectorAdd.java create mode 100644 Demos/src/main/opencl/com/nativelibs4java/opencl/demos/mandelbrot/Mandelbrot.cl create mode 100644 Demos/src/main/opencl/com/nativelibs4java/opencl/demos/sobelfilter/SimpleSobel.cl create mode 100644 Demos/src/test/java/com/nativelibs4java/opencl/demos/TestReport.java create mode 100644 Generator/.classpath create mode 100644 Generator/.project create mode 100644 Generator/.settings/org.eclipse.jdt.core.prefs create mode 100644 Generator/.settings/org.maven.ide.eclipse.prefs create mode 100644 Generator/pom.xml create mode 100644 Generator/src/main/java/com/nativelibs4java/opencl/generator/JavaCLGenerator.java create mode 100644 Generator/src/main/java/com/nativelibs4java/opencl/generator/JavaCLGeneratorMojo.java create mode 100644 InteractiveImageDemo/pom.xml create mode 100644 InteractiveImageDemo/project/build.properties create mode 100644 InteractiveImageDemo/project/build/InteractiveImageDemoProject.scala create mode 100644 InteractiveImageDemo/src/main/java/com/nativelibs4java/opencl/demos/interactiveimage/InteractiveImageDemo.java create mode 100644 InteractiveImageDemo/src/main/java/com/nativelibs4java/opencl/demos/interactiveimage/Utils.java create mode 100644 InteractiveImageDemo/src/main/resources/examples/Blur.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/Convolution.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/DesaturateColors.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/DummySample.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/Identity.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/LuminanceThreshold.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/NaiveDenoising.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/QueryFormat.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/RichardsonLucyDeconvolution.cl create mode 100644 InteractiveImageDemo/src/main/resources/examples/SobelFilter.cl create mode 100644 InteractiveImageDemo/src/main/resources/images/lena.jpg create mode 100644 InteractiveImageDemo/src/main/resources/images/mandrill.jpg create mode 100644 JavaCL/pom.xml create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/LinearAlgebraUtils.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/OpenCLType.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/ParallelMath.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/ParallelRandom.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/ReductionUtils.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/Transformer.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/fft/AbstractDFT.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/fft/AbstractFFTPow2.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/fft/DoubleDFT.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/fft/DoubleFFTPow2.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/fft/FloatDFT.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/fft/FloatFFTPow2.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/fft/package-info.java create mode 100644 JavaCL/src/main/java/com/nativelibs4java/opencl/util/package-info.java create mode 100644 JavaCL/src/main/opencl/com/nativelibs4java/opencl/util/LinearAlgebraKernels.c create mode 100644 JavaCL/src/main/opencl/com/nativelibs4java/opencl/util/XORShiftRandom.c create mode 100644 JavaCL/src/main/opencl/com/nativelibs4java/opencl/util/fft/DoubleDFTProgram.cl create mode 100644 JavaCL/src/main/opencl/com/nativelibs4java/opencl/util/fft/DoubleFFTProgram.cl create mode 100644 JavaCL/src/main/opencl/com/nativelibs4java/opencl/util/fft/FloatDFTProgram.cl create mode 100644 JavaCL/src/main/opencl/com/nativelibs4java/opencl/util/fft/FloatFFTProgram.cl create mode 100644 JavaCL/src/main/resources/com/nativelibs4java/opencl/util/Reduction.c create mode 100644 JavaCL/src/test/java/com/nativelibs4java/opencl/util/DiscreteFourierTransformTest.java create mode 100644 JavaCL/src/test/java/com/nativelibs4java/opencl/util/ParallelRandomTest.java create mode 100644 JavaCL/src/test/java/com/nativelibs4java/opencl/util/ReductionTest.java create mode 100644 JavaCLTutorial/pom.xml create mode 100644 JavaCLTutorial/src/main/java/tutorial/DFT.java create mode 100644 JavaCLTutorial/src/main/java/tutorial/DFT2.java create mode 100644 JavaCLTutorial/src/main/opencl/tutorial/DiscreteFourierTransformProgram.c create mode 100644 JavaCLTutorial/src/main/opencl/tutorial/DiscreteFourierTransformProgram.cl create mode 100644 LICENSE.header create mode 100644 LibCL/pom.xml create mode 100644 LibCL/src/main/resources/LibCL/Bits.cl create mode 100644 LibCL/src/main/resources/LibCL/Gaussian7x7.cl create mode 100644 LibCL/src/main/resources/LibCL/ImageConvert.cl create mode 100644 LibCL/src/main/resources/LibCL/ImageConvolution.cl create mode 100644 LibCL/src/main/resources/LibCL/RichardsonLucyImageDeconvolution.cl create mode 100644 LibCL/src/main/resources/LibCL/SobelOperator.cl create mode 100644 LibCL/src/main/resources/LibCL/hsla2rgba.cl create mode 100644 LibCL/src/main/resources/LibCL/rgba2hsla.cl create mode 100644 LibCL/src/main/resources/LibCL/stdlib.h create mode 100644 LibCL/src/main/resources/LibCL/strstr.c create mode 100644 LibCL/src/main/resources/LibCL/strtod.c create mode 100644 LibCL/src/main/resources/LibCL/strtof.c create mode 100644 NumericalBenchmark/pom.xml create mode 100644 NumericalBenchmark/src/main/java/fft/FFTBench.java create mode 100644 NumericalBenchmark/src/main/scala/fft/FFTScala.scala create mode 100644 OpenCL4Java/.classpath create mode 100644 OpenCL4Java/.project create mode 100644 OpenCL4Java/.settings/org.eclipse.jdt.core.prefs create mode 100644 OpenCL4Java/.settings/org.maven.ide.eclipse.prefs create mode 100644 OpenCL4Java/pom.xml create mode 100644 OpenCL4Java/regenerate.cmd create mode 100644 OpenCL4Java/src/main/headers/1.0/CL/cl.h create mode 100644 OpenCL4Java/src/main/headers/1.0/CL/cl_gl.h create mode 100644 OpenCL4Java/src/main/headers/1.0/CL/cl_platform.h create mode 100644 OpenCL4Java/src/main/headers/1.1/CL/cl.h create mode 100644 OpenCL4Java/src/main/headers/1.1/CL/cl_ext.h create mode 100644 OpenCL4Java/src/main/headers/1.1/CL/cl_gl.h create mode 100644 OpenCL4Java/src/main/headers/1.1/CL/cl_gl_ext.h create mode 100644 OpenCL4Java/src/main/headers/1.1/CL/cl_platform.h create mode 100644 OpenCL4Java/src/main/headers/1.1/CL/opencl.h create mode 100644 OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/OpenCLLibrary.java create mode 100644 OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/OpenGLContextUtils.java create mode 100644 OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/cl_buffer_region.java create mode 100644 OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/cl_image_format.java create mode 100644 OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/package-info.java create mode 100644 OpenCL4Java/src/main/jnaerator/OpenCL.MacOSX.jnaerator create mode 100644 OpenCL4Java/src/main/jnaerator/OpenCL.OtherPlatforms.jnaerator create mode 100644 OpenCL4Java/src/main/jnaerator/OpenCL.Win32ATIStream.jnaerator create mode 100644 OpenCL4Java/src/main/jnaerator/OpenCL.base.jnaerator create mode 100644 OpenCL4Java/src/main/jnaerator/config.jnaerator create mode 100644 OpenGLDemos/pom.xml create mode 100644 OpenGLDemos/src/main/java/com/nativelibs4java/opencl/demos/JavaCLSettingsPanel.form create mode 100644 OpenGLDemos/src/main/java/com/nativelibs4java/opencl/demos/JavaCLSettingsPanel.java create mode 100644 OpenGLDemos/src/main/java/com/nativelibs4java/opencl/demos/particles/ParticlesDemo.java create mode 100644 OpenGLDemos/src/main/opencl/com/nativelibs4java/opencl/demos/particles/HSVtoRGB.c create mode 100644 OpenGLDemos/src/main/opencl/com/nativelibs4java/opencl/demos/particles/ParticlesDemoProgram.c create mode 100644 Parent/.classpath create mode 100644 Parent/.project create mode 100644 Parent/.settings/org.eclipse.jdt.core.prefs create mode 100644 Parent/.settings/org.maven.ide.eclipse.prefs create mode 100644 Parent/pom.xml create mode 100644 ScalaCL.svg create mode 100644 getJOGL create mode 100644 pom.xml create mode 100644 runComp create mode 100644 runComp.cmd diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..9c0c21ef --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Jan 28 23:48:24 CET 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.maven.ide.eclipse.prefs b/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 00000000..09e51cf4 --- /dev/null +++ b/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Sat Jan 30 11:48:04 CET 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 00000000..8c34af8e --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,159 @@ +Current development version (1.0-SNAPSHOT) + +... + +Version 1.0.0-RC1 (r2130, 20110621) + +- BridJ version now becomes the default : the JNA version is still maintained and available with all Maven artifact ids suffixed with "-jna" (BridJ-based JavaCL's main artifact is now "javacl", while the JNA-based version is "javacl-jna") +- added simple Fourier-analysis classes (package com.nativelibs4java.opencl.util.fft), with double and float variants, usable with primitive arrays or OpenCL buffers : + - naive Discrete Fourier Transform (DFT) + - Fast Fourier Transform (FFT) for power-of-two arrays / buffers (performs better than Apache Commons on a CPU) +- added some compiler options to CLProgram : + - setFastRelaxedMath() (triggers all the others !) + - setFiniteMathOnly() + - setUnsafeMathOptimizations() + - setMadEnable() + - setNoSignedZero() +- added CLContext.createBuffer(Usage, Buffer) +- added CLBuffer.copyTo(CLQueue, CLMem destination, CLEvent...) and CLBuffer.emptyClone(Usage) +- added NIOUtils.indirectBuffer(size, bufferClass) +- added CLContext.toString +- deprecated CLXXXBuffer in favor of CLBuffer (CLIntBuffer becomes CLBuffer, etc...) +- changed CLContext.createBuffer(Usage, length, class) to createBuffer(Usage, class, length) to match the JavaCL/BridJ API (and provoke migration issues : people should now use a primitive class rather than an NIO buffer class !!! +- complete rewrite of CLBuffer genericity to unify with the BridJ port : CLBuffer is now CLBuffer, and CLBuffer.read/write/map are no longer strongly typed (it is implicitely typed with Buffer subclasses for compatibility with existing code). The BridJ port will be favoured, and its read/write/map methods use typed Pointer. +- complete rewrite of UJMP Matrix implementation, using principles borrowed from ScalaCL +- fixed issue #66 (create temp files in ~/.javacl subdirectories instead of /tmp) +- fixed OpenGL sharing on MacOS X +- fixed CLProgram.getBinaries() in some cases +- fixed CLBuffer.read on indirect buffers +- fixed NPE that happens with null varargs CLEvent[] array +- fixed length = 1 case in reduction utility +- fixed ATI detection ("ATI Stream" now replaced by "AMD Accelerated Parallel Processing", cf. Csaba's comment in issue #39) +- fixed issue #55 : applied Kazo Csaba's patch to fix the bounds of CLBuffer.map's returned buffer +- fixed inheritance of CLBuildException (now derives from CLException) + +Version 1.0-beta-6 (r1637, 20100204) + +- Fixed support of ATI Stream 2.3 (CPU) +- New interactive image kernel demo : lets you edit and test image kernels in a snap (bundled with a few samples) +- Experimental BridJ port with same functionality as JNA-powered version, but smaller and faster (JAR weighs 750 kB instead of 1.8 MB, overhead per-function call about 10x smaller) +- Added automatic and transparent program binaries caching : + - Disabled by default on ATI Stream. + - Can force on/off with : + - property -Djavacl.cacheBinaries=true/false + - environment variable JAVACL_CACHE_BINARIES=1/0 + - methods CLContext.setCacheBinaries and CLProgram.setCached +- JavaCL.createBestContext now takes an ordered list of CLPlatform.DeviceFeature enums that help prioritize the features considered as "best" (list can be empty or contain any of CPU, GPU, DoubleSupport, MaxComputeUnits, NativeEndianness, ImageSupport, MostImageFormats...). These features are preferences, not requirements : with createBestContext(GPU, MaxComputeUnits) you might end up getting a CPU-based context if there's no GPU available, but you'll have the most powerful GPU (in terms of compute units) if there are two of them. +- Kernels can now include files that are in the classpath (+ added CLProgram.addInclude that accepts directories and base URLs) +- Added LibCL : growing collection of OpenCL functions that can be included from any JavaCL kernel +- CLKernel.enqueueNDRange has a new overload without localWorkSizes argument (it's then adjusted to a good value by the OpenCL implementation). +- ScalaCLv2 was rewritten to fit nicely into Scala's collections framework. +- Added CLContext.createProgram(Map) to create from saved binaries (contribution from Kazo Csaba, issue #30) +- Added CLProgram.addBuildOption(String) +- Fixed CLBuffer.copyTo +- Demos now use the latest jogamp JOGL binaries (see the updated build instructions : http://code.google.com/p/javacl/wiki/Build) + +Version 1.0-beta-5 (r1067, 20100717) + +- Now using a nice configuration dialog when launching ParticlesDemo : has +optional OpenCL settings with "Fastest", "Normal" and "Safest" presets + +detailed platform and device choice (with optional OpenGL sharing choice). +- Added optional context properties map argument to JavaCL.createContext (can be nulled +out) +- Fixed issue #18: CLImage.write calls enqueueImageRead ! +- Documented workaround for Linux crashes (issue #20) : http://code.google.com/p/javacl/wiki/TroubleShootingJavaCLOnLinux +- Fixed issue #21: NIOUtils.put() doesn't accept ByteBuffer +- Fixed issue #25: CLEvent.waitFor bug causes segfault +- OpenCL 1.1 support : + - CLContext.createUserEvent() + - CLUserEvent.setStatus(int), setCompleted() + - CLEvent.setCallback(status, callbac), setCompletionCallback(callback) + - CLBuffer.createSubBuffer(usage, offset, length) + - CLContext.getDeviceCount() + - CLDevice.getOpenCLVersion() + - CLDevice.isHostUnifiedMemory() + - CLDevice.getNativeVectorWidthXXX() methods + - CLMem.setDestructorCallback(callback) + - CLKernel.getPreferredWorkGroupSizeMultiple() + - CLKernel.enqueueNDRange overload with potentially non-null globalOffsets + - CLImageFormat.ChannelOrder.Rx, RGx, RGBx +- Faster enums +- Check for cl_amd_fp64 in CLDevice.isDoubleSupported() +- Fixed CLProgram.getBinaries() +- Fixed issue #22 (maven pom issue) + +Version 1.0-beta-4 (r760, 20100121) + +- Changed semantics of offset & length arguments in typed CLxxxBuffer.read / write / map methods : now expressed in elements, not in bytes (e.g. 4 bytes per element for CLIntBuffer) +- Added OpenGL interoperability methods to CLContext and CLQueue (can create a CLByteBuffer from an OpenGL buffer object, a CLImage2D/3D from an OpenGL 2D/3D texture or a renderbuffer). +- Added OpenGL-compatible context creation methods to JavaCL & CLPlatform classes +- Added basic reduction support in ReductionUtils (cumulative additions, multiplications, min, max...) +- Created javacl-demos package, with Particles, Hardware Report and Mandelbrot demos... +- Finished migration from NativeLong to NativeSize (changes only the low-level bindings) +- Added profiling methods to CLEvent (+ facility CLDevice.createProfilingQueue()) +- Better JavaDoc for low-level bindings (links to Khronos online manual pages) +- Added deferred program allocation : CLProgram.addSource(String), CLProgram.allocate() (called automatically)... +- Added very simple OpenCL backend for UJMP (Universal Java Matrix Package), which does matrix multiplications in OpenCL. +- Created a kernel wrapper autogenerator (Maven plugin based on JNAerator) : translates all constants on the Java side and presents kernels as methods with the correct Java argument types. It assumes OpenCL kernels (*.c, *.cl) are in src/main/opencl +- Added wrappers around clGetKernelWorkGroupInfo +- Fixed respect of endianness of devices that have different endianness than platform +- Fixed issue #10: "getMaxWorkItemSizes() fails on win7 64 GTX260" + +Version 1.0-beta-3 (r , 20091030) + +- Fixed Issue #8 : NativeLong's can not represent size_t on windows x64 system (all user code that uses the low-level bindings needs to be updated : NativeLong -> NativeSize) +- Added CLContext/CLDevice.isDoubleSupported, isHalfSupported, isByteAddressableStoreSupported +- Added If function to ScalaCL (operates on statements or on expressions) +- Added CLAbstractEntity.release() +- Fixed Issue #4 : CLContext.createContext(CLDevice... devices) created context on only one device +- Regenerated the low level bindings with latest JNAerator : now using NativeSize class instead of NativeLong for size_t (fixes Issue #8) +- Fixed Issue #5 : fixed formatting of CLPlatform.toString() +- Fixed Issue #6 : use max X workgroup dimension for better benchmark speed +- Fixed Issue #7 : CLMem class bug in Usage.WriteOnly and Usage.ReadWrite +- Fixed Issue #11 : call clRetainMemObject when sharing a cl_mem between CLBuffer instances. +- Choose 'best' device in benchmark test + +Version 1.0-beta-2 + +- JAR is now self-sufficient (includes JNA + JNAerator's runtime classes) +- Added CLKernel.setLocalArg(argIndex, localArgByteLength) +- Allow localWorkSizes to be null in enqueueNDRange +- Added support for barriers and markers in CLQueue +- Fixed issue #2 : enqueueNDRange does not work for nDim > 1 +- Added CLDevice.getMaxWorkItemSizes() +- CLDevice.toString() now only prints the name +- Moved method createContext from CLContext to CLPlatform +- Added all the CL_DEVICE_PREFERRED_VECTOR_WIDTH_XXX infos to CLDevice as getPreferredVectorWithXXX() +- Changed return type of getExtensions() method of both CLPlatform and CLDevice from String to String[] +- Added com.nativelibs4java.opencl.HardwareReport (with main method) : outputs html report with devices stats +- Rationalized naming of all enums : CL_ENTITY_ATTRIBUTE_SOME_VALUE = CLEntity.Attribute.SomeValue (enum item SomeValue in enum Attribute in class CLEntity) +- Added full support of images : + - CLContext.getSupportedImageFormats + CLImageFormat and associated enums + - CLImage2D, CLImage3D and corresponding creation methods in CLContext + all image info getters +- CLMem is now an abstract base class + - CLBuffer with typed subclasses (CLByteBuffer, CLIntBuffer..) + - To create a CLBuffer : context.createIntBuffer(Input, size) + - Added CLBuffer.copyTo (clEnqueueCopyBuffer) + - Each typed CLBuffer subclass has map, mapLater, read methods that return typed NIO buffers +- Added full typing of OpenCL Exceptions (now possible to selectively catch a CLException.OutOfHostMemory, for instance) +- Added hashCode and equals method to most classes +- Added ability to create out of order queues and change queue properties after creation + +Version 1.0-beta-1 + +- New CLPlatform class (~ OpenCL implementation) which now hosts the list*Devices(...) methods +- Entry point of library is now OpenCL4Java.listPlatforms() +- New CLEvent class, returned by all enqueue* methods (with methods waitFor, invokeUponCompletion...) +- Better separation between blocking and non blocking calls +- New CLSampler class supported as argument of CLKernel +- Many info getters with typesafe enums / enum sets in classes CLDevice, CLPlatform, CLKernel... +- Much more complete JavaDoc : http://nativelibs4java.sourceforge.net/sites/OpenCL4Java/apidocs/ +- Example & benchmark classes became JUnit tests and moved here : http://code.google.com/p/nativelibs4java/source/browse/#svn/trunk/lib... + +While this release is rather OpenCL4Java-focused, ScalaCL also got its bunch of enhancements : +- Added scalar variables IntVar, FloatVar, ShortVar... +- 'local' keyword can be added to variables so they're local to the programs : val x = FloatVar local +- Added many OpenCL math functions +- Added methods ArrayVar.write(Range), ArrayVar.write(Seq) +- Various bugfixes + diff --git a/Common/.classpath b/Common/.classpath new file mode 100644 index 00000000..4cf68d6b --- /dev/null +++ b/Common/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Common/.project b/Common/.project new file mode 100644 index 00000000..45e6991c --- /dev/null +++ b/Common/.project @@ -0,0 +1,29 @@ + + + Common + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + org.eclipse.iam.jdt.core.mavenIncrementalBuilder + + + + + + org.maven.ide.eclipse.maven2Nature + org.eclipse.iam.jdt.core.mavenNature + org.eclipse.jdt.core.javanature + + diff --git a/Common/.settings/org.eclipse.jdt.core.prefs b/Common/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..377e7a5f --- /dev/null +++ b/Common/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Jan 28 23:48:17 CET 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/Common/.settings/org.maven.ide.eclipse.prefs b/Common/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 00000000..a03b0328 --- /dev/null +++ b/Common/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Thu Jan 28 23:46:13 CET 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/Common/pom.xml b/Common/pom.xml new file mode 100644 index 00000000..fcc47d4d --- /dev/null +++ b/Common/pom.xml @@ -0,0 +1,32 @@ + + 4.0.0 + com.nativelibs4java + nativelibs4java-utils + NativeLibs4Java Common Utilities + http://code.google.com/p/nativelibs4java/ + 1.3 + jar + + + com.nativelibs4java + opencl4java-parent-jna + 1.0.0-RC1 + ../Parent + + + + + + com.ochafik + ochafik-util + ${jnaerator.version} + compile + + + + + + + diff --git a/Common/src/main/java/com/nativelibs4java/util/Cache.java b/Common/src/main/java/com/nativelibs4java/util/Cache.java new file mode 100644 index 00000000..9c4e536c --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/Cache.java @@ -0,0 +1,30 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; + +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author ochafik + */ +public abstract class Cache { + Map map; + public Cache() { + this(new HashMap()); + } + public Cache(Map map) { + this.map = map; + } + public synchronized V get(K key) { + V value = map.get(key); + if (value == null) + map.put(key, value = createValue(key)); + return value; + } + public abstract V createValue(K key); +} diff --git a/Common/src/main/java/com/nativelibs4java/util/EnumValue.java b/Common/src/main/java/com/nativelibs4java/util/EnumValue.java new file mode 100644 index 00000000..85c24b39 --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/EnumValue.java @@ -0,0 +1,24 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that defines the integer value for a Java enum item + * @author ochafik + */ +@Target({ElementType.TYPE, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface EnumValue { + /** + * Integral representation of the enum item + */ + long value(); +} diff --git a/Common/src/main/java/com/nativelibs4java/util/EnumValues.java b/Common/src/main/java/com/nativelibs4java/util/EnumValues.java new file mode 100644 index 00000000..f4e6bdd7 --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/EnumValues.java @@ -0,0 +1,111 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.nativelibs4java.util; + +import java.util.*; + +/** + * Methods to ease conversion between EnumValue-annotated enums and their integer value. + * @author ochafik + */ +public class EnumValues { + + private static class Cache> { + + final Map enumsByValue = new LinkedHashMap(); + final Map valuesByEnum = new LinkedHashMap(); + + public Cache(Class enumClass) { + + if (ValuedEnum.class.isAssignableFrom(enumClass)) { + for (E e : enumClass.getEnumConstants()) { + long value = ((ValuedEnum)e).value(); + enumsByValue.put(value, e); + valuesByEnum.put(e, value); + } + } else { + for (E e : enumClass.getEnumConstants()) { + EnumValue ev = null; + try { + ev = enumClass.getField(e.name()).getAnnotation(EnumValue.class); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + if (ev == null) { + throw new IllegalArgumentException("Enum value is not annotated with the " + EnumValue.class.getName() + " annotation : " + e); + } + long value = ev.value(); + enumsByValue.put(value, e); + valuesByEnum.put(e, value); + } + } + } + } + private static final Map>, Cache> caches = new HashMap>, Cache>(); + + @SuppressWarnings("unchecked") + private static synchronized > Cache getCache(Class enumClass) { + Cache cache = (Cache) caches.get(enumClass); + if (cache == null) { + caches.put(enumClass, cache = new Cache(enumClass)); + } + return cache; + } + + /** + * Get the first enum item in enum class E which EnumValue value is equal to value + * @param type of the enum + * @param value + * @param enumClass + * @return first enum item with matching value, null if there is no matching enum item + */ + public static > E getEnum(long value, Class enumClass) { + return getCache(enumClass).enumsByValue.get(value); + } + + /** + * Get the set of all the enum item in enum class E which EnumValue value flags are all present in value + * @param type of the enum + * @param value + * @param enumClass + * @return enum items with matching value flags + */ + public static > EnumSet getEnumSet(long value, Class enumClass) { + EnumSet set = EnumSet.noneOf(enumClass); + for (Map.Entry pair : getCache(enumClass).enumsByValue.entrySet()) { + long ev = pair.getKey(); + if ((ev & value) == ev) { + set.add(pair.getValue()); + } + } + return set; + } + + /** + * Get the integer value associated with an enum item + * @see EnumValue + * @param enumItem + * @return + */ + @SuppressWarnings("unchecked") + public static > long getValue(E enumItem) { + return getCache((Class) enumItem.getDeclaringClass()).valuesByEnum.get(enumItem); + } + + /** + * Get the integer value resulting from ORing all the values of all the enum items present in the enum set. + * @see EnumValues#getValue(java.lang.Enum) + * @see EnumValue + * @param enumItem + * @return + */ + public static > long getValue(EnumSet set) { + long v = 0; + for (E e : set) { + v |= getValue(e); + } + return v; + } +} diff --git a/Common/src/main/java/com/nativelibs4java/util/IOUtils.java b/Common/src/main/java/com/nativelibs4java/util/IOUtils.java new file mode 100644 index 00000000..a50d3950 --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/IOUtils.java @@ -0,0 +1,56 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; + +import java.io.*; +import java.net.*; + +/** + * + * @author Olivier + */ +public class IOUtils { + public static String readText(File f) throws IOException { + Reader in = new FileReader(f); + try { + return readText(in); + } finally { + in.close(); + } + } + public static String readText(InputStream in) throws IOException { + return readText(new InputStreamReader(in)); + } + public static String readText(URL url) throws IOException { + return readTextClose(url.openStream()); + } + public static String readTextClose(InputStream in) throws IOException { + return readTextClose(new InputStreamReader(in)); + } + public static String readTextClose(Reader in) throws IOException { + try { + return readText(in); + } finally { + in.close(); + } + } + public static String readText(Reader in) throws IOException { + StringBuffer b = new StringBuffer(); + BufferedReader bin = new BufferedReader(in); + String line; + while ((line = bin.readLine()) != null) { + b.append(line); + b.append('\n'); + } + return b.toString(); + } + public static void readWrite(InputStream in, OutputStream out) throws IOException { + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) + out.write(buf, 0, len); + } +} diff --git a/Common/src/main/java/com/nativelibs4java/util/ImageUtils.java b/Common/src/main/java/com/nativelibs4java/util/ImageUtils.java new file mode 100644 index 00000000..217a7a51 --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/ImageUtils.java @@ -0,0 +1,72 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; + +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferInt; +import java.awt.image.PixelGrabber; +import java.awt.image.WritableRaster; +import java.nio.IntBuffer; + +/** + * + * @author ochafik + */ +public class ImageUtils { + + public static int[] getImageIntPixels(Image image, boolean allowDeoptimizingDirectRead) { + return getImageIntPixels(image, 0, 0, image.getWidth(null), image.getHeight(null), allowDeoptimizingDirectRead); + } + public static int[] getImageIntPixels(Image image, int x, int y, int width, int height, boolean allowDeoptimizingDirectRead) { + if (image instanceof BufferedImage) { + BufferedImage bim = (BufferedImage)image; + WritableRaster raster = bim.getRaster(); + if (allowDeoptimizingDirectRead && + raster.getParent() == null && + raster.getDataBuffer().getNumBanks() == 1) + { + DataBuffer b = bim.getRaster().getDataBuffer(); + if (b instanceof DataBufferInt) { + int[] array = ((DataBufferInt)b).getData(); + return array; + } + } + return bim.getRGB(x, y, width, height, null, 0, width); + } + PixelGrabber grabber = new PixelGrabber(image, x, y, width, height, true); + try { + grabber.grabPixels(); + return (int[])grabber.getPixels(); + } catch (InterruptedException ex) { + throw new RuntimeException("Pixel read operation was interrupted", ex); + } + } + + public static void setImageIntPixels(BufferedImage image, boolean allowDeoptimizingDirectRead, IntBuffer pixels) { + setImageIntPixels(image, 0, 0, image.getWidth(null), image.getHeight(null), allowDeoptimizingDirectRead, pixels); + } + public static void setImageIntPixels(BufferedImage bim, int x, int y, int width, int height, boolean allowDeoptimizingDirectRead, IntBuffer pixels) { + WritableRaster raster = bim.getRaster(); + if (allowDeoptimizingDirectRead && + raster.getParent() == null && + raster.getDataBuffer().getNumBanks() == 1) + { + DataBuffer b = bim.getRaster().getDataBuffer(); + if (b instanceof DataBufferInt) { + IntBuffer.wrap(((DataBufferInt)b).getData()).put(pixels); + return; + } + } + + IntBuffer b = IntBuffer.allocate(width * height); + b.put(pixels); + b.rewind(); + int[] array = b.array(); + bim.setRGB(x, y, width, height, array, 0, width); + } +} diff --git a/Common/src/main/java/com/nativelibs4java/util/NIOUtils.java b/Common/src/main/java/com/nativelibs4java/util/NIOUtils.java new file mode 100644 index 00000000..d27cdf1a --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/NIOUtils.java @@ -0,0 +1,376 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; +import java.nio.*; +/** + * NIO Buffer util methods + * @author ochafik + */ +public class NIOUtils +{ + + public static Class getBufferClass(Class primitiveClass) { + if (primitiveClass == Byte.class || primitiveClass == byte.class) + return ByteBuffer.class; + if (primitiveClass == Short.class || primitiveClass == short.class) + return ShortBuffer.class; + if (primitiveClass == Character.class || primitiveClass == char.class) + return CharBuffer.class; + if (primitiveClass == Integer.class || primitiveClass == int.class) + return IntBuffer.class; + if (primitiveClass == Long.class || primitiveClass == long.class) + return LongBuffer.class; + if (primitiveClass == Float.class || primitiveClass == float.class) + return FloatBuffer.class; + if (primitiveClass == Double.class || primitiveClass == double.class) + return DoubleBuffer.class; + throw new UnsupportedOperationException("Unhandled primitive type : " + primitiveClass.getName()); + } + public static Class getPrimitiveClass(Class bufferClass) { + if (bufferClass == ByteBuffer.class) return Byte.class; + if (bufferClass == ShortBuffer.class) return Short.class; + if (bufferClass == CharBuffer.class) return Character.class; + if (bufferClass == IntBuffer.class) return Integer.class; + if (bufferClass == LongBuffer.class) return Long.class; + if (bufferClass == FloatBuffer.class) return Float.class; + if (bufferClass == DoubleBuffer.class) return Double.class; + throw new UnsupportedOperationException("Unhandled buffer type : " + bufferClass.getName()); + } + + /** + * Bulk-copy all of the input buffer into output byte buffer + * @param inputBytes + * @param output + */ + public static void put(Buffer input, Buffer output) { + if (input instanceof ByteBuffer) + put((ByteBuffer)input, output); + else if (output instanceof ByteBuffer) + put(input, (ByteBuffer)output); + else if (input instanceof IntBuffer && output instanceof IntBuffer) + ((IntBuffer)output).duplicate().put((IntBuffer)input); + else if (input instanceof LongBuffer && output instanceof LongBuffer) + ((LongBuffer)output).duplicate().put((LongBuffer)input); + else if (input instanceof ShortBuffer && output instanceof ShortBuffer) + ((ShortBuffer)output).duplicate().put((ShortBuffer)input); + else if (input instanceof CharBuffer && output instanceof CharBuffer) + ((CharBuffer)output).duplicate().put((CharBuffer)input); + else if (input instanceof DoubleBuffer && output instanceof DoubleBuffer) + ((DoubleBuffer)output).duplicate().put((DoubleBuffer)input); + else if (input instanceof FloatBuffer && output instanceof FloatBuffer) + ((FloatBuffer)output).duplicate().put((FloatBuffer)input); + else + throw new UnsupportedOperationException("Unhandled buffer type : " + input.getClass().getName()); + } + + /** + * Bulk-copy all of the input buffer into output byte buffer + * @param inputBytes + * @param output + */ + public static void put(Buffer input, ByteBuffer outputBytes) { + + if (input instanceof ByteBuffer) + outputBytes.duplicate().put(((ByteBuffer)input).duplicate()); + else if (input instanceof IntBuffer) + outputBytes.asIntBuffer().put(((IntBuffer)input).duplicate()); + else if (input instanceof LongBuffer) + outputBytes.asLongBuffer().put(((LongBuffer)input).duplicate()); + else if (input instanceof ShortBuffer) + outputBytes.asShortBuffer().put(((ShortBuffer)input).duplicate()); + else if (input instanceof CharBuffer) + outputBytes.asCharBuffer().put(((CharBuffer)input).duplicate()); + else if (input instanceof DoubleBuffer) + outputBytes.asDoubleBuffer().put(((DoubleBuffer)input).duplicate()); + else if (input instanceof FloatBuffer) + outputBytes.asFloatBuffer().put(((FloatBuffer)input).duplicate()); + else + throw new UnsupportedOperationException("Unhandled buffer type : " + input.getClass().getName()); + + } + + /** + * Bulk-copy all input bytes into output buffer + * @param inputBytes + * @param output + */ + public static void put(ByteBuffer inputBytes, Buffer output) { + + if (output instanceof IntBuffer) + ((IntBuffer)output).put(inputBytes.asIntBuffer()); + else if (output instanceof LongBuffer) + ((LongBuffer)output).put(inputBytes.asLongBuffer()); + else if (output instanceof ShortBuffer) + ((ShortBuffer)output).put(inputBytes.asShortBuffer()); + else if (output instanceof CharBuffer) + ((CharBuffer)output).put(inputBytes.asCharBuffer()); + else if (output instanceof ByteBuffer) + ((ByteBuffer)output).put(inputBytes); + else if (output instanceof DoubleBuffer) + ((DoubleBuffer)output).put(inputBytes.asDoubleBuffer()); + else if (output instanceof FloatBuffer) + ((FloatBuffer)output).put(inputBytes.asFloatBuffer()); + else if (output instanceof CharBuffer) + ((CharBuffer)output).put(inputBytes.asCharBuffer()); + else + throw new UnsupportedOperationException("Unhandled buffer type : " + output.getClass().getName()); + + } + + public static IntBuffer directCopy(IntBuffer b, ByteOrder order) { + return directCopy((Buffer)b, order).asIntBuffer(); + } + public static LongBuffer directCopy(LongBuffer b, ByteOrder order) { + return directCopy((Buffer)b, order).asLongBuffer(); + } + public static ShortBuffer directCopy(ShortBuffer b, ByteOrder order) { + return directCopy((Buffer)b, order).asShortBuffer(); + } + public static CharBuffer directCopy(CharBuffer b, ByteOrder order) { + return directCopy((Buffer)b, order).asCharBuffer(); + } + public static DoubleBuffer directCopy(DoubleBuffer b, ByteOrder order) { + return directCopy((Buffer)b, order).asDoubleBuffer(); + } + public static FloatBuffer directCopy(FloatBuffer b, ByteOrder order) { + return directCopy((Buffer)b, order).asFloatBuffer(); + } + public static ByteBuffer directCopy(Buffer b, ByteOrder order) { + ByteBuffer copy = ByteBuffer.allocateDirect((int)getSizeInBytes(b)).order(order == null ? ByteOrder.nativeOrder() : order); + put(b, copy); + return copy; + } + + /** + * Creates a direct int buffer of the specified size (in elements) and a native byte order + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @return view on new direct buffer + */ + public static IntBuffer directInts(int size, ByteOrder order) { + return ByteBuffer.allocateDirect(size * 4).order(order == null ? ByteOrder.nativeOrder() : order).asIntBuffer(); + } + + /** + * Creates a direct lpng buffer of the specified size (in elements) and a native byte order + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @return view on new direct buffer + */ + public static LongBuffer directLongs(int size, ByteOrder order) { + return ByteBuffer.allocateDirect(size * 8).order(order == null ? ByteOrder.nativeOrder() : order).asLongBuffer(); + } + + /** + * Creates a direct short buffer of the specified size (in elements) and a native byte order + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @return view on new direct buffer + */ + public static ShortBuffer directShorts(int size, ByteOrder order) { + return ByteBuffer.allocateDirect(size * 2).order(order == null ? ByteOrder.nativeOrder() : order).asShortBuffer(); + } + + /** + * Creates a direct byte buffer of the specified size (in elements) and a native byte order + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @return new direct buffer + */ + public static ByteBuffer directBytes(int size, ByteOrder order) { + return ByteBuffer.allocateDirect(size).order(order == null ? ByteOrder.nativeOrder() : order); + } + + /** + * Creates a direct float buffer of the specified size (in elements) and a native byte order + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @return view on new direct buffer + */ + public static FloatBuffer directFloats(int size, ByteOrder order) { + return ByteBuffer.allocateDirect(size * 4).order(order == null ? ByteOrder.nativeOrder() : order).asFloatBuffer(); + } + + /** + * Creates a direct char buffer of the specified size (in elements) and a native byte order + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @return view on new direct buffer + */ + public static CharBuffer directChars(int size, ByteOrder order) { + return ByteBuffer.allocateDirect(size * 4).order(order == null ? ByteOrder.nativeOrder() : order).asCharBuffer(); + } + + /** + * Creates a direct double buffer of the specified size (in elements) and a native byte order + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @return view on new direct buffer + */ + public static DoubleBuffer directDoubles(int size, ByteOrder order) { + return ByteBuffer.allocateDirect(size * 8).order(order == null ? ByteOrder.nativeOrder() : order).asDoubleBuffer(); + } + + /** + * Creates a direct buffer of the specified size (in elements) and type.. + * @param size size of the buffer in elements + * @param order byte order of the direct buffer + * @param bufferClass type of the buffer. Must be one of IntBuffer.class, LongBuffer.class, ShortBuffer.class, ByteBuffer.class, DoubleBuffer.class, FloatBuffer.class + * @return view on new direct buffer + */ + @SuppressWarnings("unchecked") + public static B directBuffer(int size, ByteOrder order, Class bufferClass) { + if (IntBuffer.class.isAssignableFrom(bufferClass)) + return (B)directInts(size, order); + if (LongBuffer.class.isAssignableFrom(bufferClass)) + return (B)directLongs(size, order); + if (ShortBuffer.class.isAssignableFrom(bufferClass)) + return (B)directShorts(size, order); + if (ByteBuffer.class.isAssignableFrom(bufferClass)) + return (B)directBytes(size, order); + if (DoubleBuffer.class.isAssignableFrom(bufferClass)) + return (B)directDoubles(size, order); + if (FloatBuffer.class.isAssignableFrom(bufferClass)) + return (B)directFloats(size, order); + if (CharBuffer.class.isAssignableFrom(bufferClass)) + return (B)directChars(size, order); + + throw new UnsupportedOperationException("Cannot create direct buffers of type " + bufferClass.getName()); + } + /** + * Creates a indirect buffer of the specified size (in elements) and type.. + * @param size size of the buffer in elements + * @param bufferClass type of the buffer. Must be one of IntBuffer.class, LongBuffer.class, ShortBuffer.class, ByteBuffer.class, DoubleBuffer.class, FloatBuffer.class + * @return view on new direct buffer + */ + @SuppressWarnings("unchecked") + public static B indirectBuffer(int size, Class bufferClass) { + if (IntBuffer.class.isAssignableFrom(bufferClass)) + return (B)IntBuffer.allocate(size); + if (LongBuffer.class.isAssignableFrom(bufferClass)) + return (B)LongBuffer.allocate(size); + if (ShortBuffer.class.isAssignableFrom(bufferClass)) + return (B)ShortBuffer.allocate(size); + if (ByteBuffer.class.isAssignableFrom(bufferClass)) + return (B)ByteBuffer.allocate(size); + if (DoubleBuffer.class.isAssignableFrom(bufferClass)) + return (B)DoubleBuffer.allocate(size); + if (FloatBuffer.class.isAssignableFrom(bufferClass)) + return (B)FloatBuffer.allocate(size); + if (CharBuffer.class.isAssignableFrom(bufferClass)) + return (B)CharBuffer.allocate(size); + + throw new UnsupportedOperationException("Cannot create indirect buffers of type " + bufferClass.getName()); + } + /** + * Get the size in bytes of a buffer + */ + public static long getSizeInBytes(Buffer b) { + int c = b.capacity(); + return getComponentSizeInBytes(b) * c; + } + + /** + * Get the size in bytes of a primitive component of a buffer + */ + public static int getComponentSizeInBytes(Buffer b) { + if (b instanceof IntBuffer || b instanceof FloatBuffer) + return 4; + if (b instanceof LongBuffer || b instanceof DoubleBuffer) + return 8; + if (b instanceof ShortBuffer || b instanceof CharBuffer) + return 2; + if (b instanceof ByteBuffer) + return 1; + throw new UnsupportedOperationException("Cannot guess byte size of buffers of type " + b.getClass().getName()); + } + + public static void put(B buffer, int position, V value) { + if (buffer instanceof IntBuffer) + ((IntBuffer)buffer).put(position, ((Number)value).intValue()); + else if (buffer instanceof LongBuffer) + ((LongBuffer)buffer).put(position, ((Number)value).longValue()); + else if (buffer instanceof ShortBuffer) + ((ShortBuffer)buffer).put(position, ((Number)value).shortValue()); + else if (buffer instanceof ByteBuffer) + ((ByteBuffer)buffer).put(position, ((Number)value).byteValue()); + else if (buffer instanceof DoubleBuffer) + ((DoubleBuffer)buffer).put(position, ((Number)value).doubleValue()); + else if (buffer instanceof FloatBuffer) + ((FloatBuffer)buffer).put(position, ((Number)value).floatValue()); + else if (buffer instanceof CharBuffer) + ((CharBuffer)buffer).put(position, (char)((Number)value).shortValue()); + else + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + public static V get(B buffer, int position) { + if (buffer instanceof IntBuffer) + return (V)(Integer)((IntBuffer)buffer).get(position); + else if (buffer instanceof LongBuffer) + return (V)(Long)((LongBuffer)buffer).get(position); + else if (buffer instanceof ShortBuffer) + return (V)(Short)((ShortBuffer)buffer).get(position); + else if (buffer instanceof ByteBuffer) + return (V)(Byte)((ByteBuffer)buffer).get(position); + else if (buffer instanceof DoubleBuffer) + return (V)(Double)((DoubleBuffer)buffer).get(position); + else if (buffer instanceof FloatBuffer) + return (V)(Float)((FloatBuffer)buffer).get(position); + else if (buffer instanceof CharBuffer) + return (V)(Character)((CharBuffer)buffer).get(position); + else + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + public static Object getArray(B buffer) { + int length = buffer.capacity(); + if (buffer instanceof IntBuffer) { + int[] a = new int[length]; + ((IntBuffer)buffer).duplicate().get(a); + return a; + } else if (buffer instanceof LongBuffer) { + long[] a = new long[length]; + ((LongBuffer)buffer).duplicate().get(a); + return a; + } else if (buffer instanceof ShortBuffer) { + short[] a = new short[length]; + ((ShortBuffer)buffer).duplicate().get(a); + return a; + } else if (buffer instanceof ByteBuffer) { + byte[] a = new byte[length]; + ((ByteBuffer)buffer).duplicate().get(a); + return a; + } else if (buffer instanceof DoubleBuffer) { + double[] a = new double[length]; + ((DoubleBuffer)buffer).duplicate().get(a); + return a; + } else if (buffer instanceof FloatBuffer) { + float[] a = new float[length]; + ((FloatBuffer)buffer).duplicate().get(a); + return a; + } else + throw new UnsupportedOperationException(); + } + public static B wrapArray(Object a) { + if (a instanceof int[]) + return (B)IntBuffer.wrap((int[])a); + if (a instanceof long[]) + return (B)LongBuffer.wrap((long[])a); + if (a instanceof short[]) + return (B)ShortBuffer.wrap((short[])a); + if (a instanceof byte[]) + return (B)ByteBuffer.wrap((byte[])a); + if (a instanceof float[]) + return (B)FloatBuffer.wrap((float[])a); + if (a instanceof double[]) + return (B)DoubleBuffer.wrap((double[])a); + throw new UnsupportedOperationException("Cannot wrap primitive arrays of type " + a.getClass().getName()); + } + +} diff --git a/Common/src/main/java/com/nativelibs4java/util/ValuedEnum.java b/Common/src/main/java/com/nativelibs4java/util/ValuedEnum.java new file mode 100644 index 00000000..e109b02e --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/ValuedEnum.java @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; + +/** + * + * @author ochafik + */ +public interface ValuedEnum { + long value(); +} diff --git a/Common/src/main/java/com/nativelibs4java/util/ValuedEnums.java b/Common/src/main/java/com/nativelibs4java/util/ValuedEnums.java new file mode 100644 index 00000000..6b305a42 --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/ValuedEnums.java @@ -0,0 +1,34 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; + +import java.util.EnumSet; + +/** + * + * @author ochafik + */ +public class ValuedEnums { + public static > long or(EnumSet enums) { + long value = 0; + for (E e : enums) + value |= ((ValuedEnum)e).value(); + return value; + } + public static > long and(EnumSet enums) { + long value = 0; + boolean first = true; + for (E e : enums) { + long ev = ((ValuedEnum)e).value(); + if (first) { + value = ev; + first = false; + } else + value &= ev; + } + return value; + } +} \ No newline at end of file diff --git a/Common/src/main/java/com/nativelibs4java/util/package-info.java b/Common/src/main/java/com/nativelibs4java/util/package-info.java new file mode 100644 index 00000000..5c2b5a1a --- /dev/null +++ b/Common/src/main/java/com/nativelibs4java/util/package-info.java @@ -0,0 +1,5 @@ +/* + * Util classes and methods related to java.nio package, to JNA, enums, images and file IO. + */ +package com.nativelibs4java.util; + diff --git a/Contributions/Kazo Csaba/BinaryKernelTest - issue 30.java b/Contributions/Kazo Csaba/BinaryKernelTest - issue 30.java new file mode 100644 index 00000000..33a54c41 --- /dev/null +++ b/Contributions/Kazo Csaba/BinaryKernelTest - issue 30.java @@ -0,0 +1,58 @@ +package com.nativelibs4java.opencl; + +import static com.nativelibs4java.util.NIOUtils.directBuffer; +import java.util.Map; +import static org.junit.Assert.assertEquals; + +import java.nio.IntBuffer; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.nativelibs4java.test.MiscTestUtils; + +/** + * + * @author Kazó Csaba + */ +@SuppressWarnings("unchecked") +public class BinaryKernelTest extends AbstractCommon { + + @BeforeClass + public static void setup() { + MiscTestUtils.protectJNI(); + } + + @Test + public void simpleTest() throws CLBuildException { + CLProgram program = context.createProgram( + "__kernel void copy(__global int* a, __global int* b) {\n" + + " int i = get_global_id(0);\n" + + " b[i]=a[i];\n" + + "} "); + program.build(); + Map binaries = program.getBinaries(); + program.release(); + + CLProgram binaryProgram = context.createProgram(binaries); + CLKernel kernel=binaryProgram.createKernel("copy"); + + CLIntBuffer a=context.createIntBuffer(CLMem.Usage.Input, 4); + CLIntBuffer b=context.createIntBuffer(CLMem.Usage.Output, 4); + + IntBuffer source = directBuffer(4, context.getByteOrder(), IntBuffer.class); + for (int i=0; i<4; i++) + source.put(i, 3*i+10); + + a.write(queue, source, true); + + kernel.setArgs(a, b); + kernel.enqueueNDRange(queue, new int[]{4}, new int[]{1}).waitFor(); + + IntBuffer target = b.read(queue); + + assertEquals(target.capacity(), source.capacity()); + for (int i=0; i<4; i++) + assertEquals(source.get(i), target.get(i)); + } +} \ No newline at end of file diff --git a/Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.README b/Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.README new file mode 100644 index 00000000..b156bfaa --- /dev/null +++ b/Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.README @@ -0,0 +1,8 @@ +See http://code.google.com/p/nativelibs4java/issues/detail?id=30 + +kazocsaba's first comment : +<<< +Certainly, I'm happy to contribute the patch under LGPL and BSD. + +Csaba +>>> diff --git a/Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.diff b/Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.diff new file mode 100644 index 00000000..6704c485 --- /dev/null +++ b/Contributions/Kazo Csaba/CreateBinaryProgram - issue 30.diff @@ -0,0 +1,82 @@ +Index: OpenCL/Core/src/main/java/com/nativelibs4java/opencl/CLContext.java +=================================================================== +--- OpenCL/Core/src/main/java/com/nativelibs4java/opencl/CLContext.java (revision 993) ++++ OpenCL/Core/src/main/java/com/nativelibs4java/opencl/CLContext.java (working copy) +@@ -64,6 +64,7 @@ + import com.sun.jna.Platform; + import com.sun.jna.Pointer; + import com.sun.jna.ptr.IntByReference; ++import java.util.Map; + + /** + * OpenCL context.
+@@ -189,6 +190,10 @@ + return program; + } + ++ public CLProgram createProgram(Map binaries) { ++ return new CLProgram(this, binaries); ++ } ++ + //cl_queue queue; + @Override + protected void clear() { +Index: OpenCL/Core/src/main/java/com/nativelibs4java/opencl/CLProgram.java +=================================================================== +--- OpenCL/Core/src/main/java/com/nativelibs4java/opencl/CLProgram.java (revision 993) ++++ OpenCL/Core/src/main/java/com/nativelibs4java/opencl/CLProgram.java (working copy) +@@ -47,6 +47,7 @@ + import com.sun.jna.Native; + import com.sun.jna.Pointer; + import com.sun.jna.ptr.IntByReference; ++import com.sun.jna.ptr.PointerByReference; + + /** + * OpenCL program.
+@@ -83,7 +84,30 @@ + this.context = context; + this.devices = devices == null || devices.length == 0 ? context.getDevices() : devices; + } ++ CLProgram(CLContext context, Map binaries) { ++ super(null, true); ++ this.context = context; ++ this.devices = binaries.keySet().toArray(new CLDevice[binaries.size()]); + ++ NativeSize[] lengths = new NativeSize[devices.length]; ++ cl_device_id[] deviceIds = new cl_device_id[devices.length]; ++ String[] binptr=new String[devices.length]; ++ for (int i = 0; i < devices.length; i++) { ++ final byte[] binary = binaries.get(devices[i]); ++ lengths[i] = toNS(binary.length); ++ deviceIds[i] = devices[i].getEntity(); ++ binptr[i]=new String(binary); ++ } ++ ++ IntBuffer errBuff = NIOUtils.directInts(1, ByteOrder.nativeOrder()); ++ cl_program program; ++ int previousAttempts = 0; ++ do { ++ program = CL.clCreateProgramWithBinary(context.getEntity(), devices.length, deviceIds, lengths, binptr, null, errBuff); ++ } while (failedForLackOfMemory(errBuff.get(0), previousAttempts++)); ++ entity = program; ++ } ++ + List sources = new ArrayList(); + Map programByDevice = new HashMap(); + +Index: OpenCL/OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/OpenCLLibrary.java +=================================================================== +--- OpenCL/OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/OpenCLLibrary.java (revision 993) ++++ OpenCL/OpenCL4Java/src/main/java/com/nativelibs4java/opencl/library/OpenCLLibrary.java (working copy) +@@ -595,6 +595,11 @@ + * Original signature : cl_program clCreateProgramWithBinary(cl_context, cl_uint, const cl_device_id*, const size_t*, const unsigned char**, cl_int*, cl_int*)
+ * @see Khronos Documentation for clCreateProgramWithBinary + */ ++ OpenCLLibrary.cl_program clCreateProgramWithBinary(OpenCLLibrary.cl_context cl_context1, int cl_uint1, OpenCLLibrary.cl_device_id cl_device_idPtr1[], NativeSize size_tPtr1[], String[] charPtrPtr1, IntBuffer cl_intPtr1, IntBuffer cl_intPtr2); ++ /** ++ * Original signature : cl_program clCreateProgramWithBinary(cl_context, cl_uint, const cl_device_id*, const size_t*, const unsigned char**, cl_int*, cl_int*)
++ * @see Khronos Documentation for clCreateProgramWithBinary ++ */ + OpenCLLibrary.cl_program clCreateProgramWithBinary(OpenCLLibrary.cl_context cl_context1, int cl_uint1, OpenCLLibrary.cl_device_id cl_device_idPtr1[], NativeSizeByReference size_tPtr1, PointerByReference charPtrPtr1, IntByReference cl_intPtr1, IntByReference cl_intPtr2); + /** + * Original signature : cl_int clRetainProgram(cl_program)
diff --git a/Core/.classpath b/Core/.classpath new file mode 100644 index 00000000..921941ce --- /dev/null +++ b/Core/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Core/.project b/Core/.project new file mode 100644 index 00000000..8004803d --- /dev/null +++ b/Core/.project @@ -0,0 +1,29 @@ + + + Core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + org.eclipse.iam.jdt.core.mavenIncrementalBuilder + + + + + + org.maven.ide.eclipse.maven2Nature + org.eclipse.iam.jdt.core.mavenNature + org.eclipse.jdt.core.javanature + + diff --git a/Core/.settings/org.eclipse.jdt.core.prefs b/Core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..45a45b3f --- /dev/null +++ b/Core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Jan 28 23:48:18 CET 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/Core/.settings/org.maven.ide.eclipse.prefs b/Core/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 00000000..1a131b4c --- /dev/null +++ b/Core/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Thu Jan 28 23:46:12 CET 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/Core/nb-configuration.xml b/Core/nb-configuration.xml new file mode 100644 index 00000000..3486bc9d --- /dev/null +++ b/Core/nb-configuration.xml @@ -0,0 +1,18 @@ + + + + + + all + + diff --git a/Core/nbactions.xml b/Core/nbactions.xml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Core/nbactions.xml @@ -0,0 +1 @@ + diff --git a/Core/pom.xml b/Core/pom.xml new file mode 100644 index 00000000..7557e212 --- /dev/null +++ b/Core/pom.xml @@ -0,0 +1,75 @@ + + 4.0.0 + com.nativelibs4java + javacl-core-jna + JavaCL Core / JNA + http://code.google.com/p/javacl/ + 1.0.0-RC1 + jar + + + +JavaCL is an Object-Oriented API that makes the C OpenCL API available to Java in a very natural way. +It hides away the complexity of cross-platform C bindings, has a clean OO design (with generics, Java enums, NIO buffers, fully typed exceptions...), provides high-level features (OpenGL-interop, array reductions) and comes with samples and demos. +For more info, please visit http://code.google.com/p/nativelibs4java/wiki/OpenCL. + + + + com.nativelibs4java + opencl4java-parent-jna + 1.0.0-RC1 + ../Parent + + + + + + com.nativelibs4java + opencl4java-jna + ${opencl4java.version} + compile + + + + com.nativelibs4java + nativelibs4java-utils + 1.3 + compile + + + + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.4 + + + + + + + + + com.nativelibs4java + maven-velocity-plugin + ${bridj.version} + + + + generate + + + + + + + + + + + diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLAbstractEntity.java b/Core/src/main/java/com/nativelibs4java/opencl/CLAbstractEntity.java new file mode 100644 index 00000000..504dcedc --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLAbstractEntity.java @@ -0,0 +1,110 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import com.sun.jna.PointerType; + +abstract class CLAbstractEntity { + protected volatile T entity; + private final boolean nullable; + + CLAbstractEntity(T entity) { + this(entity, false); + } + CLAbstractEntity(T entity, boolean nullable) { + if (!nullable && entity == null) { + throw new IllegalArgumentException("Null OpenCL " + getClass().getSimpleName() + " !"); + } + this.nullable = nullable; + this.entity = entity; + } + + /** + * Manual release of the OpenCL resources represented by this object.
+ * Note that resources are automatically released by the garbage collector, so in general there's no need to call this method.
+ * In an environment with fast allocation/deallocation of large objects, it might be safer to call release() manually, though.
+ * Note that release() does not necessarily free the object immediately : OpenCL maintains a reference count for all its objects, and an object released on the Java side might still be pointed to by running kernels or queued operations. + */ + public synchronized void release() { + if (entity == null) { + if (!nullable) + throw new RuntimeException("This " + getClass().getSimpleName() + " has already been released ! Besides, keep in mind that manual release is not necessary, as it will automatically be done by the garbage collector."); + else + return; + } + + doRelease(); + } + + public static > E[] getEntities(A[] objects, E[] out) { + for (int i = 0, len = objects.length; i < len; i++) + out[i] = objects[i].getEntity(); + return out; + } + synchronized T getEntity() { + if (entity == null && !nullable) + throw new RuntimeException("This " + getClass().getSimpleName() + " has been manually released and can't be used anymore !"); + + return entity; + } + + synchronized void doRelease() { + if (entity != null) { + clear(); + entity = null; + } + } + @Override + protected void finalize() throws Throwable { + doRelease(); + } + + protected abstract void clear(); + + /** + * Underyling implementation pointer-based hashCode computation + */ + @Override + public int hashCode() { + return getEntity() == null ? 0 : getEntity().getPointer().hashCode(); + } + + /** + * Underyling implementation pointer-based equality test + */ + @Override + public boolean equals(Object obj) { + if (obj == null || !getClass().isInstance(obj)) + return false; + CLAbstractEntity e = (CLAbstractEntity)obj; + return getEntity().getPointer().equals(e.getEntity().getPointer()); + } + +} \ No newline at end of file diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLAbstractUserProgram.java b/Core/src/main/java/com/nativelibs4java/opencl/CLAbstractUserProgram.java new file mode 100644 index 00000000..8255d02d --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLAbstractUserProgram.java @@ -0,0 +1,127 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + +import com.nativelibs4java.util.IOUtils; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.lang.reflect.Array; + +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +/** + * + * @author ochafik + */ +public abstract class CLAbstractUserProgram { + + final CLProgram program; + String rawSource; + Map velocityArgs; + //Map kernels; + + volatile boolean addedSources; + + protected Long getSourceChecksum() { + return null; + } + + public CLProgram getProgram() { + return program; + } + + protected void checkArrayLength(Object arr, int length, String argName) { + if (arr == null) + throw new IllegalArgumentException("Argument " + argName + " cannot be null. Expected array of size " + length); + + int len = Array.getLength(arr); + if (len != length) + throw new IllegalArgumentException("Argument " + argName + " must be an array of size " + length + ", but given array of size " + len); + } + protected static String readRawSourceForClass(Class c) throws IOException { + String simpleName = c.getSimpleName(); + + InputStream srcIn = c.getResourceAsStream(simpleName + ".cl"); + try { + if (srcIn == null) + srcIn = c.getResourceAsStream(simpleName + ".c"); + + if (srcIn == null) + throw new FileNotFoundException("OpenCL source code not found : '" + simpleName + "'"); + + return IOUtils.readText(srcIn); + } finally { + if (srcIn != null) + srcIn.close(); + } + } + protected CLAbstractUserProgram(CLProgram program, String rawSource) { + this.program = program; + this.rawSource = rawSource; + } + + protected CLAbstractUserProgram(CLContext context, String rawSource) { + this(context.createProgram(), rawSource); + } + + protected synchronized void addSources() { + if (addedSources) { + return; + } + + String src; + if (velocityArgs != null) { + src = rawSource;//veloTransform(rawSource, velocityArgs); + } else { + src = rawSource; + } + + program.addSource(src); + addedSources = true; + } + + protected void defineMacro(String name, String value) { + if (value == null) { + program.undefineMacro(name); + } else { + program.defineMacro(name, value); + } + } + + protected synchronized CLKernel createKernel(String name) throws CLBuildException { + addSources(); + return program.createKernel(name); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLBuildException.java b/Core/src/main/java/com/nativelibs4java/opencl/CLBuildException.java new file mode 100644 index 00000000..87307cae --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLBuildException.java @@ -0,0 +1,50 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + +import com.ochafik.util.string.StringUtils; +import java.util.Collection; + +/** + * OpenCL program build exception + * @author ochafik + */ +@SuppressWarnings("serial") +public class CLBuildException extends CLException { + final CLProgram program; + CLBuildException(CLProgram program, String string, Collection errors) { + super(string + "\n" + StringUtils.implode(errors, "\n"), -1); + this.program = program; + } + public CLProgram getProgram() { + return program; + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLByteBuffer.java b/Core/src/main/java/com/nativelibs4java/opencl/CLByteBuffer.java new file mode 100644 index 00000000..3bfcab7e --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLByteBuffer.java @@ -0,0 +1,51 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import java.nio.*; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; + +/** + * OpenCL Memory Buffer Object.
+ * A buffer object stores a one-dimensional collection of elements.
+ * Elements of a buffer object can be a scalar data type (such as an int, float), vector data type, or a user-defined structure.
+ * @see CLContext#createByteBuffer(com.nativelibs4java.opencl.CLMem.Usage, long) + * @see CLContext#createByteBuffer(com.nativelibs4java.opencl.CLMem.Usage, java.nio.Buffer, boolean) + * @author Olivier Chafik + * @deprecated Use {@link CLBuffer}<{@link Byte}> + */ +@Deprecated +public class CLByteBuffer extends CLBuffer { + CLByteBuffer(CLContext context, long byteCount, cl_mem entity, Buffer buffer) { + super(context, byteCount, entity, buffer, 1, ByteBuffer.class); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLCharBuffer.java b/Core/src/main/java/com/nativelibs4java/opencl/CLCharBuffer.java new file mode 100644 index 00000000..5207f88c --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLCharBuffer.java @@ -0,0 +1,49 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import java.nio.*; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; + +/** + * OpenCL Memory Buffer Object with Character values.
+ * @see CLContext#createCharBuffer(com.nativelibs4java.opencl.CLMem.Usage, long) + * @see CLContext#createCharBuffer(com.nativelibs4java.opencl.CLMem.Usage, java.nio.CharBuffer, boolean) + * @author Olivier Chafik + * @deprecated Use {@link CLBuffer}<{@link Character}> + */ +@Deprecated +public class CLCharBuffer extends CLBuffer { + CLCharBuffer(CLContext context, long byteCount, cl_mem entity, Buffer buffer) { + super(context, byteCount, entity, buffer, 2, CharBuffer.class); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLDevice.java b/Core/src/main/java/com/nativelibs4java/opencl/CLDevice.java new file mode 100644 index 00000000..a511f915 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLDevice.java @@ -0,0 +1,986 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + +import com.nativelibs4java.util.EnumValue; +import com.nativelibs4java.util.EnumValues; +import com.nativelibs4java.opencl.library.OpenCLLibrary; +import com.nativelibs4java.util.IOUtils; +import com.nativelibs4java.util.NIOUtils; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import com.sun.jna.*; +import com.sun.jna.ptr.*; +import java.io.IOException; +import java.nio.*; +import static com.nativelibs4java.opencl.JavaCL.*; +import static com.nativelibs4java.util.JNAUtils.*; +import static com.nativelibs4java.util.NIOUtils.*; +import java.util.*; +import static com.nativelibs4java.opencl.CLException.*; +import com.nativelibs4java.util.ValuedEnum; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * OpenCL device (CPU, GPU...).
+ * Devices are retrieved from a CLPlatform + * @see CLPlatform#listDevices(java.util.EnumSet, boolean) + * @see CLPlatform#listAllDevices(boolean) + * @see CLPlatform#listCPUDevices(boolean) + * @see CLPlatform#listGPUDevices(boolean) + */ +@SuppressWarnings("unused") +public class CLDevice extends CLAbstractEntity { + + private static CLInfoGetter infos = new CLInfoGetter() { + + @Override + protected int getInfo(cl_device_id entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetDeviceInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + volatile CLPlatform platform; + + CLDevice(CLPlatform platform, cl_device_id device) { + super(device); + this.platform = platform; + } + + public synchronized CLPlatform getPlatform() { + if (platform == null) { + Pointer pplat = infos.getPointer(getEntity(), CL_DEVICE_PLATFORM); + platform = new CLPlatform(pplat == null ? null : new cl_platform_id(pplat)); + } + return platform; + } + + @Override + protected void clear() { + } + + public String createSignature() { + return getName() + "|" + getVendor() + "|" + getDriverVersion() + "|" + getProfile(); + } + public static Map> getDevicesBySignature(List devices) { + Map> ret = new HashMap>(); + for (CLDevice device : devices) { + String signature = device.createSignature(); + List list = ret.get(signature); + if (list == null) + ret.put(signature, list = new ArrayList()); + list.add(device); + } + return ret; + } + + + public ByteOrder getByteOrder() { + return isEndianLittle() ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN; + } + + ByteOrder kernelsDefaultByteOrder; + public synchronized ByteOrder getKernelsDefaultByteOrder() { + if (kernelsDefaultByteOrder == null) { + kernelsDefaultByteOrder = ByteOrder.nativeOrder(); + /* + CLPlatform platform = getPlatform(); + if (platform != null && platform.getVendor().toLowerCase().contains("nvidia")) + kernelsDefaultByteOrder = getByteOrder(); + else { + CLContext context = JavaCL.createContext((Map)null, this); + CLQueue queue = context.createDefaultQueue(); + try { + int n = 16; + + CLIntBuffer inputMatchResult = context.createIntBuffer(CLMem.Usage.Output, n); + float testValue = 12; + CLFloatBuffer inPtr = context.createFloatBuffer(CLMem.Usage.Input, n); + inPtr.write(queue, FloatBuffer.wrap(new float[] { testValue }), true); + CLProgram program = + context.createProgram(IOUtils.readText(CLDevice.class.getResourceAsStream("EndiannessTest.cl"))) + .defineMacro("TEST_VALUE", testValue) + .build(); + + CLKernel test = program.createKernel("testEndianness", inPtr, inPtr, inPtr, inputMatchResult); + test.enqueueNDRange(queue, new int[] { n }, new int[] { 1 }); + queue.finish(); + + IntBuffer b = NIOUtils.directInts(n, getByteOrder()); + inputMatchResult.read(queue, b, true); + switch (b.get(0)) { + case 1: // device endianness + kernelsDefaultByteOrder = getByteOrder(); + break; + case 2: // host endianness + kernelsDefaultByteOrder = ByteOrder.nativeOrder(); + break; + default: + throw new RuntimeException("Default kernel argument endianness of this device couldn't be guessed out."); + } + + } catch (CLBuildException ex) { + throw new RuntimeException("Default kernel argument endianness of this device couldn't be guessed out.", ex); + } catch (IOException ex) { + throw new RuntimeException("Couldn't find internal resources needed to guess this device's kernel argument endianness.", ex); + } finally { + queue.finish(); + System.gc(); + queue.release(); + context.release(); + } + }//*/ + } + return kernelsDefaultByteOrder; + } + + /** Bit values for CL_DEVICE_EXECUTION_CAPABILITIES */ + public enum ExecutionCapability implements ValuedEnum { + + Kernel(CL_EXEC_KERNEL), + NativeKernel(CL_EXEC_NATIVE_KERNEL); + + ExecutionCapability(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static long getValue(EnumSet set) { + return EnumValues.getValue(set); + } + + public static EnumSet getEnumSet(long v) { + return EnumValues.getEnumSet(v, ExecutionCapability.class); + } + } + + /** + * Describes the execution capabilities of the device.
+ * The mandated minimum capability is: Kernel. + */ + @InfoName("CL_DEVICE_EXECUTION_CAPABILITIES") + public EnumSet getExecutionCapabilities() { + return ExecutionCapability.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_EXECUTION_CAPABILITIES)); + } + + /** Bit values for CL_DEVICE_TYPE */ + public enum Type implements ValuedEnum { + + CPU(CL_DEVICE_TYPE_CPU), + GPU(CL_DEVICE_TYPE_GPU), + Accelerator(CL_DEVICE_TYPE_ACCELERATOR), + Default(CL_DEVICE_TYPE_DEFAULT); + + Type(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + + public static long getValue(EnumSet set) { + return EnumValues.getValue(set); + } + + public static EnumSet getEnumSet(long v) { + return EnumValues.getEnumSet(v, Type.class); + } + } + + /** + * The OpenCL device type. + */ + @InfoName("CL_DEVICE_TYPE") + public EnumSet getType() { + return Type.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_TYPE)); + } + + /** + * A unique device vendor identifier.
+ * An example of a unique device identifier could be the PCIe ID. + */ + @InfoName("CL_DEVICE_VENDOR_ID") + public int getVendorId() { + return infos.getInt(getEntity(), CL_DEVICE_VENDOR_ID); + } + + /** + * The number of parallel compute cores on the OpenCL device.
+ * The minimum value is 1. + */ + @InfoName("CL_DEVICE_MAX_COMPUTE_UNITS") + public int getMaxComputeUnits() { + return infos.getInt(getEntity(), CL_DEVICE_MAX_COMPUTE_UNITS); + } + + /** + * Maximum dimensions that specify the global and local work-item IDs used by the data parallel execution model.
+ * (Refer to clEnqueueNDRangeKernel). + *
The minimum value is 3. + */ + @InfoName("CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS") + public int getMaxWorkItemDimensions() { + return infos.getInt(getEntity(), CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS); + } + + /** + * Maximum number of work-items that can be specified in each dimension of the work-group to clEnqueueNDRangeKernel. + */ + @InfoName("CL_DEVICE_MAX_WORK_ITEM_SIZES") + public long[] getMaxWorkItemSizes() { + long sizes[] = infos.getNativeSizes(getEntity(), CL_DEVICE_MAX_WORK_ITEM_SIZES, getMaxWorkItemDimensions()); + for (int i = 0, n = sizes.length; i < n; i++) { + long size = sizes[i]; + if ((size & 0xffffffff00000000L) == 0xcccccccc00000000L) + sizes[i] = size & 0xffffffffL; + } + return sizes; + } + + /** + * Maximum number of work-items in a work-group executing a kernel using the data parallel execution model. + * (Refer to clEnqueueNDRangeKernel).
+ * The minimum value is 1. + */ + @InfoName("CL_DEVICE_MAX_WORK_GROUP_SIZE") + public long getMaxWorkGroupSize() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_WORK_GROUP_SIZE); + } + + /** + * Maximum configured clock frequency of the device in MHz. + */ + @InfoName("CL_DEVICE_MAX_CLOCK_FREQUENCY") + public int getMaxClockFrequency() { + return infos.getInt(getEntity(), CL_DEVICE_MAX_CLOCK_FREQUENCY); + } + + /** + * The default compute device address space size specified as an unsigned integer value in bits. Currently supported values are 32 or 64 bits..
+ * Size of size_t type in OpenCL kernels can be obtained with getAddressBits() / 8. + */ + @InfoName("CL_DEVICE_ADDRESS_BITS") + public int getAddressBits() { + return infos.getInt(getEntity(), CL_DEVICE_ADDRESS_BITS); + } + + /** + * Max size of memory object allocation in bytes. The minimum value is max (1/4th of CL_DEVICE_GLOBAL_MEM_SIZE , 128*1024*1024) + */ + @InfoName("CL_DEVICE_MAX_MEM_ALLOC_SIZE") + public long getMaxMemAllocSize() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_MEM_ALLOC_SIZE); + } + + /** + * Is CL_TRUE if images are supported by the OpenCL device and CL_FALSE otherwise. + */ + @InfoName("CL_DEVICE_IMAGE_SUPPORT") + public boolean hasImageSupport() { + return infos.getBool(getEntity(), CL_DEVICE_IMAGE_SUPPORT); + } + + /** + * Max number of simultaneous image objects that can be read by a kernel.
+ * The minimum value is 128 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE (@see hasImageSupport()). + */ + @InfoName("CL_DEVICE_MAX_READ_IMAGE_ARGS") + public int getMaxReadImageArgs() { + return infos.getInt(getEntity(), CL_DEVICE_MAX_READ_IMAGE_ARGS); + } + + /** + * Max number of simultaneous image objects that can be written to by a kernel.
+ * The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE (@see hasImageSupport()). + */ + @InfoName("CL_DEVICE_MAX_WRITE_IMAGE_ARGS") + public int getMaxWriteImageArgs() { + return infos.getInt(getEntity(), CL_DEVICE_MAX_WRITE_IMAGE_ARGS); + } + + @Override + public String toString() { + return getName();// + "{singleFPConfig: " + getSingleFPConfig() + "}"; + } + + /** + * Create an OpenCL execution queue on this device for the specified context. + * @param context context of the queue to create + * @return new OpenCL queue object + */ + @SuppressWarnings("deprecation") + public CLQueue createQueue(CLContext context, QueueProperties... queueProperties) { + IntByReference pErr = new IntByReference(); + long flags = 0; + for (QueueProperties prop : queueProperties) + flags |= prop.value(); + cl_command_queue queue = CL.clCreateCommandQueue(context.getEntity(), getEntity(), flags, pErr); + error(pErr.getValue()); + + return new CLQueue(context, queue, this); + } + + @Deprecated + public CLQueue createQueue(EnumSet queueProperties, CLContext context) { + IntByReference pErr = new IntByReference(); + cl_command_queue queue = CL.clCreateCommandQueue(context.getEntity(), getEntity(), QueueProperties.getValue(queueProperties), pErr); + error(pErr.getValue()); + + return new CLQueue(context, queue, this); + } + + public CLQueue createOutOfOrderQueue(CLContext context) { + return createQueue(EnumSet.of(QueueProperties.OutOfOrderExecModeEnable), context); + } + + public CLQueue createProfilingQueue(CLContext context) { + return createQueue(EnumSet.of(QueueProperties.ProfilingEnable), context); + } + + /** + * Max width of 2D image in pixels.
+ * The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE. + */ + @InfoName("CL_DEVICE_IMAGE2D_MAX_WIDTH") + public long getImage2DMaxWidth() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE2D_MAX_WIDTH); + } + + /** + * Max height of 2D image in pixels.
+ * The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE. + */ + @InfoName("CL_DEVICE_IMAGE2D_MAX_HEIGHT") + public long getImage2DMaxHeight() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE2D_MAX_HEIGHT); + } + + /** + * Max width of 3D image in pixels.
+ * The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE. + */ + @InfoName("CL_DEVICE_IMAGE3D_MAX_WIDTH") + public long getImage3DMaxWidth() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE3D_MAX_WIDTH); + } + + /** + * Max height of 3D image in pixels.
+ * The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE. + */ + @InfoName("CL_DEVICE_IMAGE3D_MAX_HEIGHT") + public long getImage3DMaxHeight() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE3D_MAX_HEIGHT); + } + + /** + * Max depth of 3D image in pixels.
+ * The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE. + */ + @InfoName("CL_DEVICE_IMAGE3D_MAX_DEPTH") + public long getImage3DMaxDepth() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE3D_MAX_DEPTH); + } + + /** + * Maximum number of samplers that can be used in a kernel.
+ * Refer to section 6.11.8 for a detailed description on samplers.
+ * The minimum value is 16 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE. + */ + @InfoName("CL_DEVICE_MAX_SAMPLERS") + public int getMaxSamplers() { + return infos.getInt(getEntity(), CL_DEVICE_MAX_SAMPLERS); + } + + /** + * Max size in bytes of the arguments that can be passed to a kernel.
+ * The minimum value is 256. + */ + @InfoName("CL_DEVICE_MAX_PARAMETER_SIZE") + public long getMaxParameterSize() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_PARAMETER_SIZE); + } + + /** + * Describes the alignment in bits of the base address of any allocated memory object. + */ + @InfoName("CL_DEVICE_MEM_BASE_ADDR_ALIGN") + public int getMemBaseAddrAlign() { + return infos.getInt(getEntity(), CL_DEVICE_MEM_BASE_ADDR_ALIGN); + } + + /** + * The smallest alignment in bytes which can be used for any data type. + */ + @InfoName("CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE") + public int getMinDataTypeAlign() { + return infos.getInt(getEntity(), CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE); + } + + /** Bit values for CL_DEVICE_SINGLE_FP_CONFIG */ + public enum SingleFPConfig implements ValuedEnum { + + /** denorms are supported */ + Denorm(CL_FP_DENORM), + /** INF and quiet NaNs are supported. */ + InfNaN(CL_FP_INF_NAN), + /** round to nearest even rounding mode supported */ + RoundToNearest(CL_FP_ROUND_TO_NEAREST), + /** round to zero rounding mode supported */ + RoundToZero(CL_FP_ROUND_TO_ZERO), + /** round to +ve and -ve infinity rounding modes supported */ + RoundToInf(CL_FP_ROUND_TO_INF), + /** IEEE754-2008 fused multiply-add is supported. */ + FMA(CL_FP_FMA); + + SingleFPConfig(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + + + public static long getValue(EnumSet set) { + return EnumValues.getValue(set); + } + + public static EnumSet getEnumSet(long v) { + return EnumValues.getEnumSet(v, SingleFPConfig.class); + } + } + + /** + * Describes single precision floating- point capability of the device.
+ * The mandated minimum floating-point capability is: RoundToNearest and InfNaN. + */ + @InfoName("CL_DEVICE_SINGLE_FP_CONFIG") + public EnumSet getSingleFPConfig() { + return SingleFPConfig.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_SINGLE_FP_CONFIG)); + } + + /** Values for CL_DEVICE_GLOBAL_MEM_CACHE_TYPE */ + public enum GlobalMemCacheType implements ValuedEnum { + + None(CL_NONE), + ReadOnlyCache(CL_READ_ONLY_CACHE), + ReadWriteCache(CL_READ_WRITE_CACHE); + + GlobalMemCacheType(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + + public static GlobalMemCacheType getEnum(long v) { + return EnumValues.getEnum(v, GlobalMemCacheType.class); + } + } + + /** + * Type of global memory cache supported. + */ + @InfoName("CL_DEVICE_GLOBAL_MEM_CACHE_TYPE") + public GlobalMemCacheType getGlobalMemCacheType() { + return GlobalMemCacheType.getEnum(infos.getInt(getEntity(), CL_DEVICE_GLOBAL_MEM_CACHE_TYPE)); + } + + /** + * Size of global memory cache line in bytes. + */ + @InfoName("CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE") + public int getGlobalMemCachelineSize() { + return infos.getInt(getEntity(), CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE); + } + + /** + * Size of global memory cache in bytes. + */ + @InfoName("CL_DEVICE_GLOBAL_MEM_CACHE_SIZE") + public long getGlobalMemCacheSize() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_GLOBAL_MEM_CACHE_SIZE); + } + + /** + * Size of global device memory in bytes. + */ + @InfoName("CL_DEVICE_GLOBAL_MEM_SIZE") + public long getGlobalMemSize() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_GLOBAL_MEM_SIZE); + } + + /** + * Max size in bytes of a constant buffer allocation.
+ * The minimum value is 64 KB. + */ + @InfoName("CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE") + public long getMaxConstantBufferSize() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE); + } + + /** + * Max number of arguments declared with the __constant qualifier in a kernel.
+ * The minimum value is 8. + */ + @InfoName("CL_DEVICE_MAX_CONSTANT_ARGS") + public int getMaxConstantArgs() { + return infos.getInt(getEntity(), CL_DEVICE_MAX_CONSTANT_ARGS); + } + + /** Values for CL_DEVICE_LOCAL_MEM_TYPE */ + public enum LocalMemType implements ValuedEnum { + + /** implying dedicated local memory storage such as SRAM */ + Local(CL_LOCAL), + Global(CL_GLOBAL); + + LocalMemType(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + + public static LocalMemType getEnum(long v) { + return EnumValues.getEnum(v, LocalMemType.class); + } + } + + /** + * Type of local memory supported.
+ */ + @InfoName("CL_DEVICE_LOCAL_MEM_TYPE") + public LocalMemType getLocalMemType() { + return LocalMemType.getEnum(infos.getInt(getEntity(), CL_DEVICE_LOCAL_MEM_TYPE)); + } + + /** + * Size of local memory arena in bytes.
+ * The minimum value is 16 KB. + */ + @InfoName("CL_DEVICE_LOCAL_MEM_SIZE") + public long getLocalMemSize() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_LOCAL_MEM_SIZE); + } + + /** + * Is CL_TRUE if the device implements error correction for the memories, caches, registers etc. in the device.
+ * Is CL_FALSE if the device does not implement error correction.
+ * This can be a requirement for certain clients of OpenCL. + */ + @InfoName("CL_DEVICE_ERROR_CORRECTION_SUPPORT") + public boolean hasErrorCorrectionSupport() { + return infos.getBool(getEntity(), CL_DEVICE_ERROR_CORRECTION_SUPPORT); + } + + @InfoName("Out of order queues support") + public boolean hasOutOfOrderQueueSupport() { + CLContext context = getPlatform().createContext(null, this); + CLQueue queue = null; + try { + queue = createOutOfOrderQueue(context); + return true; + } catch (CLException.InvalidQueueProperties ex) { + return false; + } finally { + if (queue != null) + queue.release(); + context.release(); + } + } + + /** + * Describes the resolution of device timer.
+ * This is measured in nanoseconds.
+ * Refer to section 5.9 for details. + */ + @InfoName("CL_DEVICE_PROFILING_TIMER_RESOLUTION") + public long getProfilingTimerResolution() { + return infos.getIntOrLong(getEntity(), CL_DEVICE_PROFILING_TIMER_RESOLUTION); + } + + /** + * Is CL_TRUE if the OpenCL device is a little endian device and CL_FALSE otherwise. + */ + @InfoName("CL_DEVICE_ENDIAN_LITTLE") + public boolean isEndianLittle() { + return infos.getBool(getEntity(), CL_DEVICE_ENDIAN_LITTLE); + } + + /** + * Is CL_TRUE if the device is available and CL_FALSE if the device is not available. + */ + @InfoName("CL_DEVICE_AVAILABLE") + public boolean isAvailable() { + return infos.getBool(getEntity(), CL_DEVICE_AVAILABLE); + } + + /** + * Is CL_FALSE if the implementation does not have a compiler available to compile the program source.
+ * Is CL_TRUE if the compiler is available.
+ * This can be CL_FALSE for the embededed platform profile only. + */ + @InfoName("CL_DEVICE_COMPILER_AVAILABLE") + public boolean isCompilerAvailable() { + return infos.getBool(getEntity(), CL_DEVICE_COMPILER_AVAILABLE); + } + + /** + Device name string. + */ + @InfoName("CL_DEVICE_NAME") + public String getName() { + return infos.getString(getEntity(), CL_DEVICE_NAME); + } + + /** + * OpenCL C version string.
+ * Returns the highest OpenCL C version supported by the compiler for this device.
+ * This version string has the following format:
+ * OpenCL<space>C<space><major_version.minor_version><space><vendor-specific information>
+ * The major_version.minor_version value returned must be 1.1 if CL_DEVICE_VERSION is OpenCL 1.1.
+ * The major_version.minor_version value returned can be 1.0 or 1.1 if CL_DEVICE_VERSION is OpenCL 1.0.
+ * If OpenCL C 1.1 is returned, this implies that the language feature set defined in section 6 of the OpenCL 1.1 specification is supported by the OpenCL 1.0 device. + * @since OpenCL 1.1 + */ + @InfoName("CL_DEVICE_OPENCL_C_VERSION") + public String getOpenCLVersion() { + try { + return infos.getString(getEntity(), CL_DEVICE_OPENCL_C_VERSION); + } catch (Throwable th) { + // TODO throw if supposed to handle OpenCL 1.1 + return "OpenCL C 1.0"; + } + } + + /** + Vendor name string. + */ + @InfoName("CL_DEVICE_VENDOR") + public String getVendor() { + return infos.getString(getEntity(), CL_DEVICE_VENDOR); + } + + /** + OpenCL software driver version string in the form major_number.minor_number. + */ + @InfoName("CL_DRIVER_VERSION") + public String getDriverVersion() { + return infos.getString(getEntity(), CL_DRIVER_VERSION); + } + + /** + * OpenCL profile string.
+ * Returns the profile name supported by the device.
+ * The profile name returned can be one of the following strings: + *
    + *
  • FULL_PROFILE if the device supports the OpenCL specification (functionality defined as part of the core specification and does not require any extensions to be supported).
  • + *
  • EMBEDDED_PROFILE if the device supports the OpenCL embedded profile.
  • + *
+ */ + @InfoName("CL_DEVICE_PROFILE") + public String getProfile() { + return infos.getString(getEntity(), CL_DEVICE_PROFILE); + } + + /** + * Whether the device and the host have a unified memory subsystem. + * @since OpenCL 1.1 + */ + @InfoName("CL_DEVICE_HOST_UNIFIED_MEMORY") + public boolean isHostUnifiedMemory() { + try { + return infos.getBool(getEntity(), CL_DEVICE_HOST_UNIFIED_MEMORY); + } catch (Throwable th) { + // TODO throw if supposed to handle OpenCL 1.1 + return false; + } + } + + /** + * Preferred native vector width size for built-in scalar types that can be put into vectors.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR") + public int getPreferredVectorWidthChar() { + return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR); + } + + /** + * Preferred native vector width size for built-in scalar types that can be put into vectors.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT") + public int getPreferredVectorWidthShort() { + return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT); + } + + /** + * Preferred native vector width size for built-in scalar types that can be put into vectors.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT") + public int getPreferredVectorWidthInt() { + return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT); + } + + /** + * Preferred native vector width size for built-in scalar types that can be put into vectors.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG") + public int getPreferredVectorWidthLong() { + return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG); + } + + /** + * Preferred native vector width size for built-in scalar types that can be put into vectors.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT") + public int getPreferredVectorWidthFloat() { + return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT); + } + + /** + * Preferred native vector width size for built-in scalar types that can be put into vectors.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE") + public int getPreferredVectorWidthDouble() { + return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE); + } + + /** + * Returns the native ISA vector width.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR") + public int getNativeVectorWidthChar() { + return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR); + } + + /** + * Returns the native ISA vector width.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT") + public int getNativeVectorWidthShort() { + return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT); + } + + /** + * Returns the native ISA vector width.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_INT") + public int getNativeVectorWidthInt() { + return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_INT); + } + + /** + * Returns the native ISA vector width.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG") + public int getNativeVectorWidthLong() { + return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG); + } + + /** + * Returns the native ISA vector width.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT") + public int getNativeVectorWidthFloat() { + return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT); + } + + /** + * Returns the native ISA vector width.
+ * The vector width is defined as the number of scalar elements that can be stored in the vector.
+ * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0. + */ + @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE") + public int getNativeVectorWidthDouble() { + return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE); + } + + /** + * OpenCL version string.
+ * Returns the OpenCL version supported by the device.
+ * This version string has the following format: + * + * OpenCL<space><major_version.min or_version><space><vendor-specific information> + * + * The major_version.minor_version value returned will be 1.0. + */ + @InfoName("CL_DEVICE_VERSION") + public String getVersion() { + return infos.getString(getEntity(), CL_DEVICE_VERSION); + } + + /** + Returns a space separated list of extension names (the extension names themselves do not contain any spaces). The list of extension names returned currently can include one or more of + */ + @InfoName("CL_DEVICE_EXTENSIONS") + public String[] getExtensions() { + if (extensions == null) { + extensions = infos.getString(getEntity(), CL_DEVICE_EXTENSIONS).split("\\s+"); + } + return extensions; + } + private String[] extensions; + + public boolean hasExtension(String name) { + name = name.trim(); + for (String x : getExtensions()) { + if (name.equals(x.trim())) { + return true; + } + } + return false; + } + + /** + * Whether this device support any double-precision number extension (cl_khr_fp64 or cl_amd_fp64) + */ + public boolean isDoubleSupported() { + return isDoubleSupportedKHR() || isDoubleSupportedAMD(); + } + + /** + * Whether this device support the cl_khr_fp64 double-precision number extension + */ + public boolean isDoubleSupportedKHR() { + return hasExtension("cl_khr_fp64"); + } + + /** + * Whether this device supports the cl_amd_fp64 double-precision number extension + */ + public boolean isDoubleSupportedAMD() { + return hasExtension("cl_amd_fp64"); + } + + /** + * If this device supports the extension cl_amd_fp64 but not cl_khr_fp64, replace any OpenCL source code pragma of the style #pragma OPENCL EXTENSION cl_khr_fp64 : enable by #pragma OPENCL EXTENSION cl_amd_fp64 : enable.
+ * Also works the other way around (if the KHR extension is available but the source code refers to the AMD extension).
+ * This method is called automatically by CLProgram unless the javacl.adjustDoubleExtension property is set to false or the JAVACL_ADJUST_DOUBLE_EXTENSION is set to 0. + */ + public String replaceDoubleExtensionByExtensionActuallyAvailable(String kernelSource) { + boolean hasKHR = isDoubleSupportedKHR(), hasAMD = isDoubleSupportedAMD(); + if (hasAMD && !hasKHR) + kernelSource = kernelSource.replaceAll("#pragma\\s+OPENCL\\s+EXTENSION\\s+cl_khr_fp64\\s*:\\s*enable", "#pragma OPENCL EXTENSION cl_amd_fp64 : enable"); + else if (!hasAMD && hasKHR) + kernelSource = kernelSource.replaceAll("#pragma\\s+OPENCL\\s+EXTENSION\\s+cl_amd_fp64\\s*:\\s*enable", "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"); + return kernelSource; + } + + /** + * Whether this device supports the cl_khr_fp16 extension. + */ + public boolean isHalfSupported() { + return hasExtension("cl_khr_fp16"); + } + + /** + * Whether this device supports the cl_khr_byte_addressable_store extension. + */ + public boolean isByteAddressableStoreSupported() { + return hasExtension("cl_khr_byte_addressable_store"); + } + + /** + * Whether this device supports any OpenGL sharing extension (cl_khr_gl_sharing or cl_APPLE_gl_sharing) + */ + public boolean isGLSharingSupported() { + return hasExtension("cl_khr_gl_sharing") || hasExtension("cl_APPLE_gl_sharing"); + } + /** + * Whether this device supports the cl_khr_global_int32_base_atomics extension. + */ + public boolean isGlobalInt32BaseAtomicsSupported() { + return hasExtension("cl_khr_global_int32_base_atomics"); + } + /** + * Whether this device supports the cl_khr_global_int32_extended_atomics extension. + */ + public boolean isGlobalInt32ExtendedAtomicsSupported() { + return hasExtension("cl_khr_global_int32_extended_atomics"); + } + /** + * Whether this device supports the cl_khr_local_int32_base_atomics extension. + */ + public boolean isLocalInt32BaseAtomicsSupported() { + return hasExtension("cl_khr_local_int32_base_atomics"); + } + /** + * Whether this device supports the cl_khr_local_int32_extended_atomics extension. + */ + public boolean isLocalInt32ExtendedAtomicsSupported() { + return hasExtension("cl_khr_local_int32_extended_atomics"); + } + + /** Bit values for CL_DEVICE_QUEUE_PROPERTIES */ + public enum QueueProperties implements ValuedEnum { + + OutOfOrderExecModeEnable(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE), + ProfilingEnable(CL_QUEUE_PROFILING_ENABLE); + + QueueProperties(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + + public static long getValue(EnumSet set) { + return EnumValues.getValue(set); + } + + public static EnumSet getEnumSet(long v) { + return EnumValues.getEnumSet(v, QueueProperties.class); + } + } + + /** + * Describes the command-queue properties supported by the device.
+ * These properties are described in table 5.1.
+ * The mandated minimum capability is: ProfilingEnable. + */ + @InfoName("CL_DEVICE_QUEUE_PROPERTIES") + public EnumSet getQueueProperties() { + return QueueProperties.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_QUEUE_PROPERTIES)); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLDoubleBuffer.java b/Core/src/main/java/com/nativelibs4java/opencl/CLDoubleBuffer.java new file mode 100644 index 00000000..5b136666 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLDoubleBuffer.java @@ -0,0 +1,49 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import java.nio.*; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; + +/** + * OpenCL Memory Buffer Object with Double values.
+ * @see CLContext#createDoubleBuffer(com.nativelibs4java.opencl.CLMem.Usage, long) + * @see CLContext#createDoubleBuffer(com.nativelibs4java.opencl.CLMem.Usage, java.nio.DoubleBuffer, boolean) + * @author Olivier Chafik + * @deprecated Use {@link CLBuffer}<{@link Double}> + */ +@Deprecated +public class CLDoubleBuffer extends CLBuffer { + CLDoubleBuffer(CLContext context, long byteCount, cl_mem entity, Buffer buffer) { + super(context, byteCount, entity, buffer, 8, DoubleBuffer.class); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLEvent.java b/Core/src/main/java/com/nativelibs4java/opencl/CLEvent.java new file mode 100644 index 00000000..74f8657c --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLEvent.java @@ -0,0 +1,380 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; + +import java.util.Arrays; + +import com.nativelibs4java.opencl.library.OpenCLLibrary; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_event; +import com.nativelibs4java.util.EnumValue; +import com.nativelibs4java.util.EnumValues; +import com.nativelibs4java.util.ValuedEnum; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.sun.jna.Callback; +import com.sun.jna.Memory; +import com.sun.jna.Pointer; + +/** + * OpenCL event object.
+ * Event objects can be used to refer to a kernel execution command (clEnqueueNDRangeKernel, clEnqueueTask, clEnqueueNativeKernel), or read, write, map and copy commands on memory objects (clEnqueue{Read|Write|Map}{Buffer|Image}, clEnqueueCopy{Buffer|Image}, clEnqueueCopyBufferToImage, or clEnqueueCopyImageToBuffer).
+ * An event object can be used to track the execution status of a command.
+ * The API calls that enqueue commands to a command-queue create a new event object that is returned in the event argument.
+ * In case of an error enqueuing the command in the command-queue the event argument does not return an event object.
+ * The execution status of an enqueued command at any given point in time can be CL_QUEUED (command has been enqueued in the command-queue), CL_SUBMITTED (enqueued command has been submitted by the host to the device associated with the command-queue), CL_RUNNING (device is currently executing this command), CL_COMPLETE (command has successfully completed) or the appropriate error code if the command was abnormally terminated (this may be caused by a bad memory access etc.).
+ * The error code returned by a terminated command is a negative integer value.
+ * A command is considered to be complete if its execution status is CL_COMPLETE or is a negative integer value.
+ * If the execution of a command is terminated, the command-queue associated with this terminated command, and the associated context (and all other command-queues in this context) may no longer be available.
+ * The behavior of OpenCL API calls that use this context (and command-queues associated with this context) are now considered to be implementation- defined.
+ * The user registered callback function specified when context is created can be used to report appropriate error information.
+ * + * @author ochafik + */ +public class CLEvent extends CLAbstractEntity { + + private static CLInfoGetter infos = new CLInfoGetter() { + @Override + protected int getInfo(cl_event entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetEventInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + + private static CLInfoGetter profilingInfos = new CLInfoGetter() { + @Override + protected int getInfo(cl_event entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetEventProfilingInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + + CLEvent(cl_event evt) { + super(evt, false); + } + + CLEvent() { + super(null, true); + } + + public interface EventCallback { + public void callback(CLEvent event, int executionStatus); + } + + /** + * Registers a user callback function for the completion execution status (CL_COMPLETE).
+ * @param callback + * @throws UnsupportedOperationException in OpenCL 1.0 + * @since OpenCL 1.1 + */ + public void setCompletionCallback(final EventCallback callback) { + setCallback(CL_COMPLETE, callback); + } + /** + * Registers a user callback function for a specific command execution status.
+ * The registered callback function will be called when the execution status of command associated with event changes to the execution status specified by command_exec_status. + * @param commandExecStatus specifies the command execution status for which the callback is registered. The command execution callback values for which a callback can be registered are: CL_COMPLETE. There is no guarantee that the callback functions registered for various execution status values for an event will be called in the exact order that the execution status of a command changes. + * @param callback + * @throws UnsupportedOperationException in OpenCL 1.0 + * @since OpenCL 1.1 + */ + public void setCallback(int commandExecStatus, final EventCallback callback) { + try { + error(CL.clSetEventCallback(getEntity(), commandExecStatus, new clSetEventCallback_arg1_callback() { + public void invoke(OpenCLLibrary.cl_event evt, int executionStatus, Pointer voidPtr1) { + callback.callback(CLEvent.this, executionStatus); + } + }, null)); + } catch (Throwable th) { + // TODO check if supposed to handle OpenCL 1.1 + throw new UnsupportedOperationException("Cannot set event callback (OpenCL 1.1 feature).", th); + } + } + + static boolean noEvents = false; + public static void setNoEvents(boolean noEvents) { + CLEvent.noEvents = noEvents; + } + static CLEvent createEvent(final CLQueue queue, cl_event evt) { + return createEvent(queue, evt, false); + } + static CLEvent createEvent(final CLQueue queue, cl_event evt, boolean isUserEvent) { + if (noEvents && queue != null) { + if (evt != null) + CL.clReleaseEvent(evt); + evt = null; + + if (isUserEvent) + return new CLUserEvent() { + volatile boolean waited = false; + @Override + public synchronized void waitFor() { + if (!waited) { + queue.finish(); + waited = true; + } + } + }; + return new CLEvent() { + volatile boolean waited = false; + @Override + public synchronized void waitFor() { + if (!waited) { + queue.finish(); + waited = true; + } + } + }; + } + if (evt == null) + return null; + + return isUserEvent ? + new CLUserEvent(evt) : + new CLEvent(evt); + } + + static CLEvent createEvent(CLQueue queue, cl_event[] evt1) { + if (evt1 == null) + return null; + return createEvent(queue, evt1[0]); + } + + + /** + * Wait for this event, blocking the caller thread independently of any queue until all of the command associated with this events completes. + */ + public void waitFor() { + if (entity == null) + return; + waitFor(this); + } + + /** + * Wait for events, blocking the caller thread independently of any queue until all of the commands associated with the events completed. + * @param eventsToWaitFor List of events which completion is to be waited for + */ + public static void waitFor(CLEvent... eventsToWaitFor) { + if (eventsToWaitFor.length == 0) + return; + + try { + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + if (evts == null || evts.length == 0) + return; + error(CL.clWaitForEvents(evts.length, evts)); + } catch (Exception ex) { + throw new RuntimeException("Exception while waiting for events " + Arrays.asList(eventsToWaitFor), ex); + } + } + + /** + * Invoke an action in a separate thread only after completion of the command associated with this event.
+ * Returns immediately. + * @param action an action to be ran + * @throws IllegalArgumentException if action is null + */ + public void invokeUponCompletion(final Runnable action) { + invokeUponCompletion(action, this); + } + + /** + * Invoke an action in a separate thread only after completion of all of the commands associated with the specified events.
+ * Returns immediately. + * @param action an action to be ran + * @param eventsToWaitFor list of events which commands's completion should be waited for before the action is ran + * @throws IllegalArgumentException if action is null + */ + public static void invokeUponCompletion(final Runnable action, final CLEvent... eventsToWaitFor) { + if (action == null) + throw new IllegalArgumentException("Null action !"); + + new Thread() { + public void run() { + waitFor(eventsToWaitFor); + action.run(); + } + }.start(); + } + + static cl_event[] new_event_out(CLEvent[] eventsToWaitFor) { + return noEvents || eventsToWaitFor == null ? null : new cl_event[1]; + } + + static cl_event[] to_cl_event_array(CLEvent... events) { + if (events == null) + return null; + if (noEvents) { + for (CLEvent evt : events) + if (evt != null) + evt.waitFor(); + return null; + } + int n = events.length; + if (n == 0) + return null; + int nonNulls = 0; + for (int i = 0; i < n; i++) + if (events[i] != null && events[i].getEntity() != null) + nonNulls++; + + if (nonNulls == 0) + return null; + + cl_event[] event_wait_list = new cl_event[nonNulls]; + int iDest = 0; + for (int i = 0; i < n; i++) { + CLEvent event = events[i]; + if (event == null || event.getEntity() == null) + continue; + event_wait_list[iDest] = event.getEntity(); + iDest++; + } + return event_wait_list; + } + + @Override + protected void clear() { + error(CL.clReleaseEvent(getEntity())); + } + + /** Values for CL_EVENT_COMMAND_EXECUTION_STATUS */ + public enum CommandExecutionStatus implements ValuedEnum { + /** command has been enqueued in the command-queue */ + Queued(CL_QUEUED), + /** enqueued command has been submitted by the host to the device associated with the command-queue */ + Submitted(CL_SUBMITTED), + /** device is currently executing this command */ + Running(CL_RUNNING), + /** the command has completed */ + Complete(CL_COMPLETE); + + CommandExecutionStatus(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static CommandExecutionStatus getEnum(long v) { return EnumValues.getEnum(v, CommandExecutionStatus.class); } + } + + /** + * Return the execution status of the command identified by event.
+ * @throws CLException is the execution status denotes an error + */ + public CommandExecutionStatus getCommandExecutionStatus() { + int v = infos.getInt(getEntity(), CL_EVENT_COMMAND_EXECUTION_STATUS); + CommandExecutionStatus status = CommandExecutionStatus.getEnum(v); + if (status == null) + error(v); + return status; + } + /** + * Return the execution status of the command identified by event.
+ * @throws CLException is the execution status denotes an error + */ + @InfoName("CL_EVENT_COMMAND_EXECUTION_STATUS") + public int getCommandExecutionStatusValue() { + return infos.getInt(getEntity(), CL_EVENT_COMMAND_EXECUTION_STATUS); + } + + /** Values for CL_EVENT_COMMAND_TYPE */ + public enum CommandType implements ValuedEnum { + NDRangeKernel(CL_COMMAND_NDRANGE_KERNEL), + Task(CL_COMMAND_TASK), + NativeKernel(CL_COMMAND_NATIVE_KERNEL), + ReadBuffer(CL_COMMAND_READ_BUFFER), + WriteBuffer(CL_COMMAND_WRITE_BUFFER), + CopyBuffer(CL_COMMAND_COPY_BUFFER), + ReadImage(CL_COMMAND_READ_IMAGE), + WriteImage(CL_COMMAND_WRITE_IMAGE), + CopyImage(CL_COMMAND_COPY_IMAGE), + CopyBufferToImage(CL_COMMAND_COPY_BUFFER_TO_IMAGE), + CopyImageToBuffer(CL_COMMAND_COPY_IMAGE_TO_BUFFER), + MapBuffer(CL_COMMAND_MAP_BUFFER), + CommandMapImage(CL_COMMAND_MAP_IMAGE), + UnmapMemObject(CL_COMMAND_UNMAP_MEM_OBJECT), + Marker(CL_COMMAND_MARKER), + AcquireGLObjects(CL_COMMAND_ACQUIRE_GL_OBJECTS), + ReleaseGLObjects(CL_COMMAND_RELEASE_GL_OBJECTS); + + CommandType(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static CommandType getEnum(long v) { return EnumValues.getEnum(v, CommandType.class); } + } + + /** + * Return the command associated with event. + */ + @InfoName("CL_EVENT_COMMAND_TYPE") + public CommandType getCommandType() { + return CommandType.getEnum(infos.getInt(getEntity(), CL_EVENT_COMMAND_TYPE)); + } + + + /** + * A 64-bit value that describes the current device time counter in nanoseconds when the command identified by event is enqueued in a command-queue by the host. + */ + @InfoName("CL_CL_PROFILING_COMMAND_QUEUED") + public long getProfilingCommandQueued() { + return profilingInfos.getIntOrLong(getEntity(), CL_PROFILING_COMMAND_QUEUED); + } + + /** + * A 64-bit value that describes the current device time counter in nanoseconds when the command identified by event that has been enqueued is submitted by the host to the device associated with the command- queue. + */ + @InfoName("CL_CL_PROFILING_COMMAND_SUBMIT") + public long getProfilingCommandSubmit() { + return profilingInfos.getIntOrLong(getEntity(), CL_PROFILING_COMMAND_SUBMIT); + } + + /** + * A 64-bit value that describes the current device time counter in nanoseconds when the command identified by event starts execution on the device. + */ + @InfoName("CL_CL_PROFILING_COMMAND_START") + public long getProfilingCommandStart() { + return profilingInfos.getIntOrLong(getEntity(), CL_PROFILING_COMMAND_START); + } + + /** + * A 64-bit value that describes the current device time counter in nanoseconds when the command identified by event has finished execution on the device. + */ + @InfoName("CL_CL_PROFILING_COMMAND_END") + public long getProfilingCommandEnd() { + return profilingInfos.getIntOrLong(getEntity(), CL_PROFILING_COMMAND_END); + } + + + @Override + public String toString() { + return "Event {commandType: " + getCommandType() + "}"; + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLException.java b/Core/src/main/java/com/nativelibs4java/opencl/CLException.java new file mode 100644 index 00000000..60a15031 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLException.java @@ -0,0 +1,258 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import com.nativelibs4java.opencl.library.OpenCLLibrary; +import com.ochafik.util.string.StringUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.*; +import java.lang.reflect.*; +import static com.nativelibs4java.opencl.JavaCL.log; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * OpenCL error + * @author ochafik + */ +@SuppressWarnings("serial") +public class CLException extends RuntimeException { + protected int code; + CLException(String message, int code) { + super(message); + this.code = code; + } + public int getCode() { + return code; + } + + @Retention(RetentionPolicy.RUNTIME) + public @interface ErrorCode { + int value(); + } + + public static class CLTypedException extends CLException { + protected String message; + public CLTypedException() { + super("", 0); + ErrorCode code = getClass().getAnnotation(ErrorCode.class); + this.code = code.value(); + this.message = getClass().getSimpleName(); + } + + @Override + public String getMessage() { + return message + logSuffix; + } + + void setKernelArg(CLKernel kernel, int argIndex) { + message += " (kernel name = " + kernel.getFunctionName() + ", num args = " + kernel.getNumArgs() + ", arg index = " + argIndex; + CLProgram program = kernel.getProgram(); + if (program != null) + message += ", source = <<<\n\t" + program.getSource().replaceAll("\n", "\n\t"); + + message += "\n>>> )"; + } + + } + + @ErrorCode(CL_MISALIGNED_SUB_BUFFER_OFFSET) + public static class MisalignedSubBufferOffset extends CLTypedException {} + @ErrorCode(CL_OUT_OF_RESOURCES) + public static class OutOfResources extends CLTypedException {} + @ErrorCode(CL_COMPILER_NOT_AVAILABLE) + public static class CompilerNotAvailable extends CLTypedException {} + @ErrorCode(CL_INVALID_GLOBAL_WORK_SIZE) + public static class InvalidGlobalWorkSize extends CLTypedException {} + @ErrorCode(CL_MAP_FAILURE) + public static class MapFailure extends CLTypedException {} + @ErrorCode(CL_MEM_OBJECT_ALLOCATION_FAILURE) + public static class MemObjectAllocationFailure extends CLTypedException {} + @ErrorCode(CL_INVALID_EVENT_WAIT_LIST) + public static class InvalidEventWaitList extends CLTypedException {} + @ErrorCode(CL_INVALID_ARG_INDEX) + public static class InvalidArgIndex extends CLTypedException {} + @ErrorCode(CL_INVALID_ARG_SIZE) + public static class InvalidArgSize extends CLTypedException {} + @ErrorCode(CL_INVALID_ARG_VALUE) + public static class InvalidArgValue extends CLTypedException {} + @ErrorCode(CL_INVALID_BINARY) + public static class InvalidBinary extends CLTypedException {} + @ErrorCode(CL_INVALID_EVENT) + public static class InvalidEvent extends CLTypedException {} + @ErrorCode(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) + public static class InvalidImageFormatDescriptor extends CLTypedException {} + @ErrorCode(CL_INVALID_IMAGE_SIZE) + public static class InvalidImageSize extends CLTypedException {} + @ErrorCode(CL_INVALID_WORK_DIMENSION) + public static class InvalidWorkDimension extends CLTypedException {} + @ErrorCode(CL_INVALID_WORK_GROUP_SIZE) + public static class InvalidWorkGroupSize extends CLTypedException {} + @ErrorCode(CL_INVALID_WORK_ITEM_SIZE) + public static class InvalidWorkItemSize extends CLTypedException {} + @ErrorCode(CL_INVALID_OPERATION) + public static class InvalidOperation extends CLTypedException {} + @ErrorCode(CL_INVALID_BUFFER_SIZE) + public static class InvalidBufferSize extends CLTypedException {} + @ErrorCode(CL_INVALID_GLOBAL_OFFSET) + public static class InvalidGlobalOffset extends CLTypedException {} + @ErrorCode(CL_OUT_OF_HOST_MEMORY) + public static class OutOfHostMemory extends CLTypedException {} + @ErrorCode(CL_INVALID_COMMAND_QUEUE) + public static class InvalidCommandQueue extends CLTypedException {} + @ErrorCode(CL_MEM_COPY_OVERLAP) + public static class MemCopyOverlap extends CLTypedException {} + @ErrorCode(CL_INVALID_CONTEXT) + public static class InvalidContext extends CLTypedException {} + @ErrorCode(CL_INVALID_KERNEL) + public static class InvalidKernel extends CLTypedException {} + @ErrorCode(CL_INVALID_GL_CONTEXT_APPLE) + public static class InvalidGLContextApple extends CLTypedException {} + @ErrorCode(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR) + public static class InvalidGLShareGroupReference extends CLTypedException {} + @ErrorCode(CL_INVALID_GL_OBJECT) + public static class InvalidGLObject extends CLTypedException {} + @ErrorCode(CL_INVALID_KERNEL_ARGS) + public static class InvalidKernelArgs extends CLTypedException {} + @ErrorCode(CL_INVALID_KERNEL_DEFINITION) + public static class InvalidKernelDefinition extends CLTypedException {} + @ErrorCode(CL_INVALID_KERNEL_NAME) + public static class InvalidKernelName extends CLTypedException {} + @ErrorCode(CL_INVALID_MEM_OBJECT) + public static class InvalidMemObject extends CLTypedException {} + @ErrorCode(CL_INVALID_MIP_LEVEL) + public static class InvalidMipLevel extends CLTypedException {} + @ErrorCode(CL_INVALID_PROGRAM) + public static class InvalidProgram extends CLTypedException {} + @ErrorCode(CL_INVALID_PROGRAM_EXECUTABLE) + public static class InvalidProgramExecutable extends CLTypedException {} + @ErrorCode(CL_INVALID_QUEUE_PROPERTIES) + public static class InvalidQueueProperties extends CLTypedException {} + @ErrorCode(CL_INVALID_VALUE) + public static class InvalidValue extends CLTypedException {} + @ErrorCode(CL_INVALID_SAMPLER) + public static class InvalidSampler extends CLTypedException {} + @ErrorCode(CL_INVALID_DEVICE_TYPE) + public static class InvalidDeviceType extends CLTypedException {} + @ErrorCode(CL_INVALID_BUILD_OPTIONS) + public static class InvalidBuildOptions extends CLTypedException {} + @ErrorCode(CL_BUILD_PROGRAM_FAILURE) + public static class BuildProgramFailure extends CLTypedException {} + + public static String errorString(int err) { + if (err == CL_SUCCESS) + return null; + + List candidates = new ArrayList(); + for (Field f : OpenCLLibrary.class.getDeclaredFields()) { + if (!Modifier.isStatic(f.getModifiers())) { + continue; + } + if (f.getType().equals(Integer.TYPE)) { + try { + int i = (Integer) f.get(null); + if (i == err) { + String name = f.getName(), lname = name.toLowerCase(); + if (lname.contains("invalid") || lname.contains("bad") || lname.contains("illegal") || lname.contains("wrong")) { + candidates.clear(); + candidates.add(name); + break; + } else + candidates.add(name); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return StringUtils.implode(candidates, " or "); + } + + static boolean failedForLackOfMemory(int err, int previousAttempts) { + switch (err) { + case CL_SUCCESS: + return false; + case CL_OUT_OF_HOST_MEMORY: + case CL_OUT_OF_RESOURCES: + case CL_MEM_OBJECT_ALLOCATION_FAILURE: + if (previousAttempts <= 1) { + System.gc(); + if (previousAttempts == 1) { + try { + Thread.sleep(100); + } catch (InterruptedException ex) {} + } + return true; + } + default: + error(err); + assert false; // won't reach + return false; + } + } + static final String logSuffix = System.getenv("CL_LOG_ERRORS") == null ? " (make sure to log all errors with environment variable CL_LOG_ERRORS=stdout)" : ""; + + static Map> typedErrorClassesByCode; + @SuppressWarnings("unchecked") + public static void error(int err) { + if (err == CL_SUCCESS) + return; + //if (err == CL_OUT_OF_RESOURCES) + // return; + + if (typedErrorClassesByCode == null) { + typedErrorClassesByCode = new HashMap>(); + for (Class c : CLException.class.getDeclaredClasses()) { + if (c == CLTypedException.class || !CLTypedException.class.isAssignableFrom(c)) + continue; + typedErrorClassesByCode.put(c.getAnnotation(ErrorCode.class).value(), (Class)c); + } + } + CLException toThrow = null; + Class c = typedErrorClassesByCode.get(err); + if (c != null) { + try { + toThrow = c.newInstance(); + } catch (InstantiationException ex) { + assert log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + assert log(Level.SEVERE, null, ex); + } + } + if (toThrow == null) + toThrow = new CLException("OpenCL Error : " + errorString(err) + logSuffix, err); + + //assert log(Level.SEVERE, null, toThrow); + + throw toThrow; + } +} \ No newline at end of file diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLFloatBuffer.java b/Core/src/main/java/com/nativelibs4java/opencl/CLFloatBuffer.java new file mode 100644 index 00000000..a48b5f9f --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLFloatBuffer.java @@ -0,0 +1,50 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; + +/** + * OpenCL Memory Buffer Object with Float values.
+ * @see CLContext#createFloatBuffer(com.nativelibs4java.opencl.CLMem.Usage, long) + * @see CLContext#createFloatBuffer(com.nativelibs4java.opencl.CLMem.Usage, java.nio.FloatBuffer, boolean) + * @author Olivier Chafik + * @deprecated Use {@link CLBuffer}<{@link Float}> + */ +@Deprecated +public class CLFloatBuffer extends CLBuffer { + CLFloatBuffer(CLContext context, long byteCount, cl_mem entity, Buffer buffer) { + super(context, byteCount, entity, buffer, 4, FloatBuffer.class); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLImage.java b/Core/src/main/java/com/nativelibs4java/opencl/CLImage.java new file mode 100644 index 00000000..3077efca --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLImage.java @@ -0,0 +1,192 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_FALSE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_IMAGE_ELEMENT_SIZE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_IMAGE_FORMAT; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_TRUE; +import static com.nativelibs4java.util.JNAUtils.toNS; +import static com.nativelibs4java.util.NIOUtils.directCopy; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; + +import com.nativelibs4java.opencl.library.cl_image_format; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_event; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; +import com.nativelibs4java.util.NIOUtils; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.ochafik.util.listenable.Pair; +import com.sun.jna.Native; +import com.sun.jna.Pointer; + + +/** + * OpenCL Image Memory Object.
+ * An image object is used to store a two- or three- dimensional texture, frame-buffer or image
+ * An image object is used to represent a buffer that can be used as a texture or a frame-buffer. The elements of an image object are selected from a list of predefined image formats. + * @author Oliveir Chafik + */ +public abstract class CLImage extends CLMem { + + CLImageFormat format; + CLImage(CLContext context, cl_mem entity, CLImageFormat format) { + super(context, -1, entity); + this.format = format; + } + + + + /** + * Return image format descriptor specified when image is created with CLContext.create{Input|Output|InputOutput}{2D|3D}. + */ + @InfoName("CL_IMAGE_FORMAT") + public CLImageFormat getFormat() { + if (format == null) { + /// TODO: DOES NOT SEEM TO WORK ON MAC OS X 10.6.1 / CPU + cl_image_format fmt = new cl_image_format(); + fmt.use(infos.getMemory(getEntity(), CL_IMAGE_FORMAT)); + fmt.read(); + format = new CLImageFormat(fmt); + } + return format; + } + + /** + * Return size of each element of the image memory object given by image.
+ * An element is made up of n channels. The value of n is given in cl_image_format descriptor. + */ + @InfoName("CL_IMAGE_ELEMENT_SIZE") + public long getElementSize() { + return infos.getIntOrLong(getEntity(), CL_IMAGE_ELEMENT_SIZE); + } + + + protected CLEvent read(CLQueue queue, NativeSize[] origin, NativeSize[] region, long rowPitch, long slicePitch, Buffer out, boolean blocking, CLEvent... eventsToWaitFor) { + /*if (!out.isDirect()) { + + }*/ + cl_event[] eventOut = blocking ? null : CLEvent.new_event_out(eventsToWaitFor); + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + error(CL.clEnqueueReadImage(queue.getEntity(), getEntity(), + blocking ? CL_TRUE : CL_FALSE, + origin, + region, + toNS(rowPitch), + toNS(slicePitch), + Native.getDirectBufferPointer(out), + evts == null ? 0 : evts.length, evts, + eventOut + )); + return CLEvent.createEvent(queue, eventOut); + } + + protected CLEvent write(CLQueue queue, NativeSize[] origin, NativeSize[] region, long rowPitch, long slicePitch, Buffer in, boolean blocking, CLEvent... eventsToWaitFor) { + boolean indirect = !in.isDirect(); + if (indirect) + in = directCopy(in, getContext().getByteOrder()); + + cl_event[] eventOut = blocking ? null : CLEvent.new_event_out(eventsToWaitFor); + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + error(CL.clEnqueueWriteImage(queue.getEntity(), getEntity(), + blocking ? CL_TRUE : CL_FALSE, + origin, + region, + toNS(rowPitch), + toNS(slicePitch), + Native.getDirectBufferPointer(in), + evts == null ? 0 : evts.length, evts, + eventOut + )); + CLEvent evt = CLEvent.createEvent(queue, eventOut); + + if (indirect && !blocking) { + final Buffer toHold = in; + evt.invokeUponCompletion(new Runnable() { + public void run() { + // Make sure the GC held a reference to directData until the write was completed ! + toHold.rewind(); + } + }); + } + + return evt; + } + + protected Pair map(CLQueue queue, MapFlags flags, + NativeSize[] offset3, NativeSize[] length3, + Long imageRowPitch, + Long imageSlicePitch, + boolean blocking, CLEvent... eventsToWaitFor) + { + //checkBounds(offset, length); + cl_event[] eventOut = blocking ? null : CLEvent.new_event_out(eventsToWaitFor); + IntBuffer pErr = NIOUtils.directInts(1, ByteOrder.nativeOrder()); + + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + Pointer p = CL.clEnqueueMapImage( + queue.getEntity(), getEntity(), blocking ? CL_TRUE : CL_FALSE, + flags.value(), + offset3, + length3, + imageRowPitch == null ? null : new NativeSizeByReference(toNS(imageRowPitch)), + imageSlicePitch == null ? null : new NativeSizeByReference(toNS(imageSlicePitch)), + evts == null ? 0 : evts.length, evts, + eventOut, + pErr + ); + error(pErr.get()); + return new Pair( + p.getByteBuffer(0, getByteCount()), + CLEvent.createEvent(queue, eventOut) + ); + } + + /** + * @see CLImage2D#map(com.nativelibs4java.opencl.CLQueue, com.nativelibs4java.opencl.CLMem.MapFlags, com.nativelibs4java.opencl.CLEvent[]) + * @see CLImage3D#map(com.nativelibs4java.opencl.CLQueue, com.nativelibs4java.opencl.CLMem.MapFlags, com.nativelibs4java.opencl.CLEvent[]) + * @param queue + * @param buffer + * @param eventsToWaitFor + * @return Event which completion indicates that the OpenCL was unmapped + */ + public CLEvent unmap(CLQueue queue, ByteBuffer buffer, CLEvent... eventsToWaitFor) { + cl_event[] eventOut = CLEvent.new_event_out(eventsToWaitFor); + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + error(CL.clEnqueueUnmapMemObject(queue.getEntity(), getEntity(), Native.getDirectBufferPointer(buffer), evts == null ? 0 : evts.length, evts, eventOut)); + return CLEvent.createEvent(queue, eventOut); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLImage2D.java b/Core/src/main/java/com/nativelibs4java/opencl/CLImage2D.java new file mode 100644 index 00000000..2eca5a8e --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLImage2D.java @@ -0,0 +1,153 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import com.nativelibs4java.opencl.ImageIOUtils.ImageInfo; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_IMAGE_HEIGHT; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_IMAGE_ROW_PITCH; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_IMAGE_WIDTH; +import static com.nativelibs4java.util.JNAUtils.toNS; +import static com.nativelibs4java.util.NIOUtils.directInts; + +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; +import com.nativelibs4java.util.NIOUtils; +import com.ochafik.util.listenable.Pair; + +/** + * OpenCL 2D Image Memory Object
+ * @see CLContext#createImage2D(com.nativelibs4java.opencl.CLMem.Usage, java.awt.Image, boolean) + * @see CLContext#createImage2D(com.nativelibs4java.opencl.CLMem.Usage, com.nativelibs4java.opencl.CLImageFormat, long, long) + * @see CLContext#createImage2D(com.nativelibs4java.opencl.CLMem.Usage, com.nativelibs4java.opencl.CLImageFormat, long, long, long) + * @see CLContext#createImage2D(com.nativelibs4java.opencl.CLMem.Usage, com.nativelibs4java.opencl.CLImageFormat, long, long, long, java.nio.Buffer, boolean) + * @see CLContext#createImage2DFromGLRenderBuffer(com.nativelibs4java.opencl.CLMem.Usage, int) + * @see CLContext#createImage2DFromGLTexture2D(com.nativelibs4java.opencl.CLMem.Usage, com.nativelibs4java.opencl.CLContext.GLTextureTarget, int, int) + * @author Olivier Chafik + */ +public class CLImage2D extends CLImage { + CLImage2D(CLContext context, cl_mem entity, CLImageFormat format) { + super(context, entity, format); + } + + /** + * Return size in bytes of a row of elements of the image object given by image. + */ + @InfoName("CL_IMAGE_ROW_PITCH") + public long getRowPitch() { + return infos.getIntOrLong(getEntity(), CL_IMAGE_ROW_PITCH); + } + + /** + * Return width of the image in pixels + */ + @InfoName("CL_IMAGE_WIDTH") + public long getWidth() { + return infos.getIntOrLong(getEntity(), CL_IMAGE_WIDTH); + } + + /** + * Return height of the image in pixels + */ + @InfoName("CL_IMAGE_HEIGHT") + public long getHeight() { + return infos.getIntOrLong(getEntity(), CL_IMAGE_HEIGHT); + } + + public CLEvent read(CLQueue queue, long minX, long minY, long width, long height, long rowPitch, Buffer out, boolean blocking, CLEvent... eventsToWaitFor) { + return read(queue, toNS(minX, minY, 0), toNS(width, height, 1), rowPitch, 0, out, blocking, eventsToWaitFor); + } + public CLEvent write(CLQueue queue, long minX, long minY, long width, long height, long rowPitch, Buffer in, boolean blocking, CLEvent... eventsToWaitFor) { + return write(queue, toNS(minX, minY, 0), toNS(width, height, 1), rowPitch, 0, in, blocking, eventsToWaitFor); + } + + public BufferedImage read(CLQueue queue, CLEvent... eventsToWaitFor) { + ImageInfo info = ImageIOUtils.getBufferedImageInfo(getFormat()); + int imageType = info == null ? 0 : info.bufferedImageType; + if (imageType == 0) + throw new UnsupportedOperationException("Cannot convert image of format " + getFormat() + " to a BufferedImage."); + //imageType = BufferedImage.TYPE_INT_ARGB; + + BufferedImage im = new BufferedImage((int)getWidth(), (int)getHeight(), imageType); + read(queue, im, false, eventsToWaitFor); + return im; + } + public void read(CLQueue queue, BufferedImage imageOut, boolean allowDeoptimizingDirectWrite, CLEvent... eventsToWaitFor) { + //if (!getFormat().isIntBased()) + // throw new IllegalArgumentException("Image-read only supports int-based RGBA images"); + ImageInfo info = ImageIOUtils.getBufferedImageInfo(getFormat()); + int width = imageOut.getWidth(null), height = imageOut.getHeight(null); + + Buffer dataOut = NIOUtils.directBuffer(width * height * info.channelCount, getContext().getByteOrder(), info.bufferClass); + //Buffer dataOut = info.createBuffer(width, height, true); + //IntBuffer dataOut = directInts(width * height, getContext().getByteOrder()); + read(queue, 0, 0, width, height, 0, dataOut, true, eventsToWaitFor); + info.dataSetter.setData(imageOut, dataOut, allowDeoptimizingDirectWrite); + } + public CLEvent write(CLQueue queue, Image image, CLEvent... eventsToWaitFor) { + return write(queue, image, 0, 0, image.getWidth(null), image.getHeight(null), false, false, eventsToWaitFor); + } + public CLEvent write(CLQueue queue, Image image, boolean allowDeoptimizingDirectRead, boolean blocking, CLEvent... eventsToWaitFor) { + return write(queue, image, 0, 0, image.getWidth(null), image.getHeight(null), allowDeoptimizingDirectRead, blocking, eventsToWaitFor); + } + public CLEvent write(CLQueue queue, Image image, int destX, int destY, int width, int height, boolean allowDeoptimizingDirectRead, boolean blocking, CLEvent... eventsToWaitFor) { + //int imWidth = image.getWidth(null), height = image.getHeight(null); + ImageInfo info = ImageIOUtils.getBufferedImageInfo(getFormat()); + return write(queue, 0, 0, width, height, width * info.pixelByteSize, info.dataGetter.getData(image, null, false, allowDeoptimizingDirectRead, getContext().getByteOrder()), blocking, eventsToWaitFor); + } + public void write(CLQueue queue, BufferedImage imageIn, boolean allowDeoptimizingDirectRead, CLEvent... eventsToWaitFor) { + //if (!getFormat().isIntBased()) + // throw new IllegalArgumentException("Image read only supports int-based RGBA images"); + + int width = imageIn.getWidth(null), height = imageIn.getHeight(null); + ImageInfo info = ImageIOUtils.getBufferedImageInfo(getFormat()); + write(queue, 0, 0, width, height, 0, info.dataGetter.getData(imageIn, null, false, allowDeoptimizingDirectRead, getContext().getByteOrder()), true, eventsToWaitFor); + } + public void write(CLQueue queue, BufferedImage im) { + write(queue, im, false); + } + + public ByteBuffer map(CLQueue queue, MapFlags flags, CLEvent... eventsToWaitFor) { + return map(queue, flags, toNS(0, 0), toNS(getWidth(), getHeight()), getWidth(), null, true, eventsToWaitFor).getFirst(); + } + public ByteBuffer map(CLQueue queue, MapFlags flags, long offsetX, long offsetY, long lengthX, long lengthY, long rowPitch, CLEvent... eventsToWaitFor) { + return map(queue, flags, toNS(offsetX, offsetY), toNS(lengthX, lengthY), rowPitch, null, true, eventsToWaitFor).getFirst(); + } + public Pair mapLater(CLQueue queue, MapFlags flags, boolean blocking, CLEvent... eventsToWaitFor) { + return map(queue, flags, toNS(0, 0), toNS(getWidth(), getHeight()), getWidth(), null, blocking, eventsToWaitFor); + } + public Pair mapLater(CLQueue queue, MapFlags flags, long offsetX, long offsetY, long lengthX, long lengthY, long rowPitch, boolean blocking, CLEvent... eventsToWaitFor) { + return map(queue, flags, toNS(offsetX, offsetY), toNS(lengthX, lengthY), rowPitch, null, blocking, eventsToWaitFor); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLImage3D.java b/Core/src/main/java/com/nativelibs4java/opencl/CLImage3D.java new file mode 100644 index 00000000..42be112f --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLImage3D.java @@ -0,0 +1,93 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_IMAGE_DEPTH; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_IMAGE_SLICE_PITCH; +import static com.nativelibs4java.util.JNAUtils.toNS; + +import java.nio.Buffer; +import java.nio.ByteBuffer; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; +import com.ochafik.util.listenable.Pair; + +/** + * OpenCL 3D Image Memory Object
+ * @see CLContext#createImage3D(com.nativelibs4java.opencl.CLMem.Usage, com.nativelibs4java.opencl.CLImageFormat, long, long, long) + * @see CLContext#createImage3D(com.nativelibs4java.opencl.CLMem.Usage, com.nativelibs4java.opencl.CLImageFormat, long, long, long, long, long) + * @see CLContext#createImage3D(com.nativelibs4java.opencl.CLMem.Usage, com.nativelibs4java.opencl.CLImageFormat, long, long, long, long, long, java.nio.Buffer, boolean) + * @see CLContext#createImage3DFromGLTexture3D(com.nativelibs4java.opencl.CLMem.Usage, int, int) + * @author Olivier Chafik + */ +public class CLImage3D extends CLImage2D { + CLImage3D(CLContext context, cl_mem entity, CLImageFormat format) { + super(context, entity, format); + } + + /** + * Return size in bytes of a 2D slice for this 3D image object.
+ */ + @InfoName("CL_IMAGE_SLICE_PITCH") + public long getSlicePitch() { + return infos.getIntOrLong(getEntity(), CL_IMAGE_SLICE_PITCH); + } + + /** + * Return depth of the image in pixels. + */ + @InfoName("CL_IMAGE_DEPTH") + public long getDepth() { + return infos.getIntOrLong(getEntity(), CL_IMAGE_DEPTH); + } + + public CLEvent read(CLQueue queue, long minX, long minY, long minZ, long width, long height, long depth, long rowPitch, long slicePitch, Buffer out, boolean blocking, CLEvent... eventsToWaitFor) { + return read(queue, toNS(minX, minY, minZ), toNS(width, height, depth), rowPitch, slicePitch, out, blocking, eventsToWaitFor); + } + + public CLEvent write(CLQueue queue, long minX, long minY, long minZ, long width, long height, long depth, long rowPitch, long slicePitch, Buffer in, boolean blocking, CLEvent... eventsToWaitFor) { + return write(queue, toNS(minX, minY, minZ), toNS(width, height, depth), rowPitch, slicePitch, in, blocking, eventsToWaitFor); + } + + public ByteBuffer map(CLQueue queue, MapFlags flags, CLEvent... eventsToWaitFor) { + return map(queue, flags, 0, 0, 0, getWidth(), getHeight(), getDepth(), getWidth(), getHeight(), true, eventsToWaitFor); + } + public Pair mapLater(CLQueue queue, MapFlags flags, CLEvent... eventsToWaitFor) { + return map(queue, flags, toNS(0, 0, 0), toNS(getWidth(), getHeight(), getDepth()), getWidth(), getHeight(), true, eventsToWaitFor); + } + + public ByteBuffer map(CLQueue queue, MapFlags flags, long offsetX, long offsetY, long offsetZ, long lengthX, long lengthY, long lengthZ, long rowPitch, long slicePitch, boolean blocking, CLEvent... eventsToWaitFor) { + return map(queue, flags, toNS(offsetX, offsetY, offsetZ), toNS(lengthX, lengthY, lengthZ), rowPitch, slicePitch, true, eventsToWaitFor).getFirst(); + } + public Pair mapLater(CLQueue queue, MapFlags flags, long offsetX, long offsetY, long offsetZ, long lengthX, long lengthY, long lengthZ, long rowPitch, long slicePitch, CLEvent... eventsToWaitFor) { + return map(queue, flags, toNS(offsetX, offsetY, offsetZ), toNS(lengthX, lengthY, lengthZ), rowPitch, slicePitch, true, eventsToWaitFor); + } + +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLImageFormat.java b/Core/src/main/java/com/nativelibs4java/opencl/CLImageFormat.java new file mode 100644 index 00000000..70857af4 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLImageFormat.java @@ -0,0 +1,284 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; + +import com.nativelibs4java.opencl.library.cl_image_format; +import com.nativelibs4java.util.EnumValue; +import com.nativelibs4java.util.EnumValues; +import com.nativelibs4java.util.ValuedEnum; + +/** + * OpenCL Image Format + * @see CLContext#getSupportedImageFormats(com.nativelibs4java.opencl.CLMem.Flags, com.nativelibs4java.opencl.CLMem.ObjectType) + * @author Olivier Chafik + */ +public class CLImageFormat { + + private final ChannelOrder channelOrder; + private final ChannelDataType channelDataType; + + CLImageFormat(cl_image_format fmt) { + this(ChannelOrder.getEnum(fmt.image_channel_order), ChannelDataType.getEnum(fmt.image_channel_data_type)); + } + cl_image_format to_cl_image_format() { + return new cl_image_format((int)channelOrder.value(), (int)channelDataType.value()); + } + public CLImageFormat(ChannelOrder channelOrder, ChannelDataType channelDataType) { + super(); + this.channelDataType = channelDataType; + this.channelOrder = channelOrder; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof CLImageFormat)) + return false; + CLImageFormat f = (CLImageFormat)obj; + if (channelOrder == null) { + if (f.channelOrder != null) + return false; + } else if (!channelOrder.equals(f.channelOrder)) + return false; + + + if (channelDataType == null) { + return f.channelDataType == null; + } else return channelDataType.equals(f.channelDataType); + } + + @Override + public int hashCode() { + int h = super.hashCode(); + if (channelOrder != null) + h ^= channelOrder.hashCode(); + if (channelDataType != null) + h ^= channelDataType.hashCode(); + return h; + } + + public boolean isIntBased() { + if (channelDataType == null || channelOrder == null) + return false; + switch (getChannelOrder()) { + case ARGB: + case BGRA: + case RGBA: + switch (getChannelDataType()) { + case SNormInt8: + case SignedInt8: + case UNormInt8: + case UnsignedInt8: + return true; + } + } + return false; + } + public final ChannelOrder getChannelOrder() { + return channelOrder; + } + public final ChannelDataType getChannelDataType() { + return channelDataType; + } + + @Override + public String toString() { + return "(" + channelOrder + ", " + channelDataType + ")"; + } + + + + public enum ChannelOrder implements ValuedEnum { + + /** + * components of channel data: (r, 0.0, 0.0, 1.0) + */ + R(CL_R), + /** + * components of channel data: (r, 0.0, 0.0, 1.0) + * @since OpenCL 1.1 + */ + Rx(CL_Rx), + /** + * components of channel data: (0.0, 0.0, 0.0, a) + */ + A(CL_A), + /** + * components of channel data: (I, I, I, I)
+ * This format can only be used if channel data type = CL_UNORM_INT8, CL_UNORM_INT16, CL_SNORM_INT8, CL_SNORM_INT16, CL_HALF_FLOAT or CL_FLOAT. + */ + INTENSITY(CL_INTENSITY), + /** + * components of channel data: (L, L, L, 1.0)
+ * This format can only be used if channel data type = CL_UNORM_INT8, CL_UNORM_INT16, CL_SNORM_INT8, CL_SNORM_INT16, CL_HALF_FLOAT or CL_FLOAT. + */ + LUMINANCE(CL_LUMINANCE), + /** + * components of channel data: (r, g, 0.0, 1.0) + */ + RG(CL_RG), + /** + * components of channel data: (r, g, 0.0, 1.0) + * @since OpenCL 1.1 + */ + RGx(CL_RGx), + /** + * components of channel data: (r, 0.0, 0.0, a) + */ + RA(CL_RA), + /** + * components of channel data: (r, g, b, 1.0)
+ * This format can only be used if channel data type = CL_UNORM_SHORT_565, CL_UNORM_SHORT_555 or CL_UNORM_INT101010. + */ + RGB(CL_RGB), + /** + * components of channel data: (r, g, b, 1.0)
+ * This format can only be used if channel data type = CL_UNORM_SHORT_565, CL_UNORM_SHORT_555 or CL_UNORM_INT101010. + * @since OpenCL 1.1 + */ + RGBx(CL_RGBx), + /** + * components of channel data: (r, g, b, a) + */ + RGBA(CL_RGBA), + /** + * components of channel data: (r, g, b, a) + */ + ARGB(CL_ARGB), + /** + * components of channel data: (r, g, b, a)
+ * This format can only be used if channel data type = CL_UNORM_INT8, CL_SNORM_INT8, CL_SIGNED_INT8 or CL_UNSIGNED_INT8. + */ + BGRA(CL_BGRA); + + + ChannelOrder(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static ChannelOrder getEnum(long v) { return EnumValues.getEnum(v, ChannelOrder.class); } + + } + + /** + * For example, to specify a normalized unsigned 8-bit / channel RGBA image, image_channel_order = CL_RGBA, and image_channel_data_type = CL_UNORM_INT8. The memory layout of this image format is described below: + */ + public enum ChannelDataType implements ValuedEnum { + /** + * Each channel component is a normalized signed 8-bit integer value + */ + SNormInt8(CL_SNORM_INT8, 8), + /** + * Each channel component is a normalized signed 16-bit integer value + */ + SNormInt16(CL_SNORM_INT16, 16), + /** + * Each channel component is a normalized unsigned 8-bit integer value + */ + UNormInt8(CL_UNORM_INT8, 8), + /** + * Each channel component is a normalized unsigned 16- bit integer value + */ + UNormInt16(CL_UNORM_INT16, 16), + /** + * Represents a normalized 5-6-5 3-channel RGB image.
+ * The channel order must be CL_RGB or CL_RGBx.
+ * CL_UNORM_SHORT_565 is a special cases of packed image format where the channels of each element are packed into a single unsigned short or unsigned int.
+ * For this special packed image format, the channels are normally packed with the first channel in the most significant bits of the bitfield, and successive channels occupying progressively less significant locations.
+ * For CL_UNORM_SHORT_565, R is in bits 15:11, G is in bits 10:5 and B is in bits 4:0. + */ + UNormShort565(CL_UNORM_SHORT_565, 16/* ?? */), + /** + * Represents a normalized x-5-5-5 4-channel xRGB image.
+ * The channel order must be CL_RGB or CL_RGBx.
+ * CL_UNORM_SHORT_555 is a special cases of packed image format where the channels of each element are packed into a single unsigned short or unsigned int.
+ * For this special packed image format, the channels are normally packed with the first channel in the most significant bits of the bitfield, and successive channels occupying progressively less significant locations.
+ * For CL_UNORM_SHORT_555, bit 15 is undefined, R is in bits 14:10, G in bits 9:5 and B in bits 4:0. + */ + UNormShort555(CL_UNORM_SHORT_555, 15/* ?? */), + /** + * Represents a normalized x-10-10-10 4-channel xRGB image.
+ * The channel order must be CL_RGB or CL_RGBx.
+ * CL_UNORM_INT_101010 is a special cases of packed image format where the channels of each element are packed into a single unsigned short or unsigned int.
+ * For this special packed image format, the channels are normally packed with the first channel in the most significant bits of the bitfield, and successive channels occupying progressively less significant locations.
+ * For CL_UNORM_INT_101010, bits 31:30 are undefined, R is in bits 29:20, G in bits 19:10 and B in bits 9:0. + */ + UNormInt101010(CL_UNORM_INT_101010, 30/* TODO ?? */), + /** + * Each channel component is an unnormalized signed 8- bit integer value + */ + SignedInt8(CL_SIGNED_INT8, 8), + /** + * Each channel component is an unnormalized signed 16- bit integer value + */ + SignedInt16(CL_SIGNED_INT16, 16), + /** + * Each channel component is an unnormalized signed 32- bit integer value + */ + SignedInt32(CL_SIGNED_INT32, 32), + /** + * Each channel component is an unnormalized unsigned 8-bit integer value + */ + UnsignedInt8(CL_UNSIGNED_INT8, 8), + /** + * Each channel component is an unnormalized unsigned 16-bit integer value + */ + UnsignedInt16(CL_UNSIGNED_INT16, 16), + /** + * Each channel component is an unnormalized unsigned 32-bit integer value + */ + UnsignedInt32(CL_UNSIGNED_INT32, 32), + /** + * Each channel component is a 16-bit half-float value + */ + HalfFloat(CL_HALF_FLOAT, 16), + /** + * Each channel component is a single precision floating- point value + */ + Float(CL_FLOAT, 32); + + ChannelDataType(long value, int bits) { + this.SIZE = bits; + this.value = value; + } + /** + * Size of this ChannelDataType, in bits + */ + public final int SIZE; + long value; + @Override + public long value() { return value; } + public static ChannelDataType getEnum(long v) { return EnumValues.getEnum(v, ChannelDataType.class); } + } + + static CLImageFormat INT_ARGB_FORMAT = new CLImageFormat(ChannelOrder.BGRA, ChannelDataType.UNormInt8); + //static CLImageFormat INT_ARGB_FORMAT = new CLImageFormat(ChannelOrder.RGBA, ChannelDataType.UNormInt8); +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLInfoGetter.java b/Core/src/main/java/com/nativelibs4java/opencl/CLInfoGetter.java new file mode 100644 index 00000000..1c2a514b --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLInfoGetter.java @@ -0,0 +1,148 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.util.JNAUtils.readNS; +import static com.nativelibs4java.util.JNAUtils.toNS; + +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import com.sun.jna.PointerType; +import com.sun.jna.ptr.IntByReference; + +/** + * + * @author ochafik + */ +abstract class CLInfoGetter { + + protected abstract int getInfo(T entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut); + + public String getString(T entity, int infoName) { + NativeSizeByReference pLen = new NativeSizeByReference(); + error(getInfo(entity, infoName, toNS(0), null, pLen)); + + int len = pLen.getValue().intValue(); + if (len == 0) { + return ""; + } + Memory buffer = new Memory(len + 1); + error(getInfo(entity, infoName, pLen.getValue(), buffer, null)); + + return buffer.getString(0); + } + + public Pointer getPointer(T entity, int infoName) { + NativeSizeByReference pLen = new NativeSizeByReference(); + Memory mem = new Memory(Pointer.SIZE); + error(getInfo(entity, infoName, toNS(Pointer.SIZE), mem, pLen)); + if (pLen.getValue().intValue() != Pointer.SIZE) { + throw new RuntimeException("Not a pointer : len = " + pLen.getValue()); + } + return mem.getPointer(0); + } + + public Memory getMemory(T entity, int infoName) { + NativeSizeByReference pLen = new NativeSizeByReference(); + error(getInfo(entity, infoName, toNS(0), null, pLen)); + + Memory buffer = new Memory(pLen.getValue().intValue()); + error(getInfo(entity, infoName, pLen.getValue(), buffer, null)); + + return buffer; + } + + public long[] getNativeSizes(T entity, int infoName, int n) { + int nBytes = NativeSize.SIZE * n; + NativeSizeByReference pLen = new NativeSizeByReference(toNS(nBytes)); + Memory mem = new Memory(nBytes); + error(getInfo(entity, infoName, toNS(nBytes), mem, null)); + + if (pLen.getValue().longValue() != nBytes) { + throw new RuntimeException("Not a Size[" + n + "] : len = " + pLen.getValue()); + } + long[] longs = new long[n]; + for (int i = 0; i < n; i++) { + longs[i] = readNS(mem, i * NativeSize.SIZE).longValue(); + } + return longs; + } + + public int getOptionalFeatureInt(T entity, int infoName) { + try { + return getInt(entity, infoName); + } catch (CLException.InvalidValue ex) { + throw new UnsupportedOperationException("Cannot get value " + infoName, ex); + } catch (CLException.InvalidOperation ex) { + throw new UnsupportedOperationException("Cannot get value " + infoName, ex); + } + } + public int getInt(T entity, int infoName) { + return (int)getIntOrLong(entity, infoName); + } + + public boolean getBool(T entity, int infoName) { + NativeSizeByReference pLen = new NativeSizeByReference(); + Memory mem = new Memory(8); + error(getInfo(entity, infoName, toNS(8), mem, pLen)); + + switch ((int)pLen.getValue().longValue()) { + case 1: + return mem.getByte(0) != 0; + case 2: + return mem.getShort(0) != 0; + case 4: + return mem.getInt(0) != 0; + case 8: + return mem.getLong(0) != 0; + default: + throw new RuntimeException("Not a BOOL : len = " + pLen.getValue()); + } + } + + public long getIntOrLong(T entity, int infoName) { + NativeSizeByReference pLen = new NativeSizeByReference(); + Memory mem = new Memory(8); + error(getInfo(entity, infoName, toNS(8), mem, pLen)); + + switch (pLen.getValue().intValue()) { + case 4: + return mem.getInt(0); + case 8: + return mem.getLong(0); + default: + throw new RuntimeException("Not a native long : len = " + pLen.getValue()); + } + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLIntBuffer.java b/Core/src/main/java/com/nativelibs4java/opencl/CLIntBuffer.java new file mode 100644 index 00000000..1ca79f11 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLIntBuffer.java @@ -0,0 +1,49 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import java.nio.*; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; + +/** + * OpenCL Memory Buffer Object with Int values.
+ * @see CLContext#createIntBuffer(com.nativelibs4java.opencl.CLMem.Usage, long) + * @see CLContext#createIntBuffer(com.nativelibs4java.opencl.CLMem.Usage, java.nio.IntBuffer, boolean) + * @author Olivier Chafik + * @deprecated Use {@link CLBuffer}<{@link Integer}> + */ +@Deprecated +public class CLIntBuffer extends CLBuffer { + CLIntBuffer(CLContext context, long byteCount, cl_mem entity, Buffer buffer) { + super(context, byteCount, entity, buffer, 4, IntBuffer.class); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLKernel.java b/Core/src/main/java/com/nativelibs4java/opencl/CLKernel.java new file mode 100644 index 00000000..e73f9985 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLKernel.java @@ -0,0 +1,427 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.CLException.*; +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import static com.nativelibs4java.util.JNAUtils.toNS; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; +import java.util.HashMap; +import java.util.Map; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_device_id; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_event; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_kernel; +import com.nativelibs4java.util.NIOUtils; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.ByteByReference; +import com.sun.jna.ptr.DoubleByReference; +import com.sun.jna.ptr.FloatByReference; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.LongByReference; +import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.ptr.ShortByReference; + +/** + * OpenCL kernel.
+ * A kernel is a function declared in a program.
+ * A kernel is identified by the __kernel qualifier applied to any function in a program.
+ * A kernel object encapsulates the specific __kernel function declared in a program and the argument values to be used when executing this __kernel function.
+ *
+ * Kernels can be queued for execution in a CLQueue (see enqueueTask and enqueueNDRange) + * See {@link CLProgram#createKernel(java.lang.String, java.lang.Object[])} and {@link CLProgram#createKernels()} + * @author Olivier Chafik + */ +public class CLKernel extends CLAbstractEntity { + + protected final CLProgram program; + protected String name; + private static CLInfoGetter infos = new CLInfoGetter() { + @Override + protected int getInfo(cl_kernel entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetKernelInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + + private volatile CLInfoGetter kernelInfos; + protected synchronized CLInfoGetter getKernelInfos() { + if (kernelInfos == null) + kernelInfos = new CLInfoGetter() { + + @Override + protected int getInfo(cl_device_id entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetKernelWorkGroupInfo(getEntity(), entity, infoTypeEnum, size, out, sizeOut); + } + }; + return kernelInfos; + } + + CLKernel(CLProgram program, String name, cl_kernel entity) { + super(entity); + this.program = program; + this.name = name; + } + public CLProgram getProgram() { + return program; + } + + public String toString() { + return getFunctionName() + " {args: " + getNumArgs() + "}";//, workGroupSize = " + getWorkGroupSize() + ", localMemSize = " + getLocalMemSize() + "}"; + } + + /** + * Returns the preferred multiple of work- group size for launch.
+ * This is a performance hint.
+ * Specifying a work- group size that is not a multiple of the value returned by this query as the value of the local work size argument to clEnqueueNDRangeKernel will not fail to enqueue the kernel for execution unless the work-group size specified is larger than the device maximum. + * @since OpenCL 1.1 + */ + public Map getPreferredWorkGroupSizeMultiple() { + try { + CLDevice[] devices = program.getDevices(); + Map ret = new HashMap(devices.length); + for (CLDevice device : devices) + ret.put(device, getKernelInfos().getIntOrLong(device.getEntity(), CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE)); + return ret; + } catch (Throwable th) { + // TODO check if supposed to handle OpenCL 1.1 + throw new UnsupportedOperationException("Cannot get CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE (OpenCL 1.1 feature).", th); + } + } + + /** + * This provides a mechanism for the application to query the maximum work-group size that can be used to execute a kernel on a specific device given by device.
+ * The OpenCL implementation uses the resource requirements of the kernel (register usage etc.) to determine what this work- group size should be.
+ * See CL_KERNEL_WORK_GROUP_SIZE + */ + public Map getWorkGroupSize() { + CLDevice[] devices = program.getDevices(); + Map ret = new HashMap(devices.length); + for (CLDevice device : devices) + ret.put(device, getKernelInfos().getIntOrLong(device.getEntity(), CL_KERNEL_WORK_GROUP_SIZE)); + return ret; + } + + /** + * Returns the work-group size specified by the __attribute__((reqd_work_gr oup_size(X, Y, Z))) qualifier.
+ * Refer to section 6.7.2.
+ * If the work-group size is not specified using the above attribute qualifier (0, 0, 0) is returned.
+ * See CL_KERNEL_COMPILE_WORK_GROUP_SIZE + * @return for each CLDevice, array of 3 longs + */ + public Map getCompileWorkGroupSize() { + CLDevice[] devices = program.getDevices(); + Map ret = new HashMap(devices.length); + for (CLDevice device : devices) + ret.put(device, getKernelInfos().getNativeSizes(device.getEntity(), CL_KERNEL_COMPILE_WORK_GROUP_SIZE, 3)); + return ret; + } + + /** + * Returns the amount of local memory in bytes being used by a kernel.
+ * This includes local memory that may be needed by an implementation to execute the kernel, variables declared inside the kernel with the __local address qualifier and local memory to be allocated for arguments to the kernel declared as pointers with the __local address qualifier and whose size is specified with clSetKernelArg.
+ * If the local memory size, for any pointer argument to the kernel declared with the __local address qualifier, is not specified, its size is assumed to be 0.
+ * See CL_KERNEL_LOCAL_MEM_SIZE + */ + public Map getLocalMemSize() { + CLDevice[] devices = program.getDevices(); + Map ret = new HashMap(devices.length); + for (CLDevice device : devices) + ret.put(device, getKernelInfos().getIntOrLong(device.getEntity(), CL_KERNEL_LOCAL_MEM_SIZE)); + return ret; + } + + public void setArgs(Object... args) { + for (int i = 0; i < args.length; i++) { + setObjectArg(i, args[i]); + } + } + + public static class LocalSize { + long size; + public LocalSize(long size) { + this.size = size; + } + } + private static final NativeSize zeroNS = toNS(0); + public static final Object NULL_POINTER_KERNEL_ARGUMENT = new Object() {}; + public void setObjectArg(int iArg, Object arg) { + + if (arg == null) + throw new IllegalArgumentException("Null arguments are not accepted. Please use CLKernel.NULL_POINTER_KERNEL_ARGUMENT instead."); + + if (arg == NULL_POINTER_KERNEL_ARGUMENT) { + setArg(iArg, (NativeSize)zeroNS); + //} else if (arg instanceof NativeLong) { + // setArg(iArg, (NativeLong) arg); + } else if (arg instanceof NativeSize) { + setArg(iArg, (NativeSize) arg); + } else if (arg instanceof CLMem) { + setArg(iArg, (CLMem) arg); + } else if (arg instanceof CLEvent) { + setArg(iArg, (CLEvent) arg); + } else if (arg instanceof CLSampler) { + setArg(iArg, (CLSampler) arg); + } else if (arg instanceof Integer) { + setArg(iArg, (Integer) arg); + } else if (arg instanceof LocalSize) { + setArg(iArg, (LocalSize)arg); + } else if (arg instanceof Long) { + setArg(iArg, (Long) arg); + } else if (arg instanceof Short) { + setArg(iArg, (Short) arg); + } else if (arg instanceof Byte) { + setArg(iArg, (Byte) arg); + } else if (arg instanceof Float) { + setArg(iArg, (Float) arg); + } else if (arg instanceof Double) { + setArg(iArg, (Double) arg); + } else if (arg instanceof Boolean) { + setArg(iArg, (byte)(Boolean.TRUE.equals(arg) ? 1 : 0)); + } else if (arg instanceof Buffer) { + setArg(iArg, (Buffer) arg); + } else if (arg instanceof int[]) { + setArg(iArg, IntBuffer.wrap((int[])arg)); + } else if (arg instanceof long[]) { + setArg(iArg, LongBuffer.wrap((long[])arg)); + } else if (arg instanceof short[]) { + setArg(iArg, ShortBuffer.wrap((short[])arg)); + } else if (arg instanceof double[]) { + setArg(iArg, DoubleBuffer.wrap((double[])arg)); + } else if (arg instanceof float[]) { + setArg(iArg, FloatBuffer.wrap((float[])arg)); + } else if (arg instanceof byte[]) { + setArg(iArg, ByteBuffer.wrap((byte[])arg)); + } else if (arg instanceof boolean[]) { + boolean[] bools = (boolean[])arg; + byte[] bytes = new byte[bools.length]; + for (int iValue = 0, n = bools.length; iValue < n; iValue++) + bytes[iValue] = (byte)(bools[iValue] ? 1 : 0); + setArg(iArg, ByteBuffer.wrap(bytes)); + } else { + throw new IllegalArgumentException("Cannot handle kernel arguments of type " + arg.getClass().getName() + ". Use CLKernel.get() and OpenCL4Java directly."); + } + } + + public void setArg(int i, LocalSize arg) { + setLocalArg(i, arg.size); + } + public void setLocalArg(int argIndex, long localArgByteLength) { + setKernelArg(argIndex, toNS(localArgByteLength), null); + } + + //public void setArg(int i, NativeLong arg) { + // error(CL.clSetKernelArg(getEntity(), i, toNS(NativeLong.SIZE), new NativeLongByReference(arg).getPointer())); +// error(CL.clSetKernelArg(get(), i, OpenCL4Java.toNL(Native.LONG_SIZE), new IntByReference(128).getPointer())); +// error(CL.clSetKernelArg(get(), i, toNL(Native.LONG_SIZE), new IntByReference(arg.intValue()).getPointer())); + //} + + public void setArg(int i, float[] arg) { + setArg(i, FloatBuffer.wrap(arg)); + } + public void setArg(int i, int[] arg) { + setArg(i, IntBuffer.wrap(arg)); + } + public void setArg(int i, double[] arg) { + setArg(i, DoubleBuffer.wrap(arg)); + } + public void setArg(int i, long[] arg) { + setArg(i, LongBuffer.wrap(arg)); + } + public void setArg(int i, short[] arg) { + setArg(i, ShortBuffer.wrap(arg)); + } + public void setArg(int i, byte[] arg) { + setArg(i, ByteBuffer.wrap(arg)); + } + public void setArg(int i, char[] arg) { + setArg(i, CharBuffer.wrap(arg)); + } + public void setArg(int i, Buffer arg) { + if (!arg.isDirect()) + arg = NIOUtils.directCopy(arg, getProgram().getContext().getByteOrder()); + long size = NIOUtils.getSizeInBytes(arg); + setKernelArg(i, toNS(size), Native.getDirectBufferPointer(arg)); + } + + protected void setKernelArg(int i, NativeSize size, Pointer ptr) { + try { + error(CL.clSetKernelArg(getEntity(), i, size, ptr)); + } catch (CLTypedException ex) { + ex.setKernelArg(this, i); + throw ex; + } + } + + public void setArg(int i, NativeSize arg) { + switch (getProgram().getContext().getAddressBits()) { + case 32: + setKernelArg(i, toNS(4), new IntByReference(arg.intValue()).getPointer()); + break; + case 64: + setKernelArg(i, toNS(8), new LongByReference(arg.longValue()).getPointer()); + break; + default: + setKernelArg(i, toNS(NativeSize.SIZE), new NativeSizeByReference(arg).getPointer()); + break; + } + } + + public void setArg(int i, int arg) { + setKernelArg(i, toNS(4), new IntByReference(arg).getPointer()); + } + + public void setArg(int i, long arg) { + setKernelArg(i, toNS(8), new LongByReference(arg).getPointer()); + } + + public void setArg(int i, short arg) { + setKernelArg(i, toNS(2), new ShortByReference(arg).getPointer()); + } + + public void setArg(int i, byte arg) { + setKernelArg(i, toNS(1), new ByteByReference(arg).getPointer()); + } + + public void setArg(int i, float arg) { + setKernelArg(i, toNS(4), new FloatByReference(arg).getPointer()); + } + + public void setArg(int i, double arg) { + setKernelArg(i, toNS(8), new DoubleByReference(arg).getPointer()); + } + + public void setArg(int index, CLMem mem) { + setKernelArg(index, toNS(Pointer.SIZE), new PointerByReference(mem.getEntity().getPointer()).getPointer()); + } + + public void setArg(int index, CLEvent event) { + setKernelArg(index, toNS(Pointer.SIZE), new PointerByReference(event.getEntity().getPointer()).getPointer()); + } + + public void setArg(int index, CLSampler sampler) { + setKernelArg(index, toNS(Pointer.SIZE), new PointerByReference(sampler.getEntity().getPointer()).getPointer()); + } + + @Override + protected void clear() { + error(CL.clReleaseKernel(getEntity())); + } + + private static final NativeSize[] oneNL = new NativeSize[] {new NativeSize(1)}; + /** + * Enqueues a command to execute a kernel on a device.
+ * The kernel is executed using a single work-item. + * @param queue + * @param eventsToWaitFor Events that need to complete before this particular command can be executed. + * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete. + */ + public CLEvent enqueueTask(CLQueue queue, CLEvent... eventsToWaitFor) { + cl_event[] eventOut = CLEvent.new_event_out(eventsToWaitFor); + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + error(CL.clEnqueueNDRangeKernel(queue.getEntity(), getEntity(), 1, null, oneNL, oneNL, evts == null ? 0 : evts.length, evts, eventOut)); + return CLEvent.createEvent(queue, eventOut); + } + + /** + * Enqueues a command to execute a kernel on a device (see {@link CLKernel#enqueueNDRange(CLQueue, int[], int[], int[], CLEvent[])}) + * @param globalWorkSizes Each element describes the number of global work-items in a dimension that will execute the kernel function. The total number of global work-items is computed as globalWorkSizes[0] * ... * globalWorkSizes[globalWorkSizes.length - 1]. + * @param localWorkSizes Each element describes the number of work-items that make up a work-group (also referred to as the size of the work-group) that will execute the kernel specified by kernel. The total number of work-items in a work-group is computed as localWorkSizes[0] * ... * localWorkSizes[localWorkSizes.length - 1]. The total number of work-items in the work-group must be less than or equal to the CL_DEVICE_MAX_WORK_GROUP_SIZE value specified in table 4.3 and the number of work- items specified in localWorkSizes[0], ... localWorkSizes[localWorkSizes.length - 1] must be less than or equal to the corresponding values specified by CLDevice.getMaxWorkItemSizes()[dimensionIndex]. The explicitly specified localWorkSize will be used to determine how to break the global work-items specified by global_work_size into appropriate work-group instances. If localWorkSize is specified, the values specified in globalWorkSize[dimensionIndex] must be evenly divisible by the corresponding values specified in localWorkSize[dimensionIndex]. This parameter can be left null, in which case the OpenCL implementation will choose good values. + * @param queue This kernel will be queued for execution on the device associated with that queue. + * @param eventsToWaitFor Events that need to complete before this particular command can be executed. + * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete. + */ + public CLEvent enqueueNDRange(CLQueue queue /*, int[] globalOffsets*/, int[] globalWorkSizes, int[] localWorkSizes, CLEvent... eventsToWaitFor) { + return enqueueNDRange(queue, null, globalWorkSizes, localWorkSizes, eventsToWaitFor); + } + + /** + * Enqueues a command to execute a kernel on a device, using local work sizes chosen by the OpenCL implementation. + * See {@link CLKernel#enqueueNDRange(CLQueue, int[], int[], int[], CLEvent[])} + * @param globalWorkSizes Each element describes the number of global work-items in a dimension that will execute the kernel function. The total number of global work-items is computed as globalWorkSizes[0] * ... * globalWorkSizes[globalWorkSizes.length - 1]. + * @param queue This kernel will be queued for execution on the device associated with that queue. + * @param eventsToWaitFor Events that need to complete before this particular command can be executed. + * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete. + */ + public CLEvent enqueueNDRange(CLQueue queue /*, int[] globalOffsets*/, int[] globalWorkSizes, CLEvent... eventsToWaitFor) { + return enqueueNDRange(queue, null, globalWorkSizes, null, eventsToWaitFor); + } + + /** + * Enqueues a command to execute a kernel on a device. + * @param globalOffsets Must be null in OpenCL 1.0. Each element describes the offset used to calculate the global ID of a work-item. If globalOffsets is null, the global IDs start at offset (0, 0, ... 0). + * @param globalWorkSizes Each element describes the number of global work-items in a dimension that will execute the kernel function. The total number of global work-items is computed as globalWorkSizes[0] * ... * globalWorkSizes[globalWorkSizes.length - 1]. + * @param localWorkSizes Each element describes the number of work-items that make up a work-group (also referred to as the size of the work-group) that will execute the kernel specified by kernel. The total number of work-items in a work-group is computed as localWorkSizes[0] * ... * localWorkSizes[localWorkSizes.length - 1]. The total number of work-items in the work-group must be less than or equal to the CL_DEVICE_MAX_WORK_GROUP_SIZE value specified in table 4.3 and the number of work- items specified in localWorkSizes[0], ... localWorkSizes[localWorkSizes.length - 1] must be less than or equal to the corresponding values specified by CLDevice.getMaxWorkItemSizes()[dimensionIndex]. The explicitly specified localWorkSize will be used to determine how to break the global work-items specified by global_work_size into appropriate work-group instances. If localWorkSize is specified, the values specified in globalWorkSize[dimensionIndex] must be evenly divisible by the corresponding values specified in localWorkSize[dimensionIndex]. This parameter can be left null, in which case the OpenCL implementation will choose good values. + * @param queue This kernel will be queued for execution on the device associated with that queue. + * @param eventsToWaitFor Events that need to complete before this particular command can be executed. + * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete. + */ + public CLEvent enqueueNDRange(CLQueue queue, int[] globalOffsets, int[] globalWorkSizes, int[] localWorkSizes, CLEvent... eventsToWaitFor) { + int nDims = globalWorkSizes.length; + if (localWorkSizes != null && localWorkSizes.length != nDims) { + throw new IllegalArgumentException("Global and local sizes must have same dimensions, given " + globalWorkSizes.length + " vs. " + localWorkSizes.length); + } + cl_event[] eventOut = CLEvent.new_event_out(eventsToWaitFor); + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + error(CL.clEnqueueNDRangeKernel(queue.getEntity(), getEntity(), nDims, toNS(globalOffsets), toNS(globalWorkSizes), toNS(localWorkSizes), evts == null ? 0 : evts.length, evts, eventOut)); + return CLEvent.createEvent(queue, eventOut); + } + + /** + * Return the number of arguments to kernel. + */ + @InfoName("CL_KERNEL_NUM_ARGS") + public int getNumArgs() { + return infos.getInt(getEntity(), CL_KERNEL_NUM_ARGS); + } + + /** + * Return the kernel function name. + */ + @InfoName("CL_KERNEL_FUNCTION_NAME") + public String getFunctionName() { + if (name == null) + name = infos.getString(getEntity(), CL_KERNEL_FUNCTION_NAME); + return name; + } + + +} \ No newline at end of file diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLLongBuffer.java b/Core/src/main/java/com/nativelibs4java/opencl/CLLongBuffer.java new file mode 100644 index 00000000..b3fd23df --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLLongBuffer.java @@ -0,0 +1,49 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import java.nio.*; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; + +/** + * OpenCL Memory Buffer Object with Long values.
+ * @see CLContext#createLongBuffer(com.nativelibs4java.opencl.CLMem.Usage, long) + * @see CLContext#createLongBuffer(com.nativelibs4java.opencl.CLMem.Usage, java.nio.LongBuffer, boolean) + * @author Olivier Chafik + * @deprecated Use {@link CLBuffer}<{@link Long}> + */ +@Deprecated +public class CLLongBuffer extends CLBuffer { + CLLongBuffer(CLContext context, long byteCount, cl_mem entity, Buffer buffer) { + super(context, byteCount, entity, buffer, 8, LongBuffer.class); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLMem.java b/Core/src/main/java/com/nativelibs4java/opencl/CLMem.java new file mode 100644 index 00000000..c42138ba --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLMem.java @@ -0,0 +1,256 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; + +import java.util.EnumSet; + +import com.nativelibs4java.opencl.library.OpenCLLibrary; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; +import com.nativelibs4java.util.EnumValue; +import com.nativelibs4java.util.EnumValues; +import com.nativelibs4java.util.ValuedEnum; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.sun.jna.Callback; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.IntByReference; + +/** + * OpenCL memory object.
+ * Memory objects are categorized into two types: buffer objects, and image objects.
+ * A buffer object stores a one-dimensional collection of elements whereas an image object is used to store a two- or three- dimensional texture, frame-buffer or image.
+ * Elements of a buffer object can be a scalar data type (such as an int, float), vector data type, or a user-defined structure. An image object is used to represent a buffer that can be used as a texture or a frame-buffer. The elements of an image object are selected from a list of predefined image formats.
+ * The minimum number of elements in a memory object is one.
+ * The fundamental differences between a buffer and an image object are: + *
    + *
  • Elements in a buffer are stored in sequential fashion and can be accessed using a pointer by a kernel executing on a device. Elements of an image are stored in a format that is opaque to the user and cannot be directly accessed using a pointer. Built-in functions are provided by the OpenCL C programming language to allow a kernel to read from or write to an image.
  • + *
  • For a buffer object, the data is stored in the same format as it is accessed by the kernel, but in the case of an image object the data format used to store the image elements may not be the same as the data format used inside the kernel. Image elements are always a 4- component vector (each component can be a float or signed/unsigned integer) in a kernel. The built-in function to read from an image converts image element from the format it is stored into a 4-component vector. Similarly, the built-in function to write to an image converts the image element from a 4-component vector to the appropriate image format specified such as 4 8-bit elements, for example.
  • + *
+ * + * Kernels take memory objects as input, and output to one or more memory objects. + * @author Olivier Chafik + */ +public abstract class CLMem extends CLAbstractEntity { + + protected final CLContext context; + protected long byteCount = -1; + boolean isGL; + + protected static CLInfoGetter infos = new CLInfoGetter() { + @Override + protected int getInfo(cl_mem entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetImageInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + + CLMem(CLContext context, long byteCount, cl_mem entity) { + super(entity); + this.byteCount = byteCount; + this.context = context; + } + + public CLContext getContext() { + return context; + } + + public interface DestructorCallback { + void callback(CLMem mem); + } + + /** + * Registers a user callback function that will be called when the memory object is deleted and its resources freed.
+ * Each call to clSetMemObjectDestructorCallback registers the specified user callback function on a callback stack associated with memobj.
+ * The registered user callback functions are called in the reverse order in which they were registered.
+ * The user callback functions are called and then the memory object's resources are freed and the memory object is deleted.
+ * This provides a mechanism for the application (and libraries) using memobj to be notified when the memory referenced by host_ptr, specified when the memory object is created and used as the storage bits for the memory object, can be reused or freed. + * @since OpenCL 1.1 + * @param callback + */ + public void setDestructorCallback(final DestructorCallback callback) { + error(CL.clSetMemObjectDestructorCallback(getEntity(), new clSetMemObjectDestructorCallback_arg1_callback() { + /// @param cl_mem1 user_data + public void invoke(OpenCLLibrary.cl_mem mem, Pointer userData) { + callback.callback(CLMem.this); + } + }, null)); + } + + public CLEvent acquireGLObject(CLQueue queue, CLEvent... eventsToWaitFor) { + return queue.enqueueAcquireGLObjects(new CLMem[] { this }, eventsToWaitFor); + } + + public CLEvent releaseGLObject(CLQueue queue, CLEvent... eventsToWaitFor) { + return queue.enqueueReleaseGLObjects(new CLMem[] { this }, eventsToWaitFor); + } + + /** + * Get the actual size of the memory object in bytes + * @return actual size of the memory object in bytes + */ + public long getByteCount() { + if (byteCount < 0) { + try { + byteCount = infos.getIntOrLong(getEntity(), CL_MEM_SIZE); + } catch (CLException.InvalidMemObject ex) { + if (isGL) + return -1; // GL objects are not (always?) considered as valid mem objects + else + throw ex; + } + } + return byteCount; + } + + /** + * Memory Object Usage enum + */ + public enum Usage { + Input(CL_MEM_READ_ONLY, Flags.ReadOnly), + Output(CL_MEM_WRITE_ONLY, Flags.WriteOnly), + InputOutput(CL_MEM_READ_WRITE, Flags.ReadWrite); + + private int intFlags; + private Flags flags; + Usage(int intFlags, Flags flags) { + this.intFlags = intFlags; + this.flags = flags; + } + public int getIntFlags() { + return intFlags; + } + public Flags getFlags() { + return flags; + } + } + + public enum Flags implements ValuedEnum { + /** + * This flag specifies that the memory object will be read and written by a kernel. This is the default. + */ + ReadWrite(CL_MEM_READ_WRITE), + /** + * This flags specifies that the memory object will be written but not read by a kernel.
+ * Reading from a buffer or image object created with CL_MEM_WRITE_ONLY inside a kernel is undefined. + */ + WriteOnly(CL_MEM_WRITE_ONLY), + /** + * This flag specifies that the memory object is a read-only memory object when used inside a kernel.
+ * Writing to a buffer or image object created with CL_MEM_READ_ONLY inside a kernel is undefined. + */ + ReadOnly(CL_MEM_READ_ONLY), + /** + * This flag is valid only if host_ptr is not NULL. If specified, it indicates that the application wants the OpenCL implementation to use memory referenced by host_ptr as the storage bits for the memory object.
+ * OpenCL implementations are allowed to cache the buffer contents pointed to by host_ptr in device memory. This cached copy can be used when kernels are executed on a device.
+ * The result of OpenCL commands that operate on multiple buffer objects created with the same host_ptr or overlapping host regions is considered to be undefined. + */ + UseHostPtr(CL_MEM_USE_HOST_PTR), + /** + * This flag specifies that the application wants the OpenCL implementation to allocate memory from host accessible memory.
+ * CL_MEM_ALLOC_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.
+ * CL_MEM_COPY_HOST_PTR: This flag is valid only if host_ptr is not NULL. If specified, it indicates that the application wants the OpenCL implementation to allocate memory for the memory object and copy the data from memory referenced by host_ptr.
+ * CL_MEM_COPY_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.
+ * CL_MEM_COPY_HOST_PTR can be used with CL_MEM_ALLOC_HOST_PTR to initialize the contents of the cl_mem object allocated using host-accessible (e.g. PCIe) memory. + */ + AllocHostPtr(CL_MEM_ALLOC_HOST_PTR), + CopyHostPtr(CL_MEM_COPY_HOST_PTR); + + Flags(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static long getValue(EnumSet set) { return EnumValues.getValue(set); } + public static EnumSet getEnumSet(long v) { return EnumValues.getEnumSet(v, Flags.class); } + } + public enum ObjectType implements ValuedEnum { + Buffer(CL_MEM_OBJECT_BUFFER), + Image2D(CL_MEM_OBJECT_IMAGE2D), + Image3D(CL_MEM_OBJECT_IMAGE3D); + + ObjectType(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static ObjectType getEnum(long v) { return EnumValues.getEnum(v, ObjectType.class); } + } + + public enum GLObjectType implements ValuedEnum { + Buffer(CL_GL_OBJECT_BUFFER), + RenderBuffer(CL_GL_OBJECT_RENDERBUFFER), + Texture2D(CL_GL_OBJECT_TEXTURE2D), + Texture3D(CL_GL_OBJECT_TEXTURE3D); + + GLObjectType(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static GLObjectType getEnum(long v) { return EnumValues.getEnum(v, GLObjectType.class); } + } + + public static class GLObjectInfo { + final GLObjectType type; + final int name; + public GLObjectInfo(GLObjectType type, int name) { + this.type = type; + this.name = name; + } + public GLObjectType getType() { + return type; + } + public int getName() { + return name; + } + } + @SuppressWarnings("deprecation") + public GLObjectInfo getGLObjectInfo() { + IntByReference typeRef = new IntByReference(); + IntByReference nameRef = new IntByReference(); + CL.clGetGLObjectInfo(getEntity(), typeRef, nameRef); + return new GLObjectInfo(GLObjectType.getEnum(typeRef.getValue()), nameRef.getValue()); + } + public enum MapFlags implements ValuedEnum { + Read(CL_MAP_READ), + Write(CL_MAP_WRITE), + ReadWrite(CL_MAP_READ | CL_MAP_WRITE); + + MapFlags(long value) { this.value = value; } + long value; + public long value() { return value; } + public static MapFlags getEnum(long v) { return EnumValues.getEnum(v, MapFlags.class); } + } + + @Override + protected void clear() { + error(CL.clReleaseMemObject(getEntity())); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLPlatform.java b/Core/src/main/java/com/nativelibs4java/opencl/CLPlatform.java new file mode 100644 index 00000000..6b5295a5 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLPlatform.java @@ -0,0 +1,516 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + + +import com.nativelibs4java.util.ValuedEnum; +import com.nativelibs4java.opencl.library.OpenGLContextUtils; +import com.nativelibs4java.util.EnumValue; +import com.nativelibs4java.util.EnumValues; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import com.sun.jna.*; +import com.sun.jna.ptr.*; +import java.nio.ByteOrder; +import java.util.*; +import static com.nativelibs4java.opencl.JavaCL.*; +import static com.nativelibs4java.opencl.CLException.*; +import static com.nativelibs4java.util.JNAUtils.*; + +/** + * OpenCL implementation entry point. + * @see JavaCL#listPlatforms() + * @author Olivier Chafik + */ +public class CLPlatform extends CLAbstractEntity { + + CLPlatform(cl_platform_id platform) { + super(platform, true); + } + private static CLInfoGetter infos = new CLInfoGetter() { + + @Override + protected int getInfo(cl_platform_id entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetPlatformInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + + @Override + public String toString() { + return getName() + " {vendor: " + getVendor() + ", version: " + getVersion() + ", profile: " + getProfile() + ", extensions: " + Arrays.toString(getExtensions()) + "}"; + } + + @Override + protected void clear() { + } + + /** + * Lists all the devices of the platform + * @param onlyAvailable if true, only returns devices that are available + * @see CLPlatform#listDevices(java.util.EnumSet, boolean) + */ + public CLDevice[] listAllDevices(boolean onlyAvailable) { + return listDevices(EnumSet.allOf(CLDevice.Type.class), onlyAvailable); + } + + /** + * Lists all the GPU devices of the platform + * @param onlyAvailable if true, only returns GPU devices that are available + * @see CLPlatform#listDevices(java.util.EnumSet, boolean) + */ + public CLDevice[] listGPUDevices(boolean onlyAvailable) { + try { + return listDevices(EnumSet.of(CLDevice.Type.GPU), onlyAvailable); + } catch (CLException ex) { + if (ex.getCode() == CL_DEVICE_NOT_FOUND) { + return new CLDevice[0]; + } + throw new RuntimeException("Unexpected OpenCL error", ex); + } + } + + /** + * Lists all the CPU devices of the platform + * @param onlyAvailable if true, only returns CPU devices that are available + * @see CLPlatform#listDevices(java.util.EnumSet, boolean) + */ + public CLDevice[] listCPUDevices(boolean onlyAvailable) { + try { + return listDevices(EnumSet.of(CLDevice.Type.CPU), onlyAvailable); + } catch (CLException ex) { + if (ex.getCode() == CL_DEVICE_NOT_FOUND) { + return new CLDevice[0]; + } + throw new RuntimeException("Unexpected OpenCL error", ex); + } + } + + private CLDevice[] getDevices(cl_device_id[] ids, boolean onlyAvailable) { + int nDevs = ids.length; + CLDevice[] devices; + if (onlyAvailable) { + List list = new ArrayList(nDevs); + for (int i = 0; i < nDevs; i++) { + CLDevice device = new CLDevice(this, ids[i]); + if (device.isAvailable()) { + list.add(device); + } + } + devices = list.toArray(new CLDevice[list.size()]); + } else { + devices = new CLDevice[nDevs]; + for (int i = 0; i < nDevs; i++) { + devices[i] = new CLDevice(this, ids[i]); + } + } + return devices; + } + + static long[] getContextProps(Map contextProperties) { + if (contextProperties == null) + return null; + final long[] properties = new long[contextProperties.size() * 2 + 1]; + int iProp = 0; + for (Map.Entry e : contextProperties.entrySet()) { + //if (!(v instanceof Number)) throw new IllegalArgumentException("Invalid context property value for '" + e.getKey() + ": " + v); + properties[iProp++] = e.getKey().value(); + Object v = e.getValue(); + if (v instanceof Number) + properties[iProp++] = ((Number)v).longValue(); + else if (v instanceof Pointer) + properties[iProp++] = PointerUtils.getAddress((Pointer)v); + else + throw new IllegalArgumentException("Cannot convert value " + v + " to a context property value !"); + } + //properties[iProp] = 0; + return properties; + } + + /** + * Enums used to indicate how to choose the best CLDevice. + */ + public enum DeviceFeature { + /** + * Prefer CPU devices (see @see CLDevice#getType()) + */ + CPU { + Comparable extractValue(CLDevice device) { + return device.getType().contains(CLDevice.Type.CPU) ? 1 : 0; + } + }, + /** + * Prefer GPU devices (see @see CLDevice#getType()) + */ + GPU { + Comparable extractValue(CLDevice device) { + return device.getType().contains(CLDevice.Type.GPU) ? 1 : 0; + } + }, + /** + * Prefer Accelerator devices (see @see CLDevice#getType()) + */ + Accelerator { + Comparable extractValue(CLDevice device) { + return device.getType().contains(CLDevice.Type.Accelerator) ? 1 : 0; + } + }, + /** + * Prefer devices with the most compute units (see @see CLDevice#getMaxComputeUnits()) + */ + MaxComputeUnits { + Comparable extractValue(CLDevice device) { + return device.getMaxComputeUnits(); + } + }, + /** + * Prefer devices with the same byte ordering as the hosting platform (@see CLDevice#getKernelsDefaultByteOrder()) + */ + NativeEndianness { + Comparable extractValue(CLDevice device) { + return device.getKernelsDefaultByteOrder() == ByteOrder.nativeOrder() ? 1 : 0; + } + }, + /** + * Prefer devices that support double-precision float computations (@see CLDevice#isDoubleSupported()) + */ + DoubleSupport { + Comparable extractValue(CLDevice device) { + return device.isDoubleSupported() ? 1 : 0; + } + }, + /** + * Prefer devices that support images and with the most supported image formats (@see CLDevice#hasImageSupport()) + */ + ImageSupport { + Comparable extractValue(CLDevice device) { + return device.hasImageSupport() ? 1 : 0; + } + }, + /** + * Prefer devices that support out of order queues (@see CLDevice#hasOutOfOrderQueueSupport()) + */ + OutOfOrderQueueSupport { + Comparable extractValue(CLDevice device) { + return device.hasOutOfOrderQueueSupport() ? 1 : 0; + } + }, + /** + * Prefer devices with the greatest variety of supported image formats (@see CLContext#getSupportedImageFormats()) + */ + MostImageFormats { + Comparable extractValue(CLDevice device) { + if (!device.hasImageSupport()) + return 0; + // TODO: fix that ugly hack ? + CLContext context = JavaCL.createContext(null, device); + try { + return (Integer)context.getSupportedImageFormats(CLMem.Flags.ReadWrite, CLMem.ObjectType.Image2D).length; + } finally { + context.release(); + } + } + }; + + Comparable extractValue(CLDevice device) { + throw new RuntimeException(); + } + } + + public static class DeviceComparator implements Comparator { + + private final List evals; + public DeviceComparator(List evals) { + this.evals = evals; + } + + @Override + public int compare(CLDevice a, CLDevice b) { + for (DeviceFeature eval : evals) { + if (eval == null) + continue; + + Comparable va = eval.extractValue(a), vb = eval.extractValue(b); + int c = va.compareTo(vb); + if (c != 0) + return c; + } + return 0; + } + + } + public static CLDevice getBestDevice(List evals, Collection devices) { + List list = new ArrayList(devices); + Collections.sort(list, new DeviceComparator(evals)); + return !list.isEmpty() ? list.get(list.size() - 1) : null; + } + + public CLDevice getBestDevice() { + return getBestDevice(Arrays.asList(DeviceFeature.MaxComputeUnits), Arrays.asList(listGPUDevices(true))); + } + + /** Bit values for CL_CONTEXT_PROPERTIES */ + public enum ContextProperties implements ValuedEnum { + //D3D10Device(CL_CONTEXT_D3D10_DEVICE_KHR), + GLContext(CL_GL_CONTEXT_KHR), + EGLDisplay(CL_EGL_DISPLAY_KHR), + GLXDisplay(CL_GLX_DISPLAY_KHR), + WGLHDC(CL_WGL_HDC_KHR), + Platform(CL_CONTEXT_PLATFORM), + CGLShareGroupApple(CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE), + CGLShareGroup(CL_CGL_SHAREGROUP_KHR); + + ContextProperties(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + + public static long getValue(EnumSet set) { + return EnumValues.getValue(set); + } + + public static EnumSet getEnumSet(long v) { + return EnumValues.getEnumSet(v, ContextProperties.class); + } + } + + public CLContext createContextFromCurrentGL() { + return createGLCompatibleContext(listAllDevices(true)); + } + + static Map getGLContextProperties(CLPlatform platform) { + Map out = new LinkedHashMap(); + + if (Platform.isMac()) { + NativeSize context = OpenGLContextUtils.INSTANCE.CGLGetCurrentContext(); + NativeSize shareGroup = OpenGLContextUtils.INSTANCE.CGLGetShareGroup(context); + out.put(ContextProperties.CGLShareGroupApple, shareGroup.longValue()); + } else if (Platform.isWindows()) { + NativeSize context = OpenGLContextUtils.INSTANCE.wglGetCurrentContext(); + NativeSize dc = OpenGLContextUtils.INSTANCE.wglGetCurrentDC(); + out.put(ContextProperties.GLContext, context.longValue()); + out.put(ContextProperties.WGLHDC, dc.longValue()); + out.put(ContextProperties.Platform, PointerUtils.getAddress(platform.getEntity().getPointer())); + } else if (Platform.isX11()) { + NativeSize context = OpenGLContextUtils.INSTANCE.glXGetCurrentContext(); + NativeSize dc = OpenGLContextUtils.INSTANCE.glXGetCurrentDisplay(); + out.put(ContextProperties.GLContext, context.longValue()); + out.put(ContextProperties.GLXDisplay, dc.longValue()); + out.put(ContextProperties.Platform, PointerUtils.getAddress(platform.getEntity().getPointer())); + } else + throw new UnsupportedOperationException("Current GL context retrieval not implemented on this platform !"); + + //out.put(ContextProperties.Platform, platform.getEntity().getPointer()); + + return out; + } + @Deprecated + public CLContext createGLCompatibleContext(CLDevice... devices) { + try { + return createContext(getGLContextProperties(this), devices); + } catch (Throwable th) {} + + for (CLDevice device : devices) { + if (!device.isGLSharingSupported()) + continue; + + try { + return createContext(getGLContextProperties(this), device); + } catch (Throwable th) {} + } + throw new UnsupportedOperationException("Failed to create an OpenGL-sharing-enabled OpenCL context out of devices " + Arrays.asList(devices)); + } + + /** + * Creates an OpenCL context formed of the provided devices.
+ * It is generally not a good idea to create a context with more than one device, + * because much data is shared between all the devices in the same context. + * @param devices devices that are to form the new context + * @return new OpenCL context + */ + public CLContext createContext(Map contextProperties, CLDevice... devices) { + int nDevs = devices.length; + if (nDevs == 0) { + throw new IllegalArgumentException("Cannot create a context with no associated device !"); + } + cl_device_id[] ids = new cl_device_id[nDevs]; + for (int i = 0; i < nDevs; i++) { + ids[i] = devices[i].getEntity(); + } + + IntByReference errRef = new IntByReference(); + + long[] props = getContextProps(contextProperties); + Memory propsMem = toNSArray(props); + NativeSizeByReference propsRef = new NativeSizeByReference(); + propsRef.setPointer(propsMem); + cl_context context = CL.clCreateContext(propsRef, ids.length, ids, null/*errorCallback.getPointer()*/, null, errRef); + error(errRef.getValue()); + return new CLContext(this, ids, context); + } + /* + public static final clCreateContext_arg1_callback errorCallback = new clCreateContext_arg1_callback() { + public void apply(Pointer errInfo, Pointer private_info, @Ptr long cb, Pointer user_data) { + String log = errInfo.getCString(); + System.out.println("[JavaCL] " + log); + throw new CLException(log); + } + }; + */ + + /** + * List all the devices of the specified types, with only the ones declared as available if onlyAvailable is true. + */ + @SuppressWarnings("deprecation") + public CLDevice[] listDevices(EnumSet types, boolean onlyAvailable) { + int flags = (int) CLDevice.Type.getValue(types); + + IntByReference pCount = new IntByReference(); + error(CL.clGetDeviceIDs(getEntity(), flags, 0, (PointerByReference) null, pCount)); + + int nDevs = pCount.getValue(); + if (nDevs == 0) { + return new CLDevice[0]; + } + + cl_device_id[] ids = new cl_device_id[nDevs]; + + error(CL.clGetDeviceIDs(getEntity(), flags, nDevs, ids, pCount)); + return getDevices(ids, onlyAvailable); + } + + /* + public CLDevice[] listGLDevices(long openglContextId, boolean onlyAvailable) { + + IntByReference errRef = new IntByReference(); + long[] props = getContextProps(getGLContextProperties()); + Memory propsMem = toNSArray(props); + NativeSizeByReference propsRef = new NativeSizeByReference(); + propsRef.setPointer(propsMem); + + NativeSizeByReference pCount = new NativeSizeByReference(); + error(CL.clGetGLContextInfoKHR(propsRef, CL_DEVICES_FOR_GL_CONTEXT_KHR, toNS(0), (Pointer) null, pCount)); + + int nDevs = pCount.getValue().intValue(); + if (nDevs == 0) + return new CLDevice[0]; + Memory idsMem = new Memory(nDevs * Pointer.SIZE); + error(CL.clGetGLContextInfoKHR(propsRef, CL_DEVICES_FOR_GL_CONTEXT_KHR, toNS(nDevs), idsMem, pCount)); + cl_device_id[] ids = new cl_device_id[nDevs]; + for (int i = 0; i < nDevs; i++) + ids[i] = new cl_device_id(idsMem.getPointer(i * Pointer.SIZE)); + return getDevices(ids, onlyAvailable); + }*/ + + /** + * OpenCL profile string. Returns the profile name supported by the implementation. The profile name returned can be one of the following strings: + *
    + *
  • FULL_PROFILE if the implementation supports the OpenCL specification (functionality defined as part of the core specification and does not require any extensions to be supported).
  • + *
  • EMBEDDED_PROFILE if the implementation supports the OpenCL embedded profile. The embedded profile is defined to be a subset for each version of OpenCL. The embedded profile for OpenCL 1.0 is described in section 10.
  • + *
+ */ + @InfoName("CL_PLATFORM_PROFILE") + public String getProfile() { + return infos.getString(getEntity(), CL_PLATFORM_PROFILE); + } + + /** + OpenCL version string. Returns the OpenCL version supported by the implementation. This version string has the following format: + OpenCL + Last Revision Date: 5/16/09 Page 30 + The major_version.minor_version value returned will be 1.0. + */ + @InfoName("CL_PLATFORM_VERSION") + public String getVersion() { + return infos.getString(getEntity(), CL_PLATFORM_VERSION); + } + + /** + * Platform name string. + */ + @InfoName("CL_PLATFORM_NAME") + public String getName() { + return infos.getString(getEntity(), CL_PLATFORM_NAME); + } + + /** + * Platform vendor string. + */ + @InfoName("CL_PLATFORM_VENDOR") + public String getVendor() { + return infos.getString(getEntity(), CL_PLATFORM_VENDOR); + } + + /** + * Returns a list of extension names
+ * Extensions defined here must be supported by all devices associated with this platform. + */ + @InfoName("CL_PLATFORM_EXTENSIONS") + public String[] getExtensions() { + if (extensions == null) { + extensions = infos.getString(getEntity(), CL_PLATFORM_EXTENSIONS).split("\\s+"); + } + return extensions; + } + + private String[] extensions; + + boolean hasExtension(String name) { + name = name.trim(); + for (String x : getExtensions()) { + if (name.equals(x.trim())) { + return true; + } + } + return false; + } + + @InfoName("cl_nv_device_attribute_query") + public boolean isNVDeviceAttributeQuerySupported() { + return hasExtension("cl_nv_device_attribute_query"); + } + + @InfoName("cl_nv_compiler_options") + public boolean isNVCompilerOptionsSupported() { + return hasExtension("cl_nv_compiler_options"); + } + + @InfoName("cl_khr_byte_addressable_store") + public boolean isByteAddressableStoreSupported() { + return hasExtension("cl_khr_byte_addressable_store"); + } + + @InfoName("cl_khr_gl_sharing") + public boolean isGLSharingSupported() { + return hasExtension("cl_khr_gl_sharing") || hasExtension("cl_APPLE_gl_sharing"); + } + +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLProgram.java b/Core/src/main/java/com/nativelibs4java/opencl/CLProgram.java new file mode 100644 index 00000000..4f9ccb69 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLProgram.java @@ -0,0 +1,768 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import com.ochafik.util.listenable.Pair; +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.opencl.CLException.errorString; +import static com.nativelibs4java.opencl.CLException.failedForLackOfMemory; +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.JavaCL.log; +import java.util.logging.Level; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_PROGRAM_BINARIES; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_PROGRAM_BINARY_SIZES; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_PROGRAM_BUILD_LOG; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_PROGRAM_SOURCE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_SUCCESS; +import static com.nativelibs4java.util.JNAUtils.readNSArray; +import static com.nativelibs4java.util.JNAUtils.toNS; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.net.MalformedURLException; +import java.net.URLConnection; +import java.net.URL; + +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Arrays; +import java.util.Map; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_device_id; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_kernel; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_program; +import com.nativelibs4java.util.NIOUtils; +import com.ochafik.io.IOUtils; +import com.ochafik.io.ReadText; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.ochafik.util.string.RegexUtils; +import com.sun.jna.Memory; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.Process; +import java.net.URL; +import java.util.Collection; +import java.util.regex.Pattern; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; +import java.util.zip.GZIPOutputStream; +import java.util.zip.GZIPInputStream; + +/** + * OpenCL program.
+ * An OpenCL program consists of a set of kernels that are identified as functions declared with the __kernel qualifier in the program source. OpenCL programs may also contain auxiliary functions and constant data that can be used by __kernel functions. The program executable can be generated online or offline by the OpenCL compiler for the appropriate target device(s).
+ * A program object encapsulates the following information: + *
    + *
  • An associated context.
  • + *
  • A program source or binary.
  • + *
  • The latest successfully built program executable
  • + *
  • The list of devices for which the program executable is built
  • + *
  • The build options used and a build log.
  • + *
  • The number of kernel objects currently attached.
  • + *
+ * + * A program can be compiled on the fly (costly) but its binaries can be stored and + * loaded back in subsequent executions to avoid recompilation.
+ * By default, program binaries are automatically cached on stable platforms (which currently exclude ATI Stream), but the caching can be forced on/off with * @see CLContext#setCached(boolean).
+ * To create a program from sources, please use @see CLContext#createProgram(java.lang.String[]) + * @author Olivier Chafik + */ +public class CLProgram extends CLAbstractEntity { + + protected final CLContext context; + + private static CLInfoGetter infos = new CLInfoGetter() { + @Override + protected int getInfo(cl_program entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetProgramInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + + CLDevice[] devices; + CLProgram(CLContext context, CLDevice... devices) { + super(null, true); + this.context = context; + this.devices = devices == null || devices.length == 0 ? context.getDevices() : devices; + } + CLProgram(CLContext context, Map binaries, String source) { + super(null, true); + this.context = context; + this.source = source; + + setBinaries(binaries); + } + protected void setBinaries(Map binaries) { + if (this.devices == null) { + this.devices = new CLDevice[binaries.size()]; + int iDevice = 0; + for (CLDevice device : binaries.keySet()) + this.devices[iDevice++] = device; + } + int nDevices = this.devices.length; + NativeSize[] lengths = new NativeSize[nDevices]; + cl_device_id[] deviceIds = new cl_device_id[nDevices]; + Memory binariesArray = new Memory(Pointer.SIZE * nDevices); + Memory[] binariesMems = new Memory[nDevices]; + + for (int iDevice = 0; iDevice < nDevices; iDevice++) + { + CLDevice device = devices[iDevice]; + byte[] binary = binaries.get(device); + + Memory binaryMem = binariesMems[iDevice] = new Memory(binary.length); + binaryMem.write(0, binary, 0, binary.length); + binariesArray.setPointer(iDevice * Pointer.SIZE, binaryMem); + + lengths[iDevice] = toNS(binary.length); + deviceIds[iDevice] = device.getEntity(); + } + PointerByReference binariesPtr = new PointerByReference(); + binariesPtr.setPointer(binariesArray); + + IntBuffer errBuff = NIOUtils.directInts(1, ByteOrder.nativeOrder()); + int previousAttempts = 0; + IntBuffer statuses = NIOUtils.directInts(nDevices, ByteOrder.nativeOrder()); + do { + entity = CL.clCreateProgramWithBinary(context.getEntity(), nDevices, deviceIds, lengths, binariesPtr, statuses, errBuff); + } while (failedForLackOfMemory(errBuff.get(0), previousAttempts++)); + } + + /** + * Write the compiled binaries of this program (for all devices it was compiled for), so that it can be restored later using {@link CLContext#loadProgram(java.io.InputStream) } + * @param out will be closed + * @throws CLBuildException + * @throws IOException + */ + public void store(OutputStream out) throws CLBuildException, IOException { + writeBinaries(getBinaries(), getSource(), null, out); + } + + private static final void addStoredEntry(ZipOutputStream zout, String name, byte[] data) throws IOException { + ZipEntry ze = new ZipEntry(name); + ze.setMethod(ZipEntry.STORED); + ze.setSize(data.length); + CRC32 crc = new CRC32(); + crc.update(data,0,data.length); + ze.setCrc(crc.getValue()); + zout.putNextEntry(ze); + zout.write(data); + zout.closeEntry(); + } + + private static final String BinariesSignatureZipEntryName = "SIGNATURE", SourceZipEntryName = "SOURCE", textEncoding = "utf-8"; + public static void writeBinaries(Map binaries, String source, String contentSignatureString, OutputStream out) throws IOException { + Map binaryBySignature = new HashMap(); + for (Map.Entry e : binaries.entrySet()) + binaryBySignature.put(e.getKey().createSignature(), e.getValue()); // Maybe multiple devices will have the same signature : too bad, we don't care and just write one binary per signature. + + ZipOutputStream zout = new ZipOutputStream(new GZIPOutputStream(new BufferedOutputStream(out))); + if (contentSignatureString != null) + addStoredEntry(zout, BinariesSignatureZipEntryName, contentSignatureString.getBytes(textEncoding)); + + if (source != null) + addStoredEntry(zout, SourceZipEntryName, source.getBytes(textEncoding)); + + for (Map.Entry e : binaryBySignature.entrySet()) + addStoredEntry(zout, e.getKey(), e.getValue()); + + zout.close(); + } + public static Pair, String> readBinaries(List allowedDevices, String expectedContentSignatureString, InputStream in) throws IOException { + Map ret = new HashMap(); + Map> devicesBySignature = CLDevice.getDevicesBySignature(allowedDevices); + + ZipInputStream zin = new ZipInputStream(new GZIPInputStream(new BufferedInputStream(in))); + ZipEntry ze; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + + String source = null; + + boolean first = true; + byte[] b = new byte[65536]; + while ((ze = zin.getNextEntry()) != null) { + String signature = ze.getName(); + boolean isSignature = signature.equals(BinariesSignatureZipEntryName); + if (first && !isSignature && expectedContentSignatureString != null || + !first && isSignature) + throw new IOException("Expected signature to be the first zip entry, got '" + signature + "' instead !"); + + first = false; + bout.reset(); + int len; + while ((len = zin.read(b)) > 0) + bout.write(b, 0, len); + + byte[] data = bout.toByteArray(); + if (isSignature) { + if (expectedContentSignatureString != null) { + String contentSignatureString = new String(data, textEncoding); + if (!expectedContentSignatureString.equals(contentSignatureString)) + throw new IOException("Content signature does not match expected one :\nExpected '" + expectedContentSignatureString + "',\nGot '" + contentSignatureString + "'"); + } + } else if (signature.equals(SourceZipEntryName)) { + source = new String(data, textEncoding); + } else { + List devices = devicesBySignature.get(signature); + for (CLDevice device : devices) + ret.put(device, data); + } + } + zin.close(); + return new Pair, String>(ret, source); + } + + List sources = new ArrayList(); + Map programByDevice = new HashMap(); + + public CLDevice[] getDevices() { + return devices.clone(); + } + + /// Workaround to avoid crash of ATI Stream 2.0.0 final (beta 3 & 4 worked fine) + public static boolean passMacrosAsSources = true; + + public synchronized void allocate() { + if (entity != null) + throw new IllegalThreadStateException("Program was already allocated !"); + + if (passMacrosAsSources) { + if (macros != null && !macros.isEmpty()) { + StringBuilder b = new StringBuilder(); + for (Map.Entry m : macros.entrySet()) + b.append("#define " + m.getKey() + " " + m.getValue() + "\n"); + this.sources.add(0, b.toString()); + } + } + + if (!"false".equals(System.getProperty("javacl.adjustDoubleExtension")) && !"0".equals(System.getenv("JAVACL_ADJUST_DOUBLE_EXTENSION"))) { + for (int i = 0, len = sources.size(); i < len; i++) { + String source = sources.get(i); + for (CLDevice device : getDevices()) + source = device.replaceDoubleExtensionByExtensionActuallyAvailable(source); + sources.set(i, source); + // TODO keep different sources for each device !!! + } + } + + String[] sources = this.sources.toArray(new String[this.sources.size()]); + NativeSize[] lengths = new NativeSize[sources.length]; + for (int i = 0; i < sources.length; i++) { + lengths[i] = toNS(sources[i].length()); + } + IntBuffer errBuff = NIOUtils.directInts(1, ByteOrder.nativeOrder()); + cl_program program; + int previousAttempts = 0; + do { + program = CL.clCreateProgramWithSource(context.getEntity(), sources.length, sources, lengths, errBuff); + } while (failedForLackOfMemory(errBuff.get(0), previousAttempts++)); + entity = program; + } + + @Override + protected synchronized cl_program getEntity() { + if (entity == null) + allocate(); + + return entity; + } + + List includes; + + /** + * Add a path (file or URL) to the list of paths searched for included files.
+ * OpenCL kernels may contain #include "subpath/file.cl" statements.
+ * This automatically adds a "-Ipath" argument to the compilator's command line options.
+ * Note that it's not necessary to add include paths for files that are in the classpath. + * @param path A file or URL that points to the root path from which includes can be resolved. + */ + public synchronized void addInclude(String path) { + if (includes == null) + includes = new ArrayList(); + includes.add(path); + resolvedInclusions = null; + } + public synchronized void addSource(String src) { + if (entity != null) + throw new IllegalThreadStateException("Program was already allocated : cannot add sources anymore."); + sources.add(src); + resolvedInclusions = null; + } + + Map resolvedInclusions; + + protected Runnable copyIncludesToTemporaryDirectory() throws IOException { + Map inclusions = resolveInclusions(); + File includesDir = JavaCL.createTempDirectory("includes", "", "includes"); + final List filesToDelete = new ArrayList(); + for (Map.Entry e : inclusions.entrySet()) { + assert log(Level.INFO, "Copying include '" + e.getKey() + "' from '" + e.getValue() + "' to '" + includesDir + "'"); + File f = new File(includesDir, e.getKey().replace('/', File.separatorChar)); + File p = f.getParentFile(); + filesToDelete.add(f); + if (p != null) { + p.mkdirs(); + filesToDelete.add(p); + } + InputStream in = e.getValue().openStream(); + OutputStream out = new FileOutputStream(f); + IOUtils.readWrite(in, out); + in.close(); + out.close(); + f.deleteOnExit(); + } + filesToDelete.add(includesDir); + addInclude(includesDir.toString()); + return new Runnable() { public void run() { + for (File f : filesToDelete) + f.delete(); + }}; + } + public Map resolveInclusions() throws IOException { + if (resolvedInclusions == null) { + resolvedInclusions = new HashMap(); + for (String source : sources) + resolveInclusions(source, resolvedInclusions); + } + return resolvedInclusions; + } + + static Pattern includePattern = Pattern.compile("#\\s*include\\s*\"([^\"]+)\""); + private void resolveInclusions(String source, Map ret) throws IOException { + Collection includedPaths = RegexUtils.find(source, includePattern, 1); + //System.out.println("Included paths = " + includedPaths); + for (String includedPath : includedPaths) { + if (ret.containsKey(includedPath)) + continue; + URL url = getIncludedSourceURL(includedPath); + if (url == null) { + assert log(Level.SEVERE, "Failed to resolve include '" + includedPath + "'"); + } else { + String s = ReadText.readText(url); + ret.put(includedPath, url); + resolveInclusions(s, ret); + } + } + } + + public String getIncludedSourceContent(String path) throws IOException { + URL url = getIncludedSourceURL(path); + if (url == null) + return null; + + String src = ReadText.readText(url); + return src; + } + + public URL getIncludedSourceURL(String path) throws MalformedURLException { + File f = new File(path); + if (f.exists()) + return f.toURI().toURL(); + URL url = getClass().getClassLoader().getResource(path); + if (url != null) + return url; + + if (includes != null) + for (String include : includes) { + f = new File(new File(include), path); + if (f.exists()) + return f.toURI().toURL(); + + url = getClass().getClassLoader().getResource(f.toString()); + if (url != null) + return url; + + try { + url = new URL(include + (include.endsWith("/") ? "" : "/") + path); + url.openStream().close(); + return url; + } catch (IOException ex) { + // Bad URL or impossible to read from the URL + } + + } + + return null; + } + + String source; + /** + * Get the source code of this program + */ + public synchronized String getSource() { + if (source == null) + source = infos.getString(getEntity(), CL_PROGRAM_SOURCE); + + return source; + } + + /** + * Get the binaries of the program (one for each device, in order) + * @return map from each device the program was compiled for to the corresponding binary data + */ + public Map getBinaries() throws CLBuildException { + synchronized (this) { + if (!built) + build(); + } + + Memory s = infos.getMemory(getEntity(), CL_PROGRAM_BINARY_SIZES); + int n = (int)s.getSize() / Native.SIZE_T_SIZE; + NativeSize[] sizes = readNSArray(s, n); + //int[] sizes = new int[n]; + //for (int i = 0; i < n; i++) { + // sizes[i] = s.getNativeLong(i * Native.LONG_SIZE).intValue(); + //} + + Memory[] binMems = new Memory[n]; + Memory ptrs = new Memory(n * Native.POINTER_SIZE); + for (int i = 0; i < n; i++) { + ptrs.setPointer(i * Native.POINTER_SIZE, binMems[i] = new Memory(sizes[i].intValue())); + } + error(infos.getInfo(getEntity(), CL_PROGRAM_BINARIES, toNS(ptrs.getSize() * Native.POINTER_SIZE), ptrs, null)); + + Map ret = new HashMap(devices.length); + int iBin = n == devices.length + 1 ? 1 : 0; + for (int i = 0; i < n; i++) { + CLDevice device = devices[i]; + Memory bytes = binMems[iBin + i]; + if (bytes != null) + ret.put(device, bytes.getByteArray(0, sizes[iBin + i].intValue())); + } + return ret; + } + + /** + * Returns the context of this program + */ + public CLContext getContext() { + return context; + } + Map macros; + public CLProgram defineMacro(String name, Object value) { + createMacros(); + macros.put(name, value); + return this; + } + public CLProgram undefineMacro(String name) { + if (macros != null) + macros.remove(name); + return this; + } + + private void createMacros() { + if (macros == null) + macros = new LinkedHashMap(); + } + public void defineMacros(Map macros) { + createMacros(); + this.macros.putAll(macros); + } + List extraBuildOptions; + + /** + * Add the -cl-fast-relaxed-math compile option.
+ * Sets the optimization options -cl-finite-math-only and -cl-unsafe-math-optimizations. + * This allows optimizations for floating-point arithmetic that may violate the IEEE 754 standard and the OpenCL numerical compliance requirements defined in the specification in section 7.4 for single-precision floating-point, section 9.3.9 for double-precision floating-point, and edge case behavior in section 7.5. + * This option causes the preprocessor macro __FAST_RELAXED_MATH__ to be defined in the OpenCL program.
+ * Also see : Khronos' documentation for clBuildProgram. + */ + public void setFastRelaxedMath() { + addBuildOption("-cl-fast-relaxed-math"); + } + + /** + * Add the -cl-no-signed-zero compile option.
+ * Allow optimizations for floating-point arithmetic that ignore the signedness of zero. + * IEEE 754 arithmetic specifies the behavior of distinct +0.0 and -0.0 values, which then prohibits simplification of expressions such as x+0.0 or 0.0*x (even with -clfinite-math only). + * This option implies that the sign of a zero result isn't significant.
+ * Also see : Khronos' documentation for clBuildProgram. + */ + public void setNoSignedZero() { + addBuildOption("-cl-no-signed-zero"); + } + + /** + * Add the -cl-mad-enable compile option.
+ * Allow a * b + c to be replaced by a mad. The mad computes a * b + c with reduced accuracy. For example, some OpenCL devices implement mad as truncate the result of a * b before adding it to c.
+ * Also see : Khronos' documentation for clBuildProgram. + */ + public void setMadEnable() { + addBuildOption("-cl-mad-enable"); + } + /** + * Add the -cl-finite-math-only compile option.
+ * Allow optimizations for floating-point arithmetic that assume that arguments and results are not NaNs or infinites. This option may violate the OpenCL numerical compliance requirements defined in in section 7.4 for single-precision floating-point, section 9.3.9 for double-precision floating-point, and edge case behavior in section 7.5.
+ * Also see : Khronos' documentation for clBuildProgram. + */ + public void setFiniteMathOnly() { + addBuildOption("-cl-finite-math-only"); + } + /** + * Add the -cl-unsafe-math-optimizations option.
+ * Allow optimizations for floating-point arithmetic that (a) assume that arguments and results are valid, (b) may violate IEEE 754 standard and (c) may violate the OpenCL numerical compliance requirements as defined in section 7.4 for single-precision floating-point, section 9.3.9 for double-precision floating-point, and edge case behavior in section 7.5. This option includes the -cl-no-signed-zeros and -cl-mad-enable options.
+ * Also see : Khronos' documentation for clBuildProgram. + */ + public void setUnsafeMathOptimizations() { + addBuildOption("-cl-unsafe-math-optimizations"); + } + + /** + * Please see OpenCL's clBuildProgram documentation for details on supported build options. + */ + public synchronized void addBuildOption(String option) { + if (option.startsWith("-I")) { + addInclude(option.substring(2)); + return; + } + if (extraBuildOptions == null) + extraBuildOptions = new ArrayList(); + + extraBuildOptions.add(option); + } + + protected String getOptionsString() { + StringBuilder b = new StringBuilder("-DJAVACL=1 "); + + if (extraBuildOptions != null) + for (String option : extraBuildOptions) + b.append(option).append(' '); + + // http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clBuildProgram.html + //b.append("-O2 -cl-no-signed-zeros -cl-unsafe-math-optimizations -cl-finite-math-only -cl-fast-relaxed-math -cl-strict-aliasing "); + + if (!passMacrosAsSources && macros != null && !macros.isEmpty()) + for (Map.Entry m : macros.entrySet()) + b.append("-D" + m.getKey() + "=" + m.getValue() + " "); + + if (includes != null) + for (String path : includes) + if (new File(path).exists()) // path can be an URL as well, in which case it's copied to a local file copyIncludesToTemporaryDirectory() + b.append("-I").append(path).append(' '); + + return b.toString(); + } + + private volatile Boolean cached; + public synchronized void setCached(boolean cached) { + this.cached = cached; + } + public synchronized boolean isCached() { + if (cached == null) + cached = context.getCacheBinaries(); + return cached; + } + + protected String computeCacheSignature() throws IOException { + StringBuilder b = new StringBuilder(1024); + for (CLDevice device : getDevices()) + b.append(device).append("\n"); + + b.append(getOptionsString()).append('\n'); + if (macros != null) + for (Map.Entry m : macros.entrySet()) + b.append("-D").append(m.getKey()).append("=").append(m.getValue()).append('\n'); + + if (includes != null) + for (String path : includes) + b.append("-I").append(path).append('\n'); + + if (sources != null) + for (String source : sources) + b.append(source).append("\n"); + + Map inclusions = resolveInclusions(); + for (Map.Entry e : inclusions.entrySet()) { + URLConnection con = e.getValue().openConnection(); + InputStream in = con.getInputStream(); + b.append('#').append(e.getKey()).append(con.getLastModified()).append('\n'); + in.close(); + } + return b.toString(); + } + + boolean built; + /** + * Returns the context of this program + */ + public synchronized CLProgram build() throws CLBuildException { + if (built) + throw new IllegalThreadStateException("Program was already built !"); + + String contentSignature = null; + File cacheFile = null; + boolean readBinaries = false; + if (isCached()) { + try { + contentSignature = computeCacheSignature(); + byte[] sha = java.security.MessageDigest.getInstance("MD5").digest(contentSignature.getBytes(textEncoding)); + StringBuilder shab = new StringBuilder(); + for (byte b : sha) + shab.append(Integer.toHexString(b & 0xff)); + String hash = shab.toString(); + cacheFile = new File(JavaCL.userCacheDir, hash); + if (cacheFile.exists()) { + Pair, String> bins = readBinaries(Arrays.asList(getDevices()), contentSignature, new FileInputStream(cacheFile)); + setBinaries(bins.getFirst()); + this.source = bins.getSecond(); + assert log(Level.INFO, "Read binaries cache from '" + cacheFile + "'"); + readBinaries = true; + } + } catch (Exception ex) { + assert log(Level.WARNING, "Failed to load cached program", ex); + entity = null; + } + } + + if (entity == null) + allocate(); + + Runnable deleteTempFiles = null; + if (!readBinaries) + try { + deleteTempFiles = copyIncludesToTemporaryDirectory(); + } catch (IOException ex) { + throw new CLBuildException(this, ex.toString(), Collections.EMPTY_LIST); + } + + int nDevices = devices.length; + cl_device_id[] deviceIds = null; + if (nDevices != 0) { + deviceIds = new cl_device_id[nDevices]; + for (int i = 0; i < nDevices; i++) + deviceIds[i] = devices[i].getEntity(); + } + int err = CL.clBuildProgram(getEntity(), nDevices, deviceIds, readBinaries ? null : getOptionsString(), null, null); + //int err = CL.clBuildProgram(getEntity(), 0, null, getOptionsString(), null, null); + if (err != CL_SUCCESS) {//BUILD_PROGRAM_FAILURE) { + NativeSizeByReference len = new NativeSizeByReference(); + int bufLen = 2048 * 32; //TODO find proper size + Memory buffer = new Memory(bufLen); + + HashSet errs = new HashSet(); + if (deviceIds == null) { + error(CL.clGetProgramBuildInfo(getEntity(), null, CL_PROGRAM_BUILD_LOG, toNS(bufLen), buffer, len)); + String s = buffer.getString(0); + errs.add(s); + } else + for (cl_device_id device : deviceIds) { + error(CL.clGetProgramBuildInfo(getEntity(), device, CL_PROGRAM_BUILD_LOG, toNS(bufLen), buffer, len)); + String s = buffer.getString(0); + errs.add(s); + } + + throw new CLBuildException(this, "Compilation failure : " + errorString(err), errs); + } + built = true; + if (deleteTempFiles != null) + deleteTempFiles.run(); + + if (isCached() && !readBinaries) { + JavaCL.userCacheDir.mkdirs(); + try { + writeBinaries(getBinaries(), getSource(), contentSignature, new FileOutputStream(cacheFile)); + assert log(Level.INFO, "Wrote binaries cache to '" + cacheFile + "'"); + } catch (Exception ex) { + new IOException("[JavaCL] Failed to cache program", ex).printStackTrace(); + } + } + + return this; + } + + @Override + protected void clear() { + error(CL.clReleaseProgram(getEntity())); + } + + /** + * Return all the kernels found in the program. + */ + public CLKernel[] createKernels() throws CLBuildException { + synchronized (this) { + if (!built) + build(); + } + IntByReference pCount = new IntByReference(); + int previousAttempts = 0; + while (failedForLackOfMemory(CL.clCreateKernelsInProgram(getEntity(), 0, (cl_kernel[])null, pCount), previousAttempts++)) {} + + int count = pCount.getValue(); + cl_kernel[] kerns = new cl_kernel[count]; + previousAttempts = 0; + while (failedForLackOfMemory(CL.clCreateKernelsInProgram(getEntity(), count, kerns, pCount), previousAttempts++)) {} + + CLKernel[] kernels = new CLKernel[count]; + for (int i = 0; i < count; i++) + kernels[i] = new CLKernel(this, null, kerns[i]); + + return kernels; + } + + /** + * Find a kernel by its functionName, and optionally bind some arguments to it. + */ + public CLKernel createKernel(String name, Object... args) throws CLBuildException { + synchronized (this) { + if (!built) + build(); + } + IntBuffer errBuff = NIOUtils.directInts(1, ByteOrder.nativeOrder()); + cl_kernel kernel; + int previousAttempts = 0; + do { + kernel = CL.clCreateKernel(getEntity(), name, errBuff); + } while (failedForLackOfMemory(errBuff.get(0), previousAttempts++)); + + CLKernel kn = new CLKernel(this, name, kernel); + kn.setArgs(args); + return kn; + } + + +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLQueue.java b/Core/src/main/java/com/nativelibs4java/opencl/CLQueue.java new file mode 100644 index 00000000..04285dfa --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLQueue.java @@ -0,0 +1,194 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_FALSE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_QUEUE_PROPERTIES; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_TRUE; + +import java.util.EnumSet; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_command_queue; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_event; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.LongByReference; + +/** + * OpenCL command queue.
+ * OpenCL objects such as memory, program and kernel objects are created using a context.
+ * Operations on these objects are performed using a command-queue.
+ * The command-queue can be used to queue a set of operations (referred to as commands) in order.
+ * Having multiple command-queues allows applications to queue multiple independent commands without requiring synchronization.
+ * Note that this should work as long as these objects are not being shared.
+ * Sharing of objects across multiple command-queues will require the application to perform appropriate synchronization.
+ *
+ * A queue is bound to a single device. + * @see CLDevice#createQueue(com.nativelibs4java.opencl.CLContext, com.nativelibs4java.opencl.CLDevice.QueueProperties[]) + * @see CLDevice#createOutOfOrderQueue(com.nativelibs4java.opencl.CLContext) + * @see CLDevice#createProfilingQueue(com.nativelibs4java.opencl.CLContext) + * @see CLContext#createDefaultQueue(com.nativelibs4java.opencl.CLDevice.QueueProperties[]) + * @see CLContext#createDefaultOutOfOrderQueue() + * @see CLContext#createDefaultProfilingQueue() + * @author Olivier Chafik + * + */ +public class CLQueue extends CLAbstractEntity { + + private CLInfoGetter infos = new CLInfoGetter() { + @Override + protected int getInfo(cl_command_queue entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetCommandQueueInfo(getEntity(), infoTypeEnum, size, out, sizeOut); + } + }; + + final CLContext context; + final CLDevice device; + + CLQueue(CLContext context, cl_command_queue entity, CLDevice device) { + super(entity); + this.context = context; + this.device = device; + } + + public CLContext getContext() { + return context; + } + public CLDevice getDevice() { + return device; + } + + volatile Boolean outOfOrder; + public synchronized boolean isOutOfOrder() { + if (outOfOrder == null) + outOfOrder = getProperties().contains(CLDevice.QueueProperties.OutOfOrderExecModeEnable); + return outOfOrder; + } + + @InfoName("CL_QUEUE_PROPERTIES") + public EnumSet getProperties() { + return CLDevice.QueueProperties.getEnumSet(infos.getIntOrLong(getEntity(), CL_QUEUE_PROPERTIES)); + } + + @SuppressWarnings("deprecation") + public void setProperty(CLDevice.QueueProperties property, boolean enabled) { + error(CL.clSetCommandQueueProperty(getEntity(), property.value(), enabled ? CL_TRUE : CL_FALSE, (LongByReference)null)); + } + + + @Override + protected void clear() { + error(CL.clReleaseCommandQueue(getEntity())); + } + + /** + * Blocks until all previously queued OpenCL commands in this queue are issued to the associated device and have completed.
+ * finish() does not return until all queued commands in this queue have been processed and completed.
+ * finish() is also a synchronization point. + */ + public void finish() { + error(CL.clFinish(getEntity())); + } + + /** + * Issues all previously queued OpenCL commands in this queue to the device associated with this queue.
+ * flush() only guarantees that all queued commands in this queue get issued to the appropriate device.
+ * There is no guarantee that they will be complete after flush() returns. + */ + public void flush() { + error(CL.clFlush(getEntity())); + } + + /** + * Enqueues a wait for a specific event or a list of events to complete before any future commands queued in the this queue are executed. + */ + public void enqueueWaitForEvents(CLEvent... events) { + cl_event[] evts = CLEvent.to_cl_event_array(events); + error(CL.clEnqueueWaitForEvents(getEntity(), evts == null ? 0 : evts.length, evts)); + } + + /** + * Enqueue a barrier operation.
+ * The enqueueBarrier() command ensures that all queued commands in command_queue have finished execution before the next batch of commands can begin execution.
+ * enqueueBarrier() is a synchronization point. + */ + public void enqueueBarrier() { + error(CL.clEnqueueBarrier(getEntity())); + } + + /** + * Enqueue a marker command to command_queue.
+ * The marker command returns an event which can be used by to queue a wait on this marker event i.e. wait for all commands queued before the marker command to complete. + * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete. + */ + public CLEvent enqueueMarker() { + cl_event[] eventOut = new cl_event[1]; + error(CL.clEnqueueMarker(getEntity(), eventOut)); + return CLEvent.createEvent(this, eventOut); + } + + /** + * Used to acquire OpenCL memory objects that have been created from OpenGL objects.
+ * These objects need to be acquired before they can be used by any OpenCL commands queued to a command-queue.
+ * The OpenGL objects are acquired by the OpenCL context associated with this queue and can therefore be used by all command-queues associated with the OpenCL context. + * @param objects CL memory objects that correspond to GL objects. + * @param eventsToWaitFor Events that need to complete before this particular command can be executed. + * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete. + */ + public CLEvent enqueueAcquireGLObjects(CLMem[] objects, CLEvent... eventsToWaitFor) { + cl_event[] eventOut = CLEvent.new_event_out(eventsToWaitFor); + cl_mem[] mems = new cl_mem[objects.length]; + for (int i = 0; i < objects.length; i++) + mems[i] = objects[i].getEntity(); + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + error(CL.clEnqueueAcquireGLObjects(getEntity(), mems.length, mems, evts == null ? 0 : evts.length, evts, eventOut)); + return CLEvent.createEvent(this, eventOut); + } + + /** + * Used to release OpenCL memory objects that have been created from OpenGL objects.
+ * These objects need to be released before they can be used by OpenGL.
+ * The OpenGL objects are released by the OpenCL context associated with this queue. + * @param objects CL memory objects that correpond to GL objects. + * @param eventsToWaitFor Events that need to complete before this particular command can be executed. + * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete. + */ + public CLEvent enqueueReleaseGLObjects(CLMem[] objects, CLEvent... eventsToWaitFor) { + cl_event[] eventOut = CLEvent.new_event_out(eventsToWaitFor); + cl_mem[] mems = getEntities(objects, new cl_mem[objects.length]); + cl_event[] evts = CLEvent.to_cl_event_array(eventsToWaitFor); + error(CL.clEnqueueReleaseGLObjects(getEntity(), mems.length, mems, evts == null ? 0 : evts.length, evts, eventOut)); + return CLEvent.createEvent(this, eventOut); + } +} \ No newline at end of file diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLSampler.java b/Core/src/main/java/com/nativelibs4java/opencl/CLSampler.java new file mode 100644 index 00000000..22a65b96 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLSampler.java @@ -0,0 +1,135 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_ADDRESS_CLAMP; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_ADDRESS_CLAMP_TO_EDGE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_ADDRESS_NONE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_ADDRESS_REPEAT; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_FILTER_LINEAR; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_FILTER_NEAREST; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_SAMPLER_ADDRESSING_MODE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_SAMPLER_FILTER_MODE; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.CL_SAMPLER_NORMALIZED_COORDS; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_sampler; +import com.nativelibs4java.util.EnumValue; +import com.nativelibs4java.util.EnumValues; +import com.nativelibs4java.util.ValuedEnum; +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.sun.jna.Pointer; + +/** + * OpenCL sampler object.
+ * A sampler object describes how to sample an image when the image is read in the kernel.
+ * The built-in functions to read from an image in a kernel take a sampler as an argument.
+ * The sampler arguments to the image read function can be sampler objects created using OpenCL functions and passed as argument values to the kernel or can be samplers declared inside a kernel. + *
+ * @see CLContext#createSampler(boolean, com.nativelibs4java.opencl.CLSampler.AddressingMode, com.nativelibs4java.opencl.CLSampler.FilterMode) + * @author Olivier Chafik + */ +public class CLSampler extends CLAbstractEntity { + private static CLInfoGetter infos = new CLInfoGetter() { + @Override + protected int getInfo(cl_sampler entity, int infoTypeEnum, NativeSize size, Pointer out, NativeSizeByReference sizeOut) { + return CL.clGetSamplerInfo(entity, infoTypeEnum, size, out, sizeOut); + } + }; + + CLSampler(cl_sampler entity) { + super(entity); + } + + @Override + protected void clear() { + error(CL.clReleaseSampler(getEntity())); + } + + /** + * Values for CL_SAMPLER_ADDRESSING_MODE
+ * How out-of-range image coordinates are handled when reading from an image + */ + public enum AddressingMode implements ValuedEnum { + Repeat(CL_ADDRESS_REPEAT), + ClampToEdge(CL_ADDRESS_CLAMP_TO_EDGE), + Clamp(CL_ADDRESS_CLAMP), + None(CL_ADDRESS_NONE); + + AddressingMode(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static AddressingMode getEnum(long v) { return EnumValues.getEnum(v, AddressingMode.class); } + } + + /** + * Return the value specified by addressing_mode argument to CLContext.createSampler. + */ + @InfoName("CL_SAMPLER_ADDRESSING_MODE") + public AddressingMode getAddressingMode() { + return AddressingMode.getEnum(infos.getInt(getEntity(), CL_SAMPLER_ADDRESSING_MODE)); + } + + /** + * Values for CL_SAMPLER_FILTER_MODE
+ * Type of filter that must be applied when reading an image + */ + public enum FilterMode implements ValuedEnum { + Nearest(CL_FILTER_NEAREST), + Linear(CL_FILTER_LINEAR); + + FilterMode(long value) { this.value = value; } + long value; + @Override + public long value() { return value; } + public static FilterMode getEnum(int v) { return EnumValues.getEnum(v, FilterMode.class); } + } + /** + * Return the value specified by filter_mode argument to CLContext.createSampler. + */ + @InfoName("CL_SAMPLER_FILTER_MODE") + public FilterMode getFilterMode() { + return FilterMode.getEnum(infos.getInt(getEntity(), CL_SAMPLER_FILTER_MODE)); + } + + /** + * Return the value specified by normalized_coords argument to CLContext.createSampler. + */ + @InfoName("CL_SAMPLER_NORMALIZED_COORDS") + public boolean getNormalizedCoords() { + return infos.getBool(getEntity(), CL_SAMPLER_NORMALIZED_COORDS); + } + + + +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLShortBuffer.java b/Core/src/main/java/com/nativelibs4java/opencl/CLShortBuffer.java new file mode 100644 index 00000000..5b3cccb9 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLShortBuffer.java @@ -0,0 +1,49 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import java.nio.*; + +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_mem; + +/** + * OpenCL Memory Buffer Object with Short values.
+ * @see CLContext#createShortBuffer(com.nativelibs4java.opencl.CLMem.Usage, long) + * @see CLContext#createShortBuffer(com.nativelibs4java.opencl.CLMem.Usage, java.nio.ShortBuffer, boolean) + * @author Olivier Chafik + * @deprecated Use {@link CLBuffer}<{@link Short}> + */ +@Deprecated +public class CLShortBuffer extends CLBuffer { + CLShortBuffer(CLContext context, long byteCount, cl_mem entity, Buffer buffer) { + super(context, byteCount, entity, buffer, 2, ShortBuffer.class); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/CLUserEvent.java b/Core/src/main/java/com/nativelibs4java/opencl/CLUserEvent.java new file mode 100644 index 00000000..58ec05fe --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/CLUserEvent.java @@ -0,0 +1,61 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + + +import static com.nativelibs4java.opencl.JavaCL.CL; +import static com.nativelibs4java.opencl.CLException.error; +import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_event; + +public class CLUserEvent extends CLEvent { + CLUserEvent(cl_event evt) { + super(evt); + } + CLUserEvent() { + super(); + } + /** + * Sets the execution status of a this event object. + * NOTE: Enqueued commands that specify user events in the event_wait_list argument of clEnqueue*** commands must ensure that the status of these user events being waited on are set using clSetUserEventStatus before any OpenCL APIs that release OpenCL objects except for event objects are called; otherwise the behavior is undefined. More details in the OpenCL specifications at section 5.9. + * @param executionStatus specifies the new execution status to be set and can be CL_COMPLETE or a negative integer value to indicate an error. A negative integer value causes all enqueued commands that wait on this user event to be terminated. setStatus can only be called once to change the execution status of event. + */ + public void setStatus(int executionStatus) { + error(CL.clSetUserEventStatus(getEntity(), executionStatus)); + } + + /** + * Calls setStatus(CL_COMPLETE) + */ + public void setComplete() { + setStatus(CL_COMPLETE); + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/ImageIOUtils.java b/Core/src/main/java/com/nativelibs4java/opencl/ImageIOUtils.java new file mode 100644 index 00000000..1926e0a2 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/ImageIOUtils.java @@ -0,0 +1,474 @@ +package com.nativelibs4java.opencl; + +import com.nativelibs4java.opencl.CLImageFormat.ChannelOrder; +import com.nativelibs4java.opencl.CLImageFormat.ChannelDataType; +import com.nativelibs4java.util.NIOUtils; +import java.awt.Image; +import java.awt.image.*; +import java.nio.*; +import static com.nativelibs4java.opencl.ImageIOUtils.ImageInfo.*; + +/** + * No apparent correspondance with any OpenCL image type for the following BufferedImage types : + * TYPE_3BYTE_BGR + * TYPE_4BYTE_ABGR (support only argb or bgra : need to see if endian-magic can help...) + * TYPE_4BYTE_ABGR_PRE (no support for pre-multiplied channels) + * TYPE_BYTE_BINARY + * TYPE_BYTE_INDEXED + * TYPE_CUSTOM + * TYPE_INT_ARGB_PRE (no support for pre-multiplied channels) + * TYPE_INT_BGR + * TYPE_INT_RGB (no support for UnsignedInt8 channel data type) + * TYPE_USHORT_555_RGB + * TYPE_USHORT_565_RGB + */ +class ImageIOUtils { + + public static class ImageInfo { + public final int bufferedImageType; + public final CLImageFormat clImageFormat; + //public final int width, height; + public final ImageDataGetter dataGetter; + public final ImageDataSetter dataSetter; + public final Class bufferClass; + public final int channelCount; + public final int pixelByteSize; + public ImageInfo( + int bufferedImageType, + CLImageFormat clImageFormat, + ImageDataGetter dataGetter, + ImageDataSetter dataSetter, + Class bufferClass, + int channelCount, + int pixelByteSize) + { + this.bufferedImageType = bufferedImageType; + this.clImageFormat = clImageFormat; + this.dataGetter = dataGetter; + this.dataSetter = dataSetter; + this.bufferClass = bufferClass; + this.channelCount = channelCount; + this.pixelByteSize = pixelByteSize; + } + + public interface ImageDataGetter { + Buffer getData(I image, Buffer optionalExistingOutput, boolean directBuffer, boolean allowDeoptimizingDirectRead, ByteOrder byteOrder); + } + public interface ImageDataSetter { + void setData(I image, Buffer data, boolean allowDeoptimizingDirectWrite); + } + } + + public static ImageInfo getGenericImageInfo() { + return new ImageInfo( + 0, + CLImageFormat.INT_ARGB_FORMAT, + new ImageDataGetter() { + public Buffer getData(Image image, Buffer optionalExistingOutput, boolean directBuffer, boolean allowDeoptimizingDirectRead, ByteOrder byteOrder) { + int[] intData = null; + int width = image.getWidth(null), height = image.getHeight(null); + PixelGrabber grabber = new PixelGrabber(image, 0, 0, width, height, true); + try { + grabber.grabPixels(); + intData = (int[])grabber.getPixels(); + } catch (InterruptedException ex) { + throw new RuntimeException("Pixel read operation was interrupted", ex); + } + IntBuffer output = IntBuffer.wrap(intData); + if (directBuffer) + return NIOUtils.directCopy(output, byteOrder); + else + return output; + } + }, + new ImageDataSetter() { + public void setData(Image image, Buffer data, boolean allowDeoptimizingDirectWrite) { + if (!(image instanceof BufferedImage)) + throw new UnsupportedOperationException("Image must be a BufferedImage"); + + BufferedImage bufferedImage = (BufferedImage)image; + int width = bufferedImage.getWidth(), height = bufferedImage.getHeight(); + WritableRaster raster = checkWritableRaster(bufferedImage); + + IntBuffer input = checkBuffer(data, IntBuffer.class); + int[] intData = input.array(); + if (intData == null) { + intData = new int[width * height]; + input.get(intData); + } + raster.setPixels(0, 0, width, height, intData); + } + }, + IntBuffer.class, + 1, + 4 + ); + } + + static void checkSinglePixelPackedSampleModel(Raster raster) { + if (raster.getNumDataElements() != 1) + throw new IllegalArgumentException("Raster has " + raster.getNumBands() + " data elements, should have only 1 !"); + + //SampleModel sampleModel = raster.getSampleModel(); + //if (!(sampleModel instanceof SinglePixelPackedSampleModel)) + // throw new IllegalArgumentException("Expected SinglePixelPackedSampleModel, got " + sampleModel.getClass().getName()); + + //return (SinglePixelPackedSampleModel)sampleModel; + } + static DB checkDataBuffer(Raster raster, Class dbType) { + DataBuffer dataBuffer = raster.getDataBuffer(); + if (!dbType.isInstance(dataBuffer)) + throw new IllegalArgumentException("Expected " + dbType.getName() + ", got " + (dataBuffer == null ? null : dataBuffer.getClass().getName())); + + return (DB)dataBuffer; + } + static B checkBuffer(Buffer buffer, Class bType) { + if (!bType.isInstance(buffer)) + throw new IllegalArgumentException("Expected " + bType.getName() + ", got " + (buffer == null ? null : buffer.getClass().getName())); + + return (B)buffer; + } + static WritableRaster checkWritableRaster(BufferedImage image) { + Raster raster = image.getRaster(); + if (!(raster instanceof WritableRaster)) + throw new UnsupportedOperationException("Image data is not writable"); + + return (WritableRaster)raster; + } + public static ImageInfo getShortGrayImageInfo() { + return new ImageInfo( + BufferedImage.TYPE_USHORT_GRAY, + new CLImageFormat(CLImageFormat.ChannelOrder.LUMINANCE, CLImageFormat.ChannelDataType.UNormInt16), + new ImageDataGetter() { + public Buffer getData(BufferedImage image, Buffer optionalExistingOutput, boolean directBuffer, boolean allowDeoptimizingDirectRead, ByteOrder byteOrder) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + + short[] existingArray = getIndirectArray(optionalExistingOutput, width * height, short[].class); + short[] array; + ShortBuffer output = null; + if (!allowDeoptimizingDirectRead) + array = (short[])raster.getDataElements(0, 0, width, height, existingArray); + else { + array = checkDataBuffer(raster, DataBufferShort.class).getData(); + if (optionalExistingOutput instanceof ShortBuffer) { + output = (ShortBuffer)optionalExistingOutput; + if (output != null && output.capacity() == width * height) { + if (!output.isDirect()) + System.arraycopy(array, 0, output.array(), 0, width * height); + else { + output.duplicate().put(array); + } + } + } + } + if (output == null) + output = ShortBuffer.wrap(array); + return directBuffer && !output.isDirect() ? NIOUtils.directCopy(output, byteOrder) : output; + } + }, + new ImageDataSetter() { + public void setData(BufferedImage image, Buffer inputBuffer, boolean allowDeoptimizingDirectWrite) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + ShortBuffer input = checkBuffer(inputBuffer, ShortBuffer.class); + short[] inputArray = input.isDirect() ? null : input.array(); + if (allowDeoptimizingDirectWrite) { + if (input.isDirect()) { + short[] outputArray = checkDataBuffer(raster, DataBufferShort.class).getData(); + ShortBuffer.wrap(outputArray).put(input.duplicate()); + return; + } + } + if (inputArray == null) { + inputArray = new short[width * height]; + input.duplicate().get(inputArray); + } + raster.setDataElements(0, 0, width, height, inputArray); + } + }, + ShortBuffer.class, + 1, + 2 + ); + } + + /** + * Image stored in TYPE_USHORT_GRAY BufferedImages but in ChannelOrder.RGBA/BGRA + ChannelDataType.short + */ + public static ImageInfo getARGBShortGrayImageInfo(CLImageFormat format) { + return new ImageInfo( + BufferedImage.TYPE_USHORT_GRAY, + format, + new ImageDataGetter() { + public Buffer getData(BufferedImage image, Buffer optionalExistingOutput, boolean directBuffer, boolean allowDeoptimizingDirectRead, ByteOrder byteOrder) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + + int length = width * height; + short[] existingArray = getIndirectArray(optionalExistingOutput, length, short[].class); + short[] array = (short[])raster.getDataElements(0, 0, width, height, existingArray); + + ShortBuffer output = null; + if (optionalExistingOutput instanceof ShortBuffer) { + output = (ShortBuffer)optionalExistingOutput; + if (output.capacity() != length * 4) + output = null; + } + if (output == null) + output = NIOUtils.directShorts(length * 4, byteOrder); + + for (int i = 0; i < length; i++) { + int offset = i * 4; + short value = array[i]; + output.put(offset, value); + output.put(offset + 1, value); + output.put(offset + 2, value); + output.put(offset + 3, (short)0xffff); + } + + return output; + } + }, + new ImageDataSetter() { + public void setData(BufferedImage image, Buffer inputBuffer, boolean allowDeoptimizingDirectWrite) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + ShortBuffer input = checkBuffer(inputBuffer, ShortBuffer.class); + int length = width * height; + short[] data = new short[length]; + short[] four = new short[4]; + for (int i = 0; i < length; i++) { + int offset = i * 4; + int a = input.get(offset); + int b = input.get(offset + 1); + int c = input.get(offset + 2); + int alpha = input.get(offset + 3); // TODO multiply by ALPHA ??? + data[i] = (short)((a + b + c) / 3); + } + raster.setDataElements(0, 0, width, height, data); + } + }, + ShortBuffer.class, + 4, + 4 * 2 + ); + } + + public static ImageInfo getByteGrayImageInfo() { + return new ImageInfo( + BufferedImage.TYPE_BYTE_GRAY, + new CLImageFormat(CLImageFormat.ChannelOrder.LUMINANCE, CLImageFormat.ChannelDataType.SignedInt8), + new ImageDataGetter() { + public Buffer getData(BufferedImage image, Buffer optionalExistingOutput, boolean directBuffer, boolean allowDeoptimizingDirectRead, ByteOrder byteOrder) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + + byte[] existingArray = getIndirectArray(optionalExistingOutput, width * height, byte[].class); + byte[] array; + ByteBuffer output = null; + if (!allowDeoptimizingDirectRead) + array = (byte[])raster.getDataElements(0, 0, width, height, existingArray); + else { + array = checkDataBuffer(raster, DataBufferByte.class).getData(); + if (optionalExistingOutput instanceof ByteBuffer) { + output = (ByteBuffer)optionalExistingOutput; + if (output != null && output.capacity() == width * height) { + if (!output.isDirect()) + System.arraycopy(array, 0, output.array(), 0, width * height); + else { + output.duplicate().put(array); + } + } + } + } + if (output == null) + output = ByteBuffer.wrap(array); + return directBuffer && !output.isDirect() ? NIOUtils.directCopy(output, byteOrder) : output; + } + }, + new ImageDataSetter() { + public void setData(BufferedImage image, Buffer inputBuffer, boolean allowDeoptimizingDirectWrite) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + ByteBuffer input = checkBuffer(inputBuffer, ByteBuffer.class); + byte[] inputArray = input.isDirect() ? null : input.array(); + if (allowDeoptimizingDirectWrite) { + if (input.isDirect()) { + byte[] outputArray = checkDataBuffer(raster, DataBufferByte.class).getData(); + ByteBuffer.wrap(outputArray).put(input.duplicate()); + return; + } + } + if (inputArray == null) { + inputArray = new byte[width * height]; + input.duplicate().get(inputArray); + } + raster.setDataElements(0, 0, width, height, inputArray); + } + }, + ByteBuffer.class, + 1, + 1 + ); + } + static A getIndirectArray(Buffer buffer, int length, Class arrayClass) { + if (buffer instanceof IntBuffer && arrayClass == int[].class) + return (A)((IntBuffer)buffer).array(); + if (buffer instanceof ShortBuffer && arrayClass == short[].class) + return (A)((ShortBuffer)buffer).array(); + if (buffer instanceof ByteBuffer && arrayClass == byte[].class) + return (A)((ByteBuffer)buffer).array(); + if (buffer instanceof FloatBuffer && arrayClass == float[].class) + return (A)((FloatBuffer)buffer).array(); + if (buffer instanceof LongBuffer && arrayClass == long[].class) + return (A)((LongBuffer)buffer).array(); + if (buffer instanceof DoubleBuffer && arrayClass == double[].class) + return (A)((DoubleBuffer)buffer).array(); + if (buffer instanceof CharBuffer && arrayClass == char[].class) + return (A)((CharBuffer)buffer).array(); + return null; + } + public static ImageInfo getIntARGBImageInfo() { + return new ImageInfo( + BufferedImage.TYPE_INT_ARGB, + CLImageFormat.INT_ARGB_FORMAT, + new ImageDataGetter() { + public Buffer getData(BufferedImage image, Buffer optionalExistingOutput, boolean directBuffer, boolean allowDeoptimizingDirectRead, ByteOrder byteOrder) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + int[] existingArray = getIndirectArray(optionalExistingOutput, width * height, int[].class); + int[] array; + IntBuffer output = null; + if (!allowDeoptimizingDirectRead) + array = (int[])raster.getDataElements(0, 0, width, height, existingArray); + else { + array = checkDataBuffer(raster, DataBufferInt.class).getData(); + if (optionalExistingOutput instanceof IntBuffer) { + output = (IntBuffer)optionalExistingOutput; + if (output != null && output.capacity() == width * height) { + if (output.array() != null) + System.arraycopy(array, 0, output.array(), 0, width * height); + else { + output.duplicate().put(array); + } + } + } + } + if (output == null) + output = IntBuffer.wrap(array); + return directBuffer && !output.isDirect() ? NIOUtils.directCopy(output, byteOrder) : output; + } + }, + new ImageDataSetter() { + public void setData(BufferedImage image, Buffer inputBuffer, boolean allowDeoptimizingDirectWrite) { + int width = image.getWidth(), height = image.getHeight(); + WritableRaster raster = checkWritableRaster(image); + checkSinglePixelPackedSampleModel(raster); + IntBuffer input = checkBuffer(inputBuffer, IntBuffer.class); + int[] inputArray = input.isDirect() ? null : input.array(); + if (allowDeoptimizingDirectWrite) { + if (input.isDirect()) { + int[] outputArray = checkDataBuffer(raster, DataBufferInt.class).getData(); + IntBuffer.wrap(outputArray).put(input.duplicate()); + return; + } + } + if (inputArray == null) { + inputArray = new int[width * height]; + input.duplicate().get(inputArray); + } + raster.setDataElements(0, 0, width, height, inputArray); + } + }, + IntBuffer.class, + 1, + 4 + ); + } + + public static ImageInfo getImageInfo(Image image) { + if (image instanceof BufferedImage) + return getBufferedImageInfo(((BufferedImage)image).getType()); + return getGenericImageInfo(); + } + public static ImageInfo getBufferedImageInfo(int bufferedImageType) { + switch (bufferedImageType) { + case BufferedImage.TYPE_INT_ARGB: + return getIntARGBImageInfo(); + case BufferedImage.TYPE_BYTE_GRAY: + return getByteGrayImageInfo(); + case BufferedImage.TYPE_USHORT_GRAY: + return getShortGrayImageInfo(); + default: + return (ImageInfo)getGenericImageInfo(); + } + } + public static ImageInfo getBufferedImageInfo(CLImageFormat imageFormat) { + if (imageFormat == null || imageFormat.getChannelOrder() == null || imageFormat.getChannelDataType() == null) + return null; + + switch (imageFormat.getChannelOrder()) { + case BGRA: + case RGBA: + switch (imageFormat.getChannelDataType()) { + case UNormInt16: + case UnsignedInt16: + case SignedInt16: + return getARGBShortGrayImageInfo(imageFormat); + } + } + return getBufferedImageInfo(getBufferedImageType(imageFormat)); + } + static int getBufferedImageType(CLImageFormat imageFormat) { + if (imageFormat == null || imageFormat.getChannelOrder() == null || imageFormat.getChannelDataType() == null) + return 0; + + switch (imageFormat.getChannelOrder()) { + case INTENSITY: + case LUMINANCE: + switch (imageFormat.getChannelDataType()) { + case UNormInt8: + case UnsignedInt8: + case SignedInt8: + return BufferedImage.TYPE_BYTE_GRAY; + case UnsignedInt16: + case UNormInt16: + case SignedInt16: + return BufferedImage.TYPE_USHORT_GRAY; + default: + return 0; + } + case ARGB: + case BGRA: + case RGBA: + switch (imageFormat.getChannelDataType()) { + case UNormInt8: + case UnsignedInt8: + case SignedInt8: + return BufferedImage.TYPE_INT_ARGB; + default: + return 0; + } + case RGB: + switch (imageFormat.getChannelDataType()) { + case UNormInt8: + case UnsignedInt8: + case SignedInt8: + return BufferedImage.TYPE_INT_BGR; + default: + return 0; + } + case RGBx: + default: + return 0; + } + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/InfoName.java b/Core/src/main/java/com/nativelibs4java/opencl/InfoName.java new file mode 100644 index 00000000..98e2c15b --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/InfoName.java @@ -0,0 +1,46 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Tagging annotation to indicate the name of an OpenCL information in the OpenCL specifications. + * @author ochafik + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface InfoName { + String value(); +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/JavaCL.java b/Core/src/main/java/com/nativelibs4java/opencl/JavaCL.java new file mode 100644 index 00000000..39447331 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/JavaCL.java @@ -0,0 +1,244 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.nativelibs4java.opencl; + +import static com.nativelibs4java.opencl.CLException.error; +import com.nativelibs4java.opencl.CLPlatform.DeviceFeature; + +import java.io.File; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.logging.*; + +import com.nativelibs4java.opencl.library.OpenCLLibrary; +import com.nativelibs4java.opencl.library.OpenCLLibrary.cl_platform_id; +import com.sun.jna.Platform; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.Native; + +/** + * Entry point class for the OpenCL4Java Object-oriented wrappers around the OpenCL API.
+ * @author Olivier Chafik + */ +public class JavaCL { + + static final boolean verbose = "true".equals(System.getProperty("javacl.verbose")) || "1".equals(System.getenv("JAVACL_VERBOSE")); + static final int minLogLevel = Level.WARNING.intValue(); + static boolean shouldLog(Level level) { + return verbose || level.intValue() >= minLogLevel; + } + static boolean log(Level level, String message, Throwable ex) { + if (!shouldLog(level)) + return true; + Logger.getLogger(JavaCL.class.getName()).log(level, message, ex); + return true; + } + + static boolean log(Level level, String message) { + log(level, message, null); + return true; + } + + private static int getPlatformIDs(OpenCLLibrary lib, int count, cl_platform_id[] out, IntByReference pCount) { + try { + return lib.clIcdGetPlatformIDsKHR(count, out, pCount); + } catch (Throwable th) { + return lib.clGetPlatformIDs(count, out, pCount); + } + } + public interface OpenCLStdCallLibrary extends com.nativelibs4java.opencl.library.OpenCLLibrary, com.sun.jna.win32.StdCallLibrary { + + } + + static final OpenCLLibrary CL; + static { + Class libClass = Platform.isWindows() && !Platform.is64Bit() ? OpenCLStdCallLibrary.class : OpenCLLibrary.class; + OpenCLLibrary lib = (OpenCLLibrary)Native.loadLibrary("OpenCL", libClass); + //if (Platform.isWindows()) + try { + IntByReference pCount = new IntByReference(); + boolean success = false; + try { + success = getPlatformIDs(lib, 0, null, pCount) == OpenCLLibrary.CL_SUCCESS; + } catch (Throwable th) {} + if (!success) { + OpenCLLibrary atiLib = null; + if (Platform.is64Bit()) + atiLib = (OpenCLLibrary)Native.loadLibrary("atiocl64", libClass); + if (atiLib == null) + atiLib = (OpenCLLibrary)Native.loadLibrary("atiocl32", libClass); + if (atiLib == null) + atiLib = (OpenCLLibrary)Native.loadLibrary("atiocl", libClass); + if (atiLib != null) { + int err = getPlatformIDs(atiLib, 0, null, pCount); + if (err == OpenCLLibrary.CL_SUCCESS) { + System.out.println("[JavaCL] Hacking around ATI's weird driver bugs (using atiocl library instead of OpenCL)"); + lib = atiLib; + } + } + } + } catch (Throwable th) {} + + CL = (OpenCLLibrary)Native.synchronizedLibrary(lib); + } + + /** + * List the OpenCL implementations that contain at least one GPU device. + */ + public static CLPlatform[] listGPUPoweredPlatforms() { + CLPlatform[] platforms = listPlatforms(); + List out = new ArrayList(platforms.length); + for (CLPlatform platform : platforms) { + if (platform.listGPUDevices(true).length > 0) + out.add(platform); + } + return out.toArray(new CLPlatform[out.size()]); + } + /** + * Lists all available OpenCL implementations. + */ + public static CLPlatform[] listPlatforms() { + IntByReference pCount = new IntByReference(); + error(getPlatformIDs(CL, 0, null, pCount)); + + int nPlats = pCount.getValue(); + if (nPlats == 0) + return new CLPlatform[0]; + + cl_platform_id[] ids = new cl_platform_id[nPlats]; + + error(getPlatformIDs(CL, nPlats, ids, null)); + CLPlatform[] platforms = new CLPlatform[nPlats]; + + for (int i = 0; i < nPlats; i++) { + platforms[i] = new CLPlatform(ids[i]); + } + return platforms; + } + + /** + * Creates an OpenCL context formed of the provided devices.
+ * It is generally not a good idea to create a context with more than one device, + * because much data is shared between all the devices in the same context. + * @param devices devices that are to form the new context + * @return new OpenCL context + */ + public static CLContext createContext(Map contextProperties, CLDevice... devices) { + return devices[0].getPlatform().createContext(contextProperties, devices); + } + + /** + * Allows the implementation to release the resources allocated by the OpenCL compiler.
+ * This is a hint from the application and does not guarantee that the compiler will not be used in the future or that the compiler will actually be unloaded by the implementation.
+ * Calls to Program.build() after unloadCompiler() will reload the compiler, if necessary, to build the appropriate program executable. + */ + public static void unloadCompiler() { + error(CL.clUnloadCompiler()); + } + + /** + * Returns the "best" OpenCL device (currently, the one that has the largest amount of compute units).
+ * For more control on what is to be considered a better device, please use the @see JavaCL#getBestDevice(CLPlatform.DeviceFeature[]) variant.
+ * This is currently equivalent to getBestDevice(MaxComputeUnits) + */ + public static CLDevice getBestDevice() { + return getBestDevice(CLPlatform.DeviceFeature.MaxComputeUnits); + } + /** + * Returns the "best" OpenCL device based on the comparison of the provided prioritized device feature.
+ * The returned device does not necessarily exhibit the features listed in preferredFeatures, but it has the best ordered composition of them.
+ * For instance on a system with a GPU and a CPU device, JavaCL.getBestDevice(CPU, MaxComputeUnits) will return the CPU device, but on another system with two GPUs and no CPU device it will return the GPU that has the most compute units. + */ + public static CLDevice getBestDevice(CLPlatform.DeviceFeature... preferredFeatures) { + List devices = new ArrayList(); + for (CLPlatform platform : listPlatforms()) + devices.addAll(Arrays.asList(platform.listAllDevices(true))); + return CLPlatform.getBestDevice(Arrays.asList(preferredFeatures), devices); + } + /** + * Creates an OpenCL context with the "best" device (see @see JavaCL#getBestDevice()) + */ + public static CLContext createBestContext() { + return createBestContext(DeviceFeature.MaxComputeUnits); + } + + /** + * Creates an OpenCL context with the "best" device based on the comparison of the provided prioritized device feature (see @see JavaCL#getBestDevice(CLPlatform.DeviceFeature)) + */ + public static CLContext createBestContext(CLPlatform.DeviceFeature... preferredFeatures) { + CLDevice device = getBestDevice(preferredFeatures); + return device.getPlatform().createContext(null, device); + } + + /** + * Creates an OpenCL context able to share entities with the current OpenGL context. + * @throws RuntimeException if JavaCL is unable to create an OpenGL-shared OpenCL context. + */ + public static CLContext createContextFromCurrentGL() { + RuntimeException first = null; + for (CLPlatform platform : listPlatforms()) { + try { + CLContext ctx = platform.createContextFromCurrentGL(); + if (ctx != null) + return ctx; + } catch (RuntimeException ex) { + if (first == null) + first = ex; + + } + } + throw new RuntimeException("Failed to create an OpenCL context based on the current OpenGL context", first); + } + + static File userJavaCLDir = new File(new File(System.getProperty("user.home")), ".javacl"); + static File userCacheDir = new File(userJavaCLDir, "cache"); + + static synchronized File createTempFile(String prefix, String suffix, String category) { + File dir = new File(userJavaCLDir, category); + dir.mkdirs(); + try { + return File.createTempFile(prefix, suffix, dir); + } catch (IOException ex) { + throw new RuntimeException("Failed to create a temporary directory for category '" + category + "' in " + userJavaCLDir + ": " + ex.getMessage(), ex); + } + } + static synchronized File createTempDirectory(String prefix, String suffix, String category) { + File file = createTempFile(prefix, suffix, category); + file.delete(); + file.mkdir(); + return file; + } +} diff --git a/Core/src/main/java/com/nativelibs4java/opencl/package-info.java b/Core/src/main/java/com/nativelibs4java/opencl/package-info.java new file mode 100644 index 00000000..87f62d69 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/opencl/package-info.java @@ -0,0 +1,35 @@ +/* + * JavaCL - Java API and utilities for OpenCL + * http://javacl.googlecode.com/ + * + * Copyright (c) 2009-2010, Olivier Chafik (http://ochafik.free.fr/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Olivier Chafik nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * Object-oriented wrappers around the OpenCL API, with methods that help creating and managing OpenCL applications.
+ * Also see the low-level bindings : {@link com.nativelibs4java.opencl.library.OpenCL4Java} + */ +package com.nativelibs4java.opencl; diff --git a/Core/src/main/java/com/nativelibs4java/util/JNAUtils.java b/Core/src/main/java/com/nativelibs4java/util/JNAUtils.java new file mode 100644 index 00000000..6e230836 --- /dev/null +++ b/Core/src/main/java/com/nativelibs4java/util/JNAUtils.java @@ -0,0 +1,121 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.nativelibs4java.util; + +import com.ochafik.lang.jnaerator.runtime.NativeSize; +import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; +import com.sun.jna.*; +import com.sun.jna.ptr.*; + +/** + * JNA-related util methods + * @author ochafik + */ +public class JNAUtils { + + /** + * Casts an IntByReference to a NativeLongByReference + */ + public static NativeSizeByReference castToNS(IntByReference local) { + NativeSizeByReference nl = new NativeSizeByReference(); + nl.setPointer(local.getPointer()); + return nl; + } + + /** + * Casts a LongByReference to a NativeSizeByReference + */ + public static NativeSizeByReference castToNS(LongByReference local) { + NativeSizeByReference nl = new NativeSizeByReference(); + nl.setPointer(local.getPointer()); + return nl; + } + + public static NativeSize readNS(Pointer p, long offset) { + if (NativeSize.SIZE == 4) + return new NativeSize(p.getInt(offset)); + else if (NativeSize.SIZE == 8) + return new NativeSize(p.getLong(offset)); + else + throw new RuntimeException("sizeof(size_t) must be either 4 or 8"); + } + public static void writeNS(Pointer p, long offset, long value) { + if (NativeSize.SIZE == 4) + p.setInt(offset, (int)value); + else if (NativeSize.SIZE == 8) + p.setLong(offset, value); + else + throw new RuntimeException("sizeof(size_t) must be either 4 or 8"); + } + + public static NativeSize[] readNSArray(Pointer p, int n) { + NativeSize[] sizes = new NativeSize[n]; + for (int i = 0; i < n; i++) + sizes[i] = readNS(p, i * NativeSize.SIZE); + return sizes; + } + + public static void writeNSArray(Pointer p, long... values) { + if (values == null) + return; + for (int i = 0, n = values.length; i < n; i++) + writeNS(p, i * NativeSize.SIZE, values[i]); + } + + /** + * Converts int/long values array to a Memory object containing contiguous size_t values + * @see NativeSize#SIZE + */ + public static Memory toNSArray(long... values) { + if (values == null) + return null; + Memory mem = new Memory(values.length * NativeSize.SIZE); + writeNSArray(mem, values); + return mem; + } + + /** + * Return a new Size with the provided int value + */ + public static NativeSize[] toNS(int[] ints) { + if (ints == null) + return null; + int n = ints.length; + NativeSize[] nls = new NativeSize[n]; + for (int i = 0; i < n; i++) + nls[i] = toNS(ints[i]); + + return nls; + } + + /** + * Return a new NativeSize array with the provided long values + */ + public static NativeSize[] toNS(long... ints) { + if (ints == null) + return null; + int n = ints.length; + NativeSize[] nls = new NativeSize[n]; + for (int i = 0; i < n; i++) + nls[i] = toNS(ints[i]); + + return nls; + } + + /** + * Return a new NativeSize with the provided int value + */ + public static NativeSize toNS(int i) { + return new NativeSize(i); + } + + /** + * Return a new NativeSize with the provided long value + */ + public static NativeSize toNS(long i) { + return new NativeSize(i); + } +} diff --git a/Core/src/main/javadoc/overview.html b/Core/src/main/javadoc/overview.html new file mode 100644 index 00000000..03e8f3de --- /dev/null +++ b/Core/src/main/javadoc/overview.html @@ -0,0 +1,75 @@ + + + +

+JavaCL is an Object-Oriented API that wraps the OpenCL API.
+It makes it easy to do cross-platform GPGPU with Java. +

+ +

+Core classes : +