diff options
author | Yang Ni <yangni@google.com> | 2015-04-17 16:51:55 -0700 |
---|---|---|
committer | Yang Ni <yangni@google.com> | 2015-04-21 14:13:47 -0700 |
commit | 18314caccd4e4b7cf59f2a18a38181f8e3d88634 (patch) | |
tree | 97dbae15b3ecd991e969a4dbd1e460dcc89b2916 /rs/java/android/renderscript/ScriptGroup2.java | |
parent | 9d4efdf2802f06ccf7031610891f75af70ea5538 (diff) |
Move new script group API into ScriptGroup class
And mark existing methods and builder deprecated.
Removed ScriptGroup2 class.
Renamed nested class UnboundValue to Input.
Marked classes Closure, Future, and Input as final.
Change-Id: I362910c115e9d0173dc515674e08bf4878232879
Diffstat (limited to 'rs/java/android/renderscript/ScriptGroup2.java')
-rw-r--r-- | rs/java/android/renderscript/ScriptGroup2.java | 592 |
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 96bb6e203bff..000000000000 --- 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; - } - - } -} |