+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
------------
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 = \
--transform=s,^,$(dist_NAME)-$(dist_VERSION)/, \
config.make java.make Makefile src \
$(dist_EXTRA)
-
<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=<path_to_property_file> jar (where you put the property "platforms.${platform.active}.home" in a .properties file)
+ or ant -Dplatforms.${platform.active}.home=<path_to_JDK_home> 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}"/>
<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">
<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">
<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"/>
<!-- 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>
<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"/>
</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>
</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>
<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"/>
</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."/>
<classpath>
<path path="@{classpath}"/>
</classpath>
+ <bootclasspath>
+ <path path="${platform.bootcp}"/>
+ </bootclasspath>
</nbjpdastart>
</sequential>
</macrodef>
<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>
<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">
<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}">
<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}"/>
</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>
<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>
<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}"/>
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
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}
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.
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
<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>
/*
- * 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);
}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
*/
package au.notzed.zcl;
+import jdk.incubator.foreign.*;
+
import java.nio.ByteBuffer;
+import java.lang.invoke.MethodHandle;
/**
* Interface for memory buffers.
*/
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().
*
* Parameters for Buffer.createSubBuffer()
* <p>
* Specific types are defined on CLBuffer.
- *
+ *
*/
public abstract class CLBufferInfo {
*/
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.
*
* @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) {
*
* @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.
* @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.
* @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();
+ }
/**
*
* @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,
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);
+ }
+ }
/**
*
* @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,
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
* @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.
* @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.
* @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.
*
* @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.
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
* @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,
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);
+ }
+ }
/**
*
* @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);
+ }
+ }
/**
*
* @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,
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,
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,
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,
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);
+ }
+ }
/**
*
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.
*
* @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);
+ }
+ }
/**
*
* @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.
* 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.
* @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.
* @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().
}
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() {
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.
*/
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
*/
/**
* 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() {
}
@Override
- int getInfoType() {
- return TYPE_CONTEXT;
+ MethodHandle getInfoFunc() {
+ return clGetContextInfo;
}
/**
* @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());
}
/**
* 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) -> {
* 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.
* @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.
* @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);
+ }
+ }
/**
*
* @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.
* @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
* @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.
* @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.
* @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.
* @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.
* @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
* @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.
* 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);
}
* @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.
* 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.
* @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.
* @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.
* @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.
* @return List of devices.
*/
public CLDevice[] getDevices() {
- return getInfoAnyV(CTYPE_DEVICE, CL_CONTEXT_DEVICES);
+ return getInfoAnyV(CL_CONTEXT_DEVICES, clGetContextInfo, CLDevice::new, CLDevice[]::new);
}
/**
*
* @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);
+ // }
}
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*()
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;
+ }
+ }
+
+
}
*/
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.
*
* @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() {
}
@Override
- int getInfoType() {
- return TYPE_DEVICE;
+ MethodHandle getInfoFunc() {
+ return clGetDeviceInfo;
}
@Override
* @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.
* @return host_timestamp.
* @since OpenCN 2.1
*/
- public native long getHostTimer();
+ //public native long getHostTimer();
/**
* Create a property representing CL_DEVICE_PARTITION_EQUALLY.
* @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
}
public CLPlatform getPlatform() {
- return getInfoAny(CTYPE_PLATFORM, CL_DEVICE_PLATFORM);
+ return getInfoAny(CL_DEVICE_PLATFORM, clGetDeviceInfo, CLPlatform::new);
}
public String getName() {
}
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];
+ //}
}
*/
package au.notzed.zcl;
+import api.Native;
+import jdk.incubator.foreign.MemoryAddress;
+
/**
* Properties for CLDevice sub-device creation.
*
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;
+ }
}
}
*/
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;
}
/**
* @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).
* @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.
* @return
*/
public CLCommandQueue getCommandQueue() {
- return getInfoAny(CTYPE_COMMAND_QUEUE, CL_EVENT_COMMAND_QUEUE);
+ return getInfoAny(CL_EVENT_COMMAND_QUEUE, clGetEventInfo, CLCommandQueue::new);
}
/**
* @return
*/
public CLContext getContext() {
- return getInfoAny(CTYPE_CONTEXT, CL_EVENT_CONTEXT);
+ return getInfoAny(CL_EVENT_CONTEXT, clGetEventInfo, CLContext::new);
}
/**
}
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);
}
}
*/
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>
*/
public class CLEventList {
- /**
- * C-accessible copy of jevets[i].p
- */
- final long[] events;
/**
* Event references.
*/
* @param capacity Sets the event list capacity. This
*/
public CLEventList(int capacity) {
- this.events = new long[capacity];
this.jevents = new CLEvent[capacity];
}
public void reset() {
for (int i = 0; i < index; i++) {
jevents[i] = null;
- events[i] = 0;
}
index = 0;
}
* @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.
*
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);
+ }
+ }
+ }
}
*/
package au.notzed.zcl;
+import api.Callback;
+import api.Native;
+
/**
* Callback for CLEvent.
*/
+@FunctionalInterface
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;
+ }
+ }
}
-/**
- * *****************************************************************************
- * 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;
}
}
*/
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.
*/
final int apiVersion;
- public CLExtendable(long p) {
+ public CLExtendable(MemoryAddress p) {
super(p);
platform = initPlatform();
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.
* @return
*/
protected <T extends CLExtension> T getExtension(Class<T> klass, int id) {
- return platform.getExtension(klass, id);
+ //return platform.getExtension(klass, id);
+ return null;
}
}
*/
package au.notzed.zcl;
+import jdk.incubator.foreign.MemoryAddress;
+import java.lang.invoke.MethodHandle;
+
/**
* Experimental code for extension support.
* <p>
*/
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();
}
-
+
}
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.
* 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);
}
public CLBuffer getBuffer() {
- return getInfoAny(CTYPE_BUFFER, CL_IMAGE_BUFFER);
+ return getInfoAny(CL_IMAGE_BUFFER, clGetImageInfo, CLBuffer::new);
}
public int getNumMipLevels() {
@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());
}
/**
*/
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;
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}]"); }
+
}
*/
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 {
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)]"); }
}
*/
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.
*
* @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;
}
/**
* @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.
* 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.
* @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);
}
/**
* @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,
* @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
* @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
* @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
* @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.
* @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.
* @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.
* @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
* @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
* @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
* @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
* @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
* @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
* @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.
}
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
*
* @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 */
*/
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.
*
* @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);
}
/**
* @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);
}
/**
* @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);
}
/**
* @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);
}
/**
* @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);
}
}
*/
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.
*/
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.
* @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);
}
/**
* 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.
* @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);
}
/**
* @return
*/
public CLBuffer getAssociatedMemObject() {
- return getInfoAny(CTYPE_BUFFER, CL_MEM_ASSOCIATED_MEMOBJECT);
+ return getInfoAny(CL_MEM_ASSOCIATED_MEMOBJECT, clGetMemObjectInfo, CLBuffer::new);
}
/**
}
}
- 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
*/
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;
+ }
+ }
}
*/
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.
* 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;
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.
* @return
*/
public int getInfoInt(int param) {
- return getInfoInt(getInfoType(), param);
+ return getInfoInt(param, getInfoFunc());
}
/**
* @return
*/
public long getInfoLong(int param) {
- return getInfoLong(getInfoType(), param);
+ return getInfoLong(param, getInfoFunc());
}
/**
* @throws CLRuntimeException
*/
public long getInfoSizeT(int param) {
- return getInfoSizeT(getInfoType(), param);
+ return getInfoSizeT(param, getInfoFunc());
}
/**
* @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());
}
/**
* @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();
}
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.
*
* @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() {
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
*
* @param p Native pointer.
*/
- public CLPlatform(long p) {
+ public CLPlatform(MemoryAddress p) {
super(p);
String v = getVersion();
}
}
- private native static void release(long p);
+ private static void release(MemoryAddress p) {
+ // noop
+ }
+
+ @Override
+ public void release() {
+ // noop
+ }
@Override
public String toString() {
}
@Override
- int getInfoType() {
- return TYPE_PLATFORM;
+ MethodHandle getInfoFunc() {
+ return clGetPlatformInfo;
}
/**
* @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.
* @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.
*
* @throws CLRuntimeException
*/
- public native void unloadPlatformCompiler() throws CLRuntimeException;
+ //public native void unloadPlatformCompiler() throws CLRuntimeException;
/**
* get CL_PLATFORM_PROFILE.
* <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.
* @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;
+ //}
}
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.
*
* @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;
}
/**
* @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) -> {
* @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.
* 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() {
}
public CLDevice[] getDevices() {
- return getInfoAnyV(CTYPE_DEVICE, CL_PROGRAM_DEVICES);
+ return getInfoAnyV(CL_PROGRAM_DEVICES, clGetProgramInfo, CLDevice::new, CLDevice[]::new);
}
public String getSource() {
}
/* 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);
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);
}
-
}
*/
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.
* @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.
* @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.
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);
+ }
}
/**
* @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;
}
* @param props
* @return
*/
+ /*
public static int[] toInt(Object[] props) {
int[] dst = new int[getSize(props)];
int o = 0;
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;
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);
+ }
}
-/*
- * 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 + ")";
}
-
}
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.
*
* @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() {
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);
}
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);
}
* 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;
}
--- /dev/null
+#!/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;
--- /dev/null
+
+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)
--- /dev/null
+#!/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);
+}
--- /dev/null
+
+# 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
+);
--- /dev/null
+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
+++ /dev/null
-# 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 $@
+++ /dev/null
-/*
- * 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
+++ /dev/null
-#!/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";
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-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
-}
-
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
-}