diff options
Diffstat (limited to 'rs/java/android/renderscript')
| -rw-r--r-- | rs/java/android/renderscript/Allocation.java | 15 | ||||
| -rw-r--r-- | rs/java/android/renderscript/FieldPacker.java | 225 | ||||
| -rw-r--r-- | rs/java/android/renderscript/RenderScript.java | 32 | ||||
| -rw-r--r-- | rs/java/android/renderscript/RenderScriptCacheDir.java | 40 | ||||
| -rw-r--r-- | rs/java/android/renderscript/ScriptC.java | 4 | ||||
| -rw-r--r-- | rs/java/android/renderscript/ScriptGroup2.java | 208 | ||||
| -rw-r--r-- | rs/java/android/renderscript/ScriptIntrinsicBlur.java | 2 |
7 files changed, 308 insertions, 218 deletions
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java index 2b2e611..2203850 100644 --- a/rs/java/android/renderscript/Allocation.java +++ b/rs/java/android/renderscript/Allocation.java @@ -1340,15 +1340,22 @@ public class Allocation extends BaseObj { private void copyTo(Object array, Element.DataType dt, int arrayLen) { Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); - if (dt.mSize * arrayLen < mSize) { - throw new RSIllegalArgumentException( - "Size of output array cannot be smaller than size of allocation."); - } mRS.validate(); boolean usePadding = false; if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { usePadding = true; } + if (usePadding) { + if (dt.mSize * arrayLen < mSize / 4 * 3) { + throw new RSIllegalArgumentException( + "Size of output array cannot be smaller than size of allocation."); + } + } else { + if (dt.mSize * arrayLen < mSize) { + throw new RSIllegalArgumentException( + "Size of output array cannot be smaller than size of allocation."); + } + } mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding); Trace.traceEnd(RenderScript.TRACE_TAG); } diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java index 0f967fc..de1c497 100644 --- a/rs/java/android/renderscript/FieldPacker.java +++ b/rs/java/android/renderscript/FieldPacker.java @@ -47,6 +47,15 @@ public class FieldPacker { // subAlign() can never work correctly for copied FieldPacker objects. } + static FieldPacker createFromArray(Object[] args) { + FieldPacker fp = new FieldPacker(RenderScript.sPointerSize * 8); + for (Object arg : args) { + fp.addSafely(arg); + } + fp.resize(fp.mPos); + return fp; + } + public void align(int v) { if ((v <= 0) || ((v & (v - 1)) != 0)) { throw new RSIllegalArgumentException("argument must be a non-negative non-zero power of 2: " + v); @@ -618,294 +627,182 @@ public class FieldPacker { return mPos; } - private static void addToPack(FieldPacker fp, Object obj) { + private void add(Object obj) { if (obj instanceof Boolean) { - fp.addBoolean(((Boolean)obj).booleanValue()); + addBoolean((Boolean)obj); return; } if (obj instanceof Byte) { - fp.addI8(((Byte)obj).byteValue()); + addI8((Byte)obj); return; } if (obj instanceof Short) { - fp.addI16(((Short)obj).shortValue()); + addI16((Short)obj); return; } if (obj instanceof Integer) { - fp.addI32(((Integer)obj).intValue()); + addI32((Integer)obj); return; } if (obj instanceof Long) { - fp.addI64(((Long)obj).longValue()); + addI64((Long)obj); return; } if (obj instanceof Float) { - fp.addF32(((Float)obj).floatValue()); + addF32((Float)obj); return; } if (obj instanceof Double) { - fp.addF64(((Double)obj).doubleValue()); + addF64((Double)obj); return; } if (obj instanceof Byte2) { - fp.addI8((Byte2)obj); + addI8((Byte2)obj); return; } if (obj instanceof Byte3) { - fp.addI8((Byte3)obj); + addI8((Byte3)obj); return; } if (obj instanceof Byte4) { - fp.addI8((Byte4)obj); + addI8((Byte4)obj); return; } if (obj instanceof Short2) { - fp.addI16((Short2)obj); + addI16((Short2)obj); return; } if (obj instanceof Short3) { - fp.addI16((Short3)obj); + addI16((Short3)obj); return; } if (obj instanceof Short4) { - fp.addI16((Short4)obj); + addI16((Short4)obj); return; } if (obj instanceof Int2) { - fp.addI32((Int2)obj); + addI32((Int2)obj); return; } if (obj instanceof Int3) { - fp.addI32((Int3)obj); + addI32((Int3)obj); return; } if (obj instanceof Int4) { - fp.addI32((Int4)obj); + addI32((Int4)obj); return; } if (obj instanceof Long2) { - fp.addI64((Long2)obj); + addI64((Long2)obj); return; } if (obj instanceof Long3) { - fp.addI64((Long3)obj); + addI64((Long3)obj); return; } if (obj instanceof Long4) { - fp.addI64((Long4)obj); + addI64((Long4)obj); return; } if (obj instanceof Float2) { - fp.addF32((Float2)obj); + addF32((Float2)obj); return; } if (obj instanceof Float3) { - fp.addF32((Float3)obj); + addF32((Float3)obj); return; } if (obj instanceof Float4) { - fp.addF32((Float4)obj); + addF32((Float4)obj); return; } if (obj instanceof Double2) { - fp.addF64((Double2)obj); + addF64((Double2)obj); return; } if (obj instanceof Double3) { - fp.addF64((Double3)obj); + addF64((Double3)obj); return; } if (obj instanceof Double4) { - fp.addF64((Double4)obj); + addF64((Double4)obj); return; } if (obj instanceof Matrix2f) { - fp.addMatrix((Matrix2f)obj); + addMatrix((Matrix2f)obj); return; } if (obj instanceof Matrix3f) { - fp.addMatrix((Matrix3f)obj); + addMatrix((Matrix3f)obj); return; } if (obj instanceof Matrix4f) { - fp.addMatrix((Matrix4f)obj); + addMatrix((Matrix4f)obj); return; } if (obj instanceof BaseObj) { - fp.addObj((BaseObj)obj); + addObj((BaseObj)obj); return; } } - private static int getPackedSize(Object obj) { - if (obj instanceof Boolean) { - return 1; - } - - if (obj instanceof Byte) { - return 1; - } - - if (obj instanceof Short) { - return 2; - } - - if (obj instanceof Integer) { - return 4; - } - - if (obj instanceof Long) { - return 8; - } - - if (obj instanceof Float) { - return 4; - } - - if (obj instanceof Double) { - return 8; - } - - if (obj instanceof Byte2) { - return 2; - } - - if (obj instanceof Byte3) { - return 3; - } - - if (obj instanceof Byte4) { - return 4; - } - - if (obj instanceof Short2) { - return 4; - } - - if (obj instanceof Short3) { - return 6; - } - - if (obj instanceof Short4) { - return 8; - } - - if (obj instanceof Int2) { - return 8; - } - - if (obj instanceof Int3) { - return 12; - } - - if (obj instanceof Int4) { - return 16; - } - - if (obj instanceof Long2) { - return 16; - } - - if (obj instanceof Long3) { - return 24; - } - - if (obj instanceof Long4) { - return 32; - } - - if (obj instanceof Float2) { - return 8; - } - - if (obj instanceof Float3) { - return 12; + private boolean resize(int newSize) { + if (newSize == mLen) { + return false; } - if (obj instanceof Float4) { - return 16; - } - - if (obj instanceof Double2) { - return 16; - } - - if (obj instanceof Double3) { - return 24; - } - - if (obj instanceof Double4) { - return 32; - } - - if (obj instanceof Matrix2f) { - return 16; - } - - if (obj instanceof Matrix3f) { - return 36; - } - - if (obj instanceof Matrix4f) { - return 64; - } - - if (obj instanceof BaseObj) { - if (RenderScript.sPointerSize == 8) { - return 32; - } else { - return 4; - } - } - - return 0; + byte[] newData = new byte[newSize]; + System.arraycopy(mData, 0, newData, 0, mPos); + mData = newData; + mLen = newSize; + return true; } - static FieldPacker createFieldPack(Object[] args) { - int len = 0; - for (Object arg : args) { - len += getPackedSize(arg); - } - FieldPacker fp = new FieldPacker(len); - for (Object arg : args) { - addToPack(fp, arg); - } - return fp; + private void addSafely(Object obj) { + boolean retry; + final int oldPos = mPos; + do { + retry = false; + try { + add(obj); + } catch (ArrayIndexOutOfBoundsException e) { + mPos = oldPos; + resize(mLen * 2); + retry = true; + } + } while (retry); } - private final byte mData[]; + private byte mData[]; private int mPos; private int mLen; private BitSet mAlignment; - } - - diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java index 7ef17a7..5fc1f93 100644 --- a/rs/java/android/renderscript/RenderScript.java +++ b/rs/java/android/renderscript/RenderScript.java @@ -129,8 +129,6 @@ public class RenderScript { native void nContextInitToClient(long con); native void nContextDeinitToClient(long con); - static File mCacheDir; - // this should be a monotonically increasing ID // used in conjunction with the API version of a device static final long sMinorID = 1; @@ -146,23 +144,6 @@ public class RenderScript { return sMinorID; } - /** - * Sets the directory to use as a persistent storage for the - * renderscript object file cache. - * - * @hide - * @param cacheDir A directory the current process can write to - */ - public static void setupDiskCache(File cacheDir) { - if (!sInitialized) { - Log.e(LOG_TAG, "RenderScript.setupDiskCache() called when disabled"); - return; - } - - // Defer creation of cache path to nScriptCCreate(). - mCacheDir = cacheDir; - } - /** * ContextType specifies the specific type of context to be created. * @@ -251,6 +232,11 @@ public class RenderScript { validate(); rsnContextSetPriority(mContext, p); } + native void rsnContextSetCacheDir(long con, String cacheDir); + synchronized void nContextSetCacheDir(String cacheDir) { + validate(); + rsnContextSetCacheDir(mContext, cacheDir); + } native void rsnContextDump(long con, int bits); synchronized void nContextDump(int bits) { validate(); @@ -1345,6 +1331,14 @@ public class RenderScript { if (rs.mContext == 0) { throw new RSDriverException("Failed to create RS context."); } + + // set up cache directory for entire context + final String CACHE_PATH = "com.android.renderscript.cache"; + File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH); + String mCachePath = f.getAbsolutePath(); + f.mkdirs(); + rs.nContextSetCacheDir(mCachePath); + rs.mMessageThread = new MessageThread(rs); rs.mMessageThread.start(); return rs; diff --git a/rs/java/android/renderscript/RenderScriptCacheDir.java b/rs/java/android/renderscript/RenderScriptCacheDir.java new file mode 100644 index 0000000..95a9d75 --- /dev/null +++ b/rs/java/android/renderscript/RenderScriptCacheDir.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008-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 java.io.File; + +/** + * Used only for tracking the RenderScript cache directory. + * @hide + */ +public class RenderScriptCacheDir { + /** + * Sets the directory to use as a persistent storage for the + * renderscript object file cache. + * + * @hide + * @param cacheDir A directory the current process can write to + */ + public static void setupDiskCache(File cacheDir) { + // Defer creation of cache path to nScriptCCreate(). + mCacheDir = cacheDir; + } + + static File mCacheDir; + +} diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java index 64d21e4..bf706c1 100644 --- a/rs/java/android/renderscript/ScriptC.java +++ b/rs/java/android/renderscript/ScriptC.java @@ -124,7 +124,7 @@ public class ScriptC extends Script { // Create the RS cache path if we haven't done so already. if (mCachePath == null) { - File f = new File(rs.mCacheDir, CACHE_PATH); + File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH); mCachePath = f.getAbsolutePath(); f.mkdirs(); } @@ -135,7 +135,7 @@ public class ScriptC extends Script { private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) { // Create the RS cache path if we haven't done so already. if (mCachePath == null) { - File f = new File(rs.mCacheDir, CACHE_PATH); + File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH); mCachePath = f.getAbsolutePath(); f.mkdirs(); } diff --git a/rs/java/android/renderscript/ScriptGroup2.java b/rs/java/android/renderscript/ScriptGroup2.java index 4a56572..858a957 100644 --- a/rs/java/android/renderscript/ScriptGroup2.java +++ b/rs/java/android/renderscript/ScriptGroup2.java @@ -24,26 +24,41 @@ 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. + */ -****************************** -You have tried to change the API from what has been previously approved. - -To make these errors go away, you have two choices: -1) You can add "@hide" javadoc comments to the methods, etc. listed in the -errors above. - -2) You can update current.txt by executing the following command: -make update-api - -To submit the revised current.txt to the main Android repository, -you will need approval. -****************************** - -@hide Pending Android public API approval. -*/ 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; @@ -62,8 +77,9 @@ public class ScriptGroup2 extends BaseObj { Object[] args, Map<Script.FieldID, Object> globals) { super(0, rs); + mArgs = args; mReturnValue = Allocation.createTyped(rs, returnType); - mBindings = new HashMap<Script.FieldID, Object>(); + mBindings = globals; mGlobalFuture = new HashMap<Script.FieldID, Future>(); int numValues = args.length + globals.size(); @@ -110,9 +126,10 @@ public class ScriptGroup2 extends BaseObj { public Closure(RenderScript rs, Script.InvokeID invokeID, Object[] args, Map<Script.FieldID, Object> globals) { super(0, rs); - mFP = FieldPacker.createFieldPack(args); + mFP = FieldPacker.createFromArray(args); - mBindings = new HashMap<Script.FieldID, Object>(); + mArgs = args; + mBindings = globals; mGlobalFuture = new HashMap<Script.FieldID, Future>(); int numValues = globals.size(); @@ -132,7 +149,6 @@ public class ScriptGroup2 extends BaseObj { UnboundValue unbound = (UnboundValue)obj; unbound.addReference(this, fieldID); } else { - // TODO(yangni): Verify obj not a future. retrieveValueAndDependenceInfo(rs, i, obj, values, sizes, depClosures, depFieldIDs); } @@ -174,6 +190,12 @@ public class ScriptGroup2 extends BaseObj { 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); @@ -182,6 +204,13 @@ public class ScriptGroup2 extends BaseObj { 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); @@ -198,11 +227,13 @@ public class ScriptGroup2 extends BaseObj { } 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); } @@ -234,6 +265,10 @@ public class ScriptGroup2 extends BaseObj { } } + /** + * An opaque class for futures + */ + public static class Future { Closure mClosure; Script.FieldID mFieldID; @@ -250,6 +285,10 @@ public class ScriptGroup2 extends BaseObj { 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; @@ -309,6 +348,13 @@ public class ScriptGroup2 extends BaseObj { 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, " + @@ -343,32 +389,95 @@ public class ScriptGroup2 extends BaseObj { } /** - @hide Pending Android public API approval. - */ + * 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 { - public Script.FieldID mField; - public Object mValue; + 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; } } /** - @hide Pending Android public API approval. - */ + * 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); @@ -376,6 +485,15 @@ public class ScriptGroup2 extends BaseObj { 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); @@ -383,12 +501,25 @@ public class ScriptGroup2 extends BaseObj { 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>(); @@ -398,6 +529,14 @@ public class ScriptGroup2 extends BaseObj { 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>(); @@ -407,7 +546,20 @@ public class ScriptGroup2 extends BaseObj { return addInvoke(invoke, args.toArray(), bindingMap); } - public ScriptGroup2 create(Future... outputs) { + /** + * 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, mClosures, mInputs, outputs); return ret; } @@ -428,7 +580,7 @@ public class ScriptGroup2 extends BaseObj { return false; } Binding b = (Binding)argsAndBindings[i]; - bindingMap.put(b.mField, b.mValue); + bindingMap.put(b.getField(), b.getValue()); } return true; diff --git a/rs/java/android/renderscript/ScriptIntrinsicBlur.java b/rs/java/android/renderscript/ScriptIntrinsicBlur.java index 5c4edd3..60e2b6d 100644 --- a/rs/java/android/renderscript/ScriptIntrinsicBlur.java +++ b/rs/java/android/renderscript/ScriptIntrinsicBlur.java @@ -34,7 +34,7 @@ public final class ScriptIntrinsicBlur extends ScriptIntrinsic { * Create an intrinsic for applying a blur to an allocation. The * default radius is 5.0. * - * Supported elements types are {@link Element#U8_4} + * Supported elements types are {@link Element#U8_4 Element#U8} * * @param rs The RenderScript context * @param e Element type for inputs and outputs |
