Started a panama (no jni) based implementation.
authorNot Zed <notzed@gmail.com>
Fri, 24 Jan 2020 02:48:05 +0000 (13:18 +1030)
committerNot Zed <notzed@gmail.com>
Fri, 24 Jan 2020 02:48:05 +0000 (13:18 +1030)
63 files changed:
README
config.make.in
java.make
nbproject/build-impl.xml
nbproject/genfiles.properties
nbproject/project.properties
nbproject/project.xml
src/notzed.zcl/classes/api/Allocator.java [moved from src/notzed.zcl/jni/zcl-init-so.c with 54% similarity]
src/notzed.zcl/classes/api/Callback.java [new file with mode: 0644]
src/notzed.zcl/classes/api/Memory.java [new file with mode: 0644]
src/notzed.zcl/classes/api/Native.java [new file with mode: 0644]
src/notzed.zcl/classes/au/notzed/zcl/CLBuffer.java
src/notzed.zcl/classes/au/notzed/zcl/CLBufferInfo.java
src/notzed.zcl/classes/au/notzed/zcl/CLCommandQueue.java
src/notzed.zcl/classes/au/notzed/zcl/CLContext.java
src/notzed.zcl/classes/au/notzed/zcl/CLContextNotify.java
src/notzed.zcl/classes/au/notzed/zcl/CLDevice.java
src/notzed.zcl/classes/au/notzed/zcl/CLDeviceProperty.java
src/notzed.zcl/classes/au/notzed/zcl/CLEvent.java
src/notzed.zcl/classes/au/notzed/zcl/CLEventList.java
src/notzed.zcl/classes/au/notzed/zcl/CLEventNotify.java
src/notzed.zcl/classes/au/notzed/zcl/CLException.java
src/notzed.zcl/classes/au/notzed/zcl/CLExtendable.java
src/notzed.zcl/classes/au/notzed/zcl/CLExtension.java
src/notzed.zcl/classes/au/notzed/zcl/CLImage.java
src/notzed.zcl/classes/au/notzed/zcl/CLImageDesc.java
src/notzed.zcl/classes/au/notzed/zcl/CLImageFormat.java
src/notzed.zcl/classes/au/notzed/zcl/CLKernel.java
src/notzed.zcl/classes/au/notzed/zcl/CLMemory.java
src/notzed.zcl/classes/au/notzed/zcl/CLNotify.java
src/notzed.zcl/classes/au/notzed/zcl/CLObject.java
src/notzed.zcl/classes/au/notzed/zcl/CLPipe.java
src/notzed.zcl/classes/au/notzed/zcl/CLPlatform.java
src/notzed.zcl/classes/au/notzed/zcl/CLProgram.java
src/notzed.zcl/classes/au/notzed/zcl/CLProperty.java
src/notzed.zcl/classes/au/notzed/zcl/CLRuntimeException.java
src/notzed.zcl/classes/au/notzed/zcl/CLSampler.java
src/notzed.zcl/classes/au/notzed/zcl/khr/GLEvent.java
src/notzed.zcl/classes/au/notzed/zcl/khr/GLSharing.java
src/notzed.zcl/classes/module-info.java
src/notzed.zcl/gen/export-defines [new file with mode: 0755]
src/notzed.zcl/gen/gen.make [new file with mode: 0644]
src/notzed.zcl/gen/generate-api [new file with mode: 0755]
src/notzed.zcl/gen/opencl.pm [new file with mode: 0644]
src/notzed.zcl/gen/opencl.txt [new file with mode: 0644]
src/notzed.zcl/include/CL/cl.h [moved from src/notzed.zcl/jni/include/CL/cl.h with 100% similarity]
src/notzed.zcl/include/CL/cl_d3d10.h [moved from src/notzed.zcl/jni/include/CL/cl_d3d10.h with 100% similarity]
src/notzed.zcl/include/CL/cl_d3d11.h [moved from src/notzed.zcl/jni/include/CL/cl_d3d11.h with 100% similarity]
src/notzed.zcl/include/CL/cl_dx9_media_sharing.h [moved from src/notzed.zcl/jni/include/CL/cl_dx9_media_sharing.h with 100% similarity]
src/notzed.zcl/include/CL/cl_egl.h [moved from src/notzed.zcl/jni/include/CL/cl_egl.h with 100% similarity]
src/notzed.zcl/include/CL/cl_ext.h [moved from src/notzed.zcl/jni/include/CL/cl_ext.h with 100% similarity]
src/notzed.zcl/include/CL/cl_gl.h [moved from src/notzed.zcl/jni/include/CL/cl_gl.h with 100% similarity]
src/notzed.zcl/include/CL/cl_gl_ext.h [moved from src/notzed.zcl/jni/include/CL/cl_gl_ext.h with 100% similarity]
src/notzed.zcl/include/CL/cl_platform.h [moved from src/notzed.zcl/jni/include/CL/cl_platform.h with 100% similarity]
src/notzed.zcl/include/CL/opencl.h [moved from src/notzed.zcl/jni/include/CL/opencl.h with 100% similarity]
src/notzed.zcl/jni/jni.make [deleted file]
src/notzed.zcl/jni/zcl-extension.h [deleted file]
src/notzed.zcl/jni/zcl-generate [deleted file]
src/notzed.zcl/jni/zcl-init-dll.c [deleted file]
src/notzed.zcl/jni/zcl-jni.c [deleted file]
src/notzed.zcl/jni/zcl-jni.def [deleted file]
src/notzed.zcl/jni/zcl-khr-gl-event.c [deleted file]
src/notzed.zcl/jni/zcl-khr-gl-sharing.c [deleted file]

diff --git a/README b/README
index a51ca98..591c71f 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,14 @@
 
+foreign-abi branch note
+-----------------------
+
+This is still work in progress, expect breakage, out of date doco,
+other issues.
+
+Various native support code is in the temporary package api.*,
+eventually to be moved to a new nativez.
+
+
 INTRODUCTION
 ------------
 
index f0186c5..dba9824 100644 (file)
@@ -3,15 +3,12 @@ TARGET ?= linux-amd64
 
 JAVA_HOME ?= /usr/local/jdk-13+33
 
-# See also JAVACFLAGS --module-path
-NATIVEZ_HOME=../nativez/bin/$(TARGET)
-
-JAVAMODPATH = $(NATIVEZ_HOME)/lib
 JAVACFLAGS += -source 13
+JAVACFLAGS += --add-exports jdk.incubator.foreign/jdk.incubator.foreign.unsafe=notzed.zcl
 
-JAVAC ?= javac
-JAR ?= jar
-JMOD ?= jmod
+JAVAC ?= $(JAVA_HOME)/bin/javac
+JAR ?= $(JAVA_HOME)/bin/jar
+JMOD ?= $(JAVA_HOME)/bin/jmod
 
 # Linux options
 linux-amd64_CPPFLAGS = \
index ee876b1..01df66d 100644 (file)
--- a/java.make
+++ b/java.make
@@ -347,4 +347,3 @@ dist:
         --transform=s,^,$(dist_NAME)-$(dist_VERSION)/, \
         config.make java.make Makefile src             \
         $(dist_EXTRA)
-
index 489097b..9cc58e9 100644 (file)
@@ -69,7 +69,43 @@ is divided into following sections:
         <property name="dist.jlink.output" value="${dist.jlink.dir}/${application.title}"/>
     </target>
     <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
-        <property name="platform.java" value="${java.home}/bin/java"/>
+        <j2semodularproject1:property xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" name="platform.home" value="platforms.${platform.active}.home"/>
+        <j2semodularproject1:property xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" name="platform.bootcp" value="platforms.${platform.active}.bootclasspath"/>
+        <j2semodularproject1:property xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" name="platform.compiler" value="platforms.${platform.active}.compile"/>
+        <j2semodularproject1:property xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" name="platform.javac.tmp" value="platforms.${platform.active}.javac"/>
+        <condition property="platform.javac" value="${platform.home}/bin/javac">
+            <equals arg1="${platform.javac.tmp}" arg2="$${platforms.${platform.active}.javac}"/>
+        </condition>
+        <property name="platform.javac" value="${platform.javac.tmp}"/>
+        <j2semodularproject1:property xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" name="platform.java.tmp" value="platforms.${platform.active}.java"/>
+        <condition property="platform.java" value="${platform.home}/bin/java">
+            <equals arg1="${platform.java.tmp}" arg2="$${platforms.${platform.active}.java}"/>
+        </condition>
+        <property name="platform.java" value="${platform.java.tmp}"/>
+        <j2semodularproject1:property xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" name="platform.javadoc.tmp" value="platforms.${platform.active}.javadoc"/>
+        <condition property="platform.javadoc" value="${platform.home}/bin/javadoc">
+            <equals arg1="${platform.javadoc.tmp}" arg2="$${platforms.${platform.active}.javadoc}"/>
+        </condition>
+        <property name="platform.javadoc" value="${platform.javadoc.tmp}"/>
+        <condition property="platform.invalid" value="true">
+            <or>
+                <contains string="${platform.javac}" substring="$${platforms."/>
+                <contains string="${platform.java}" substring="$${platforms."/>
+                <contains string="${platform.javadoc}" substring="$${platforms."/>
+            </or>
+        </condition>
+        <fail unless="platform.home">Must set platform.home</fail>
+        <fail unless="platform.bootcp">Must set platform.bootcp</fail>
+        <fail unless="platform.java">Must set platform.java</fail>
+        <fail unless="platform.javac">Must set platform.javac</fail>
+        <fail if="platform.invalid">
+ The J2SE Platform is not correctly set up.
+ Your active platform is: ${platform.active}, but the corresponding property "platforms.${platform.active}.home" is not found in the project's properties files. 
+ Either open the project in the IDE and setup the Platform with the same name or add it manually.
+ For example like this:
+     ant -Duser.properties.file=&lt;path_to_property_file&gt; jar (where you put the property "platforms.${platform.active}.home" in a .properties file)
+  or ant -Dplatforms.${platform.active}.home=&lt;path_to_JDK_home&gt; jar (where no properties file is used) 
+  </fail>
         <j2semodularproject1:modsource_regexp xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" modsource="${test.src.dir.path}" property="have.tests.test.src.dir.regexp"/>
         <dirset dir="${basedir}/${test.src.dir}" id="have.tests.test.src.dir.set" includes="*/*">
             <filename regex="${have.tests.test.src.dir.regexp}"/>
@@ -94,11 +130,16 @@ is divided into following sections:
         <union id="have.tests.patchset">
             <dirset refid="have.tests.test.src.dir.patchset"/>
         </union>
+        <j2semodularproject1:modsource_regexp xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" modsource="${src.gen2.dir.path}" property="have.sources.src.gen2.dir.regexp"/>
+        <dirset dir="${basedir}/${src.gen2.dir}" id="have.sources.src.gen2.dir.set" includes="*/*">
+            <filename regex="${have.sources.src.gen2.dir.regexp}"/>
+        </dirset>
         <j2semodularproject1:modsource_regexp xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" modsource="${src.dir.path}" property="have.sources.src.dir.regexp"/>
         <dirset dir="${basedir}/${src.dir}" id="have.sources.src.dir.set" includes="*/*">
             <filename regex="${have.sources.src.dir.regexp}"/>
         </dirset>
         <union id="have.sources.set">
+            <dirset refid="have.sources.src.gen2.dir.set"/>
             <dirset refid="have.sources.src.dir.set"/>
         </union>
         <condition property="have.sources">
@@ -106,6 +147,9 @@ is divided into following sections:
                 <resourcecount count="0" when="greater">
                     <union refid="have.sources.set"/>
                 </resourcecount>
+                <resourcecount count="0" when="greater">
+                    <union refid="have.sources.set"/>
+                </resourcecount>
             </or>
         </condition>
         <condition property="main.class.available">
@@ -177,20 +221,6 @@ is divided into following sections:
         <condition else="" property="javac.profile.cmd.line.arg" value="-profile ${javac.profile}">
             <isset property="profile.available"/>
         </condition>
-        <condition else="false" property="jdkBug6558476">
-            <and>
-                <matches pattern="1\.[56]" string="${java.specification.version}"/>
-                <not>
-                    <os family="unix"/>
-                </not>
-            </and>
-        </condition>
-        <condition else="false" property="javac.fork">
-            <or>
-                <istrue value="${jdkBug6558476}"/>
-                <istrue value="${javac.external.vm}"/>
-            </or>
-        </condition>
         <condition property="main.class.check.available">
             <and>
                 <isset property="libs.CopyLibs.classpath"/>
@@ -262,6 +292,7 @@ is divided into following sections:
         <!-- You can override this target in the ../build.xml file. -->
     </target>
     <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+        <fail unless="src.gen2.dir">Must set src.gen2.dir</fail>
         <fail unless="src.dir">Must set src.dir</fail>
         <fail unless="test.src.dir">Must set test.src.dir</fail>
         <fail unless="build.dir">Must set build.dir</fail>
@@ -293,7 +324,7 @@ is divided into following sections:
             <attribute default="${build.modules.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <attribute default="${javac.modulepath}" name="modulepath"/>
-            <attribute default="${src.dir}/*/${src.dir.path}" name="modulesourcepath"/>
+            <attribute default="${src.gen2.dir}/*/${src.gen2.dir.path}:${src.dir}/*/${src.dir.path}" name="modulesourcepath"/>
             <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/>
             <attribute default="${javac.processorpath}" name="processorpath"/>
             <attribute default="${javac.processormodulepath}" name="processormodulepath"/>
@@ -314,7 +345,7 @@ is divided into following sections:
                         </path>
                     </resourcecount>
                 </condition>
-                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" executable="${platform.javac}" fork="yes" includeantruntime="false" includes="@{includes}" source="${javac.source}" target="${javac.target}" tempdir="${java.io.tmpdir}">
                     <classpath>
                         <path path="@{classpath}"/>
                     </classpath>
@@ -346,7 +377,7 @@ is divided into following sections:
     </target>
     <target depends="-init-macrodef-javac" name="-init-macrodef-javac-depend">
         <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-modular-project/1">
-            <attribute default="${src.dir}" name="srcdir"/>
+            <attribute default="${src.gen2.dir}:${src.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <sequential>
@@ -407,7 +438,7 @@ is divided into following sections:
             <sequential>
                 <property location="${build.dir}/empty" name="empty.dir"/>
                 <property name="junit.forkmode" value="perTest"/>
-                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" jvm="${platform.java}" showoutput="true" tempdir="${build.dir}">
                     <syspropertyset>
                         <propertyref prefix="test-sys-prop."/>
                         <mapper from="test-sys-prop.*" to="*" type="glob"/>
@@ -492,7 +523,7 @@ is divided into following sections:
                     </fileset>
                 </union>
                 <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
-                <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="notzed.zcl" testname="TestNG tests" workingDir="${work.dir}">
+                <testng classfilesetref="test.set" failureProperty="tests.failed" jvm="${platform.java}" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="notzed.zcl" testname="TestNG tests" workingDir="${work.dir}">
                     <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
                     <propertyset>
                         <propertyref prefix="test-sys-prop."/>
@@ -723,6 +754,9 @@ is divided into following sections:
                     <classpath>
                         <path path="@{classpath}"/>
                     </classpath>
+                    <bootclasspath>
+                        <path path="${platform.bootcp}"/>
+                    </bootclasspath>
                 </nbjpdastart>
             </sequential>
         </macrodef>
@@ -772,7 +806,7 @@ is divided into following sections:
             <attribute default="jvm" name="jvm"/>
             <element name="customize" optional="true"/>
             <sequential>
-                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true" module="@{modulename}">
+                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true" jvm="${platform.java}" module="@{modulename}">
                     <classpath>
                         <path path="@{classpath}"/>
                     </classpath>
@@ -842,15 +876,6 @@ is divided into following sections:
         <propertyfile file="${built-jar.properties}">
             <entry key="${basedir}" value=""/>
         </propertyfile>
-        <antcall target="-maybe-call-dep">
-            <param name="call.built.properties" value="${built-jar.properties}"/>
-            <param location="${project.notzed_nativez}" name="call.subproject"/>
-            <param location="${project.notzed_nativez}/build.xml" name="call.script"/>
-            <param name="call.target" value="jar"/>
-            <param name="transfer.built-jar.properties" value="${built-jar.properties}"/>
-            <param name="transfer.not.archive.disabled" value="true"/>
-            <param name="transfer.do.jlink" value="false"/>
-        </antcall>
     </target>
     <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
     <target depends="init" name="-check-automatic-build">
@@ -999,10 +1024,16 @@ is divided into following sections:
                 <include name="*"/>
             </dirset>
         </pathconvert>
-        <j2semodularproject1:depend xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" srcdir="${src.dir}:${build.generated.subdirs}"/>
+        <j2semodularproject1:depend xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" srcdir="${src.gen2.dir}:${src.dir}:${build.generated.subdirs}"/>
     </target>
     <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
         <j2semodularproject1:javac xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" gensrcdir="${build.generated.sources.dir}"/>
+        <j2semodularproject1:modsource_regexp xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" filePattern="(.*$)" modsource="${src.gen2.dir.path}" property="src.gen2.dir.path.regexp"/>
+        <echo message="Copying resources from ${src.gen2.dir}"/>
+        <copy todir="${build.modules.dir}">
+            <fileset dir="${src.gen2.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+            <regexpmapper from="${src.gen2.dir.path.regexp}" to="\1/\3"/>
+        </copy>
         <j2semodularproject1:modsource_regexp xmlns:j2semodularproject1="http://www.netbeans.org/ns/j2se-modular-project/1" filePattern="(.*$)" modsource="${src.dir.path}" property="src.dir.path.regexp"/>
         <echo message="Copying resources from ${src.dir}"/>
         <copy todir="${build.modules.dir}">
@@ -1170,8 +1201,8 @@ is divided into following sections:
                 <isset property="main.class.available"/>
             </and>
         </condition>
-        <property name="platform.jlink" value="${jdk.home}/bin/jlink"/>
-        <property name="jlink.systemmodules.internal" value="${jdk.home}/jmods"/>
+        <property name="platform.jlink" value="${platform.home}/bin/jlink"/>
+        <property name="jlink.systemmodules.internal" value="${platform.home}/jmods"/>
         <exec executable="${platform.jlink}">
             <arg value="--module-path"/>
             <arg path="${jlink.systemmodules.internal}:${run.modulepath}:${dist.dir}"/>
@@ -1414,19 +1445,25 @@ is divided into following sections:
                 </not>
             </and>
         </condition>
+        <exec executable="${platform.java}" failonerror="false" outputproperty="platform.version.output">
+            <arg value="-version"/>
+        </exec>
         <condition else="" property="bug5101868workaround" value="*.java">
-            <matches pattern="1\.[56](\..*)?" string="${java.version}"/>
+            <matches multiline="true" pattern="1\.[56](\..*)?" string="${platform.version.output}"/>
         </condition>
         <condition else="" property="javadoc.html5.cmd.line.arg" value="-html5">
             <and>
                 <isset property="javadoc.html5"/>
-                <available file="${jdk.home}${file.separator}lib${file.separator}jrt-fs.jar"/>
+                <available file="${platform.home}${file.separator}lib${file.separator}jrt-fs.jar"/>
             </and>
         </condition>
-        <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+        <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" executable="${platform.javadoc}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
             <classpath>
                 <path path="${javac.classpath}"/>
             </classpath>
+            <fileset dir="${src.gen2.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
+                <filename name="**/*.java"/>
+            </fileset>
             <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
                 <filename name="**/*.java"/>
             </fileset>
@@ -1438,6 +1475,9 @@ is divided into following sections:
             <arg line="${javadoc.html5.cmd.line.arg}"/>
         </javadoc>
         <copy todir="${dist.javadoc.dir}">
+            <fileset dir="${src.gen2.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
             <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
                 <filename name="**/doc-files/**"/>
             </fileset>
@@ -1695,15 +1735,6 @@ is divided into following sections:
         <propertyfile file="${built-clean.properties}">
             <entry key="${basedir}" value=""/>
         </propertyfile>
-        <antcall target="-maybe-call-dep">
-            <param name="call.built.properties" value="${built-clean.properties}"/>
-            <param location="${project.notzed_nativez}" name="call.subproject"/>
-            <param location="${project.notzed_nativez}/build.xml" name="call.script"/>
-            <param name="call.target" value="clean"/>
-            <param name="transfer.built-clean.properties" value="${built-clean.properties}"/>
-            <param name="transfer.not.archive.disabled" value="true"/>
-            <param name="transfer.do.jlink" value="false"/>
-        </antcall>
     </target>
     <target depends="init" name="-do-clean">
         <delete dir="${build.dir}"/>
index c2d597c..29eae41 100644 (file)
@@ -3,6 +3,6 @@ build.xml.script.CRC32=b55362bc
 build.xml.stylesheet.CRC32=32069288@1.6.1
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=e7caf820
-nbproject/build-impl.xml.script.CRC32=2c69bf13
-nbproject/build-impl.xml.stylesheet.CRC32=0f0529df@1.6.1
+nbproject/build-impl.xml.data.CRC32=2c0455af
+nbproject/build-impl.xml.script.CRC32=68c8182d
+nbproject/build-impl.xml.stylesheet.CRC32=0f0529df@1.7
index f1aaa57..20b0bb1 100644 (file)
@@ -40,11 +40,10 @@ includes=**
 jar.compress=false
 javac.classpath=
 # Space-separated list of extra javac options
-javac.compilerargs=-Xlint:unchecked
+javac.compilerargs=-Xlint:unchecked --add-exports jdk.incubator.foreign/jdk.incubator.foreign.unsafe=notzed.zcl
 javac.deprecation=false
 javac.external.vm=false
-javac.modulepath=\
-    ${reference.notzed_nativez.notzed_nativez_jar}
+javac.modulepath=
 javac.processormodulepath=
 javac.processorpath=\
     ${javac.classpath}
@@ -75,9 +74,7 @@ jlink.additionalmodules=
 jlink.additionalparam=
 jlink.launcher=true
 jlink.launcher.name=notzed.zcl
-platform.active=default_platform
-project.notzed_nativez=../nativez
-reference.notzed_nativez.notzed_nativez_jar=${project.notzed_nativez}/dist/notzed.nativez.jar
+platform.active=JDK_15
 run.classpath=
 # Space-separated list of JVM arguments used when running the project.
 # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
@@ -94,5 +91,9 @@ run.test.modulepath=\
 source.encoding=UTF-8
 src.dir=src
 src.dir.path=classes
+src.gen.dir=bin/gen
+src.gen.dir.path=classes
+src.gen2.dir=bin/gen
+src.gen2.dir.path=classes
 test.src.dir=src
 test.src.dir.path=tests
index 15787d7..575ebab 100644 (file)
@@ -4,22 +4,15 @@
     <configuration>
         <data xmlns="http://www.netbeans.org/ns/j2se-modular-project/1">
             <name>notzed.zcl</name>
+            <explicit-platform explicit-source-supported="true"/>
             <source-roots>
+                <root id="src.gen2.dir" pathref="src.gen2.dir.path"/>
                 <root id="src.dir" pathref="src.dir.path"/>
             </source-roots>
             <test-roots>
                 <root id="test.src.dir" pathref="test.src.dir.path"/>
             </test-roots>
         </data>
-        <references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
-            <reference>
-                <foreign-project>notzed_nativez</foreign-project>
-                <artifact-type>jar</artifact-type>
-                <script>build.xml</script>
-                <target>jar</target>
-                <clean-target>clean</clean-target>
-                <id>notzed.nativez.jar</id>
-            </reference>
-        </references>
+        <references xmlns="http://www.netbeans.org/ns/ant-project-references/1"/>
     </configuration>
 </project>
similarity index 54%
rename from src/notzed.zcl/jni/zcl-init-so.c
rename to src/notzed.zcl/classes/api/Allocator.java
index 8465a4a..87f96f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Michael Zucchi
+ * Copyright (C) 2020 Michael Zucchi
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/*
-  shared library init
- */
-
-#include <CL/cl.h>
-#include <dlfcn.h>
-#include <jni.h>
-
-#include "zcl-extension.h"
-
-#define ZCL_DL_TABLE 1
-#include "zcl-functions.h"
+package api;
 
-static void *lib_opencl;
+import jdk.incubator.foreign.MemoryAddress;
+import jdk.incubator.foreign.MemorySegment;
 
-int init_dynamic(JNIEnv *env) {
-       lib_opencl = dlopen("libOpenCL.so", RTLD_LAZY|RTLD_GLOBAL);
-
-       if (lib_opencl) {
-               for (int i=0;i<zcl_fn_SIZEOF;i++)
-                       zcl_fp[i] = dlsym(lib_opencl, zcl_fn[i]);
-               return 0;
-       }
-
-       return -1;
+/**
+ * An interface to a 'pool' type allocator.
+ *
+ * That is, one where individual items cannot necessarily be freed.
+ */
+public interface Allocator extends AutoCloseable {
+       @Override
+       public void close();
+
+       /**
+        * allocate memory
+        */
+       public MemoryAddress alloca(long size);
+
+       /**
+          Allocate bounded memory.
+          Whether you can close the segment depends on the implementation.
+       */
+       public MemorySegment allocs(long size);
 }
diff --git a/src/notzed.zcl/classes/api/Callback.java b/src/notzed.zcl/classes/api/Callback.java
new file mode 100644 (file)
index 0000000..936ae55
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 Michael Zucchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+  Not sure on this.
+
+  Something needs to handle gc of callback stubs.
+  This uses Native to do it.
+ */
+
+package api;
+
+import jdk.incubator.foreign.*;
+
+public class Callback<T> extends Native implements AutoCloseable {
+       T func;
+
+       public Callback(MemoryAddress addr, T func) {
+               super(addr);
+
+               this.func = func;
+       }
+
+       /*
+        * A callback that resolve to MemoryAddress.NULL.
+        * This can be released safely any number of times.
+        * This must never be registerd with ref queue.
+        */
+       public static final Callback NULL = new Callback<>(MemoryAddress.NULL, null) {
+                       @Override
+                       public void release() {
+                       }
+                       @Override
+                       public void close() {
+                       }
+               };
+
+       private static void release(MemoryAddress p) {
+               System.err.printf("** release upcall stub %016x\n", Memory.toLong(p));
+               freeUpcallStub(p);
+       }
+
+       @Override
+       public void close() {
+               release();
+       }
+}
diff --git a/src/notzed.zcl/classes/api/Memory.java b/src/notzed.zcl/classes/api/Memory.java
new file mode 100644 (file)
index 0000000..8107d6c
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2020 Michael Zucchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package api;
+
+import jdk.incubator.foreign.*;
+import jdk.incubator.foreign.unsafe.ForeignUnsafe;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+
+/**
+ * A utility library for memory operations including a stack allocator.
+ *
+ * The stack allocator works like this
+ *  try (Memory.Frame f = Memory.frame()) {
+ *    MemoryAddress a = Memory.alloca(size);
+ *  }
+ *  Any memory allocated is freed when the frame is closed.
+ *
+ * Note that unlike C's alloca() the frame scope is not per-function
+ * but application defined.
+ */
+public class Memory {
+
+       private static final ThreadLocal<Stack> stacks = ThreadLocal.withInitial(() -> Native.resolve(malloc(4096), (p) -> new Stack(p, 4096)));
+       private static final ThreadLocal<Allocator> stackAllocators = new ThreadLocal<>();
+
+       /* older idea */
+
+       // eh, this isn't really necessary, it's just a safety check/debug?
+       //private static final ThreadLocal<Frame> frames = new ThreadLocal<>();
+
+       /**
+        * Alloc memory in the current frame.  The size is not enforced.
+        */
+       /*
+       public static MemoryAddress alloca(long size) {
+               if (frames.get() == null)
+                       throw new UnsupportedOperationException("Must have a frame");
+               return stack().alloca(size);
+               }*/
+
+       /**
+        * Allocate a segment in the current frame.  The segment must not be closed.
+        */
+/*
+       public static MemorySegment slicea(long size) {
+               if (frames.get() == null)
+                       throw new UnsupportedOperationException("Must have a frame");
+               return stack().slicea(size);
+       }
+
+       public static Frame frame() {
+               Stack stack = stack();
+               long fp = stack.sp;
+               Frame old = frames.get();
+               Frame gnu = () -> {
+                       frames.set(old);
+                       stack.sp = fp;
+               };
+               frames.set(gnu);
+
+               return gnu;
+       }
+
+       public interface Frame extends AutoCloseable {
+               @Override
+               public void close();
+       }
+*/
+       static class Stack extends Native {
+               final MemorySegment stack;
+               final MemoryAddress base;
+               long sp;
+
+               Stack(MemoryAddress p, long size) {
+                       super(p);
+
+                       stack = ForeignUnsafe.ofNativeUnchecked(addr(), size);
+                       base = stack.baseAddress();
+                       sp = size;
+               }
+
+               private static void release(MemoryAddress p) {
+                       System.err.printf("** release stack " + p);
+                       free(p);
+               }
+
+               public MemoryAddress alloca(long size) {
+                       sp -= (size + 7 ) & ~7;
+                       return base.addOffset(sp);
+               }
+
+               public MemorySegment allocs(long size) {
+                       sp -= (size + 7 ) & ~7;
+                       return stack.asSlice(sp, size);
+               }
+
+               public MemorySegment slicea(long size) {
+                       sp -= (size + 7 ) & ~7;
+                       return stack.asSlice(sp, size);
+               }
+       }
+
+       /*
+         Alternatative version.
+         This allows different allocators to be used for functions that use one.
+         Individual memory cannot be freed.
+        */
+
+       /**
+        * Create a stack allocator.
+        * The stack allocator uses thread-specific backing buffer.
+        * This should only be used for small allocations.
+        */
+       public static Allocator stack() {
+               Stack stack = stacks.get();
+               long fp = stack.sp;
+               Allocator old = stackAllocators.get();
+               Thread me = Thread.currentThread();
+
+               Allocator gnu = new Allocator() {
+                               public void close() {
+                                       stack.sp = fp;
+                                       stackAllocators.set(old);
+                               }
+                               public MemoryAddress alloca(long size) {
+                                       if (stackAllocators.get() != this || me != Thread.currentThread())
+                                               throw new IllegalStateException();
+                                       return stack.alloca(size);
+                               }
+                               public MemorySegment allocs(long size) {
+                                       if (stackAllocators.get() != this || me != Thread.currentThread())
+                                               throw new IllegalStateException();
+                                       return stack.allocs(size);
+                               }
+                       };
+
+               stackAllocators.set(gnu);
+               return gnu;
+       }
+
+
+       static final MethodHandle malloc;
+       static final MethodHandle free;
+
+       static {
+               // So for whatever reason it's been decided that MemorySegment can't be freed normally on another thread
+               SystemABI abi = SystemABI.getInstance();
+               MethodHandles.Lookup lookup = MethodHandles.lookup();
+               LibraryLookup libc = LibraryLookup.ofDefault();
+
+               try {
+                       malloc = abi.downcallHandle(libc.lookup("malloc"),
+                                                   MethodType.methodType(MemoryAddress.class,
+                                                                         long.class),
+                                                   FunctionDescriptor.of(MemoryLayouts.SysV.C_POINTER,
+                                                                         false,
+                                                                         MemoryLayouts.SysV.C_ULONG));
+                       free = abi.downcallHandle(libc.lookup("free"),
+                                                   MethodType.methodType(void.class,
+                                                                         MemoryAddress.class),
+                                                   FunctionDescriptor.ofVoid(false,
+                                                                             MemoryLayouts.SysV.C_POINTER));
+               } catch (NoSuchMethodException x) {
+                       throw new RuntimeException(x);
+               }
+       }
+
+       /**
+        * Create a sized memory segment from a segment allocated with malloc.
+        * Closing this segment has no effect on the original, and the original must be used for that.
+        */
+       public static MemorySegment ofNative(MemoryAddress addr, long size) {
+               return ForeignUnsafe.ofNativeUnchecked(addr, size);
+       }
+
+       /**
+        * Get the physical address.  I mean how is this an "offset"?
+        */
+       public static long toLong(MemoryAddress addr) {
+               return ForeignUnsafe.getUnsafeOffset(addr);
+       }
+
+       /**
+        * Allocate C memory.
+        * This is not usable by java directly, see memsize()
+        */
+       public static MemoryAddress malloc(long size) {
+               try {
+                       MemoryAddress addr = (MemoryAddress)malloc.invokeExact(size);
+
+                       return addr;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       public static void free(MemoryAddress ptr) {
+               try {
+                       free.invokeExact(ptr);
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+}
diff --git a/src/notzed.zcl/classes/api/Native.java b/src/notzed.zcl/classes/api/Native.java
new file mode 100644 (file)
index 0000000..ef599df
--- /dev/null
@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) 2020 Michael Zucchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package api;
+
+import java.io.StringReader;
+import java.lang.invoke.*;
+import java.lang.reflect.Method;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import jdk.incubator.foreign.*;
+import jdk.incubator.foreign.unsafe.ForeignUnsafe;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.System.Logger.Level;
+
+public class Native {
+
+       private final MemoryAddress p;
+
+       private final static boolean dolog = true;
+
+       final static VarHandle byteHandle = MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder());
+       final static VarHandle shortHandle = MemoryHandles.varHandle(short.class, ByteOrder.nativeOrder());
+       final static VarHandle intHandle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());
+       final static VarHandle longHandle = MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder());
+       final static VarHandle floatHandle = MemoryHandles.varHandle(float.class, ByteOrder.nativeOrder());
+       final static VarHandle doubleHandle = MemoryHandles.varHandle(double.class, ByteOrder.nativeOrder());
+       final static VarHandle addrHandle = MemoryHandles.varHandle(MemoryAddress.class, ByteOrder.nativeOrder());
+
+       final static VarHandle byteVHandle = MemoryHandles.withStride(byteHandle, 1);
+       final static VarHandle shortVHandle = MemoryHandles.withStride(shortHandle, 2);
+       final static VarHandle intVHandle = MemoryHandles.withStride(intHandle, 4);
+       final static VarHandle longVHandle = MemoryHandles.withStride(longHandle, 8);
+       final static VarHandle floatVHandle = MemoryHandles.withStride(floatHandle, 4);
+       final static VarHandle doubleVHandle = MemoryHandles.withStride(doubleHandle, 8);
+       final static VarHandle addrVHandle = MemoryHandles.withStride(addrHandle, 8);
+
+       protected Native(MemoryAddress p) {
+               this.p = p;
+       }
+
+       static System.Logger log() {
+               return System.getLogger("notzed.native");
+       }
+
+       public MemoryAddress addr() {
+               return p;
+       }
+
+       public static MemoryAddress addr(Native o) {
+               return o != null ? o.addr() : MemoryAddress.NULL;
+       }
+
+       public static MemoryAddress addr(MemorySegment o) {
+               return o != null ? o.baseAddress() : MemoryAddress.NULL;
+       }
+
+       public static byte getByte(MemoryAddress p) {
+               return (byte)byteHandle.get(p);
+       }
+
+       public static byte getByte(MemoryAddress p, long i) {
+               return (byte)byteVHandle.get(p, i);
+       }
+
+       public static void setByte(MemoryAddress p, byte v) {
+               byteHandle.set(p, v);
+       }
+
+       public static void setByte(MemoryAddress p, int i, byte v) {
+               byteVHandle.set(p, i, v);
+       }
+
+       public static int getInt(MemoryAddress p) {
+               return (int)intHandle.get(p);
+       }
+
+       public static int getInt(MemoryAddress p, long i) {
+               return (int)intVHandle.get(p, i);
+       }
+
+       public static void setInt(MemoryAddress p, int v) {
+               intHandle.set(p, v);
+       }
+
+       public static void setInt(MemoryAddress p, long i, int v) {
+               intVHandle.set(p, i, v);
+       }
+
+       public static short getShort(MemoryAddress p) {
+               return (short)shortHandle.get(p);
+       }
+
+       public static void setShort(MemoryAddress p, short v) {
+               shortHandle.set(p, v);
+       }
+
+       public static void setShort(MemoryAddress p, long i, short v) {
+               shortVHandle.set(p, i, v);
+       }
+
+       public static long getLong(MemoryAddress p) {
+               return (long)longHandle.get(p);
+       }
+
+       public static long getLong(MemoryAddress p, long i) {
+               return (long)longVHandle.get(p, i);
+       }
+
+       public static void setLong(MemoryAddress p, long v) {
+               longHandle.set(p, v);
+       }
+
+       public static void setLong(MemoryAddress p, long i, long v) {
+               longVHandle.set(p, i, v);
+       }
+
+       public static float getFloat(MemoryAddress p) {
+               return (float)floatHandle.get(p);
+       }
+
+       public static float getFloat(MemoryAddress p, long i) {
+               return (float)floatVHandle.get(p, i);
+       }
+
+       public static void setFloat(MemoryAddress p, float v) {
+               floatHandle.set(p, v);
+       }
+
+       public static void setFloat(MemoryAddress p, long i, float v) {
+               floatVHandle.set(p, i, v);
+       }
+
+       public static double getDouble(MemoryAddress p) {
+               return (int)doubleHandle.get(p);
+       }
+
+       public static double getDouble(MemoryAddress p, long i) {
+               return (int)doubleVHandle.get(p, i);
+       }
+
+       public static void setDouble(MemoryAddress p, double v) {
+               doubleHandle.set(p, v);
+       }
+
+       public static void setDouble(MemoryAddress p, long i, double v) {
+               doubleVHandle.set(p, i, v);
+       }
+
+       public static MemoryAddress getAddr(MemoryAddress p) {
+               return (MemoryAddress)addrHandle.get(p);
+       }
+
+       public static MemoryAddress getAddr(MemoryAddress p, long i) {
+               return (MemoryAddress)addrVHandle.get(p, i);
+       }
+
+       public static void setAddr(MemoryAddress p, MemoryAddress v) {
+               addrHandle.set(p, v);
+       }
+
+       public static void setAddr(MemoryAddress p, long i, MemoryAddress v) {
+               addrVHandle.set(p, i, v);
+       }
+
+       /* helpers - java to native */
+       public static <T extends Native> MemoryAddress toAddrV(Allocator frame, T[]array) {
+               MemoryAddress list = frame.alloca(8 *  array.length);
+
+               for (int i=0;i<array.length;i++)
+                       setAddr(list, i, array[i].addr());
+
+               return list;
+       }
+
+       public static <T extends Native> MemoryAddress toAddrV(Allocator frame, String[]array) {
+                if (array != null) {
+                        MemoryAddress list = frame.alloca(8 *  array.length);
+
+                        for (int i=0;i<array.length;i++)
+                                setAddr(list, i, toByteV(frame, array[i]));
+
+                        return list;
+                } else {
+                        return MemoryAddress.NULL;
+                }
+        }
+
+       public static <T extends Native> MemoryAddress toLongV(Allocator frame, long[]array) {
+               MemoryAddress list = frame.alloca(8 *  array.length);
+
+               for (int i=0;i<array.length;i++)
+                       setLong(list, i, array[i]);
+
+               return list;
+       }
+
+       public static <T extends Native> MemoryAddress toByteV(Allocator frame, byte[] data) {
+               if (data != null) {
+                       MemoryAddress list = frame.alloca(data.length);
+
+                       for (int i=0;i<data.length;i++)
+                               setByte(list, i, data[i]);
+
+                       return list;
+               } else {
+                       return MemoryAddress.NULL;
+               }
+       }
+
+       public static <T extends Native> MemoryAddress toByteV(Allocator frame, String string) {
+               if (string != null) {
+                       byte[] data = string.getBytes();
+                       MemoryAddress list = frame.alloca(data.length + 1);
+
+                       for (int i=0;i<data.length;i++)
+                               setByte(list, i, data[i]);
+                       setByte(list, data.length, (byte)0);
+
+                       return list;
+               } else {
+                       return MemoryAddress.NULL;
+               }
+       }
+
+       /* helpers - native to java */
+       public static <T extends Native> T[] toObjectV(MemoryAddress list, T[] array, Function<MemoryAddress,T> create) {
+               for (int i=0;i<array.length;i++)
+                       array[i] = Native.resolve(getAddr(list, i), create);
+               return array;
+       }
+
+       public static <T extends Native> T[] toObjectV(MemorySegment list, Function<MemoryAddress,T> create, IntFunction<T[]> createArray) {
+               return toObjectV(list.baseAddress(), createArray.apply((int)(list.byteSize() >>> 3)), create);
+       }
+
+       public static String toString(MemoryAddress cstr) {
+               MemorySegment seg = ForeignUnsafe.ofNativeUnchecked(cstr, Integer.MAX_VALUE);
+               MemoryAddress add = seg.baseAddress();
+               byte[] data;
+               int len = 0;
+
+               while (getByte(add, len) != 0)
+                       len++;
+
+               data = new byte[len];
+               for (int i=0;i<data.length;i++)
+                       data[i] = getByte(add, i);
+
+               return new String(data);
+       }
+
+       public static long[] toLongV(MemorySegment valp) {
+               MemoryAddress val = valp.baseAddress();
+               int len = (int)(valp.byteSize() >>> 3);
+               long[] list = new long[len];
+
+               for (int i=0;i<list.length;i++)
+                       list[i] = getLong(val, i);
+
+               return list;
+       }
+
+       /* abi stuff */
+
+       public static MethodHandle downcallHandle(LibraryLookup[] libs, String name, String signature) {
+               Signature sig = Signature.parse(signature);
+               int n = sig.classes.length;
+               SystemABI abi = SystemABI.getInstance();
+
+               if (sig.classes.length != sig.layouts.length)
+                       throw new RuntimeException("layout class mismatch");
+               Class<?> resClass = sig.classes[n-1];
+               MemoryLayout resLayout = sig.layouts[n-1];
+
+               for (LibraryLookup lib: libs) {
+                       try {
+                               return abi.downcallHandle(lib.lookup(name),
+                                                         MethodType.methodType(resClass, Arrays.copyOf(sig.classes, n-1)),
+                                                         FunctionDescriptor.of(resLayout, false, Arrays.copyOf(sig.layouts, n-1)));
+                       } catch (NoSuchMethodException x) {
+                       }
+               }
+               // or use some 'unsupportedoperation' one?
+               System.err.println("not found: "+ name);
+
+               return null;
+       }
+
+       public static MethodHandle downcallHandle(MemoryAddress addr, String signature) {
+               Signature sig = Signature.parse(signature);
+               int n = sig.classes.length;
+               SystemABI abi = SystemABI.getInstance();
+
+               if (sig.classes.length != sig.layouts.length)
+                       throw new RuntimeException("layout class mismatch");
+               Class<?> resClass = sig.classes[n-1];
+               MemoryLayout resLayout = sig.layouts[n-1];
+
+               return abi.downcallHandle(addr,
+                                         MethodType.methodType(resClass, Arrays.copyOf(sig.classes, n-1)),
+                                         FunctionDescriptor.of(resLayout, false, Arrays.copyOf(sig.layouts, n-1)));
+       }
+
+       // instance must be of a functional interface
+       public static MemoryAddress upcallStub(MethodHandles.Lookup lookup, Object instance, String signature) {
+               Signature sig = Signature.parse(signature);
+               int n = sig.classes.length;
+               SystemABI abi = SystemABI.getInstance();
+
+               if (sig.classes.length != sig.layouts.length)
+                       throw new RuntimeException("layout class mismatch");
+               Class<?> resClass = sig.classes[n-1];
+               MemoryLayout resLayout = sig.layouts[n-1];
+
+
+               Method m = instance.getClass().getMethods()[0];
+               MethodType mt = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
+
+               //System.out.printf("instance %s\n", instance);
+               //System.out.printf("declaring class %s\n", m.getDeclaringClass());
+
+               try {
+                       return abi.upcallStub(lookup.findVirtual(
+                                                     m.getDeclaringClass(),
+                                                     m.getName(),
+                                                     mt)
+                                             .bindTo(instance),
+                                             FunctionDescriptor.of(resLayout, false, Arrays.copyOf(sig.layouts, n-1)));
+               } catch (NoSuchMethodException | IllegalAccessException x) {
+                       throw new RuntimeException(x);
+               }
+       }
+
+       public static void freeUpcallStub(MemoryAddress addr) {
+               SystemABI.getInstance().freeUpcallStub(addr);
+       }
+
+       public static LibraryLookup[] loadLibraries(String... libraries) {
+               LibraryLookup[] libs = new LibraryLookup[libraries.length];
+               MethodHandles.Lookup lookup = MethodHandles.lookup();
+               for (int i=0;i<libraries.length;i++)
+                       libs[i] = LibraryLookup.ofLibrary(lookup, libraries[i]);
+               return libs;
+       }
+
+       public static MemoryLayout parseStruct(String layout) {
+               Signature sig = Signature.parse(layout);
+
+               return MemoryLayout.ofStruct(sig.layouts);
+       }
+
+       public static MemoryLayout parseUnion(String layout) {
+               Signature sig = Signature.parse(layout);
+
+               return MemoryLayout.ofUnion(sig.layouts);
+       }
+
+       public static void dumpSignature(String signature) {
+               Signature sig = Signature.parse(signature);
+               for (int i=0;i<sig.classes.length;i++) {
+                       System.out.printf(" %-40s %s\n", sig.classes[i].getName(), sig.layouts[i]);
+               }
+       }
+
+       static class Signature {
+               Class classes[];
+               MemoryLayout layouts[];
+
+               public Signature(Class[] classes, MemoryLayout[] layouts) {
+                       this.classes = classes;
+                       this.layouts = layouts;
+               }
+
+               public static Signature parse(String s) {
+                       List<Class> argClass = new ArrayList<>();
+                       List<MemoryLayout> argLayout = new ArrayList<>();
+                       StringReader r = new StringReader(s);
+                       int c;
+                       int size = 0;
+                       StringBuilder sb = new StringBuilder();
+                       int pointerDepth = 0;
+                       int type = 0; // func/struct/union
+
+                       //System.out.printf("parse: '%s'\n", s);
+                       try {
+                               c = r.read();
+                               switch (c) {
+                               case '(':
+                                       type = 0;
+                                       break;
+                               case '[':
+                                       type = 1;
+                                       break;
+                               default:
+                                       throw new RuntimeException("Unknown type: " + (char)c);
+                               }
+                               c = r.read();
+
+                               while ( c != -1) {
+                                       switch (c) {
+                                       case 'u':
+                                       case 'i':
+                                       case 'f':
+                                       case 'x': {
+                                               int d;
+                                               size = 0;
+                                               while ((d = r.read()) != -1 && d >= '0' && d <= '9')
+                                                       size = size * 10 + (d - '0');
+
+                                               // named field
+                                               if (d == '(') {
+                                                       while ((d = r.read()) != -1 && d != ')')
+                                                               ;
+                                                       d = r.read();
+                                               }
+
+                                               if (d == ':') {
+                                                       //System.out.printf(" pointer: size=%d\n", size);
+                                                       pointerDepth++;
+                                               } else {
+                                                       if (d == '=') {
+                                                               // actually it's bitfield, but ignore internal details
+                                                               d = r.read();
+                                                               if (d != '[')
+                                                                       throw new UnsupportedOperationException("expecting [");
+                                                               while ((d = r.read()) != -1 && d != ']')
+                                                                       ;
+                                                               d = r.read();
+                                                       } else {
+                                                               //System.out.printf(" prim: *=%d size=%d\n", pointerDepth, size);
+                                                       }
+
+                                                       if (pointerDepth > 0) {
+                                                               argClass.add(MemoryAddress.class);
+                                                               argLayout.add(MemoryLayouts.SysV.C_POINTER);
+                                                       } else {
+                                                               switch (c) {
+                                                               case 'u':
+                                                                       switch (size) {
+                                                                       case 8:
+                                                                               argClass.add(byte.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_UCHAR);
+                                                                               break;
+                                                                       case 16:
+                                                                               // char.class?
+                                                                               argClass.add(short.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_USHORT);
+                                                                               break;
+                                                                       case 32:
+                                                                               argClass.add(int.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_UINT);
+                                                                               break;
+                                                                       case 64:
+                                                                               argClass.add(long.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_ULONG);
+                                                                               break;
+                                                                       }
+                                                                       break;
+                                                               case 'i':
+                                                                       switch (size) {
+                                                                       case 8:
+                                                                               argClass.add(byte.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_SCHAR);
+                                                                               break;
+                                                                       case 16:
+                                                                               argClass.add(short.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_SHORT);
+                                                                               break;
+                                                                       case 32:
+                                                                               argClass.add(int.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_INT);
+                                                                               break;
+                                                                       case 64:
+                                                                               argClass.add(long.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_LONG);
+                                                                               break;
+                                                                       }
+                                                                       break;
+                                                               case 'f':
+                                                                       switch (size) {
+                                                                       case 32:
+                                                                               argClass.add(float.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_FLOAT);
+                                                                               break;
+                                                                       case 64:
+                                                                               argClass.add(double.class);
+                                                                               argLayout.add(MemoryLayouts.SysV.C_DOUBLE);
+                                                                               break;
+                                                                       }
+                                                                       break;
+                                                               case 'x':
+                                                                       switch (size) {
+                                                                       case 8:
+                                                                               argLayout.add(MemoryLayouts.PAD_8);
+                                                                               break;
+                                                                       case 16:
+                                                                               argLayout.add(MemoryLayouts.PAD_16);
+                                                                               break;
+                                                                       case 32:
+                                                                               argLayout.add(MemoryLayouts.PAD_32);
+                                                                               break;
+                                                                       case 64:
+                                                                               argLayout.add(MemoryLayouts.PAD_64);
+                                                                               break;
+                                                                       }
+                                                                       break;
+                                                               }
+                                                       }
+                                                       c = d;
+                                                       pointerDepth = 0;
+                                                       continue;
+                                               }
+                                               break;
+                                       }
+                                       case 'v':
+                                               //System.out.printf("void *=%d\n", pointerDepth);
+                                               if (pointerDepth > 0) {
+                                                       argClass.add(MemoryAddress.class);
+                                                       argLayout.add(MemoryLayouts.SysV.C_POINTER);
+                                               } else {
+                                                       // can only be return value
+                                                       argClass.add(void.class);
+                                                       argLayout.add(null);
+                                               }
+                                               pointerDepth = 0;
+                                               break;
+                                       case '$':
+                                               c = r.read();
+                                               if (c != '{')
+                                                       throw new RuntimeException();
+                                               sb.setLength(0);
+                                               boolean cap = true;
+                                               while ((c = r.read()) != -1 && c != '}') {
+                                                       if (c == '_') {
+                                                               cap = true;
+                                                               continue;
+                                                       }
+                                                       if (cap) {
+                                                               c = Character.toUpperCase(c);
+                                                               cap = false;
+                                                       }
+                                                       sb.append((char)c);
+                                               }
+                                               //System.out.printf(" type: *=%d  %s\n", pointerDepth, sb);
+                                               if (pointerDepth > 0) {
+                                                       argClass.add(MemoryAddress.class);
+                                                       argLayout.add(MemoryLayouts.SysV.C_POINTER);
+                                               } else {
+                                                       argClass.add(MemorySegment.class);
+                                                       try {
+                                                               Class<?> stype = Class.forName("api." + sb.toString());
+                                                               argLayout.add((MemoryLayout)stype.getDeclaredMethod("layout").invoke(null));
+                                                       } catch (Exception x) {
+                                                               throw new RuntimeException(x);
+                                                       }
+                                               }
+                                               pointerDepth = 0;
+                                               break;
+                                       case '(': // named field, ignore it
+                                               while ((c = r.read()) != -1 && c != ')')
+                                                       ;
+                                               break;
+                                       case '|':
+                                               // wrong!  could be inline union sub-part
+                                               if (type == 1 || type == 2)
+                                                       type = 2;
+                                               else
+                                                       throw new UnsupportedOperationException("union in thing?");
+                                               break;
+                                       case ')':
+                                               break;
+                                       case ']':
+                                               break;
+                                       default:
+                                               throw new UnsupportedOperationException("Unknown token: " + (char)c);
+                                       }
+                                       c = r.read();
+                               }
+                       } catch (java.io.IOException x) {
+                               throw new RuntimeException(x);
+                       }
+
+                       return new Signature(argClass.stream().toArray(Class[]::new),
+                                            argLayout.stream().toArray(MemoryLayout[]::new));
+               }
+       }
+
+       /* ********************************************************************** */
+       /* GC handling */
+       /* ********************************************************************** */
+
+       /**
+        * Resource index.
+        */
+       static private final PointerTable map = new PointerTable();
+
+       /**
+        * Reference queue for stale objects.
+        */
+       static private final ReferenceQueue<Native> references = new ReferenceQueue<>();
+
+       private static <T extends Native> T createInstance(Class<T> jtype, MemoryAddress p) {
+               cleanerStep();
+               try {
+                       Class[] params = {MemoryAddress.class};
+                       Constructor<T> cc = jtype.getDeclaredConstructor(params);
+
+                       cc.setAccessible(true);
+
+                       return cc.newInstance(p);
+               } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                       log().log(Level.ERROR, "createInstance", ex);
+                       throw new RuntimeException(ex);
+               }
+       }
+
+       /*
+       public static <T extends Native> T resolve(Class<T> jtype, MemoryAddress p) {
+               T o;
+
+               //if (dolog)
+               log().log(Level.DEBUG, () -> String.format("  resolve $%016x %s", p.offset(), jtype.getName()));
+
+               // Instantiation needs to be synchronized for obvious reasons.
+               synchronized (map) {
+                       CHandle h = (CHandle) map.get(p);
+
+                       if (h == null || (o = jtype.cast(h.get())) == null) {
+                               o = createInstance(jtype, p);
+                               h = new CHandle(o, references, p);
+                               map.putAlways(h);
+                       }
+               }
+               return o;
+               }*/
+
+       public static <T extends Native> T resolve(MemoryAddress p, Function<MemoryAddress,T> create) {
+               T o;
+               boolean step = false;
+
+               if (dolog)
+                       log().log(Level.DEBUG, () -> String.format("  resolv $%016x %s", Memory.toLong(p), create));
+
+               // ??? who the fuck knows if this will work
+               if (p.offset() == 0)
+                       return null;
+
+               // Instantiation needs to be synchronized for obvious reasons.
+               synchronized (map) {
+                       CHandle h = (CHandle) map.get(p);
+
+                       if (h == null || (o = (T)(h.get())) == null) {
+                               o = create.apply(p);
+                               h = new CHandle(o, references, p);
+                               map.put(h);
+                               step = true;
+                       }
+               }
+
+               if (step)
+                       cleanerStep();
+
+               return o;
+       }
+
+       /*
+       public static <T extends Native> void register(T o) {
+               T o;
+               boolean step = false;
+
+               if (dolog)
+                       log().log(Level.DEBUG, () -> String.format("  regist $%016x %s", o.addr().offset(), o.getClass().getName()));
+
+               CHandle h = new CHandle(o, references, o.addr());
+
+               synchronized (map) {
+                       map.put(h);
+                       step = true;
+               }
+
+               if (step)
+                       cleanerStep();
+
+               return o;
+               }*/
+
+       public void release() {
+               WeakReference<? extends Native> ref;
+
+               synchronized (map) {
+                       ref = map.remove(p);
+               }
+
+               if (ref != null) {
+                       if (dolog)
+                               log().log(Level.DEBUG, () -> String.format("  force  $%016x %s", Memory.toLong(p), getClass().getName()));
+
+                       ref.enqueue();
+               }
+       }
+
+       public static <T extends Native> void release(T a) {
+               if (a != null)
+                       a.release();
+       }
+
+       public static void release(Native... list) {
+               for (Native o : list)
+                       release(o);
+       }
+
+       static {
+               Thread cleanup = new Thread(Native::cleaner, "Native cleaner");
+               cleanup.setPriority(Thread.MAX_PRIORITY);
+               cleanup.setDaemon(true);
+               cleanup.start();
+       }
+
+       private static void cleanerStep() {
+               try {
+                       CHandle stale = (CHandle) references.poll();
+                       if (stale != null) {
+                               synchronized (map) {
+                                       map.remove(stale.p);
+                               }
+                               stale.release();
+                       }
+               } catch (Throwable ex) {
+               }
+       }
+
+       /**
+        * Cleaner thread.
+        * <p>
+        * This polls the reference queue and releases objects via
+        * their static release method.
+        */
+       private static void cleaner() {
+               if (dolog)
+                       log().log(Level.INFO, "Native finaliser started");
+               try {
+                       while (true) {
+                               CHandle stale = (CHandle) references.remove();
+                               do {
+                                       try {
+                                               synchronized (map) {
+                                                       map.remove(stale.p);
+                                               }
+                                               stale.release();
+                                       } catch (Throwable ex) {
+                                       }
+                                       stale = (CHandle) references.poll();
+                               } while (stale != null);
+                       }
+               } catch (InterruptedException ex) {
+               }
+       }
+
+       private static class CHandle extends WeakReference<Native> {
+               protected MemoryAddress p;
+               final Class<? extends Native> jtype;
+               CHandle next;
+
+               CHandle(Native referent, ReferenceQueue<Native> references, MemoryAddress p) {
+                       super(referent, references);
+                       this.p = p;
+                       this.jtype = referent.getClass();
+               }
+
+               void release() {
+                       try {
+                               if (p != null) {
+                                       if (dolog)
+                                               log().log(Level.DEBUG, () -> String.format("  releas $%016x %s", Memory.toLong(p), jtype.getName()));
+
+                                       Method mm = jtype.getDeclaredMethod("release", MemoryAddress.class);
+                                       mm.setAccessible(true);
+                                       mm.invoke(null, p);
+                               }
+                       } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                               log().log(Level.ERROR, jtype.getName(), ex);
+                       } finally {
+                               p = null;
+                       }
+               }
+
+               @Override
+               public boolean equals(Object obj) {
+                       return (obj instanceof CHandle) && ((CHandle) obj).p == p;
+               }
+
+               @Override
+               public int hashCode() {
+                       //return p.hashCode();
+                       return hashCode(p);
+               }
+
+               /**
+                * Simple hashcode for native pointers.
+                * <p>
+                * This simply strips the bottom 4 bits from the pointer as
+                * on a 64-bit system the low 3 bits are typically zero and the 4th
+                * isn't very well distributed.
+                *
+                * @param p
+                * @return
+                */
+               public static final int hashCode(long p) {
+                       return (int) p >>> 4;
+               }
+
+               /**
+                * Sigh, memoryaddress has a miserable hashCode(), it's even worse than Long.hashCode()
+                */
+               public static final int hashCode(MemoryAddress p) {
+                       return p.hashCode() >>> 5;
+               }
+       }
+
+       /**
+        * Lightweight pointer hashtable.
+        * <p>
+        * This serves two purposes:
+        * <ol>
+        * <li>Track and resolve unique objects based on memory address;
+        * <li>Hold hard references to the WeakReference as required by the gc system.
+        * </ol>
+        * <p>
+        * CHandle's are chained directly from the index table, the p field
+        * is used as a key directly, and hash values are not cached. This combines
+        * to save significant memory per node.
+        */
+       private static class PointerTable {
+
+               int mask = 63;
+               int size = 0;
+               CHandle[] table = new CHandle[64];
+
+               private void resize(int length) {
+                       CHandle[] ntable = new CHandle[length];
+                       int nmask = length - 1;
+
+                       for (int i = 0; i < table.length; i++) {
+                               CHandle h = table[i];
+
+                               while (h != null) {
+                                       CHandle n = h.next;
+                                       int k = h.hashCode() & nmask;
+
+                                       h.next = ntable[k];
+                                       ntable[k] = h;
+
+                                       h = n;
+                               }
+                       }
+
+                       table = ntable;
+                       mask = nmask;
+               }
+
+               public CHandle put(CHandle h) {
+                       CHandle o = remove(h.p);
+
+                       putAlways(h);
+
+                       return o;
+               }
+
+               public void putAlways(CHandle h) {
+                       if (size > table.length * 2)
+                               resize(table.length * 2);
+
+                       int i = h.hashCode() & mask;
+
+                       h.next = table[i];
+                       table[i] = h;
+                       size += 1;
+               }
+
+               public CHandle get(MemoryAddress p) {
+                       int i = CHandle.hashCode(p) & mask;
+                       CHandle h = table[i];
+
+                       while (h != null && !h.p.equals(p))
+                               h = h.next;
+                       return h;
+               }
+
+               public CHandle remove(MemoryAddress p) {
+                       int i = CHandle.hashCode(p) & mask;
+                       CHandle h = table[i];
+                       CHandle a = null;
+
+                       while (h != null && !h.p.equals(p)) {
+                               a = h;
+                               h = h.next;
+                       }
+                       if (h != null) {
+                               if (a != null)
+                                       a.next = h.next;
+                               else
+                                       table[i] = h.next;
+                               size -= 1;
+                       }
+
+                       return h;
+               }
+       }
+}
index 731823a..d0f59af 100644 (file)
  */
 package au.notzed.zcl;
 
+import jdk.incubator.foreign.*;
+
 import java.nio.ByteBuffer;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Interface for memory buffers.
@@ -24,43 +27,24 @@ import java.nio.ByteBuffer;
  */
 public class CLBuffer extends CLMemory {
 
-       /**
-        * Use USE_HOST_PTR was used then this keeps track of the host ptr reference
-        * to avoid java freeing it.
-        */
-       private final ByteBuffer hostPtr;
-
        /**
         * Create an interface for a native pointer of type cl_mem that refers to a
         * buffer object.
         *
         * @param p Native pointer.
         */
-       public CLBuffer(long p) {
-               super(p);
-               hostPtr = null;
+       public CLBuffer(MemoryAddress p) {
+               this(p, null);
        }
 
-       public CLBuffer(long p, ByteBuffer hostPtr) {
-               super(p);
-
-               this.hostPtr = hostPtr;
+       public CLBuffer(MemoryAddress p, MemorySegment seg) {
+               super(p, seg);
        }
 
-       static void release(long p) {
+       static void release(MemoryAddress p) {
                CLMemory.release(p);
        }
 
-       @Override
-       int getInfoType() {
-               return TYPE_MEM_OBJECT;
-       }
-
-       @Override
-       public ByteBuffer getHostPtr() {
-               return hostPtr;
-       }
-
        /**
         * Parameter to define a region for createSubBuffer().
         *
index 94ef9ec..fa97c8a 100644 (file)
@@ -20,7 +20,7 @@ package au.notzed.zcl;
  * Parameters for Buffer.createSubBuffer()
  * <p>
  * Specific types are defined on CLBuffer.
- * 
+ *
  */
 public abstract class CLBufferInfo {
 
index ed2539b..c73cfa7 100644 (file)
  */
 package au.notzed.zcl;
 
-import java.nio.ByteBuffer;
 import static au.notzed.zcl.CL.*;
-import au.notzed.zcl.khr.GLSharing;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Allocator;
+import api.Memory;
+import api.Callback;
+
+import java.util.ArrayList;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+//import static au.au.notzed.zcl.CL.*;
+//import au.notzed.zcl.khr.GLSharing;
+
+import java.lang.invoke.MethodHandle;
+import java.util.function.Function;
 
 /**
  * Interface for cl_command_queue.
@@ -44,15 +60,24 @@ public class CLCommandQueue extends CLExtendable {
         *
         * @param p Native pointer.
         */
-       public CLCommandQueue(long p) {
+       CLCommandQueue(MemoryAddress p) {
                super(p);
        }
 
-       private native static void release(long p);
+       public static CLCommandQueue create(MemoryAddress p) {
+               return Native.resolve(p, CLCommandQueue::new);
+       }
+
+       private static void release(MemoryAddress p) {
+               try {
+                       clReleaseCommandQueue(p);
+               } catch (Throwable t) {
+               }
+       }
 
        @Override
-       int getInfoType() {
-               return TYPE_COMMAND_QUEUE;
+       MethodHandle getInfoFunc() {
+               return clGetCommandQueueInfo;
        }
 
        public static CLQueueProperty PROPERTIES(long flags) {
@@ -82,36 +107,92 @@ public class CLCommandQueue extends CLExtendable {
         *
         * @throws CLException
         */
-       public native void flush() throws CLException;
+       public void flush() throws CLException {
+               try {
+                       int res = clFlush(addr());
+                       if (res != 0)
+                               throw new CLException(res);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clFinish.
         *
         * @throws CLException
         */
-       public native void finish() throws CLException;
+       public void finish() throws CLException {
+               try {
+                       int res = clFinish(addr());
+                       if (res != 0)
+                               throw new CLException(res);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
-        * Calls clEnqueueReadBuffer for a direct Buffer.
+        * Calls clEnqueueReadBuffer for a MemorySegment.
         *
         * @param mem
         * @param blocking
         * @param mem_offset source memory offset in bytes.
         * @param size memory transfer size in bytes.
-        * @param buffer destination buffer. Must be a direct buffer.
+        * @param buffer destination buffer.  It must be a native segment.
         * @param wait
         * @param event
         * @throws CLException
         */
-       native public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, long size,
+               MemorySegment buffer,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               if (size > buffer.byteSize())
+                       throw new BufferOverflowException();
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       int res;
+
+                       res = clEnqueueReadBuffer(addr(), mem.addr(), blocking ? 1 : 0,
+                               mem_offset, size,
+                               buffer.baseAddress(),
+                               info.nwait, info.wait, info.event);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
                long mem_offset, long size,
                ByteBuffer buffer,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.ofByteBuffer(buffer)) {
+                       enqueueReadBuffer(mem, blocking,
+                               mem_offset, size,
+                               seg,
+                               wait, event);
+               }
+       }
 
        /**
         * Calls clEnqueueReadBuffer for a byte array.
         *
+        * panama note: the buffer must always be copied.
+        *
         * @param mem
         * @param blocking ignored, array reads are always blocking.
         * @param mem_offset source memory offset in bytes.
@@ -122,15 +203,22 @@ public class CLCommandQueue extends CLExtendable {
         * @param event
         * @throws CLException
         */
-       native public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               byte[] buffer, long buf_offset,
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               byte[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size)) {
+                       enqueueReadBuffer(mem, true, mem_offset, size, seg, wait, event);
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).get(buffer, buf_offset, size);
+               }
+       }
 
        /**
         * Calls clEnqueueReadBuffer for a short array.
         *
+        * Note that mem_offset and size are in terms of the buffer element size.
+        *
         * @param mem
         * @param blocking ignored, array reads are always blocking.
         * @param mem_offset source memory offset in shorts.
@@ -141,35 +229,78 @@ public class CLCommandQueue extends CLExtendable {
         * @param event
         * @throws CLException
         */
-       native public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               short[] buffer, long buf_offset,
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               short[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 2)) {
+                       enqueueReadBuffer(mem, true, mem_offset * 2, size * 2, seg, wait, event);
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asShortBuffer().get(buffer, buf_offset, size);
+               }
+       }
 
-       native public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               int[] buffer, long buf_offset,
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               int[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 4)) {
+                       enqueueReadBuffer(mem, true, mem_offset * 4, size * 4, seg, wait, event);
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asIntBuffer().get(buffer, buf_offset, size);
+               }
+       }
 
-       native public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               long[] buffer, long buf_offset,
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               long[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 8)) {
+                       enqueueReadBuffer(mem, true, mem_offset * 8, size * 8, seg, wait, event);
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asLongBuffer().get(buffer, buf_offset, size);
+               }
+       }
 
-       native public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               float[] buffer, long buf_offset,
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               float[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 4)) {
+                       enqueueReadBuffer(mem, true, mem_offset * 4, size * 4, seg, wait, event);
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asFloatBuffer().get(buffer, buf_offset, size);
+               }
+       }
 
-       native public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               double[] buffer, long buf_offset,
+       public void enqueueReadBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               double[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 8)) {
+                       enqueueReadBuffer(mem, true, mem_offset * 8, size * 8, seg, wait, event);
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asDoubleBuffer().get(buffer, buf_offset, size);
+               }
+       }
+
+       private void checkBufferRectRange(
+               long[] buffer_origin, long[] host_origin, long[] region,
+               long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch,
+               long limit) {
+               if (buffer_origin.length != 3
+                   || host_origin.length != 3
+                   || region.length != 3)
+                       throw new IllegalArgumentException("origin and region must be 3-dimensional");
+
+               long stride = host_row_pitch == 0 ? region[0] : host_row_pitch;
+               long slice = host_slice_pitch == 0 ? region[1] * stride : host_slice_pitch;
+
+               if (host_origin[0] + host_origin[1] * stride + host_origin[2] * slice
+                   + region[0] + (region[1]-1) * stride + (region[2]-1) * slice
+                   > limit)
+                       throw new BufferOverflowException();
+       }
 
        /**
         *
@@ -189,17 +320,89 @@ public class CLCommandQueue extends CLExtendable {
         * @throws UnsupportedOperationException
         * @since OpenCL 1.1
         */
-       public native void enqueueReadBufferRect(CLBuffer mem, boolean blocking,
+       public void enqueueReadBufferRect(CLBuffer mem, boolean blocking,
+               long[] buffer_origin, long[] host_origin, long[] region,
+               long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch,
+               MemorySegment buffer,
+               CLEventList wait, CLEventList event) throws CLException, UnsupportedOperationException {
+               checkBufferRectRange(
+                       buffer_origin, host_origin, region,
+                       buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch,
+                       buffer.byteSize());
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       MemoryAddress cbuffer_origin = toLongV(frame, buffer_origin);
+                       MemoryAddress chost_origin = toLongV(frame, host_origin);
+                       MemoryAddress cregion = toLongV(frame, region);
+                       int res;
+
+                       res = clEnqueueReadBufferRect(
+                               addr(), mem.addr(), blocking ? 1 : 0,
+                               cbuffer_origin, chost_origin, cregion,
+                               buffer_row_pitch,
+                               buffer_slice_pitch,
+                               host_row_pitch,
+                               host_slice_pitch,
+                               buffer.baseAddress(),
+                               info.nwait, info.wait, info.event);
+
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       public void enqueueReadBufferRect(CLBuffer mem, boolean blocking,
                long[] buffer_origin, long[] host_origin, long[] region,
                long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch,
                ByteBuffer buffer,
-               CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException;
+               CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException {
+
+               try (MemorySegment seg = MemorySegment.ofByteBuffer(buffer)) {
+                       enqueueReadBufferRect(mem, blocking,
+                               buffer_origin, host_origin, region,
+                               buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch,
+                               seg,
+                               waiters, events);
+               }
+       }
 
-       public native void enqueueReadBufferRect(CLBuffer mem, boolean blocking,
+       public void enqueueReadBufferRect(CLBuffer mem, boolean blocking,
                long[] buffer_origin, long[] host_origin, long[] region,
                long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch,
                byte[] buffer,
-               CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException;
+               CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException {
+               // This allocates only what is required and then copies row by row to the target host_origin.
+               // yikes this isn't very nice.
+               long stride = region[0];
+               long slice = region[1] * stride;
+               long size = slice * region[2];
+
+               try (MemorySegment seg = MemorySegment.allocateNative(size)) {
+                       enqueueReadBufferRect(mem, blocking,
+                               buffer_origin, OFFSET_0x0x0, region,
+                               buffer_row_pitch, buffer_slice_pitch, stride, slice,
+                               seg,
+                               waiters, events);
+                       long host_stride = host_row_pitch == 0 ? region[0] : host_row_pitch;
+                       long host_slice = host_slice_pitch == 0 ? region[1] * host_stride : host_slice_pitch;
+                       long host_offset = host_origin[0] + host_origin[1] * host_stride + host_origin[2] * host_slice;
+                       ByteBuffer bb = seg.asByteBuffer().order(ByteOrder.nativeOrder());
+
+                       for (long z = 0; z < region[2]; z++) {
+                               for (long y = 0; y < region[1]; y++) {
+                                       long o = host_offset + y * host_stride + z * host_slice;
+                                       bb.get(buffer, (int)o, (int)region[0]);
+                               }
+                       }
+               }
+       }
 
        public native void enqueueReadBufferRect(CLBuffer mem, boolean blocking,
                long[] buffer_origin, long[] host_origin, long[] region,
@@ -231,47 +434,111 @@ public class CLCommandQueue extends CLExtendable {
                double[] buffer,
                CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException;
 
-       native public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
                long mem_offset, long size,
-               ByteBuffer buffer,
+               MemorySegment buffer,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               if (size > buffer.byteSize())
+                       throw new BufferUnderflowException();
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       int res;
+
+                       res = clEnqueueWriteBuffer(addr(), mem.addr(), blocking ? 1 : 0,
+                               mem_offset, size,
+                               buffer.baseAddress(),
+                               info.nwait, info.wait, info.event);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
-       native public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
                long mem_offset, long size,
-               byte[] buffer, long buf_offset,
+               ByteBuffer buffer,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.ofByteBuffer(buffer)) {
+                       enqueueWriteBuffer(mem, blocking,
+                               mem_offset, size,
+                               seg,
+                               wait, event);
+               }
+       }
 
-       native public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               short[] buffer, long buf_offset,
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               byte[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size)) {
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).put(buffer, buf_offset, size);
+                       enqueueWriteBuffer(mem, true, mem_offset, size, seg, wait, event);
+               }
+       }
 
-       native public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               int[] buffer, long buf_offset,
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               short[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 2L)) {
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asShortBuffer().put(buffer, buf_offset, size);
+                       enqueueWriteBuffer(mem, true, mem_offset * 2, size * 2L, seg, wait, event);
+               }
+       }
 
-       native public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               long[] buffer, long buf_offset,
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               int[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 4L)) {
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asIntBuffer().put(buffer, buf_offset, size);
+                       enqueueWriteBuffer(mem, true, mem_offset * 4, size * 4L, seg, wait, event);
+               }
+       }
 
-       native public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               float[] buffer, long buf_offset,
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               long[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 8L)) {
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asLongBuffer().put(buffer, buf_offset, size);
+                       enqueueWriteBuffer(mem, true, mem_offset * 8, size * 8L, seg, wait, event);
+               }
+       }
 
-       native public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
-               long mem_offset, long size,
-               double[] buffer, long buf_offset,
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               float[] buffer, int buf_offset,
                CLEventList wait,
-               CLEventList event) throws CLException;
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 4L)) {
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asFloatBuffer().put(buffer, buf_offset, size);
+                       enqueueWriteBuffer(mem, true, mem_offset * 4, size * 4L, seg, wait, event);
+               }
+       }
+
+       public void enqueueWriteBuffer(CLBuffer mem, boolean blocking,
+               long mem_offset, int size,
+               double[] buffer, int buf_offset,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(size * 8L)) {
+                       seg.asByteBuffer().order(ByteOrder.nativeOrder()).asDoubleBuffer().put(buffer, buf_offset, size);
+                       enqueueWriteBuffer(mem, true, mem_offset * 8, size * 8L, seg, wait, event);
+               }
+       }
 
        /**
         *
@@ -291,11 +558,60 @@ public class CLCommandQueue extends CLExtendable {
         * @throws UnsupportedOperationException
         * @since OpenCL 1.1
         */
-       public native void enqueueWriteBufferRect(CLBuffer mem, boolean blocking,
+       public void enqueueWriteBufferRect(CLBuffer mem, boolean blocking,
+               long[] buffer_origin, long[] host_origin, long[] region,
+               long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch,
+               MemorySegment buffer,
+               CLEventList wait, CLEventList event) throws CLException, UnsupportedOperationException {
+
+               requireAPIVersion(CLPlatform.VERSION_1_1);
+
+               checkBufferRectRange(
+                       buffer_origin, host_origin, region,
+                       buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch,
+                       buffer.byteSize());
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       MemoryAddress cbuffer_origin = toLongV(frame, buffer_origin);
+                       MemoryAddress chost_origin = toLongV(frame, host_origin);
+                       MemoryAddress cregion = toLongV(frame, region);
+                       int res;
+
+                       res = clEnqueueWriteBufferRect(
+                               addr(), mem.addr(), blocking ? 1 : 0,
+                               cbuffer_origin, chost_origin, cregion,
+                               buffer_row_pitch,
+                               buffer_slice_pitch,
+                               host_row_pitch,
+                               host_slice_pitch,
+                               buffer.baseAddress(),
+                               info.nwait, info.wait, info.event);
+
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       public void enqueueWriteBufferRect(CLBuffer mem, boolean blocking,
                long[] buffer_origin, long[] host_origin, long[] region,
                long buffer_row_pitch, long buffer_slice_pitch, long host_row_pitch, long host_slice_pitch,
                ByteBuffer buffer,
-               CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException;
+               CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException {
+               try (MemorySegment seg = MemorySegment.ofByteBuffer(buffer)) {
+                       enqueueWriteBufferRect(mem, blocking,
+                               buffer_origin, host_origin, region,
+                               buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch,
+                               seg,
+                               waiters, events);
+               }
+       }
 
        public native void enqueueWriteBufferRect(CLBuffer mem, boolean blocking,
                long[] buffer_origin, long[] host_origin, long[] region,
@@ -334,7 +650,10 @@ public class CLCommandQueue extends CLExtendable {
                CLEventList waiters, CLEventList events) throws CLException, UnsupportedOperationException;
 
        /**
-        * Calls clEnqueueFillBuffer for byte types.
+        * Calls clEnqueueFillBuffer.
+        *
+        * This fills the buffer with a pattern.  The offset and size
+        * is in multiples of the pattern size.
         *
         * @param buffer
         * @param pattern pattern to fill
@@ -345,12 +664,75 @@ public class CLCommandQueue extends CLExtendable {
         * @since OpenCL 1.2
         * @throws CLException
         */
-       public native void enqueueFillBuffer(CLBuffer buffer,
-               byte[] pattern,
+       public void enqueueFillBuffer(CLBuffer buffer,
+                                     MemorySegment pattern,
+                                     long offset,
+                                     long size,
+                                     CLEventList wait,
+                                     CLEventList event) throws CLException {
+               requireAPIVersion(CLPlatform.VERSION_1_2);
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       int res;
+
+                       res = clEnqueueFillBuffer(
+                               addr(), buffer.addr(),
+                               pattern.baseAddress(), pattern.byteSize(),
+                               offset * pattern.byteSize(),
+                               size * pattern.byteSize(),
+                               info.nwait, info.wait, info.event);
+
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+       public void enqueueFillBuffer(CLBuffer buffer,
+               ByteBuffer pattern,
                long offset,
                long size,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.ofByteBuffer(pattern)) {
+                       enqueueFillBuffer(buffer,
+                               pattern,
+                               offset, size,
+                               wait, event);
+               }
+       }
+
+       /**
+        * Calls clEnqueueFillBuffer for byte types.
+        *
+        * @param buffer
+        * @param pattern pattern to fill
+        * @param offset offset in multiples of the pattern size.
+        * @param size number of elements in multiples of the pattern size.
+        * @param waiters
+        * @param events
+        * @since OpenCL 1.2
+        * @throws CLException
+        */
+       public void enqueueFillBuffer(CLBuffer buffer,
+                                     byte[] pattern,
+                                     long offset,
+                                     long size,
+                                     CLEventList wait,
+                                     CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(pattern.length)) {
+                       MemoryAddress add = seg.baseAddress();
+
+                       for (int i=0;i<pattern.length;i++)
+                               setByte(add, i, pattern[i]);
+
+                       enqueueFillBuffer(buffer, seg, offset, size, wait, event);
+               }
+       }
 
        /**
         * Calls clEnqueueFillBuffer for short types.
@@ -364,12 +746,21 @@ public class CLCommandQueue extends CLExtendable {
         * @since OpenCL 1.2
         * @throws CLException
         */
-       public native void enqueueFillBuffer(CLBuffer buffer,
-               short[] pattern,
-               long offset,
-               long size,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       public void enqueueFillBuffer(CLBuffer buffer,
+                                            short[] pattern,
+                                            long offset,
+                                            long size,
+                                            CLEventList wait,
+                                            CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(pattern.length * 2)) {
+                       MemoryAddress add = seg.baseAddress();
+
+                       for (int i=0;i<pattern.length;i++)
+                               setShort(add, i, pattern[i]);
+
+                       enqueueFillBuffer(buffer, seg, offset * 2, size * 2, wait, event);
+               }
+       }
 
        /**
         * Calls clEnqueueFillBuffer for integer types.
@@ -383,12 +774,21 @@ public class CLCommandQueue extends CLExtendable {
         * @since OpenCL 1.2
         * @throws CLException
         */
-       public native void enqueueFillBuffer(CLBuffer buffer,
-               int[] pattern,
-               long offset,
-               long size,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       public void enqueueFillBuffer(CLBuffer buffer,
+                                            int[] pattern,
+                                            long offset,
+                                            long size,
+                                            CLEventList wait,
+                                            CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(pattern.length * 4)) {
+                       MemoryAddress add = seg.baseAddress();
+
+                       for (int i=0;i<pattern.length;i++)
+                               setInt(add, i, pattern[i]);
+
+                       enqueueFillBuffer(buffer, seg, offset * 4, size * 4, wait, event);
+               }
+       }
 
        /**
         * Calls clEnqueueFillBuffer for long types.
@@ -414,19 +814,28 @@ public class CLCommandQueue extends CLExtendable {
         *
         * @param buffer
         * @param pattern pattern to fill
-        * @param offset offset in multiples of the pattern size.
-        * @param size number of elements in multiples of the pattern size.
+        * @param offset offset in multiples of the pattern size in floats.
+        * @param size number of elements in multiples of the pattern size in floats.
         * @param waiters
         * @param events
         * @since OpenCL 1.2
         * @throws CLException
         */
-       public native void enqueueFillBuffer(CLBuffer buffer,
-               float[] pattern,
-               long offset,
-               long size,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       public void enqueueFillBuffer(CLBuffer buffer,
+                                     float[] pattern,
+                                     long offset,
+                                     long size,
+                                     CLEventList wait,
+                                     CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.allocateNative(pattern.length * 4)) {
+                       MemoryAddress add = seg.baseAddress();
+
+                       for (int i=0;i<pattern.length;i++)
+                               setFloat(add, i, pattern[i]);
+
+                       enqueueFillBuffer(buffer, seg, offset * 4, size * 4, wait, event);
+               }
+       }
 
        /**
         * Calls clEnqueueFillBuffer for double types.
@@ -447,9 +856,29 @@ public class CLCommandQueue extends CLExtendable {
                CLEventList waiters,
                CLEventList events) throws CLException;
 
-       public native void enqueueCopyBuffer(CLBuffer srcmem, CLBuffer dstmem, long srcoffset, long dstoffset, long size,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       public void enqueueCopyBuffer(CLBuffer srcmem, CLBuffer dstmem, long srcoffset, long dstoffset, long size,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       int res;
+
+                       res = clEnqueueCopyBuffer(
+                               addr(), srcmem.addr(), dstmem.addr(),
+                               srcoffset, dstoffset, size,
+                               info.nwait, info.wait, info.event);
+
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * @param srcmem
@@ -467,7 +896,7 @@ public class CLCommandQueue extends CLExtendable {
         * @throws UnsupportedOperationException
         * @since OpenCL 1.1
         */
-       public native void enqueueCopyBufferRect(CLBuffer srcmem, CLBuffer dstmem,
+       public void enqueueCopyBufferRect(CLBuffer srcmem, CLBuffer dstmem,
                long[] src_origin,
                long[] dst_origin,
                long[] region,
@@ -476,7 +905,115 @@ public class CLCommandQueue extends CLExtendable {
                long dst_row_pitch,
                long dst_slice_pitch,
                CLEventList waiters,
-               CLEventList events) throws CLException, UnsupportedOperationException;
+               CLEventList events) throws CLException, UnsupportedOperationException {
+       }
+
+       /*
+        * Parameterised image<>buffer copy function, for read or write
+        */
+       private void doImageBuffer(CLImage image, boolean blocking,
+               long[] origin,
+               long[] region,
+               long row_pitch,
+               long slice_pitch,
+               MemorySegment buffer,
+               CLEventList wait,
+               CLEventList event,
+               MethodHandle op) throws CLException {
+
+               if (origin.length != 3
+                   || region.length != 3)
+                       throw new IllegalArgumentException("origin and region must be 3-dimensional");
+
+               long stride = row_pitch == 0 ? region[0] * image.getElementSize() : row_pitch;
+               long slice = slice_pitch == 0 ? region[1] * stride : slice_pitch;
+
+               if (buffer.byteSize() < slice * region[2])
+                       throw new BufferOverflowException();
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       MemoryAddress corigin = toLongV(frame, origin);
+                       MemoryAddress cregion = toLongV(frame, region);
+                       int res;
+
+                       res = (int)op.invokeExact(
+                               addr(), image.addr(), blocking ? 1 : 0,
+                               corigin, cregion,
+                               row_pitch, slice_pitch,
+                               buffer.baseAddress(),
+                               info.nwait, info.wait, info.event);
+
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       private interface CopyAppend {
+               void apply(int doff, int size);
+
+               default void copy(int w, int h, int d, int stride, int slice) {
+                       for (int z=0;z<d;z++) {
+                               for (int y=0;y<h;y++) {
+                                       apply(y * stride + z * slice, w);
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Parameterised image<>buffer copy function, for read or write
+        * of primitive types.
+        * This first copies to the exact size required
+        * and then copies to the target.
+        */
+       private void doImageBufferPrimitive(
+               CLImage image, boolean blocking,
+               long[] origin,
+               long[] region,
+               long row_pitch,
+               long slice_pitch,
+               boolean readMode,
+               Function<MemorySegment, CopyAppend> writer,
+               long write_size,
+               long dshift,
+               MethodHandle op,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               //  Just transfer the minimum size, then copy to target
+               long elsize = image.getElementSize();
+
+               // these sizes are in array elmeents
+               long stride = row_pitch == 0 ? (region[0] * elsize) >> dshift : row_pitch;
+               long slice = slice_pitch == 0 ? (region[1] * stride) >> dshift : slice_pitch;
+
+               // Test target size
+               if (slice * region[2] > write_size)
+                       throw new BufferOverflowException();
+
+               // these are in bytes
+               long alloc = (region[0] * region[1] * region[2]) << dshift;
+               long xstride = region[0] << dshift;
+               long xslice = xstride * region[1];
+
+               try (MemorySegment seg = MemorySegment.allocateNative(alloc)) {
+                       if (!readMode)
+                               writer.apply(seg).copy((int)region[0], (int)region[1], (int)region[2],(int)stride, (int)slice);
+                       doImageBuffer(image, blocking, origin, region, xstride, 0, seg, wait, event, op);
+                       if (readMode)
+                               writer.apply(seg).copy((int)region[0], (int)region[1], (int)region[2],(int)stride, (int)slice);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         *
@@ -491,14 +1028,36 @@ public class CLCommandQueue extends CLExtendable {
         * @param events
         * @throws CLException
         */
-       public native void enqueueReadImage(CLImage image, boolean blocking,
+       public void enqueueReadImage(CLImage image, boolean blocking,
+               long[] origin,
+               long[] region,
+               long row_pitch,
+               long slice_pitch,
+               MemorySegment buffer,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               doImageBuffer(image, blocking, origin, region, row_pitch, slice_pitch, buffer, wait, event, clEnqueueReadImage);
+       }
+
+       /**
+        * @see #enqueueReadImage(CLImage,boolean,long[],long[],long,long,MemorySegment,CLEventList,CLEventList)
+        */
+       public void enqueueReadImage(CLImage image, boolean blocking,
                long[] origin,
                long[] region,
                long row_pitch,
                long slice_pitch,
                ByteBuffer buffer,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.ofByteBuffer(buffer)) {
+                       enqueueReadImage(image, blocking,
+                               origin, region,
+                               row_pitch, slice_pitch,
+                               seg,
+                               wait, event);
+               }
+       }
 
        /**
         *
@@ -514,23 +1073,50 @@ public class CLCommandQueue extends CLExtendable {
         * @param events
         * @throws CLException
         */
-       public native void enqueueReadImage(CLImage image, boolean blocking,
+       public void enqueueReadImage(CLImage image, boolean blocking,
                long[] origin,
                long[] region,
                long row_pitch,
                long slice_pitch,
-               byte[] buffer, long buff_offset,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               byte[] buffer, int buff_offset,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+
+               doImageBufferPrimitive(image, blocking, origin, region, row_pitch, slice_pitch,
+                       true,
+                       (seg) -> {
+                               var sb = seg.asByteBuffer();
+                               return (off, size) -> sb.get(buffer, buff_offset + off, size);
+                       },
+                       buff_offset - buffer.length,
+                       0,
+                       clEnqueueReadImage,
+                       wait, event);
+       }
 
-       public native void enqueueReadImage(CLImage image, boolean blocking,
+       /**
+        * @see #enqueueReadImage(CLImage,boolean,long[],long[],long,long,byte[],int,CLEventList,CLEventList)
+        */
+       public void enqueueReadImage(CLImage image, boolean blocking,
                long[] origin,
                long[] region,
                long row_pitch,
                long slice_pitch,
-               short[] buffer, long buff_offset,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               short[] buffer, int buff_offset,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+
+               doImageBufferPrimitive(image, blocking, origin, region, row_pitch, slice_pitch,
+                       true,
+                       (seg) -> {
+                               var sb = seg.asByteBuffer().order(ByteOrder.nativeOrder()).asShortBuffer();
+                               return (off, size) -> sb.get(buffer, buff_offset + off, size);
+                       },
+                       buff_offset - buffer.length,
+                       1,
+                       clEnqueueReadImage,
+                       wait, event);
+       }
 
        public native void enqueueReadImage(CLImage image, boolean blocking,
                long[] origin,
@@ -550,14 +1136,25 @@ public class CLCommandQueue extends CLExtendable {
                CLEventList waiters,
                CLEventList events) throws CLException;
 
-       public native void enqueueReadImage(CLImage image, boolean blocking,
+       public void enqueueReadImage(CLImage image, boolean blocking,
                long[] origin,
                long[] region,
                long row_pitch,
                long slice_pitch,
-               float[] buffer, long buff_offset,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               float[] buffer, int buff_offset,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               doImageBufferPrimitive(image, blocking, origin, region, row_pitch, slice_pitch,
+                       true,
+                       (seg) -> {
+                               var sb = seg.asByteBuffer().order(ByteOrder.nativeOrder()).asFloatBuffer();
+                               return (off, size) -> sb.get(buffer, buff_offset + off, size);
+                       },
+                       buff_offset - buffer.length,
+                       2,
+                       clEnqueueReadImage,
+                       wait, event);
+       }
 
        public native void enqueueReadImage(CLImage image, boolean blocking,
                long[] origin,
@@ -568,23 +1165,54 @@ public class CLCommandQueue extends CLExtendable {
                CLEventList waiters,
                CLEventList events) throws CLException;
 
-       public native void enqueueWriteImage(CLImage image, boolean blocking,
+       public void enqueueWriteImage(CLImage image, boolean blocking,
+               long[] origin,
+               long[] region,
+               long row_pitch,
+               long slice_pitch,
+               MemorySegment buffer,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               doImageBuffer(image, blocking, origin, region, row_pitch, slice_pitch, buffer, wait, event, clEnqueueWriteImage);
+       }
+
+       public void enqueueWriteImage(CLImage image, boolean blocking,
                long[] origin,
                long[] region,
                long row_pitch,
                long slice_pitch,
                ByteBuffer buffer,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               try (MemorySegment seg = MemorySegment.ofByteBuffer(buffer)) {
+                       enqueueWriteImage(image, blocking,
+                               origin, region,
+                               row_pitch, slice_pitch,
+                               seg,
+                               wait, event);
+               }
+       }
 
-       public native void enqueueWriteImage(CLImage image, boolean blocking,
+       public void enqueueWriteImage(CLImage image, boolean blocking,
                long[] origin,
                long[] region,
                long row_pitch,
                long slice_pitch,
-               byte[] buffer, long buff_offset,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               byte[] buffer, int buff_offset,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+
+               doImageBufferPrimitive(image, blocking, origin, region, row_pitch, slice_pitch,
+                       false,
+                       (seg) -> {
+                               var sb = seg.asByteBuffer();
+                               return (off, size) -> sb.put(buffer, buff_offset + off, size);
+                       },
+                       buff_offset - buffer.length,
+                       0,
+                       clEnqueueWriteImage,
+                       wait, event);
+       }
 
        public native void enqueueWriteImage(CLImage image, boolean blocking,
                long[] origin,
@@ -613,14 +1241,25 @@ public class CLCommandQueue extends CLExtendable {
                CLEventList waiters,
                CLEventList events) throws CLException;
 
-       public native void enqueueWriteImage(CLImage image, boolean blocking,
+       public void enqueueWriteImage(CLImage image, boolean blocking,
                long[] origin,
                long[] region,
                long row_pitch,
                long slice_pitch,
-               float[] buffer, long buff_offset,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               float[] buffer, int buff_offset,
+               CLEventList wait,
+               CLEventList event) throws CLException {
+               doImageBufferPrimitive(image, blocking, origin, region, row_pitch, slice_pitch,
+                       false,
+                       (seg) -> {
+                               var sb = seg.asByteBuffer().order(ByteOrder.nativeOrder()).asFloatBuffer();
+                               return (off, size) -> sb.put(buffer, buff_offset + off, size);
+                       },
+                       buff_offset - buffer.length,
+                       2,
+                       clEnqueueWriteImage,
+                       wait, event);
+       }
 
        public native void enqueueWriteImage(CLImage image, boolean blocking,
                long[] origin,
@@ -692,25 +1331,163 @@ public class CLCommandQueue extends CLExtendable {
                CLEventList waiters,
                CLEventList events) throws CLException;
 
-       public native ByteBuffer enqueueMapBuffer(CLBuffer buffer, boolean blocking,
-               long flags,
-               long offset,
-               long size,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       static class MapData {
+               MemoryAddress raw;
+               ByteBuffer buffer;
 
-       public native ByteBuffer enqueueMapImage(CLImage image, boolean blocking,
-               long flags,
-               long[] origin,
-               long[] region,
-               long[] image_row_pitch,
-               long[] image_slice_pitch,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+               public MapData(MemoryAddress p, ByteBuffer buffer) {
+                       this.raw = p;
+                       this.buffer = buffer;
+               }
+       }
 
-       public native void enqueueUnmapMemObject(CLMemory mem, ByteBuffer mapped,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       private final ArrayList<MapData> maps = new ArrayList<>();
+
+       private void addMap(MemoryAddress raw, ByteBuffer bb) {
+               synchronized (maps) {
+                       maps.add(new MapData(raw, bb));
+               }
+       }
+
+       private MemoryAddress getMap(ByteBuffer bb) {
+               synchronized (maps) {
+                       // Note this can't use a hashtable as ByteBuffer
+                       // hashes on state like position.
+                       for (int i=0;i<maps.size();i++) {
+                               MapData d = maps.get(i);
+
+                               if (d.buffer == bb) {
+                                       maps.remove(i);
+                                       return d.raw;
+                               }
+                       }
+               }
+               throw new IllegalArgumentException();
+       }
+
+       public ByteBuffer enqueueMapBuffer(CLBuffer buffer, boolean blocking,
+                                          long flags,
+                                          long offset,
+                                          long size,
+                                          CLEventList wait,
+                                          CLEventList event) throws CLException {
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       MemoryAddress cres = frame.alloca(8);
+                       MemoryAddress cmap;
+                       int res;
+
+                       cmap = clEnqueueMapBuffer(addr(), buffer.addr(), blocking ? 1 : 0,
+                                                 flags, offset, size,
+                                                 info.nwait, info.wait, info.event,
+                                                 cres);
+                       res = getInt(cres);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       // Need to map the segment and track it separately
+                       ByteBuffer bb = Memory.ofNative(cmap, size).asByteBuffer();
+
+                       addMap(cmap, bb);
+
+                       info.post(event);
+
+                       return bb;
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       /* There is some scope for improvement in this shittastic interface */
+       public ByteBuffer enqueueMapImage(CLImage image, boolean blocking,
+                                                long flags,
+                                                long[] origin,
+                                                long[] region,
+                                                long[] image_row_pitch,
+                                                long[] image_slice_pitch,
+                                                CLEventList wait,
+                                                CLEventList event) throws CLException {
+               if (origin.length != 3 || region.length != 3)
+                       throw new IllegalArgumentException("origin and region must be 3-dimensional");
+               if (image_row_pitch.length < 1)
+                       throw new IllegalArgumentException("image_row_pitch must contain 1 element");
+               // image_slice_pitch may be null for 2D images, checking this isn't worth it
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       MemoryAddress corigin = toLongV(frame, origin);
+                       MemoryAddress cregion = toLongV(frame, region);
+                       MemoryAddress cstride = frame.alloca(8);
+                       MemoryAddress cslice = frame.alloca(8);
+                       MemoryAddress cres = frame.alloca(8);
+                       MemoryAddress cmap;
+                       long stride, slice;
+                       int res;
+
+                       cmap = clEnqueueMapImage(
+                               addr(), image.addr(), blocking ? 1 : 0,
+                               flags,
+                               corigin, cregion,
+                               cstride, cslice,
+                               info.nwait, info.wait, info.event,
+                               cres);
+                       res = getInt(cres);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       stride = getLong(cstride);
+                       slice = getLong(cslice);
+
+                       image_row_pitch[0] = stride;
+                       if (image_slice_pitch != null)
+                               image_slice_pitch[0] = slice;
+
+                       // These look weird but that's what the docs say
+                       long size = slice == 0
+                                   ?                     stride * region[1] + region[0] // 2D
+                                   : slice * region[2] + stride * region[1] + region[0]; // 3D
+
+                       // Need to map the segment and track it separately
+                       ByteBuffer bb = Memory.ofNative(cmap, size).asByteBuffer();
+
+                       addMap(cmap, bb);
+
+                       info.post(event);
+
+                       return bb;
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       public void enqueueUnmapMemObject(CLMemory mem, ByteBuffer mapped,
+                                         CLEventList wait,
+                                         CLEventList event) throws CLException {
+               MemoryAddress cmap = getMap(mapped);
+
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, wait, event);
+                       int res;
+
+                       res = clEnqueueUnmapMemObject(
+                               addr(), mem.addr(),
+                               cmap,
+                               info.nwait, info.wait, info.event);
+
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(event);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         *
@@ -725,6 +1502,39 @@ public class CLCommandQueue extends CLExtendable {
                CLEventList waiters,
                CLEventList events) throws CLException;
 
+       private MemoryAddress wsToLongV(Allocator frame, long[] ws, int dim) {
+               if (ws != null) {
+                       if (ws.length < dim)
+                               throw new IllegalArgumentException();
+                       return toLongV(frame, ws);
+               } else {
+                       return MemoryAddress.NULL;
+               }
+       }
+
+       static private class EventInfo {
+               final int nwait;
+               final MemoryAddress wait;
+               final MemoryAddress event;
+
+               EventInfo(Allocator frame, CLEventList waiters, CLEventList events) {
+                       nwait = waiters != null ? waiters.size() : 0;
+                       if (nwait > 0) {
+                               wait = frame.alloca(8 * nwait);
+                               for (int i=0;i<nwait;i++)
+                                       Native.setAddr(wait, i, waiters.get(i).addr());
+                       } else {
+                               wait = MemoryAddress.NULL;
+                       }
+                       event = events != null ? frame.alloca(8) : MemoryAddress.NULL;
+               }
+
+               void post(CLEventList events) {
+                       if (events != null)
+                               events.add(resolve(getAddr(event), CLEvent::new));
+               }
+       }
+
        /**
         * Call clEnqueueNDRangeKernel.
         *
@@ -739,12 +1549,33 @@ public class CLCommandQueue extends CLExtendable {
         * @param events
         * @throws CLException
         */
-       public native void enqueueNDRangeKernel(CLKernel kernel, int work_dim,
-               long[] global_offset,
-               long[] global_size,
-               long[] local_size,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       public void enqueueNDRangeKernel(CLKernel kernel,
+                                        int work_dim,
+                                        long[] global_offset,
+                                        long[] global_size,
+                                        long[] local_size,
+                                        CLEventList waiters,
+                                        CLEventList events) throws CLException {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress gwo = wsToLongV(frame, global_offset, work_dim);
+                       MemoryAddress gws = wsToLongV(frame, global_size, work_dim);
+                       MemoryAddress lws = wsToLongV(frame, local_size, work_dim);
+                       EventInfo info = new EventInfo(frame, waiters, events);
+                       int res;
+
+                       res = clEnqueueNDRangeKernel(addr(), kernel.addr(),
+                                                    work_dim, gwo, gws, lws,
+                                                    info.nwait, info.wait, info.event);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(events);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         *
@@ -752,12 +1583,28 @@ public class CLCommandQueue extends CLExtendable {
         * @param waiters
         * @param events
         * @throws CLException
-        * @deprecated as of OpenCL 2.0
+        * x-deprecated as of OpenCL 2.0
         */
-       @Deprecated
-       public native void enqueueTask(CLKernel kernel,
-               CLEventList waiters,
-               CLEventList events) throws CLException;
+       //@Deprecated
+       public void enqueueTask(CLKernel kernel,
+                               CLEventList waiters,
+                               CLEventList events) throws CLException {
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, waiters, events);
+                       int res;
+
+                       res = clEnqueueTask(addr(), kernel.addr(),
+                                           info.nwait, info.wait, info.event);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(events);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Invoke a native kernel.
@@ -769,11 +1616,61 @@ public class CLCommandQueue extends CLExtendable {
         * be replaced by a ByteBuffer in the kernel.
         * @throws CLException
         */
-       public native void enqueueNativeKernel(
+       public void enqueueNativeKernel(
                CLNativeKernel kernel,
                CLEventList waiters,
                CLEventList events,
-               Object... args) throws CLException;
+               Object... args) throws CLException {
+               // This basically just passes the memory objects to opencl, the rest are handled by the lambda.
+               // This means args and mem_list are the same value
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, waiters, events);
+                       MemoryAddress memstage = frame.alloca(8 * args.length);
+                       MemoryAddress memptrs = frame.alloca(8 * args.length);
+                       int nmem = 0;
+                       int res;
+
+                       Object[] save = args.clone();
+
+                       for (Object a: args) {
+                               if (a instanceof CLMemory) {
+                                       setAddr(memstage, nmem, ((CLMemory)a).addr());
+                                       setAddr(memptrs, nmem, memstage.addOffset(nmem * 8));
+                                       nmem++;
+                               }
+                       }
+
+                       Callback<CLNativeKernel> call = Native.resolve(
+                               Call_pv_v.stub((MemoryAddress memargs) -> {
+                                               int xmem = 0;
+
+                                               for (int i=0;i<args.length;i++) {
+                                                       if (args[i] instanceof CLMemory) {
+                                                               MemoryAddress mem = getAddr(memargs, xmem);
+                                                               long size = ((CLMemory)args[i]).getSize();
+
+                                                               save[i] = Memory.ofNative(mem, size).asByteBuffer().order(ByteOrder.nativeOrder());
+                                                               xmem++;
+                                                       }
+                                               }
+
+                                               kernel.invoke(save);
+                                       }),
+                               (p) -> new Callback<>(p, kernel));
+
+                       res = clEnqueueNativeKernel(addr(), call.addr(), memstage, nmem * 8, nmem, memstage, memptrs, info.nwait, info.wait, info.event);
+
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       info.post(events);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+
+       }
 
        /**
         * Enqueues a marker point.
@@ -785,9 +1682,24 @@ public class CLCommandQueue extends CLExtendable {
         * @param events
         * @throws CLException
         */
-       public native void enqueueMarkerWithWaitList(
+       public void enqueueMarkerWithWaitList(
                CLEventList waiters,
-               CLEventList events) throws CLException;
+               CLEventList events) throws CLException {
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, waiters, events);
+                       if (haveAPIVersion(CLPlatform.VERSION_1_2)) {
+                               clEnqueueMarkerWithWaitList(addr(), info.nwait, info.wait, info.event);
+                       } else {
+                               clEnqueueWaitForEvents(addr(), info.nwait, info.wait);
+                               clEnqueueMarker(addr(), info.event);
+                       }
+                       info.post(events);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Enqueues a barrier.
@@ -800,9 +1712,25 @@ public class CLCommandQueue extends CLExtendable {
         * @param events
         * @throws CLException
         */
-       public native void enqueueBarrierWithWaitList(
+       public  void enqueueBarrierWithWaitList(
                CLEventList waiters,
-               CLEventList events) throws CLException;
+               CLEventList events) throws CLException {
+               try (Allocator frame = Memory.stack()) {
+                       EventInfo info = new EventInfo(frame, waiters, events);
+                       if (haveAPIVersion(CLPlatform.VERSION_1_2)) {
+                               clEnqueueBarrierWithWaitList(addr(), info.nwait, info.wait, info.event);
+                       } else {
+                               clEnqueueWaitForEvents(addr(), info.nwait, info.wait);
+                               clEnqueueBarrier(addr());
+                               clEnqueueMarker(addr(), info.event);
+                       }
+                       info.post(events);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Call clEnqueueSVMFree().
@@ -1002,11 +1930,11 @@ public class CLCommandQueue extends CLExtendable {
        }
 
        public CLContext getContext() {
-               return getInfoAny(CTYPE_CONTEXT, CL_QUEUE_CONTEXT);
+               return getInfoAny(CL_QUEUE_CONTEXT, clGetCommandQueueInfo, CLContext::new);
        }
 
        public CLDevice getDevice() {
-               return getInfoAny(CTYPE_DEVICE, CL_QUEUE_DEVICE);
+               return getInfoAny(CL_QUEUE_DEVICE, clGetCommandQueueInfo, CLDevice::new);
        }
 
        public long getProperties() {
@@ -1026,26 +1954,26 @@ public class CLCommandQueue extends CLExtendable {
                return getDevice().platform;
        }
 
-       protected GLSharing getGLSharing() {
-               return getExtension(GLSharing.class, CLPlatform.cl_khr_gl_sharing);
-       }
+       //protected GLSharing getGLSharing() {
+       //      return getExtension(GLSharing.class, CLPlatform.cl_khr_gl_sharing);
+       //}
 
        /*
         Experimental: Alternative interface to extensions.
         */
-       public void enqueueAcquireGLObjects(
-               CLMemory[] mem_objects,
-               CLEventList waiters,
-               CLEventList events) {
-               getGLSharing().enqueueAcquireGLObjects(this, mem_objects, waiters, events);
-       }
-
-       public void enqueueReleaseGLObjects(
-               CLMemory[] mem_objects,
-               CLEventList waiters,
-               CLEventList events) {
-               getGLSharing().enqueueReleaseGLObjects(this, mem_objects, waiters, events);
-       }
+       //public void enqueueAcquireGLObjects(
+       //      CLMemory[] mem_objects,
+       //      CLEventList waiters,
+       //      CLEventList events) {
+       //      getGLSharing().enqueueAcquireGLObjects(this, mem_objects, waiters, events);
+       //}
+
+       //public void enqueueReleaseGLObjects(
+       //      CLMemory[] mem_objects,
+       //      CLEventList waiters,
+       //      CLEventList events) {
+       //      getGLSharing().enqueueReleaseGLObjects(this, mem_objects, waiters, events);
+       //}
 
        /**
         * Invoke task.queue for this queue with no event lists.
index a2d51c3..34d89d0 100644 (file)
  */
 package au.notzed.zcl;
 
-import java.nio.ByteBuffer;
 import static au.notzed.zcl.CL.*;
-import au.notzed.zcl.khr.GLEvent;
-import au.notzed.zcl.khr.GLSharing;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import api.Memory;
+import api.Allocator;
+import api.Native;
+import api.Callback;
+import java.util.stream.Stream;
+
+import java.lang.invoke.MethodHandle;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
 
+import java.util.function.Function;
+import java.util.function.IntFunction;
+
 /**
  * Interface for cl_context
  */
@@ -33,24 +45,34 @@ public class CLContext extends CLExtendable {
        /**
         * If a notify callback is supplied to createContext() then this is used to track the reference.
         */
-       final CLContextNotify notify;
+       final Callback<CLContextNotify> notify;
 
        /**
         * Creates an interface for a native pointer of type cl_context.
         *
         * @param p Native pointer.
         */
-       public CLContext(long p) {
+       public CLContext(MemoryAddress p) {
                super(p);
                this.notify = null;
        }
 
-       CLContext(long p, CLContextNotify notify) {
+       CLContext(MemoryAddress p, Callback<CLContextNotify> notify) {
                super(p);
                this.notify = notify;
        }
 
-       private native static void release(long p);
+       static CLContext create(MemoryAddress p) {
+               return Native.resolve(p, CLContext::new);
+       }
+
+       private static void release(MemoryAddress p) {
+               try {
+                       clReleaseContext(p);
+               } catch (Throwable t) {
+                       t.printStackTrace();
+               }
+       }
 
        @Override
        public String toString() {
@@ -65,8 +87,8 @@ public class CLContext extends CLExtendable {
        }
 
        @Override
-       int getInfoType() {
-               return TYPE_CONTEXT;
+       MethodHandle getInfoFunc() {
+               return clGetContextInfo;
        }
 
        /**
@@ -76,7 +98,7 @@ public class CLContext extends CLExtendable {
         * @return new property
         */
        public static CLContextProperty PLATFORM(CLPlatform platform) {
-               return new CLContextProperty.TagValue(CL.CL_CONTEXT_PLATFORM, platform.getP());
+               return new CLContextProperty.TagValue(CL.CL_CONTEXT_PLATFORM, platform.addr().offset());
        }
 
        /**
@@ -99,7 +121,31 @@ public class CLContext extends CLExtendable {
         * release() should be called when it is no longer needed.
         * @throws CLRuntimeException
         */
-       public static native CLContext createContext(CLContextProperty[] properties, CLDevice[] devices, CLContextNotify notify) throws CLRuntimeException;
+       public static CLContext createContext(CLContextProperty[] properties, CLDevice[] devices, CLContextNotify notify) throws CLRuntimeException {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pprops = CLProperty.toNative(frame, properties);
+                       MemoryAddress pdevs = frame.alloca(devices.length * 8);
+                       MemoryAddress pres = frame.alloca(8);
+                       Callback<CLContextNotify> call = CLContextNotify.call(notify);
+                       MemoryAddress cl;
+                       int res;
+
+                       for (int i=0;i<devices.length;i++)
+                               setAddr(pdevs, i, devices[i].addr());
+
+                       cl = clCreateContext(pprops, devices.length, pdevs, call.addr(), MemoryAddress.NULL, pres);
+                       res = getInt(pres);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return Native.resolve(cl, CLContext::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        public static CLContext createContext(CLContextProperty[] properties, CLDevice[] devices) throws CLRuntimeException {
                return createContext(properties, devices, (String what, ByteBuffer error_info) -> {
@@ -117,7 +163,28 @@ public class CLContext extends CLExtendable {
         * release() should be called when it is no longer needed.
         * @throws CLRuntimeException
         */
-       public static native CLContext createContextFromType(CLContextProperty[] properties, long device_type, CLContextNotify notify) throws CLRuntimeException;
+       public static CLContext createContextFromType(CLContextProperty[] properties, long device_type, CLContextNotify notify) throws CLRuntimeException {
+
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pprops = CLProperty.toNative(frame, properties);
+                       MemoryAddress pres = frame.alloca(8);
+                       MemoryAddress cl;
+                       Callback<CLContextNotify> call = CLContextNotify.call(notify);
+                       int res;
+
+                       cl = clCreateContextFromType(pprops, device_type, call.addr(), MemoryAddress.NULL, pres);
+                       res = getInt(pres);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return Native.resolve(cl, (p) -> new CLContext(p, call));
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clCreateCommandQueue.
@@ -127,10 +194,27 @@ public class CLContext extends CLExtendable {
         * @return Newly created command queue.<p>
         * release() should be called when it is no longer needed.
         * @throws CLRuntimeException
-        * @deprecated as of OpenCL 2.0
+        * deprecated as of OpenCL 2.0
         */
-       @Deprecated
-       native public CLCommandQueue createCommandQueue(CLDevice dev, long properties) throws CLRuntimeException;
+       public CLCommandQueue createCommandQueue(CLDevice dev, long properties) throws CLRuntimeException {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pres = frame.alloca(8);
+                       MemoryAddress q;
+                       int res;
+
+                       q = clCreateCommandQueue(addr(), dev.addr(), properties, pres);
+                       res = getInt(pres);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return Native.resolve(q, CLCommandQueue::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clCreateCommandQueueWithProperties.
@@ -141,7 +225,29 @@ public class CLContext extends CLExtendable {
         * @throws CLRuntimeException
         * @since OpenCL 2.0
         */
-       native public CLCommandQueue createCommandQueue(CLDevice dev, CLQueueProperty[] properties) throws CLRuntimeException;
+       public CLCommandQueue createCommandQueue(CLDevice dev, CLQueueProperty[] properties) throws CLRuntimeException {
+               // Fallback if opencl2 not supported?
+               requireAPIVersion(CLPlatform.VERSION_2_0);
+
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pprops = CLProperty.toNative(frame, properties);
+                       MemoryAddress pres = frame.alloca(8);
+                       MemoryAddress q;
+                       int res;
+
+                       q = clCreateCommandQueueWithProperties(addr(), dev.addr(), pprops, pres);
+                       res = getInt(pres);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return Native.resolve(q, CLCommandQueue::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         *
@@ -150,23 +256,105 @@ public class CLContext extends CLExtendable {
         * @throws CLException
         * @since OpenCL 2.1
         */
-       native public void setDefaultDeviceCommandQueue(CLDevice dev, CLCommandQueue q) throws CLException;
+       public void setDefaultDeviceCommandQueue(CLDevice dev, CLCommandQueue q) throws CLException {
+               requireAPIVersion(CLPlatform.VERSION_2_1);
 
+               try {
+                       int res;
+
+                       res = clSetDefaultDeviceCommandQueue(addr(), dev.addr(), q.addr());
+                       if (res != 0)
+                               throw new CLException(res);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       /* ********************************************************************** */
+
+       /**
+        * Calls clCreateBuffer with an empty host pointer.
+        *
+        * @param flags CL_MEM_* flags.
+        * @param size Size in bytes.
+        * @throws CLRuntimeException
+        */
        public CLBuffer createBuffer(long flags, long size) throws CLRuntimeException {
-               return createBuffer(flags, size, null);
+               return createBuffer(flags, size, (MemorySegment)null);
        }
 
        /**
         * Calls clCreateBuffer.
         *
+        * If flags contains CL_MEM_USE_HOST_PTR then hostp must not
+        * be null.  Currently in this case the CLBuffer must be
+        * explicitly released() on the caller thread.
+        *
         * @param flags CL_MEM_* flags.
         * @param size Size in bytes.
         * @param hostp Optional host memory pointer.
-        * @return Newly allocated buffer.<p>
-        * release() should be called when it is no longer needed.
+        * @return Newly allocated buffer.
         * @throws CLRuntimeException
         */
-       native public CLBuffer createBuffer(long flags, long size, ByteBuffer hostp) throws CLRuntimeException;
+       public CLBuffer createBuffer(long flags, long size, MemorySegment hostseg) throws CLRuntimeException {
+               if (hostseg != null && hostseg.byteSize() < size)
+                       throw new CLRuntimeException(CL_INVALID_HOST_PTR);
+
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pres = frame.alloca(8);
+                       MemoryAddress pbuffer;
+                       int res;
+
+                       pbuffer = clCreateBuffer(addr(), flags, size, addr(hostseg), pres);
+                       res = getInt(pres);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       if (hostseg != null && (flags & CL_MEM_USE_HOST_PTR) != 0)
+                               return resolve(pbuffer, (x) -> new CLBuffer(x, hostseg));
+                       else
+                               return resolve(pbuffer, CLBuffer::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       /**
+        * Calls clCreateBuffer.
+        *
+        * If flags contains CL_MEM_USE_HOST_PTR then hostp must not
+        * be null.  Currently the CLBuffer must be explicitly
+        * released() on the caller thread.
+        *
+        * @param flags CL_MEM_* flags.
+        * @param size Size in bytes.
+        * @param hostp Optional host memory pointer.
+        * @return Newly allocated buffer.
+        * @throws CLRuntimeException
+        */
+       public CLBuffer createBuffer(long flags, long size, ByteBuffer hostp) throws CLRuntimeException {
+               if (hostp != null) {
+                       MemorySegment hostseg = MemorySegment.ofByteBuffer(hostp);
+                       try {
+                               CLBuffer buffer = createBuffer(flags, size, hostseg);
+
+                               if ((flags & CL_MEM_USE_HOST_PTR) != 0)
+                                       hostseg = null;
+
+                               return buffer;
+                       } finally {
+                               if (hostseg != null)
+                                       hostseg.close();
+                       }
+               } else {
+                       return createBuffer(flags, size, (MemorySegment)null);
+               }
+       }
 
        /**
         * Wraps a full buffer.
@@ -192,41 +380,150 @@ public class CLContext extends CLExtendable {
         * @throws CLRuntimeException if the clCreateBuffer fails, or with CL_INVALID_VALUE if CL_MEM_USE_HOST_PTR is specified in flags.
         * @throws NullPointerException if hostp is null.
         */
-       native public CLBuffer createBuffer(long flags, byte[] hostp) throws CLRuntimeException;
+       public CLBuffer createBuffer(long flags, byte[] hostp) throws CLRuntimeException {
+               if ((flags & CL_MEM_USE_HOST_PTR) != 0)
+                       throw new CLRuntimeException(CL_INVALID_VALUE);
+
+               if (hostp == null)
+                       throw new NullPointerException();
 
-       native public CLBuffer createBuffer(long flags, short[] hostp) throws CLRuntimeException;
+               // Must copy.
+               try (MemorySegment mem = MemorySegment.allocateNative(hostp.length, 16)) {
+                       mem.asByteBuffer().order(ByteOrder.nativeOrder()).put(hostp);
+                       return createBuffer(flags, hostp.length, mem);
+               }
+       }
 
-       native public CLBuffer createBuffer(long flags, int[] hostp) throws CLRuntimeException;
+       //native public CLBuffer createBuffer(long flags, short[] hostp) throws CLRuntimeException;
 
-       native public CLBuffer createBuffer(long flags, float[] hostp) throws CLRuntimeException;
+       //native public CLBuffer createBuffer(long flags, int[] hostp) throws CLRuntimeException;
 
-       native public CLBuffer createBuffer(long flags, double[] hostp) throws CLRuntimeException;
+       public CLBuffer createBuffer(long flags, float[] hostp) throws CLRuntimeException {
+               if ((flags & CL_MEM_USE_HOST_PTR) != 0)
+                       throw new CLRuntimeException(CL_INVALID_VALUE);
+
+               if (hostp == null)
+                       throw new NullPointerException();
+
+               // Must copy.
+               try (MemorySegment mem = MemorySegment.allocateNative(hostp.length, 16)) {
+                       mem.asByteBuffer().order(ByteOrder.nativeOrder()).asFloatBuffer().put(hostp);
+                       return createBuffer(flags, hostp.length * 4, mem);
+               }
+       }
+
+       //native public CLBuffer createBuffer(long flags, double[] hostp) throws CLRuntimeException;
+
+       /* ********************************************************************** */
 
        public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc) throws CLRuntimeException, UnsupportedOperationException {
-               return createImage(flags, fmt, desc, (ByteBuffer) null);
+               return createImage(flags, fmt, desc, (MemorySegment) null);
        }
 
        /**
-        * Calls clCreateImage.
+        * Calls clCreateImage, or clCreateImageXD on OpenCL 1.1 or less.
         *
         * @param flags CL_MEM_* flags.
         * @param fmt Image format.
-        * @param desc Image descriptor. For OpenCL 1.2 only CL_MEM_OBJECT_IMAGE2D and CL_MEM_OBJECT_IMAGE3D are allowed.
+        * @param desc Image descriptor. For OpenCL 1.2, only CL_MEM_OBJECT_IMAGE2D and CL_MEM_OBJECT_IMAGE3D are allowed.
         * @param hostp
         * @return Newly allocated image.<p>
         * release() should be called when it is no longer needed.
         * @throws CLRuntimeException
         * @throws UnsupportedOperationException
         */
-       native public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, ByteBuffer hostp) throws CLRuntimeException, UnsupportedOperationException;
+       public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, MemorySegment hostseg) throws CLRuntimeException, UnsupportedOperationException {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress cfmt = CLImageFormat.toNative(frame, fmt);
+                       MemoryAddress cres = frame.alloca(8);
+                       MemoryAddress ci;
+                       int res;
+
+                       // FIXME: perform range checks
+
+                       if (haveAPIVersion(CLPlatform.VERSION_1_2)) {
+                               MemoryAddress cdesc = CLImageDesc.toNative(frame, desc);
+
+                               ci = clCreateImage(addr(), flags, cfmt, cdesc, addr(hostseg), cres);
+                       } else {
+                               switch (desc.imageType) {
+                               case CL_MEM_OBJECT_IMAGE2D:
+                                       ci = clCreateImage2D(addr(), flags, cfmt, desc.imageWidth, desc.imageHeight, desc.imageRowPitch, addr(hostseg), cres);
+                                       break;
+                               case CL_MEM_OBJECT_IMAGE3D:
+                                       ci = clCreateImage3D(addr(), flags, cfmt, desc.imageWidth, desc.imageHeight, desc.imageDepth,
+                                                            desc.imageRowPitch, desc.imageSlicePitch, addr(hostseg), cres);
+                                       break;
+                               default:
+                                       throw new UnsupportedOperationException("Requires OpenCL 1.2");
+                               }
+                       }
+
+                       res = getInt(cres);
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
 
-       native public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, byte[] hostp) throws CLRuntimeException, UnsupportedOperationException;
+                       if (hostseg != null && (flags & CL_MEM_USE_HOST_PTR) != 0)
+                               return resolve(ci, (x) -> new CLImage(x, hostseg));
+                       else
+                               return resolve(ci, CLImage::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, ByteBuffer hostp) throws CLRuntimeException, UnsupportedOperationException {
+               if (hostp != null) {
+                       MemorySegment hostseg = MemorySegment.ofByteBuffer(hostp);
+                       try {
+                               CLImage image = createImage(flags, fmt, desc, hostseg);
 
-       native public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, short[] hostp) throws CLRuntimeException, UnsupportedOperationException;
+                               if ((flags & CL_MEM_USE_HOST_PTR) != 0)
+                                       hostseg = null;
 
-       native public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, int[] hostp) throws CLRuntimeException, UnsupportedOperationException;
+                               return image;
+                       } finally {
+                               if (hostseg != null)
+                                       hostseg.close();
+                       }
+               } else {
+                       return createImage(flags, fmt, desc, (MemorySegment)null);
+               }
+       }
+
+       public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, byte[] hostp) throws CLRuntimeException, UnsupportedOperationException {
+               if ((flags & CL_MEM_USE_HOST_PTR) != 0)
+                       throw new CLRuntimeException(CL_INVALID_VALUE);
+
+               if (hostp == null)
+                       throw new NullPointerException();
+
+               // Must copy.
+               try (MemorySegment mem = MemorySegment.allocateNative(hostp.length, 16)) {
+                       mem.asByteBuffer().order(ByteOrder.nativeOrder()).put(hostp);
+                       return createImage(flags, fmt, desc, mem);
+               }
+       }
 
-       native public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, float[] hostp) throws CLRuntimeException, UnsupportedOperationException;
+       //native public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, short[] hostp) throws CLRuntimeException, UnsupportedOperationException;
+
+       //native public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, int[] hostp) throws CLRuntimeException, UnsupportedOperationException;
+
+       public CLImage createImage(long flags, CLImageFormat fmt, CLImageDesc desc, float[] hostp) throws CLRuntimeException, UnsupportedOperationException {
+               if ((flags & CL_MEM_USE_HOST_PTR) != 0)
+                       throw new CLRuntimeException(CL_INVALID_VALUE);
+
+               if (hostp == null)
+                       throw new NullPointerException();
+
+               // Must copy.
+               try (MemorySegment mem = MemorySegment.allocateNative(hostp.length * 4, 16)) {
+                       mem.asByteBuffer().order(ByteOrder.nativeOrder()).asFloatBuffer().put(hostp);
+                       return createImage(flags, fmt, desc, mem);
+               }
+       }
 
        /**
         * Calls clCreatePipe
@@ -240,7 +537,27 @@ public class CLContext extends CLExtendable {
         * @throws UnsupportedOperationException
         * @since OpenCL 2.0
         */
-       native public CLPipe createPipe(long flags, int packetSize, int maxPackets, CLPipeProperty[] properties) throws CLRuntimeException, UnsupportedOperationException;
+       public CLPipe createPipe(long flags, int packetSize, int maxPackets, CLPipeProperty[] properties) throws CLRuntimeException, UnsupportedOperationException {
+               requireAPIVersion(CLPlatform.VERSION_2_0);
+
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress cprops = CLProperty.toNative(frame, properties);
+                       MemoryAddress cres = frame.alloca(8);
+                       int res;
+                       MemoryAddress cp;
+
+                       cp = clCreatePipe(addr(), flags, packetSize, maxPackets, cprops, cres);
+                       res = getInt(cres);
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return resolve(cp, CLPipe::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clGetSupportedImageFormats.
@@ -250,7 +567,33 @@ public class CLContext extends CLExtendable {
         * @return List of supported image formats.
         * @throws CLRuntimeException
         */
-       native public CLImageFormat[] getSupportedImageFormats(long flags, int type) throws CLRuntimeException;
+       public CLImageFormat[] getSupportedImageFormats(long flags, int type) throws CLRuntimeException {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress cnum = frame.alloca(8);
+                       MemoryAddress list;
+                       int num;
+                       int res;
+
+                       res = clGetSupportedImageFormats(addr(), flags, type, 0, MemoryAddress.NULL, cnum);
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       num = getInt(cnum);
+                       list = frame.alloca(num * 8);
+
+                       res = clGetSupportedImageFormats(addr(), flags, type, num, list, cnum);
+
+                       CLImageFormat[] out = new CLImageFormat[num];
+                       for (int i=0;i<out.length;i++)
+                               out[i] = CLImageFormat.fromNative(getAddr(list, i));
+
+                       return out;
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Allocate shared virtual memory.
@@ -264,7 +607,9 @@ public class CLContext extends CLExtendable {
         * @throws CLRuntimeException
         * @since OpenCL 2.0
         */
-       native public ByteBuffer SVMAlloc(long flags, long size, int alignment) throws CLRuntimeException;
+       public ByteBuffer SVMAlloc(long flags, long size, int alignment) throws CLRuntimeException {
+               throw new UnsupportedOperationException();
+       }
 
        /**
         * Free memory allocated by SVMAlloc. It is up to the caller to ensure the memory is not in use.
@@ -273,7 +618,9 @@ public class CLContext extends CLExtendable {
         * @throws CLRuntimeException
         * @since OpenCL 2.0
         */
-       native public void SVMFree(ByteBuffer mem) throws CLRuntimeException;
+       public void SVMFree(ByteBuffer mem) throws CLRuntimeException {
+               throw new UnsupportedOperationException();
+       }
 
        /**
         * Calls clCreateSampler.
@@ -286,10 +633,27 @@ public class CLContext extends CLExtendable {
         * @return Newly created sampler.<p>
         * release() should be called when it is no longer needed.
         * @throws CLRuntimeException
-        * @deprecated as of OpenCL 2.0
+        * xdeprecated as of OpenCL 2.0
         */
-       @Deprecated
-       native public CLSampler createSampler(boolean norm, int addr_mode, int filter_mode) throws CLRuntimeException;
+       //@Deprecated
+       public CLSampler createSampler(boolean norm, int addr_mode, int filter_mode) throws CLRuntimeException {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress cres = frame.alloca(8);
+                       int res;
+                       MemoryAddress cs;
+
+                       cs = clCreateSampler(addr(), norm ? 1 : 0, addr_mode, filter_mode, cres);
+                       res = getInt(cres);
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return resolve(cs, CLSampler::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clCreateSamplerWithProperties
@@ -299,7 +663,50 @@ public class CLContext extends CLExtendable {
         * @throws CLRuntimeException
         * @since OpenCL 2.0
         */
-       native public CLSampler createSampler(CLSamplerProperty[] props) throws CLRuntimeException;
+       public CLSampler createSampler(CLSamplerProperty[] props) throws CLRuntimeException {
+               // Fallback if opencl2 not supported?
+               requireAPIVersion(CLPlatform.VERSION_2_0);
+
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress cres = frame.alloca(8);
+                       MemoryAddress cprops = CLProperty.toNative(frame, props);
+                       int res;
+                       MemoryAddress cs;
+
+                       cs = clCreateSamplerWithProperties(addr(), cprops, cres);
+                       res = getInt(cres);
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return resolve(cs, CLSampler::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+
+       }
+
+       static long length(byte[][] strings) {
+               long len = 0;
+               for (int i=0;i<strings.length;i++)
+                       len += strings[i].length;
+               return len;
+       }
+
+       static void copy(MemoryAddress addr, byte[][]list) {
+               for (int i=0,k=0;i<list.length;i++) {
+                       byte[] row = list[i];
+
+                       for (int j=0;j<row.length;j++,k++)
+                               setByte(addr, k, row[j]);
+               }
+       }
+
+       static void copy(MemoryAddress addr, byte[]row) {
+               for (int j=0;j<row.length;j++)
+                       setByte(addr, j, row[j]);
+       }
 
        /**
         * Calls clCreateProgramWithSource.
@@ -309,13 +716,40 @@ public class CLContext extends CLExtendable {
         * release() should be called when it is no longer needed or allow for GC cleanup.
         * @throws CLException
         */
-       native public CLProgram createProgramWithSource(byte[]... strings) throws CLException;
+       public CLProgram createProgramWithSource(byte[]... strings) throws CLException {
+               long size = length(strings);
+               try (Allocator frame = Memory.stack();
+                    MemorySegment buffer = MemorySegment.allocateNative(size)) {
+                       MemoryAddress cstring = frame.alloca(8);
+                       MemoryAddress clength = frame.alloca(8);
+                       MemoryAddress cret = frame.alloca(8);
+                       MemoryAddress base = buffer.baseAddress();
+                       MemoryAddress cp;
+                       int res;
+
+                       copy(base, strings);
+                       setAddr(cstring, base);
+                       setLong(clength, size);
+
+                       cp = clCreateProgramWithSource(addr(), 1, cstring, clength, cret);
+
+                       res = getInt(cret);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       return resolve(cp, CLProgram::new);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        public CLProgram createProgramWithSource(String... strings) throws CLException {
                byte[][] bytes = new byte[strings.length][];
-               for (int i = 0; i < strings.length; i++) {
+
+               for (int i = 0; i < strings.length; i++)
                        bytes[i] = strings[i].getBytes(Charset.forName("UTF-8"));
-               }
 
                return createProgramWithSource(bytes);
        }
@@ -340,7 +774,31 @@ public class CLContext extends CLExtendable {
         * @return
         * @throws CLException
         */
-       native public CLProgram createProgramWithIL(byte[] il) throws CLException;
+       public CLProgram createProgramWithIL(byte[] il) throws CLException {
+               requireAPIVersion(CLPlatform.VERSION_2_1);
+
+               try (Allocator frame = Memory.stack();
+                    MemorySegment buffer = MemorySegment.allocateNative(il.length, 1)) {
+                       MemoryAddress cret = frame.alloca(8);
+                       MemoryAddress base = buffer.baseAddress();
+                       MemoryAddress cp;
+                       int res;
+
+                       copy(base, il);
+
+                       cp = clCreateProgramWithIL(addr(), base, il.length, cret);
+
+                       res = getInt(cret);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       return resolve(cp, CLProgram::new);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clCreateProgramWithBinary.
@@ -352,7 +810,47 @@ public class CLContext extends CLExtendable {
         * release() should be called when it is no longer needed.
         * @throws CLException
         */
-       native public CLProgram createProgramWithBinary(CLDevice[] devices, byte[][] binaries, int[] status) throws CLException;
+       public CLProgram createProgramWithBinary(CLDevice[] devices, byte[][] binaries, int[] status) throws CLException {
+               long size = length(binaries);
+               try (Allocator frame = Memory.stack();
+                    MemorySegment buffer = MemorySegment.allocateNative(size, 1)) {
+                       MemoryAddress cdevs = toAddrV(frame, devices);
+                       MemoryAddress barray = frame.alloca(8 * binaries.length);
+                       MemoryAddress larray = frame.alloca(8 * binaries.length);
+                       MemoryAddress cstatus = status != null ? frame.alloca(4 * devices.length) : MemoryAddress.NULL;
+                       MemoryAddress cret = frame.alloca(8);
+                       MemoryAddress base = buffer.baseAddress();
+                       MemoryAddress cp;
+                       int res;
+
+                       for (int i=0, o=0;i<binaries.length;i++) {
+                               MemoryAddress addr = base.addOffset(o);
+
+                               copy(addr, binaries[i]);
+                               setAddr(barray, i, addr);
+
+                               setLong(larray,  i, binaries[i].length);
+                               o += binaries[i].length;
+                       }
+
+                       cp = clCreateProgramWithBinary(addr(), devices.length, cdevs, larray, barray, cstatus, cret);
+
+                       res = getInt(cret);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       if (status != null) {
+                               for (int i=0;i<status.length;i++)
+                                       status[i] = getInt(cstatus, i);
+                       }
+
+                       return resolve(cp, CLProgram::new);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clCreateProgramWithBuiltInKernels.
@@ -364,7 +862,29 @@ public class CLContext extends CLExtendable {
         * @throws UnsupportedOperationException
         * @since OpenCL 1.2
         */
-       native public CLProgram createProgramWithBuiltInKernels(CLDevice[] devices, String names) throws CLException, UnsupportedOperationException;
+       public CLProgram createProgramWithBuiltInKernels(CLDevice[] devices, String names) throws CLException, UnsupportedOperationException {
+               requireAPIVersion(CLPlatform.VERSION_1_2);
+
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress cdevs = toAddrV(frame, devices);
+                       MemoryAddress cnames = toByteV(frame, names);
+                       MemoryAddress cret = frame.alloca(8);
+                       MemoryAddress cp;
+                       int res;
+
+                       cp = clCreateProgramWithBuiltInKernels(addr(), devices.length, cdevs, cnames, cret);
+
+                       res = getInt(cret);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       return resolve(cp, CLProgram::new);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clLinkProgram.
@@ -379,7 +899,31 @@ public class CLContext extends CLExtendable {
         * @throws UnsupportedOperationException
         * @since OpenCL 1.2
         */
-       native public CLProgram linkProgram(CLDevice[] devices, String options, CLProgram[] programs, CLNotify<CLProgram> notify) throws CLException, UnsupportedOperationException;
+       public CLProgram linkProgram(CLDevice[] devices, String options, CLProgram[] programs, CLNotify<CLProgram> notify) throws CLException, UnsupportedOperationException {
+               requireAPIVersion(CLPlatform.VERSION_1_2);
+
+               try (Allocator frame = Memory.stack();
+                    Callback<CLNotify<CLProgram>> cnotify = CLNotify.call(notify, CLProgram::new)) {
+                       MemoryAddress cdevs = toAddrV(frame, devices);
+                       MemoryAddress coptions = toByteV(frame, options);
+                       MemoryAddress cprogs = toAddrV(frame, programs);
+                       MemoryAddress cret = frame.alloca(8);
+                       MemoryAddress cp;
+                       int res;
+
+                       cp = clLinkProgram(addr(), devices.length, cdevs, coptions, programs.length, cprogs, cnotify.addr(), MemoryAddress.NULL, cret);
+
+                       res = getInt(cret);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       return resolve(cp, CLProgram::new);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clCreateUserEvent.
@@ -389,7 +933,27 @@ public class CLContext extends CLExtendable {
         * @throws CLRuntimeException
         * @since OpenCL 1.1
         */
-       native public CLEvent createUserEvent() throws CLRuntimeException;
+       public CLEvent createUserEvent() throws CLException {
+               requireAPIVersion(CLPlatform.VERSION_1_1);
+
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress cret = frame.alloca(8);
+                       MemoryAddress ce;
+                       int res;
+
+                       ce = clCreateUserEvent(addr(), cret);
+
+                       res = getInt(cret);
+                       if (res != 0)
+                               throw new CLException(res);
+
+                       return resolve(ce, CLEvent::new);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * gets CL_CONTEXT_NUM_DEVICES.
@@ -406,7 +970,7 @@ public class CLContext extends CLExtendable {
         * @return List of devices.
         */
        public CLDevice[] getDevices() {
-               return getInfoAnyV(CTYPE_DEVICE, CL_CONTEXT_DEVICES);
+               return getInfoAnyV(CL_CONTEXT_DEVICES, clGetContextInfo, CLDevice::new, CLDevice[]::new);
        }
 
        /**
@@ -414,45 +978,48 @@ public class CLContext extends CLExtendable {
         *
         * @return List of properties used at create time.
         */
-       public native CLContextProperty[] getProperties();
+       public CLContextProperty[] getProperties() {
+               return getInfoPropertyV(CL_CONTEXT_PROPERTIES, clGetContextInfo, CLContextProperty.TagValue::new, CLContextProperty[]::new);
+       }
 
        @Override
        protected CLPlatform initPlatform() {
                return getDevices()[0].platform;
        }
 
-       protected GLSharing getGLSharing() {
-               return getExtension(GLSharing.class, CLPlatform.cl_khr_gl_sharing);
-       }
+       //protected GLSharing getGLSharing() {
+       //      return getExtension(GLSharing.class, CLPlatform.cl_khr_gl_sharing);
+       //}
 
-       protected GLEvent getGLEvent() {
-               return getExtension(GLEvent.class, CLPlatform.cl_khr_gl_event);
-       }
+       //protected GLEvent getGLEvent() {
+       //      return getExtension(GLEvent.class, CLPlatform.cl_khr_gl_event);
+       //}
 
        /*
         Experimental: extension interface mechanism
         */
-       public CLBuffer createFromGLBuffer(
-               long flags,
-               int bufobj) {
-               return getGLSharing().createFromGLBuffer(this, flags, bufobj);
-       }
 
-       public CLImage createFromGLTexture(
-               long flags /* flags */,
-               int target /* target */,
-               int miplevel /* miplevel */,
-               int texture /* texture */) {
-               return getGLSharing().createFromGLTexture(this, flags, target, miplevel, texture);
-       }
+       // public CLBuffer createFromGLBuffer(
+       //      long flags,
+       //      int bufobj) {
+       //      return getGLSharing().createFromGLBuffer(this, flags, bufobj);
+       // }
 
-       public CLImage createFromGLRenderbuffer(
-               long flags /* flags */,
-               int renderbuffer /* renderbuffer */) {
-               return getGLSharing().createFromGLRenderbuffer(this, flags, renderbuffer);
-       }
+       // public CLImage createFromGLTexture(
+       //      long flags /* flags */,
+       //      int target /* target */,
+       //      int miplevel /* miplevel */,
+       //      int texture /* texture */) {
+       //      return getGLSharing().createFromGLTexture(this, flags, target, miplevel, texture);
+       // }
 
-       public CLEvent createEventFromGLsync(long glsync) {
-               return getGLEvent().clCreateEventFromGLsync(this, glsync);
-       }
+       // public CLImage createFromGLRenderbuffer(
+       //      long flags /* flags */,
+       //      int renderbuffer /* renderbuffer */) {
+       //      return getGLSharing().createFromGLRenderbuffer(this, flags, renderbuffer);
+       // }
+
+       // public CLEvent createEventFromGLsync(long glsync) {
+       //      return getGLEvent().clCreateEventFromGLsync(this, glsync);
+       // }
 }
index 8c3a304..e8f18f7 100644 (file)
 package au.notzed.zcl;
 
 import java.nio.ByteBuffer;
+import java.util.function.Function;
+import jdk.incubator.foreign.MemoryAddress;
+import jdk.incubator.foreign.MemorySegment;
+import api.Native;
+import api.Callback;
+import api.Memory;
 
 /**
  * Callback for CLContext.createContext*()
@@ -25,4 +31,19 @@ public interface CLContextNotify {
 
        public void notify(String what, ByteBuffer error_info);
 
+       @SuppressWarnings("unchecked")
+       static Callback<CLContextNotify> call(CLContextNotify notify) {
+               if (notify != null) {
+                       return Native.resolve(
+                               Call_pBpvJpv_v.stub((cwhat, cinfo, cinfolen, dummy) -> {
+                                               MemorySegment seg = Memory.ofNative(cinfo, cinfolen);
+                                               notify.notify(Native.toString(cwhat), seg.asByteBuffer());
+                                       }),
+                               (p) -> new Callback<>(p, notify));
+               } else {
+                       return Callback.NULL;
+               }
+       }
+
+
 }
index 37dc9fb..f6e474c 100644 (file)
  */
 package au.notzed.zcl;
 
+import api.Native;
+import java.lang.invoke.MethodHandle;
+import java.util.function.Function;
+import jdk.incubator.foreign.*;
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
 
 /**
  * Interface for cl_device_id.
@@ -28,11 +33,18 @@ public class CLDevice extends CLExtendable {
         *
         * @param p Native pointer.
         */
-       public CLDevice(long p) {
+       public CLDevice(MemoryAddress p) {
                super(p);
        }
 
-       private native static void release(long p);
+       private static void release(MemoryAddress p) {
+               try {
+                       clReleaseDevice(p);
+               } catch (Throwable t) {
+               }
+       }
+
+       //private native static void release(long p);
 
        @Override
        public String toString() {
@@ -40,8 +52,8 @@ public class CLDevice extends CLExtendable {
        }
 
        @Override
-       int getInfoType() {
-               return TYPE_DEVICE;
+       MethodHandle getInfoFunc() {
+               return clGetDeviceInfo;
        }
 
        @Override
@@ -55,7 +67,7 @@ public class CLDevice extends CLExtendable {
         * @param times { device_timestamp, host_timestamp }
         * @since OpenCL 2.1
         */
-       public native void getDeviceAndHostTimer(long[] times);
+       //public native void getDeviceAndHostTimer(long[] times);
 
        /**
         * Gets device view of host clock.
@@ -63,7 +75,7 @@ public class CLDevice extends CLExtendable {
         * @return host_timestamp.
         * @since OpenCN 2.1
         */
-       public native long getHostTimer();
+       //public native long getHostTimer();
 
        /**
         * Create a property representing CL_DEVICE_PARTITION_EQUALLY.
@@ -107,7 +119,7 @@ public class CLDevice extends CLExtendable {
         * @throws CLException
         * @since OpenCL 1.2
         */
-       public native CLDevice[] createSubDevices(CLDeviceProperty[] properties, int num_devices) throws CLException, UnsupportedOperationException;
+       //public native CLDevice[] createSubDevices(CLDeviceProperty[] properties, int num_devices) throws CLException, UnsupportedOperationException;
 
        /**
         * get CL_DEVICE_TYPE
@@ -349,7 +361,7 @@ public class CLDevice extends CLExtendable {
        }
 
        public CLPlatform getPlatform() {
-               return getInfoAny(CTYPE_PLATFORM, CL_DEVICE_PLATFORM);
+               return getInfoAny(CL_DEVICE_PLATFORM, clGetDeviceInfo, CLPlatform::new);
        }
 
        public String getName() {
@@ -389,22 +401,22 @@ public class CLDevice extends CLExtendable {
        }
 
        public CLDevice getParentDevice() {
-               return getInfoAny(CTYPE_DEVICE, CL_DEVICE_PARENT_DEVICE);
+               return getInfoAny(CL_DEVICE_PARENT_DEVICE, clGetDeviceInfo, CLDevice::new);
        }
 
        public int getPartitionMaxSubDevices() {
                return getInfoInt(CL_DEVICE_PARTITION_MAX_SUB_DEVICES);
        }
 
-       public native CLDeviceProperty[] getPartitionProperties();
+       //public native CLDeviceProperty[] getPartitionProperties();
 
        public long getPartitionAffinityDomain() {
                return getInfoLong(CL_DEVICE_PARTITION_AFFINITY_DOMAIN);
        }
 
-       public native CLDeviceProperty[] getPartitionType();
+       //public native CLDeviceProperty[] getPartitionType();
 
-       public static CLDevice[] newArray(int n) {
-               return new CLDevice[n];
-       }
+       //public static CLDevice[] newArray(int n) {
+       //      return new CLDevice[n];
+       //}
 }
index 4d1d0b4..f3f1afb 100644 (file)
@@ -16,6 +16,9 @@
  */
 package au.notzed.zcl;
 
+import api.Native;
+import jdk.incubator.foreign.MemoryAddress;
+
 /**
  * Properties for CLDevice sub-device creation.
  *
@@ -62,6 +65,14 @@ public interface CLDeviceProperty extends CLProperty {
                        dst[o++] = CL.CL_DEVICE_PARTITION_BY_COUNTS_LIST_END;
                        return o;
                }
+
+               public int toLong(MemoryAddress dst, int o) {
+                       Native.setLong(dst, o++, CL.CL_DEVICE_PARTITION_BY_COUNTS);
+                       for (int c : counts)
+                               Native.setLong(dst, o++, c);
+                       Native.setLong(dst, o++, CL.CL_DEVICE_PARTITION_BY_COUNTS_LIST_END);
+                       return o;
+               }
        }
 
 }
index f8dcb60..6e63126 100644 (file)
  */
 package au.notzed.zcl;
 
+import jdk.incubator.foreign.*;
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
+import api.Native;
+import api.Callback;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Interface for cl_event.
  */
 public class CLEvent extends CLObject {
 
+       /**
+        * This is used to retain a reference for any callback set
+        */
+       Callback<CLEventNotify> callback;
+
        /**
         * Create an interface for a native pointer of type cl_event.
         *
         * @param p Native pointer.
         */
-       public CLEvent(long p) {
+       public CLEvent(MemoryAddress p) {
                super(p);
        }
 
-       private native static void release(long p);
+       public static CLEvent create(MemoryAddress p) {
+               return Native.resolve(p, CLEvent::new);
+       }
+
+       private static void release(MemoryAddress p) {
+               try {
+                       System.err.printf("** release event %016x\n", api.Memory.toLong(p));
+                       clReleaseEvent(p);
+               } catch (Throwable t) {
+               }
+       }
+
+       public void release() {
+               Native.release(callback);
+               callback = null;
+               super.release();
+       }
 
        @Override
-       int getInfoType() {
-               return TYPE_EVENT;
+       MethodHandle getInfoFunc() {
+               return clGetEventInfo;
        }
 
        /**
@@ -48,7 +74,20 @@ public class CLEvent extends CLObject {
         * @throws CLRuntimeException
         * @since OpenCL 1.1
         */
-       public native void setUserEventStatus(int status) throws CLRuntimeException;
+       public void setUserEventStatus(int status) throws CLRuntimeException {
+               // avoid platform lookup for costs
+               //requiredAPIVersion(CLPlatform.VERSION_1_1);
+               try {
+                       int res = clSetUserEventStatus(addr(), status);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Call clSetEventCallback(type, notify).
@@ -58,7 +97,28 @@ public class CLEvent extends CLObject {
         * @throws CLRuntimeException
         * @since OpenCL 1.1
         */
-       public native void setEventCallback(int type, CLEventNotify notify) throws CLRuntimeException;
+       public void setEventCallback(int type, CLEventNotify notify) throws CLRuntimeException {
+               //requiredAPIVersion(CLPlatform.VERSION_1_1);
+
+               Native.release(callback);
+
+               if (notify != null) {
+                       callback = CLEventNotify.call(notify);
+
+                       try {
+                               int res = clSetEventCallback(addr(), type, callback.addr(), MemoryAddress.NULL);
+
+                               if (res != 0)
+                                       throw new CLRuntimeException(res);
+                       } catch (RuntimeException | Error t) {
+                               throw t;
+                       } catch (Throwable t) {
+                               throw new RuntimeException(t);
+                       }
+               } else {
+                       callback = null;
+               }
+       }
 
        /**
         * Get CL_EVENT_COMMAND_QUEUE.
@@ -68,7 +128,7 @@ public class CLEvent extends CLObject {
         * @return
         */
        public CLCommandQueue getCommandQueue() {
-               return getInfoAny(CTYPE_COMMAND_QUEUE, CL_EVENT_COMMAND_QUEUE);
+               return getInfoAny(CL_EVENT_COMMAND_QUEUE, clGetEventInfo, CLCommandQueue::new);
        }
 
        /**
@@ -79,7 +139,7 @@ public class CLEvent extends CLObject {
         * @return
         */
        public CLContext getContext() {
-               return getInfoAny(CTYPE_CONTEXT, CL_EVENT_CONTEXT);
+               return getInfoAny(CL_EVENT_CONTEXT, clGetEventInfo, CLContext::new);
        }
 
        /**
@@ -103,22 +163,22 @@ public class CLEvent extends CLObject {
        }
 
        public long getProfilingCommandQueued() {
-               return getInfoLong(TYPE_EVENT_PROFILING, CL_PROFILING_COMMAND_QUEUED);
+               return getInfoLong(CL_PROFILING_COMMAND_QUEUED, clGetEventProfilingInfo);
        }
 
        public long getProfilingCommandSubmit() {
-               return getInfoLong(TYPE_EVENT_PROFILING, CL_PROFILING_COMMAND_SUBMIT);
+               return getInfoLong(CL_PROFILING_COMMAND_SUBMIT, clGetEventProfilingInfo);
        }
 
        public long getProfilingCommandStart() {
-               return getInfoLong(TYPE_EVENT_PROFILING, CL_PROFILING_COMMAND_START);
+               return getInfoLong(CL_PROFILING_COMMAND_START, clGetEventProfilingInfo);
        }
 
        public long getProfilingCommandEnd() {
-               return getInfoLong(TYPE_EVENT_PROFILING, CL_PROFILING_COMMAND_END);
+               return getInfoLong(CL_PROFILING_COMMAND_END, clGetEventProfilingInfo);
        }
 
        public long getProfilingCommandComplete() {
-               return getInfoLong(TYPE_EVENT_PROFILING, CL_PROFILING_COMMAND_COMPLETE);
+               return getInfoLong(CL_PROFILING_COMMAND_COMPLETE, clGetEventProfilingInfo);
        }
 }
index 96f6c5d..bb38677 100644 (file)
  */
 package au.notzed.zcl;
 
+import jdk.incubator.foreign.MemoryAddress;
+import api.Memory;
+import api.Allocator;
+import api.Native;
+import static au.notzed.zcl.CLLib.*;
+
 /**
  * Manages a list of cl_events.
  * <p>
@@ -37,10 +43,6 @@ package au.notzed.zcl;
  */
 public class CLEventList {
 
-       /**
-        * C-accessible copy of jevets[i].p
-        */
-       final long[] events;
        /**
         * Event references.
         */
@@ -53,7 +55,6 @@ public class CLEventList {
         * @param capacity Sets the event list capacity. This
         */
        public CLEventList(int capacity) {
-               this.events = new long[capacity];
                this.jevents = new CLEvent[capacity];
        }
 
@@ -65,7 +66,6 @@ public class CLEventList {
        public void reset() {
                for (int i = 0; i < index; i++) {
                        jevents[i] = null;
-                       events[i] = 0;
                }
                index = 0;
        }
@@ -86,19 +86,9 @@ public class CLEventList {
         * @param event
         */
        public void add(CLEvent event) {
-               events[index] = event.getP();
                jevents[index++] = event;
        }
 
-       /**
-        * Interface for JNI to add an event after a successful enqueue operation.
-        *
-        * @param eid
-        */
-       private void add(long eid) {
-               add(CLObject.resolve(CLEvent.class, eid));
-       }
-
        /**
         * Get the number of active events.
         *
@@ -108,10 +98,38 @@ public class CLEventList {
                return index;
        }
 
+       static MemoryAddress toWaitList(Allocator frame, CLEventList list) {
+               if (list != null) {
+                       MemoryAddress addr = frame.alloca(list.index * 8);
+
+                       for (int i=0;i<list.index;i++)
+                               Native.setAddr(addr, i, list.jevents[i].addr());
+
+                       return addr;
+               } else {
+                       return MemoryAddress.NULL;
+               }
+       }
+
        /**
         * Calls clWaitForEvents with all active events in this list.
         *
         * @throws CLException
         */
-       public native void waitForEvents() throws CLException;
+       public void waitForEvents() throws CLException {
+               if (size() > 0) {
+                       try (Allocator frame = Memory.stack()) {
+                               MemoryAddress events = toWaitList(frame, this);
+                               int res;
+
+                               res = clWaitForEvents(size(), events);
+                               if (res != 0)
+                                       throw new CLException(res);
+                       } catch (CLException | RuntimeException | Error t) {
+                               throw t;
+                       } catch (Throwable t) {
+                               throw new RuntimeException(t);
+                       }
+               }
+       }
 }
index 1c793a1..95331d1 100644 (file)
  */
 package au.notzed.zcl;
 
+import api.Callback;
+import api.Native;
+
 /**
  * Callback for CLEvent.
  */
+@FunctionalInterface
 public interface CLEventNotify {
 
        /**
@@ -28,4 +32,15 @@ public interface CLEventNotify {
         * @param status status.
         */
        public void notify(CLEvent event, int status);
+
+       @SuppressWarnings("unchecked")
+       static Callback<CLEventNotify> call(CLEventNotify notify) {
+               if (notify != null) {
+                       return Native.resolve(
+                               Call_pLIpv_v.stub((cevent, status, dummy) -> notify.notify(Native.resolve(cevent, CLEvent::new), status)),
+                               (p) -> new Callback<>(p, notify));
+               } else {
+                       return Callback.NULL;
+               }
+       }
 }
index fccafe9..fd6a922 100644 (file)
-/**
- * *****************************************************************************
- * Copyright (c) 2008 - 2012 The Khronos Group Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and/or associated documentation files (the "Materials"), to
- * deal in the Materials without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Materials, and to permit persons to whom the Materials are
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Materials.
- *
- * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN
- * THE MATERIALS.
- * ****************************************************************************
- */
+
 package au.notzed.zcl;
 
-/**
- * Exception for OpenCL error values.
- */
 public class CLException extends Exception {
+       int res;
 
-       int id;
-
-       public CLException(int id) {
-               this.id = id;
-       }
-
-       /**
-        * Get the error code.
-        *
-        * @return OpenCL error code.
-        * @see #codeToError
-        */
-       public int getID() {
-               return id;
+       public CLException() {
        }
 
-       @Override
-       public String getMessage() {
-               return String.format("Error (%d): '%s'", id, codeToError(id));
-       }
-
-       /**
-        * Convert the error code to a description.
-        *
-        * @param code
-        * @return
-        */
-       public static String codeToError(int code) {
-               switch (code) {
-               case CL.CL_SUCCESS:
-                       return "CL_SUCCESS";
-               case CL.CL_DEVICE_NOT_FOUND:
-                       return "CL_DEVICE_NOT_FOUND";
-               case CL.CL_DEVICE_NOT_AVAILABLE:
-                       return "CL_DEVICE_NOT_AVAILABLE";
-               case CL.CL_COMPILER_NOT_AVAILABLE:
-                       return "CL_COMPILER_NOT_AVAILABLE";
-               case CL.CL_MEM_OBJECT_ALLOCATION_FAILURE:
-                       return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
-               case CL.CL_OUT_OF_RESOURCES:
-                       return "CL_OUT_OF_RESOURCES";
-               case CL.CL_OUT_OF_HOST_MEMORY:
-                       return "CL_OUT_OF_HOST_MEMORY";
-               case CL.CL_PROFILING_INFO_NOT_AVAILABLE:
-                       return "CL_PROFILING_INFO_NOT_AVAILABLE";
-               case CL.CL_MEM_COPY_OVERLAP:
-                       return "CL_MEM_COPY_OVERLAP";
-               case CL.CL_IMAGE_FORMAT_MISMATCH:
-                       return "CL_IMAGE_FORMAT_MISMATCH";
-               case CL.CL_IMAGE_FORMAT_NOT_SUPPORTED:
-                       return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
-               case CL.CL_BUILD_PROGRAM_FAILURE:
-                       return "CL_BUILD_PROGRAM_FAILURE";
-               case CL.CL_MAP_FAILURE:
-                       return "CL_MAP_FAILURE";
-               case CL.CL_MISALIGNED_SUB_BUFFER_OFFSET:
-                       return "CL_MISALIGNED_SUB_BUFFER_OFFSET";
-               case CL.CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST:
-                       return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
-               case CL.CL_COMPILE_PROGRAM_FAILURE:
-                       return "CL_COMPILE_PROGRAM_FAILURE";
-               case CL.CL_LINKER_NOT_AVAILABLE:
-                       return "CL_LINKER_NOT_AVAILABLE";
-               case CL.CL_LINK_PROGRAM_FAILURE:
-                       return "CL_LINK_PROGRAM_FAILURE";
-               case CL.CL_DEVICE_PARTITION_FAILED:
-                       return "CL_DEVICE_PARTITION_FAILED";
-               case CL.CL_KERNEL_ARG_INFO_NOT_AVAILABLE:
-                       return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE";
-
-               case CL.CL_INVALID_VALUE:
-                       return "CL_INVALID_VALUE";
-               case CL.CL_INVALID_DEVICE_TYPE:
-                       return "CL_INVALID_DEVICE_TYPE";
-               case CL.CL_INVALID_PLATFORM:
-                       return "CL_INVALID_PLATFORM";
-               case CL.CL_INVALID_DEVICE:
-                       return "CL_INVALID_DEVICE";
-               case CL.CL_INVALID_CONTEXT:
-                       return "CL_INVALID_CONTEXT";
-               case CL.CL_INVALID_QUEUE_PROPERTIES:
-                       return "CL_INVALID_QUEUE_PROPERTIES";
-               case CL.CL_INVALID_COMMAND_QUEUE:
-                       return "CL_INVALID_COMMAND_QUEUE";
-               case CL.CL_INVALID_HOST_PTR:
-                       return "CL_INVALID_HOST_PTR";
-               case CL.CL_INVALID_MEM_OBJECT:
-                       return "CL_INVALID_MEM_OBJECT";
-               case CL.CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
-                       return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
-               case CL.CL_INVALID_IMAGE_SIZE:
-                       return "CL_INVALID_IMAGE_SIZE";
-               case CL.CL_INVALID_SAMPLER:
-                       return "CL_INVALID_SAMPLER";
-               case CL.CL_INVALID_BINARY:
-                       return "CL_INVALID_BINARY";
-               case CL.CL_INVALID_BUILD_OPTIONS:
-                       return "CL_INVALID_BUILD_OPTIONS";
-               case CL.CL_INVALID_PROGRAM:
-                       return "CL_INVALID_PROGRAM";
-               case CL.CL_INVALID_PROGRAM_EXECUTABLE:
-                       return "CL_INVALID_PROGRAM_EXECUTABLE";
-               case CL.CL_INVALID_KERNEL_NAME:
-                       return "CL_INVALID_KERNEL_NAME";
-               case CL.CL_INVALID_KERNEL_DEFINITION:
-                       return "CL_INVALID_KERNEL_DEFINITION";
-               case CL.CL_INVALID_KERNEL:
-                       return "CL_INVALID_KERNEL";
-               case CL.CL_INVALID_ARG_INDEX:
-                       return "CL_INVALID_ARG_INDEX";
-               case CL.CL_INVALID_ARG_VALUE:
-                       return "CL_INVALID_ARG_VALUE";
-               case CL.CL_INVALID_ARG_SIZE:
-                       return "CL_INVALID_ARG_SIZE";
-               case CL.CL_INVALID_KERNEL_ARGS:
-                       return "CL_INVALID_KERNEL_ARGS";
-               case CL.CL_INVALID_WORK_DIMENSION:
-                       return "CL_INVALID_WORK_DIMENSION";
-               case CL.CL_INVALID_WORK_GROUP_SIZE:
-                       return "CL_INVALID_WORK_GROUP_SIZE";
-               case CL.CL_INVALID_WORK_ITEM_SIZE:
-                       return "CL_INVALID_WORK_ITEM_SIZE";
-               case CL.CL_INVALID_GLOBAL_OFFSET:
-                       return "CL_INVALID_GLOBAL_OFFSET";
-               case CL.CL_INVALID_EVENT_WAIT_LIST:
-                       return "CL_INVALID_EVENT_WAIT_LIST";
-               case CL.CL_INVALID_EVENT:
-                       return "CL_INVALID_EVENT";
-               case CL.CL_INVALID_OPERATION:
-                       return "CL_INVALID_OPERATION";
-               case CL.CL_INVALID_GL_OBJECT:
-                       return "CL_INVALID_GL_OBJECT";
-               case CL.CL_INVALID_BUFFER_SIZE:
-                       return "CL_INVALID_BUFFER_SIZE";
-               case CL.CL_INVALID_MIP_LEVEL:
-                       return "CL_INVALID_MIP_LEVEL";
-               case CL.CL_INVALID_GLOBAL_WORK_SIZE:
-                       return "CL_INVALID_GLOBAL_WORK_SIZE";
-               case CL.CL_INVALID_PROPERTY:
-                       return "CL_INVALID_PROPERTY";
-               case CL.CL_INVALID_IMAGE_DESCRIPTOR:
-                       return "CL_INVALID_IMAGE_DESCRIPTOR";
-               case CL.CL_INVALID_COMPILER_OPTIONS:
-                       return "CL_INVALID_COMPILER_OPTIONS";
-               case CL.CL_INVALID_LINKER_OPTIONS:
-                       return "CL_INVALID_LINKER_OPTIONS";
-               case CL.CL_INVALID_DEVICE_PARTITION_COUNT:
-                       return "CL_INVALID_DEVICE_PARTITION_COUNT";
-               default:
-                       return "Unknown error";
-               }
+       public CLException(int res) {
+               this.res = res;
        }
 }
index 85e073e..6686295 100644 (file)
@@ -16,6 +16,8 @@
  */
 package au.notzed.zcl;
 
+import jdk.incubator.foreign.MemoryAddress;
+
 /**
  * Extendable object. These keep track of the platform and api revision to be
  * able to lookup extension pointers efficiently.
@@ -28,7 +30,7 @@ public abstract class CLExtendable extends CLObject {
         */
        final int apiVersion;
 
-       public CLExtendable(long p) {
+       public CLExtendable(MemoryAddress p) {
                super(p);
 
                platform = initPlatform();
@@ -51,6 +53,15 @@ public abstract class CLExtendable extends CLObject {
                return apiVersion;
        }
 
+       public void requireAPIVersion(int version) throws UnsupportedOperationException {
+               if (apiVersion < version)
+                       throw new UnsupportedOperationException("Requires version " + ((apiVersion >> 8) & 0xff) + "." + (apiVersion & 0xff));
+       }
+
+       public boolean haveAPIVersion(int version) {
+               return apiVersion >= version;
+       }
+
        /**
         * Retrieve an extension interface for this object.Used by implementors of
         * CLExtenable.
@@ -61,6 +72,7 @@ public abstract class CLExtendable extends CLObject {
         * @return
         */
        protected <T extends CLExtension> T getExtension(Class<T> klass, int id) {
-               return platform.getExtension(klass, id);
+               //return platform.getExtension(klass, id);
+               return null;
        }
 }
index 16e4520..e4e165e 100644 (file)
@@ -16,6 +16,9 @@
  */
 package au.notzed.zcl;
 
+import jdk.incubator.foreign.MemoryAddress;
+import java.lang.invoke.MethodHandle;
+
 /**
  * Experimental code for extension support.
  * <p>
@@ -30,15 +33,15 @@ package au.notzed.zcl;
  */
 public abstract class CLExtension extends CLObject {
 
-       protected CLExtension(long p) {
+       protected CLExtension(MemoryAddress p) {
                super(p);
        }
 
        public abstract String getName();
 
        @Override
-       int getInfoType() {
+       MethodHandle getInfoFunc() {
                throw new UnsupportedOperationException();
        }
-       
+
 }
index b4117fb..60d4509 100644 (file)
 package au.notzed.zcl;
 
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import api.Native;
+
+//import static au.au.notzed.zcl.CL.*;
 import java.nio.ByteBuffer;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Interface for cl_image.
@@ -31,21 +37,28 @@ public class CLImage<T> extends CLMemory {
         * image object.
         *
         * @param p Native pointer.
+        * @param seg A segment backing the image on the host.
         */
-       public CLImage(long p) {
-               super(p);
+       public CLImage(MemoryAddress p) {
+               this(p, null);
+       }
+
+       public CLImage(MemoryAddress p, MemorySegment seg) {
+               super(p, seg);
        }
 
-       static void release(long p) {
+       static void release(MemoryAddress p) {
                CLMemory.release(p);
        }
 
        @Override
-       int getInfoType() {
-               return TYPE_IMAGE;
+       MethodHandle getInfoFunc() {
+               return clGetImageInfo;
        }
 
-       public native CLImageFormat getFormat();
+       public CLImageFormat getFormat() {
+               return getInfoJava(CL_IMAGE_BUFFER, clGetImageInfo, CLImageFormat::fromNative);
+       }
 
        public long getElementSize() {
                return getInfoSizeT(CL_IMAGE_ELEMENT_SIZE);
@@ -76,7 +89,7 @@ public class CLImage<T> extends CLMemory {
        }
 
        public CLBuffer getBuffer() {
-               return getInfoAny(CTYPE_BUFFER, CL_IMAGE_BUFFER);
+               return getInfoAny(CL_IMAGE_BUFFER, clGetImageInfo, CLBuffer::new);
        }
 
        public int getNumMipLevels() {
@@ -89,7 +102,7 @@ public class CLImage<T> extends CLMemory {
 
        @Override
        public String toString() {
-               return String.format("[%s: %dx%dx%d  0x%x]", getClass().getSimpleName(), getWidth(), getHeight(), getDepth(), getP());
+               return String.format("[%s: %dx%dx%d  0x%x]", getClass().getSimpleName(), getWidth(), getHeight(), getDepth(), addr().offset());
        }
 
        /**
index aacc985..f12e299 100644 (file)
  */
 package au.notzed.zcl;
 
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Allocator;
+
 /**
  * Holder for cl_image_desc equivalent.
+ * <h2>panama notes</h2>
+   To maintain compatability with the
+ *  previous api this remains as a simple pojo and marshalling is
+ *  done as required.
+<p>
+This also means it doesn't have to deal with allocation and deallocation and so on.
  */
 public class CLImageDesc {
 
        public int imageType;
-       public int imageWidth;
-       public int imageHeight;
-       public int imageDepth;
-       public int imageArraySize;
-       public int imageRowPitch;
-       public int imageSlicePitch;
-       public int numMipLevels;
-       public int numSamples;
+       public long imageWidth;
+       public long imageHeight;
+       public long imageDepth;
+       public long imageArraySize;
+       public long imageRowPitch;
+       public long imageSlicePitch;
+       public long numMipLevels;
+       public long numSamples;
        public CLMemory memObject;
 
        public CLImageDesc() {
        }
 
-       public CLImageDesc(int imageType, int imageWidth, int imageHeight, int imageDepth, int imageArraySize, int imageRowPitch, int imageSlicePitch, int numMipLevels, int numSamples, CLMemory memObject) {
+       public CLImageDesc(int imageType, long imageWidth, long imageHeight, long imageDepth, long imageArraySize, long imageRowPitch, long imageSlicePitch, long numMipLevels, long numSamples, CLMemory memObject) {
                this.imageType = imageType;
                this.imageWidth = imageWidth;
                this.imageHeight = imageHeight;
@@ -70,4 +80,35 @@ public class CLImageDesc {
        public static CLImageDesc create2D(int w, int h, int count) {
                return new CLImageDesc(CL.CL_MEM_OBJECT_IMAGE2D_ARRAY, w, h, 1, count, 0, 0, 0, 0, null);
        }
+
+
+       /*
+        * This is just hand-rolled for now.  I'm not really sure how to approach it
+        * since these are just going to be used temporarily
+        */
+       public static <T extends CLProperty> MemoryAddress toNative(Allocator frame, CLImageDesc d) {
+               MemoryAddress addr = frame.alloca(sizeof);
+
+               Native.setInt(addr, d.imageType);
+               Native.setLong(addr, 1, d.imageWidth);
+               Native.setLong(addr, 2, d.imageHeight);
+               Native.setLong(addr, 3, d.imageDepth);
+               Native.setLong(addr, 4, d.imageArraySize);
+               Native.setLong(addr, 5, d.imageRowPitch);
+               Native.setLong(addr, 6, d.imageSlicePitch);
+               Native.setLong(addr, 7, d.numMipLevels);
+               Native.setLong(addr, 8, d.numSamples);
+               Native.setAddr(addr, 9, Native.addr(d.memObject));
+
+               return addr;
+       }
+
+       public static CLImageFormat fromNative(MemoryAddress addr) {
+               return new CLImageFormat(Native.getInt(addr), Native.getInt(addr, 1));
+       }
+
+       public static final long sizeof = 72;
+
+       public static MemoryLayout layout() { return Native.parseStruct("[u32(image_type)x32u64(image_width)u64(image_height)u64(image_depth)u64(image_array_size)u64(image_row_pitch)u64(image_slice_pitch)u32(num_mip_levels)u32(num_samples)u64(buffer):${_cl_mem}u64(mem_object):${_cl_mem}]"); }
+
 }
index d870024..f419bc6 100644 (file)
  */
 package au.notzed.zcl;
 
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Allocator;
+
 /**
  * Holder for cl_image_format equivalent.
+ *
+ * <h2>panama notes</h2>
+   To maintain compatability with the
+ *  previous api this remains as a simple pojo and marshalling is
+ *  done as required.
+<p>
+This also means it doesn't have to deal with allocation and deallocation and so on.
+
  */
 public class CLImageFormat {
 
@@ -80,4 +92,26 @@ public class CLImageFormat {
                                getChannelOrder(), getChannelDataType());
        }
 
+       /*
+        * This is just hand-rolled for now.  I'm not really sure how to approach it
+        * since these are just going to be used temporarily
+        */
+       static <T extends CLProperty> MemoryAddress toNative(Allocator frame, CLImageFormat fmt) {
+               MemoryAddress addr = frame.alloca(2*4);
+
+               Native.setInt(addr, fmt.channelOrder);
+               Native.setInt(addr, 1, fmt.channelDataType);
+
+               return addr;
+       }
+
+       static CLImageFormat fromNative(MemoryAddress addr) {
+               return new CLImageFormat(Native.getInt(addr), Native.getInt(addr, 1));
+       }
+
+       static CLImageFormat fromNative(MemorySegment addr) {
+               return fromNative(addr.baseAddress());
+       }
+
+       static MemoryLayout layout() { return Native.parseStruct("[u32(image_channel_order)u32(image_channel_data_type)]"); }
 }
index 899e206..aaade1e 100644 (file)
  */
 package au.notzed.zcl;
 
-import java.nio.Buffer;
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Allocator;
+import api.Memory;
+
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Interface for cl_kernel.
@@ -33,15 +40,24 @@ public class CLKernel extends CLObject {
         *
         * @param p Native pointer.
         */
-       public CLKernel(long p) {
+       CLKernel(MemoryAddress p) {
                super(p);
        }
 
-       private native static void release(long p);
+       static CLKernel create(MemoryAddress p) {
+               return Native.resolve(p, CLKernel::new);
+       }
+
+       private static void release(MemoryAddress p) {
+               try {
+                       clReleaseKernel(p);
+               } catch (Throwable t) {
+               }
+       }
 
        @Override
-       int getInfoType() {
-               return TYPE_KERNEL;
+       MethodHandle getInfoFunc() {
+               return clGetKernelInfo;
        }
 
        /**
@@ -51,7 +67,32 @@ public class CLKernel extends CLObject {
         * @throws CLRuntimeException
         * @since OpenCL 2.1
         */
-       public native CLKernel cloneKernel() throws CLRuntimeException;
+       public CLKernel cloneKernel() throws CLRuntimeException {
+               if (clCloneKernel != null) {
+                       // ??
+               }
+               throw new UnsupportedOperationException();
+       }
+
+       /**
+        * Calls clGetKernelArg.
+        * pval is a  pointer to the value.
+        */
+       private void setKernelArg(int index, long size, MemoryAddress pval) {
+               try {
+                       int res;
+
+                       res = clSetKernelArg(addr(), index, size, pval);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+               } catch (CLRuntimeException t) {
+                       // oh joy
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clSetKernelArg with the arguments.
@@ -62,7 +103,7 @@ public class CLKernel extends CLObject {
         * ignored. May be null to setArg the size of a local scope parameter.
         * @param offset Offset in buffer.
         */
-       public native void setArg(int index, long size, Buffer buffer, long offset);
+       //public native void setArg(int index, long size, Buffer buffer, long offset);
 
        /**
         * Set the size of a parameter that is of a local scope.
@@ -71,7 +112,7 @@ public class CLKernel extends CLObject {
         * @param size The size to reserve in bytes.
         */
        public void setArgLDS(int index, long size) {
-               setArg(index, size, null, 0);
+               setKernelArg(index, size, MemoryAddress.NULL);
        }
 
        /**
@@ -80,7 +121,14 @@ public class CLKernel extends CLObject {
         * @param index
         * @param o
         */
-       public native void setArg(int index, CLObject o);
+       public void setArg(int index, CLObject o) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(8);
+
+                       setAddr(pval, o.addr());
+                       setKernelArg(index, 8, pval);
+               }
+       }
 
        /**
         * Set a byte-valued argument. Equates to OpenCL types char, unsigned char,
@@ -89,7 +137,14 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, byte val);
+       public void setArg(int index, byte val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(8);
+
+                       setByte(pval, val);
+                       setKernelArg(index, 1, pval);
+               }
+       }
 
        /**
         * Set a short-valued argument. Equates to OpenCL types short, unsigned
@@ -98,7 +153,14 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, short val);
+       public void setArg(int index, short val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(8);
+
+                       setShort(pval, val);
+                       setKernelArg(index, 2, pval);
+               }
+       }
 
        /**
         * Set an integer-valued argument. Equates to OpenCL types int, unsigned
@@ -107,7 +169,14 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, int val);
+       public void setArg(int index, int val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(8);
+
+                       setInt(pval, val);
+                       setKernelArg(index, 4, pval);
+               }
+       }
 
        /**
         * Set a long-valued argument. Equates (somewhat conveniently) to the OpenCL
@@ -116,7 +185,14 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, long val);
+       public void setArg(int index, long val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(8);
+
+                       setLong(pval, val);
+                       setKernelArg(index, 8, pval);
+               }
+       }
 
        /**
         * Set a float-valued argument.
@@ -124,7 +200,14 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, float val);
+       public void setArg(int index, float val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(8);
+
+                       setFloat(pval, val);
+                       setKernelArg(index, 4, pval);
+               }
+       }
 
        /**
         * Set a double-valued argument.
@@ -132,7 +215,15 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, double val);
+       public void setArg(int index, double val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(8);
+
+                       setDouble(pval, val);
+                       setKernelArg(index, 8, pval);
+               }
+       }
+
 
        /**
         * Set SVM argument.
@@ -140,7 +231,9 @@ public class CLKernel extends CLObject {
         * @param index
         * @param svm MUST have been allocated using CLContext.SVMAlloc().
         */
-       public native void setArg(int index, ByteBuffer svm);
+       public void setArg(int index, ByteBuffer svm) {
+               throw new UnsupportedOperationException("not yet");
+       }
 
        /**
         * Set a multi-element byte argument. This may be used to setArg vector
@@ -149,7 +242,15 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, byte... val);
+       public void setArg(int index, byte... val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(val.length);
+
+                       for (int i=0;i<val.length;i++)
+                               setByte(pval, i, val[i]);
+                       setKernelArg(index, val.length, pval);
+               }
+       }
 
        /**
         * Set a multi-element short argument. This may be used to setArg vector
@@ -158,7 +259,15 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, short... val);
+       public void setArg(int index, short... val)  {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(val.length * 2);
+
+                       for (int i=0;i<val.length;i++)
+                               setShort(pval, i, val[i]);
+                       setKernelArg(index, val.length * 2, pval);
+               }
+       }
 
        /**
         * Set a multi-element integer argument. This may be used to setArg vector
@@ -167,7 +276,15 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, int... val);
+       public void setArg(int index, int... val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(val.length * 4);
+
+                       for (int i=0;i<val.length;i++)
+                               setInt(pval, i, val[i]);
+                       setKernelArg(index, val.length * 4, pval);
+               }
+       }
 
        /**
         * Set a multi-element long argument. This may be used to setArg vector
@@ -176,7 +293,15 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, long... val);
+       public void setArg(int index, long... val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(val.length * 8);
+
+                       for (int i=0;i<val.length;i++)
+                               setLong(pval, i, val[i]);
+                       setKernelArg(index, val.length * 8, pval);
+               }
+       }
 
        /**
         * Set a multi-element float argument. This may be used to setArg vector
@@ -185,7 +310,15 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, float... val);
+       public void setArg(int index, float... val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(val.length * 4);
+
+                       for (int i=0;i<val.length;i++)
+                               setFloat(pval, i, val[i]);
+                       setKernelArg(index, val.length * 4, pval);
+               }
+       }
 
        /**
         * Set a multi-element double argument. This may be used to setArg vector
@@ -194,7 +327,15 @@ public class CLKernel extends CLObject {
         * @param index
         * @param val
         */
-       public native void setArg(int index, double... val);
+       public void setArg(int index, double... val) {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pval = frame.alloca(val.length * 8);
+
+                       for (int i=0;i<val.length;i++)
+                               setDouble(pval, i, val[i]);
+                       setKernelArg(index, val.length * 8, pval);
+               }
+       }
 
        /**
         * Sets a number of arguments.
@@ -243,22 +384,17 @@ public class CLKernel extends CLObject {
        }
 
        public CLContext getContext() {
-               return getInfoAny(CTYPE_CONTEXT, CL_KERNEL_CONTEXT);
+               return getInfoAny(CL_KERNEL_CONTEXT, clGetKernelInfo, CLContext::new);
        }
 
        public CLProgram getProgram() {
-               return getInfoAny(CTYPE_PROGRAM, CL_KERNEL_PROGRAM);
+               return getInfoAny(CL_KERNEL_PROGRAM, clGetKernelInfo, CLProgram::new);
        }
 
        public String getAttributes() {
                return getInfoString(CL_KERNEL_ATTRIBUTES);
        }
 
-       /* cl_kernel_work_group_info */
-       native <T> T getWorkGroupInfoAny(CLDevice dev, int otype, int param_name) throws CLRuntimeException;
-
-       native <T> T getWorkGroupInfoAnyV(CLDevice dev, int otype, int param_name) throws CLRuntimeException;
-
        /**
         * gets CL_KERNEL_GLOBAL_WORK_SIZE
         *
@@ -266,58 +402,56 @@ public class CLKernel extends CLObject {
         * @return
         */
        public long[] getGlobalWorkSize(CLDevice device) {
-               return getWorkGroupInfoAnyV(device, CTYPE_SIZE_T, CL_KERNEL_GLOBAL_WORK_SIZE);
+               return getInfoLongV(device, CL_KERNEL_GLOBAL_WORK_SIZE, clGetKernelWorkGroupInfo);
        }
 
-       public long getWorkGroupSize(CLDevice device) {
-               return getWorkGroupInfoAny(device, CTYPE_SIZE_T, CL_KERNEL_WORK_GROUP_SIZE);
+        public long getWorkGroupSize(CLDevice device) {
+                return getInfoSizeT(device, CL_KERNEL_WORK_GROUP_SIZE, clGetKernelWorkGroupInfo);
        }
 
        public long[] getCompileWorkGroupSize(CLDevice device) {
-               return getWorkGroupInfoAnyV(device, CTYPE_SIZE_T, CL_KERNEL_COMPILE_WORK_GROUP_SIZE);
+               return getInfoLongV(device, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, clGetKernelWorkGroupInfo);
        }
 
        public long getLocalMemSize(CLDevice device) {
-               return getWorkGroupInfoAny(device, CTYPE_LONG, CL_KERNEL_LOCAL_MEM_SIZE);
+               return getInfoSizeT(device, CL_KERNEL_LOCAL_MEM_SIZE, clGetKernelWorkGroupInfo);
        }
 
        public long getPreferredWorkGroupSizeMultiple(CLDevice device) {
-               return getWorkGroupInfoAny(device, CTYPE_SIZE_T, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE);
+               return getInfoSizeT(device, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, clGetKernelWorkGroupInfo);
        }
 
        public long getPrivateMemSize(CLDevice device) {
-               return getWorkGroupInfoAny(device, CTYPE_SIZE_T, CL_KERNEL_PRIVATE_MEM_SIZE);
+               return getInfoSizeT(device, CL_KERNEL_PRIVATE_MEM_SIZE, clGetKernelWorkGroupInfo);
        }
 
-       /* cl_kernel_sub_group_info */
-       // this assumes all size_t's atm.
-       native <T> T getSubGroupInfoAny(CLDevice dev, int otype, int param_name, long[] input) throws CLRuntimeException;
-
-       native <T> T getSubGroupInfoAnyV(CLDevice dev, int otype, int param_name, long[] input) throws CLRuntimeException;
-
        /**
         * @since OpenCL 2.1
         */
        public long getMaxSubGroupSizeForNDRange(CLDevice device, long[] range) {
-               return getSubGroupInfoAny(device, CTYPE_SIZE_T, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, range);
+               // wrong, these all need to pass a range too
+               //return getInfoSizeT(CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, device, clGetKernelSubGroupInfo);
+               throw new UnsupportedOperationException();
        }
 
        /**
         * @since OpenCL 2.1
         */
        public long getSubGroupCountForNDRange(CLDevice device, long[] range) {
-               return getSubGroupInfoAny(device, CTYPE_SIZE_T, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, range);
+               //return getInfoSizeT(CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, device, clGetKernelSubGroupInfo);
+               throw new UnsupportedOperationException();
        }
 
-       /**
-        * @since OpenCL 2.1
-        */
-       public long[] getLocalSizeForSubGroupCount(CLDevice device, long count) {
-               return getSubGroupInfoAnyV(device, CTYPE_SIZE_T, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, new long[]{count});
-       }
+       // /**
+       //  * @since OpenCL 2.1
+       //  */
+       // public long[] getLocalSizeForSubGroupCount(CLDevice device, long count) {
+       //      return getSubGroupInfoAnyV(device, CTYPE_SIZE_T, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, new long[]{count});
+       // }
 
        public long getMaxNumSubGroups(CLDevice device) {
-               return getSubGroupInfoAny(device, CTYPE_SIZE_T, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, null);
+               throw new UnsupportedOperationException();
+               //return getInfoSizeT(CL_KERNEL_MAX_NUM_SUB_GROUPS, device, clGetKernelSubGroupInfo);
        }
 
        /* cl_kernel_exec_info */
@@ -330,11 +464,6 @@ public class CLKernel extends CLObject {
         */
        public final static int CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM = 0x11B7;
 
-       /* cl_kernel_arg_info */
-       native <T> T getArgInfoAny(int index, int otype, int param_name) throws CLRuntimeException;
-
-       native <T> T getArgInfoAnyV(int index, int otype, int param_name) throws CLRuntimeException;
-
        /**
         * gets CL_KERNEL_ARG_ADDRESS_QUALIFIER.
         *
@@ -344,7 +473,7 @@ public class CLKernel extends CLObject {
         * @since OpenCL 1.2
         */
        public int getArgAddressQualifier(int index) throws UnsupportedOperationException {
-               return getArgInfoAny(index, CTYPE_INT, CL_KERNEL_ARG_ADDRESS_QUALIFIER);
+               return getInfoInt(index, CL_KERNEL_ARG_ADDRESS_QUALIFIER, clGetKernelArgInfo);
        }
 
        /**
@@ -356,7 +485,7 @@ public class CLKernel extends CLObject {
         * @since OpenCL 1.2
         */
        public int getArgAccessQualifier(int index) throws UnsupportedOperationException {
-               return getArgInfoAny(index, CTYPE_INT, CL_KERNEL_ARG_ACCESS_QUALIFIER);
+               return getInfoInt(index, CL_KERNEL_ARG_ACCESS_QUALIFIER, clGetKernelArgInfo);
        }
 
        /**
@@ -368,7 +497,7 @@ public class CLKernel extends CLObject {
         * @since OpenCL 1.2
         */
        public String getArgTypeName(int index) throws UnsupportedOperationException {
-               return fromInfoString(getArgInfoAnyV(index, CTYPE_BYTE, CL_KERNEL_ARG_TYPE_NAME));
+               return getInfoString(index, CL_KERNEL_ARG_TYPE_NAME, clGetKernelArgInfo);
        }
 
        /**
@@ -380,7 +509,7 @@ public class CLKernel extends CLObject {
         * @since OpenCL 1.2
         */
        public long getArgTypeQualifier(int index) throws UnsupportedOperationException {
-               return getArgInfoAny(index, CTYPE_LONG, CL_KERNEL_ARG_TYPE_QUALIFIER);
+               return getInfoLong(index, CL_KERNEL_ARG_TYPE_QUALIFIER, clGetKernelArgInfo);
        }
 
        /**
@@ -392,6 +521,6 @@ public class CLKernel extends CLObject {
         * @since OpenCL 1.2
         */
        public String getArgName(int index) throws UnsupportedOperationException {
-               return fromInfoString(getArgInfoAnyV(index, CTYPE_BYTE, CL_KERNEL_ARG_NAME));
+               return getInfoString(index, CL_KERNEL_ARG_NAME, clGetKernelArgInfo);
        }
 }
index c4bd264..0a2923b 100644 (file)
  */
 package au.notzed.zcl;
 
-import java.nio.ByteBuffer;
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Callback;
+import api.Memory;
+import api.Allocator;
+import java.lang.invoke.MethodHandle;
+
+import java.nio.ByteBuffer;
+//import static au.au.notzed.zcl.CL.*;
 import java.nio.ByteOrder;
+import jdk.incubator.foreign.*;
 
 /**
  * Interface for cl_mem.
@@ -58,11 +68,81 @@ import java.nio.ByteOrder;
  */
 public abstract class CLMemory extends CLObject {
 
-       CLMemory(long p) {
+       /**
+        * If use USE_HOST_PTR was used then this keeps track of the
+        * host ptr reference both to avoid java freeing it and so it
+        * can be retrieved later.
+        */
+       MemorySegment seg;
+
+       /**
+        * If set, retain reference for lifetime of memory.
+        */
+       Callback<CLNotify<CLMemory>> destroyCallback;
+
+       CLMemory(MemoryAddress p, MemorySegment seg) {
                super(p);
+
+               this.seg = seg;
        }
 
-       native static void release(long p);
+       @Override
+       MethodHandle getInfoFunc() {
+               return clGetMemObjectInfo;
+       }
+
+       public static CLMemory create(MemoryAddress p) {
+               if (p.offset() == 0)
+                       return null;
+
+               // This is basically a workaround so that setMemObjectDestructorCallback passes
+               // the right type without changing the api or using reflection.
+               // Probably better solutions.
+
+               try (Allocator a = Memory.stack()) {
+                       MemoryAddress addr = getInfo(p, CL_MEM_TYPE, clGetMemObjectInfo, a, 4);
+                       int type = getInt(addr);
+
+                       switch (type) {
+                       case CL_MEM_OBJECT_BUFFER:
+                               return Native.resolve(p, CLBuffer::new);
+                       case CL_MEM_OBJECT_IMAGE2D:
+                       case CL_MEM_OBJECT_IMAGE3D:
+                       case CL_MEM_OBJECT_IMAGE2D_ARRAY:
+                       case CL_MEM_OBJECT_IMAGE1D:
+                       case CL_MEM_OBJECT_IMAGE1D_ARRAY:
+                       case CL_MEM_OBJECT_IMAGE1D_BUFFER:
+                               return Native.resolve(p, CLImage::new);
+                       case CL_MEM_OBJECT_PIPE:
+                               return Native.resolve(p, CLPipe::new);
+                       default:
+                               throw new UnsupportedOperationException();
+                       }
+               }
+       }
+
+       static void release(MemoryAddress p) {
+               // note: no way to free the hostSegment, even if we could
+               System.out.println("*** release clmemory");
+               try {
+                       clReleaseMemObject(p);
+               } catch (Throwable t) {
+               }
+       }
+
+       /**
+        * If CL_MEM_USE_HOST_PTR was used at creation then this must
+        * be invoked to avoid a memory leak.  It also must be invoked
+        * on the original thread of creation.
+        */
+       @Override
+       public void release() {
+               if (seg != null) {
+                       seg.close();
+                       seg = null;
+               }
+               super.release();
+       }
 
        /**
         * Call clSetMemObjectDestructorCallback.
@@ -72,14 +152,32 @@ public abstract class CLMemory extends CLObject {
         * @throws UnsupportedOperationException
         * @since OpenCL 1.1
         */
-       public native void setMemObjectDestructorCallback(CLNotify<CLMemory> notify) throws CLException, UnsupportedOperationException;
+       public void setMemObjectDestructorCallback(CLNotify<CLMemory> notify) throws CLException, UnsupportedOperationException {
+               //a bit costly perhaps
+               getContext().requireAPIVersion(CLPlatform.VERSION_1_1);
 
-       @Override
-       int getInfoType() {
-               return TYPE_MEM_OBJECT;
+               Native.release(destroyCallback);
+               if (notify != null) {
+                       destroyCallback = CLNotify.call(notify, CLMemory::create);
+
+                       try {
+                               int res = clSetMemObjectDestructorCallback(addr(), destroyCallback.addr(), MemoryAddress.NULL);
+                               if (res != 0)
+                                       throw new CLException(res);
+                       } catch (RuntimeException | Error t) {
+                               throw t;
+                       } catch (Throwable t) {
+                               throw new RuntimeException(t);
+                       }
+               } else {
+                       destroyCallback = null;
+               }
        }
 
-       public long getType() {
+       /**
+        * Get CL_MEM_TYPE
+        */
+       public int getType() {
                return getInfoInt(CL_MEM_TYPE);
        }
 
@@ -104,9 +202,15 @@ public abstract class CLMemory extends CLObject {
        /**
         * Get CL_MEM_HOST_PTR.
         *
+        * This recreates a bytebuffer from the memory segment used
+        * at creation time.  It is always in native order.
         * @return
         */
-       public native ByteBuffer getHostPtr() throws CLRuntimeException;
+       public ByteBuffer getHostPtr() throws CLRuntimeException {
+               return seg != null
+                       ? seg.asByteBuffer().order(ByteOrder.nativeOrder())
+                       : null;
+       }
 
        /**
         * Get CL_MEM_CONTEXT.
@@ -114,7 +218,7 @@ public abstract class CLMemory extends CLObject {
         * @return An interface to the context this memory was created on.
         */
        public CLContext getContext() {
-               return getInfoAny(CTYPE_CONTEXT, CL_MEM_CONTEXT);
+               return getInfoAny(CL_MEM_CONTEXT, clGetMemObjectInfo, CLContext::new);
        }
 
        /**
@@ -123,7 +227,7 @@ public abstract class CLMemory extends CLObject {
         * @return
         */
        public CLBuffer getAssociatedMemObject() {
-               return getInfoAny(CTYPE_BUFFER, CL_MEM_ASSOCIATED_MEMOBJECT);
+               return getInfoAny(CL_MEM_ASSOCIATED_MEMOBJECT, clGetMemObjectInfo, CLBuffer::new);
        }
 
        /**
@@ -197,28 +301,28 @@ public abstract class CLMemory extends CLObject {
                }
        }
 
-       public static CLTask ofAcquireGL(CLMemory... mems) {
-               return (CLCommandQueue q, CLEventList waiters, CLEventList events) -> {
-                       q.enqueueAcquireGLObjects(mems, waiters, events);
-               };
-       }
+       //public static CLTask ofAcquireGL(CLMemory... mems) {
+       //      return (CLCommandQueue q, CLEventList waiters, CLEventList events) -> {
+       //              q.enqueueAcquireGLObjects(mems, waiters, events);
+       //      };
+       //}
 
-       public static CLTask ofReleaseGL(CLMemory... mems) {
-               return (CLCommandQueue q, CLEventList waiters, CLEventList events) -> {
-                       q.enqueueReleaseGLObjects(mems, waiters, events);
-               };
-       }
+       //public static CLTask ofReleaseGL(CLMemory... mems) {
+       //      return (CLCommandQueue q, CLEventList waiters, CLEventList events) -> {
+       //              q.enqueueReleaseGLObjects(mems, waiters, events);
+       //      };
+       //}
 
        /*
         Experimental: extensions/gl
         */
-       public CLTask ofAcquireGL() {
-               return ofAcquireGL(this);
-       }
+       //public CLTask ofAcquireGL() {
+       //      return ofAcquireGL(this);
+       //}
 
-       public CLTask ofReleaseGL() {
-               return ofReleaseGL(this);
-       }
+       //public CLTask ofReleaseGL() {
+       //      return ofReleaseGL(this);
+       //}
 
        /*
        Experimental half stuff
index 94b912c..ceb6f8d 100644 (file)
  */
 package au.notzed.zcl;
 
+import java.util.function.Function;
+import jdk.incubator.foreign.MemoryAddress;
+import api.Native;
+import api.Callback;
+
 /**
  * Generic notify routine.
  * @param <T> Type of source object.
  */
+@FunctionalInterface
 public interface CLNotify<T> {
 
        public void notify(T source);
+
+       @SuppressWarnings("unchecked")
+       static <T extends Native> Callback<CLNotify<T>> call(CLNotify<T> notify, Function<MemoryAddress,T> create) {
+               if (notify != null) {
+                       return Native.resolve(
+                               Call_pLpv_v.stub((co, dummy) -> notify.notify(Native.resolve(co, create))),
+                               (p) -> new Callback<>(p, notify));
+               } else {
+                       return Callback.NULL;
+               }
+       }
 }
index 284c82a..a7eb75d 100644 (file)
  */
 package au.notzed.zcl;
 
-import au.notzed.nativez.NativeZ;
+import java.lang.invoke.MethodHandle;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.BiFunction;
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Allocator;
+import api.Memory;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 /**
  * Base class for all OpenCL types which can be represented as objects - i.e.
@@ -39,16 +48,12 @@ import au.notzed.nativez.NativeZ;
  * Memory management is explicit and objects must be released when no longer
  * needed.
  */
-public abstract class CLObject extends NativeZ {
+public abstract class CLObject extends Native {
 
-       protected CLObject(long p) {
+       protected CLObject(MemoryAddress p) {
                super(p);
        }
 
-       static {
-               System.loadLibrary("zcl");
-       }
-
        // These are not really public - for access by extensions
        public static final int CTYPE_PLATFORM = 0;
        public static final int CTYPE_DEVICE = 1;
@@ -98,42 +103,286 @@ public abstract class CLObject extends NativeZ {
        final static int TYPE_EVENT_PROFILING = 14;
        final static int TYPE_KERNEL_SUB_GROUP = 15;
 
-       /**
-        * A generic get info type for GetInfo() qeries that take 5 arguments.
-        *
-        * @param type type code for 'this', or the query that applies to this.
-        * @param param_name name of value being queried.
-        * @param otype output type
-        * @return result, primitive types are boxed.
-        * @throws CLRuntimeException
-        */
-       native <T> T getInfoAny(int type, int otype, int param_name) throws CLRuntimeException;
+       // new 5-param version
+       // this one is static so it can be accessed at creation time
+       protected static MemoryAddress getInfo(MemoryAddress self, int id, MethodHandle getInfo, Allocator frame, long size) throws CLRuntimeException {
+               try {
+                       MemoryAddress addr = frame.alloca(size);
+                       int res;
 
-       <T> T getInfoAny(int otype, int param_name) throws CLRuntimeException {
-               return getInfoAny(getInfoType(), otype, param_name);
+                       res = (int)getInfo.invokeExact(self, id, size, addr, MemoryAddress.NULL);
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return addr;
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
        }
 
-       /**
-        * A generic get info type for GetInfo() qeries that take 5 arguments and
-        * returns an array.
-        *
-        * @param type type code for 'this', or the query that applies to this.
-        * @param param_name name of value being queried.
-        * @param otype output type
-        * @return result array type.
-        * @throws CLRuntimeException
-        */
-       native <T> T getInfoAnyV(int type, int otype, int param_name) throws CLRuntimeException;
 
-       <T> T getInfoAnyV(int otype, int param_name) throws CLRuntimeException {
-               return getInfoAnyV(getInfoType(), otype, param_name);
+       protected int getInfoInt(int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return getInt(getInfo(addr(), id, getInfo, a, 4));
+               }
+       }
+
+       protected long getInfoLong(int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return getLong(getInfo(addr(), id, getInfo, a, 8));
+               }
+       }
+
+       protected long getInfoSizeT(int id, MethodHandle getInfo) {
+               return getInfoLong(id, getInfo);
+       }
+
+       protected <T extends CLObject> T getInfoAny(int id, MethodHandle getInfo, Function<MemoryAddress, T> create) {
+               try (Allocator a = Memory.stack()) {
+                       return Native.resolve(getAddr(getInfo(addr(), id, getInfo, a, 8)), create);
+               }
+       }
+
+       protected <T> T getInfoJava(int id, MethodHandle getInfo, Function<MemoryAddress, T> create) {
+               try (Allocator a = Memory.stack()) {
+                       return create.apply(getAddr(getInfo(addr(), id, getInfo, a, 8)));
+               }
+       }
+
+       // new 5-param version for get any
+       protected MemorySegment getInfoAny(int id, MethodHandle getInfo, Allocator a) throws CLRuntimeException {
+               try {
+                       MemoryAddress sizep = a.alloca(8);
+                       MemorySegment valp;
+                       long size;
+                       int res;
+
+                       res = (int)getInfo.invokeExact(addr(), id, 0L, MemoryAddress.NULL, sizep);
+
+                       size = getLong(sizep);
+                       valp = a.allocs(size);
+
+                       res = (int)getInfo.invokeExact(addr(), id, size, valp.baseAddress(), sizep);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return valp;
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       protected byte[] getInfoByteV(int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return getInfoAny(id, getInfo, a).toByteArray();
+               }
+       }
+
+       protected String getInfoString(int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return infoToString(getInfoAny(id, getInfo, a));
+               }
+       }
+
+       protected <T extends CLProperty> T[] getInfoPropertyV(int id, MethodHandle getInfo, BiFunction<Long,Long,T> create, IntFunction<T[]> createArray) {
+               try (Allocator a = Memory.stack()) {
+                       return CLProperty.fromNative(getInfoAny(id, getInfo, a), create, createArray);
+               }
+       }
+
+       protected long[] getInfoLongV(int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return Native.toLongV(getInfoAny(id, getInfo, a));
+               }
+       }
+
+       protected <T extends CLObject> T[] getInfoAnyV(int id, MethodHandle getInfo, Function<MemoryAddress,T> create, IntFunction<T[]> createArray) {
+               try (Allocator a = Memory.stack()) {
+                       return Native.toObjectV(getInfoAny(id, getInfo, a), create, createArray);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       // new 6-param version
+       protected <T extends CLObject> MemoryAddress getInfo(T ctx, int id, MethodHandle getInfo, Allocator a, long size) throws CLRuntimeException {
+               try {
+                       MemoryAddress addr = a.alloca(size);
+                       int res;
+
+                       res = (int)getInfo.invokeExact(addr(), ctx.addr(), id, size, addr, MemoryAddress.NULL);
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return addr;
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+       protected <T extends CLObject> int getInfoInt(T ctx, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return getInt(getInfo(ctx, id, getInfo, a, 4));
+               }
+       }
+
+       protected <T extends CLObject> long getInfoLong(T ctx, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return getLong(getInfo(ctx, id, getInfo, a, 8));
+               }
        }
 
-       native long getInfoLong(int type, int param_name) throws CLRuntimeException;
+       protected <T extends CLObject> long getInfoSizeT(T ctx, int id, MethodHandle getInfo) {
+               return getInfoLong(ctx, id, getInfo);
+       }
+
+       // new  6-param get-any
+       protected <T extends CLObject> MemorySegment getInfoAny(T ctx, int id, MethodHandle getInfo, Allocator a) throws CLRuntimeException {
+               try {
+                       MemoryAddress sizep = a.alloca(8);
+                       MemorySegment valp;
+                       long size;
+                       int res;
+
+                       res = (int)getInfo.invokeExact(addr(), ctx.addr(), id, 0L, MemoryAddress.NULL, sizep);
+
+                       size = getLong(sizep);
+                       valp = a.allocs(size);
+
+                       res = (int)getInfo.invokeExact(addr(), ctx.addr(), id, size, valp.baseAddress(), sizep);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return valp;
+               } catch (RuntimeException | Error x) {
+                       throw x;
+               } catch (Throwable x) {
+                       throw new RuntimeException(x);
+               }
+       }
+
+       protected <T extends CLObject> byte[] getInfoByteV(T ctx, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       MemorySegment seg = getInfoAny(ctx, id, getInfo, a);
+                       return seg.toByteArray();
+               }
+       }
+
+       // clGet*Info includes terminating 0
+       static String infoToString(MemorySegment seg) {
+               if (false) {
+                       MemoryAddress valp = seg.baseAddress();
+                       byte[] val = new byte[(int)(seg.byteSize()-1)];
+
+                       for (int i=0;i<val.length;i++)
+                               val[i] = getByte(valp, i);
+                       return new String(val);
+               } else {
+                       byte[] val = seg.toByteArray();
+                       return new String(val, 0, val.length-1);
+               }
+       }
+
+       protected <T extends CLObject> String getInfoString(T ctx, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       MemorySegment seg = getInfoAny(ctx, id, getInfo, a);
+                       return infoToString(seg);
+               }
+       }
+
+       protected <T extends CLObject> long[] getInfoLongV(T ctx, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       MemorySegment valp = getInfoAny(ctx, id, getInfo, a);
+                       MemoryAddress val = valp.baseAddress();
+                       int len = (int)(valp.byteSize() >>> 3);
+                       long[] list = new long[len];
+
+                       for (int i=0;i<list.length;i++)
+                               list[i] = getLong(val, i);
+
+                       return list;
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+
+       // check the rest
+
 
-       native int getInfoInt(int type, int param_name) throws CLRuntimeException;
+       // indexed version
+       protected MemoryAddress getInfo(int index, int id, MethodHandle getInfo, Allocator a, long size) throws CLRuntimeException {
+               try {
+                       MemoryAddress addr = a.alloca(size);
+                       int res = (int)getInfo.invokeExact(addr(), index, id, size, addr, MemoryAddress.NULL);
 
-       native long getInfoSizeT(int type, int param_name) throws CLRuntimeException;
+                       if (res != 0)
+                               throw new IllegalArgumentException();
+
+                       return addr;
+               } catch (RuntimeException | Error x) {
+                       throw x;
+               } catch (Throwable x) {
+                       throw new RuntimeException(x);
+               }
+       }
+
+       protected int getInfoInt(int index, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return getInt(getInfo(index, id, getInfo, a, 4));
+               }
+       }
+
+       protected long getInfoLong(int index, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       return getLong(getInfo(index, id, getInfo, a, 8));
+               }
+       }
+
+       protected MemorySegment getInfoAny(int index, int id, MethodHandle getInfo, Allocator a) throws CLRuntimeException {
+               try {
+                       MemoryAddress sizep = a.alloca(8);
+                       MemorySegment valp;
+                       long size;
+                       int res;
+
+                       res = (int)getInfo.invokeExact(addr(), index, id, 0L, MemoryAddress.NULL, sizep);
+
+                       size = getLong(sizep);
+                       valp = a.allocs(size);
+
+                       res = (int)getInfo.invokeExact(addr(), index, id, size, valp.baseAddress(), sizep);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       return valp;
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
+
+
+       protected String getInfoString(int index, int id, MethodHandle getInfo) {
+               try (Allocator a = Memory.stack()) {
+                       MemorySegment valp = getInfoAny(index, id, getInfo, a);
+                       return infoToString(valp);
+               }
+       }
 
        /**
         * Retrieve an int field.
@@ -142,7 +391,7 @@ public abstract class CLObject extends NativeZ {
         * @return
         */
        public int getInfoInt(int param) {
-               return getInfoInt(getInfoType(), param);
+               return getInfoInt(param, getInfoFunc());
        }
 
        /**
@@ -152,7 +401,7 @@ public abstract class CLObject extends NativeZ {
         * @return
         */
        public long getInfoLong(int param) {
-               return getInfoLong(getInfoType(), param);
+               return getInfoLong(param, getInfoFunc());
        }
 
        /**
@@ -163,7 +412,7 @@ public abstract class CLObject extends NativeZ {
         * @throws CLRuntimeException
         */
        public long getInfoSizeT(int param) {
-               return getInfoSizeT(getInfoType(), param);
+               return getInfoSizeT(param, getInfoFunc());
        }
 
        /**
@@ -174,17 +423,7 @@ public abstract class CLObject extends NativeZ {
         * @throws CLRuntimeException
         */
        public long[] getInfoSizeTA(int param) {
-               return getInfoAnyV(getInfoType(), CTYPE_SIZE_T, param);
-       }
-
-       /**
-        * Strips the trailing NUL from the c-String buffer.
-        *
-        * @param bytea
-        * @return
-        */
-       static String fromInfoString(byte[] bytea) {
-               return new String(bytea, 0, bytea.length - 1);
+               return getInfoLongV(param, getInfoFunc());
        }
 
        /**
@@ -194,13 +433,13 @@ public abstract class CLObject extends NativeZ {
         * @return
         */
        public String getInfoString(int param) {
-               return fromInfoString(getInfoAnyV(getInfoType(), CTYPE_BYTE, param));
+               return getInfoString(param, getInfoFunc());
        }
 
        /**
-        * Returns the type code for this class. Taken from TYPE_*
+        * Returns the 5-parameter method for retrieving information.
         *
         * @return
         */
-       abstract int getInfoType();
+       abstract MethodHandle getInfoFunc();
 }
index dd16778..b2e753a 100644 (file)
@@ -17,6 +17,9 @@
 package au.notzed.zcl;
 
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Interface for pipes.
@@ -31,17 +34,21 @@ public class CLPipe<T> extends CLMemory {
         *
         * @param p Native pointer.
         */
-       public CLPipe(long p) {
-               super(p);
+       public CLPipe(MemoryAddress p) {
+               this(p, null);
        }
 
-       static void release(long p) {
-               CLMemory.release(p);
+       public CLPipe(MemoryAddress p, MemorySegment seg) {
+               super(p, seg);
        }
 
        @Override
-       int getInfoType() {
-               return TYPE_PIPE;
+       MethodHandle getInfoFunc() {
+               return clGetPipeInfo;
+       }
+
+       static void release(MemoryAddress p) {
+               CLMemory.release(p);
        }
 
        public int getPacketSize() {
index 001b037..be8dcb1 100644 (file)
 package au.notzed.zcl;
 
 import static au.notzed.zcl.CL.*;
-import au.notzed.zcl.khr.GLSharing;
+import static au.notzed.zcl.CLLib.*;
+//import au.notzed.zcl.khr.GLSharing;
 import java.util.function.ToDoubleFunction;
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Memory;
+import api.Allocator;
+
+// hack test
+import java.lang.invoke.*;
+import jdk.incubator.foreign.unsafe.ForeignUnsafe;
 
 /**
  * Interface for cl_platform_id
@@ -39,7 +48,7 @@ public class CLPlatform extends CLObject {
         *
         * @param p Native pointer.
         */
-       public CLPlatform(long p) {
+       public CLPlatform(MemoryAddress p) {
                super(p);
 
                String v = getVersion();
@@ -54,7 +63,14 @@ public class CLPlatform extends CLObject {
                }
        }
 
-       private native static void release(long p);
+       private static void release(MemoryAddress p) {
+               // noop
+       }
+
+       @Override
+       public void release() {
+               // noop
+       }
 
        @Override
        public String toString() {
@@ -62,8 +78,8 @@ public class CLPlatform extends CLObject {
        }
 
        @Override
-       int getInfoType() {
-               return TYPE_PLATFORM;
+       MethodHandle getInfoFunc() {
+               return clGetPlatformInfo;
        }
 
        /**
@@ -72,7 +88,25 @@ public class CLPlatform extends CLObject {
         * @return List of all available platforms.
         * @throws CLRuntimeException
         */
-       public static native CLPlatform[] getPlatforms() throws CLRuntimeException;
+       public static CLPlatform[] getPlatforms() /*throws CLRuntimeException*/ {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress lenp = frame.alloca(8);
+                       MemoryAddress list;
+                       int len;
+                       int res;
+
+                       res = (int)clGetPlatformIDs.invokeExact(0, MemoryAddress.NULL, lenp);
+
+                       len = Native.getInt(lenp);
+                       list = frame.alloca(8 * len);
+
+                       res = (int)clGetPlatformIDs.invokeExact(len, list, lenp);
+
+                       return toObjectV(list, new CLPlatform[len], CLPlatform::new);
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Calls clGetDeviceIDs.
@@ -83,7 +117,29 @@ public class CLPlatform extends CLObject {
         * @return List of matching devices in this platform.
         * @throws CLRuntimeException
         */
-       public native CLDevice[] getDevices(long type) throws CLRuntimeException;
+       public CLDevice []getDevices(long type) /*throws CLRuntimeException*/ {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress lenp = frame.alloca(8);
+                       MemoryAddress list;
+                       int res, len;
+
+                       res = (int)clGetDeviceIDs.invokeExact(addr(), type, 0, MemoryAddress.NULL, lenp);
+
+                       if (res == CL_DEVICE_NOT_FOUND)
+                               return new CLDevice[0];
+                       else if (res != 0)
+                               throw new CLRuntimeException(res);
+
+                       len = Native.getInt(lenp);
+                       list = frame.alloca(len * 8);
+
+                       res = (int)clGetDeviceIDs.invokeExact(addr(), type, len, list, lenp);
+
+                       return toObjectV(list, new CLDevice[len], CLDevice::new);
+               } catch (Throwable t) {
+                       throw new RuntimeException();
+               }
+       }
 
        /**
         * Find the 'best' device using supplied statistic.
@@ -129,7 +185,7 @@ public class CLPlatform extends CLObject {
         *
         * @throws CLRuntimeException
         */
-       public native void unloadPlatformCompiler() throws CLRuntimeException;
+       //public native void unloadPlatformCompiler() throws CLRuntimeException;
 
        /**
         * get CL_PLATFORM_PROFILE.
@@ -190,18 +246,18 @@ public class CLPlatform extends CLObject {
         * <p>
         * Extensions are bound to platforms.
         */
-       final CLExtension[] extensions = new CLExtension[2];
+       //final CLExtension[] extensions = new CLExtension[2];
 
-       native CLExtension createExtension(int extension); // throws something
+       //native CLExtension createExtension(int extension); // throws something
 
-       public <T extends CLExtension> T getExtension(Class<T> klass, int id) {
-               synchronized (extensions) {
-                       if (extensions[id] == null) {
-                               extensions[id] = createExtension(id);
-                       }
-                       return klass.cast(extensions[id]);
-               }
-       }
+       //public <T extends CLExtension> T getExtension(Class<T> klass, int id) {
+       //      synchronized (extensions) {
+       //              if (extensions[id] == null) {
+       //                      extensions[id] = createExtension(id);
+       //              }
+       //              return klass.cast(extensions[id]);
+       //      }
+       //}
 
        /**
         * Retrieve an extension by name.
@@ -211,14 +267,13 @@ public class CLPlatform extends CLObject {
         * @param name
         * @return
         */
-       public <T extends CLExtension> T getExtension(Class<T> klass, String name) {
-               switch (name) {
-               case GLSharing.NAME:
-                       return getExtension(klass, cl_khr_gl_sharing);
-               case au.notzed.zcl.khr.GLEvent.NAME:
-                       return getExtension(klass, cl_khr_gl_event);
-               }
-               return null;
-       }
-       
+       //public <T extends CLExtension> T getExtension(Class<T> klass, String name) {
+       //      switch (name) {
+       //      case GLSharing.NAME:
+       //              return getExtension(klass, cl_khr_gl_sharing);
+       //      case au.notzed.zcl.khr.GLEvent.NAME:
+       //              return getExtension(klass, cl_khr_gl_event);
+       //      }
+       //      return null;
+       //}
 }
index 44da93d..43b97a0 100644 (file)
 package au.notzed.zcl;
 
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import api.Native;
+import api.Memory;
+import api.Allocator;
+import api.Callback;
+import java.lang.invoke.MethodHandle;
+import java.util.stream.LongStream;
 
 /**
  * Interface for cl_program.
@@ -28,15 +36,25 @@ public class CLProgram extends CLObject {
         *
         * @param p Native pointer.
         */
-       public CLProgram(long p) {
+       CLProgram(MemoryAddress p) {
                super(p);
        }
 
-       private native static void release(long p);
+       public static CLProgram create(MemoryAddress p) {
+               return Native.resolve(p, CLProgram::new);
+       }
+
+       private static void release(MemoryAddress p) {
+               try {
+                       clReleaseProgram(p);
+               } catch (Throwable t) {
+                       t.printStackTrace();
+               }
+       }
 
        @Override
-       int getInfoType() {
-               return TYPE_PROGRAM;
+       MethodHandle getInfoFunc() {
+               return clGetProgramInfo;
        }
 
        /**
@@ -47,7 +65,22 @@ public class CLProgram extends CLObject {
         * @param notify Notification callback.
         * @throws CLException
         */
-       public native void buildProgram(CLDevice[] devices, String options, CLNotify<CLProgram> notify) throws CLException;
+       public void buildProgram(CLDevice[] devices, String options, CLNotify<CLProgram> notify) throws CLException {
+               try (Allocator frame = Memory.stack();
+                       Callback<CLNotify<CLProgram>> call = CLNotify.call(notify, CLProgram::new)) {
+                       MemoryAddress pdevs = toAddrV(frame, devices);
+                       MemoryAddress poptions = toByteV(frame, options);
+                       int res;
+
+                       res = clBuildProgram(addr(), devices.length, pdevs, poptions, call.addr(), MemoryAddress.NULL);
+                       if (res != 0)
+                               throw new CLException(res);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        public void buildProgram(CLDevice[] devices, String options) throws CLException {
                CLNotify<CLProgram> notify = (CLProgram source) -> {
@@ -81,7 +114,35 @@ public class CLProgram extends CLObject {
         * @throws UnsupportedOperationException
         * @since OpenCL 1.2
         */
-       public native void compileProgram(CLDevice[] devices, String options, CLProgram[] headers, String[] header_names, CLNotify<CLProgram> notify) throws CLException, UnsupportedOperationException;
+       public void compileProgram(CLDevice[] devices, String options, CLProgram[] headers, String[] header_names, CLNotify<CLProgram> notify) throws CLException, UnsupportedOperationException {
+               int nheaders = 0;
+               if (headers != null && header_names != null) {
+                       if (headers.length != header_names.length)
+                               throw new IllegalArgumentException();
+                       nheaders = headers.length;
+               } else if (headers != null || header_names != null) {
+                       throw new IllegalArgumentException();
+               }
+
+               try (Allocator frame = Memory.stack();
+                       Callback<CLNotify<CLProgram>> call = CLNotify.call(notify, CLProgram::new)) {
+                       MemoryAddress cdevs = toAddrV(frame, devices);
+                       MemoryAddress coptions = toByteV(frame, options);
+                       MemoryAddress cheaders = toAddrV(frame, headers);
+                       MemoryAddress cnames = Native.toAddrV(frame, header_names);
+                       MemoryAddress cres = frame.alloca(8);
+                       int res;
+                       MemoryAddress ck;
+
+                       res = clCompileProgram(addr(), devices.length, cdevs, coptions, nheaders, cheaders, cnames, call.addr(), MemoryAddress.NULL);
+                       if (res != 0)
+                               throw new CLException(res);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Call clCreateKernel.
@@ -91,18 +152,54 @@ public class CLProgram extends CLObject {
         * longer needed.
         * @throws CLRuntimeException
         */
-       public native CLKernel createKernel(String name) throws CLRuntimeException;
+       public CLKernel createKernel(String name) throws CLException {
+               try (Allocator frame = Memory.stack()) {
+                       MemoryAddress pres = frame.alloca(8);
+                       MemoryAddress pname = toByteV(frame, name);
+                       int res;
+                       MemoryAddress ck;
+
+                       ck = clCreateKernel(addr(), pname, pres);
+                       res = getInt(pres);
+                       if (res != 0)
+                               throw new CLException(res);
+                       return resolve(ck, CLKernel::new);
+               } catch (CLException | RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        /**
         * Call clCreateKernelsInProgram.
         *
-        * @return Number of kernels created.
+        * @return kernels created
         * @throws CLRuntimeException
         */
-       public native CLKernel[] createKernelsInProgram() throws CLRuntimeException;
+       public CLKernel[] createKernelsInProgram() throws CLRuntimeException {
+               int size = getNumKernels();
+
+               try (api.Allocator a = api.Memory.stack()) {
+                       MemoryAddress csize = a.alloca(8);
+                       MemoryAddress ckern = a.alloca(8 * size);
+                       int res;
+
+                       res = clCreateKernelsInProgram(addr(), size, ckern, csize);
+                       if (res != 0)
+                               throw new CLRuntimeException();
+
+                       size = getInt(csize);
+                       return Native.toObjectV(ckern, new CLKernel[size], CLKernel::new);
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        public CLContext getContext() {
-               return getInfoAny(CTYPE_CONTEXT, CL_PROGRAM_CONTEXT);
+               return getInfoAny(CL_PROGRAM_CONTEXT, clGetProgramInfo, CLContext::new);
        }
 
        public int getNumDevices() {
@@ -110,7 +207,7 @@ public class CLProgram extends CLObject {
        }
 
        public CLDevice[] getDevices() {
-               return getInfoAnyV(CTYPE_DEVICE, CL_PROGRAM_DEVICES);
+               return getInfoAnyV(CL_PROGRAM_DEVICES, clGetProgramInfo, CLDevice::new, CLDevice[]::new);
        }
 
        public String getSource() {
@@ -118,14 +215,43 @@ public class CLProgram extends CLObject {
        }
 
        /* This is unnecessary since getBinaries() is the only thing that needs it
-        public long[] getBinarySizes() {
-        long[] sizes = new long[getNumDevices()];
+        public long[] getBinarySizes() { }
+       */
+
+       public byte[][] getBinaries() {
+               long[] sizes = getInfoSizeTA(CL_PROGRAM_BINARY_SIZES);
+               long size = LongStream.of(sizes).sum();
+
+               try (api.Allocator a = api.Memory.stack();
+                       MemorySegment seg = MemorySegment.allocateNative(size)) {
+                       MemoryAddress data = seg.baseAddress();
+                       MemoryAddress cptrs = a.alloca(size * 8);
+                       long off = 0;
+                       int res;
+
+                       for (int i=0;i<sizes.length;i++) {
+                               setAddr(cptrs, i, data.addOffset(off));
+                               off += sizes[i];
+                       }
+                       res = clGetProgramInfo(addr(), CL_PROGRAM_BINARIES, sizes.length * 8L, cptrs, MemoryAddress.NULL);
+
+                       if (res != 0)
+                               throw new CLRuntimeException(res);
 
-        getInfoSizeTA(CL_PROGRAM_BINARY_SIZES, sizes);
+                       byte[][] out = new byte[sizes.length][];
+                       off = 0;
+                       for (int i=0;i<sizes.length;i++) {
+                               out[i] = seg.asSlice(off, sizes[i]).toByteArray();
+                               off += sizes[i];
+                       }
 
-        return sizes;
-        }*/
-       public native byte[][] getBinaries();
+                       return out;
+               } catch (RuntimeException | Error t) {
+                       throw t;
+               } catch (Throwable t) {
+                       throw new RuntimeException(t);
+               }
+       }
 
        public int getNumKernels() {
                return getInfoInt(CL_PROGRAM_NUM_KERNELS);
@@ -135,25 +261,19 @@ public class CLProgram extends CLObject {
                return getInfoString(CL_PROGRAM_KERNEL_NAMES);
        }
 
-       /* cl_program_build_info */
-       native <T> T getBuildInfoAny(CLDevice dev, int otype, int param_name) throws CLRuntimeException;
-
-       native <T> T getBuildInfoAnyV(CLDevice dev, int otype, int param_name) throws CLRuntimeException;
-
        public int getBuildStatus(CLDevice device) {
-               return getBuildInfoAny(device, CTYPE_INT, CL_PROGRAM_BUILD_STATUS);
+               return getInfoInt(device, CL_PROGRAM_BUILD_STATUS, clGetProgramBuildInfo);
        }
 
        public String getBuildOptions(CLDevice device) {
-               return fromInfoString(getBuildInfoAnyV(device, CTYPE_BYTE, CL_PROGRAM_BUILD_OPTIONS));
+               return getInfoString(device, CL_PROGRAM_BUILD_OPTIONS, clGetProgramBuildInfo);
        }
 
        public String getBuildLog(CLDevice device) {
-               return fromInfoString(getBuildInfoAnyV(device, CTYPE_BYTE, CL_PROGRAM_BUILD_LOG));
+               return getInfoString(device, CL_PROGRAM_BUILD_LOG, clGetProgramBuildInfo);
        }
 
        public int getBinaryType(CLDevice device) {
-               return getBuildInfoAny(device, CTYPE_INT, CL_PROGRAM_BINARY_TYPE);
+               return getInfoInt(device, CL_PROGRAM_BINARY_TYPE, clGetProgramBuildInfo);
        }
-
 }
index ef03c45..02e1906 100644 (file)
  */
 package au.notzed.zcl;
 
+import api.Native;
+
+import static au.notzed.zcl.CL.*;
+
+import api.Allocator;
+import jdk.incubator.foreign.MemoryAddress;
+import jdk.incubator.foreign.MemorySegment;
+import java.util.function.BiFunction;
+import java.util.function.IntFunction;
+import java.util.ArrayList;
+
 /**
  * All property arrays implement this interface.
  */
 public interface CLProperty {
 
-       public abstract int getSize();
+       int getSize();
 
        /**
         * Encode this property as an integer array.
@@ -30,7 +41,7 @@ public interface CLProperty {
         * @param o offset
         * @return updated o (o + getSize())
         */
-       public abstract int toInt(int dst[], int o);
+       int toInt(int dst[], int o);
 
        /**
         * Encode this property as a long array.
@@ -39,7 +50,9 @@ public interface CLProperty {
         * @param o offset
         * @return updated o (o + getSize())
         */
-       public abstract int toLong(long dst[], int o);
+       int toLong(long dst[], int o);
+
+       int toLong(MemoryAddress addr, int i);
 
        /**
         * A simple tag/value property type.
@@ -73,6 +86,16 @@ public interface CLProperty {
                        return o;
                }
 
+               public int toLong(MemoryAddress dst, int o) {
+                       Native.setLong(dst, o++, tag);
+                       Native.setLong(dst, o++, value);
+                       return o;
+               }
+
+               public String toString() {
+                       return String.format("[%s: %08x=%08x]",
+                                            getClass().getName(), tag, value);
+               }
        }
 
        /**
@@ -81,11 +104,11 @@ public interface CLProperty {
         * @param props
         * @return
         */
-       static int getSize(Object[] props) {
+       static <T extends CLProperty> int getSize(T[] props) {
                int size = 0;
-               for (Object p : props) {
-                       size += ((CLProperty) p).getSize();
-               }
+
+               for (CLProperty p : props)
+                       size += p.getSize();
 
                return size + 1;
        }
@@ -96,6 +119,7 @@ public interface CLProperty {
         * @param props
         * @return
         */
+       /*
        public static int[] toInt(Object[] props) {
                int[] dst = new int[getSize(props)];
                int o = 0;
@@ -109,13 +133,14 @@ public interface CLProperty {
 
                return dst;
        }
-
+       */
        /**
         * Convert to 64-bit intptr_t array. A terminating 0L is included.
         *
         * @param props
         * @return
         */
+       /*
        public static long[] toLong(Object[] props) {
                long[] dst = new long[getSize(props)];
                int o = 0;
@@ -129,4 +154,57 @@ public interface CLProperty {
 
                return dst;
        }
+       */
+       /*
+       public static <T extends CLProperty> Pointer<Long> toLong(T[] properties) {
+               if (properties != null && properties.length > 0) {
+                       Pointer<Long> props = Pointer.alloc(getSize(properties), 8, Long.class);
+                       int o = 0;
+
+                       for (CLProperty p : properties)
+                               o = p.toLong(props, o);
+                       props.set(o, 0L);
+
+                       return props;
+               } else {
+                       return Pointer.NULL;
+               }
+               }*/
+
+       public static <T extends CLProperty> MemoryAddress toNative(Allocator frame, T[] properties) {
+               if (properties != null && properties.length > 0) {
+                       MemoryAddress addr = frame.alloca(getSize(properties) * 8);
+                       int i = 0;
+
+                       for (CLProperty p: properties)
+                               i = p.toLong(addr, i);
+                       Native.setLong(addr, i, 0L);
+                       return addr;
+               } else {
+                       MemoryAddress addr = frame.alloca(8);
+                       Native.setLong(addr, 0L);
+                       return addr;
+
+                       //return MemoryAddress.NULL;
+               }
+       }
+
+       public static <T extends CLProperty> T[] fromNative(MemorySegment seg, BiFunction<Long,Long,T> create, IntFunction<T[]> createArray) {
+               MemoryAddress add = seg.baseAddress();
+               ArrayList<T> list = new ArrayList<>();
+               long tag;
+
+               for (int i = 0;(tag = Native.getLong(add, i++)) != 0;) {
+                       // HACK: this needs some other mechanism, just hardcode each for now
+                       if (tag == CL_DEVICE_PARTITION_BY_COUNTS) {
+                               throw new UnsupportedOperationException();
+                       } else {
+                               long value = Native.getLong(add, i++);
+
+                               list.add(create.apply(tag, value));
+                       }
+               }
+
+               return list.toArray(createArray);
+       }
 }
index 1a6a088..f3a54d2 100644 (file)
@@ -1,46 +1,16 @@
-/*
- * Copyright (C) 2014 Michael Zucchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package au.notzed.zcl;
 
-import static au.notzed.zcl.CLException.codeToError;
+package au.notzed.zcl;
 
-/**
- * An exception that is likely to occur from a more serious error such as out of
- * memory.
- */
 public class CLRuntimeException extends RuntimeException {
-
-       private final int id;
-
-       /**
-        *
-        * @param id
-        */
-       public CLRuntimeException(int id) {
-               this.id = id;
+       int err;
+       public CLRuntimeException() {
        }
-
-       public int getID() {
-               return id;
+       public CLRuntimeException(int err) {
+               this.err = err;
        }
 
        @Override
        public String getMessage() {
-               return String.format("Error (%d): '%s'", id, codeToError(id));
+               return "cl_error(" + err + ")";
        }
-
 }
index 1133e15..cacbbb7 100644 (file)
 package au.notzed.zcl;
 
 import static au.notzed.zcl.CL.*;
+import static au.notzed.zcl.CLLib.*;
+import jdk.incubator.foreign.*;
+import api.Native;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Interface for cl_sampler.
@@ -28,19 +32,38 @@ public class CLSampler extends CLObject {
         *
         * @param p Native pointer.
         */
-       public CLSampler(long p) {
+       public CLSampler(MemoryAddress p) {
                super(p);
        }
 
-       private native static void release(long p);
-
        @Override
-       int getInfoType() {
-               return TYPE_SAMPLER;
+       MethodHandle getInfoFunc() {
+               return clGetSamplerInfo;
+       }
+
+       private static void release(MemoryAddress p) {
+               try {
+                       clReleaseSampler(p);
+               } catch (Throwable t) {
+                       t.printStackTrace();
+               }
+       }
+
+       public static CLSamplerProperty NORMALIZED_COORDS(boolean enable) {
+               return new CLSamplerProperty.TagValue(CL_SAMPLER_NORMALIZED_COORDS, enable ? 1 : 0);
        }
 
+       public static CLSamplerProperty ADDRESSING_MODE(int mode) {
+               return new CLSamplerProperty.TagValue(CL_SAMPLER_ADDRESSING_MODE, mode);
+       }
+
+       public static CLSamplerProperty FILTER_MODE(int mode) {
+               return new CLSamplerProperty.TagValue(CL_SAMPLER_FILTER_MODE, mode);
+       }
+
+
        public CLContext getContext() {
-               return getInfoAny(CTYPE_CONTEXT, CL_SAMPLER_CONTEXT);
+               return getInfoAny(CL_SAMPLER_CONTEXT, clGetSamplerInfo, CLContext::new);
        }
 
        public boolean getNormalisedCoords() {
index ffa2599..449da72 100644 (file)
@@ -20,12 +20,14 @@ import au.notzed.zcl.CLContext;
 import au.notzed.zcl.CLEvent;
 import au.notzed.zcl.CLExtension;
 
+import jdk.incubator.foreign.MemoryAddress;
+
 /**
  * cl_khr_gl_sharing extension interface.
  */
 public class GLEvent extends CLExtension {
 
-       public GLEvent(long p) {
+       public GLEvent(MemoryAddress p) {
                super(p);
        }
 
index 1bb988c..665d19b 100644 (file)
@@ -28,12 +28,14 @@ import au.notzed.zcl.CLMemory;
 import au.notzed.zcl.CLObject;
 import au.notzed.zcl.CLRuntimeException;
 
+import jdk.incubator.foreign.MemoryAddress;
+
 /**
  * cl_khr_gl_sharing extension interface.
  */
 public class GLSharing extends CLExtension {
 
-       public GLSharing(long p) {
+       public GLSharing(MemoryAddress p) {
                super(p);
        }
 
index e83a880..67454d8 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 module notzed.zcl {
-       requires java.logging;
-       requires notzed.nativez;
-       
+       requires jdk.incubator.foreign;
+
        exports au.notzed.zcl;
-       exports au.notzed.zcl.khr;
-       
-       opens au.notzed.zcl to notzed.nativez;
+       //exports au.notzed.zcl.khr;
 }
diff --git a/src/notzed.zcl/gen/export-defines b/src/notzed.zcl/gen/export-defines
new file mode 100755 (executable)
index 0000000..fbd92bc
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+
+# the gcc plugin can't get to defines, this extracts the opencl ones
+
+$ignore = qr/CL_VERSION_.*/;
+
+$src = shift;
+
+open (my $in,"<$src") || die ("Unable to open $src\n");
+
+print <<END;
+package au.notzed.zcl;
+
+public interface CL {
+END
+
+while (<$in>) {
+    next if (/$ignore/);
+
+    my $line = $_;
+
+    $line =~ s@/\*.*\*/@@;
+
+    if ($line =~ m/^\#define\s+(\w*)\s+(.+)/) {
+       my $name = $1;
+       my $value = $2;
+
+       if ($last =~ m@^/*\* (.*) \*/@) {
+           print "\t".$last;
+       }
+
+       if ($line =~ m/deprecated/) {
+           print "\t\@Deprecated\n";
+       }
+       print "\tpublic static final int $name = $value;\n";
+    }
+    $last = $_;
+}
+
+print <<END;
+}
+END
+
+close $in;
diff --git a/src/notzed.zcl/gen/gen.make b/src/notzed.zcl/gen/gen.make
new file mode 100644 (file)
index 0000000..62508ae
--- /dev/null
@@ -0,0 +1,45 @@
+
+export_defines=src/notzed.zcl/gen/export-defines
+generate_api=src/notzed.zcl/gen/generate-api
+opencl_pm=src/notzed.zcl/gen/opencl.pm
+
+# this is in src/notzed.zcl/classes already
+notzed.zcl_defines =                           \
+ au/notzed/zcl/CL.java
+
+notzed.zcl_generated =                                 \
+ au/notzed/zcl/CLLib.java                      \
+ au/notzed/zcl/Call_pBpvJpv_v.java             \
+ au/notzed/zcl/Call_pLIppvpv_v.java            \
+ au/notzed/zcl/Call_pLIpv_v.java               \
+ au/notzed/zcl/Call_pLpv_v.java                        \
+ au/notzed/zcl/Call_pv_v.java
+
+notzed.zcl_JAVA_GENERATED =                    \
+ $(notzed.zcl_generated)
+
+$(info $(notzed.zcl_genjavadir))
+$(info $(addprefix $(notzed.zcl_genjavadir),$(notzed.zcl_generated)): $(generate_api) $(opencl_pm))
+
+$(notzed.zcl_genjavadir)/au/notzed/zcl/CL.java: src/notzed.zcl/include/CL/cl.h $(export_defines)
+       @install -d $(@D)
+       perl $(export_defines) $< > $@ || rm -f $@
+
+$(addprefix $(notzed.zcl_genjavadir)/,$(notzed.zcl_generated)): $(generate_api) $(opencl_pm)
+       perl $(generate_api) \
+               -d $(notzed.zcl_genjavadir) \
+               -t au.notzed.zcl \
+               -r _cl_platform_id=CLPlatform \
+               -r _cl_device_id=CLDevice \
+               -r _cl_context=CLContext \
+               -r _cl_command_queue=CLCommandQueue \
+               -r _cl_program=CLProgram \
+               -r _cl_kernel=CLKernel \
+               -r _cl_event=CLEvent \
+               -r _cl_mem=CLMemory \
+               -r _cl_sampler=CLSampler \
+               -r _cl_image_desc=CLImageDesc \
+               -r _cl_image_format=CLImageFormat \
+               --raw-calls \
+               -c CLLib -lOpenCL --func-file src/notzed.zcl/gen/opencl.txt \
+               ./$(opencl_pm)
diff --git a/src/notzed.zcl/gen/generate-api b/src/notzed.zcl/gen/generate-api
new file mode 100755 (executable)
index 0000000..ca3d95f
--- /dev/null
@@ -0,0 +1,1418 @@
+#!/usr/bin/perl
+
+# This is a massive fucking mess.
+# It's got a lot of historical baggage and not all options will work.
+# Will be cleaned up later, most of it isn't required.
+
+# replace a datatype with another, do not generate any code for it
+# -r name=new
+
+@matchStruct = ();
+$meta = "";
+# @classes = ( { name => 'class', match => [ func-pattern, ... ], match_file => [ file, ... ], enum => [ enum-pattern, ... ], enum_file => [ file, ...] } )
+@classes = ();
+%class = ();
+$output = ".";
+# map call signatures to a class name
+%callMap = ();
+$package = "";
+# don't output types, replace their name
+%replace = ();
+# calls take raw types and throw Throwable
+$rawCalls = 0;
+# calls visited by all output types
+%usedCalls = ();
+
+while (@ARGV) {
+    my $cmd = shift(@ARGV);
+
+    if ($cmd eq "-f") {
+       my $v = shift(@ARGV);
+       push @{$class{match}}, qr/$v/;
+    } elsif ($cmd eq "--func-file") {
+       my $file = shift(@ARGV);
+
+       push @{$class{match_file}}, $file;
+       push @{$class{match}}, readMatchFile($file);
+    } elsif ($cmd eq "-e") {
+       my $v = shift(@ARGV);
+       push @{$class{enum}}, qr/$v/;
+    } elsif ($cmd eq "--enum-file") {
+       my $file = shift(@ARGV);
+       push @{$class{enum_file}}, $file;
+       push @{$class{enum}}, readMatchFile($file);
+    } elsif ($cmd eq "-s") {
+       my $v = shift(@ARGV);
+       push @matchStruct, qr/$v/;
+    } elsif ($cmd eq "--struct-file") {
+       my $file = shift(@ARGV);
+       push @matchStruct, readMatchFile($file);
+    } elsif ($cmd eq "-r") {
+       my $v = shift(@ARGV);
+
+       $v =~ m/(.*)=(.*)/;
+       $replace{$1} = $2;
+    } elsif ($cmd eq "--raw-calls") {
+       $rawCalls = 1;
+    } elsif ($cmd eq "-t") {
+       $package = shift(@ARGV);
+    } elsif ($cmd eq "-c") {
+       my %new = (
+           name => shift(@ARGV),
+           match => [],
+           match_file => [],
+           enum => [],
+           enum_file => [],
+           libs => []);
+       push @classes, \%new;
+       %class = %new;
+       #print "new:\n".Dumper(\%class);
+    } elsif ($cmd =~ m/^-l(.*)/) {
+       push @{$class{libs}}, $1;
+    } elsif ($cmd eq "-d") {
+       $output = shift(@ARGV);
+    } elsif ($cmd eq "--enclosing-type") {
+       $enclosingType = shift(@ARGV);
+    } else {
+       $meta = $cmd;
+    }
+}
+
+$importPointer = "import api.Native.Pointer;" if (!$rawCalls);
+
+use Data::Dumper;
+
+require $meta;
+
+# box types for primitives
+%map_box = (
+    "long" => "Long",
+    "int" => "Integer",
+    "short" => "Short",
+    "char" => "Character",
+    "float" => "Float",
+    "double" => "Double",
+    "byte" => "Byte",
+    "void" => "Void"
+    );
+
+sub readMatchFile {
+    my $path = shift @_;
+    my @lines = ();
+
+    open(my $f,"<$path");
+    while (<$f>) {
+       chop;
+       next if m/^#/;
+
+       #push @lines, qr/\^$_\$/;
+       push @lines, $_;
+    }
+    close($f);
+
+    my $all = join ('|', @lines);
+
+    return qr/^($all)$/;
+}
+
+sub camelCase {
+    my $name = shift @_;
+
+    $name =~ s/_(.)/uc($1)/eg;
+
+    return $name;
+}
+
+sub StudlyCaps {
+    my $name = shift @_;
+
+    # hack, or good spot for it?
+    return $replace{$name} if $replace{$name};
+
+    $name =~ s/^(.)/uc($1)/e;
+    $name =~ s/_(.)/uc($1)/eg;
+
+    return $name;
+}
+
+
+sub structSignature {
+    my %struct = %{shift(@_)};
+    my $union = shift(@_);
+    my $sig = "";
+    my @fields = @{$struct{fields}};
+    my $offset = 0;
+
+    my $inbf = 0;
+    my $bfoffset = 0;
+    my $bfstart = 0;
+    my $bfsig = "";
+
+    for $fi (@fields) {
+       my %field = %{$fi};
+       my $off = $field{offset};
+
+       # bitfields, this only handles 1x u64 bitfield section
+       #  They need to: align to u32/u64
+       #  Group fields into one full u32/u64
+       # TODO: check alignment @ start?
+       # TODO: clean up and complete
+       # TODO: bitfields in unions are probably broken
+       if ($field{ctype} eq 'bitfield') {
+           if ($inbf) {
+               if ($off - $offset) {
+                   $bfsig .= "x";
+                   $bfsig .= ($off - $offset);
+               }
+               $bfsig .= $field{type};
+               $bfsig .= "($field{name})";
+               $offset = $off + $field{size};
+           } else {
+               $inbf = 1;
+               $bfsig = $field{type};
+               $bfsig .= "($field{name})";
+               $offset = $off + $field{size};
+               $bfstart = $field{offset};
+           }
+
+           if ($union) {
+               $inbf = 0;
+
+               if (($offset - $bfstart) == 32) {
+                   $bfsig = "u32=[$bfsig]";
+               } elsif (($offset - $bfstart) < 32) {
+                   $bfsig .= "x";
+                   $bfsig .= 32 - ($offset - $bfstart);
+                   $offset = $bfstart + 32;
+                   $bfsig = "u32=[$bfsig]";
+               } elsif (($offset - $bfstart) == 64) {
+                   $bfsig = "u64=[$bfsig]";
+               } elsif (($offset - $bfstart) < 64) {
+                   $bfsig .= "x";
+                   $bfsig .= 64 - ($offset - $bfstart);
+                   $offset = $bfstart + 64;
+                   $bfsig = "u64=[$bfsig]";
+               }
+
+               $sig .= $bfsig;
+               $sig .= "|" if ($union && $fi != @fields[$#fields]);
+           }
+           next;
+       } elsif ($inbf) {
+           if (($offset - $bfstart) == 32) {
+               $bfsig = "u32=[$bfsig]";
+           } elsif (($offset - $bfstart) < 32) {
+               $bfsig .= "x";
+               $bfsig .= 32 - ($offset - $bfstart);
+               $offset = $bfstart + 32;
+               $bfsig = "u32=[$bfsig]";
+           } elsif (($offset - $bfstart) == 64) {
+               $bfsig = "u64=[$bfsig]";
+           } elsif (($offset - $bfstart) < 64) {
+               $bfsig .= "x";
+               $bfsig .= 64 - ($offset - $bfstart);
+               $offset = $bfstart + 64;
+               $bfsig = "u64=[$bfsig]";
+           }
+           $sig .= $bfsig;
+           $inbf = 0;
+       }
+
+       # skip to next offset if necessary
+       if ($off > $offset) {
+           $sig .= "x";
+           $sig .= ($off - $offset);
+       }
+       $offset = $off + $field{size};
+
+       # normal field processing
+       if ($field{deref}) {
+           my $deref = $field{deref};
+
+           # HACK: function -> Void
+       #   if ($field{debug} eq 'function') {
+       #       $sig .= "u64($field{name}):v";
+       #    } els
+               if ($deref =~ m/^(u\d\d)(:.*)/) {
+               $sig .= "$1($field{name})$2";
+           } else {
+               $sig .= "$deref($field{name})";
+           }
+       } else {
+           if ($field{type} =~ m/(struct|union):(.*)/) {
+               $sig .= "\${$2}";
+           } elsif ($field{type} =~ m/([iuf])(\d+)/) {
+               $sig .= $1;
+               $sig .= $2;
+           } elsif ($field{type} eq 'void') {
+               $sig .= "v";
+           } elsif ($field{type} eq 'enum') {
+               # FIXME: set type in compiler
+               $sig .= "u32";
+           }
+
+           $sig .= "($field{name})";
+       }
+
+       $sig .= "|" if ($union && $fi != @fields[$#fields]);
+    }
+
+    # finish any trailing bitfield
+    # TODO: cleanup
+    if ($inbf) {
+       if (($offset - $bfstart) == 32) {
+           $bfsig = "u32=[$bfsig]";
+       } elsif (($offset - $bfstart) < 32) {
+           $bfsig .= "x";
+           $bfsig .= 32 - ($offset - $bfstart);
+           $offset = $bfstart + 32;
+           $bfsig = "u32=[$bfsig]";
+       } elsif (($offset - $bfstart) == 64) {
+           $bfsig = "u64=[$bfsig]";
+       } elsif (($offset - $bfstart) < 64) {
+           $bfsig .= "x";
+           $bfsig .= 64 - ($offset - $bfstart);
+           $offset = $bfstart + 64;
+           $bfsig = "u64=[$bfsig]";
+       }
+       #$bfsig .= "]";
+       $sig .= $bfsig;
+    }
+
+    return "[".$sig."]";
+}
+
+sub funcSignature {
+    my %func = %{shift(@_)};
+    my $sig = "";
+    my @params = @{$func{arguments}};
+
+    for $pi (@params) {
+       my %param = %{$pi};
+
+       if ($param{deref}) {
+           # HACK: function to void
+           if ($param{debug} eq "function") {
+               $sig .= "u64:v";
+           } else {
+               $sig .= $param{deref};
+           }
+       } else {
+           if ($param{type} =~ m/struct:(.*)/) {
+               $sig .= "\${$1}";
+           } elsif ($param{type} =~ m/([iuf])(\d*)/) {
+               $sig .= $1;
+               $sig .= $2;
+           } elsif ($param{type} eq "void") {
+               $sig .= "v";
+           }
+       }
+    }
+
+    my %result = %{$func{result}};
+    my $ret = "";
+
+    if ($result{deref}) {
+       $ret .= $result{deref};
+    } else {
+       if ($result{type} =~ m/^struct:(.*)/) {
+           $ret .= "\${$1}";
+       } elsif ($result{type} =~ m/^([iuf])(\d+)/) {
+           $ret .= $1;
+           $ret .= $2;
+       } elsif ($result{type} eq "void") {
+           $ret .= "v";
+       }
+    }
+
+    return "($sig)$ret";
+}
+
+sub deref {
+    my $type = shift @_;
+    my $ref = shift @_;
+
+    while ($ref) {
+       if ($ref =~ m/\[\d*(.*)\]/) {
+           my $sub = deref($type, $1);
+
+           return "Array<$sub>";
+       } elsif ($ref =~ m/^u64:\$/) {
+           # ignore penultimate pointer?
+           last;
+       } elsif ($ref =~ m/^u64:(.*)/) {
+           $type = "Pointer<$type>";
+           $ref = $1;
+       } else {
+           last;
+       }
+    }
+    return $type;
+}
+
+sub typeToJava {
+    my %param = %{shift(@_)};
+    my $type = $param{type};
+    my $ref = $param{deref};
+
+    if ($type =~ m/^struct:(.*)/) {
+       $type = $replace{$1} ? $replace{$1} : StudlyCaps($1);
+    } elsif ($type =~ m/call:/) {
+       # this re-writes ref to remove one pointer-to as the Callback absorbs it.
+       $type = "Callback<".$callMap{$type}.">";
+       $type || die ("No mapping for type ".Dumper(\%param));
+       $ref =~ s/^u(32|64)://;
+    } elsif ($type =~ m/^enum:(.*)/) {
+       # TODO: other enum options
+       $type = "int";
+    } elsif ($type eq "void") {
+       $type = "void";
+    } elsif ($type =~ m/^([iu])(\d*)/) {
+       my $sign = $1;
+       my $size = $2;
+
+       if ($size <= 8) {
+           $type = "byte";
+       } elsif ($size <= 16) {
+           if ($sign eq "i") {
+               $type = "short";
+           } else {
+               $type = "char";
+           }
+       } elsif ($size <= 32) {
+           $type = "int";
+       } else {
+           $type = "long";
+       }
+    } elsif ($type =~ m/^[f](\d*)$/) {
+       my $size = $1;
+
+       if ($size == 32) {
+           $type = "float";
+       } elsif ($size == 64) {
+           $type = "double";
+       }
+    }
+
+    if ($ref) {
+       $type = $map_box{$type} if ($map_box{$type});
+       $type = deref($type, $ref);
+    }
+
+    return $type;
+}
+
+sub typeToRaw {
+    my %param = %{shift(@_)};
+    my $type = $param{type};
+    my $ref = $param{deref};
+
+    my $type = typeToJava(\%param);
+
+    if ($ref =~ m/^u64:/) {
+       return "MemoryAddress";
+    } elsif ($type =~ m/^(struct|union):/) {
+       return "MemorySegment";
+    } else {
+       return $type;
+    }
+
+    # hackity hack
+#    if ($type =~ "(Pointer|Array|Callback)") {
+#      return "MemoryAddress";
+#    } elsif ($type =~ m/^[A-Z]/) {
+#      return "MemorySegment";
+#    } else {
+#      return $type;
+#    }
+}
+
+sub testMatch {
+    my $name = shift @_;
+
+    if (@_) {
+       for $pat (@_) {
+           if ($name =~ /$pat/) {
+               return 1;
+           }
+       }
+       return 0;
+    } else {
+       return 1;
+    }
+}
+
+# find all matching structures and then all that they require
+sub findStructs {
+    my %all = %{shift @_};
+    my @match = @_;
+    my @stack = grep {
+       my %e = %{$all{$_}};
+       $e{type} =~ m/(struct|union)/ && !$replace{$e{name}} && testMatch($e{name}, @match);
+    } keys %all;
+    my %visit = ();
+
+    while (@stack) {
+       my $test = shift @stack;
+
+       if (!$visit{$test}) {
+           my %struct = %{$all{$test}};
+
+           $visit{$test} = 1;
+
+           if (%struct) {
+               print "class: $struct{name}\n";
+               # find all types this one uses
+               for $f (@{$struct{fields}}) {
+                   my %field = %{$f};
+
+                   if ($field{type} =~ m/^(struct|union):(.*)/) {
+                       if (!$replace{$1} && !$set{$field{type}}) {
+                           $set{$field{type}} = $all{$field{type}};
+                           push @stack, $field{type};
+                       }
+                   }
+               }
+           } else {
+               # this is an anon type, typically used for handles
+               $test =~ m/^(struct|union):(.*)/;
+               if (!$replace{$2}) {
+                   print " anon: $2\n";
+                   my %rec = (
+                       type => 'struct',
+                       name => $2,
+                       size => 0
+                       );
+                   $data{$test} = \%rec;
+               }
+           }
+       }
+    }
+    return grep { !$replace{$_} } keys(%visit);
+}
+
+sub findDefinition {
+    my %all = %{shift @_};
+    my $type = shift @_;
+    my @match = @_;
+    my @stack = grep {
+       my %e = %{$all{$_}};
+       $e{type} eq $type && testMatch($e{name}, @match);
+    } keys %all;
+
+    return @stack;
+}
+
+sub arrayInfo {
+    my $ref = shift @_;
+    my %info = (
+       dims => [],
+       );
+
+    print "array $ref\n";
+    while ($ref =~ m/^\[(\d*)(.*)\]$/) {
+       push @{$info{dims}}, $1;
+       $ref = $2;
+       print "dim $1 -, '$2'\n";
+    }
+    $info{deref} = $ref;
+
+    return %info;
+}
+
+# ######################################################################
+
+# setup section
+
+# find all classes used by functions
+my %roots = ();
+for $c (@classes) {
+    my %class = %{$c};
+    my @libs = @{$class{libs}};
+    my @match = @{$class{match}};
+
+    for $k (findDefinition(\%data, 'func', @match)) {
+       my %func = %{$data{$k}};
+       my @params = @{$func{arguments}};
+
+       for $pi (@params) {
+           my %param = %{$pi};
+
+           if ($param{type} =~ m/^(struct|union):(.*)/) {
+               $roots{$2} = 1;
+           }
+       }
+
+       my %result = %{$func{result}};
+
+       if ($result{type} =~ m/^(struct|union):(.*)/) {
+           $roots{$2} = 1;
+       }
+    }
+}
+
+# add roots for any types used by calls
+# FIXME: only include ones used elsewhere
+for $k (grep { $_ =~ m/^call:/n } keys %data) {
+    my %func = %{$data{$k}};
+    my @params = @{$func{arguments}};
+
+    for $pi (@params) {
+       my %param = %{$pi};
+
+       if ($param{type} =~ m/^(struct|union):(.*)/) {
+           $roots{$2} = 1;
+       }
+    }
+
+    my %result = %{$func{result}};
+
+    if ($result{type} =~ m/^(struct|union):(.*)/) {
+       $roots{$2} = 1;
+    }
+}
+
+# Create anonymous structs for anything missing
+for $k (keys %roots) {
+    my $s = 'struct:'.$k;
+    my $u = 'union:'.$k;
+
+    if (!$data{$u} && !$data{$s} && !$replace{$k}) {
+       print " xanon: $s\n";
+       my %rec = (
+           type => 'struct',
+           name => $k,
+           size => 0
+           );
+       $data{$s} = \%rec;
+    }
+}
+
+$all = join ('|', keys %roots);
+if ($all) {
+    push @matchStruct, qr/^($all)$/;
+}
+#print "structures:\n";
+#print Dumper(@matchStruct);
+
+# make a map for all callbacks (call: type) to generated names
+for $c (grep { $_ =~ m/^call:/n } keys %data) {
+    my $name = $c;
+
+    #print "$c\n";
+    # enum maybe to int?
+
+    $name =~ s/^call:/Call/;
+    if ($rawCalls) {
+       $name =~ s/\$\{([^\}]*)\}/L/g;
+    } else {
+       while ($name =~ m/\$\{([^\}]*)\}/) {
+           my $x = $1;
+           if ($replace{$x}) {
+               $x = $replace{$x};
+           } else {
+               $x = StudlyCaps($x);
+           }
+           $name =~ s/\$\{([^\}]*)\}/L$x/;
+       }
+    }
+    $name =~ s/[ui](64|32):/p/g;
+    $name =~ s/[ui]64/J/g;
+    $name =~ s/[ui]32/I/g;
+    $name =~ s/[ui]8/B/g;
+    $name =~ s/f32/F/g;
+    $name =~ s/f64/D/g;
+    $name =~ s/[\[\]\(\)]/_/g;
+
+    $callMap{$c} = "$name";
+}
+
+#print "call mappings\n";
+#print Dumper(\%callMap);
+
+# ######################################################################
+# Start output
+my $dst;
+
+use File::Basename;
+use File::Path qw(make_path);
+
+if ($package ne "") {
+    $packagePrefix = $package.".";
+}
+
+if ($enclosingType) {
+    my $classname = $packagePrefix.$enclosingType;
+
+    $classname =~ s@\.@/@g;
+
+    my $path = $output."/".$classname.".java";
+    my $dir = dirname($path);
+    my $class = basename($path, ".java");
+
+    print "path $path\n";
+    print "dirname $dir\n";
+
+    make_path($dir);
+    open ($dst, ">$path");
+
+    if ($package ne "") {
+       print $dst "package $package;\n";
+    }
+
+    print $dst <<END;
+import java.foreign.Libraries;
+import java.lang.invoke.MethodHandles;
+import jdk.incubator.foreign.*;
+import api.Native;
+$importPoineter
+END
+    print $dst "public class $class {\n";
+}
+
+# ######################################################################
+# This is work in progress, aka a total fucking mess
+# Dump structures
+for $k (findStructs(\%data, @matchStruct)) {
+    my %struct = %{$data{$k}};
+    my @fields = @{$struct{fields}};
+    my $signature = structSignature(\%struct, ($struct{type} eq "union"));
+    my $name = StudlyCaps($struct{name});
+
+    if (!$enclosingType) {
+       my $classname = $packagePrefix.$name;
+
+       open ($dst, ">$path");
+       $classname =~ s@\.@/@g;
+
+       my $path = $output."/".$classname.".java";
+       my $dir = dirname($path);
+       my $class = basename($path, ".java");
+       make_path($dir);
+       open ($dst, ">$path");
+
+       if ($package ne "") {
+           print $dst "package $package;\n";
+       }
+       print $dst <<END;
+import jdk.incubator.foreign.*;
+import api.Native;
+$importPoineter
+
+END
+    }
+
+    print $dst "public class $name extends Native {\n";
+
+    print $dst "\tpublic $name(MemoryAddress p) {\n";
+    print $dst "\t\tsuper(p);\n";
+    print $dst "\t}\n";
+
+    for $fi (@fields) {
+       my %field = %{$fi};
+       my $type = typeToJava(\%field);
+       my $cc = StudlyCaps($field{name});
+
+       if ($field{deref} =~ m/^\[/) {
+           # array
+           my %info = arrayInfo($field{deref});
+           my @dims = @{$info{dims}};
+           $info{type} = $field{type};
+           my $atype = typeToJava(\%info);
+           my @strides = ();
+
+           my $stride = 1;
+           for $dim (reverse(0 .. $#dims)) {
+               push @strides,$stride;
+               $stride *= $dims[$dim];
+           }
+
+           if ($field{type} =~ m/^(struct|union):(.*)/) {
+               for $dim (0 .. $#dims) {
+                   print $dst "// $dims[$dim]\n";
+                   }
+
+               print $dst "public $atype get$cc(";
+               for $dim (0 .. $#dims) {
+                   print $dst ", " if ($dim != 0);
+                   print $dst "int i$dim";
+               }
+               print $dst ") {\n";
+               print $dst "\tint i=";
+               for $dim (0 .. $#dims) {
+                   print $dst " + " if ($dim != 0);
+                   print $dst "(i$dim * $strides[$#dims - $dim])";
+               }
+               print $dst ";\n";
+               print $dst "return Native.Pointer.ofAddress(addr().addOffset(i * 8), 32, Data::new);\n";
+               print $dst "}\n";
+           } elsif ($field{type} =~ m/^call:/) {
+           } else {
+           }
+       } elsif ($field{deref} =~ m/^u64:\$/) {
+           # pointer-to-struct
+           if ($field{type} =~ m/^(struct|union):(.*)/) {
+               my $ltype = StudlyCaps($2);
+               my $offset = $field{offset} >> 3;
+               my $addr = $offset ? "addr().addOffset($offset)" : 'addr()';
+
+               my $size = %{$data{$field{type}}}{size} >> 3;
+
+               print $dst "\tpublic $ltype get$cc() {\n";
+               print $dst "\t\treturn $ltype.create(Native.getAddr($addr, $size));\n";
+               print $dst "\t}\n";
+
+               print $dst "\tpublic void set$cc($ltype v) {\n";
+               print $dst "\t\tNative.setAddr($addr, v.addr());\n";
+               print $dst "\t}\n";
+           }
+       } elsif ($field{deref} =~ m/^u64:u64:\$/) {
+           # pointer-to-pointer-to?
+           if ($field{type} =~ m/^(struct|union):(.*)/) {
+               my $ltype = StudlyCaps($2);
+               my $offset = $field{offset} >> 3;
+               my $addr = $offset ? "addr().addOffset($offset)" : 'addr()';
+
+               my $size = %{$data{$field{type}}}{size} >> 3;
+
+               print $dst "\tpublic $type get$cc() {\n";
+               print $dst "\t\treturn Native.Pointer.ofAddress($addr, $size, $ltype"."::new);\n";
+               print $dst "\t}\n";
+
+               print $dst "\tpublic void set$cc($type v) {\n";
+               print $dst "\t\tNative.setAddr($addr, v.addr());\n";
+               print $dst "\t}\n";
+           }
+       } elsif ($field{ctype} eq 'bitfield') {
+           my $alsr = $field{type} =~ m/^u/ ? '>>>' : '>>';
+           my $lshift = $field{size} <= 32 ? 5 : 6;
+           my $lbits = 1 << $lshift;
+           my $type = $lbits == 32 ? 'int' : 'long';
+           my $ltype = $lbits == 32 ? 'Int' : 'Long';
+
+           my $offset = ($field{offset} >> ($lshift)) * ($lbits / 8);
+           my $addr = $offset ? "addr().addOffset($offset)" : 'addr()';
+           my $shift = $field{offset} & ($lbits-1);
+           my $width = $field{size};
+           my $upshift = ($lbits-$width-$shift);
+           my $downshift = ($lbits-$width);
+           my $mask = sprintf("0x%x", ((1 << $width) - 1) << $shift);
+
+           print $dst "\tpublic $type get$cc() {\n";
+           print $dst "\t\treturn (($type)Native.get$ltype($addr)) << $upshift $alsr $downshift;\n";
+           print $dst "\t}\n";
+
+           print $dst "\tpublic void set$cc($type v) {\n";
+           print $dst "\t\tMemoryAddress addr = $addr;\n";
+           print $dst "\t\tNative.set$ltype(addr, ((($type)Native.get$ltype(addr)) & ~$mask) | ((v << $shift) & $mask));\n";
+           print $dst "\t}\n";
+       } elsif ($field{type} =~ m/^(struct|union):/) {
+           # embedded struct
+       } elsif ($field{type} =~ m/^call:/) {
+           # call, function?
+           print $dst "// call? $type $cc\n";
+           my $offset = $field{offset} >> 3;
+           my $addr = $offset ? "addr().addOffset($offset)" : 'addr()';
+           my $ltype = $type;
+
+           $type =~ s/Callback<(.*)>/$1/;
+
+           print $dst "\tprivate Pointer<$type> $cc;\n";
+
+           print $dst "\tpublic void set$cc($type v) {\n";
+           print $dst "\t\tif ($cc != null) $cc.close();\n";
+           print $dst "\t\tNative.setAddr($addr, ($cc = $type.call(v)).addr());\n";
+           print $dst "\t}\n";
+       } else {
+           my $offset = $field{offset} >> 3;
+           my $addr = $offset ? "addr().addOffset($offset)" : 'addr()';
+           my $ltype = $type;
+
+           $ltype =~ s/^(.)/uc($1)/e;
+
+           die("non-byte offset=$offset ".Dumper(\%field)) if ($field{offset} & 7);
+
+           print $dst "\tpublic $type get$cc() {\n";
+           print $dst "\t\treturn Native.get$ltype($addr);\n";
+           print $dst "\t}\n";
+
+           print $dst "\tpublic void set$cc($type v) {\n";
+           print $dst "\t\tNative.set$ltype($addr, v);\n";
+           print $dst "\t}\n";
+       }
+    }
+
+    my $byteSize = $struct{size} >> 3;
+    print $dst "\tpublic static final long sizeof = $byteSize;\n";
+
+    # TODO: optional just call new()
+    print $dst "\tpublic static $name create(MemoryAddress p) {\n";
+    print $dst "\t\treturn Native.resolve(p, $name"."::new);\n";
+    print $dst "\t}\n";
+
+    print $dst "\tpublic static $name alloc() {\n";
+    print $dst "\t\treturn $name.create(MemorySegment.allocateNative(sizeof).baseAddress());\n";
+    print $dst "\t}\n";
+    print $dst "\tpublic static Pointer<$name> alloc(int n) {\n";
+    print $dst "\t\treturn Pointer.alloc(n, sizeof, $name"."::new);\n";
+    print $dst "\t}\n";
+
+    if ($struct{type} eq "union") {
+       print $dst "\tpublic static MemoryLayout layout() { return Native.parseUnion(\"$signature\"); }\n";
+    } else {
+       print $dst "\tpublic static MemoryLayout layout() { return Native.parseStruct(\"$signature\"); }\n";
+       }
+
+    print $dst "}\n";
+
+    if (!$enclosingType) {
+       close($dst);
+    }
+}
+
+# ######################################################################
+# Dump classes for library linkage
+for $c (@classes) {
+    my %class = %{$c};
+    my @libs = @{$class{libs}};
+    my @match = @{$class{match}};
+
+    if (!$enclosingType) {
+       my $classname = $packagePrefix.$class{name};
+
+       open ($dst, ">$path");
+       $classname =~ s@\.@/@g;
+
+       my $path = $output."/".$classname.".java";
+       my $dir = dirname($path);
+       my $class = basename($path, ".java");
+       make_path($dir);
+       open ($dst, ">$path");
+
+       if ($package ne "") {
+           print $dst "package $package;\n";
+       }
+       print $dst <<END;
+import jdk.incubator.foreign.*;
+import java.lang.invoke.MethodHandle;
+import api.Native;
+$importPoineter
+END
+    }
+
+    print $dst "public class $class{name} {\n";
+
+    print $dst "\tstatic final String[] libraries = {";
+    print $dst join(",", map { "\"$_\"" } @libs);
+    print $dst "};\n";
+
+    # enums to ints
+    # TODO: interfaces?
+    # TODO: static lib class?
+    # typedef enums might appear twice in the data, so ignore duplicates
+    # also, some api's have multiple definitions (?)
+    my %visited = ();
+    my @match_enum = @{$class{enum}};
+    for $k (sort(findDefinition(\%data, 'enum', @match_enum))) {
+       my %enum = %{$data{$k}};
+       my @values = @{$enum{values}};
+       my $type = "int";
+
+       if ($enum{value_type} =~ m/^[ui](\d+)/) {
+           $type = "long" if ($1 > 32)
+       }
+
+       print $dst "\n\t// enum $enum{name}\n";
+       for $vi (@values) {
+           my %value = %{$vi};
+
+           if (!$visited{$value{label}}) {
+               #print $dst "\tpublic static final $type $value{label} = ($type)$value{value};\n";
+               print $dst "\tpublic static final $type $value{label} = $value{value};\n";
+               $visited{$value{label}} = 1;
+           }
+       }
+    }
+
+    # find all 'call:' types used by any included function
+    for $k (sort(findDefinition(\%data, 'func', @match))) {
+           my %func = %{$data{$k}};
+           my @params = @{$func{arguments}};
+           my %res = %{$func{result}};
+
+           for $pi (@params) {
+               my %param = %{$pi};
+
+               if ($param{type} =~ m/^call:/) {
+                   $usedCalls{$param{type}} = 1;
+               }
+           }
+           if ($result{type} =~ m/^call:/) {
+               $usedCalls{$result{type}} = 1;
+           }
+    }
+
+    # function handles
+    #print "class $class{name} -> match:\n".Dumper(\@match);
+
+    for $k (sort(findDefinition(\%data, 'func', @match))) {
+       my %func = %{$data{$k}};
+       my @params = @{$func{arguments}};
+       my $signature = funcSignature(\%func);
+       my $name = ($func{name});
+
+       print $dst "\tfinal static MethodHandle $name;\n";
+    }
+
+    # function handle init
+    print $dst "\tstatic {\n";
+    print $dst "\t\tLibraryLookup[] libs = Native.loadLibraries(libraries);\n";
+
+    for $k (sort(findDefinition(\%data, 'func', @match))) {
+       my %func = %{$data{$k}};
+       my @params = @{$func{arguments}};
+       my $signature = funcSignature(\%func);
+       my $name = ($func{name});
+
+       print $dst "\t\t$name = Native.downcallHandle(libs, \"$name\", \"$signature\");\n";
+    }
+    print $dst "\t}\n";
+
+    # function handle invocation
+    if ($rawCalls) {
+       for $k (sort(findDefinition(\%data, 'func', @match))) {
+           my %func = %{$data{$k}};
+           my @params = @{$func{arguments}};
+           my $signature = funcSignature(\%func);
+           my $name = ($func{name});
+           my %res = %{$func{result}};
+           my $result = typeToRaw(\%res);
+
+           print $dst "\tpublic static $result $name(";
+
+           for $pi (@params) {
+               my %param = %{$pi};
+               my $type = typeToRaw($pi);
+
+               print $dst "$type $param{name}";
+               print $dst ", " if ($pi != $params[$#params]);
+           }
+
+           print $dst ") throws Throwable {\n";
+           if ($result ne "void") {
+               print $dst "return ($result)";
+           }
+           print $dst "$name.invokeExact(";
+           for $pi (@params) {
+               my %param = %{$pi};
+
+               print $dst "$param{name}";
+               print $dst ", " if ($pi != $params[$#params]);
+           }
+           print $dst ");\n";
+           print $dst "\t}\n\n";
+       }
+       print $dst "}\n";
+    } else {
+       for $k (sort(findDefinition(\%data, 'func', @match))) {
+           my %func = %{$data{$k}};
+           my @params = @{$func{arguments}};
+           my $signature = funcSignature(\%func);
+           my $name = ($func{name});
+           my %res = %{$func{result}};
+           my $result = typeToJava(\%{$func{result}});
+
+           print $dst "\tpublic static $result $name(";
+
+           for $pi (@params) {
+               my %param = %{$pi};
+               my $type = typeToJava($pi);
+
+               $type =~ s/Callback/Pointer/;
+
+               # HACK
+               $type =~ s/Pointer<Void>/Pointer<?>/;
+
+               print $dst "$type $param{name}";
+               print $dst ", " if ($pi != $params[$#params]);
+           }
+
+           print $dst ") {\n";
+           # see also call below
+           print $dst "\t\ttry {\n";
+           print $dst "\t\t\t";
+           if ($res{type} =~ m/(struct|union)/n) {
+               if ($res{deref}) {
+                   print $dst "MemoryAddress add = (MemoryAddress)";
+               } else {
+                   print $dst "MemorySegment seg = (MemorySegment)";
+               }
+           } elsif ($result ne "void") {
+               print $dst "return ($result)";
+           }
+           print $dst "$name.invokeExact(";
+           for $pi (@params) {
+               my %param = %{$pi};
+
+               print $dst "$param{name}";
+               if ($param{deref}) {
+                   print $dst ".addr()";
+               } elsif ($param{type} =~ m/^struct|union/) {
+                   print $dst ".addr().segment()";
+               }
+               print $dst ", " if ($pi != $params[$#params]);
+           }
+           print $dst ");\n";
+           if ($res{type} =~ m/(struct|union)/n) {
+               if ($res{deref}) {
+                   print $dst "\t\t\treturn $result.create(add);\n";
+               } else {
+                   print $dst "\t\t\treturn $result.create(seg.baseAddress());\n";
+               }
+           }
+           print $dst "\t\t}\n";
+           print $dst "\t\tcatch (Throwable t) { throw new RuntimeException(t); }\n";
+           print $dst "\t}\n\n";
+       }
+
+       print $dst "}\n";
+    }
+
+    if (!$enclosingType) {
+       close($dst);
+    }
+}
+
+# ######################################################################
+# Dump callbacks
+# TODO: only those used by classes and functions that were exported
+# TODO: yeah this is a total total fucking shitshow
+
+if ($rawCalls) {
+    for $c (grep { $usedCalls{$_} } keys %callMap) {
+       my %call = %{$data{$c}};
+       my $name = $callMap{$c};
+       my @params = @{$call{arguments}};
+       my %res = %{$call{result}};
+       my $result = typeToRaw(\%res);
+       my $signature = funcSignature(\%call);
+
+       if (!$enclosingType) {
+           my $classname = $packagePrefix.$name;
+
+           open ($dst, ">$path");
+           $classname =~ s@\.@/@g;
+
+           my $path = $output."/".$classname.".java";
+           my $dir = dirname($path);
+           my $class = basename($path, ".java");
+           make_path($dir);
+           open ($dst, ">$path");
+
+           if ($package ne "") {
+               print $dst "package $package;\n";
+           }
+           print $dst <<END;
+import jdk.incubator.foreign.*;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+import api.Callback;
+import api.Native;
+END
+       }
+
+       print $dst "\@FunctionalInterface\n";
+       print $dst "public interface $name {\n";
+       print $dst "\tpublic $result fn(";
+
+       for $pi (@params) {
+           my %param = %{$pi};
+           my $type = typeToRaw($pi);
+
+           print $dst "$type $param{name}";
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+
+       print $dst ") throws Throwable;\n";
+
+       # downcall
+       print $dst "\tstatic public $name of(MemoryAddress addr) {\n";
+       print $dst "\t\tMethodHandle func = Native.downcallHandle(addr, \"$signature\");\n";
+       print $dst "\t\treturn (";
+       for $pi (@params) {
+           my %param = %{$pi};
+           my $type = typeToRaw($pi);
+
+           print $dst "$type $param{name}";
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+       print $dst ") -> ";
+       if ($result ne "void") {
+           print $dst "($result)";
+       }
+       print $dst "func.invokeExact(";
+       for $pi (@params) {
+           my %param = %{$pi};
+
+           print $dst "$param{name}";
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+       print $dst ");\n";
+       print $dst "\t}\n";
+
+       # upcall ##############################################################
+       # ??
+
+       print $dst "\tstatic MemoryAddress stub($name call) {\n";
+       print $dst "\t\treturn Native.upcallStub(MethodHandles.lookup(), call, \"$signature\");\n";
+       print $dst "\t}\n";
+
+       # # the raw interface as expected by the native code
+       # my $rawresult = typeToRaw(\%res);
+       # print $dst "\tpublic interface $rawName {\n";
+       # # fixme raw result
+       # print $dst "\t\tpublic $rawresult fn(";
+
+       # for $pi (@params) {
+       #     my %param = %{$pi};
+       #     my $type = typeToRaw($pi);
+
+       #     print $dst "$type $param{name}";
+       #     print $dst ", " if ($pi != $params[$#params]);
+       # }
+
+       # print $dst ");\n";
+       # print $dst "\t}\n";
+
+       # print $dst "\tstatic public Pointer<$name> call($name v) {\n";
+       # print $dst "\t\t$rawName func = (";
+       # for $pi (@params) {
+       #     my %param = %{$pi};
+       #     my $type = typeToRaw($pi);
+
+       #     print $dst "$type $param{name}";
+       #     print $dst ", " if ($pi != $params[$#params]);
+       # }
+       # print $dst ") -> {\n";
+       # print $dst "\t\t\t";
+       # if ($rawresult ne "void") {
+       #     print $dst "return ";
+       # }
+       # print $dst "v.fn(";
+       # for $pi (@params) {
+       #     my %param = %{$pi};
+       #     my $type = typeToJava($pi);
+       #     my $rawtype = typeToRaw($pi);
+
+       #     print "type ='$type'\n";
+       #     if ($type =~ m/^Pointer<[^>]*>$/) {
+       #       print $dst "Pointer.ofAddress($param{name})";
+       #     } elsif ($type eq "Pointer<Pointer<Void>>") {
+       #       print $dst "Pointer.ofAddressP($param{name})";
+       #     } elsif ($rawtype eq "MemoryAddress") {
+       #       print $dst "$type.create($param{name})";
+       #     } elsif ($rawtype eq "MemorySegment") {
+       #       print $dst "$type.create($param{name}.baseAddress())";
+       #     } else {
+       #       print $dst "$param{name}";
+       #     }
+       #     print $dst ", " if ($pi != $params[$#params]);
+       # }
+       # print $dst ")";
+       # if ($rawresult eq "MemoryAddress") {
+       #     print $dst ".addr()";
+       # } elsif ($rawresult eq "MemorySegment") {
+       #     print $dst ".addr().segment()";
+       # }
+       # print $dst ";\n";
+
+       # print $dst "\t\t};\n";
+       # print $dst "\t\treturn Native.Pointer.ofCallback(MethodHandles.lookup(), v, func, \"$signature\");\n";
+       # print $dst "\t}\n";
+
+       print $dst "}\n";
+
+       if (!$enclosingType) {
+           close($dst);
+       }
+    }
+} else {
+    for $c (keys %callMap) {
+       my %call = %{$data{$c}};
+       my $name = $callMap{$c};
+       my @params = @{$call{arguments}};
+       my %res = %{$call{result}};
+       my $result = typeToJava(\%{$call{result}});
+       my $signature = funcSignature(\%call);
+
+       if (!$enclosingType) {
+           my $classname = $packagePrefix.$name;
+
+           open ($dst, ">$path");
+           $classname =~ s@\.@/@g;
+
+           my $path = $output."/".$classname.".java";
+           my $dir = dirname($path);
+           my $class = basename($path, ".java");
+           make_path($dir);
+           open ($dst, ">$path");
+
+           if ($package ne "") {
+               print $dst "package $package;\n";
+           }
+           print $dst <<END;
+import jdk.incubator.foreign.*;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+import api.Native;
+$importPoineter
+END
+       }
+
+       # any in-line structures need to be added to the resolutionContext
+       # TODO: only include actual inline, not pointers
+       #my %resolve = ();
+       #my @list = @params;
+       #unshift(@list,$call{result});
+       #for $pi (@list) {
+       #       my %param = %{$pi};
+       #
+       #       if ($param{type} =~ m/^(struct|union):(.*)/) {
+       #           $resolve{StudlyCaps($2).".class"} = 1;
+       #       }
+       #    }
+       #my $resolve = join (",", keys %resolve);
+
+       print $dst "\@FunctionalInterface\n";
+       print $dst "public interface $name {\n";
+       print $dst "\tpublic $result fn(";
+
+       for $pi (@params) {
+           my %param = %{$pi};
+           my $type = typeToJava($pi);
+
+           print $dst "$type $param{name}";
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+
+       print $dst ");\n";
+
+       # downcall
+       print $dst "\tstatic public $name of(MemoryAddress addr) {\n";
+       print $dst "\t\tMethodHandle func = Native.downcallHandle(addr, \"$signature\");\n";
+       print $dst "\t\treturn (";
+       for $pi (@params) {
+           my %param = %{$pi};
+           my $type = typeToJava($pi);
+
+           print $dst "$type $param{name}";
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+       print $dst ") -> {\n";
+       print $dst "\t\t\ttry {\n";
+       print $dst "\t\t\t\t";
+       if (!$res{deref} && $res{type} =~ m/(struct|union)/n) {
+           print $dst "MemorySegment seg = (MemorySegment)";
+       } elsif ($result ne "void") {
+           print $dst "return ($result)";
+       }
+       print $dst "func.invokeExact(";
+       for $pi (@params) {
+           my %param = %{$pi};
+
+           print $dst "$param{name}";
+           if ($param{deref}) {
+               print $dst ".addr()";
+           } elsif ($param{type} =~ m/^struct|union/) {
+               print $dst ".addr().segment()";
+           }
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+       print $dst ");\n";
+       if (!$res{deref} && $res{type} =~ m/(struct|union)/n) {
+           print $dst "\t\t\t\treturn $result.create(seg.baseAddress());\n";
+       }
+       print $dst "\t\t\t} catch (Throwable t) { throw new RuntimeException(t); }\n";
+       print $dst "\t\t};\n";
+       print $dst "\t}\n";
+
+       # upcall ##############################################################
+       # the raw interface as expected by the native code
+       my $rawName = $name.'Raw';
+       my $rawresult = typeToRaw(\%res);
+       print $dst "\tpublic interface $rawName {\n";
+       # fixme raw result
+       print $dst "\t\tpublic $rawresult fn(";
+
+       for $pi (@params) {
+           my %param = %{$pi};
+           my $type = typeToRaw($pi);
+
+           print $dst "$type $param{name}";
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+
+       print $dst ");\n";
+       print $dst "\t}\n";
+
+       print $dst "\tstatic public Pointer<$name> call($name v) {\n";
+       print $dst "\t\t$rawName func = (";
+       for $pi (@params) {
+           my %param = %{$pi};
+           my $type = typeToRaw($pi);
+
+           print $dst "$type $param{name}";
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+       print $dst ") -> {\n";
+       print $dst "\t\t\t";
+       if ($rawresult ne "void") {
+           print $dst "return ";
+       }
+       print $dst "v.fn(";
+       for $pi (@params) {
+           my %param = %{$pi};
+           my $type = typeToJava($pi);
+           my $rawtype = typeToRaw($pi);
+
+           print "type ='$type'\n";
+           if ($type =~ m/^Pointer<[^>]*>$/) {
+               print $dst "Pointer.ofAddress($param{name})";
+           } elsif ($type eq "Pointer<Pointer<Void>>") {
+               print $dst "Pointer.ofAddressP($param{name})";
+           } elsif ($rawtype eq "MemoryAddress") {
+               print $dst "$type.create($param{name})";
+           } elsif ($rawtype eq "MemorySegment") {
+               print $dst "$type.create($param{name}.baseAddress())";
+           } else {
+               print $dst "$param{name}";
+           }
+           print $dst ", " if ($pi != $params[$#params]);
+       }
+       print $dst ")";
+       if ($rawresult eq "MemoryAddress") {
+           print $dst ".addr()";
+       } elsif ($rawresult eq "MemorySegment") {
+           print $dst ".addr().segment()";
+       }
+       print $dst ";\n";
+
+       print $dst "\t\t};\n";
+       print $dst "\t\treturn Native.Pointer.ofCallback(MethodHandles.lookup(), v, func, \"$signature\");\n";
+       print $dst "\t}\n";
+
+       print $dst "}\n";
+
+       if (!$enclosingType) {
+           close($dst);
+       }
+    }
+}
+
+# Finish off
+if ($enclosingType) {
+    print $dst "}\n";
+    close($dst);
+}
diff --git a/src/notzed.zcl/gen/opencl.pm b/src/notzed.zcl/gen/opencl.pm
new file mode 100644 (file)
index 0000000..2908010
--- /dev/null
@@ -0,0 +1,2301 @@
+
+# Note that this was generated by a gcc plugin
+# it grabs a lot of junk that just gets ignored by the generator
+
+%data = (
+'func:__ctype_get_mb_cur_max' => { name => '__ctype_get_mb_cur_max', type => 'func',
+       result => { ctype => 'long unsigned int', type => 'u64', },
+       arguments => [
+]},
+'func:atof' => { name => 'atof', type => 'func',
+       result => { ctype => 'double', type => 'f64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:atoi' => { name => 'atoi', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:atol' => { name => 'atol', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:atoll' => { name => 'atoll', type => 'func',
+       result => { ctype => 'long long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:strtod' => { name => 'strtod', type => 'func',
+       result => { ctype => 'double', type => 'f64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:strtof' => { name => 'strtof', type => 'func',
+       result => { ctype => 'float', type => 'f32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:strtold' => { name => 'strtold', type => 'func',
+       result => { ctype => 'long double', type => 'f128', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:strtol' => { name => 'strtol', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_2', ctype => 'int', type => 'i32',},
+]},
+'func:strtoul' => { name => 'strtoul', type => 'func',
+       result => { ctype => 'long unsigned int', type => 'u64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_2', ctype => 'int', type => 'i32',},
+]},
+'func:strtoq' => { name => 'strtoq', type => 'func',
+       result => { ctype => 'long long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_2', ctype => 'int', type => 'i32',},
+]},
+'func:strtouq' => { name => 'strtouq', type => 'func',
+       result => { ctype => 'long long unsigned int', type => 'u64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_2', ctype => 'int', type => 'i32',},
+]},
+'func:strtoll' => { name => 'strtoll', type => 'func',
+       result => { ctype => 'long long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_2', ctype => 'int', type => 'i32',},
+]},
+'func:strtoull' => { name => 'strtoull', type => 'func',
+       result => { ctype => 'long long unsigned int', type => 'u64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_2', ctype => 'int', type => 'i32',},
+]},
+'func:l64a' => { name => 'l64a', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long int', type => 'i64',},
+]},
+'func:a64l' => { name => 'a64l', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'struct:timeval' => { name => 'timeval', type => 'struct', size => 128, fields => [
+       { name => 'tv_sec', size => 64, offset => 0, ctype => 'long int', type => 'i64',},
+       { name => 'tv_usec', size => 64, offset => 64, ctype => 'long int', type => 'i64',},
+]},
+'struct:timespec' => { name => 'timespec', type => 'struct', size => 128, fields => [
+       { name => 'tv_sec', size => 64, offset => 0, ctype => 'long int', type => 'i64',},
+       { name => 'tv_nsec', size => 64, offset => 64, ctype => 'long int', type => 'i64',},
+]},
+'func:select' => { name => 'select', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_1', deref => 'u64:${fd_set}', type => 'struct:fd_set',},
+               { size => 64, name => 'arg_2', deref => 'u64:${fd_set}', type => 'struct:fd_set',},
+               { size => 64, name => 'arg_3', deref => 'u64:${fd_set}', type => 'struct:fd_set',},
+               { size => 64, name => 'arg_4', deref => 'u64:${timeval}', type => 'struct:timeval',},
+]},
+'func:pselect' => { name => 'pselect', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_1', deref => 'u64:${fd_set}', type => 'struct:fd_set',},
+               { size => 64, name => 'arg_2', deref => 'u64:${fd_set}', type => 'struct:fd_set',},
+               { size => 64, name => 'arg_3', deref => 'u64:${fd_set}', type => 'struct:fd_set',},
+               { size => 64, name => 'arg_4', deref => 'u64:${timespec}', type => 'struct:timespec',},
+               { size => 64, name => 'arg_5', deref => 'u64:${__sigset_t}', type => 'struct:__sigset_t',},
+]},
+'struct:__pthread_rwlock_arch_t' => { name => '__pthread_rwlock_arch_t', type => 'struct', size => 448, fields => [
+       { name => '__readers', size => 32, offset => 0, ctype => 'unsigned int', type => 'u32',},
+       { name => '__writers', size => 32, offset => 32, ctype => 'unsigned int', type => 'u32',},
+       { name => '__wrphase_futex', size => 32, offset => 64, ctype => 'unsigned int', type => 'u32',},
+       { name => '__writers_futex', size => 32, offset => 96, ctype => 'unsigned int', type => 'u32',},
+       { name => '__pad3', size => 32, offset => 128, ctype => 'unsigned int', type => 'u32',},
+       { name => '__pad4', size => 32, offset => 160, ctype => 'unsigned int', type => 'u32',},
+       { name => '__cur_writer', size => 32, offset => 192, ctype => 'int', type => 'i32',},
+       { name => '__shared', size => 32, offset => 224, ctype => 'int', type => 'i32',},
+       { name => '__rwelision', size => 8, offset => 256, ctype => 'signed char', type => 'i8',},
+       { name => '__pad1', size => 56, offset => 264, deref => '[7u8]', ctype => 'unsigned char', type => 'u8',},
+       { name => '__pad2', size => 64, offset => 320, ctype => 'long unsigned int', type => 'u64',},
+       { name => '__flags', size => 32, offset => 384, ctype => 'unsigned int', type => 'u32',},
+]},
+'struct:__pthread_internal_list' => { name => '__pthread_internal_list', type => 'struct', size => 128, fields => [
+       { name => '__prev', size => 64, offset => 0, deref => 'u64:${__pthread_internal_list}', type => 'struct:__pthread_internal_list',},
+       { name => '__next', size => 64, offset => 64, deref => 'u64:${__pthread_internal_list}', type => 'struct:__pthread_internal_list',},
+]},
+'struct:__pthread_mutex_s' => { name => '__pthread_mutex_s', type => 'struct', size => 320, fields => [
+       { name => '__lock', size => 32, offset => 0, ctype => 'int', type => 'i32',},
+       { name => '__count', size => 32, offset => 32, ctype => 'unsigned int', type => 'u32',},
+       { name => '__owner', size => 32, offset => 64, ctype => 'int', type => 'i32',},
+       { name => '__nusers', size => 32, offset => 96, ctype => 'unsigned int', type => 'u32',},
+       { name => '__kind', size => 32, offset => 128, ctype => 'int', type => 'i32',},
+       { name => '__spins', size => 16, offset => 160, ctype => 'short int', type => 'i16',},
+       { name => '__elision', size => 16, offset => 176, ctype => 'short int', type => 'i16',},
+       { name => '__list', size => 128, offset => 192, type => 'struct:__pthread_internal_list',},
+]},
+'struct:__pthread_cond_s' => { name => '__pthread_cond_s', type => 'struct', size => 384, fields => [
+       { name => '__wseq', size => 64, offset => 0, ctype => 'long long unsigned int', type => 'u64',},
+       { name => '__wseq32', size => 64, offset => 0, type => 'struct:__pthread_cond_s___wseq32',},
+       { name => '__g1_start', size => 64, offset => 64, ctype => 'long long unsigned int', type => 'u64',},
+       { name => '__g1_start32', size => 64, offset => 64, type => 'struct:__pthread_cond_s___g1_start32',},
+       { name => '__g_refs', size => 64, offset => 128, deref => '[2u32]', ctype => 'unsigned int', type => 'u32',},
+       { name => '__g_size', size => 64, offset => 192, deref => '[2u32]', ctype => 'unsigned int', type => 'u32',},
+       { name => '__g1_orig_size', size => 32, offset => 256, ctype => 'unsigned int', type => 'u32',},
+       { name => '__wrefs', size => 32, offset => 288, ctype => 'unsigned int', type => 'u32',},
+       { name => '__g_signals', size => 64, offset => 320, deref => '[2u32]', ctype => 'unsigned int', type => 'u32',},
+]},
+'union:pthread_attr_t' => { name => 'pthread_attr_t', type => 'union', size => 448, fields => [
+       { name => '__size', size => 448, offset => 0, deref => '[56i8]', ctype => 'char', type => 'i8',},
+       { name => '__align', size => 64, offset => 0, ctype => 'long int', type => 'i64',},
+]},
+'func:random' => { name => 'random', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+]},
+'func:srandom' => { name => 'srandom', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:initstate' => { name => 'initstate', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:setstate' => { name => 'setstate', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'struct:random_data' => { name => 'random_data', type => 'struct', size => 384, fields => [
+       { name => 'fptr', size => 64, offset => 0, deref => 'u64:i32', ctype => 'int', type => 'i32',},
+       { name => 'rptr', size => 64, offset => 64, deref => 'u64:i32', ctype => 'int', type => 'i32',},
+       { name => 'state', size => 64, offset => 128, deref => 'u64:i32', ctype => 'int', type => 'i32',},
+       { name => 'rand_type', size => 32, offset => 192, ctype => 'int', type => 'i32',},
+       { name => 'rand_deg', size => 32, offset => 224, ctype => 'int', type => 'i32',},
+       { name => 'rand_sep', size => 32, offset => 256, ctype => 'int', type => 'i32',},
+       { name => 'end_ptr', size => 64, offset => 320, deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:random_r' => { name => 'random_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${random_data}', type => 'struct:random_data',},
+               { size => 64, name => 'arg_1', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:srandom_r' => { name => 'srandom_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_1', deref => 'u64:${random_data}', type => 'struct:random_data',},
+]},
+'func:initstate_r' => { name => 'initstate_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:${random_data}', type => 'struct:random_data',},
+]},
+'func:setstate_r' => { name => 'setstate_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:${random_data}', type => 'struct:random_data',},
+]},
+'func:rand' => { name => 'rand', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+]},
+'func:srand' => { name => 'srand', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:rand_r' => { name => 'rand_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u32', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:drand48' => { name => 'drand48', type => 'func',
+       result => { ctype => 'double', type => 'f64', },
+       arguments => [
+]},
+'func:erand48' => { name => 'erand48', type => 'func',
+       result => { ctype => 'double', type => 'f64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+]},
+'func:lrand48' => { name => 'lrand48', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+]},
+'func:nrand48' => { name => 'nrand48', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+]},
+'func:mrand48' => { name => 'mrand48', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+]},
+'func:jrand48' => { name => 'jrand48', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+]},
+'func:srand48' => { name => 'srand48', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long int', type => 'i64',},
+]},
+'func:seed48' => { name => 'seed48', type => 'func',
+       result => { deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+]},
+'func:lcong48' => { name => 'lcong48', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+]},
+'struct:drand48_data' => { name => 'drand48_data', type => 'struct', size => 192, fields => [
+       { name => '__x', size => 48, offset => 0, deref => '[3u16]', ctype => 'short unsigned int', type => 'u16',},
+       { name => '__old_x', size => 48, offset => 48, deref => '[3u16]', ctype => 'short unsigned int', type => 'u16',},
+       { name => '__c', size => 16, offset => 96, ctype => 'short unsigned int', type => 'u16',},
+       { name => '__init', size => 16, offset => 112, ctype => 'short unsigned int', type => 'u16',},
+       { name => '__a', size => 64, offset => 128, ctype => 'long long unsigned int', type => 'u64',},
+]},
+'func:drand48_r' => { name => 'drand48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+               { size => 64, name => 'arg_1', deref => 'u64:f64', ctype => 'double', type => 'f64',},
+]},
+'func:erand48_r' => { name => 'erand48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+               { size => 64, name => 'arg_1', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+               { size => 64, name => 'arg_2', deref => 'u64:f64', ctype => 'double', type => 'f64',},
+]},
+'func:lrand48_r' => { name => 'lrand48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+               { size => 64, name => 'arg_1', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+]},
+'func:nrand48_r' => { name => 'nrand48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+               { size => 64, name => 'arg_1', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+               { size => 64, name => 'arg_2', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+]},
+'func:mrand48_r' => { name => 'mrand48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+               { size => 64, name => 'arg_1', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+]},
+'func:jrand48_r' => { name => 'jrand48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+               { size => 64, name => 'arg_1', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+               { size => 64, name => 'arg_2', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+]},
+'func:srand48_r' => { name => 'srand48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long int', type => 'i64',},
+               { size => 64, name => 'arg_1', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+]},
+'func:seed48_r' => { name => 'seed48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+               { size => 64, name => 'arg_1', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+]},
+'func:lcong48_r' => { name => 'lcong48_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u16', ctype => 'short unsigned int', type => 'u16',},
+               { size => 64, name => 'arg_1', deref => 'u64:${drand48_data}', type => 'struct:drand48_data',},
+]},
+'func:malloc' => { name => 'malloc', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:calloc' => { name => 'calloc', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:realloc' => { name => 'realloc', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:reallocarray' => { name => 'reallocarray', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:free' => { name => 'free', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+]},
+'func:alloca' => { name => 'alloca', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:valloc' => { name => 'valloc', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:posix_memalign' => { name => 'posix_memalign', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u64:v', type => 'void',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:aligned_alloc' => { name => 'aligned_alloc', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:abort' => { name => 'abort', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+]},
+'func:atexit' => { name => 'atexit', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:()v', type => 'call:()v', },
+]},
+'func:at_quick_exit' => { name => 'at_quick_exit', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:()v', type => 'call:()v', },
+]},
+'func:on_exit' => { name => 'on_exit', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:(i32u64:v)v', type => 'call:(i32u64:v)v', },
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+]},
+'func:exit' => { name => 'exit', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+]},
+'func:quick_exit' => { name => 'quick_exit', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+]},
+'func:_Exit' => { name => '_Exit', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+]},
+'func:getenv' => { name => 'getenv', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:putenv' => { name => 'putenv', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:setenv' => { name => 'setenv', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_2', ctype => 'int', type => 'i32',},
+]},
+'func:unsetenv' => { name => 'unsetenv', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:clearenv' => { name => 'clearenv', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+]},
+'func:mktemp' => { name => 'mktemp', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:mkstemp' => { name => 'mkstemp', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:mkstemps' => { name => 'mkstemps', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+]},
+'func:mkdtemp' => { name => 'mkdtemp', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:system' => { name => 'system', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:realpath' => { name => 'realpath', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'call:__compar_fn_t' => { name => '__compar_fn_t', deref => 'u64:(u64:vu64:v)i32',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+]},
+'func:bsearch' => { name => 'bsearch', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:(u64:vu64:v)i32', type => 'call:(u64:vu64:v)i32', },
+]},
+'func:qsort' => { name => 'qsort', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:(u64:vu64:v)i32', type => 'call:(u64:vu64:v)i32', },
+]},
+'func:abs' => { name => 'abs', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+]},
+'func:labs' => { name => 'labs', type => 'func',
+       result => { ctype => 'long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long int', type => 'i64',},
+]},
+'func:llabs' => { name => 'llabs', type => 'func',
+       result => { ctype => 'long long int', type => 'i64', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long long int', type => 'i64',},
+]},
+'func:div' => { name => 'div', type => 'func',
+       result => { type => 'struct:div_t', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+]},
+'func:ldiv' => { name => 'ldiv', type => 'func',
+       result => { type => 'struct:ldiv_t', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long int', type => 'i64',},
+               { size => 64, name => 'arg_1', ctype => 'long int', type => 'i64',},
+]},
+'func:lldiv' => { name => 'lldiv', type => 'func',
+       result => { type => 'struct:lldiv_t', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'long long int', type => 'i64',},
+               { size => 64, name => 'arg_1', ctype => 'long long int', type => 'i64',},
+]},
+'func:ecvt' => { name => 'ecvt', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'double', type => 'f64',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:fcvt' => { name => 'fcvt', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'double', type => 'f64',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:gcvt' => { name => 'gcvt', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'double', type => 'f64',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:qecvt' => { name => 'qecvt', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 128, name => 'arg_0', ctype => 'long double', type => 'f128',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:qfcvt' => { name => 'qfcvt', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 128, name => 'arg_0', ctype => 'long double', type => 'f128',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:qgcvt' => { name => 'qgcvt', type => 'func',
+       result => { deref => 'u64:i8', ctype => 'char', type => 'i8', },
+       arguments => [
+               { size => 128, name => 'arg_0', ctype => 'long double', type => 'f128',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:ecvt_r' => { name => 'ecvt_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'double', type => 'f64',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_4', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:fcvt_r' => { name => 'fcvt_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', ctype => 'double', type => 'f64',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_4', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:qecvt_r' => { name => 'qecvt_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 128, name => 'arg_0', ctype => 'long double', type => 'f128',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_4', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:qfcvt_r' => { name => 'qfcvt_r', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 128, name => 'arg_0', ctype => 'long double', type => 'f128',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_4', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:mblen' => { name => 'mblen', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:mbtowc' => { name => 'mbtowc', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:wctomb' => { name => 'wctomb', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+]},
+'func:mbstowcs' => { name => 'mbstowcs', type => 'func',
+       result => { ctype => 'long unsigned int', type => 'u64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:wcstombs' => { name => 'wcstombs', type => 'func',
+       result => { ctype => 'long unsigned int', type => 'u64', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:rpmatch' => { name => 'rpmatch', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:getsubopt' => { name => 'getsubopt', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:getloadavg' => { name => 'getloadavg', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:f64', ctype => 'double', type => 'f64',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+]},
+'enum:_mm_hint' => { name => '_mm_hint', type => 'enum', size => 32, value_type => 'u32', values => [
+       { label => '_MM_HINT_ET0', value => '7' },
+       { label => '_MM_HINT_ET1', value => '6' },
+       { label => '_MM_HINT_T0', value => '3' },
+       { label => '_MM_HINT_T1', value => '2' },
+       { label => '_MM_HINT_T2', value => '1' },
+       { label => '_MM_HINT_NTA', value => '0' },
+]},
+'struct:_cl_image_format' => { name => '_cl_image_format', type => 'struct', size => 64, fields => [
+       { name => 'image_channel_order', size => 32, offset => 0, ctype => 'unsigned int', type => 'u32',},
+       { name => 'image_channel_data_type', size => 32, offset => 32, ctype => 'unsigned int', type => 'u32',},
+]},
+'struct:_cl_image_desc' => { name => '_cl_image_desc', type => 'struct', size => 576, fields => [
+       { name => 'image_type', size => 32, offset => 0, ctype => 'unsigned int', type => 'u32',},
+       { name => 'image_width', size => 64, offset => 64, ctype => 'long unsigned int', type => 'u64',},
+       { name => 'image_height', size => 64, offset => 128, ctype => 'long unsigned int', type => 'u64',},
+       { name => 'image_depth', size => 64, offset => 192, ctype => 'long unsigned int', type => 'u64',},
+       { name => 'image_array_size', size => 64, offset => 256, ctype => 'long unsigned int', type => 'u64',},
+       { name => 'image_row_pitch', size => 64, offset => 320, ctype => 'long unsigned int', type => 'u64',},
+       { name => 'image_slice_pitch', size => 64, offset => 384, ctype => 'long unsigned int', type => 'u64',},
+       { name => 'num_mip_levels', size => 32, offset => 448, ctype => 'unsigned int', type => 'u32',},
+       { name => 'num_samples', size => 32, offset => 480, ctype => 'unsigned int', type => 'u32',},
+       { name => 'buffer', size => 64, offset => 512, deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+       { name => 'mem_object', size => 64, offset => 512, deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+]},
+'struct:_cl_buffer_region' => { name => '_cl_buffer_region', type => 'struct', size => 128, fields => [
+       { name => 'origin', size => 64, offset => 0, ctype => 'long unsigned int', type => 'u64',},
+       { name => 'size', size => 64, offset => 64, ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetPlatformIDs' => { name => 'clGetPlatformIDs', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:${_cl_platform_id}', type => 'struct:_cl_platform_id',},
+               { size => 64, name => 'arg_2', deref => 'u64:u32', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:clGetPlatformInfo' => { name => 'clGetPlatformInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_platform_id}', type => 'struct:_cl_platform_id',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetDeviceIDs' => { name => 'clGetDeviceIDs', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_platform_id}', type => 'struct:_cl_platform_id',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_4', deref => 'u64:u32', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:clGetDeviceInfo' => { name => 'clGetDeviceInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clCreateSubDevices' => { name => 'clCreateSubDevices', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_1', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_4', deref => 'u64:u32', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:clRetainDevice' => { name => 'clRetainDevice', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+]},
+'func:clReleaseDevice' => { name => 'clReleaseDevice', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+]},
+'func:clSetDefaultDeviceCommandQueue' => { name => 'clSetDefaultDeviceCommandQueue', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+]},
+'func:clGetDeviceAndHostTimer' => { name => 'clGetDeviceAndHostTimer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetHostTimer' => { name => 'clGetHostTimer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clCreateContext' => { name => 'clCreateContext', type => 'func',
+       result => { deref => 'u64:${_cl_context}', type => 'struct:_cl_context', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_3', deref => 'u64:(u64:i8u64:vu64u64:v)v', type => 'call:(u64:i8u64:vu64u64:v)v', },
+               { size => 64, name => 'arg_4', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_5', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateContextFromType' => { name => 'clCreateContextFromType', type => 'func',
+       result => { deref => 'u64:${_cl_context}', type => 'struct:_cl_context', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', deref => 'u64:(u64:i8u64:vu64u64:v)v', type => 'call:(u64:i8u64:vu64u64:v)v', },
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clRetainContext' => { name => 'clRetainContext', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+]},
+'func:clReleaseContext' => { name => 'clReleaseContext', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+]},
+'func:clGetContextInfo' => { name => 'clGetContextInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clCreateCommandQueueWithProperties' => { name => 'clCreateCommandQueueWithProperties', type => 'func',
+       result => { deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clRetainCommandQueue' => { name => 'clRetainCommandQueue', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+]},
+'func:clReleaseCommandQueue' => { name => 'clReleaseCommandQueue', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+]},
+'func:clGetCommandQueueInfo' => { name => 'clGetCommandQueueInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clCreateBuffer' => { name => 'clCreateBuffer', type => 'func',
+       result => { deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateSubBuffer' => { name => 'clCreateSubBuffer', type => 'func',
+       result => { deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateImage' => { name => 'clCreateImage', type => 'func',
+       result => { deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_image_format}', type => 'struct:_cl_image_format',},
+               { size => 64, name => 'arg_3', deref => 'u64:${_cl_image_desc}', type => 'struct:_cl_image_desc',},
+               { size => 64, name => 'arg_4', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_5', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreatePipe' => { name => 'clCreatePipe', type => 'func',
+       result => { deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 32, name => 'arg_3', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_4', deref => 'u64:i64', ctype => 'long int', type => 'i64',},
+               { size => 64, name => 'arg_5', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clRetainMemObject' => { name => 'clRetainMemObject', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+]},
+'func:clReleaseMemObject' => { name => 'clReleaseMemObject', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+]},
+'func:clGetSupportedImageFormats' => { name => 'clGetSupportedImageFormats', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 32, name => 'arg_3', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_4', deref => 'u64:${_cl_image_format}', type => 'struct:_cl_image_format',},
+               { size => 64, name => 'arg_5', deref => 'u64:u32', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:clGetMemObjectInfo' => { name => 'clGetMemObjectInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetImageInfo' => { name => 'clGetImageInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetPipeInfo' => { name => 'clGetPipeInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clSetMemObjectDestructorCallback' => { name => 'clSetMemObjectDestructorCallback', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_1', deref => 'u64:(u64:${_cl_mem}u64:v)v', type => 'call:(u64:${_cl_mem}u64:v)v', },
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+]},
+'func:clSVMAlloc' => { name => 'clSVMAlloc', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_3', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:clSVMFree' => { name => 'clSVMFree', type => 'func',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+]},
+'func:clCreateSamplerWithProperties' => { name => 'clCreateSamplerWithProperties', type => 'func',
+       result => { deref => 'u64:${_cl_sampler}', type => 'struct:_cl_sampler', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clRetainSampler' => { name => 'clRetainSampler', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_sampler}', type => 'struct:_cl_sampler',},
+]},
+'func:clReleaseSampler' => { name => 'clReleaseSampler', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_sampler}', type => 'struct:_cl_sampler',},
+]},
+'func:clGetSamplerInfo' => { name => 'clGetSamplerInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_sampler}', type => 'struct:_cl_sampler',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clCreateProgramWithSource' => { name => 'clCreateProgramWithSource', type => 'func',
+       result => { deref => 'u64:${_cl_program}', type => 'struct:_cl_program', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateProgramWithBinary' => { name => 'clCreateProgramWithBinary', type => 'func',
+       result => { deref => 'u64:${_cl_program}', type => 'struct:_cl_program', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64:u8', ctype => 'unsigned char', type => 'u8',},
+               { size => 64, name => 'arg_5', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_6', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateProgramWithBuiltInKernels' => { name => 'clCreateProgramWithBuiltInKernels', type => 'func',
+       result => { deref => 'u64:${_cl_program}', type => 'struct:_cl_program', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_3', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_4', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateProgramWithIL' => { name => 'clCreateProgramWithIL', type => 'func',
+       result => { deref => 'u64:${_cl_program}', type => 'struct:_cl_program', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clRetainProgram' => { name => 'clRetainProgram', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+]},
+'func:clReleaseProgram' => { name => 'clReleaseProgram', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+]},
+'func:clBuildProgram' => { name => 'clBuildProgram', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_3', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_4', deref => 'u64:(u64:${_cl_program}u64:v)v', type => 'call:(u64:${_cl_program}u64:v)v', },
+               { size => 64, name => 'arg_5', deref => 'u64:v', type => 'void',},
+]},
+'func:clCompileProgram' => { name => 'clCompileProgram', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_3', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_4', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_7', deref => 'u64:(u64:${_cl_program}u64:v)v', type => 'call:(u64:${_cl_program}u64:v)v', },
+               { size => 64, name => 'arg_8', deref => 'u64:v', type => 'void',},
+]},
+'func:clLinkProgram' => { name => 'clLinkProgram', type => 'func',
+       result => { deref => 'u64:${_cl_program}', type => 'struct:_cl_program', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_3', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 32, name => 'arg_4', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 64, name => 'arg_6', deref => 'u64:(u64:${_cl_program}u64:v)v', type => 'call:(u64:${_cl_program}u64:v)v', },
+               { size => 64, name => 'arg_7', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_8', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clUnloadPlatformCompiler' => { name => 'clUnloadPlatformCompiler', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_platform_id}', type => 'struct:_cl_platform_id',},
+]},
+'func:clGetProgramInfo' => { name => 'clGetProgramInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetProgramBuildInfo' => { name => 'clGetProgramBuildInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clCreateKernel' => { name => 'clCreateKernel', type => 'func',
+       result => { deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_2', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateKernelsInProgram' => { name => 'clCreateKernelsInProgram', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 64, name => 'arg_3', deref => 'u64:u32', ctype => 'unsigned int', type => 'u32',},
+]},
+'func:clCloneKernel' => { name => 'clCloneKernel', type => 'func',
+       result => { deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 64, name => 'arg_1', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clRetainKernel' => { name => 'clRetainKernel', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+]},
+'func:clReleaseKernel' => { name => 'clReleaseKernel', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+]},
+'func:clSetKernelArg' => { name => 'clSetKernelArg', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+]},
+'func:clSetKernelArgSVMPointer' => { name => 'clSetKernelArgSVMPointer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+]},
+'func:clSetKernelExecInfo' => { name => 'clSetKernelExecInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+]},
+'func:clGetKernelInfo' => { name => 'clGetKernelInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetKernelArgInfo' => { name => 'clGetKernelArgInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetKernelWorkGroupInfo' => { name => 'clGetKernelWorkGroupInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clGetKernelSubGroupInfo' => { name => 'clGetKernelSubGroupInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clWaitForEvents' => { name => 'clWaitForEvents', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clGetEventInfo' => { name => 'clGetEventInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clCreateUserEvent' => { name => 'clCreateUserEvent', type => 'func',
+       result => { deref => 'u64:${_cl_event}', type => 'struct:_cl_event', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clRetainEvent' => { name => 'clRetainEvent', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clReleaseEvent' => { name => 'clReleaseEvent', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clSetUserEventStatus' => { name => 'clSetUserEventStatus', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+]},
+'func:clSetEventCallback' => { name => 'clSetEventCallback', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:(u64:${_cl_event}i32u64:v)v', type => 'call:(u64:${_cl_event}i32u64:v)v', },
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+]},
+'func:clGetEventProfilingInfo' => { name => 'clGetEventProfilingInfo', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+]},
+'func:clFlush' => { name => 'clFlush', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+]},
+'func:clFinish' => { name => 'clFinish', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+]},
+'func:clEnqueueReadBuffer' => { name => 'clEnqueueReadBuffer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueReadBufferRect' => { name => 'clEnqueueReadBufferRect', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_7', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_8', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_9', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_10', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_11', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_12', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_13', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueWriteBuffer' => { name => 'clEnqueueWriteBuffer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueWriteBufferRect' => { name => 'clEnqueueWriteBufferRect', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_7', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_8', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_9', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_10', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_11', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_12', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_13', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueFillBuffer' => { name => 'clEnqueueFillBuffer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueCopyBuffer' => { name => 'clEnqueueCopyBuffer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueCopyBufferRect' => { name => 'clEnqueueCopyBufferRect', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_7', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_8', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_9', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_10', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_11', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_12', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueReadImage' => { name => 'clEnqueueReadImage', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_7', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_8', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_9', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_10', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueWriteImage' => { name => 'clEnqueueWriteImage', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_7', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_8', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_9', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_10', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueFillImage' => { name => 'clEnqueueFillImage', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_5', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueCopyImage' => { name => 'clEnqueueCopyImage', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueCopyImageToBuffer' => { name => 'clEnqueueCopyImageToBuffer', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueCopyBufferToImage' => { name => 'clEnqueueCopyBufferToImage', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueMapBuffer' => { name => 'clEnqueueMapBuffer', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_9', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clEnqueueMapImage' => { name => 'clEnqueueMapImage', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_8', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_9', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_10', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_11', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clEnqueueUnmapMemObject' => { name => 'clEnqueueUnmapMemObject', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_3', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueMigrateMemObjects' => { name => 'clEnqueueMigrateMemObjects', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_4', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueNDRangeKernel' => { name => 'clEnqueueNDRangeKernel', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_6', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueNativeKernel' => { name => 'clEnqueueNativeKernel', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:(u64:v)v', type => 'call:(u64:v)v', },
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_4', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_5', deref => 'u64:u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:v', type => 'void',},
+               { size => 32, name => 'arg_7', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_8', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_9', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueMarkerWithWaitList' => { name => 'clEnqueueMarkerWithWaitList', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueBarrierWithWaitList' => { name => 'clEnqueueBarrierWithWaitList', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueSVMFree' => { name => 'clEnqueueSVMFree', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', deref => 'u64:(u64:${_cl_command_queue}u32u64:u64:vu64:v)v', type => 'call:(u64:${_cl_command_queue}u32u64:u64:vu64:v)v', },
+               { size => 64, name => 'arg_4', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_5', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueSVMMemcpy' => { name => 'clEnqueueSVMMemcpy', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_5', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueSVMMemFill' => { name => 'clEnqueueSVMMemFill', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_5', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueSVMMap' => { name => 'clEnqueueSVMMap', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_5', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueSVMUnmap' => { name => 'clEnqueueSVMUnmap', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueSVMMigrateMem' => { name => 'clEnqueueSVMMigrateMem', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 32, name => 'arg_5', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_6', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_7', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clGetExtensionFunctionAddressForPlatform' => { name => 'clGetExtensionFunctionAddressForPlatform', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_platform_id}', type => 'struct:_cl_platform_id',},
+               { size => 64, name => 'arg_1', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:clCreateImage2D' => { name => 'clCreateImage2D', type => 'func',
+       result => { deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_image_format}', type => 'struct:_cl_image_format',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_7', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateImage3D' => { name => 'clCreateImage3D', type => 'func',
+       result => { deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_2', deref => 'u64:${_cl_image_format}', type => 'struct:_cl_image_format',},
+               { size => 64, name => 'arg_3', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_4', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_5', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_6', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_7', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_8', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_9', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clEnqueueMarker' => { name => 'clEnqueueMarker', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueWaitForEvents' => { name => 'clEnqueueWaitForEvents', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'func:clEnqueueBarrier' => { name => 'clEnqueueBarrier', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+]},
+'func:clUnloadCompiler' => { name => 'clUnloadCompiler', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+]},
+'func:clGetExtensionFunctionAddress' => { name => 'clGetExtensionFunctionAddress', type => 'func',
+       result => { deref => 'u64:v', type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+]},
+'func:clCreateCommandQueue' => { name => 'clCreateCommandQueue', type => 'func',
+       result => { deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_device_id}', type => 'struct:_cl_device_id',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clCreateSampler' => { name => 'clCreateSampler', type => 'func',
+       result => { deref => 'u64:${_cl_sampler}', type => 'struct:_cl_sampler', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_context}', type => 'struct:_cl_context',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 32, name => 'arg_3', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_4', deref => 'u64:i32', ctype => 'int', type => 'i32',},
+]},
+'func:clEnqueueTask' => { name => 'clEnqueueTask', type => 'func',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 64, name => 'arg_1', deref => 'u64:${_cl_kernel}', type => 'struct:_cl_kernel',},
+               { size => 32, name => 'arg_2', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_3', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 64, name => 'arg_4', deref => 'u64:u64:${_cl_event}', type => 'struct:_cl_event',},
+]},
+'struct:__pthread_cond_s___wseq32' => { name => '__pthread_cond_s___wseq32', type => 'struct', size => 64, fields => [
+       { name => '__low', size => 32, offset => 0, ctype => 'unsigned int', type => 'u32',},
+       { name => '__high', size => 32, offset => 32, ctype => 'unsigned int', type => 'u32',},
+]},
+'struct:__pthread_cond_s___g1_start32' => { name => '__pthread_cond_s___g1_start32', type => 'struct', size => 64, fields => [
+       { name => '__low', size => 32, offset => 0, ctype => 'unsigned int', type => 'u32',},
+       { name => '__high', size => 32, offset => 32, ctype => 'unsigned int', type => 'u32',},
+]},
+'call:()v' => { name => '()v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+]},
+'call:(i32u64:v)v' => { name => '(i32u64:v)v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+               { size => 32, name => 'arg_0', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+]},
+'call:(u64:vu64:v)i32' => { name => '(u64:vu64:v)i32', type => 'call',
+       result => { ctype => 'int', type => 'i32', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+]},
+'call:(u64:i8u64:vu64u64:v)v' => { name => '(u64:i8u64:vu64u64:v)v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:i8', ctype => 'char', type => 'i8',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+               { size => 64, name => 'arg_2', ctype => 'long unsigned int', type => 'u64',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+]},
+'call:(u64:${_cl_mem}u64:v)v' => { name => '(u64:${_cl_mem}u64:v)v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_mem}', type => 'struct:_cl_mem',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+]},
+'call:(u64:${_cl_program}u64:v)v' => { name => '(u64:${_cl_program}u64:v)v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_program}', type => 'struct:_cl_program',},
+               { size => 64, name => 'arg_1', deref => 'u64:v', type => 'void',},
+]},
+'call:(u64:${_cl_event}i32u64:v)v' => { name => '(u64:${_cl_event}i32u64:v)v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_event}', type => 'struct:_cl_event',},
+               { size => 32, name => 'arg_1', ctype => 'int', type => 'i32',},
+               { size => 64, name => 'arg_2', deref => 'u64:v', type => 'void',},
+]},
+'call:(u64:v)v' => { name => '(u64:v)v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:v', type => 'void',},
+]},
+'call:(u64:${_cl_command_queue}u32u64:u64:vu64:v)v' => { name => '(u64:${_cl_command_queue}u32u64:u64:vu64:v)v', type => 'call',
+       result => { type => 'void', },
+       arguments => [
+               { size => 64, name => 'arg_0', deref => 'u64:${_cl_command_queue}', type => 'struct:_cl_command_queue',},
+               { size => 32, name => 'arg_1', ctype => 'unsigned int', type => 'u32',},
+               { size => 64, name => 'arg_2', deref => 'u64:u64:v', type => 'void',},
+               { size => 64, name => 'arg_3', deref => 'u64:v', type => 'void',},
+]},
+# dumped structs:
+# __u_char
+# __u_short
+# __u_int
+# __u_long
+# __int8_t
+# __uint8_t
+# __int16_t
+# __uint16_t
+# __int32_t
+# __uint32_t
+# __int64_t
+# __uint64_t
+# __int_least8_t
+# __uint_least8_t
+# __int_least16_t
+# __uint_least16_t
+# __int_least32_t
+# __uint_least32_t
+# __int_least64_t
+# __uint_least64_t
+# __quad_t
+# __u_quad_t
+# __intmax_t
+# __uintmax_t
+# __dev_t
+# __uid_t
+# __gid_t
+# __ino_t
+# __ino64_t
+# __mode_t
+# __nlink_t
+# __off_t
+# __off64_t
+# __pid_t
+# __fsid_t
+# __clock_t
+# __rlim_t
+# __rlim64_t
+# __id_t
+# __time_t
+# __useconds_t
+# __suseconds_t
+# __daddr_t
+# __key_t
+# __clockid_t
+# __timer_t
+# __blksize_t
+# __blkcnt_t
+# __blkcnt64_t
+# __fsblkcnt_t
+# __fsblkcnt64_t
+# __fsfilcnt_t
+# __fsfilcnt64_t
+# __fsword_t
+# __ssize_t
+# __syscall_slong_t
+# __syscall_ulong_t
+# __loff_t
+# __caddr_t
+# __intptr_t
+# __socklen_t
+# __sig_atomic_t
+# int8_t
+# int16_t
+# int32_t
+# int64_t
+# uint8_t
+# uint16_t
+# uint32_t
+# uint64_t
+# int_least8_t
+# int_least16_t
+# int_least32_t
+# int_least64_t
+# uint_least8_t
+# uint_least16_t
+# uint_least32_t
+# uint_least64_t
+# int_fast8_t
+# int_fast16_t
+# int_fast32_t
+# int_fast64_t
+# uint_fast8_t
+# uint_fast16_t
+# uint_fast32_t
+# uint_fast64_t
+# intptr_t
+# uintptr_t
+# intmax_t
+# uintmax_t
+# cl_char
+# cl_uchar
+# cl_short
+# cl_ushort
+# cl_int
+# cl_uint
+# cl_long
+# cl_ulong
+# cl_half
+# cl_float
+# cl_double
+# ptrdiff_t
+# size_t
+# wchar_t
+# max_align_t
+# cl_GLuint
+# cl_GLint
+# cl_GLenum
+# __m64
+# __m64_u
+# __v2si
+# __v4hi
+# __v8qi
+# __v1di
+# __v2sf
+# div_t
+# ldiv_t
+# lldiv_t
+# __ctype_get_mb_cur_max
+# atof
+# atoi
+# atol
+# atoll
+# strtod
+# strtof
+# strtold
+# strtol
+# strtoul
+# strtoq
+# strtouq
+# strtoll
+# strtoull
+# l64a
+# a64l
+# u_char
+# u_short
+# u_int
+# u_long
+# quad_t
+# u_quad_t
+# fsid_t
+# loff_t
+# ino_t
+# dev_t
+# gid_t
+# mode_t
+# nlink_t
+# uid_t
+# off_t
+# pid_t
+# id_t
+# ssize_t
+# daddr_t
+# caddr_t
+# key_t
+# clock_t
+# clockid_t
+# time_t
+# timer_t
+# ulong
+# ushort
+# uint
+# u_int8_t
+# u_int16_t
+# u_int32_t
+# u_int64_t
+# register_t
+# __sigset_t
+# sigset_t
+# timeval
+# timespec
+# suseconds_t
+# __fd_mask
+# fd_set
+# fd_mask
+# select
+# pselect
+# blksize_t
+# blkcnt_t
+# fsblkcnt_t
+# fsfilcnt_t
+# __pthread_rwlock_arch_t
+# __pthread_internal_list
+# __pthread_list_t
+# __pthread_mutex_s
+# __pthread_cond_s
+# pthread_t
+# pthread_mutexattr_t
+# pthread_condattr_t
+# pthread_key_t
+# pthread_once_t
+# pthread_attr_t
+# pthread_mutex_t
+# pthread_cond_t
+# pthread_rwlock_t
+# pthread_rwlockattr_t
+# pthread_spinlock_t
+# pthread_barrier_t
+# pthread_barrierattr_t
+# random
+# srandom
+# initstate
+# setstate
+# random_data
+# random_r
+# srandom_r
+# initstate_r
+# setstate_r
+# rand
+# srand
+# rand_r
+# drand48
+# erand48
+# lrand48
+# nrand48
+# mrand48
+# jrand48
+# srand48
+# seed48
+# lcong48
+# drand48_data
+# drand48_r
+# erand48_r
+# lrand48_r
+# nrand48_r
+# mrand48_r
+# jrand48_r
+# srand48_r
+# seed48_r
+# lcong48_r
+# malloc
+# calloc
+# realloc
+# reallocarray
+# free
+# alloca
+# valloc
+# posix_memalign
+# aligned_alloc
+# abort
+# atexit
+# at_quick_exit
+# on_exit
+# exit
+# quick_exit
+# _Exit
+# getenv
+# putenv
+# setenv
+# unsetenv
+# clearenv
+# mktemp
+# mkstemp
+# mkstemps
+# mkdtemp
+# system
+# realpath
+# __compar_fn_t
+# bsearch
+# qsort
+# abs
+# labs
+# llabs
+# div
+# ldiv
+# lldiv
+# ecvt
+# fcvt
+# gcvt
+# qecvt
+# qfcvt
+# qgcvt
+# ecvt_r
+# fcvt_r
+# qecvt_r
+# qfcvt_r
+# mblen
+# mbtowc
+# wctomb
+# mbstowcs
+# wcstombs
+# rpmatch
+# getsubopt
+# getloadavg
+# _mm_hint
+# __m128
+# __m128_u
+# __v4sf
+# __v2df
+# __v2di
+# __v2du
+# __v4si
+# __v4su
+# __v8hi
+# __v8hu
+# __v16qi
+# __v16qs
+# __v16qu
+# __m128i
+# __m128d
+# __m128i_u
+# __m128d_u
+# __cl_float4
+# __cl_uchar16
+# __cl_char16
+# __cl_ushort8
+# __cl_short8
+# __cl_uint4
+# __cl_int4
+# __cl_ulong2
+# __cl_long2
+# __cl_double2
+# __cl_uchar8
+# __cl_char8
+# __cl_ushort4
+# __cl_short4
+# __cl_uint2
+# __cl_int2
+# __cl_ulong1
+# __cl_long1
+# __cl_float2
+# cl_char2
+# cl_char4
+# cl_char3
+# cl_char8
+# cl_char16
+# cl_uchar2
+# cl_uchar4
+# cl_uchar3
+# cl_uchar8
+# cl_uchar16
+# cl_short2
+# cl_short4
+# cl_short3
+# cl_short8
+# cl_short16
+# cl_ushort2
+# cl_ushort4
+# cl_ushort3
+# cl_ushort8
+# cl_ushort16
+# cl_int2
+# cl_int4
+# cl_int3
+# cl_int8
+# cl_int16
+# cl_uint2
+# cl_uint4
+# cl_uint3
+# cl_uint8
+# cl_uint16
+# cl_long2
+# cl_long4
+# cl_long3
+# cl_long8
+# cl_long16
+# cl_ulong2
+# cl_ulong4
+# cl_ulong3
+# cl_ulong8
+# cl_ulong16
+# cl_float2
+# cl_float4
+# cl_float3
+# cl_float8
+# cl_float16
+# cl_double2
+# cl_double4
+# cl_double3
+# cl_double8
+# cl_double16
+# cl_platform_id
+# cl_device_id
+# cl_context
+# cl_command_queue
+# cl_mem
+# cl_program
+# cl_kernel
+# cl_event
+# cl_sampler
+# cl_bool
+# cl_bitfield
+# cl_device_type
+# cl_platform_info
+# cl_device_info
+# cl_device_fp_config
+# cl_device_mem_cache_type
+# cl_device_local_mem_type
+# cl_device_exec_capabilities
+# cl_device_svm_capabilities
+# cl_command_queue_properties
+# cl_device_partition_property
+# cl_device_affinity_domain
+# cl_context_properties
+# cl_context_info
+# cl_queue_properties
+# cl_command_queue_info
+# cl_channel_order
+# cl_channel_type
+# cl_mem_flags
+# cl_svm_mem_flags
+# cl_mem_object_type
+# cl_mem_info
+# cl_mem_migration_flags
+# cl_image_info
+# cl_buffer_create_type
+# cl_addressing_mode
+# cl_filter_mode
+# cl_sampler_info
+# cl_map_flags
+# cl_pipe_properties
+# cl_pipe_info
+# cl_program_info
+# cl_program_build_info
+# cl_program_binary_type
+# cl_build_status
+# cl_kernel_info
+# cl_kernel_arg_info
+# cl_kernel_arg_address_qualifier
+# cl_kernel_arg_access_qualifier
+# cl_kernel_arg_type_qualifier
+# cl_kernel_work_group_info
+# cl_kernel_sub_group_info
+# cl_event_info
+# cl_command_type
+# cl_profiling_info
+# cl_sampler_properties
+# cl_kernel_exec_info
+# _cl_image_format
+# cl_image_format
+# _cl_image_desc
+# cl_image_desc
+# _cl_buffer_region
+# cl_buffer_region
+# clGetPlatformIDs
+# clGetPlatformInfo
+# clGetDeviceIDs
+# clGetDeviceInfo
+# clCreateSubDevices
+# clRetainDevice
+# clReleaseDevice
+# clSetDefaultDeviceCommandQueue
+# clGetDeviceAndHostTimer
+# clGetHostTimer
+# clCreateContext
+# clCreateContextFromType
+# clRetainContext
+# clReleaseContext
+# clGetContextInfo
+# clCreateCommandQueueWithProperties
+# clRetainCommandQueue
+# clReleaseCommandQueue
+# clGetCommandQueueInfo
+# clCreateBuffer
+# clCreateSubBuffer
+# clCreateImage
+# clCreatePipe
+# clRetainMemObject
+# clReleaseMemObject
+# clGetSupportedImageFormats
+# clGetMemObjectInfo
+# clGetImageInfo
+# clGetPipeInfo
+# clSetMemObjectDestructorCallback
+# clSVMAlloc
+# clSVMFree
+# clCreateSamplerWithProperties
+# clRetainSampler
+# clReleaseSampler
+# clGetSamplerInfo
+# clCreateProgramWithSource
+# clCreateProgramWithBinary
+# clCreateProgramWithBuiltInKernels
+# clCreateProgramWithIL
+# clRetainProgram
+# clReleaseProgram
+# clBuildProgram
+# clCompileProgram
+# clLinkProgram
+# clUnloadPlatformCompiler
+# clGetProgramInfo
+# clGetProgramBuildInfo
+# clCreateKernel
+# clCreateKernelsInProgram
+# clCloneKernel
+# clRetainKernel
+# clReleaseKernel
+# clSetKernelArg
+# clSetKernelArgSVMPointer
+# clSetKernelExecInfo
+# clGetKernelInfo
+# clGetKernelArgInfo
+# clGetKernelWorkGroupInfo
+# clGetKernelSubGroupInfo
+# clWaitForEvents
+# clGetEventInfo
+# clCreateUserEvent
+# clRetainEvent
+# clReleaseEvent
+# clSetUserEventStatus
+# clSetEventCallback
+# clGetEventProfilingInfo
+# clFlush
+# clFinish
+# clEnqueueReadBuffer
+# clEnqueueReadBufferRect
+# clEnqueueWriteBuffer
+# clEnqueueWriteBufferRect
+# clEnqueueFillBuffer
+# clEnqueueCopyBuffer
+# clEnqueueCopyBufferRect
+# clEnqueueReadImage
+# clEnqueueWriteImage
+# clEnqueueFillImage
+# clEnqueueCopyImage
+# clEnqueueCopyImageToBuffer
+# clEnqueueCopyBufferToImage
+# clEnqueueMapBuffer
+# clEnqueueMapImage
+# clEnqueueUnmapMemObject
+# clEnqueueMigrateMemObjects
+# clEnqueueNDRangeKernel
+# clEnqueueNativeKernel
+# clEnqueueMarkerWithWaitList
+# clEnqueueBarrierWithWaitList
+# clEnqueueSVMFree
+# clEnqueueSVMMemcpy
+# clEnqueueSVMMemFill
+# clEnqueueSVMMap
+# clEnqueueSVMUnmap
+# clEnqueueSVMMigrateMem
+# clGetExtensionFunctionAddressForPlatform
+# clCreateImage2D
+# clCreateImage3D
+# clEnqueueMarker
+# clEnqueueWaitForEvents
+# clEnqueueBarrier
+# clUnloadCompiler
+# clGetExtensionFunctionAddress
+# clCreateCommandQueue
+# clCreateSampler
+# clEnqueueTask
+# __pthread_cond_s___wseq32
+# __pthread_cond_s___g1_start32
+# ()v
+# (i32u64:v)v
+# (u64:vu64:v)i32
+# (u64:i8u64:vu64u64:v)v
+# (u64:${_cl_mem}u64:v)v
+# (u64:${_cl_program}u64:v)v
+# (u64:${_cl_event}i32u64:v)v
+# (u64:v)v
+# (u64:${_cl_command_queue}u32u64:u64:vu64:v)v
+);
diff --git a/src/notzed.zcl/gen/opencl.txt b/src/notzed.zcl/gen/opencl.txt
new file mode 100644 (file)
index 0000000..fa360b3
--- /dev/null
@@ -0,0 +1,108 @@
+clGetPlatformIDs
+clGetPlatformInfo
+clGetDeviceIDs
+clGetDeviceInfo
+clCreateSubDevices
+clRetainDevice
+clReleaseDevice
+clSetDefaultDeviceCommandQueue
+clGetDeviceAndHostTimer
+clGetHostTimer
+clCreateContext
+clCreateContextFromType
+clRetainContext
+clReleaseContext
+clGetContextInfo
+clCreateCommandQueueWithProperties
+clRetainCommandQueue
+clReleaseCommandQueue
+clGetCommandQueueInfo
+clCreateBuffer
+clCreateSubBuffer
+clCreateImage
+clCreatePipe
+clRetainMemObject
+clReleaseMemObject
+clGetSupportedImageFormats
+clGetMemObjectInfo
+clGetImageInfo
+clGetPipeInfo
+clSetMemObjectDestructorCallback
+clSVMAlloc
+clSVMFree
+clCreateSamplerWithProperties
+clRetainSampler
+clReleaseSampler
+clGetSamplerInfo
+clCreateProgramWithSource
+clCreateProgramWithBinary
+clCreateProgramWithBuiltInKernels
+clCreateProgramWithIL
+clRetainProgram
+clReleaseProgram
+clBuildProgram
+clCompileProgram
+clLinkProgram
+clUnloadPlatformCompiler
+clGetProgramInfo
+clGetProgramBuildInfo
+clCreateKernel
+clCreateKernelsInProgram
+clCloneKernel
+clRetainKernel
+clReleaseKernel
+clSetKernelArg
+clSetKernelArgSVMPointer
+clSetKernelExecInfo
+clGetKernelInfo
+clGetKernelArgInfo
+clGetKernelWorkGroupInfo
+clGetKernelSubGroupInfo
+clWaitForEvents
+clGetEventInfo
+clCreateUserEvent
+clRetainEvent
+clReleaseEvent
+clSetUserEventStatus
+clSetEventCallback
+clGetEventProfilingInfo
+clFlush
+clFinish
+clEnqueueReadBuffer
+clEnqueueReadBufferRect
+clEnqueueWriteBuffer
+clEnqueueWriteBufferRect
+clEnqueueFillBuffer
+clEnqueueCopyBuffer
+clEnqueueCopyBufferRect
+clEnqueueReadImage
+clEnqueueWriteImage
+clEnqueueFillImage
+clEnqueueCopyImage
+clEnqueueCopyImageToBuffer
+clEnqueueCopyBufferToImage
+clEnqueueMapBuffer
+clEnqueueMapImage
+clEnqueueUnmapMemObject
+clEnqueueMigrateMemObjects
+clEnqueueNDRangeKernel
+clEnqueueNativeKernel
+clEnqueueMarkerWithWaitList
+clEnqueueBarrierWithWaitList
+clEnqueueSVMFree
+clEnqueueSVMMemcpy
+clEnqueueSVMMemFill
+clEnqueueSVMMap
+clEnqueueSVMUnmap
+clEnqueueSVMMigrateMem
+clGetExtensionFunctionAddressForPlatform
+clCreateImage2D
+clCreateImage3D
+clEnqueueMarker
+clEnqueueWaitForEvents
+clEnqueueBarrier
+clUnloadCompiler
+clGetExtensionFunctionAddress
+clCreateCommandQueue
+clCreateSampler
+clEnqueueTask
diff --git a/src/notzed.zcl/jni/jni.make b/src/notzed.zcl/jni/jni.make
deleted file mode 100644 (file)
index 611bab7..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2015,2019 Michael Zucchi
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-notzed.zcl_JNI_LIBRARIES=zcl
-
-linux-amd64_zcl_SOURCES = zcl-init-so.c
-linux-amd64_zcl_LDLIBS = -L$(NATIVEZ_HOME)/lib -lnativez -dl
-
-windows-amd64_zcl_SOURCES = zcl-init-dll.c
-windows-amd64_zcl_LDLIBS = -L$(NATIVEZ_HOME)/bin -lnativez
-
-zcl_SOURCES=zcl-jni.c                          \
-       zcl-khr-gl-event.c                      \
-       zcl-khr-gl-sharing.c                    \
-       $($(TARGET)_zcl_SOURCES)
-
-zcl_CPPFLAGS=-Isrc/notzed.zcl/jni/include      \
-       -I$(notzed.zcl_jnidir)                  \
-       -Wno-deprecated-declarations            \
-       -I$(NATIVEZ_HOME)/include
-
-zcl_LDLIBS=$($(TARGET)_zcl_LDLIBS)
-zcl_DEFS=zcl-jni.def
-
-$(addprefix $(notzed.zcl_objdir)/,$(zcl_SOURCES:.c=.o)): bin/include/notzed.zcl/zcl-functions.h
-bin/include/notzed.zcl/zcl-functions.h: src/notzed.zcl/jni/include/CL/cl.h src/notzed.zcl/jni/zcl-generate
-       @install -d $(@D)
-       src/notzed.zcl/jni/zcl-generate $< > $@.tmp
-       install -C $@.tmp $@
diff --git a/src/notzed.zcl/jni/zcl-extension.h b/src/notzed.zcl/jni/zcl-extension.h
deleted file mode 100644 (file)
index dc49b67..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Zucchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-  Common definitions.
-  Header file for extension handlers.
- */
-#ifndef ZCL_EXTENSION_H
-#define ZCL_EXTENSION_H
-
-jobject createExtension(JNIEnv *env, void *p, const char *className);
-
-jobject createExtension_cl_khr_gl_sharing(JNIEnv *env, cl_platform_id platform);
-jobject createExtension_cl_khr_gl_event(JNIEnv *env, cl_platform_id platform);
-
-void *getExtensionAddress(cl_platform_id platform, const char *func);
-
-/* Utility functions */
-/* Convert property array to array, result must be freed if not null */
-void *fromPropertyArray(JNIEnv *env, jobjectArray jpropArray);
-
-/* CLObjects */
-jobject toCLObject(JNIEnv *env, int, void *p);
-jobject toCLObjectArray(JNIEnv *env, int ctype, size_t count, void **ptrs);
-int fromObjectArray(JNIEnv *env, jobjectArray jobjects, void **dst, int size);
-jobject toArray(JNIEnv *env, int ctype, size_t size, void *value);
-jobject toObject(JNIEnv *env, int ctype, size_t size, void *value);
-
-/* Exceptions */
-
-#define THROW_ERROR_RET(res, ret) if (res != CL_SUCCESS) { throwCLException(env, res); return ret; }
-#define THROW_ERROR(res) if (res != CL_SUCCESS) { throwCLException(env, res); return; }
-
-#define THROW_RTERROR_RET(res, ret) if (res != CL_SUCCESS) { throwCLRuntimeException(env, res); return ret; }
-#define THROW_RTERROR(res) if (res != CL_SUCCESS) { throwCLRuntimeException(env, res); return; }
-
-#define C2J(x) ((jlong)(uintptr_t)(x))
-#define J2C(x) ((void *)(uintptr_t)(x))
-
-void throwCLException(JNIEnv *env, jint id);
-void throwCLRuntimeException(JNIEnv *env, jint id);
-void throwException(JNIEnv *env, const char *type, const char *msg);
-void throwUnsupportedOperation(JNIEnv *env, const char *fail);
-
-#define THROW_UNSUPPORTED_RET(fn, fail, ret) do { if (!fn) { throwUnsupportedOperation(env, fail); return ret; } } while (0)
-#define THROW_UNSUPPORTED(fn, fail) do { if (!fn) { throwUnsupportedOperation(env, fail); return; } } while (0)
-
-/* Events */
-
-#define EVENTS_MAX 28
-
-struct events_info {
-       cl_int wait_count;
-       cl_event *waitersp;
-       cl_event *eventp;
-
-       cl_event waiters[EVENTS_MAX];
-       cl_event event;
-};
-
-int events_init(JNIEnv *env, struct events_info *einfo, jobject jwaiters, jobject jevents);
-int events_post(JNIEnv *env, struct events_info *einfo, jobject jevents);
-
-/* Entry point for dynamic loader init & submodules, return 0 on success */
-int init_dynamic(JNIEnv *env);
-
-#endif
diff --git a/src/notzed.zcl/jni/zcl-generate b/src/notzed.zcl/jni/zcl-generate
deleted file mode 100755 (executable)
index fc0de43..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/perl
-
-# Copyright (C) 2015 Michael Zucchi
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#
-# Compiles cl.h into function types and useful tables
-#
-# Fortunately cl.h is very strictly formatted so this is a simple task.
-#
-
-# $1 == cl header files
-$cl_h = $ARGV[0];
-
-@fn = ();
-%fnproto = {};
-$fnprefix = {};
-$fnsuffix = {};
-
-open (H, "$cl_h") || die ("Can't open");
-while (<H>) {
-    if (m/^extern (CL_API_ENTRY.*)/) {
-       $start = $1;
-       $proto = "";
-       while (<H>) {
-           chop($_);
-           $proto .= $_." ";
-           last if (m/;/);
-       }
-
-       $proto =~ s@/\*.*?\*/@@g;
-       $proto =~ s@ +@ @g;
-
-       if ($proto =~ m/^(\w+)(\(.*)/) {
-           $f = $1;
-
-           push @fn, $f;
-           $fnprefix{$f} = $start;
-           $fnsuffix{$f} = $2;
-       }
-    }
-}
-
-print "#ifndef _ZCL_FUNCIONS_H\n";
-print "/* Autogenerated by zcl-generate from $cl_h */\n\n";
-print "// Function types\n";
-for $f (@fn) {
-    print "typedef $fnprefix{$f} (*$f"."_fn) $fnsuffix{$f}\n";
-}
-
-print "#define zcl_fn_SIZEOF ".($#fn + 1)."\n";
-
-print "#ifdef ZCL_DL_TABLE\n";
-print "// Entry point names\n";
-print "const char const * zcl_fn[] = {\n";
-for $f (@fn) {
-    print "\t\"$f\",\n";
-}
-print "};\n";
-print "// Entry point addresses\n";
-print "const void *zcl_fp[zcl_fn_SIZEOF];\n";
-print "#else\n";
-print "// Entry point names\n";
-print "extern const char const * zcl_fn[zcl_fn_SIZEOF];\n";
-print "// Entry point addresses\n";
-print "extern const void *zcl_fp[zcl_fn_SIZEOF];\n";
-print "#endif\n";
-
-print "// Invoke Macros\n";
-$i = 0;
-for $f (@fn) {
-    print "#define $f (($f"."_fn)zcl_fp[$i])\n";
-    $i++;
-}
-
-print "// Checking macros\n";
-$i = 0;
-for $f (@fn) {
-    $prefix = $fnprefix{$f};
-    $suffix = $fnsuffix{$f};
-
-    print "#define CHECK_$f() (zcl_fp[$i])\n";
-    print "#define FAIL_$f() do { if (!zcl_check_fn(env, $i)) return; } while (0)\n";
-    print "#define FAIL_".$f."_RET(r) do { if (!zcl_check_fn(env, $i)) return (r); } while (0)\n";
-    $i++;
-}
-
-print "#endif /* _ZCL_FUNCTIONS_H */\n";
diff --git a/src/notzed.zcl/jni/zcl-init-dll.c b/src/notzed.zcl/jni/zcl-init-dll.c
deleted file mode 100644 (file)
index 1a9a10e..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Zucchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-  shared library init for mingwin
- */
-
-#include <windows.h>
-
-#include <CL/cl.h>
-#include <jni.h>
-
-#include "zcl-extension.h"
-
-#define ZCL_DL_TABLE 1
-#include "zcl-functions.h"
-
-static void *lib_opencl;
-
-int init_dynamic(JNIEnv *env) {
-       lib_opencl = LoadLibrary("OpenCL.dll");
-
-       if (lib_opencl) {
-               for (int i=0;i<zcl_fn_SIZEOF;i++)
-                       zcl_fp[i] = GetProcAddress(lib_opencl, zcl_fn[i]);
-               return 0;
-       }
-
-       return -1;
-}
diff --git a/src/notzed.zcl/jni/zcl-jni.c b/src/notzed.zcl/jni/zcl-jni.c
deleted file mode 100644 (file)
index b4e6fce..0000000
+++ /dev/null
@@ -1,4930 +0,0 @@
-/*
- * Copyright (C) 2014,2015,2019 Michael Zucchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-#include <string.h>
-#include "nativez.h"
-
-#include "au_notzed_zcl_CLBuffer.h"
-#include "au_notzed_zcl_CLCommandQueue.h"
-#include "au_notzed_zcl_CLContext.h"
-#include "au_notzed_zcl_CLDevice.h"
-#include "au_notzed_zcl_CLEvent.h"
-#include "au_notzed_zcl_CLEventList.h"
-#include "au_notzed_zcl_CLImage.h"
-#include "au_notzed_zcl_CLKernel.h"
-#include "au_notzed_zcl_CLMemory.h"
-#include "au_notzed_zcl_CLObject.h"
-#include "au_notzed_zcl_CLPlatform.h"
-#include "au_notzed_zcl_CLProgram.h"
-
-#include <CL/cl.h>
-
-#include "zcl-extension.h"
-#include "zcl-functions.h"
-#include "zcl-jni.h"
-
-// "real" version isn't what cl.h reports
-#ifdef VERSION_IS_1_0
-#undef CL_VERSION_1_1
-#endif
-
-/**
- * Primitive array transfers can only be blocking on OpenCL 1.0
- *
- * Note however that for simplicity all primtiive array operations are blocking.
- */
-#ifdef CL_VERSION_1_1
-#define PRIMITIVE_BLOCKING(x) 1 // x
-#else
-#define PRIMITIVE_BLOCKING(x) 1
-#endif
-
-#ifndef CL_VERSION_1_2
-typedef struct _cl_image_desc {
-    cl_mem_object_type      image_type;
-    size_t                  image_width;
-    size_t                  image_height;
-    size_t                  image_depth;
-    size_t                  image_array_size;
-    size_t                  image_row_pitch;
-    size_t                  image_slice_pitch;
-    cl_uint                 num_mip_levels;
-    cl_uint                 num_samples;
-    cl_mem                  buffer;
-} cl_image_desc;
-#endif
-
-/* ********************************************************************** */
-/* Helpers */
-
-#define D(x) //x; fflush(stdout)
-
-typedef void (JNICALL *getArrayRegion_t)(JNIEnv *env, jarray array, jsize start, jsize len, void *buf);
-typedef void (JNICALL *setArrayRegion_t)(JNIEnv *env, jarray array, jsize start, jsize len, const void *buf);
-
-typedef void (JNICALL *getArrayRect_t)(JNIEnv *env, jarray array, jsize start, size_t region[3], jlong row_pitch, jlong slice_pitch, void *buf);
-typedef void (JNICALL *setArrayRect_t)(JNIEnv *env, jarray array, jsize start, size_t region[3], jlong row_pitch, jlong slice_pitch, void *buf);
-
-// read or write
-typedef void (JNICALL *copyRegion_t)(JNIEnv *env, jarray array, jsize start, jsize len, void *buf);
-
-// Read/write functions follow the same pattern, use it to reuse some code
-typedef CL_API_ENTRY cl_int CL_API_CALL
-(*enqueueReadWriteBuffer_t)(cl_command_queue    /* command_queue */,
-                         cl_mem              /* buffer */,
-                         cl_bool             /* blocking_read */,
-                         size_t              /* offset */,
-                         size_t              /* size */, 
-                         void *              /* ptr */,
-                         cl_uint             /* num_events_in_wait_list */,
-                         const cl_event *    /* event_wait_list */,
-                         cl_event *          /* event */);
-
-typedef CL_API_ENTRY cl_int CL_API_CALL
-(*enqueueReadWriteBufferRect_t)(cl_command_queue    /* command_queue */,
-                               cl_mem              /* buffer */,
-                               cl_bool             /* blocking_read */,
-                               const size_t *      /* buffer_offset */,
-                               const size_t *      /* host_offset */, 
-                               const size_t *      /* region */,
-                               size_t              /* buffer_row_pitch */,
-                               size_t              /* buffer_slice_pitch */,
-                               size_t              /* host_row_pitch */,
-                               size_t              /* host_slice_pitch */,                        
-                               void *              /* ptr */,
-                               cl_uint             /* num_events_in_wait_list */,
-                               const cl_event *    /* event_wait_list */,
-                               cl_event *          /* event */);
-
-typedef CL_API_ENTRY cl_int CL_API_CALL
-(*enqueueReadWriteImage_t)(cl_command_queue     /* command_queue */,
-                        cl_mem               /* image */,
-                        cl_bool              /* blocking_read */, 
-                        const size_t *       /* origin[3] */,
-                        const size_t *       /* region[3] */,
-                        size_t               /* row_pitch */,
-                        size_t               /* slice_pitch */, 
-                        void *               /* ptr */,
-                        cl_uint              /* num_events_in_wait_list */,
-                        const cl_event *     /* event_wait_list */,
-                        cl_event *           /* event */);
-
-
-static const char * const names[au_notzed_zcl_CLObject_CTYPE_SIZEOF] = {
-       "CLPlatform",
-       "CLDevice",
-       "CLContext",
-       "CLCommandQueue",
-       "CLPipe",
-       "CLBuffer",
-       "CLImage",
-       "CLSampler",
-       "CLProgram",
-       "CLKernel",
-       "CLEvent"
-};
-
-size_t const ctype_sizes[] = {
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       sizeof(void *),
-       0, // reserves
-       0,
-       0,
-       0,
-       0,
-       sizeof(size_t),
-       1, // byte
-       2, // short
-       4, // int
-       8, // long
-       4, // float
-       8, // double
-};
-
-static JavaVM *vm;
-
-static jclass classid[au_notzed_zcl_CLObject_CTYPE_SIZEOF];
-
-/* special constructor for handling notify */
-static jmethodID CLContext_new_pn;
-/* special constructor for handling buffer */
-static jmethodID CLBuffer_new_jb;
-
-static int debug_sync = 0;
-
-/* ********************************************************************** */
-
-jint JNI_OnLoad(JavaVM *vmi, void *reserved) {
-       jclass jc;
-       char name[64];
-       JNIEnv *env;
-
-       D(printf("libclz.so: OnLoad()\n"));
-
-       /* Save VM - required for callbacks from threads */
-       vm = vmi;
-
-       if ((*vmi)->GetEnv(vmi, (void *)&env, JNI_VERSION_1_4) < 0)
-               return 0;
-
-       /* Lookup and save all the class / method / field handles */
-       for (int i=0;i<au_notzed_zcl_CLObject_CTYPE_SIZEOF;i++) {
-               sprintf(name, "au/notzed/zcl/%s", names[i]);
-
-               jc = (*env)->FindClass(env, name);
-               if (jc == NULL) {
-                       fprintf(stderr, "class not found: %s\n", name);
-                       return 0;
-               }
-
-               classid[i] = jc = (*env)->NewGlobalRef(env, jc);
-       }
-
-       CLContext_new_pn = (*env)->GetMethodID(env, classid[au_notzed_zcl_CLObject_CTYPE_CONTEXT], "<init>", "(JLau/notzed/zcl/CLContextNotify;)V");
-       CLBuffer_new_jb = (*env)->GetMethodID(env, classid[au_notzed_zcl_CLObject_CTYPE_BUFFER], "<init>", "(JLjava/nio/ByteBuffer;)V");
-
-       if (nativez_OnLoad(vmi, env)
-           || init_dynamic(env)
-           || nativez_ResolveReferences(env, java_names, &java) != 0)
-               return 0;
-
-       char *s = getenv("ZCL_SYNC");
-       if (s)
-               debug_sync = atoi(s);
-       
-       return JNI_VERSION_1_4;
-}
-
-static int zcl_check_fn(JNIEnv *env, int fid) {
-       int ok = zcl_fp[fid] != NULL;
-
-       if (!ok)
-               throwException(env, "java/lang/UnsupportedOperationException", zcl_fn[fid]);
-       
-       return ok;
-}
-
-void throwCLException(JNIEnv *env, jint id) {
-       jclass jc = (*env)->FindClass(env, "au/notzed/zcl/CLException");
-       jmethodID new_i = (*env)->GetMethodID(env, jc, "<init>", "(I)V");
-       jobject ex = (*env)->NewObject(env, jc, new_i, id);
-
-       (*env)->Throw(env, ex); 
-}
-
-void throwCLRuntimeException(JNIEnv *env, jint id) {
-       jclass jc = (*env)->FindClass(env, "au/notzed/zcl/CLRuntimeException");
-       jmethodID new_i = (*env)->GetMethodID(env, jc, "<init>", "(I)V");
-       jobject ex = (*env)->NewObject(env, jc, new_i, id);
-
-       (*env)->Throw(env, ex); 
-}
-
-void throwException(JNIEnv *env, const char *type, const char *msg) {
-       jclass jc = (*env)->FindClass(env, type);
-
-       if (jc)
-               (*env)->ThrowNew(env, jc, msg);
-}
-
-void throwUnsupportedOperation(JNIEnv *env, const char *fail) {
-       throwException(env, "java/lang/UnsupportedOperationException", fail);
-}
-
-#define GETP(env, o) NativeZ_getP(env, o)
-
-static int check_p(JNIEnv *env, jobject src, void **dst, const char *fail) {
-       if (!src) {
-               throwException(env, "java/lang/NullPointerException", fail);
-               return 1;
-       }
-
-       *dst = GETP(env, src);
-
-       return 0;
-}
-
-#define GET_P(env, jval, val, ret, error) do { if (check_p(env, jval, (void **)&val, error)) return ret; } while (0)
-
-static int check_array_min(JNIEnv *env, jobject src, jsize min, const char *fail) {
-       jsize size;
-
-       if (!src) {
-               throwException(env, "java/lang/NullPointerException", fail);
-               return 1;
-       }
-
-       size = (*env)->GetArrayLength(env, src);
-       if (size < min) {
-               throwException(env, "java/lang/ArrayIndexOutOfBoundsException", fail);
-               return 1;
-       }
-
-       return 0;
-}
-
-#define CHECK_ARRAY_MIN(env, jval, min, ret, error) do { if (check_array_min(env, jval, min, error)) return ret; } while (0)
-
-static int check_null(JNIEnv *env, jobject jo, const char *fail) {
-       if (!jo) {
-               throwException(env, "java/lang/NullPointerException", fail);
-               return 1;
-       }
-       return 0;
-}
-
-#define CHECK_NULL(env, jo, ret, error)  do { if (check_null(env, jo, error)) return ret; } while (0)
-
-int fromObjectArray(JNIEnv *env, jobjectArray jobjects, void **dst, int size) {
-       for (int i=0;i<size;i++) {
-               jobject jo = (*env)->GetObjectArrayElement(env, jobjects, i);
-
-               dst[i] = GETP(env, jo);
-       }
-
-       return 0;
-}
-
-jobject toCLObject(JNIEnv *env, int id, void *p) {
-       if (id < au_notzed_zcl_CLObject_CTYPE_SIZEOF) {
-               return NativeZ_resolve(env, classid[id], p);
-       } else {
-               throwCLRuntimeException(env, CL_INVALID_VALUE);
-               return NULL;
-       }
-}
-
-/* unified object instantiator for CLObject and boxed primitive types */
-jobject toObject(JNIEnv *env, int ctype, size_t size, void *value) {
-       jobject jres = NULL;
-       jvalue jarg;
-       
-       switch (ctype) {
-               //case  au_notzed_zcl_CLObject_CTYPE_BYTE:
-       case  au_notzed_zcl_CLObject_CTYPE_INT:
-               jarg.i = ((cl_int *)value)[0];
-               jres = (*env)->CallStaticObjectMethodA(env, Integer_classid, Integer_valueOf_i, &jarg);
-               break;
-       case  au_notzed_zcl_CLObject_CTYPE_LONG:
-               jarg.j = ((cl_long *)value)[0];
-               jres = (*env)->CallStaticObjectMethodA(env, Long_classid, Long_valueOf_j, &jarg);
-               break;
-       case  au_notzed_zcl_CLObject_CTYPE_SIZE_T:
-               jarg.j = ((size_t *)value)[0];
-               jres = (*env)->CallStaticObjectMethodA(env, Long_classid, Long_valueOf_j, &jarg);
-               break;
-       default:
-               jres = toCLObject(env, ctype, ((void **)value)[0]);
-               break;
-       }
-       
-       return jres;
-}
-
-jobject toCLObjectArray(JNIEnv *env, int ctype, size_t count, void **ptrs) {
-       jobject jvalue = NULL;
-       
-       if (ctype < au_notzed_zcl_CLObject_CTYPE_SIZEOF) {
-               jvalue = (*env)->NewObjectArray(env, count, classid[ctype], NULL);
-               if (jvalue) {
-                       for (int i=0;i<count;i++) {
-                               jobject o = toCLObject(env, ctype, ptrs[i]);
-                               
-                               (*env)->SetObjectArrayElement(env, jvalue, i, o);
-                       }
-               }
-       } else {
-               throwCLRuntimeException(env, CL_INVALID_VALUE);
-       }
-
-       return jvalue;
-}
-
-/* unified array builder based on CTYPE* defines */
-jobject toArray(JNIEnv *env, int ctype, size_t size, void *value) {
-       jobject jvalue = NULL;
-       int count;
-
-       switch (ctype) {
-       case  au_notzed_zcl_CLObject_CTYPE_BYTE:
-               count = size;
-               jvalue = (*env)->NewByteArray(env, count);
-               if (jvalue)
-                       (*env)->SetByteArrayRegion(env, jvalue, 0, count, (jbyte *)value);
-               break;
-       case  au_notzed_zcl_CLObject_CTYPE_INT:
-               count = size / sizeof(cl_int);
-               jvalue = (*env)->NewIntArray(env, count);
-               if (jvalue)
-                       (*env)->SetIntArrayRegion(env, jvalue, 0, count, (jint *)value);
-               break;
-       case  au_notzed_zcl_CLObject_CTYPE_LONG:
-               count = size / sizeof(cl_long);
-               jvalue = (*env)->NewLongArray(env, count);
-               if (jvalue)
-                       (*env)->SetLongArrayRegion(env, jvalue, 0, count, (jlong *)value);
-               break;
-       case  au_notzed_zcl_CLObject_CTYPE_SIZE_T:
-               count = size / sizeof(size_t);
-               jvalue = (*env)->NewLongArray(env, count);
-               if (jvalue) {
-                       if (sizeof(size_t) == sizeof(jlong)) {
-                               (*env)->SetLongArrayRegion(env, jvalue, 0, count, (jlong *)value);
-                       } else {
-                               jlong *tmp = alloca(count * sizeof(*tmp));
-                               size_t *data = value;
-
-                               for (int i=0;i<count;i++)
-                                       tmp[i] = (jlong)data[i];
-               
-                               (*env)->SetLongArrayRegion(env, jvalue, 0, count, (jlong *)tmp);
-                       }
-               }
-               break;
-       default:
-               jvalue = toCLObjectArray(env, ctype, size / sizeof(void *), value);
-               break;
-       }
-       
-       return jvalue;
-}
-
-/* Convert a tag/value property array to a primitive array */
-void *fromPropertyArray(JNIEnv *env, jobjectArray jpropArray) {
-#if UINTPTR_MAX == 0xffffffffU
-       jint *res = NULL;
-       
-       if (jpropArray) {
-               jvalue jargs = { .l = jpropArray };
-               jlongArray ptmp = (*env)->CallStaticObjectMethodA(env, CLProperty_classid, CLProperty_toInt__l, &jargs);
-               
-               if (!(*env)->ExceptionCheck(env)) {
-                       jint plen = (*env)->GetArrayLength(env, ptmp);
-                       res = malloc(sizeof(*res) * plen);
-                       if (res)
-                               (*env)->GetIntArrayRegion(env, ptmp, 0, plen, res);
-                       else
-                               throwException(env, "java/lang/OutOfMemoryError", "Allocating propery list");
-               }
-       }
-       return res;
-#else
-       jlong *res = NULL;
-       
-       if (jpropArray) {
-               jvalue jargs = { .l = jpropArray };
-               jlongArray ptmp = (*env)->CallStaticObjectMethodA(env, CLProperty_classid, CLProperty_toLong__l, &jargs);
-               
-               if (!(*env)->ExceptionCheck(env)) {
-                       jint plen = (*env)->GetArrayLength(env, ptmp);
-                       res = malloc(sizeof(*res) * plen);
-                       if (res)
-                               (*env)->GetLongArrayRegion(env, ptmp, 0, plen, res);
-                       else
-                               throwException(env, "java/lang/OutOfMemoryError", "Allocating property list");
-               }
-       }
-       return res;
-
-#endif
-}
-
-/**
- * Convert a jlongArray to a size_t *
- */
-static void getSizeTA(JNIEnv *env, jlongArray jsrc, size_t *dst, size_t count) {
-       memset(dst, 0, sizeof(*dst) * count);
-       if (jsrc) {
-               if (sizeof(size_t) == sizeof(jlong))
-                       (*env)->GetLongArrayRegion(env, jsrc, 0, count, (jlong *)dst);
-               else {
-                       jlong *jdst = alloca(sizeof(*jdst) * count);
-                       (*env)->GetLongArrayRegion(env, jsrc, 0, count, jdst);
-                       for (int i=0;i<count;i++)
-                               dst[i] = (size_t)jdst[i];
-               }
-       }
-}
-
-static jint getAPIVersion(JNIEnv *env, jobject jo) {
-       return (*env)->GetIntField(env, jo, CLExtendable_apiVersion);
-}
-
-static int checkAPIVersion(JNIEnv *env, jobject jo, jint version) {
-       return getAPIVersion(env, jo) >= version;
-}
-
-/* ********************************************************************** */
-
-/*
-  Some helper code to manage the mess of dealing with CLEventList for
-  waiting and event output.
-
-  The primary task is to copy the CLEventList.events list for the 'waiters'
-  object to a local cl_event array, and after-the-event to invoke
-  CLEventList.add() if an event must be recorded as output.
-
-  See any of the CLCommandQueue.enqueue*() functions for how it's used.
-
-  To avoid the overhead of malloc and the need for alloca() in the callee
-  waiters[] is fixed in size, but that could be changed here.
- */
-int events_init(JNIEnv *env, struct events_info *einfo, jobject jwaiters, jobject jevents) {
-       if (jwaiters) {
-               int count = (*env)->GetIntField(env, jwaiters, CLEventList_index);
-               jlongArray jwaitlist = (*env)->GetObjectField(env, jwaiters, CLEventList_events);
-
-               if (count > EVENTS_MAX) {
-                       throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "Waiting list exceeds internal limit");
-                       return -1;
-               }
-
-               einfo->wait_count = count;
-               einfo->waitersp = &einfo->waiters[0];
-
-               if (sizeof(cl_event) == sizeof(jlong)) {
-                       (*env)->GetLongArrayRegion(env, jwaitlist, 0, count, (jlong *)&einfo->waiters[0]);
-               } else {
-                       jlong *levents = alloca(count * sizeof(*levents));
-                       (*env)->GetLongArrayRegion(env, jwaitlist, 0, count, levents);
-                       for (int i=0;i<count;i++)
-                               einfo->waiters[i] = (cl_event)(uintptr_t)levents[i];
-               }
-       } else {
-               einfo->wait_count = 0;
-               einfo->waitersp = NULL;
-       }
-
-       if (jevents)
-               einfo->eventp = &einfo->event;
-       else
-               einfo->eventp = NULL;
-
-       return 0;
-}
-
-int events_post(JNIEnv *env, struct events_info *einfo, jobject jevents) {
-       if (jevents) {
-               jvalue arg = { .j = (uintptr_t)einfo->event };
-
-               (*env)->CallVoidMethodA(env, jevents, CLEventList_add_j, &arg);
-       }
-
-       return 0;
-}
-
-/* ********************************************************************** */
-/* Build/compile/link notify handler */
-
-struct build_notify_info {
-       cl_program prog;
-       jobject jprog;
-       jobject jnotify;
-};
-
-static struct build_notify_info *build_notify_alloc(JNIEnv *env, cl_program prog, jobject jprog, jobject jnotify) {
-       struct build_notify_info *data = malloc(sizeof(*data));
-
-       if (!data) {
-               throwException(env, "java/lang/OutOfMemoryError", "Allocating hook data");
-               return NULL;
-       }
-       
-       data->prog = prog;
-       data->jnotify = (*env)->NewGlobalRef(env, jnotify);
-       data->jprog = jprog ? (*env)->NewGlobalRef(env, jprog) : NULL;
-
-
-       return data;
-}
-
-static void build_notify_hook(cl_program prog, void *data) {
-       struct build_notify_info *info = data;
-       JNIEnv *env;
-
-       D(printf("build notify()\n"));
-
-       if (!(env = nativez_AttachCurrentThreadAsDaemon())) {
-               // NB: can't do anything here
-               fprintf(stderr, "Unable to attach java environment\n");
-               free(data);
-               return;
-       }
-
-       if (!info->jprog) {
-               /* For linking, this is the first time we've seen the program */
-               jvalue arg = { .l = toCLObject(env, au_notzed_zcl_CLObject_CTYPE_PROGRAM, prog) };
-
-               (*env)->CallVoidMethodA(env, info->jnotify, CLNotify_notify_l, &arg);
-       } else if (info->prog == prog) {
-               jvalue arg = { .l = info->jprog };
-
-               (*env)->CallVoidMethodA(env, info->jnotify, CLNotify_notify_l, &arg);
-       } else {
-               fprintf(stderr, "build_notify_hook given wrong cl_program\n");
-       }
-
-       (*env)->DeleteGlobalRef(env, info->jnotify);
-       if (info->jprog)
-               (*env)->DeleteGlobalRef(env, info->jprog);
-
-       free(info);
-}
-
-/* ********************************************************************** */
-
-/* APIs */
-
-/* ********************************************************************** */
-
-/* CLObject */
-
-/*
-  To cut-down on significant API baggage the getInfo, retain, and
-  release methods are implemented in an object-oriented way using
-  using a manual type specifier.
-
-  Some info queries have target-specific variants.
- */
-
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLSampler_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       cl_int res;
-       FAIL_clReleaseSampler();
-       res = clReleaseSampler((cl_sampler)jp);
-       if (res != CL_SUCCESS)
-               throwCLRuntimeException(env, res);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLProgram_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       cl_int res;
-       FAIL_clReleaseProgram();
-       res = clReleaseProgram((cl_program)jp);
-       if (res != CL_SUCCESS)
-               throwCLRuntimeException(env, res);
-}
-
-/* */
-
-static int getInfo(JNIEnv *env, void *jid, jint type, jint param, size_t size, void *val, void *size_ret) {
-       switch (type) {
-       case  au_notzed_zcl_CLObject_TYPE_PLATFORM:
-               FAIL_clGetPlatformInfo_RET(-1);
-               return clGetPlatformInfo((cl_platform_id)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_DEVICE:
-               FAIL_clGetDeviceInfo_RET(-1);
-               return clGetDeviceInfo((cl_device_id)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_CONTEXT:
-               FAIL_clGetContextInfo_RET(-1);
-               return clGetContextInfo((cl_context)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_COMMAND_QUEUE:
-               FAIL_clGetCommandQueueInfo_RET(-1);
-               return clGetCommandQueueInfo((cl_command_queue)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_MEM_OBJECT:
-               FAIL_clGetMemObjectInfo_RET(-1);
-               return clGetMemObjectInfo((cl_mem)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_IMAGE:
-               FAIL_clGetImageInfo_RET(-1);
-               return clGetImageInfo((cl_mem)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_PIPE:
-#ifdef CL_VERSION_2_0
-               FAIL_clGetPipeInfo_RET(-1);
-               return clGetPipeInfo((cl_mem)jid, param, size, val, size_ret);
-#else
-               return CL_INVALID_OPERATION;
-#endif
-       case  au_notzed_zcl_CLObject_TYPE_SAMPLER:
-               FAIL_clGetSamplerInfo_RET(-1);
-               return clGetSamplerInfo((cl_sampler)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_PROGRAM:
-               FAIL_clGetProgramInfo_RET(-1);
-               return clGetProgramInfo((cl_program)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_KERNEL:
-               FAIL_clGetKernelInfo_RET(-1);
-               return clGetKernelInfo((cl_kernel)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_EVENT:
-               FAIL_clGetEventInfo_RET(-1);
-               return clGetEventInfo((cl_event)jid, param, size, val, size_ret);
-       case  au_notzed_zcl_CLObject_TYPE_EVENT_PROFILING:
-               FAIL_clGetEventProfilingInfo_RET(-1);
-               return clGetEventProfilingInfo((cl_event)jid, param, size, val, size_ret);
-       default:
-               return CL_INVALID_VALUE;
-       }
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLObject_getInfoAny
-(JNIEnv *env, jobject jid, jint type, int otype, jint param) {
-       void *jp = GETP(env, jid);
-       void *value;
-       size_t size = ctype_sizes[otype];
-       cl_int res;
-
-       value = alloca(size);
-       res = getInfo(env, jp, type, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toObject(env, otype, size, value);
-}
-
-JNIEXPORT jint JNICALL Java_au_notzed_zcl_CLObject_getInfoInt
-(JNIEnv *env, jobject jid, jint type, jint param) {
-       void *jp = GETP(env, jid);
-       cl_int res;
-       jint value;
-
-       res = getInfo(env, jp, type, param, sizeof(value), &value, NULL);
-       THROW_RTERROR_RET(res, 0);
-
-       return value;
-}
-
-JNIEXPORT jlong JNICALL Java_au_notzed_zcl_CLObject_getInfoLong
-(JNIEnv *env, jobject jid, jint type, jint param) {
-       void *jp = GETP(env, jid);
-       cl_int res;
-       jlong value;
-
-       res = getInfo(env, jp, type, param, sizeof(value), &value, NULL);
-       THROW_RTERROR_RET(res, 0);
-
-       return value;
-}
-
-JNIEXPORT jlong JNICALL Java_au_notzed_zcl_CLObject_getInfoSizeT
-(JNIEnv *env, jobject jid, jint type, jint param) {
-       void *jp = GETP(env, jid);
-       cl_int res;
-       size_t value;
-
-       res = getInfo(env, jp, type, param, sizeof(value), &value, NULL);
-       THROW_RTERROR_RET(res, 0);
-
-       return value;
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLObject_getInfoAnyV
-(JNIEnv *env, jobject jid, jint type, int otype, jint param) {
-       void *jp = GETP(env, jid);
-       void *value;
-       size_t size;
-       cl_int res;
-
-       res = getInfo(env, jp, type, param, 0, NULL, &size);
-       THROW_RTERROR_RET(res, NULL);
-
-       value = alloca(size);
-
-       res = getInfo(env, jp, type, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toArray(env, otype, size, value);
-}
-
-/*
-  Query a property list and convert it to an array.
-
-  Most properties are simple tag+value pairs but not all so this must
-  handle those specifically.
-*/
-static jobjectArray getInfoProperties
-(JNIEnv *env, jobject jsrc, jint type, jint param, jclass array_classid, jclass new_classid, jmethodID new_tagvalue) {
-       void *src = GETP(env, jsrc);
-       intptr_t *props;
-       cl_int res;
-       size_t size;
-       int count, limit;
-       jobjectArray jprops;
-
-       res = getInfo(env, src, type, param, 0, NULL, &size);
-       THROW_RTERROR_RET(res, NULL);
-
-       if (size == 0)
-               return (*env)->NewObjectArray(env, 0, array_classid, NULL);
-
-       props = alloca(size);
-       res = getInfo(env, src, type, param, size, props, &size);
-       THROW_RTERROR_RET(res, NULL);
-
-       limit = size / sizeof(*props);
-       count = 0;
-       for (int i=0;i < limit && props[i];) {
-               intptr_t p = props[i];
-
-               count += 1;
-
-               switch (p) {
-               case CL_DEVICE_PARTITION_BY_COUNTS:
-                       i++;
-                       while (props[i] != CL_DEVICE_PARTITION_BY_COUNTS_LIST_END)
-                               i++;
-                       break;
-               default:
-                       i += 2;
-                       break;
-               }
-       }
-
-       jprops = (*env)->NewObjectArray(env, count, array_classid, NULL);
-       if (!jprops)
-               return NULL;
-
-       for (int i=0, j=0;i<limit && props[i];j++) {
-               intptr_t p = props[i];
-               jobject jo;
-
-               switch (p) {
-               case CL_DEVICE_PARTITION_BY_COUNTS: {
-                       int start, ccount;
-
-                       i++;
-                       start = i;
-
-                       while (props[i] != CL_DEVICE_PARTITION_BY_COUNTS_LIST_END)
-                               i++;
-                       ccount = i-start;
-
-                       jint *counts = alloca(sizeof(jint) * ccount);
-                       jintArray jcounts = (*env)->NewIntArray(env, ccount);
-
-                       for (int k=0;k<ccount;k++)
-                               counts[k] = (jint)props[start+k];
-
-                       (*env)->SetIntArrayRegion(env, jcounts, 0, ccount, counts);
-
-                       jo = (*env)->NewObject(env,
-                                              CLDeviceProperty_PartitionByCounts_classid,
-                                              CLDeviceProperty_PartitionByCounts_new__i,
-                                              jcounts);
-                       break;
-               }
-               default:
-                       jo = (*env)->NewObject(env, new_classid, new_tagvalue,
-                                              (jlong)props[i],
-                                              (jlong)props[i+1]);
-                       i += 2;
-                       break;
-               }
-
-               (*env)->SetObjectArrayElement(env, jprops, j, jo);
-       }
-
-       return jprops;
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLObject_retain
-(JNIEnv *env, jobject jid, jint type) {
-       void *jp = GETP(env, jid);
-       cl_int res = CL_INVALID_VALUE;
-
-       switch (type) {
-       case  au_notzed_zcl_CLObject_TYPE_PLATFORM:
-               return;
-       case  au_notzed_zcl_CLObject_TYPE_DEVICE:
-#ifdef CL_VERSION_1_2
-               if (CHECK_clRetainDevice())
-                       res = clRetainDevice((cl_device_id)jp);
-               else
-                       return;
-               break;
-#else
-               return;
-#endif
-       case  au_notzed_zcl_CLObject_TYPE_CONTEXT:
-               FAIL_clRetainContext();
-               res = clRetainContext((cl_context)jp);
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_COMMAND_QUEUE:
-               FAIL_clRetainCommandQueue();
-               res = clRetainCommandQueue((cl_command_queue)jp);
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_MEM_OBJECT:
-       case  au_notzed_zcl_CLObject_TYPE_IMAGE:
-       case  au_notzed_zcl_CLObject_TYPE_PIPE:
-               FAIL_clRetainMemObject();
-               res = clRetainMemObject((cl_mem)jp);
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_SAMPLER:
-               FAIL_clRetainSampler();
-               res = clRetainSampler((cl_sampler)jp);
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_PROGRAM:
-               FAIL_clRetainProgram();
-               res = clRetainProgram((cl_program)jp);
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_KERNEL:
-               FAIL_clRetainKernel();
-               res = clRetainKernel((cl_kernel)jp);
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_KERNEL_WORK_GROUP:
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_EVENT:
-               FAIL_clRetainEvent();
-               res = clRetainEvent((cl_event)jp);
-               break;
-       case  au_notzed_zcl_CLObject_TYPE_EVENT_PROFILING:
-               break;
-       }
-
-       if (res != CL_SUCCESS) {
-               throwCLException(env, res);
-               return;
-       }
-}
-
-/* ********************************************************************** */
-/* CLPlatform */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLPlatform_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       // NOOP
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLPlatform_getPlatforms
-(JNIEnv *env, jclass jc) {
-       FAIL_clGetPlatformIDs_RET(NULL);
-
-       cl_platform_id *platforms;
-       cl_int res;
-       cl_uint count;
-
-       res = clGetPlatformIDs(0, NULL, &count);
-       THROW_RTERROR_RET(res, NULL);
-       
-       platforms = alloca(sizeof(*platforms) * count);
-
-       res = clGetPlatformIDs(count, platforms, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObjectArray(env, au_notzed_zcl_CLObject_CTYPE_PLATFORM, count, (void **)platforms);
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLPlatform_getDevices
-(JNIEnv *env, jobject jplatform, jlong type) {
-       cl_platform_id platform = GETP(env, jplatform);
-       cl_device_id *devices;
-       cl_uint count;
-       cl_int res;
-
-       res = clGetDeviceIDs(platform, type, 0, NULL, &count);
-       if (res == CL_DEVICE_NOT_FOUND)
-               return toCLObjectArray(env, au_notzed_zcl_CLObject_CTYPE_DEVICE, 0, NULL);
-               
-       THROW_RTERROR_RET(res, NULL);
-
-       devices = alloca(sizeof(devices[0]) * count);
-
-       res = clGetDeviceIDs(platform, type, count, devices, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObjectArray(env, au_notzed_zcl_CLObject_CTYPE_DEVICE, count, (void **)devices);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLPlatform_unloadPlatformCompiler
-(JNIEnv *env, jobject jplatform) {
-#ifdef CL_VERSION_1_2
-       if (CHECK_clUnloadPlatformCompiler()) {
-               cl_platform_id platform = GETP(env, jplatform);
-               cl_int res;
-
-               res = clUnloadPlatformCompiler(platform);
-               THROW_RTERROR(res);
-       } else {
-               cl_int res;
-
-               res = clUnloadCompiler();
-               THROW_RTERROR(res);
-       }       
-#else
-       cl_int res;
-
-       res = clUnloadCompiler();
-       THROW_RTERROR(res);
-#endif
-}
-
-/* ********************************************************************** */
-/* CLPlatform - CLExtension(s) */
-#include <CL/cl_gl_ext.h>
-
-jobject createExtension(JNIEnv *env, void *p, const char *className) {
-       jclass jc = (*env)->FindClass(env, className);
-       if (jc == NULL)
-               return NULL;
-
-       return NativeZ_create(env, jc, p);
-}
-
-void *getExtensionAddress(cl_platform_id platform, const char *func) {
-#ifdef CL_VERSION_1_2
-       if (CHECK_clGetExtensionFunctionAddressForPlatform())
-               return clGetExtensionFunctionAddressForPlatform(platform, func);
-#endif
-       if (CHECK_clGetExtensionFunctionAddress())
-               return clGetExtensionFunctionAddress(func);
-       else
-               return NULL;
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLPlatform_createExtension
-(JNIEnv *env, jobject jplatform, jint extensionid) {
-       cl_platform_id platform = GETP(env, jplatform);
-
-       switch (extensionid) {
-       case au_notzed_zcl_CLPlatform_cl_khr_gl_sharing:
-               return createExtension_cl_khr_gl_sharing(env, platform);
-       case au_notzed_zcl_CLPlatform_cl_khr_gl_event:
-               return createExtension_cl_khr_gl_event(env, platform);
-       }
-
-       // throws unknownextension?
-       throwUnsupportedOperation(env, "Unknown extension number");
-       return NULL;
-}
-
-/* ********************************************************************** */
-/* CLDevice */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLDevice_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       // NOOP
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLDevice_getDeviceAndHostTimer
-(JNIEnv *env, jobject jdevice, jlongArray jdst) {
-#ifdef CL_VERSION_2_1
-       if (checkAPIVersion(env, jdevice, au_notzed_zcl_CLPlatform_VERSION_2_1)) {
-               FAIL_clGetDeviceAndHostTimer();
-       
-               cl_device_id device = GETP(env, jdevice);
-               cl_int res;
-               cl_ulong ts[2];
-
-               res = clGetDeviceAndHostTimer(device, &ts[0], &ts[1]);
-               THROW_RTERROR(res);
-
-               (*env)->SetLongArrayRegion(env, jdst, 0, 2, (jlong *)ts);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.1");
-}
-
-JNIEXPORT jlong JNICALL Java_au_notzed_zcl_CLDevice_getHostTimer
-(JNIEnv *env, jobject jdevice) {
-#ifdef CL_VERSION_2_1
-       if (checkAPIVersion(env, jdevice, au_notzed_zcl_CLPlatform_VERSION_2_1)) {
-               FAIL_clGetHostTimer_RET(0);
-       
-               cl_device_id device = GETP(env, jdevice);
-               cl_int res;
-               cl_ulong ts;
-
-               res = clGetHostTimer(device, &ts);
-               THROW_RTERROR_RET(res, 0);
-
-               return ts;
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.1");
-       return 0;
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLDevice_createSubDevices
-(JNIEnv *env, jobject jdevice, jobjectArray jprops, jint count) {
-#ifdef CL_VERSION_1_2
-       FAIL_clCreateSubDevices_RET(NULL);
-
-       cl_device_id device = GETP(env, jdevice);
-       cl_int res;
-       cl_device_partition_property *props = fromPropertyArray(env, jprops);
-       cl_device_id *devices;
-       cl_uint dcount;
-
-       if ((*env)->ExceptionCheck(env)) return NULL;
-
-       devices = alloca(sizeof(*devices) * count);
-
-       res = clCreateSubDevices(device, props, count, devices, &dcount);
-       free(props);
-       
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObjectArray(env, au_notzed_zcl_CLObject_CTYPE_DEVICE, dcount, (void **)devices);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-       return NULL;
-#endif
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLDevice_getPartitionProperties
-(JNIEnv *env, jobject jcontext) {
-#ifdef CL_VERSION_1_2
-       return getInfoProperties(env, jcontext, au_notzed_zcl_CLObject_TYPE_DEVICE, CL_DEVICE_PARTITION_PROPERTIES,
-                                CLDeviceProperty_classid,
-                                CLDeviceProperty_TagValue_classid, CLDeviceProperty_TagValue_new_jj);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-       return NULL;
-#endif
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLDevice_getPartitionType
-(JNIEnv *env, jobject jcontext) {
-#ifdef CL_VERSION_1_2
-       return getInfoProperties(env, jcontext, au_notzed_zcl_CLObject_TYPE_DEVICE, CL_DEVICE_PARTITION_TYPE,
-                                CLDeviceProperty_classid,
-                                CLDeviceProperty_TagValue_classid, CLDeviceProperty_TagValue_new_jj);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-       return NULL;
-#endif
-}
-
-/* ********************************************************************** */
-/* CLContext */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLContext_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       cl_int res;
-       
-       FAIL_clReleaseContext();
-       if ((res = clReleaseContext((cl_context)jp)) != CL_SUCCESS)
-               throwCLRuntimeException(env, res);
-}
-
-/**
- * Bounces the context notify callback to java
- */
-static void context_notify_hook(const char *error_info, const void *private_info, size_t private_size, void *data) {
-       JNIEnv *env;
-       jobject jnotify = data;
-       jobject jerror_info;
-       jobject jprivate_info = NULL;
-
-       D(printf("context notify: %s\n", error_info));
-
-       if (!(env = nativez_AttachCurrentThreadAsDaemon())) {
-               fprintf(stderr, "Unable to attach java environment\n");
-               return;
-       }
-
-       jnotify = (*env)->NewLocalRef(env, jnotify);
-       if (!jnotify) {
-               fprintf(stderr, "cl_context notify called after object death\n");
-               return;
-       }
-
-       jerror_info = (*env)->NewStringUTF(env, error_info);
-
-       if (private_info && private_size)
-               jprivate_info = nativez_NewDirectBuffer(env, (void *)private_info, private_size);
-
-       jvalue args[2] = {
-               { .l = jerror_info },
-               { .l = jprivate_info }
-       };
-
-       (*env)->CallVoidMethodA(env, jnotify, CLContextNotify_notify_ll, args);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createContext
-(JNIEnv *env, jclass jc, jobjectArray jprops, jobjectArray jdevices, jobject jnotify) {
-       FAIL_clCreateContext_RET(NULL);
-
-       cl_context_properties *props = fromPropertyArray(env, jprops);
-       cl_device_id *devices;
-       cl_int res;
-       cl_context ret;
-       int dlen;
-       void (CL_CALLBACK* notify)(const char *, const void *, size_t, void *);
-       void *data;
-
-       if ((*env)->ExceptionCheck(env)) return NULL;
-
-       if (jdevices) {
-               dlen = (*env)->GetArrayLength(env, jdevices);
-               devices = alloca(dlen * sizeof(*devices));
-               fromObjectArray(env, jdevices, (void **)devices, dlen);
-       } else {
-               devices = NULL;
-               dlen = 0;
-       }
-
-       if (jnotify) {
-               // Note: solid reference is handled by constructor
-               notify = context_notify_hook;
-               data = (*env)->NewWeakGlobalRef(env, jnotify);
-       } else {
-               notify = NULL;
-               data = NULL;
-       }
-
-       ret = clCreateContext(props, dlen, devices, notify, data, &res);
-       free(props);
-       THROW_RTERROR_RET(res, NULL);
-
-       return NativeZ_register(env, (*env)->NewObject(env, classid[au_notzed_zcl_CLObject_CTYPE_CONTEXT], CLContext_new_pn, C2J(ret), jnotify));
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createContextFromType
-(JNIEnv *env, jclass jc, jobjectArray jprops, jlong type, jobject jnotify) {
-       FAIL_clCreateContextFromType_RET(NULL);
-
-       cl_context_properties *props = fromPropertyArray(env, jprops);
-       cl_int res;
-       cl_context ret;
-       void (CL_CALLBACK * notify)(const char *, const void *, size_t, void *);
-       void *data;
-
-       if ((*env)->ExceptionCheck(env)) return NULL;
-
-       if (jnotify) {
-               // Note: solid reference is handled by constructor
-               notify = context_notify_hook;
-               data = (*env)->NewWeakGlobalRef(env, jnotify);
-       } else {
-               notify = NULL;
-               data = NULL;
-       }
-
-       ret = clCreateContextFromType(props, type, notify, data, &res);
-       free(props);
-       THROW_RTERROR_RET(res, NULL);
-
-       return NativeZ_register(env, (*env)->NewObject(env, classid[au_notzed_zcl_CLObject_CTYPE_CONTEXT], CLContext_new_pn, C2J(ret), jnotify));
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createCommandQueue__Lau_notzed_zcl_CLDevice_2J
-(JNIEnv *env, jobject jcontext, jobject jdevice, jlong properties) {
-       FAIL_clCreateCommandQueue_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       cl_device_id device = GETP(env, jdevice);
-       cl_int res;
-       cl_command_queue ret;
-
-       ret = clCreateCommandQueue(context,
-                                  device,
-                                  properties,
-                                  &res);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_COMMAND_QUEUE, ret);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createCommandQueue__Lau_notzed_zcl_CLDevice_2_3Lau_notzed_zcl_CLQueueProperty_2
-(JNIEnv *env, jobject jcontext, jobject jdevice, jobjectArray jprops) {
-#ifdef CL_VERSION_2_0
-       if (getAPIVersion(env, jcontext) < au_notzed_zcl_CLPlatform_VERSION_2_0) {
-               cl_command_queue_properties properties = 0;
-
-               printf("Warning: Calling OpenCL 2.0 CreateCommandQueueWithProperties, using fallback\n");
-               fflush(stdout);
-
-               if (jprops) {
-                       cl_queue_properties *props = fromPropertyArray(env, jprops);
-                       
-                       if ((*env)->ExceptionCheck(env))
-                               return NULL;
-                       
-                       for (int i=0;props[i] != 0;i+=2) {
-                               if (CL_QUEUE_PROPERTIES == props[i]) {
-                                       properties = props[i+1];
-                                       break;
-                               }
-                       }
-                       free(props);
-               }
-               return Java_au_notzed_zcl_CLContext_createCommandQueue__Lau_notzed_zcl_CLDevice_2J(env, jcontext, jdevice, properties);
-       }
-
-       FAIL_clCreateCommandQueueWithProperties_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       cl_device_id device = GETP(env, jdevice);
-       cl_int res;
-       cl_command_queue ret;
-       cl_queue_properties *props = fromPropertyArray(env, jprops);
-
-       if ((*env)->ExceptionCheck(env)) return NULL;
-
-       ret = clCreateCommandQueueWithProperties(context,
-                                                device,
-                                                props,
-                                                &res);
-       free(props);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_COMMAND_QUEUE, ret);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-       return NULL;
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLContext_setDefaultDeviceCommandQueue
-(JNIEnv *env, jobject jcontext, jobject jdevice, jobject jqueue)
-{
-#ifdef CL_VERSION_2_1
-       if (checkAPIVersion(env, jcontext, au_notzed_zcl_CLPlatform_VERSION_2_1)) {
-               FAIL_clSetDefaultDeviceCommandQueue();
-
-               cl_context context = GETP(env, jcontext);
-               cl_device_id device = GETP(env, jdevice);
-               cl_command_queue queue = GETP(env, jqueue);
-               cl_int res;
-
-               res = clSetDefaultDeviceCommandQueue(context, device, queue);
-               THROW_ERROR(res);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.1");
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createBuffer__JJLjava_nio_ByteBuffer_2
-(JNIEnv *env, jobject jcontext, jlong flags, jlong size, jobject jhost_ptr) {
-       FAIL_clCreateBuffer_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       cl_int res;
-       cl_mem ret;
-       void *host_ptr = NULL;
-
-       D(printf("createBuffer(%08lx, %ld, %p)\n", flags, size, jhost_ptr));
-       
-       if (jhost_ptr) {
-               jlong jhost_size;
-
-               // TODO: an aligned allocator may be necessary
-               
-               host_ptr = (*env)->GetDirectBufferAddress(env, jhost_ptr);
-               jhost_size = (*env)->GetDirectBufferCapacity(env, jhost_ptr);
-               if (jhost_size < size) {
-                       throwCLException(env, CL_INVALID_HOST_PTR);
-                       return NULL;
-               }
-       }
-
-       ret = clCreateBuffer(context,
-                            flags,
-                            size,
-                            host_ptr,
-                            &res);
-
-       THROW_RTERROR_RET(res, NULL);
-
-       if (jhost_ptr && (flags & CL_MEM_USE_HOST_PTR)) {
-               jvalue args[] = {
-                       { .j = (uintptr_t)ret },
-                       { .l = jhost_ptr }
-               };
-
-               return NativeZ_register(env, (*env)->NewObjectA(env, classid[au_notzed_zcl_CLObject_CTYPE_BUFFER], CLBuffer_new_jb, args));
-       } else
-               return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_BUFFER, ret);
-}
-
-/* The convenience is worth it */
-
-static jobject
-createBufferPrimitive(JNIEnv *env, jobject jcontext, jlong flags, jarray jhost_ptr, int elshift) {
-       FAIL_clCreateBuffer_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       cl_int res;
-       cl_mem ret;
-       void *host_ptr;
-
-       // No way to implement this with java arrays currently
-       if (flags & CL_MEM_USE_HOST_PTR) {
-               throwCLException(env, CL_INVALID_VALUE);
-               return NULL;
-       }
-
-       if (!jhost_ptr) {
-               throwException(env, "java/lang/NullPointerException", "null array");
-               return NULL;
-       }
-
-       jsize size = (*env)->GetArrayLength(env, jhost_ptr);
-
-       host_ptr = (*env)->GetPrimitiveArrayCritical(env, jhost_ptr, NULL);
-
-       ret = clCreateBuffer(context,
-                            flags,
-                            size << elshift,
-                            host_ptr,
-                            &res);
-
-       (*env)->ReleasePrimitiveArrayCritical(env, jhost_ptr, host_ptr, 0);
-
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_BUFFER, ret);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createBuffer__J_3B
-(JNIEnv *env, jobject jcontext, jlong flags, jbyteArray jhost_ptr) {
-       return createBufferPrimitive(env, jcontext, flags, jhost_ptr, 0);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createBuffer__J_3S
-(JNIEnv *env, jobject jcontext, jlong flags, jbyteArray jhost_ptr) {
-       return createBufferPrimitive(env, jcontext, flags, jhost_ptr, 1);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createBuffer__J_3I
-(JNIEnv *env, jobject jcontext, jlong flags, jbyteArray jhost_ptr) {
-       return createBufferPrimitive(env, jcontext, flags, jhost_ptr, 2);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createBuffer__J_3F
-(JNIEnv *env, jobject jcontext, jlong flags, jfloatArray jhost_ptr) {
-       return createBufferPrimitive(env, jcontext, flags, jhost_ptr, 2);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createBuffer__J_3D
-(JNIEnv *env, jobject jcontext, jlong flags, jfloatArray jhost_ptr) {
-       return createBufferPrimitive(env, jcontext, flags, jhost_ptr, 2);
-}
-
-/* ********************************************************************** */
-
-// fmt = unmarshall(jfmt)
-// returns size of 1 element in bytes
-static size_t marshal_image_format(JNIEnv *env, cl_image_format *fmt, jobject jfmt) {
-       size_t nc, ds;
-       
-       fmt->image_channel_order = (*env)->GetIntField(env, jfmt, CLImageFormat_channelOrder);
-       fmt->image_channel_data_type = (*env)->GetIntField(env, jfmt, CLImageFormat_channelDataType);
-
-       switch (fmt->image_channel_order) {
-       case CL_R:
-       case CL_A:
-       case CL_INTENSITY:
-       case CL_LUMINANCE:
-       case CL_DEPTH:
-       case CL_DEPTH_STENCIL: // ???
-               nc = 1;
-               break;
-       case CL_RG:
-       case CL_RA:
-       case CL_Rx:
-               nc = 2;
-               break;
-       case CL_RGB:
-       case CL_RGx:
-       case CL_sRGB: // ??
-               nc = 3;
-               break;
-       case CL_RGBA:
-       case CL_BGRA:
-       case CL_ARGB:
-       case CL_RGBx:
-       case CL_sRGBx:
-       case CL_sRGBA:
-       case CL_sBGRA:
-       case CL_ABGR:
-       default:
-               nc = 4;
-               break;
-       }
-
-       switch (fmt->image_channel_data_type) {
-       case CL_SNORM_INT8:
-       case CL_UNORM_INT8:
-       case CL_SIGNED_INT8:
-       case CL_UNSIGNED_INT8:
-               ds = 1;
-               break;
-       case CL_SNORM_INT16:
-       case CL_UNORM_INT16:
-       case CL_UNORM_SHORT_565:
-       case CL_UNORM_SHORT_555:
-       case CL_UNORM_INT_101010:               
-       case CL_SIGNED_INT16:
-       case CL_UNSIGNED_INT16:
-       case CL_HALF_FLOAT:
-               ds = 2;
-               break;
-       case CL_UNORM_INT24:
-               ds = 3;
-               break;
-       case CL_SIGNED_INT32:
-       case CL_UNSIGNED_INT32:
-       case CL_FLOAT:
-       case CL_UNORM_INT_101010_2: // ??
-       default:
-               ds = 4;
-               break;
-       }
-
-       return nc * ds;
-}
-
-static size_t get_row_pitch(cl_image_desc *desc, size_t elsize) {
-       return desc->image_row_pitch != 0
-               ? desc->image_row_pitch
-               : elsize * desc->image_width;
-}
-
-static size_t get_slice_pitch(cl_image_desc *desc, size_t elsize) {
-       return desc->image_slice_pitch != 0
-               ? desc->image_slice_pitch
-               : desc->image_height * get_row_pitch(desc, elsize);
-}
-
-static size_t get_transfer_size(size_t region[3], size_t row_pitch, size_t slice_pitch, size_t elsize) {
-       if (slice_pitch == 0) {
-               if (row_pitch != 0)
-                       row_pitch = region[0] * elsize;
-               slice_pitch = row_pitch * region[1];
-       }
-       return slice_pitch * region[2];
-}
-
-// desc = unmarshall(jdesc)
-// returns required bytes
-static size_t marshal_image_desc(JNIEnv *env, cl_image_desc *desc, jobject jdesc, size_t elsize) {
-       desc->image_type = (*env)->GetIntField(env, jdesc, CLImageDesc_imageType);
-       desc->image_width = (*env)->GetIntField(env, jdesc, CLImageDesc_imageWidth);
-       desc->image_height = (*env)->GetIntField(env, jdesc, CLImageDesc_imageHeight);
-       desc->image_depth = (*env)->GetIntField(env, jdesc, CLImageDesc_imageDepth);
-       desc->image_array_size = (*env)->GetIntField(env, jdesc, CLImageDesc_imageArraySize);
-       desc->image_row_pitch = (*env)->GetIntField(env, jdesc, CLImageDesc_imageRowPitch);
-       desc->image_slice_pitch = (*env)->GetIntField(env, jdesc, CLImageDesc_imageSlicePitch);
-       desc->num_mip_levels = (*env)->GetIntField(env, jdesc, CLImageDesc_numMipLevels);
-       desc->num_samples = (*env)->GetIntField(env, jdesc, CLImageDesc_numSamples);
-       jobject jmemObject = (*env)->GetObjectField(env, jdesc, CLImageDesc_memObject);
-       desc->mem_object = jmemObject ? GETP(env, jmemObject) : NULL;
-
-       switch (desc->image_type) {
-       case CL_MEM_OBJECT_IMAGE2D:
-               return get_row_pitch(desc, elsize) * desc->image_height;
-       case CL_MEM_OBJECT_IMAGE3D:
-               return get_slice_pitch(desc, elsize) * desc->image_depth;
-#ifdef CL_VERSION_1_2
-       case CL_MEM_OBJECT_IMAGE1D:
-       case CL_MEM_OBJECT_IMAGE1D_BUFFER:
-               return get_row_pitch(desc, elsize);
-       case CL_MEM_OBJECT_IMAGE1D_ARRAY:
-       case CL_MEM_OBJECT_IMAGE2D_ARRAY:
-               return get_slice_pitch(desc, elsize) * desc->image_array_size;
-#endif
-       default:
-               return ~0;
-       }
-}
-
-static jobject createImage(JNIEnv *env, cl_context context, jlong flags, cl_image_format *fmt, cl_image_desc *desc, void *host_ptr) {
-
-       int res = 0;
-       cl_mem ret;
-
-#ifdef CL_VERSION_1_2
-       if (CHECK_clCreateImage()) {
-               ret = clCreateImage(context, flags, fmt, desc, host_ptr, &res);
-       } else {
-               switch (desc->image_type) {
-               case CL_MEM_OBJECT_IMAGE2D:
-                       FAIL_clCreateImage2D_RET(NULL);
-                       D(printf("createImage2D(%dx%d stride=%d host=%p)\n", desc->image_width, desc->image_height, desc->image_row_pitch, host_ptr));
-                       ret = clCreateImage2D(context, flags, fmt, desc->image_width, desc->image_height, desc->image_row_pitch, host_ptr, &res);
-                       break;
-               case CL_MEM_OBJECT_IMAGE3D:
-                       FAIL_clCreateImage3D_RET(NULL);
-                       ret = clCreateImage3D(context, flags, fmt, desc->image_width, desc->image_height, desc->image_depth,
-                                             desc->image_row_pitch, desc->image_slice_pitch, host_ptr, &res);
-                       break;
-               default:
-                       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-                       return NULL;
-               }
-       }
-#else
-       switch (desc->image_type) {
-       case CL_MEM_OBJECT_IMAGE2D:
-               FAIL_clCreateImage2D_RET(NULL);
-               D(printf("createImage2D(%dx%d stride=%d host=%p)\n", desc->image_width, desc->image_height, desc->image_row_pitch, host_ptr));
-               ret = clCreateImage2D(context, flags, fmt, desc->image_width, desc->image_height, desc->image_row_pitch, host_ptr, &res);
-               break;
-       case CL_MEM_OBJECT_IMAGE3D:
-               FAIL_clCreateImage3D_RET(NULL);
-               ret = clCreateImage3D(context, flags, fmt, desc->image_width, desc->image_height, desc->image_depth,
-                                     desc->image_row_pitch, desc->image_slice_pitch, host_ptr, &res);
-               break;
-       default:
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-               return NULL;
-       }
-#endif
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_IMAGE, ret);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createImage__JLau_notzed_zcl_CLImageFormat_2Lau_notzed_zcl_CLImageDesc_2Ljava_nio_ByteBuffer_2
-(JNIEnv *env, jobject jcontext, jlong flags, jobject jfmt, jobject jdesc, jobject jhost_ptr) {
-       cl_context context = GETP(env, jcontext);
-       cl_image_format fmt = { 0 };
-       cl_image_desc desc = { 0 };
-       void *host_ptr = NULL;
-       size_t required, elsize;
-
-       elsize = marshal_image_format(env, &fmt, jfmt);
-       required = marshal_image_desc(env, &desc, jdesc, elsize);
-       
-       if (jhost_ptr) {
-               jsize jhost_size = (*env)->GetDirectBufferCapacity(env, jhost_ptr);
-
-               if (jhost_size < required) {
-                       throwCLException(env, CL_INVALID_HOST_PTR);
-                       return NULL;
-               }
-
-               host_ptr = (*env)->GetDirectBufferAddress(env, jhost_ptr);
-       }
-
-       return createImage(env, context, flags, &fmt, &desc, host_ptr);
-}
-
-static jobject createImagePrimitive
-(JNIEnv *env, jobject jcontext, jlong flags, jobject jfmt, jobject jdesc, jarray jhost_ptr, int elshift) {
-       cl_context context = GETP(env, jcontext);
-       cl_image_format fmt = { 0 };
-       cl_image_desc desc = { 0 };
-       jobject ret;
-       void *host_ptr = NULL;
-       size_t required, elsize;
-
-       // No way to implement this with java arrays currently
-       if (flags & CL_MEM_USE_HOST_PTR) {
-               throwCLException(env, CL_INVALID_VALUE);
-               return NULL;
-       }
-
-       if (!jhost_ptr) {
-               throwException(env, "java/lang/NullPointerException", "null array");
-               return NULL;
-       }
-
-       elsize = marshal_image_format(env, &fmt, jfmt);
-       required = marshal_image_desc(env, &desc, jdesc, elsize);
-
-       jsize size = (*env)->GetArrayLength(env, jhost_ptr) << elshift;
-
-       if (size < required) {
-               throwCLException(env, CL_INVALID_HOST_PTR);
-               return NULL;
-       }
-
-       host_ptr = (*env)->GetPrimitiveArrayCritical(env, jhost_ptr, NULL);
-
-       ret = createImage(env, context, flags, &fmt, &desc, host_ptr);
-
-       (*env)->ReleasePrimitiveArrayCritical(env, jhost_ptr, host_ptr, 0);
-
-       return ret;
-}
-
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createImage__JLau_notzed_zcl_CLImageFormat_2Lau_notzed_zcl_CLImageDesc_2_3B
-(JNIEnv *env, jobject jcontext, jlong flags, jobject jfmt, jobject jdesc, jbyteArray jhost_ptr) {
-       return createImagePrimitive(env, jcontext, flags, jfmt, jdesc, jhost_ptr, 0);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createImage__JLau_notzed_zcl_CLImageFormat_2Lau_notzed_zcl_CLImageDesc_2_3S
-(JNIEnv *env, jobject jcontext, jlong flags, jobject jfmt, jobject jdesc, jbyteArray jhost_ptr) {
-       return createImagePrimitive(env, jcontext, flags, jfmt, jdesc, jhost_ptr, 1);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createImage__JLau_notzed_zcl_CLImageFormat_2Lau_notzed_zcl_CLImageDesc_2_3I
-(JNIEnv *env, jobject jcontext, jlong flags, jobject jfmt, jobject jdesc, jbyteArray jhost_ptr) {
-       return createImagePrimitive(env, jcontext, flags, jfmt, jdesc, jhost_ptr, 2);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createImage__JLau_notzed_zcl_CLImageFormat_2Lau_notzed_zcl_CLImageDesc_2_3F
-(JNIEnv *env, jobject jcontext, jlong flags, jobject jfmt, jobject jdesc, jbyteArray jhost_ptr) {
-       return createImagePrimitive(env, jcontext, flags, jfmt, jdesc, jhost_ptr, 2);
-}
-
-/* ********************************************************************** */
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createPipe
-(JNIEnv *env, jobject jcontext, jlong flags, jint packetSize, jint maxPackets, jobjectArray jprops) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jcontext, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clCreatePipe_RET(NULL);
-
-               cl_context context = GETP(env, jcontext);
-               cl_int res;
-               cl_mem ret;
-               cl_pipe_properties *props = fromPropertyArray(env, jprops);
-
-               if ((*env)->ExceptionCheck(env)) return NULL;
-
-               ret = clCreatePipe(context,
-                                  flags,
-                                  packetSize,
-                                  maxPackets,
-                                  props,
-                                  &res);
-               free(props);
-               THROW_RTERROR_RET(res, NULL);
-
-               return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_PIPE, ret);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-       return NULL;
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLContext_getSupportedImageFormats
-(JNIEnv *env, jobject jcontext, jlong flags, jint type) {
-       FAIL_clGetSupportedImageFormats_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       cl_uint count;
-       cl_image_format *formats;
-       jobjectArray jformats;
-       cl_int res;
-
-       res = clGetSupportedImageFormats(context,
-                                        flags,
-                                        type,
-                                        0, NULL, &count);
-       THROW_RTERROR_RET(res, NULL);
-
-       formats = alloca(sizeof(*formats) * count);
-       res = clGetSupportedImageFormats(context,
-                                        flags,
-                                        type,
-                                        count, formats, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       jformats = (*env)->NewObjectArray(env, count, CLImageFormat_classid, NULL);
-       if (!jformats)
-               return NULL;
-
-       for (int i=0;i<count;i++) {
-               jobject o = (*env)->NewObject(env, CLImageFormat_classid, CLImageFormat_new_ii,
-                                             formats[i].image_channel_order,
-                                             formats[i].image_channel_data_type);
-               (*env)->SetObjectArrayElement(env, jformats, i, o);
-       }
-
-       return jformats;
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_SVMAlloc
-(JNIEnv *env, jobject jcontext, jlong flags, jlong size, jint alignment) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jcontext, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clSVMAlloc_RET(NULL);
-
-               cl_context context = GETP(env, jcontext);
-               void *svm;
-
-               svm = clSVMAlloc(context, flags, size, alignment);
-               if (!svm) {
-                       // This isn't necessarily correct but there's no other return code
-                       // and it's a bunch of work to look up what it might be.
-                       throwCLRuntimeException(env, CL_OUT_OF_RESOURCES);
-                       return NULL;
-               }
-               
-               return nativez_NewDirectBuffer(env, svm, size);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-       return NULL;
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLContext_SVMFree
-(JNIEnv *env, jobject jcontext, jobject jsvm) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jcontext, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clSVMFree();
-
-               cl_context context = GETP(env, jcontext);
-
-               // NULL is ok & ignored
-               if (jsvm) {
-                       void *svm = (*env)->GetDirectBufferAddress(env, jsvm);
-                       
-                       clSVMFree(context, svm);
-               }
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-}
-
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createSampler__ZII
-(JNIEnv *env, jobject jcontext, jboolean norm, jint addr_mode, jint filter_mode) {
-       FAIL_clCreateSampler_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       cl_sampler ret;
-       cl_int res;
-
-       ret = clCreateSampler(context, norm, addr_mode, filter_mode, &res);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_SAMPLER, ret);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createSampler___3Lau_notzed_zcl_CLSamplerProperty_2
-(JNIEnv *env, jobject jcontext, jobjectArray jprops) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jcontext, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clCreateSamplerWithProperties_RET(NULL);
-
-               cl_context context = GETP(env, jcontext);
-               cl_sampler ret;
-               cl_int res;
-               cl_sampler_properties *props = fromPropertyArray(env, jprops);
-
-               if ((*env)->ExceptionCheck(env)) return NULL;
-
-               ret = clCreateSamplerWithProperties(context, props, &res);
-               free(props);
-               THROW_RTERROR_RET(res, NULL);
-
-               return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_SAMPLER, ret);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-       return NULL;
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createProgramWithSource
-(JNIEnv *env, jobject jcontext, jobjectArray jstrings) {
-       FAIL_clCreateProgramWithSource_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       int count;
-       const char **strings;
-       size_t *lengths;
-       cl_int res;
-       cl_program ret;
-
-       count = (*env)->GetArrayLength(env, jstrings);
-       strings = alloca(sizeof(*strings) * count);
-       lengths = alloca(sizeof(*lengths) * count);
-       for (int i=0;i<count;i++) {
-               jobject jo = (*env)->GetObjectArrayElement(env, jstrings, i);
-
-               lengths[i] = (*env)->GetArrayLength(env, jo);
-               strings[i] = (*env)->GetPrimitiveArrayCritical(env, jo, NULL);
-       }
-
-       ret = clCreateProgramWithSource(context,
-                                       count,
-                                       strings,
-                                       lengths,
-                                       &res);
-       for (int i=0;i<count;i++) {
-               jobject jo = (*env)->GetObjectArrayElement(env, jstrings, i);
-
-               (*env)->ReleasePrimitiveArrayCritical(env, jo, (void *)strings[i], 0);
-       }
-
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_PROGRAM, ret);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createProgramWithIL
-(JNIEnv *env, jobject jcontext, jbyteArray jil) {
-#ifdef CL_VERSION_2_1
-       if (checkAPIVersion(env, jcontext, au_notzed_zcl_CLPlatform_VERSION_2_1)) {
-               FAIL_clCreateProgramWithIL_RET(NULL);
-       
-               cl_context context = GETP(env, jcontext);
-               void *il;
-               size_t length;
-               cl_int res;
-               cl_program ret;
-
-               length = (*env)->GetArrayLength(env, jil);
-               il = (*env)->GetPrimitiveArrayCritical(env, jil, NULL);
-
-               ret = clCreateProgramWithIL(context,
-                                           il,
-                                           length,
-                                           &res);
-       
-               (*env)->ReleasePrimitiveArrayCritical(env, jil, il, 0);
-               THROW_ERROR_RET(res, NULL);
-
-               return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_PROGRAM, ret);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.1");
-       return NULL;
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createProgramWithBinary
-(JNIEnv *env, jobject jcontext, jobjectArray jdevices, jobjectArray jbinaries, jintArray jstatus) {
-       FAIL_clCreateProgramWithBinary_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       int dlen, blen, slen;
-       cl_device_id *devices;
-       size_t *lengths;
-       const unsigned char **binaries;
-       cl_int *status;
-       cl_int res;
-       cl_program ret;
-
-       if (!jdevices) {
-               throwException(env, "java/lang/NullPointerException", "device_list must not be null");
-               return NULL;
-       }
-
-       if (!jbinaries) {
-               throwException(env, "java/lang/NullPointerException", "binaries must not be null");
-               return NULL;
-       }
-
-       dlen = (*env)->GetArrayLength(env, jdevices);
-       blen = (*env)->GetArrayLength(env, jbinaries);
-       slen = jstatus ? (*env)->GetArrayLength(env, jbinaries) : 0;
-
-       if (slen > 0 && slen != blen) {
-               throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "binary_status.length != binaries.length");
-               return NULL;
-       }
-
-       devices = alloca(dlen * sizeof(*devices));
-       fromObjectArray(env, jdevices, (void **)devices, dlen);
-
-       binaries = alloca(blen * sizeof(*binaries));
-       lengths = alloca(blen * sizeof(*lengths));
-       status = alloca(blen * sizeof(*status));
-
-       for (int i=0;i<blen;i++) {
-               jobject jo = (*env)->GetObjectArrayElement(env, jbinaries, i);
-
-               lengths[i] = (*env)->GetArrayLength(env, jo);
-               binaries[i] = (*env)->GetPrimitiveArrayCritical(env, jo, NULL);
-       }
-
-       ret = clCreateProgramWithBinary(context,
-                                       dlen,
-                                       devices,
-                                       lengths,
-                                       binaries,
-                                       status,
-                                       &res);
-
-       for (int i=0;i<blen;i++) {
-               jobject jo = (*env)->GetObjectArrayElement(env, jbinaries, i);
-
-               (*env)->ReleasePrimitiveArrayCritical(env, jo, (void *)binaries[i], 0);
-       }
-       THROW_ERROR_RET(res, NULL);
-
-       if (jstatus)
-               (*env)->SetIntArrayRegion(env, jstatus, 0, blen, status);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_PROGRAM, ret);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createProgramWithBuiltInKernels
-(JNIEnv *env, jobject jcontext, jobjectArray jdevices, jstring jnames) {
-#ifdef CL_VERSION_1_2
-       FAIL_clCreateProgramWithBuiltInKernels_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       int dlen;
-       cl_device_id *devices;
-       const char *names;
-       cl_int res;
-       cl_program ret;
-
-       if (!jdevices) {
-               throwException(env, "java/lang/NullPointerException", "device_list must not be null");
-               return NULL;
-       }
-
-       dlen = (*env)->GetArrayLength(env, jdevices);
-       devices = alloca(dlen * sizeof(*devices));
-       fromObjectArray(env, jdevices, (void **)devices, dlen);
-
-       names = (*env)->GetStringUTFChars(env, jnames, NULL);
-       if (!names)
-               return NULL;
-
-       ret = clCreateProgramWithBuiltInKernels(context,
-                                               dlen,
-                                               devices,
-                                               names,
-                                               &res);
-       (*env)->ReleaseStringUTFChars(env, jnames, names);
-
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_PROGRAM, ret);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-       return NULL;
-#endif
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_linkProgram
-(JNIEnv *env, jobject jcontext, jobjectArray jdevices, jstring joptions, jobjectArray jprograms, jobject jnotify) {
-#ifdef CL_VERSION_1_2
-       FAIL_clLinkProgram_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       int dlen = 0, plen;
-       cl_device_id *devices = NULL;
-       cl_program *programs;
-       const char *options;
-       cl_int res;
-       cl_program ret = NULL;
-       void (CL_CALLBACK *notify)(cl_program /* program */, void * /* user_data */) = NULL;
-       struct build_notify_info *data = NULL;
-
-       if (!jprograms) {
-               throwException(env, "java/lang/NullPointerException", "device_list must not be null");
-               return NULL;
-       }
-
-       plen = (*env)->GetArrayLength(env, jprograms);
-       programs = alloca(plen * sizeof(*programs));
-       fromObjectArray(env, jprograms, (void **)programs, plen);
-
-       if (jdevices) {
-               dlen = (*env)->GetArrayLength(env, jdevices);
-               devices = alloca(dlen * sizeof(*devices));
-               fromObjectArray(env, jdevices, (void **)devices, dlen);
-       }
-
-       options = (*env)->GetStringUTFChars(env, joptions, NULL);
-
-       if (jnotify) {
-               // Note: build_notify_hook deletes the global ref
-               notify = build_notify_hook;
-               data = build_notify_alloc(env, NULL, NULL, jnotify);    
-               if (!data) {
-                       res = CL_OUT_OF_HOST_MEMORY;
-                       goto fail;
-               }
-       }
-
-       ret = clLinkProgram(context,
-                           dlen,
-                           devices,
-                           options,
-                           plen,
-                           programs,
-                           notify,
-                           data,
-                           &res);
-
- fail:
-       (*env)->ReleaseStringUTFChars(env, joptions, options);
-
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_PROGRAM, ret);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-       return NULL;
-#endif
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLContext_createUserEvent
-(JNIEnv *env, jobject jcontext) {
-#ifdef CL_VERSION_1_1
-       FAIL_clCreateUserEvent_RET(NULL);
-
-       cl_context context = GETP(env, jcontext);
-       cl_event ret;
-       cl_int res;
-
-       ret = clCreateUserEvent(context, &res);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_EVENT, ret);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-       return NULL;
-#endif
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLContext_getProperties
-(JNIEnv *env, jobject jcontext) {
-       return getInfoProperties(env, jcontext, au_notzed_zcl_CLObject_TYPE_CONTEXT, CL_CONTEXT_PROPERTIES,
-                                CLContextProperty_classid,
-                                CLContextProperty_TagValue_classid, CLContextProperty_TagValue_new_jj);
-}
-
-/* ********************************************************************** */
-/* CLMemory */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLMemory_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       cl_int res;
-
-       FAIL_clReleaseMemObject();
-       res = clReleaseMemObject((cl_mem)jp);
-       if (res != CL_SUCCESS)
-               throwCLRuntimeException(env, res);
-}
-
-#ifdef CL_VERSION_1_1
-struct destroy_notify_info {
-       cl_mem mem;
-       jobject jnotify;
-       jobject jmem;
-};
-
-static void destroy_notify_hook(cl_mem mem, void *data) {
-       struct destroy_notify_info *info = data;
-       JNIEnv *env;
-
-       D(printf("destroy notify()\n"));
-
-       if (!(env = nativez_AttachCurrentThreadAsDaemon())) {
-               // NB: can't do anything here
-               fprintf(stderr, "Unable to attach java environment\n");
-               free(data);
-               return;
-       }
-
-       if (info->mem == mem) {
-               jvalue arg = { .l = info->jmem };
-
-               (*env)->CallVoidMethodA(env, info->jnotify, CLNotify_notify_l, &arg);
-       } else
-               fprintf(stderr, "destroy_notify_hook given wrong cl_mem\n");
-
-       (*env)->DeleteGlobalRef(env, info->jnotify);
-       (*env)->DeleteGlobalRef(env, info->jmem);
-
-       free(info);
-}
-#endif
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLMemory_setMemObjectDestructorCallback
-(JNIEnv *env, jobject jmem, jobject jnotify) {
-#ifdef CL_VERSION_1_1
-       FAIL_clSetMemObjectDestructorCallback();
-
-       cl_mem mem = GETP(env, jmem);
-       struct destroy_notify_info *info;
-
-       if (!jnotify)
-               return;
-
-       info = malloc(sizeof(*info));
-       if (!info)
-               return;
-
-       info->mem = mem;
-       info->jnotify = (*env)->NewGlobalRef(env, jnotify);
-       info->jmem = (*env)->NewGlobalRef(env, jmem);
-
-       THROW_RTERROR(clSetMemObjectDestructorCallback(mem, destroy_notify_hook, info));
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-#endif
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLMemory_getHostPtr
-(JNIEnv *env, jobject jmem) {
-       FAIL_clGetMemObjectInfo_RET(NULL);
-
-       cl_mem mem = GETP(env, jmem);
-       cl_int res;
-       void *host_ptr;
-       size_t host_size;
-
-       res = clGetMemObjectInfo(mem, CL_MEM_HOST_PTR, sizeof(host_ptr), &host_ptr, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       res = clGetMemObjectInfo(mem, CL_MEM_SIZE, sizeof(host_size), &host_size, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return nativez_NewDirectBuffer(env, host_ptr, host_size);
-}
-
-/* ********************************************************************** */
-/* CLBuffer */
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLBuffer_createSubBuffer
-(JNIEnv *env, jobject jmem, jlong flags, jobject jinfo) {
-#ifdef CL_VERSION_1_1
-       FAIL_clCreateSubBuffer_RET(NULL);
-
-       cl_mem mem = GETP(env, jmem);
-       cl_mem ret;
-       cl_int res;
-       cl_buffer_create_type type;
-       union {
-               cl_buffer_region region;
-       } info;
-
-       if ((*env)->IsInstanceOf(env, jinfo, CLBufferInfoRegion_classid)) {
-               type = CL_BUFFER_CREATE_TYPE_REGION;
-               info.region.origin = (size_t)(*env)->GetLongField(env, jinfo, CLBufferInfoRegion_origin);
-               info.region.size = (size_t)(*env)->GetLongField(env, jinfo, CLBufferInfoRegion_size);
-       } else {
-               throwCLException(env, CL_INVALID_VALUE);
-               return NULL;
-       }
-
-       ret = clCreateSubBuffer(mem,
-                               flags,
-                               type,
-                               &info,
-                               &res);
-
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_BUFFER, ret);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-       return NULL;
-#endif
-}
-
-/* ********************************************************************** */
-/* CLProgram */
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLProgram_getBuildInfoAny
-(JNIEnv *env, jobject jprogram, jobject jdevice, jint ctype, jint param) {
-       FAIL_clGetProgramBuildInfo_RET(NULL);
-
-       cl_program program = GETP(env, jprogram);
-       cl_device_id device = GETP(env, jdevice);
-       void *value;
-       size_t size = ctype_sizes[ctype];
-       cl_int res;
-
-       value = alloca(size);
-       res = clGetProgramBuildInfo(program, device, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-       
-       return toObject(env, ctype, size, value);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLProgram_getBuildInfoAnyV
-(JNIEnv *env, jobject jprogram, jobject jdevice, jint ctype, jint param) {
-       FAIL_clGetProgramBuildInfo_RET(NULL);
-
-       cl_program program = GETP(env, jprogram);
-       cl_device_id device = GETP(env, jdevice);
-       void *value;
-       size_t size = 0;
-       cl_int res;
-
-       res = clGetProgramBuildInfo(program, device, param, 0, NULL, &size);
-       THROW_RTERROR_RET(res, NULL);
-       
-       value = alloca(size);
-
-       res = clGetProgramBuildInfo(program, device, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toArray(env, ctype, size, value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLProgram_buildProgram
-(JNIEnv *env, jobject jprogram, jobjectArray jdevices, jstring joptions, jobject jnotify) {
-       FAIL_clBuildProgram();
-
-       cl_program program = GETP(env, jprogram);
-       cl_device_id *devices = NULL;
-       int devcount = 0;
-       const char *options = NULL;
-       cl_int res;
-       void (CL_CALLBACK *notify)(cl_program /* program */, void * /* user_data */) = NULL;
-       struct build_notify_info *data = NULL;
-
-       if (jdevices) {
-               devcount = (*env)->GetArrayLength(env, jdevices);
-               devices = alloca(sizeof(*devices) * devcount);
-               fromObjectArray(env, jdevices, (void **)devices, devcount);
-       }
-
-       if (joptions) {
-               options = (*env)->GetStringUTFChars(env, joptions, NULL);
-       }
-
-       if (jnotify) {
-               // Note: build_notify_hook deletes the global ref
-               notify = build_notify_hook;
-               data = build_notify_alloc(env, program, jprogram, jnotify);
-               if (!data) {
-                       res = CL_OUT_OF_HOST_MEMORY;
-                       goto fail;
-               }
-       }
-
-       res = clBuildProgram(program, devcount, devices, options, notify, data);
- fail:
-       if (options)
-               (*env)->ReleaseStringUTFChars(env, joptions, options);
-
-       THROW_ERROR(res);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLProgram_compileProgram
-(JNIEnv *env, jobject jprogram, jobjectArray jdevices, jstring joptions, jobjectArray jheaders, jobjectArray jheadernames, jobject jnotify) {
-#ifdef CL_VERSION_1_2
-       FAIL_clCompileProgram();
-
-       cl_program program = GETP(env, jprogram);
-       cl_device_id *devices = NULL;
-       int devcount = 0;
-       cl_int res;
-       const char *options = NULL;
-       void (CL_CALLBACK *notify)(cl_program /* program */, void * /* user_data */) = NULL;
-       struct build_notify_info *data = NULL;
-       int hlen = 0;
-       cl_program *headers = NULL;
-       const char **names = NULL;
-
-       if (jdevices) {
-               devcount = (*env)->GetArrayLength(env, jdevices);
-               devices = alloca(sizeof(*devices) * devcount);
-               fromObjectArray(env, jdevices, (void **)devices, devcount);
-       }
-
-       if (joptions) {
-               options = (*env)->GetStringUTFChars(env, joptions, NULL);
-       }
-
-       if (jheaders) {
-               hlen = (*env)->GetArrayLength(env, jheaders);
-
-               if (hlen != (*env)->GetArrayLength(env, jheadernames)) {
-                       res = CL_INVALID_VALUE;
-                       goto fail;
-               }
-
-               headers = alloca(sizeof(*headers) * hlen);
-               names = alloca(sizeof(*names) * hlen);
-
-               for (int i=0;i<hlen;i++) {
-                       jobject jheader = (*env)->GetObjectArrayElement(env, jheaders, i);
-                       jobject jname = (*env)->GetObjectArrayElement(env, jheadernames, i);
-
-                       headers[i] = GETP(env, jheader);
-                       names[i] = (*env)->GetStringUTFChars(env, jname, NULL);
-               }
-       }
-
-       if (jnotify) {
-               // Note: build_notify_hook deletes the global ref
-               notify = build_notify_hook;
-               data = build_notify_alloc(env, program, jprogram, jnotify);
-               if (!data) {
-                       res = CL_OUT_OF_HOST_MEMORY;
-                       goto fail;
-               }
-       }
-
-       res = clCompileProgram(program, devcount, devices, options, hlen, headers, names, notify, data);
- fail:
-       if (options)
-               (*env)->ReleaseStringUTFChars(env, joptions, options);
-
-       if (names) {
-               for (int i=0;i<hlen;i++) {
-                       jobject jname = (*env)->GetObjectArrayElement(env, jheadernames, i);
-
-                       (*env)->ReleaseStringUTFChars(env, jname, names[i]);
-               }
-       }
-
-       THROW_ERROR(res);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-#endif
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLProgram_createKernel
-(JNIEnv *env, jobject jprogram, jstring jname) {
-       FAIL_clCreateKernel_RET(NULL);
-
-       cl_program program = GETP(env, jprogram);
-       const char *name;
-       cl_kernel ret;
-       cl_int res;
-
-       name = (*env)->GetStringUTFChars(env, jname, NULL);
-
-       ret = clCreateKernel(program, name, &res);
-
-       (*env)->ReleaseStringUTFChars(env, jname, name);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_KERNEL, ret);
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLProgram_createKernelsInProgram
-(JNIEnv *env, jobject jprogram) {
-       FAIL_clCreateKernelsInProgram_RET(NULL);
-
-       cl_program program = GETP(env, jprogram);
-       cl_int res;
-       cl_uint kcount;
-       cl_kernel *kernels;
-
-       res = clCreateKernelsInProgram(program, 0, NULL, &kcount);
-       THROW_RTERROR_RET(res, NULL);
-
-       kernels = alloca(sizeof(*kernels) * kcount);
-
-       res = clCreateKernelsInProgram(program, kcount, kernels, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObjectArray(env, au_notzed_zcl_CLObject_CTYPE_KERNEL, kcount, (void **)kernels);
-}
-
-JNIEXPORT jobjectArray JNICALL Java_au_notzed_zcl_CLProgram_getBinaries
-(JNIEnv *env, jobject jprogram) {
-       FAIL_clGetProgramInfo_RET(NULL);
-
-       cl_program program = GETP(env, jprogram);
-       cl_uint count;
-       size_t *sizes;
-       unsigned char **binaries;
-       cl_int res;
-       jobjectArray ret;
-
-       res = clGetProgramInfo(program, CL_PROGRAM_NUM_DEVICES, sizeof(count), &count, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       sizes = alloca(sizeof(*sizes) * count);
-       res = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(*sizes) * count, sizes, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       binaries = alloca(sizeof(*binaries) * count);
-       memset(binaries, 0, sizeof(*binaries) * count);
-       for (int i=0;i<count;i++) {
-               binaries[i] = malloc(sizes[i]);
-               if (!binaries[i]) {
-                       res = CL_OUT_OF_HOST_MEMORY;
-                       goto fail;
-               }
-       }
-       res = clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(*binaries) * count, binaries, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       ret = (*env)->NewObjectArray(env, count, byte_a_classid, NULL);
-       if (!ret)
-               goto fail;
-
-       for (int i=0;i<count;i++) {
-               jbyteArray jo = (*env)->NewByteArray(env, sizes[i]);
-
-               if (!jo)
-                       goto fail;
-
-               (*env)->SetByteArrayRegion(env, jo, 0, sizes[i], (const jbyte *)binaries[i]);
-               (*env)->SetObjectArrayElement(env, ret, i, jo);
-       }
-       for (int i=0;i<count;i++) {
-               free(binaries[i]);
-       }
-
-       return ret;
- fail:
-       for (int i=0;i<count;i++) {
-               if (binaries[i])
-                       free(binaries[i]);
-       }
-
-       throwCLRuntimeException(env, res);
-
-       return NULL;
-}
-
-/* ********************************************************************** */
-/* CLKernel */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       cl_int res;
-       FAIL_clReleaseKernel();
-       res = clReleaseKernel((cl_kernel)jp);
-       if (res != CL_SUCCESS)
-               throwCLRuntimeException(env, res);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLKernel_getWorkGroupInfoAny
-(JNIEnv *env, jobject jkernel, jobject jdevice, jint ctype, jint param) {
-       FAIL_clGetKernelWorkGroupInfo_RET(NULL);
-
-       cl_kernel kernel = GETP(env, jkernel);
-       cl_device_id device = GETP(env, jdevice);
-       void *value;
-       size_t size = ctype_sizes[ctype];
-       cl_int res;
-
-       value = alloca(size);
-       res = clGetKernelWorkGroupInfo(kernel, device, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toObject(env, ctype, size, value);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLKernel_getWorkGroupInfoAnyV
-(JNIEnv *env, jobject jkernel, jobject jdevice, jint ctype, jint param) {
-       FAIL_clGetKernelWorkGroupInfo_RET(NULL);
-
-       cl_kernel kernel = GETP(env, jkernel);
-       cl_device_id device = GETP(env, jdevice);
-       void *value;
-       size_t size = ctype_sizes[ctype];
-       cl_int res;
-
-       res = clGetKernelWorkGroupInfo(kernel, device, param, 0, NULL, &size);
-       THROW_RTERROR_RET(res, NULL);
-       
-       value = alloca(size);
-
-       res = clGetKernelWorkGroupInfo(kernel, device, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toArray(env, ctype, size, value);
-}
-
-static void getInputSizeTA(JNIEnv *env, jlongArray jinput, void **input, size_t *input_size) {
-       if (jinput) {
-               int ilen = (*env)->GetArrayLength(env, jinput);
-
-               *input_size = sizeof(*input) * ilen;
-               *input = alloca(sizeof(*input) * ilen);
-               getSizeTA(env, jinput, *input, ilen);
-       } else {
-               *input = NULL;
-               *input_size = 0;
-       }
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLKernel_getSubGroupInfoAny
-(JNIEnv *env, jobject jkernel, jobject jdevice, jint ctype, jint param, jlongArray jinput) {
-       FAIL_clGetKernelSubGroupInfo_RET(NULL);
-
-       cl_kernel kernel = GETP(env, jkernel);
-       cl_device_id device = GETP(env, jdevice);
-       void *value;
-       size_t size = ctype_sizes[ctype];
-       cl_int res;
-       void *input;
-       size_t input_size;
-
-       getInputSizeTA(env, jinput, &input, &input_size);
-
-       value = alloca(size);
-       res = clGetKernelSubGroupInfo(kernel, device, param, input_size, input, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toObject(env, ctype, size, value);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLKernel_getSubGroupInfoAnyV
-(JNIEnv *env, jobject jkernel, jobject jdevice, jint ctype, jint param, jlongArray jinput) {
-       FAIL_clGetKernelSubGroupInfo_RET(NULL);
-
-       cl_kernel kernel = GETP(env, jkernel);
-       cl_device_id device = GETP(env, jdevice);
-       void *value;
-       size_t size = ctype_sizes[ctype];
-       cl_int res;
-       void *input;
-       size_t input_size;
-
-       getInputSizeTA(env, jinput, &input, &input_size);
-
-       res = clGetKernelSubGroupInfo(kernel, device, param, input_size, input, 0, NULL, &size);
-       THROW_RTERROR_RET(res, NULL);
-       
-       value = alloca(size);
-
-       res = clGetKernelSubGroupInfo(kernel, device, param, input_size, input, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toArray(env, ctype, size, value);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLKernel_getArgInfoAny
-(JNIEnv *env, jobject jkernel, jint index, jint ctype, jint param) {
-       FAIL_clGetKernelArgInfo_RET(NULL);
-
-       cl_kernel kernel = GETP(env, jkernel);
-       void *value;
-       size_t size = ctype_sizes[ctype];
-       cl_int res;
-
-       value = alloca(size);
-       res = clGetKernelArgInfo(kernel, index, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toObject(env, ctype, size, value);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLKernel_getArgInfoAnyV
-(JNIEnv *env, jobject jkernel, jint index, jint ctype, jint param) {
-       FAIL_clGetKernelArgInfo_RET(NULL);
-
-       cl_kernel kernel = GETP(env, jkernel);
-       void *value;
-       size_t size = ctype_sizes[ctype];
-       cl_int res;
-
-       res = clGetKernelArgInfo(kernel, index, param, 0, NULL, &size);
-       THROW_RTERROR_RET(res, NULL);
-       
-       value = alloca(size);
-
-       res = clGetKernelArgInfo(kernel, index, param, size, value, NULL);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toArray(env, ctype, size, value);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLKernel_cloneKernel
-(JNIEnv *env, jobject jkernel) {
-       // Note: no runtime version check, see CLKernel.java
-#ifdef CL_VERSION_2_1
-       FAIL_clCloneKernel_RET(NULL);
-
-       cl_kernel kernel = GETP(env, jkernel);
-       cl_int res;
-       cl_kernel ret;
-
-       ret = clCloneKernel(kernel, &res);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_KERNEL, ret);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.1");
-       
-       return NULL;
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__IJLjava_nio_Buffer_2J
-(JNIEnv *env, jobject jkernel, jint index, jlong size, jobject jbuffer, jlong offset) {
-       FAIL_clSetKernelArg();
-
-       cl_kernel kernel = GETP(env, jkernel);
-       cl_int res;
-
-       if (jbuffer) {
-               void *buffer = (*env)->GetDirectBufferAddress(env, jbuffer);
-               jlong bsize = (*env)->GetDirectBufferCapacity(env, jbuffer);
-
-               if (offset + size > bsize) {
-                       throwCLException(env, CL_INVALID_VALUE);
-                       return; 
-               }
-
-               res = clSetKernelArg(kernel, index, size, buffer+offset);
-       } else {
-               res = clSetKernelArg(kernel, index, size, NULL);
-       }
-       THROW_ERROR(res);
-}
-
-static void zclSetKernelArg(JNIEnv *env, cl_kernel kernel, jint index, size_t size, void *valuep) {
-       FAIL_clSetKernelArg();
-       THROW_ERROR(clSetKernelArg(kernel, index, size, valuep));
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__ILau_notzed_zcl_CLObject_2
-(JNIEnv *env, jobject jkernel, jint index, jobject jvalue) {
-       cl_kernel kernel = GETP(env, jkernel);
-       void *value = jvalue ? GETP(env, jvalue) : NULL;
-
-       zclSetKernelArg(env, kernel, index, sizeof(value), &value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__IB
-(JNIEnv *env, jobject jkernel, jint index, jbyte value) {
-       cl_kernel kernel = GETP(env, jkernel);
-       zclSetKernelArg(env, kernel, index, sizeof(value), &value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__IS
-(JNIEnv *env, jobject jkernel, jint index, jshort value) {
-       cl_kernel kernel = GETP(env, jkernel);
-       zclSetKernelArg(env, kernel, index, sizeof(value), &value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__II
-(JNIEnv *env, jobject jkernel, jint index, jint value) {
-       cl_kernel kernel = GETP(env, jkernel);
-       zclSetKernelArg(env, kernel, index, sizeof(value), &value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__IJ
-(JNIEnv *env, jobject jkernel, jint index, jlong value) {
-       cl_kernel kernel = GETP(env, jkernel);
-       zclSetKernelArg(env, kernel, index, sizeof(value), &value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__IF
-(JNIEnv *env, jobject jkernel, jint index, jfloat value) {
-       cl_kernel kernel = GETP(env, jkernel);
-       zclSetKernelArg(env, kernel, index, sizeof(value), &value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__ID
-(JNIEnv *env, jobject jkernel, jint index, jdouble value) {
-       cl_kernel kernel = GETP(env, jkernel);
-       zclSetKernelArg(env, kernel, index, sizeof(value), &value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__ILjava_nio_ByteBuffer_2
-(JNIEnv *env, jobject jkernel, jint index, jobject jsvm) {
-#ifdef CL_VERSION_2_0
-       // Note: no runtime version check, see CLKernel.java
-       FAIL_clSetKernelArgSVMPointer();
-
-       cl_kernel kernel = GETP(env, jkernel);
-       void *svm = jsvm ? (*env)->GetDirectBufferAddress(env, jsvm) : NULL;
-
-       THROW_ERROR(clSetKernelArgSVMPointer(kernel, index, svm));
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__I_3B
-(JNIEnv *env, jobject jkernel, jint index, jbyteArray jvalue) {
-       cl_kernel kernel = GETP(env, jkernel);
-       jsize count = (*env)->GetArrayLength(env, jvalue);
-       jbyte *value = alloca(count * sizeof(*value));
-
-       (*env)->GetByteArrayRegion(env, jvalue, 0, count, value);
-       zclSetKernelArg(env, kernel, index, sizeof(*value) * count, value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__I_3S
-(JNIEnv *env, jobject jkernel, jint index, jshortArray jvalue) {
-       cl_kernel kernel = GETP(env, jkernel);
-       jsize count = (*env)->GetArrayLength(env, jvalue);
-       jshort *value = alloca(count * sizeof(*value));
-
-       (*env)->GetShortArrayRegion(env, jvalue, 0, count, value);
-       zclSetKernelArg(env, kernel, index, sizeof(*value) * count, value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__I_3I
-(JNIEnv *env, jobject jkernel, jint index, jintArray jvalue) {
-       cl_kernel kernel = GETP(env, jkernel);
-       jsize count = (*env)->GetArrayLength(env, jvalue);
-       jint *value = alloca(count * sizeof(*value));
-
-       (*env)->GetIntArrayRegion(env, jvalue, 0, count, value);
-       zclSetKernelArg(env, kernel, index, sizeof(*value) * count, value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__I_3J
-(JNIEnv *env, jobject jkernel, jint index, jlongArray jvalue) {
-       cl_kernel kernel = GETP(env, jkernel);
-       jsize count = (*env)->GetArrayLength(env, jvalue);
-       jlong *value = alloca(count * sizeof(*value));
-
-       (*env)->GetLongArrayRegion(env, jvalue, 0, count, value);
-       zclSetKernelArg(env, kernel, index, sizeof(*value) * count, value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__I_3F
-(JNIEnv *env, jobject jkernel, jint index, jfloatArray jvalue) {
-       cl_kernel kernel = GETP(env, jkernel);
-       jsize count = (*env)->GetArrayLength(env, jvalue);
-       jfloat *value = alloca(count * sizeof(*value));
-
-       (*env)->GetFloatArrayRegion(env, jvalue, 0, count, value);      
-       zclSetKernelArg(env, kernel, index, sizeof(*value) * count, value);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLKernel_setArg__I_3D
-(JNIEnv *env, jobject jkernel, jint index, jfloatArray jvalue) {
-       cl_kernel kernel = GETP(env, jkernel);
-       jsize count = (*env)->GetArrayLength(env, jvalue);
-       jdouble *value = alloca(count * sizeof(*value));
-
-       (*env)->GetDoubleArrayRegion(env, jvalue, 0, count, value);
-       zclSetKernelArg(env, kernel, index, sizeof(*value) * count, value);
-}
-
-/* ********************************************************************** */
-/* CLEvent */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLEvent_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       cl_int res;
-       FAIL_clReleaseEvent();
-       res = clReleaseEvent((cl_event)jp);
-       if (res != CL_SUCCESS)
-               throwCLRuntimeException(env, res);
-}
-
-#ifdef CL_VERSION_1_1
-struct event_notify_info {
-       cl_event event;
-       jobject jnotify;
-       jobject jevent;
-};
-
-static void event_notify_hook(cl_event event, cl_int status, void *data) {
-       struct event_notify_info *info = data;
-       JNIEnv *env;
-
-       D(printf("event notify()\n"));
-
-       if (!(env = nativez_AttachCurrentThreadAsDaemon())) {
-               // NB: can't do anything here
-               fprintf(stderr, "Unable to attach java environment\n");
-               free(data);
-               return;
-       }
-
-       if (info->event == event) {
-               jvalue args[2] = {
-                       { .l = info->jevent },
-                       { .i = status }
-               };
-               (*env)->CallVoidMethodA(env, info->jnotify, CLEventNotify_notify_li, args);
-       } else
-               fprintf(stderr, "destroy_notify_hook given wrong cl_mem\n");
-
-       (*env)->DeleteGlobalRef(env, info->jnotify);
-       (*env)->DeleteGlobalRef(env, info->jevent);
-
-       free(info);
-}
-#endif
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLEvent_setUserEventStatus
-(JNIEnv *env, jobject jevent, jint status) {
-#ifdef CL_VERSION_1_1
-       FAIL_clSetUserEventStatus();
-
-       cl_event event = GETP(env, jevent);
-       THROW_RTERROR(clSetUserEventStatus(event, status));
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLEvent_setEventCallback
-(JNIEnv *env, jobject jevent, jint type, jobject jnotify) {
-#ifdef CL_VERSION_1_1
-       FAIL_clSetEventCallback();
-
-       cl_event event = GETP(env, jevent);
-       struct event_notify_info *info;
-
-       if (!jnotify)
-               return;
-
-       info = malloc(sizeof(*info));
-       if (!info)
-               return;
-
-       info->event = event;
-       info->jnotify = (*env)->NewGlobalRef(env, jnotify);
-       info->jevent = (*env)->NewGlobalRef(env, jevent);
-
-       THROW_RTERROR(clSetEventCallback(event, type, event_notify_hook, info));
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-#endif
-}
-
-/* ********************************************************************** */
-/* CLEventList */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLEventList_waitForEvents
-(JNIEnv *env, jobject jevent) {
-       FAIL_clWaitForEvents();
-
-       jint count = (*env)->GetIntField(env, jevent, CLEventList_index);
-       jlongArray jevents = (*env)->GetObjectField(env, jevent, CLEventList_events);
-       cl_event *events = alloca(sizeof(*events) * count);
-       cl_int res;
-
-       if (sizeof(cl_event) == sizeof(jlong)) {
-               (*env)->GetLongArrayRegion(env, jevents, 0, count, (jlong *)events);
-       } else {
-               jlong *levents = alloca(count * sizeof(*levents));
-               (*env)->GetLongArrayRegion(env, jevents, 0, count, levents);
-               for (int i=0;i<count;i++)
-                       events[i] = (cl_event)(uintptr_t)levents[i];
-       }
-
-       res = clWaitForEvents(count, (cl_event *)events);
-       THROW_ERROR(res);
-}
-
-/* ********************************************************************** */
-/* CLCommandQueue */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       cl_int res;
-       
-       FAIL_clReleaseCommandQueue();
-       res = clReleaseCommandQueue((cl_command_queue)jp);
-       if (res != CL_SUCCESS)
-               throwCLRuntimeException(env, res);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_flush
-(JNIEnv *env, jobject jqueue) {
-       FAIL_clFlush();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       THROW_ERROR(clFlush(queue));
-}
-       
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_finish
-(JNIEnv *env, jobject jqueue) {
-       FAIL_clFinish();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       THROW_ERROR(clFinish(queue));
-}
-
-/* ********************************************************************** */
-
-static void enqueueBuffer
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize, jobject jbuffer, jobject jwaiters, jobject jevents, enqueueReadWriteBuffer_t op, const char *ex, const char *what) {
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem mem;
-       void *buffer = (*env)->GetDirectBufferAddress(env, jbuffer);
-       jint position = nativez_BufferPosition(env, jbuffer);
-       jint limit = nativez_BufferLimit(env, jbuffer);
-       struct events_info einfo;
-       cl_int res;
-
-       if (memsize > limit - position) {
-               throwException(env, ex, what);
-               return;
-       }
-
-       GET_P(env, jmem, mem,, "mem must not be null");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = (*op)(queue,
-                   mem,
-                   blocking,
-                   memoffset,
-                   memsize,
-                   buffer + position,
-                   einfo.wait_count,
-                   einfo.waitersp,
-                   einfo.eventp);
-       
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-
-JNIEXPORT void JNICALL
-Java_au_notzed_zcl_CLCommandQueue_enqueueReadBuffer__Lau_notzed_zcl_CLBuffer_2ZJJLjava_nio_ByteBuffer_2Lau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize, jobject jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBuffer(env, jqueue, jmem, blocking, memoffset, memsize, jbuffer, jwaiters, jevents, clEnqueueReadBuffer,
-                     "java/nio/BufferOverflowException", "target buffer too small");
-}
-
-JNIEXPORT void JNICALL
-Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBuffer__Lau_notzed_zcl_CLBuffer_2ZJJLjava_nio_ByteBuffer_2Lau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize, jobject jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBuffer(env, jqueue, jmem, blocking, memoffset, memsize, jbuffer, jwaiters, jevents, (enqueueReadWriteBuffer_t)clEnqueueWriteBuffer,
-                     "java/nio/BufferUnderflowException", "source buffer too small");
-}
-
-/* ********************************************************************** */
-
-static void enqueueBufferRect
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jbyteArray jbuffer, jobject jwaiters, jobject jevents,
- enqueueReadWriteBufferRect_t op) {
-#ifdef CL_VERSION_1_1
-       if (!op) {
-               throwException(env, "java/lang/UnsupportedOperationException", "Buffer read/write");
-               return;
-       }
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem mem;
-       void *buffer = (*env)->GetDirectBufferAddress(env, jbuffer);
-       jlong bsize = (*env)->GetDirectBufferCapacity(env, jbuffer);
-       struct events_info einfo;
-       cl_int res;
-       size_t buf_origin[3];
-       size_t host_origin[3];
-       size_t region[3];
-
-       CHECK_ARRAY_MIN(env, jbuf_origin, 3,, "buf origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jhost_origin, 3,, "host origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       getSizeTA(env, jbuf_origin, buf_origin, 3);
-       getSizeTA(env, jhost_origin, host_origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       size_t stride = (host_row_pitch == 0 ? region[0] : host_row_pitch);
-       size_t slice = (host_slice_pitch == 0 ? region[1] * stride : host_slice_pitch);
-
-       if (host_origin[0] + host_origin[1] * stride + host_origin[2] * slice
-           + region[0] + (region[1]-1) * stride + (region[2]-1) * slice
-           > bsize) {
-               throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "Target buffer over/overflow");
-               return;
-       }
-
-       GET_P(env, jmem, mem,, "mem must not be null");
-       
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-       
-       res = (*op)(queue,
-                   mem,
-                   blocking,
-                   buf_origin,
-                   host_origin,
-                   region,
-                   buf_row_pitch,
-                   buf_slice_pitch,
-                   host_row_pitch,
-                   host_slice_pitch,
-                   buffer,
-                   einfo.wait_count,
-                   einfo.waitersp,
-                   einfo.eventp);
-
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-#endif
-}
-
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJLjava_nio_ByteBuffer_2Lau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jobject jbuffer,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferRect(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                         buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                         jbuffer, jwaiters, jevents,
-                         clEnqueueReadBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJLjava_nio_ByteBuffer_2Lau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jobject jbuffer,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferRect(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                         buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                         jbuffer, jwaiters, jevents,
-                         (enqueueReadWriteBufferRect_t)clEnqueueWriteBufferRect);
-}
-
-/* ********************************************************************** */
-
-static void enqueueFillBuffer
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jobject jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents, getArrayRegion_t getArray, int elsize) {
-#ifdef CL_VERSION_1_2
-       FAIL_clEnqueueFillBuffer();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem buffer;
-       void *pattern;
-       size_t pattern_size;
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jbuffer, buffer,, "buffer must not be null");
-       CHECK_NULL(env, jpattern,, "pattern must not be null");
-
-       pattern_size = (*env)->GetArrayLength(env, jpattern);
-       // complex double16 is maximum possible size?
-       if (pattern_size * elsize > 16*16) {
-               throwCLException(env, CL_INVALID_VALUE);
-               return;
-       }
-       pattern = alloca(pattern_size * elsize);
-       getArray(env, jpattern, 0, pattern_size, pattern);
-
-       D(printf("enqueue fill buffer( off=%d size=%d patternsize=%d\n",
-                (int)(offset * pattern_size * elsize),
-                (int)(size * pattern_size * elsize),
-                (int)(pattern_size * elsize)));
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = clEnqueueFillBuffer(queue,
-                                 buffer,
-                                 pattern,
-                                 pattern_size * elsize,
-                                 offset * pattern_size * elsize,
-                                 size * pattern_size * elsize,
-                                 einfo.wait_count,
-                                 einfo.waitersp,
-                                 einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);      
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillBuffer__Lau_notzed_zcl_CLBuffer_2_3BJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jbyteArray jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents) {
-       enqueueFillBuffer(env, jqueue, jbuffer, jpattern, offset, size, jwaiters, jevents, (getArrayRegion_t)(*env)->GetByteArrayRegion, 1);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillBuffer__Lau_notzed_zcl_CLBuffer_2_3SJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jshortArray jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents) {
-       enqueueFillBuffer(env, jqueue, jbuffer, jpattern, offset, size, jwaiters, jevents, (getArrayRegion_t)(*env)->GetByteArrayRegion, 2);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillBuffer__Lau_notzed_zcl_CLBuffer_2_3IJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jintArray jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents) {
-       enqueueFillBuffer(env, jqueue, jbuffer, jpattern, offset, size, jwaiters, jevents, (getArrayRegion_t)(*env)->GetIntArrayRegion, sizeof(cl_int));
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillBuffer__Lau_notzed_zcl_CLBuffer_2_3JJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jlongArray jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents) {
-       enqueueFillBuffer(env, jqueue, jbuffer, jpattern, offset, size, jwaiters, jevents, (getArrayRegion_t)(*env)->GetLongArrayRegion, sizeof(cl_long));
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillBuffer__Lau_notzed_zcl_CLBuffer_2_3FJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jfloatArray jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents) {
-       enqueueFillBuffer(env, jqueue, jbuffer, jpattern, offset, size, jwaiters, jevents, (getArrayRegion_t)(*env)->GetFloatArrayRegion, sizeof(cl_float));
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillBuffer__Lau_notzed_zcl_CLBuffer_2_3DJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jdoubleArray jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents) {
-       enqueueFillBuffer(env, jqueue, jbuffer, jpattern, offset, size, jwaiters, jevents, (getArrayRegion_t)(*env)->GetDoubleArrayRegion, sizeof(cl_double));
-}
-
-/* ********************************************************************** */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueCopyBuffer
-(JNIEnv *env, jobject jqueue, jobject jsrc, jobject jdst, jlong srcoff, jlong dstoff, jlong size,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueCopyBuffer();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem src;
-       cl_mem dst;
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jsrc, src,, "src must not be null");
-       GET_P(env, jdst, dst,, "dst must not be null");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = clEnqueueCopyBuffer(queue,
-                                 src,
-                                 dst,
-                                 srcoff,
-                                 dstoff,
-                                 size,
-                                 einfo.wait_count,
-                                 einfo.waitersp,
-                                 einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);      
-}
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueCopyBufferRect
-(JNIEnv *env, jobject jqueue, jobject jsrc, jobject jdst, jlongArray jsrc_origin, jlongArray jdst_origin, jlongArray jregion,
- jlong src_row_pitch, jlong src_slice_pitch, jlong dst_row_pitch, jlong dst_slice_pitch,
- jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_1_1
-       FAIL_clEnqueueCopyBufferRect();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem src;
-       cl_mem dst;
-       size_t src_origin[3];
-       size_t dst_origin[3];
-       size_t region[3];
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jsrc, src,, "src must not be null");
-       GET_P(env, jdst, dst,, "dst must not be null");
-
-       CHECK_ARRAY_MIN(env, jsrc_origin, 3,, "src origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jdst_origin, 3,, "dst origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       getSizeTA(env, jsrc_origin, src_origin, 3);
-       getSizeTA(env, jdst_origin, dst_origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-#if 0
-       printf("CopyBufferRect[ src={ %d, %d, %d }/stride=%d slice=%d dstt={ %d, %d, %d }/stride=%d slice=%d region={ %d, %d, %d }\n",
-              (int)src_origin[0], (int)src_origin[1], (int)src_origin[2], (int)src_row_pitch, (int)src_slice_pitch,
-              (int)dst_origin[0], (int)dst_origin[1], (int)dst_origin[2], (int)dst_row_pitch, (int)dst_slice_pitch,
-              (int)region[0], (int)region[1], (int)region[2]);
-       fflush(stdout);
-#endif
-
-       res = clEnqueueCopyBufferRect(queue,
-                                     src,
-                                     dst,
-                                     src_origin,
-                                     dst_origin,
-                                     region,
-                                     src_row_pitch,
-                                     src_slice_pitch,
-                                     dst_row_pitch,
-                                     dst_slice_pitch,
-                                     einfo.wait_count,
-                                     einfo.waitersp,
-                                     einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);      
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-#endif
-}
-
-/* ********************************************************************** */
-
-/* Common driver for image read/write from/to byte buffer */
-static void enqueueImageBuffer
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jarray jbuffer,
- jobject jwaiters, jobject jevents,
- enqueueReadWriteImage_t op) {
-       if (!op) {
-               throwException(env, "java/lang/UnsupportedOperationException", "Image read/write");
-               return;
-       }
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem image;
-       void *buffer = (*env)->GetDirectBufferAddress(env, jbuffer);
-       jint position = nativez_BufferPosition(env, jbuffer);
-       jint limit = nativez_BufferLimit(env, jbuffer);
-       size_t origin[3];
-       size_t region[3];
-       size_t elsize, tsize;
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jimage, image,, "image must not be null");
-
-       CHECK_ARRAY_MIN(env, jorigin, 3,, "origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       getSizeTA(env, jorigin, origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       // Needed to check transfer size
-       clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(elsize), &elsize, NULL);
-
-       // Calculate what OpenCL will actually transfer based on parameters.
-       tsize = get_transfer_size(region, row_pitch, slice_pitch, elsize);
-
-       if (tsize > limit - position) {
-               // FIXME: overflow exception for read
-               throwException(env, "java/nio/BufferUnderflowExcetion", "source buffer too small");
-               return;
-       }
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = op(queue,
-                image,
-                blocking,
-                origin,
-                region,
-                row_pitch,
-                slice_pitch,
-                buffer + position,
-                einfo.wait_count,
-                einfo.waitersp,
-                einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL
-Java_au_notzed_zcl_CLCommandQueue_enqueueReadImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJLjava_nio_ByteBuffer_2Lau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jobject jbuffer,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueReadImage();
-       enqueueImageBuffer(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch, jbuffer,
-                          jwaiters, jevents, clEnqueueReadImage);
-}
-JNIEXPORT void JNICALL
-Java_au_notzed_zcl_CLCommandQueue_enqueueWriteImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJLjava_nio_ByteBuffer_2Lau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jobject jbuffer,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueWriteImage();
-
-       // Cast is for a harmless const warning
-       enqueueImageBuffer(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch, jbuffer,
-                          jwaiters, jevents,
-                          (enqueueReadWriteImage_t)clEnqueueWriteImage);
-}
-
-static void enqueueFillImage
-(JNIEnv *env, jobject jqueue,
- jobject jimage, void *colour, jlongArray jorigin, jlongArray jregion,
- jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_1_2
-       FAIL_clEnqueueFillImage();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem image;
-       size_t origin[3];
-       size_t region[3];
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jimage, image,, "image must not be null");
-
-       CHECK_ARRAY_MIN(env, jorigin, 3,, "origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       getSizeTA(env, jorigin, origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       D(printf("enqueue fill image( [ %d,%d,%d] [%d,%d,%d] )\n",
-                (int)origin[0], (int)origin[1], (int)origin[2],
-                (int)region[0], (int)region[1], (int)region[2]));
-       
-       res = clEnqueueFillImage(queue,
-                                image,
-                                colour,
-                                origin,
-                                region,
-                                einfo.wait_count,
-                                einfo.waitersp,
-                                einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);      
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillImage__Lau_notzed_zcl_CLImage_2_3I_3J_3JLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jintArray jcolour, jlongArray jorigin, jlongArray jregion,
- jobject jwaiters, jobject jevents) {
-       jint colour[4];
-
-       CHECK_ARRAY_MIN(env, jcolour, 4,, "colour must be 4-elements long");
-       (*env)->GetIntArrayRegion(env, jcolour, 0, 4, colour);
-
-       enqueueFillImage(env, jqueue, jimage, colour, jorigin, jregion, jwaiters, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueFillImage__Lau_notzed_zcl_CLImage_2_3F_3J_3JLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jfloatArray jcolour, jlongArray jorigin, jlongArray jregion,
- jobject jwaiters, jobject jevents) {
-       jfloat colour[4];
-
-       CHECK_ARRAY_MIN(env, jcolour, 4,, "colour must be 4-elements long");
-       (*env)->GetFloatArrayRegion(env, jcolour, 0, 4, colour);
-
-       enqueueFillImage(env, jqueue, jimage, colour, jorigin, jregion, jwaiters, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueCopyImage
-(JNIEnv *env, jobject jqueue, jobject jsrc, jobject jdst, jlongArray jsrc_origin, jlongArray jdst_origin, jlongArray jregion,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueCopyImage();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem src;
-       cl_mem dst;
-       size_t src_origin[3];
-       size_t dst_origin[3];
-       size_t region[3];
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jsrc, src,, "src must not be null");
-       GET_P(env, jdst, dst,, "dst must not be null");
-
-       CHECK_ARRAY_MIN(env, jsrc_origin, 3,, "src origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jdst_origin, 3,, "dst origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       getSizeTA(env, jsrc_origin, src_origin, 3);
-       getSizeTA(env, jdst_origin, dst_origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       res = clEnqueueCopyImage(queue,
-                                src,
-                                dst,
-                                src_origin,
-                                dst_origin,
-                                region,
-                                einfo.wait_count,
-                                einfo.waitersp,
-                                einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueCopyImageToBuffer
-(JNIEnv *env, jobject jqueue,
- jobject jsrc, jobject jdst,
- jlongArray jsrc_origin, jlongArray jregion, jlong dst_offset,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueCopyImageToBuffer();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem src;
-       cl_mem dst;
-       size_t src_origin[3];
-       size_t region[3];
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jsrc, src,, "src must not be null");
-       GET_P(env, jdst, dst,, "dst must not be null");
-
-       CHECK_ARRAY_MIN(env, jsrc_origin, 3,, "src origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       getSizeTA(env, jsrc_origin, src_origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       res = clEnqueueCopyImageToBuffer(queue,
-                                        src,
-                                        dst,
-                                        src_origin,
-                                        region,
-                                        dst_offset,
-                                        einfo.wait_count,
-                                        einfo.waitersp,
-                                        einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueCopyBufferToImage
-(JNIEnv *env, jobject jqueue,
- jobject jsrc, jobject jdst,
- jlong src_offset, jlongArray jdst_origin, jlongArray jregion,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueCopyBufferToImage();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem src;
-       cl_mem dst;
-       size_t dst_origin[3];
-       size_t region[3];
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jsrc, src,, "src must not be null");
-       GET_P(env, jdst, dst,, "dst must not be null");
-
-       CHECK_ARRAY_MIN(env, jdst_origin, 3,, "dst origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       getSizeTA(env, jdst_origin, dst_origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       res = clEnqueueCopyBufferToImage(queue,
-                                        src,
-                                        dst,
-                                        src_offset,
-                                        dst_origin,
-                                        region,
-                                        einfo.wait_count,
-                                        einfo.waitersp,
-                                        einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueMapBuffer
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong flags, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueMapBuffer_RET(NULL);
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem mem;
-       struct events_info einfo;
-       cl_int res;
-       void *ret;
-
-       GET_P(env, jmem, mem, NULL, "mem must not be null");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return NULL;
-
-       ret = clEnqueueMapBuffer(queue,
-                                mem,
-                                blocking,
-                                flags,
-                                offset,
-                                size,
-                                einfo.wait_count,
-                                einfo.waitersp,
-                                einfo.eventp,
-                                &res);
-       THROW_ERROR_RET(res, NULL);
-
-       events_post(env, &einfo, jevents);
-
-       return nativez_NewDirectBuffer(env, ret, size);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueMapImage
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlong flags,
- jlongArray jorigin, jlongArray jregion, jlongArray jrow_pitch, jlongArray jslice_pitch,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueMapImage_RET(NULL);
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem image;
-       struct events_info einfo;
-       size_t origin[3];
-       size_t region[3];
-       size_t row_pitch;
-       size_t slice_pitch;
-       cl_int res;
-       void *ret;
-
-       GET_P(env, jimage, image, NULL, "image must not be null");
-
-       CHECK_ARRAY_MIN(env, jorigin, 3, NULL, "origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3, NULL, "region must be 3-elements long");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return NULL;
-
-       getSizeTA(env, jorigin, origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       ret = clEnqueueMapImage(queue,
-                               image,
-                               blocking,
-                               flags,
-                               origin,
-                               region,
-                               &row_pitch,
-                               &slice_pitch,
-                               einfo.wait_count,
-                               einfo.waitersp,
-                               einfo.eventp,
-                               &res);
-       THROW_ERROR_RET(res, NULL);
-
-       if (jrow_pitch) {
-               jlong value = (jlong)row_pitch;
-               (*env)->SetLongArrayRegion(env, jrow_pitch, 0, 1, &value);
-       }
-       if (jslice_pitch) {
-               jlong value = (jlong)slice_pitch;
-               (*env)->SetLongArrayRegion(env, jslice_pitch, 0, 1, &value);
-       }
-
-       events_post(env, &einfo, jevents);
-
-       // TODO: check these, not sure how it works.
-
-       jlong size;
-
-       size = slice_pitch * region[2] + row_pitch * region[1] + region[0];
-
-       return nativez_NewDirectBuffer(env, ret, size);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueUnmapMemObject
-(JNIEnv *env, jobject jqueue, jobject jmem, jobject jbuffer, jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueUnmapMemObject();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem mem;
-       void *buffer = (*env)->GetDirectBufferAddress(env, jbuffer);
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jmem, mem,, "mem must not be null");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = clEnqueueUnmapMemObject(queue, mem, buffer,
-                                     einfo.wait_count,
-                                     einfo.waitersp,
-                                     einfo.eventp);
-       THROW_ERROR(res);
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueMigrateMemObjects
-(JNIEnv *env, jobject jqueue, jobjectArray jmems, jlong flags, jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_1_2
-       FAIL_clEnqueueMigrateMemObjects();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       jsize mlen = (*env)->GetArrayLength(env, jmems);
-       cl_mem *mems = alloca(mlen * sizeof(*mems));
-       struct events_info einfo;
-       cl_int res;
-
-       if (fromObjectArray(env, jmems, (void **)mems, mlen))
-               return;
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = clEnqueueMigrateMemObjects(queue,
-                                        mlen,
-                                        mems,
-                                        flags,
-                                        einfo.wait_count,
-                                        einfo.waitersp,
-                                        einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.2");
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueNDRangeKernel
-(JNIEnv *env, jobject jqueue, jobject jkernel, jint dim,
- jlongArray jgwo, jlongArray jgws, jlongArray jlws,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueNDRangeKernel();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_kernel kernel;
-       struct events_info einfo;
-       cl_int res;
-       size_t gwo[3];
-       size_t gws[3];
-       size_t lws[3];
-
-       if (dim > 3 || dim < 1) {
-               throwCLException(env, CL_INVALID_WORK_DIMENSION);
-               return;
-       }
-
-       GET_P(env, jkernel, kernel,, "kernel must not be null");
-
-       if (!jgws) {
-               throwException(env, "java/lang/NullPointerException", "global_size must not be null");
-               return;
-       }
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       getSizeTA(env, jgwo, gwo, dim);
-       getSizeTA(env, jgws, gws, dim);
-       getSizeTA(env, jlws, lws, dim);
-
-       D(printf("enqueue( dim=%d off=%d,%d,%d  gws=%d,%d,%d  lws=%d,%d,%d (%p)\n",
-                dim,
-                (int)gwo[0], (int)gwo[1], (int)gwo[2],
-                (int)gws[0], (int)gws[1], (int)gws[2],
-                (int)lws[0], (int)lws[1], (int)lws[2], jlws));
-
-       res = clEnqueueNDRangeKernel(queue,
-                                    kernel,
-                                    dim,
-                                    jgwo ? gwo : NULL,
-                                    gws,
-                                    jlws ? lws : NULL,
-                                    einfo.wait_count,
-                                    einfo.waitersp,
-                                    einfo.eventp);
-       THROW_ERROR(res);
-
-       if (debug_sync) {
-               char kname[64];
-               size_t size_ret;
-               
-               clGetKernelInfo(kernel, CL_KERNEL_FUNCTION_NAME, 64, kname, &size_ret);
-               (printf("zcl:enqueue('%s' dim=%d off=%d,%d,%d  gws=%d,%d,%d  lws=%d,%d,%d (%p)\n",
-                       kname,
-                       dim,
-                       (int)gwo[0], (int)gwo[1], (int)gwo[2],
-                       (int)gws[0], (int)gws[1], (int)gws[2],
-                       (int)lws[0], (int)lws[1], (int)lws[2], jlws));
-               fflush(stdout);
-               
-               clFlush(queue);
-               clFinish(queue);
-       }
-       
-       
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueTask
-(JNIEnv *env, jobject jqueue, jobject jkernel,
- jobject jwaiters, jobject jevents) {
-       FAIL_clEnqueueTask();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_kernel kernel;
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jkernel, kernel,, "kernel must not be null");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = clEnqueueTask(queue,
-                           kernel,
-                           einfo.wait_count,
-                           einfo.waitersp,
-                           einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-/**
- * This interrogates the argument array and provides the appropriate arguments
- * for the clEnqueueNativeKernel call.
- *
- * The first argument to the JNI hook is native_kernel_info which is used
- * to re-map the data back to Java objects.
- */
-
-struct native_kernel_info {
-       // Original kernel / args from caller (for reference)
-       jobject jkernel;
-       jobjectArray jargs;
-
-       // Actual arguments passed to clEnqueueNativeKernel
-       // args[0] points to 'this'
-       // arguments follow
-       jobject *args;
-       int argslen;
-
-       cl_mem *mems;
-       const void **memsloc;
-       int memslen;
-};
-
-static void native_kernel_free(JNIEnv *env, struct native_kernel_info *info) {
-       (*env)->DeleteGlobalRef(env, info->jargs);
-       (*env)->DeleteGlobalRef(env, info->jkernel);
-       free(info->args);
-       free(info->mems);
-       free(info->memsloc);
-
-       free(info);
-}
-
-static void native_kernel_hook(void *data) {
-       JNIEnv *env;
-       jobject *args = data;
-       struct native_kernel_info *info = (void *)args[0];
-       jobjectArray kargs;
-       int argslen = info->argslen-1;
-
-       if (!(env = nativez_AttachCurrentThreadAsDaemon())) {
-               // NB: can't do anything here
-               fprintf(stderr, "Unable to attach java environment\n");
-               free(data);
-               return;
-       }
-       
-       kargs = (*env)->NewObjectArray(env, argslen, Object_classid, NULL);
-
-       for (int i=0;i<argslen;i++) {
-               jobject jo = (*env)->GetObjectArrayElement(env, info->jargs, i);
-
-               if ((*env)->IsInstanceOf(env, jo, CLMemory_classid)) {
-                       cl_mem mem = GETP(env, jo);
-                       size_t memsize;
-
-                       clGetMemObjectInfo(mem, CL_MEM_SIZE, sizeof(memsize), &memsize, NULL);
-
-                       jo = nativez_NewDirectBuffer(env, args[i+1], memsize);
-               }
-
-               (*env)->SetObjectArrayElement(env, kargs, i, jo);
-       }
-
-       jvalue arg = { .l = kargs };
-       (*env)->CallVoidMethodA(env, info->jkernel, CLNativeKernel_invoke__l, &arg);
-
-       native_kernel_free(env, info);
-}
-
-JNIEXPORT void Java_au_notzed_zcl_CLCommandQueue_enqueueNativeKernel
-(JNIEnv *env, jobject jqueue, jobject jkernel,  jobject jwaiters, jobject jevents, jobjectArray jargs) {
-       FAIL_clEnqueueNativeKernel();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       int argslen = (*env)->GetArrayLength(env, jargs);
-       struct native_kernel_info *info;
-       struct events_info einfo;
-       cl_int res;
-
-       // TODO: check if it could use more checks
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       info = malloc(sizeof(*info));
-
-       info->jargs = (*env)->NewGlobalRef(env, jargs);
-       info->jkernel = (*env)->NewGlobalRef(env, jkernel);
-
-       info->args = malloc(sizeof(*info->args) * (argslen+1));
-       info->argslen = argslen + 1;
-       info->mems = malloc(sizeof(*info->mems) * (argslen));
-       info->memsloc = malloc(sizeof(*info->memsloc) * (argslen));
-       info->memslen = 0;
-
-       info->args[0] = (jobject)info;
-
-       for (int i=0;i<argslen;i++) {
-               jobject jo = (*env)->GetObjectArrayElement(env, jargs, i);
-
-               if ((*env)->IsInstanceOf(env, jo, CLMemory_classid)) {
-                       info->mems[info->memslen] = GETP(env, jo);
-                       info->memsloc[info->memslen] = &info->args[i+1];
-                       info->memslen++;
-                       info->args[i+1] = NULL;
-               } else {
-                       info->args[i+1] = jo;
-               }
-       }
-
-       res = clEnqueueNativeKernel(queue,
-                                   native_kernel_hook,
-                                   info->args,
-                                   sizeof(*info->args) * info->argslen,
-                                   info->memslen,
-                                   info->mems,
-                                   info->memsloc,
-                                   einfo.wait_count,
-                                   einfo.waitersp,
-                                   einfo.eventp);
-       if (res != CL_SUCCESS) {
-               native_kernel_free(env, info);
-               throwCLException(env, res);
-               return;
-       }
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueMarkerWithWaitList
-(JNIEnv *env, jobject jqueue, jobject jwaiters, jobject jevents) {
-       /* As this emulates the 1.2 interface always, must fallback */
-#ifdef CL_VERSION_1_2
-       if (CHECK_clEnqueueMarkerWithWaitList()) {
-               cl_command_queue queue = GETP(env, jqueue);
-               struct events_info einfo;
-               cl_int res;
-
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-
-               res = clEnqueueMarkerWithWaitList(queue,
-                                                 einfo.wait_count,
-                                                 einfo.waitersp,
-                                                 einfo.eventp);
-               THROW_ERROR(res);
-
-               events_post(env, &einfo, jevents);
-       } else {
-               FAIL_clEnqueueWaitForEvents();
-               FAIL_clEnqueueMarker();
-
-               cl_command_queue queue = GETP(env, jqueue);
-               struct events_info einfo;
-               cl_int res;
-
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-
-               res = clEnqueueWaitForEvents(queue,
-                                            einfo.wait_count,
-                                            einfo.waitersp);
-               THROW_ERROR(res);
-
-               res = clEnqueueMarker(queue,
-                                     einfo.eventp);
-               THROW_ERROR(res);
-
-               events_post(env, &einfo, jevents);
-       }
-#else
-       cl_command_queue queue = GETP(env, jqueue);
-       struct events_info einfo;
-       cl_int res;
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = clEnqueueWaitForEvents(queue,
-                                    einfo.wait_count,
-                                    einfo.waitersp);
-       THROW_ERROR(res);
-
-       res = clEnqueueMarker(queue,
-                             einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueBarrierWithWaitList
-(JNIEnv *env, jobject jqueue, jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_1_2
-       if (checkAPIVersion(env, jqueue, au_notzed_zcl_CLPlatform_VERSION_1_2)) {
-               cl_command_queue queue = GETP(env, jqueue);
-               struct events_info einfo;
-               cl_int res;
-
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-
-               res = clEnqueueBarrierWithWaitList(queue,
-                                                  einfo.wait_count,
-                                                  einfo.waitersp,
-                                                  einfo.eventp);
-               THROW_ERROR(res);
-               
-               events_post(env, &einfo, jevents);
-               return;
-       }
-#endif
-       FAIL_clEnqueueWaitForEvents();
-       FAIL_clEnqueueBarrier();
-       FAIL_clEnqueueMarker();
-
-       cl_command_queue queue = GETP(env, jqueue);
-       struct events_info einfo;
-       cl_int res;
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       res = clEnqueueWaitForEvents(queue,
-                                    einfo.wait_count,
-                                    einfo.waitersp);
-       THROW_ERROR(res);
-
-       res = clEnqueueBarrier(queue);
-       THROW_ERROR(res);
-
-       res = clEnqueueMarker(queue,
-                             einfo.eventp);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMFree
-(JNIEnv *env, jobject jqueue, jobjectArray jptrs, jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jqueue, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clEnqueueSVMFree();
-
-               cl_command_queue queue = GETP(env, jqueue);
-               struct events_info einfo;
-               cl_int res;
-               void **ptrs;
-               size_t size;
-       
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-       
-               size = (*env)->GetArrayLength(env, jptrs);
-               ptrs = alloca(sizeof(*ptrs) * size);
-               for (int i=0;i<size;i++) {
-                       jobject jo = (*env)->GetObjectArrayElement(env, jptrs, i);
-                       
-                       ptrs[i] = (*env)->GetDirectBufferAddress(env, jo);
-               }
-       
-               res = clEnqueueSVMFree(queue,
-                                      size,
-                                      ptrs,
-                                      NULL, // free_func
-                                      NULL, // user_data
-                                      einfo.wait_count,
-                                      einfo.waitersp,
-                                      einfo.eventp);
-               THROW_ERROR(res);
-       
-               events_post(env, &einfo, jevents);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMemcpy
-(JNIEnv *env, jobject jqueue, jboolean blocking, jobject jdst, jlong doffset, jobject jsrc, jlong soffset, jlong size, jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jqueue, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clEnqueueSVMMemcpy();
-
-               cl_command_queue queue = GETP(env, jqueue);
-               void *dst, *src;
-               struct events_info einfo;
-               cl_int res;
-       
-               CHECK_NULL(env, jdst,, "dst must not be null");
-               CHECK_NULL(env, jsrc,, "src must not be null");
-               
-               dst = (*env)->GetDirectBufferAddress(env, jdst);
-               src = (*env)->GetDirectBufferAddress(env, jsrc);
-       
-               res = clEnqueueSVMMemcpy(queue,
-                                        blocking,
-                                        dst + doffset,
-                                        src + soffset,
-                                        size,
-                                        einfo.wait_count,
-                                        einfo.waitersp,
-                                        einfo.eventp);                          
-               THROW_ERROR(res);
-       
-               events_post(env, &einfo, jevents);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-}
-
-static void enqueueSVMMemFill
-(JNIEnv *env, jobject jqueue,
- jobject jbuffer, jobject jpattern, jlong offset, jlong size,
- jobject jwaiters, jobject jevents, getArrayRegion_t getArray, int elsize) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jqueue, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clEnqueueSVMMemFill();
-
-               cl_command_queue queue = GETP(env, jqueue);
-               void *buffer;
-               void *pattern;
-               size_t pattern_size;
-               struct events_info einfo;
-               cl_int res;
-
-               CHECK_NULL(env, jbuffer,, "pattern must not be null");
-               CHECK_NULL(env, jpattern,, "pattern must not be null");
-       
-               buffer = (*env)->GetDirectBufferAddress(env, jbuffer);
-       
-               pattern_size = (*env)->GetArrayLength(env, jpattern);
-               // complex double16 is maximum possible size?
-               if (pattern_size * elsize > 16*16) {
-                       throwCLException(env, CL_INVALID_VALUE);
-                       return;
-               }
-               pattern = alloca(pattern_size * elsize);
-               getArray(env, jpattern, 0, pattern_size, pattern);
-       
-               D(printf("enqueue svm memfill( off=%d size=%d patternsize=%d\n",
-                        (int)(offset * pattern_size * elsize),
-                        (int)(size * pattern_size * elsize),
-                        (int)(pattern_size * elsize)));
-       
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-       
-               res = clEnqueueSVMMemFill(queue,
-                                         buffer + offset * pattern_size * elsize,
-                                         pattern,
-                                         pattern_size * elsize,
-                                         size * pattern_size * elsize,
-                                         einfo.wait_count,
-                                         einfo.waitersp,
-                                         einfo.eventp);
-               THROW_ERROR(res);
-       
-               events_post(env, &einfo, jevents);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMemFill__Ljava_nio_ByteBuffer_2_3BJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jdst, jbyteArray jpattern, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-       enqueueSVMMemFill(env, jqueue, jdst, jpattern, offset, size, jwaiters, jevents,  (getArrayRegion_t)(*env)->GetByteArrayRegion, 1);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMemFill__Ljava_nio_ByteBuffer_2_3SJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jdst, jshortArray jpattern, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-       enqueueSVMMemFill(env, jqueue, jdst, jpattern, offset, size, jwaiters, jevents,  (getArrayRegion_t)(*env)->GetShortArrayRegion, 2);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMemFill__Ljava_nio_ByteBuffer_2_3IJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jdst, jintArray jpattern, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-       enqueueSVMMemFill(env, jqueue, jdst, jpattern, offset, size, jwaiters, jevents,  (getArrayRegion_t)(*env)->GetIntArrayRegion, 4);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMemFill__Ljava_nio_ByteBuffer_2_3JJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jdst, jlongArray jpattern, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-       enqueueSVMMemFill(env, jqueue, jdst, jpattern, offset, size, jwaiters, jevents,  (getArrayRegion_t)(*env)->GetLongArrayRegion, 8);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMemFill__Ljava_nio_ByteBuffer_2_3FJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jdst, jfloatArray jpattern, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-       enqueueSVMMemFill(env, jqueue, jdst, jpattern, offset, size, jwaiters, jevents,  (getArrayRegion_t)(*env)->GetFloatArrayRegion, 4);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMemFill__Ljava_nio_ByteBuffer_2_3DJJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jdst, jdoubleArray jpattern, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-       enqueueSVMMemFill(env, jqueue, jdst, jpattern, offset, size, jwaiters, jevents,  (getArrayRegion_t)(*env)->GetDoubleArrayRegion, 8);
-}
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMap
-(JNIEnv *env, jobject jqueue, jboolean blocking, jlong flags, jobject jsvm, jlong offset, jlong size, jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jqueue, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clEnqueueSVMMap();
-
-               cl_command_queue queue = GETP(env, jqueue);
-               void *svm;
-               struct events_info einfo;
-               cl_int res;
-
-               CHECK_NULL(env, jsvm,, "svm pointer must not be null");
-               
-               svm = (*env)->GetDirectBufferAddress(env, jsvm);
-       
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-       
-               res = clEnqueueSVMMap(queue,
-                                     blocking,
-                                     flags,
-                                     svm + offset,
-                                     size,
-                                     einfo.wait_count,
-                                     einfo.waitersp,
-                                     einfo.eventp);
-               THROW_ERROR(res);
-       
-               events_post(env, &einfo, jevents);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMUnmap
-(JNIEnv *env, jobject jqueue, jobject jsvm, jlong offset, jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_2_0
-       if (checkAPIVersion(env, jqueue, au_notzed_zcl_CLPlatform_VERSION_2_0)) {
-               FAIL_clEnqueueSVMUnmap();
-
-               cl_command_queue queue = GETP(env, jqueue);
-               void *svm;
-               struct events_info einfo;
-               cl_int res;
-
-               CHECK_NULL(env, jsvm,, "svm pointer must not be null");
-       
-               svm = (*env)->GetDirectBufferAddress(env, jsvm);
-
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-       
-               res = clEnqueueSVMUnmap(queue,
-                                       svm + offset,
-                                       einfo.wait_count,
-                                       einfo.waitersp,
-                                       einfo.eventp);
-               THROW_ERROR(res);
-       
-               events_post(env, &einfo, jevents);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.0");
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueSVMMigrateMem
-(JNIEnv *env, jobject jqueue, jobjectArray jmems, jlongArray joffsets, jlongArray jsizes, jlong flags, jobject jwaiters, jobject jevents) {
-#ifdef CL_VERSION_2_1
-       if (checkAPIVersion(env, jqueue, au_notzed_zcl_CLPlatform_VERSION_2_1)) {
-               FAIL_clEnqueueSVMMigrateMem();
-
-               cl_command_queue queue = GETP(env, jqueue);
-               jsize mlen = (*env)->GetArrayLength(env, jmems);
-               void **mems = alloca(mlen * sizeof(*mems));
-               struct events_info einfo;
-               cl_int res;
-               size_t *sizes = NULL;
-               
-               if (fromObjectArray(env, jmems, (void **)mems, mlen))
-                       return;
-
-               if (joffsets) {
-                       size_t *offsets = alloca(sizeof(size_t) * mlen);
-               
-                       getSizeTA(env, joffsets, offsets, mlen);
-                       for (int i=0;i<mlen;i++)
-                               mems[i] += offsets[i];
-               }
-
-               if (jsizes) {
-                       sizes = alloca(sizeof(size_t) * mlen);
-                       getSizeTA(env, jsizes, sizes, mlen);
-               }
-       
-               if (events_init(env, &einfo, jwaiters, jevents))
-                       return;
-
-               res = clEnqueueSVMMigrateMem(queue,
-                                            mlen,
-                                            (const void **)mems,
-                                            sizes,
-                                            flags,
-                                            einfo.wait_count,
-                                            einfo.waitersp,
-                                            einfo.eventp);
-               THROW_ERROR(res);
-
-               events_post(env, &einfo, jevents);
-       } else
-#endif
-               throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 2.1");
-}
-
-/* ********************************************************************** */
-
-/* CLImage */
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_CLImage_getFormat
-(JNIEnv *env, jobject jid) {
-       FAIL_clGetImageInfo_RET(NULL);
-
-       void *jp = GETP(env, jid);
-       cl_int res;
-       cl_image_format value;
-
-       res = clGetImageInfo((cl_mem)jp, CL_IMAGE_FORMAT, sizeof(value), &value, NULL);
-       if (res != CL_SUCCESS) {
-               throwCLRuntimeException(env, res);
-               return NULL;
-       }
-
-       return (*env)->NewObject(env, CLImageFormat_classid, CLImageFormat_new_ii,
-                                value.image_channel_order,
-                                value.image_channel_data_type);
-}
-
-
-/* ********************************************************************** */
-/* Primitive array Buffer read/writes */
-
-/*
-  For simplicity reasons only blocking operations are implemented.
- */
-
-static void enqueueBufferPrimitive
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jarray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents,
- int elshift,
- enqueueReadWriteBuffer_t op) {
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem mem;
-       void *buffer;
-       jsize bsize = (*env)->GetArrayLength(env, jbuffer);
-       struct events_info einfo;
-       cl_int res;
-
-       //blocking = PRIMITIVE_BLOCKING(blocking);
-       blocking = CL_TRUE;
-
-       //memoffset <<= elshift;
-       //memsize <<= elshift;
-       //bufoffset <<= elshift;
-       //bsize <<= elshift;
-
-       if (memsize > bsize - bufoffset) {
-               throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "target array too small");
-               return;
-       }
-
-       GET_P(env, jmem, mem,, "mem must not be null");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       buffer = (*env)->GetPrimitiveArrayCritical(env, jbuffer, NULL);
-
-       res = op(queue,
-                mem,
-                blocking,
-                (memoffset << elshift),
-                (memsize << elshift),
-                buffer + (bufoffset << elshift),
-                einfo.wait_count,
-                einfo.waitersp,
-                einfo.eventp);
-
-       (*env)->ReleasePrimitiveArrayCritical(env, jbuffer, buffer, 0);
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3BJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jbyteArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 0,
-                              clEnqueueReadBuffer);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3SJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jshortArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 1,
-                              clEnqueueReadBuffer);
-
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3IJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jintArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 2,
-                              clEnqueueReadBuffer);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3JJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jlongArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 3,
-                              clEnqueueReadBuffer);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3FJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jfloatArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 2,
-                              clEnqueueReadBuffer);
-
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3DJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jdoubleArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 3,
-                              clEnqueueReadBuffer);
-}
-
-/* * * * */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3BJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jbyteArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 0,
-                              (enqueueReadWriteBuffer_t)clEnqueueWriteBuffer);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3SJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jshortArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 1,
-                              (enqueueReadWriteBuffer_t)clEnqueueWriteBuffer);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3IJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jintArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 2,
-                              (enqueueReadWriteBuffer_t)clEnqueueWriteBuffer);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3JJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jlongArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 3,
-                              (enqueueReadWriteBuffer_t)clEnqueueWriteBuffer);
-
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3FJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jfloatArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 2,
-                              (enqueueReadWriteBuffer_t)clEnqueueWriteBuffer);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBuffer__Lau_notzed_zcl_CLBuffer_2ZJJ_3DJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking, jlong memoffset, jlong memsize,
- jdoubleArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueBufferPrimitive(env, jqueue, jmem, blocking, memoffset, memsize,
-                              jbuffer, bufoffset,
-                              jwaiters, jevents, 3,
-                              (enqueueReadWriteBuffer_t)clEnqueueWriteBuffer);
-
-}
-
-/* ********************************************************************** */
-
-/* 2D/3D Buffer primitive array read/write operations */
-
-/*
-  For simplicity reasons only blocking operations are implemented.
- */
-
-static void enqueueBufferRectPrimitive
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jbyteArray jbuffer, jobject jwaiters, jobject jevents, int elshift,
- enqueueReadWriteBufferRect_t op) {
-#ifdef CL_VERSION_1_1
-       if (!op) {
-               throwException(env, "java/lang/UnsupportedOperationException", "Buffer read/write");
-               return;
-       }
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem mem;
-       void *buffer;
-       jsize bsize = (*env)->GetArrayLength(env, jbuffer);
-       struct events_info einfo;
-       cl_int res;
-       size_t buf_origin[3];
-       size_t host_origin[3];
-       size_t region[3];
-
-       blocking = CL_TRUE;
-
-       CHECK_ARRAY_MIN(env, jbuf_origin, 3,, "buf origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jhost_origin, 3,, "host origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       getSizeTA(env, jbuf_origin, buf_origin, 3);
-       getSizeTA(env, jhost_origin, host_origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       buf_origin[0] <<= elshift;
-       host_origin[0] <<= elshift;
-       region[0] <<= elshift;
-       buf_row_pitch <<= elshift;
-       buf_slice_pitch <<= elshift;
-       host_row_pitch <<= elshift;
-       host_slice_pitch <<= elshift;
-
-       size_t stride = (host_row_pitch == 0 ? region[0] : host_row_pitch);
-       size_t slice = (host_slice_pitch == 0 ? region[1] * stride : host_slice_pitch);
-
-#if 0
-       printf("*BufferRect[ dev={ %d, %d, %d }/stride=%d slice=%d host={ %d, %d, %d }/stride=%d slice=%d region={ %d, %d, %d }   bsize=%d dstride=%d dslice=%d  dorigin=%d  dsize=%d\n",
-              (int)buf_origin[0], (int)buf_origin[1], (int)buf_origin[2], (int)buf_row_pitch, (int)buf_slice_pitch,
-              (int)host_origin[0], (int)host_origin[1], (int)host_origin[2], (int)host_row_pitch, (int)host_slice_pitch,
-              (int)region[0], (int)region[1], (int)region[2],
-              (int)(bsize << elshift),
-              (int)stride, (int)slice,
-              (int)(host_origin[0] + host_origin[1] * stride + host_origin[2] * slice),
-              (int)(region[0] + (region[1]-1) * stride + (region[2]-1) * slice));
-       fflush(stdout);
-#endif
-
-       if (host_origin[0] + host_origin[1] * stride + host_origin[2] * slice
-           + region[0] + (region[1]-1) * stride + (region[2]-1) * slice
-           > bsize << elshift) {
-               throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "Target buffer overflow");
-               return;
-       }
-
-       GET_P(env, jmem, mem,, "mem must not be null");
-       
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-       
-       buffer = (*env)->GetPrimitiveArrayCritical(env, jbuffer, NULL);
-       res = (*op)(queue,
-                   mem,
-                   blocking,
-                   buf_origin,
-                   host_origin,
-                   region,
-                   buf_row_pitch,
-                   buf_slice_pitch,
-                   host_row_pitch,
-                   host_slice_pitch,
-                   buffer,
-                   einfo.wait_count,
-                   einfo.waitersp,
-                   einfo.eventp);
-       (*env)->ReleasePrimitiveArrayCritical(env, jbuffer, buffer, 0);
-       
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-#else
-       throwException(env, "java/lang/UnsupportedOperationException", "Requires OpenCL 1.1");
-#endif
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3BLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jbyteArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 0,
-                                  clEnqueueReadBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3SLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jshortArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 1,
-                                  clEnqueueReadBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3ILau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jintArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 2,
-                                  clEnqueueReadBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3JLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jlongArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 3,
-                                  clEnqueueReadBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3FLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jfloatArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 2,
-                                  clEnqueueReadBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3DLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jdoubleArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 3,
-                                  clEnqueueReadBufferRect);
-}
-
-/* * * * */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3BLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jbyteArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 0,
-                                  (enqueueReadWriteBufferRect_t)clEnqueueWriteBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3SLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jshortArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 1,
-                                  (enqueueReadWriteBufferRect_t)clEnqueueWriteBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3ILau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jintArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 2,
-                                  (enqueueReadWriteBufferRect_t)clEnqueueWriteBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3JLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jlongArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 3,
-                                  (enqueueReadWriteBufferRect_t)clEnqueueWriteBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3FLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jfloatArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 2,
-                                  (enqueueReadWriteBufferRect_t)clEnqueueWriteBufferRect);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteBufferRect__Lau_notzed_zcl_CLBuffer_2Z_3J_3J_3JJJJJ_3DLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jmem, jboolean blocking,
- jlongArray jbuf_origin, jlongArray jhost_origin, jlongArray jregion,
- jlong buf_row_pitch, jlong buf_slice_pitch, jlong host_row_pitch, jlong host_slice_pitch,
- jbyteArray jbuffer, jobject jwaiters, jobject jevents) {
-       enqueueBufferRectPrimitive(env, jqueue, jmem, blocking, jbuf_origin, jhost_origin, jregion,
-                                  buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch,
-                                  jbuffer, jwaiters, jevents, 3,
-                                  (enqueueReadWriteBufferRect_t)clEnqueueWriteBufferRect);
-}
-
-/* ********************************************************************** */
-/* Primitive array Image read/writes */
-
-static void enqueueImagePrimitive
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jarray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents,
- int elshift,
- enqueueReadWriteImage_t op) {
-       if (!op) {
-               throwException(env, "java/lang/UnsupportedOperationException", "Image read/write");
-               return;
-       }
-
-       cl_command_queue queue = GETP(env, jqueue);
-       cl_mem image;
-       void *buffer;
-       size_t origin[3];
-       size_t region[3];
-       size_t elsize, tsize;
-       struct events_info einfo;
-       cl_int res;
-
-       GET_P(env, jimage, image,, "image must not be null");
-
-       CHECK_ARRAY_MIN(env, jorigin, 3,, "origin must be 3-elements long");
-       CHECK_ARRAY_MIN(env, jregion, 3,, "region must be 3-elements long");
-
-       getSizeTA(env, jorigin, origin, 3);
-       getSizeTA(env, jregion, region, 3);
-
-       // Needed to check transfer size
-       clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(elsize), &elsize, NULL);
-       
-       //blocking = PRIMITIVE_BLOCKING(blocking);
-       blocking = CL_TRUE;
-
-       // Map to java primitive type.
-       bufoffset <<= elshift;
-       row_pitch <<= elshift;
-       slice_pitch <<= elshift;
-
-       tsize = get_transfer_size(region, row_pitch, slice_pitch, elsize);
-
-       CHECK_ARRAY_MIN(env, jbuffer, tsize >> elshift,, "array too small");
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       buffer = (*env)->GetPrimitiveArrayCritical(env, jbuffer, NULL);
-
-       res = op(queue,
-                image,
-                blocking,
-                origin,
-                region,
-                row_pitch,
-                slice_pitch,
-                buffer + bufoffset,
-                einfo.wait_count,
-                einfo.waitersp,
-                einfo.eventp);
-               
-       (*env)->ReleasePrimitiveArrayCritical(env, jbuffer, buffer, 0);
-
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3BJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jbyteArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 0,
-                             clEnqueueReadImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3SJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jshortArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 1,
-                             clEnqueueReadImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3IJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jintArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 2,
-                             clEnqueueReadImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3JJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jlongArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 3,
-                             clEnqueueReadImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3FJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jfloatArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 2,
-                             clEnqueueReadImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueReadImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3DJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jdoubleArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 3,
-                             clEnqueueReadImage);
-}
-
-/* * * * */
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3BJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jbyteArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 0,
-                             (enqueueReadWriteImage_t)clEnqueueWriteImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3SJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jshortArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 1,
-                             (enqueueReadWriteImage_t)clEnqueueWriteImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3IJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jintArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 2,
-                             (enqueueReadWriteImage_t)clEnqueueWriteImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3JJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jlongArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 3,
-                             (enqueueReadWriteImage_t)clEnqueueWriteImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3FJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jfloatArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 2,
-                             (enqueueReadWriteImage_t)clEnqueueWriteImage);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_CLCommandQueue_enqueueWriteImage__Lau_notzed_zcl_CLImage_2Z_3J_3JJJ_3DJLau_notzed_zcl_CLEventList_2Lau_notzed_zcl_CLEventList_2
-(JNIEnv *env, jobject jqueue, jobject jimage, jboolean blocking, jlongArray jorigin, jlongArray jregion,
- jlong row_pitch, jlong slice_pitch,
- jdoubleArray jbuffer, jlong bufoffset,
- jobject jwaiters, jobject jevents) {
-       enqueueImagePrimitive(env, jqueue, jimage, blocking, jorigin, jregion, row_pitch, slice_pitch,
-                             jbuffer, bufoffset, jwaiters, jevents, 3,
-                             (enqueueReadWriteImage_t)clEnqueueWriteImage);
-}
diff --git a/src/notzed.zcl/jni/zcl-jni.def b/src/notzed.zcl/jni/zcl-jni.def
deleted file mode 100644 (file)
index 4b58795..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-java CLExtendable au/notzed/zcl/CLExtendable {
-        apiVersion, I
-}
-java CLMemory au/notzed/zcl/CLMemory {
-}
-
-java Object java/lang/Object {
-}
-java Long java/lang/Long {
-       static valueOf, (J)Ljava/lang/Long;
-}
-java Integer java/lang/Integer {
-       static valueOf, (I)Ljava/lang/Integer;
-}
-java byte_a [B {
-}
-
-java CLProperty au/notzed/zcl/CLProperty {
-       static toInt, ([Ljava/lang/Object;)[I
-       static toLong, ([Ljava/lang/Object;)[J
-}
-java CLContextProperty au/notzed/zcl/CLContextProperty {
-}
-java CLContextProperty_TagValue au/notzed/zcl/CLContextProperty$TagValue {
-        <init>, (JJ)V
-}
-java CLDeviceProperty au/notzed/zcl/CLDeviceProperty {
-}
-java CLDeviceProperty_TagValue au/notzed/zcl/CLDeviceProperty$TagValue {
-        <init>, (JJ)V
-}
-java CLDeviceProperty_PartitionByCounts au/notzed/zcl/CLDeviceProperty$PartitionByCounts {
-        <init>, ([I)V
-}
-java CLImageDesc au/notzed/zcl/CLImageDesc {
-        imageType, I
-        imageWidth, I
-        imageHeight, I
-        imageDepth, I
-        imageArraySize, I
-        imageRowPitch, I
-        imageSlicePitch, I
-        numMipLevels, I
-        numSamples, I
-        memObject, Lau/notzed/zcl/CLMemory;
-}
-java CLImageFormat au/notzed/zcl/CLImageFormat {
-        <init>, (II)V
-        channelOrder, I
-        channelDataType, I
-}
-java CLBufferInfoRegion au/notzed/zcl/CLBufferInfo$Region {
-        origin, J
-        size, J
-}
-java CLEventList au/notzed/zcl/CLEventList {
-        add, (J)V
-        index, I
-        events, [J
-}
-java CLContextNotify au/notzed/zcl/CLContextNotify {
-        notify, (Ljava/lang/String;Ljava/nio/ByteBuffer;)V
-}
-java CLEventNotify au/notzed/zcl/CLEventNotify {
-        notify, (Lau/notzed/zcl/CLEvent;I)V
-}
-java CLNotify au/notzed/zcl/CLNotify {
-        notify, (Ljava/lang/Object;)V
-}
-java CLNativeKernel au/notzed/zcl/CLNativeKernel {
-        invoke, ([Ljava/lang/Object;)V
-}
-
diff --git a/src/notzed.zcl/jni/zcl-khr-gl-event.c b/src/notzed.zcl/jni/zcl-khr-gl-event.c
deleted file mode 100644 (file)
index 7795209..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Zucchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-  Binding handler for gl event extension.
- */
-
-#include "au_notzed_zcl_khr_GLEvent.h"
-#include "au_notzed_zcl_CLObject.h"
-
-#include <CL/cl_gl_ext.h>
-
-#include "zcl-extension.h"
-
-#include "nativez.h"
-
-extern jfieldID CLNative_p;
-#define GETP(env, o) NativeZ_getP(env, o)
-
-#ifndef CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR
-jobject createExtension_cl_khr_gl_event(JNIEnv *env, cl_platform_id platform) {
-       // throw new?
-       fprintf(stderr, "extension cl_khr_gl_event unavailable at build time\n");
-       fflush(stderr);
-       return NULL;
-}
-#else
-struct ext_cl_khr_gl_event {
-       cl_event (*clCreateEventFromGLsyncKHR)(cl_context, cl_GLsync, cl_int *);
-};
-
-jobject createExtension_cl_khr_gl_event(JNIEnv *env, cl_platform_id platform) {
-       struct ext_cl_khr_gl_event *p;
-
-       p = malloc(sizeof(*p));
-
-       p->clCreateEventFromGLsyncKHR = getExtensionAddress(platform, "clCreateEventFromGLsyncKHR");
-       // FIXME: check they are there
-
-       jobject jo = createExtension(env, p, "au/notzed/zcl/khr/GLEvent");
-
-       if (!jo)
-               free(p);
-
-       return jo;
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_khr_GLEvent_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       free((void *)jp);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_khr_GLEvent_clCreateEventFromGLsync
-(JNIEnv *env, jobject jext, jobject jcontext, jlong glsync) {
-       struct ext_cl_khr_gl_event *ext = GETP(env, jext);
-       cl_context context = GETP(env, jcontext);
-       cl_int res = 0;
-       cl_event mo;
-
-       THROW_UNSUPPORTED_RET(ext->clCreateEventFromGLsyncKHR, "clCreateEventFromGLsyncKHR", NULL);
-
-       printf("createEventFromGLsync(%ld)\n", (long int)glsync);
-       fflush(stdout);
-       
-       mo = ext->clCreateEventFromGLsyncKHR(context, (cl_GLsync)(intptr_t)glsync, &res);
-
-       printf("mo = %p, res = %d\n", mo, res);
-       fflush(stdout);
-       
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_EVENT, mo);
-}
-
-#endif // have extension
diff --git a/src/notzed.zcl/jni/zcl-khr-gl-sharing.c b/src/notzed.zcl/jni/zcl-khr-gl-sharing.c
deleted file mode 100644 (file)
index cb8b548..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Zucchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-  Binding handler for gl sharing extension.
-
-  This is just proof of concept/expriments and not complete.
- */
-
-#include "au_notzed_zcl_khr_GLSharing.h"
-#include "au_notzed_zcl_CLObject.h"
-
-#include <CL/cl_gl_ext.h>
-
-#include "zcl-extension.h"
-#include "nativez.h"
-
-extern jfieldID CLNative_p;
-#define GETP(env, o) NativeZ_getP(env, o)
-extern size_t const ctype_sizes[];
-
-#ifdef cl_khr_gl_sharing
-struct ext_cl_khr_gl_sharing {
-       cl_mem (*clCreateFromGLBuffer)(cl_context, cl_mem_flags, cl_GLuint, int *);
-       cl_mem (*clCreateFromGLTexture)(cl_context, cl_mem_flags, cl_GLenum, cl_GLint, cl_GLuint, cl_int *);
-       cl_mem (*clCreateFromGLRenderbuffer)(cl_context   /* context */,
-                                            cl_mem_flags /* flags */,
-                                            cl_GLuint    /* renderbuffer */,
-                                            cl_int *     /* errcode_ret */);   
-       cl_int (*clEnqueueAcquireGLObjects)(cl_command_queue      /* command_queue */,
-                                           cl_uint               /* num_objects */,
-                                           const cl_mem *        /* mem_objects */,
-                                           cl_uint               /* num_events_in_wait_list */,
-                                           const cl_event *      /* event_wait_list */,
-                                           cl_event *            /* event */);
-
-       cl_int (*clEnqueueReleaseGLObjects)(cl_command_queue      /* command_queue */,
-                                           cl_uint               /* num_objects */,
-                                           const cl_mem *        /* mem_objects */,
-                                           cl_uint               /* num_events_in_wait_list */,
-                                           const cl_event *      /* event_wait_list */,
-                                           cl_event *            /* event */);
-       clGetGLContextInfoKHR_fn clGetGLContextInfoKHR;
-       cl_int (*clGetGLObjectInfo)(cl_mem, cl_gl_object_type *, cl_GLuint *);
-       cl_int (*clGetGLTextureInfo)(cl_mem, cl_gl_texture_info, size_t, void *, size_t *);
-};
-
-static jclass GLObjectInfo_classid;
-static jmethodID GLObjectInfo_new_ii;
-
-jobject createExtension_cl_khr_gl_sharing(JNIEnv *env, cl_platform_id platform) {
-       struct ext_cl_khr_gl_sharing *p;
-
-       if (!GLObjectInfo_classid) {
-               jclass jc;
-               jc = (*env)->FindClass(env, "au/notzed/zcl/khr/GLSharing$GLObjectInfo");
-               if (jc == NULL)
-                       return NULL;
-
-               GLObjectInfo_classid = jc = (*env)->NewGlobalRef(env, jc);
-               GLObjectInfo_new_ii = (*env)->GetMethodID(env, jc, "<init>", "(II)V");
-       }
-
-       //cl_khr_gl_sharing
-
-       p = malloc(sizeof(*p));
-
-       p->clCreateFromGLBuffer = getExtensionAddress(platform, "clCreateFromGLBuffer");
-       p->clCreateFromGLTexture = getExtensionAddress(platform, "clCreateFromGLTexture");
-       p->clCreateFromGLRenderbuffer = getExtensionAddress(platform, "clCreateFromGLRenderbuffer");
-       p->clEnqueueAcquireGLObjects = getExtensionAddress(platform, "clEnqueueAcquireGLObjects");
-       p->clEnqueueReleaseGLObjects = getExtensionAddress(platform, "clEnqueueReleaseGLObjects");
-       p->clGetGLContextInfoKHR = getExtensionAddress(platform, "clGetGLContextInfoKHR");
-       p->clGetGLObjectInfo = getExtensionAddress(platform, "clGetGLObjectInfo");
-       p->clGetGLTextureInfo = getExtensionAddress(platform, "clGetGLTextureInfo");
-       // FIXME: check they are there
-
-       jobject jo = createExtension(env, p, "au/notzed/zcl/khr/GLSharing");
-
-       if (!jo)
-               free(p);
-       
-       return jo;
-}
-#else
-jobject createExtension_cl_khr_gl_sharing(JNIEnv *env, cl_platform_id platform) {
-       // throw new?
-       return NULL;
-}
-#endif
-
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_khr_GLSharing_release
-(JNIEnv *env, jclass jc, jlong jp) {
-       free((void *)jp);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_khr_GLSharing_createFromGLBuffer
-(JNIEnv *env, jobject jext, jobject jcontext, jlong flags, jint bufobj) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_context context = GETP(env, jcontext);
-       cl_int res;
-       cl_mem mo;
-
-       mo = ext->clCreateFromGLBuffer(context, flags, bufobj, &res);
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_BUFFER, mo);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_khr_GLSharing_createFromGLTexture
-(JNIEnv *env, jobject jext, jobject jcontext, jlong flags, jint target, jint miplevel, jint texture) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_context context = GETP(env, jcontext);
-       cl_int res;
-       cl_mem mo;
-
-       mo = ext->clCreateFromGLTexture(context, flags, target, miplevel, texture, &res);
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_IMAGE, mo);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_khr_GLSharing_createFromGLRenderbuffer
-(JNIEnv *env, jobject jext, jobject jcontext, jlong flags, jint renderbuffer) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_context context = GETP(env, jcontext);
-       cl_int res;
-       cl_mem mo;
-
-       mo = ext->clCreateFromGLRenderbuffer(context, flags, renderbuffer, &res);
-       THROW_ERROR_RET(res, NULL);
-
-       return toCLObject(env, au_notzed_zcl_CLObject_CTYPE_IMAGE, mo);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_khr_GLSharing_getGLObjectInfo
-(JNIEnv *env, jobject jext, jobject jmem) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_mem mem = GETP(env, jmem);
-       cl_gl_object_type type;
-       cl_GLuint name;
-       cl_int res;
-       
-       res = ext->clGetGLObjectInfo(mem, &type, &name);
-       THROW_ERROR_RET(res, NULL);
-
-       jvalue args[] = {
-               { .i = type },
-               { .i = name }
-       };
-       
-       return (*env)->NewObjectA(env, GLObjectInfo_classid, GLObjectInfo_new_ii, args);
-}
-
-JNIEXPORT jint JNICALL Java_au_notzed_zcl_khr_GLSharing_getGLTextureInfoInt
-(JNIEnv *env, jobject jext, jobject jmem, jint param) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_mem mem = GETP(env, jmem);
-       cl_int res;
-       cl_GLuint value;
-
-       res = ext->clGetGLTextureInfo(mem, param, sizeof(value), &value, NULL);
-       THROW_ERROR_RET(res, 0);
-
-       return value;
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_khr_GLSharing_enqueueAcquireGLObjects
-(JNIEnv *env, jobject jext, jobject jqueue, jobjectArray jmemlist, jobject jwaiters, jobject jevents) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_command_queue queue = GETP(env, jqueue);
-       struct events_info einfo;
-       cl_int res;
-       cl_mem *memlist;
-       cl_uint mlen;
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       if (jmemlist) {
-               mlen = (*env)->GetArrayLength(env, jmemlist);
-               memlist = alloca(mlen * sizeof(*memlist));
-               fromObjectArray(env, jmemlist, (void **)memlist, mlen);
-       } else {
-               memlist = NULL;
-               mlen = 0;
-       }
-       
-       res = ext->clEnqueueAcquireGLObjects(queue,
-                                            mlen, memlist,
-                                            einfo.wait_count,
-                                            einfo.waitersp,
-                                            einfo.eventp);
-
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT void JNICALL Java_au_notzed_zcl_khr_GLSharing_enqueueReleaseGLObjects
-(JNIEnv *env, jobject jext, jobject jqueue, jobjectArray jmemlist, jobject jwaiters, jobject jevents) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_command_queue queue = GETP(env, jqueue);
-       struct events_info einfo;
-       cl_int res;
-       cl_mem *memlist;
-       cl_uint mlen;
-
-       if (events_init(env, &einfo, jwaiters, jevents))
-               return;
-
-       if (jmemlist) {
-               mlen = (*env)->GetArrayLength(env, jmemlist);
-               memlist = alloca(mlen * sizeof(*memlist));
-               fromObjectArray(env, jmemlist, (void **)memlist, mlen);
-       } else {
-               memlist = NULL;
-               mlen = 0;
-       }
-       
-       res = ext->clEnqueueReleaseGLObjects(queue,
-                                            mlen, memlist,
-                                            einfo.wait_count,
-                                            einfo.waitersp,
-                                            einfo.eventp);
-
-       THROW_ERROR(res);
-
-       events_post(env, &einfo, jevents);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_khr_GLSharing_getGLContextInfoKHRAny
-(JNIEnv *env, jobject jext, jobjectArray jprops, jint ctype, jint param) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_context_properties *props = fromPropertyArray(env, jprops);
-       size_t size = ctype_sizes[ctype];
-       void *value = alloca(size);
-       cl_int res;
-
-       if ((*env)->ExceptionCheck(env)) return NULL;
-
-       value = alloca(size);
-       res = ext->clGetGLContextInfoKHR(props, param, size, value, NULL);
-       free(props);
-       THROW_RTERROR_RET(res, NULL);
-
-       return toObject(env, ctype, size, value);
-}
-
-JNIEXPORT jobject JNICALL Java_au_notzed_zcl_khr_GLSharing_getGLContextInfoKHRAnyV
-(JNIEnv *env, jobject jext, jobjectArray jprops, jint ctype, jint param) {
-       struct ext_cl_khr_gl_sharing *ext = GETP(env, jext);
-       cl_context_properties *props = fromPropertyArray(env, jprops);
-       size_t size = ctype_sizes[ctype] * 32;
-       void *value = alloca(size);
-       cl_int res;
-
-       res = ext->clGetGLContextInfoKHR(props, param, size, value, &size);
-       free(props);
-       THROW_RTERROR_RET(res, NULL);
-       
-       return toArray(env, ctype, size, value);
-}