summaryrefslogtreecommitdiffstats
path: root/rs/java/android/renderscript/ScriptGroup2.java
diff options
context:
space:
mode:
Diffstat (limited to 'rs/java/android/renderscript/ScriptGroup2.java')
-rw-r--r--rs/java/android/renderscript/ScriptGroup2.java592
1 files changed, 0 insertions, 592 deletions
diff --git a/rs/java/android/renderscript/ScriptGroup2.java b/rs/java/android/renderscript/ScriptGroup2.java
deleted file mode 100644
index 96bb6e2..0000000
--- a/rs/java/android/renderscript/ScriptGroup2.java
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.renderscript;
-
-import android.util.Log;
-import android.util.Pair;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * ScriptGroup2 is a new, enhanced API for script groups.
- * A script group is a collection of kernels or invocable functions, with
- * data dependencies defined among them. A script group is launched for
- * execution as a whole, rather than launching each kernel or invocable function
- * separately. Once created, a script group can be repeatedly used with
- * different inputs.
- * <p>
- * In the new ScriptGroup2 API, a script group is modeled using closures.
- * A closure, in this context, is defined as a function call to a kernel or
- * invocable function. Each function argument or global variable accessed inside
- * the function is bound to 1) a known value, 2) a script group input, or 3) a
- * future. A future is the output of a closure, i.e., the return value of the
- * function or a global variable written by that function.
- * <p>
- * A script group is a directed acyclic graph (DAG), in which closures are the
- * vertices and the dependencies among them are the edges.
- * The way the ScriptGroup2 API is designed makes cycles impossible in a script
- * group. For example, it is impossible to make forward references to futures,
- * i.e., it is impossible to set as input to a closure the future from itself or
- * a future from another closure that directly or indirectly depends on it.
- * <p>
- * Grouping kernels and invocable functions together allows to execute them more
- * efficiently. Runtime and compiler optimizations are applied to script
- * groups, to reduce computation or communication overhead, and to make more
- * efficient use of the CPU and the GPU.
- */
-
-public class ScriptGroup2 extends BaseObj {
-
- /**
- * An opaque class for closures
- */
-
- public static class Closure extends BaseObj {
- private Object[] mArgs;
- private Allocation mReturnValue;
- private Map<Script.FieldID, Object> mBindings;
-
- private Future mReturnFuture;
- private Map<Script.FieldID, Future> mGlobalFuture;
-
- private FieldPacker mFP;
-
- private static final String TAG = "Closure";
-
- public Closure(long id, RenderScript rs) {
- super(id, rs);
- }
-
- public Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
- Object[] args, Map<Script.FieldID, Object> globals) {
- super(0, rs);
-
- mArgs = args;
- mReturnValue = Allocation.createTyped(rs, returnType);
- mBindings = globals;
- mGlobalFuture = new HashMap<Script.FieldID, Future>();
-
- int numValues = args.length + globals.size();
-
- long[] fieldIDs = new long[numValues];
- long[] values = new long[numValues];
- int[] sizes = new int[numValues];
- long[] depClosures = new long[numValues];
- long[] depFieldIDs = new long[numValues];
-
- int i;
- for (i = 0; i < args.length; i++) {
- Object obj = args[i];
- fieldIDs[i] = 0;
- if (obj instanceof UnboundValue) {
- UnboundValue unbound = (UnboundValue)obj;
- unbound.addReference(this, i);
- } else {
- retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes,
- depClosures, depFieldIDs);
- }
- }
-
- for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
- Object obj = entry.getValue();
- Script.FieldID fieldID = entry.getKey();
- fieldIDs[i] = fieldID.getID(rs);
- if (obj instanceof UnboundValue) {
- UnboundValue unbound = (UnboundValue)obj;
- unbound.addReference(this, fieldID);
- } else {
- retrieveValueAndDependenceInfo(rs, i, obj, values,
- sizes, depClosures, depFieldIDs);
- }
- i++;
- }
-
- long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs),
- fieldIDs, values, sizes, depClosures, depFieldIDs);
-
- setID(id);
- }
-
- public Closure(RenderScript rs, Script.InvokeID invokeID,
- Object[] args, Map<Script.FieldID, Object> globals) {
- super(0, rs);
- mFP = FieldPacker.createFromArray(args);
-
- mArgs = args;
- mBindings = globals;
- mGlobalFuture = new HashMap<Script.FieldID, Future>();
-
- int numValues = globals.size();
-
- long[] fieldIDs = new long[numValues];
- long[] values = new long[numValues];
- int[] sizes = new int[numValues];
- long[] depClosures = new long[numValues];
- long[] depFieldIDs = new long[numValues];
-
- int i = 0;
- for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
- Object obj = entry.getValue();
- Script.FieldID fieldID = entry.getKey();
- fieldIDs[i] = fieldID.getID(rs);
- if (obj instanceof UnboundValue) {
- UnboundValue unbound = (UnboundValue)obj;
- unbound.addReference(this, fieldID);
- } else {
- retrieveValueAndDependenceInfo(rs, i, obj, values,
- sizes, depClosures, depFieldIDs);
- }
- i++;
- }
-
- long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs,
- values, sizes);
-
- setID(id);
- }
-
- private static
- void retrieveValueAndDependenceInfo(RenderScript rs,
- int index, Object obj,
- long[] values, int[] sizes,
- long[] depClosures,
- long[] depFieldIDs) {
-
- if (obj instanceof Future) {
- Future f = (Future)obj;
- obj = f.getValue();
- depClosures[index] = f.getClosure().getID(rs);
- Script.FieldID fieldID = f.getFieldID();
- depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
- if (obj == null) {
- // Value is originally created by the owner closure
- values[index] = 0;
- sizes[index] = 0;
- return;
- }
- } else {
- depClosures[index] = 0;
- depFieldIDs[index] = 0;
- }
-
- ValueAndSize vs = new ValueAndSize(rs, obj);
- values[index] = vs.value;
- sizes[index] = vs.size;
- }
-
- /**
- * Returns the future for the return value
- *
- * @return a future
- */
-
- public Future getReturn() {
- if (mReturnFuture == null) {
- mReturnFuture = new Future(this, null, mReturnValue);
- }
-
- return mReturnFuture;
- }
-
- /**
- * Returns the future for a global variable
- *
- * @param field the field ID for the global variable
- * @return a future
- */
-
- public Future getGlobal(Script.FieldID field) {
- Future f = mGlobalFuture.get(field);
-
- if (f == null) {
- // If the field is not bound to this closure, this will return a future
- // without an associated value (reference). So this is not working for
- // cross-module (cross-script) linking in this case where a field not
- // explicitly bound.
- f = new Future(this, field, mBindings.get(field));
- mGlobalFuture.put(field, f);
- }
-
- return f;
- }
-
- void setArg(int index, Object obj) {
- mArgs[index] = obj;
- ValueAndSize vs = new ValueAndSize(mRS, obj);
- mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
- }
-
- void setGlobal(Script.FieldID fieldID, Object obj) {
- mBindings.put(fieldID, obj);
- ValueAndSize vs = new ValueAndSize(mRS, obj);
- mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
- }
-
- private static final class ValueAndSize {
- public ValueAndSize(RenderScript rs, Object obj) {
- if (obj instanceof Allocation) {
- value = ((Allocation)obj).getID(rs);
- size = -1;
- } else if (obj instanceof Boolean) {
- value = ((Boolean)obj).booleanValue() ? 1 : 0;
- size = 4;
- } else if (obj instanceof Integer) {
- value = ((Integer)obj).longValue();
- size = 4;
- } else if (obj instanceof Long) {
- value = ((Long)obj).longValue();
- size = 8;
- } else if (obj instanceof Float) {
- value = ((Float)obj).longValue();
- size = 4;
- } else if (obj instanceof Double) {
- value = ((Double)obj).longValue();
- size = 8;
- }
- }
- public long value;
- public int size;
- }
- }
-
- /**
- * An opaque class for futures
- */
-
- public static class Future {
- Closure mClosure;
- Script.FieldID mFieldID;
- Object mValue;
-
- Future(Closure closure, Script.FieldID fieldID, Object value) {
- mClosure = closure;
- mFieldID = fieldID;
- mValue = value;
- }
-
- Closure getClosure() { return mClosure; }
- Script.FieldID getFieldID() { return mFieldID; }
- Object getValue() { return mValue; }
- }
-
- /**
- * An opaque class for unbound values (a.k.a. script group inputs)
- */
-
- public static class UnboundValue {
- // Either mFieldID or mArgIndex should be set but not both.
- List<Pair<Closure, Script.FieldID>> mFieldID;
- // -1 means unset. Legal values are 0 .. n-1, where n is the number of
- // arguments for the referencing closure.
- List<Pair<Closure, Integer>> mArgIndex;
-
- UnboundValue() {
- mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
- mArgIndex = new ArrayList<Pair<Closure, Integer>>();
- }
-
- void addReference(Closure closure, int index) {
- mArgIndex.add(Pair.create(closure, Integer.valueOf(index)));
- }
-
- void addReference(Closure closure, Script.FieldID fieldID) {
- mFieldID.add(Pair.create(closure, fieldID));
- }
-
- void set(Object value) {
- for (Pair<Closure, Integer> p : mArgIndex) {
- Closure closure = p.first;
- int index = p.second.intValue();
- closure.setArg(index, value);
- }
- for (Pair<Closure, Script.FieldID> p : mFieldID) {
- Closure closure = p.first;
- Script.FieldID fieldID = p.second;
- closure.setGlobal(fieldID, value);
- }
- }
- }
-
- String mName;
- List<Closure> mClosures;
- List<UnboundValue> mInputs;
- Future[] mOutputs;
-
- private static final String TAG = "ScriptGroup2";
-
- public ScriptGroup2(long id, RenderScript rs) {
- super(id, rs);
- }
-
- ScriptGroup2(RenderScript rs, String name, List<Closure> closures,
- List<UnboundValue> inputs, Future[] outputs) {
- super(0, rs);
- mName = name;
- mClosures = closures;
- mInputs = inputs;
- mOutputs = outputs;
-
- long[] closureIDs = new long[closures.size()];
- for (int i = 0; i < closureIDs.length; i++) {
- closureIDs[i] = closures.get(i).getID(rs);
- }
- long id = rs.nScriptGroup2Create(name, ScriptC.mCachePath, closureIDs);
- setID(id);
- }
-
- /**
- * Executes a script group
- *
- * @param inputs inputs to the script group
- * @return outputs of the script group as an array of objects
- */
-
- public Object[] execute(Object... inputs) {
- if (inputs.length < mInputs.size()) {
- Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
- "less than expected " + mInputs.size());
- return null;
- }
-
- if (inputs.length > mInputs.size()) {
- Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
- "more than expected " + mInputs.size());
- }
-
- for (int i = 0; i < mInputs.size(); i++) {
- Object obj = inputs[i];
- if (obj instanceof Future || obj instanceof UnboundValue) {
- Log.e(TAG, this.toString() + ": input " + i +
- " is a future or unbound value");
- return null;
- }
- UnboundValue unbound = mInputs.get(i);
- unbound.set(obj);
- }
-
- mRS.nScriptGroup2Execute(getID(mRS));
-
- Object[] outputObjs = new Object[mOutputs.length];
- int i = 0;
- for (Future f : mOutputs) {
- outputObjs[i++] = f.getValue();
- }
- return outputObjs;
- }
-
- /**
- * A class representing a binding of a value to a global variable in a
- * kernel or invocable function. Such a binding can be used to create a
- * closure.
- */
-
- public static final class Binding {
- private Script.FieldID mField;
- private Object mValue;
-
- /**
- * Returns a Binding object that binds value to field
- *
- * @param field the Script.FieldID of the global variable
- * @param value the value
- */
-
- public Binding(Script.FieldID field, Object value) {
- mField = field;
- mValue = value;
- }
-
- /**
- * Returns the field ID
- */
-
- public Script.FieldID getField() { return mField; }
-
- /**
- * Returns the value
- */
-
- public Object getValue() { return mValue; }
- }
-
- /**
- * The builder class to create a script group.
- * <p>
- * Closures are created using the {@link #addKernel} or {@link #addInvoke}
- * methods.
- * When a closure is created, futures from previously created closures
- * can be used as inputs.
- * Unbound values can be used as inputs to create closures as well.
- * An unbound value is created using the {@link #addInput} method.
- * Unbound values become inputs to the script group to be created,
- * in the order that they are added.
- * A script group is created by a call to the {@link #create} method, which
- * accepts an array of futures as the outputs for the script group.
- * <p>
- * Closures in a script group can be evaluated in any order as long as the
- * following conditions are met.
- * First, a closure must be evaluated before any other closures that take its
- * futures as inputs.
- * Second, all closures added before an invoke closure must be evaluated
- * before it.
- * Third, all closures added after an invoke closure must be evaluated after
- * it.
- * <p>
- * As a special case, the order that the closures are added is a legal
- * evaluation order. However, other evaluation orders are allowed, including
- * concurrently evaluating independent closures.
- */
-
- public static final class Builder {
- RenderScript mRS;
- List<Closure> mClosures;
- List<UnboundValue> mInputs;
- private static final String TAG = "ScriptGroup2.Builder";
-
- /**
- * Returns a Builder object
- *
- * @param rs the RenderScript context
- */
- public Builder(RenderScript rs) {
- mRS = rs;
- mClosures = new ArrayList<Closure>();
- mInputs = new ArrayList<UnboundValue>();
- }
-
- /**
- * Adds a closure for a kernel
- *
- * @param k Kernel ID for the kernel function
- * @param returnType Allocation type for the return value
- * @param args arguments to the kernel function
- * @param globalBindings bindings for global variables
- * @return a closure
- */
-
- public Closure addKernel(Script.KernelID k, Type returnType, Object[] args,
- Map<Script.FieldID, Object> globalBindings) {
- Closure c = new Closure(mRS, k, returnType, args, globalBindings);
- mClosures.add(c);
- return c;
- }
-
- /**
- * Adds a closure for an invocable function
- *
- * @param invoke Invoke ID for the invocable function
- * @param args arguments to the invocable function
- * @param globalBindings bindings for global variables
- * @return a closure
- */
-
- public Closure addInvoke(Script.InvokeID invoke, Object[] args,
- Map<Script.FieldID, Object> globalBindings) {
- Closure c = new Closure(mRS, invoke, args, globalBindings);
- mClosures.add(c);
- return c;
- }
-
- /**
- * Adds a script group input
- *
- * @return a unbound value that can be used to create a closure
- */
- public UnboundValue addInput() {
- UnboundValue unbound = new UnboundValue();
- mInputs.add(unbound);
- return unbound;
- }
-
- /**
- * Adds a closure for a kernel
- *
- * @param k Kernel ID for the kernel function
- * @param argsAndBindings arguments followed by bindings for global variables
- * @return a closure
- */
-
- public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
- ArrayList<Object> args = new ArrayList<Object>();
- Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
- if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
- return null;
- }
- return addKernel(k, returnType, args.toArray(), bindingMap);
- }
-
- /**
- * Adds a closure for an invocable function
- *
- * @param invoke Invoke ID for the invocable function
- * @param argsAndBindings arguments followed by bindings for global variables
- * @return a closure
- */
-
- public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
- ArrayList<Object> args = new ArrayList<Object>();
- Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
- if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
- return null;
- }
- return addInvoke(invoke, args.toArray(), bindingMap);
- }
-
- /**
- * Creates a script group
- *
- * @param name name for the script group. Legal names can only contain letters, digits,
- * '-', or '_'. The name can be no longer than 100 characters.
- * @param outputs futures intended as outputs of the script group
- * @return a script group
- */
-
- public ScriptGroup2 create(String name, Future... outputs) {
- if (name == null || name.isEmpty() || name.length() > 100 ||
- !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) {
- throw new RSIllegalArgumentException("invalid script group name");
- }
- ScriptGroup2 ret = new ScriptGroup2(mRS, name, mClosures, mInputs, outputs);
- return ret;
- }
-
- private boolean seperateArgsAndBindings(Object[] argsAndBindings,
- ArrayList<Object> args,
- Map<Script.FieldID, Object> bindingMap) {
- int i;
- for (i = 0; i < argsAndBindings.length; i++) {
- if (argsAndBindings[i] instanceof Binding) {
- break;
- }
- args.add(argsAndBindings[i]);
- }
-
- for (; i < argsAndBindings.length; i++) {
- if (!(argsAndBindings[i] instanceof Binding)) {
- return false;
- }
- Binding b = (Binding)argsAndBindings[i];
- bindingMap.put(b.getField(), b.getValue());
- }
-
- return true;
- }
-
- }
-}