Skip to content

Commit 423ebcb

Browse files
author
Jason Sams
committed
Implement ScriptGroup and add test.
Change-Id: I6ce0479c20f425d501c759c15717aa8b418c3f5f
1 parent 6cc7a92 commit 423ebcb

File tree

5 files changed

+604
-1
lines changed

5 files changed

+604
-1
lines changed
Lines changed: 391 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package android.renderscript;
18+
19+
import java.lang.reflect.Method;
20+
21+
/**
22+
* @hide
23+
**/
24+
public class ScriptGroup extends BaseObj {
25+
Node mNodes[];
26+
Connection mConnections[];
27+
Node mFirstNode;
28+
IO mOutputs[];
29+
IO mInputs[];
30+
31+
static class IO {
32+
Script mScript;
33+
Allocation mAllocation;
34+
String mName;
35+
36+
IO(Script s) {
37+
mScript = s;
38+
}
39+
IO(Script s, String n) {
40+
mScript = s;
41+
mName = n;
42+
}
43+
}
44+
45+
static class Connection {
46+
Node mTo[];
47+
String mToName[];
48+
Node mFrom;
49+
Type mAllocationType;
50+
Allocation mInternalAllocation;
51+
52+
Connection(Node out, Type t) {
53+
mFrom = out;
54+
mAllocationType = t;
55+
}
56+
57+
void addTo(Node n, String name) {
58+
if (mTo == null) {
59+
mTo = new Node[1];
60+
mToName = new String[1];
61+
} else {
62+
Node nt[] = new Node[mTo.length + 1];
63+
String ns[] = new String[mTo.length + 1];
64+
System.arraycopy(mTo, 0, nt, 0, mTo.length);
65+
System.arraycopy(mToName, 0, ns, 0, mTo.length);
66+
mTo = nt;
67+
mToName = ns;
68+
}
69+
mTo[mTo.length - 1] = n;
70+
mToName[mTo.length - 1] = name;
71+
}
72+
}
73+
74+
static class Node {
75+
Script mScript;
76+
Connection mInput[] = new Connection[8];
77+
Connection mOutput[] = new Connection[1];
78+
int mInputCount;
79+
int mOutputCount;
80+
int mDepth;
81+
boolean mSeen;
82+
83+
Node mNext;
84+
85+
Node(Script s) {
86+
mScript = s;
87+
}
88+
89+
void addInput(Connection c) {
90+
if (mInput.length <= mInputCount) {
91+
Connection[] nc = new Connection[mInput.length + 8];
92+
System.arraycopy(mInput, 0, nc, 0, mInputCount);
93+
mInput = nc;
94+
}
95+
mInput[mInputCount++] = c;
96+
}
97+
98+
void addOutput(Connection c) {
99+
if (mOutput.length <= mOutputCount) {
100+
Connection[] nc = new Connection[mOutput.length + 8];
101+
System.arraycopy(mOutput, 0, nc, 0, mOutputCount);
102+
mOutput = nc;
103+
}
104+
mOutput[mOutputCount++] = c;
105+
}
106+
}
107+
108+
109+
ScriptGroup(int id, RenderScript rs) {
110+
super(id, rs);
111+
}
112+
113+
void init(int nodeCount, int connectionCount) {
114+
mNodes = new Node[nodeCount];
115+
mConnections = new Connection[connectionCount];
116+
117+
android.util.Log.v("RSR", "init" + nodeCount + ", " + connectionCount);
118+
119+
// Count outputs and create array.
120+
Node n = mFirstNode;
121+
int outputCount = 0;
122+
int inputCount = 0;
123+
int connectionIndex = 0;
124+
int nodeNum = 0;
125+
while (n != null) {
126+
mNodes[nodeNum++] = n;
127+
128+
// Look for unattached kernel inputs
129+
boolean hasInput = false;
130+
for (int ct=0; ct < n.mInput.length; ct++) {
131+
if (n.mInput[ct] != null) {
132+
if (n.mInput[ct].mToName == null) {
133+
hasInput = true;
134+
}
135+
}
136+
}
137+
if (!hasInput) {
138+
if (mInputs == null) {
139+
mInputs = new IO[1];
140+
}
141+
if (mInputs.length <= inputCount) {
142+
IO t[] = new IO[mInputs.length + 1];
143+
System.arraycopy(mInputs, 0, t, 0, mInputs.length);
144+
mInputs = t;
145+
}
146+
mInputs[inputCount++] = new IO(n.mScript);
147+
}
148+
149+
// Look for unattached kernel outputs
150+
boolean hasOutput = false;
151+
for (int ct=0; ct < n.mOutput.length; ct++) {
152+
if (n.mOutput[ct] != null) {
153+
hasOutput = true;
154+
}
155+
}
156+
if (!hasOutput) {
157+
if (mOutputs == null) {
158+
mOutputs = new IO[1];
159+
}
160+
if (mOutputs.length <= outputCount) {
161+
IO t[] = new IO[mOutputs.length + 1];
162+
System.arraycopy(mOutputs, 0, t, 0, mOutputs.length);
163+
mOutputs = t;
164+
}
165+
mOutputs[outputCount++] = new IO(n.mScript);
166+
}
167+
168+
// Make allocations for internal connections
169+
// Since script outputs are unique, use those to avoid duplicates.
170+
for (int ct=0; ct < n.mOutput.length; ct++) {
171+
android.util.Log.v("RSR", "init out2 " + n.mOutput[ct]);
172+
if (n.mOutput[ct] != null) {
173+
Connection t = n.mOutput[ct];
174+
mConnections[connectionIndex++] = t;
175+
t.mInternalAllocation = Allocation.createTyped(mRS, t.mAllocationType);
176+
}
177+
}
178+
179+
n = n.mNext;
180+
}
181+
}
182+
183+
public void setInput(Script s, Allocation a) {
184+
for (int ct=0; ct < mInputs.length; ct++) {
185+
if (mInputs[ct].mScript == s) {
186+
mInputs[ct].mAllocation = a;
187+
return;
188+
}
189+
}
190+
throw new RSIllegalArgumentException("Script not found");
191+
}
192+
193+
public void setOutput(Script s, Allocation a) {
194+
for (int ct=0; ct < mOutputs.length; ct++) {
195+
if (mOutputs[ct].mScript == s) {
196+
mOutputs[ct].mAllocation = a;
197+
return;
198+
}
199+
}
200+
throw new RSIllegalArgumentException("Script not found");
201+
}
202+
203+
public void execute() {
204+
android.util.Log.v("RSR", "execute");
205+
boolean more = true;
206+
int depth = 0;
207+
while (more) {
208+
more = false;
209+
for (int ct=0; ct < mNodes.length; ct++) {
210+
if (mNodes[ct].mDepth == depth) {
211+
more = true;
212+
213+
Allocation kernelIn = null;
214+
for (int ct2=0; ct2 < mNodes[ct].mInputCount; ct2++) {
215+
android.util.Log.v("RSR", " kin " + ct2 + ", to " + mNodes[ct].mInput[ct2].mTo[0] + ", name " + mNodes[ct].mInput[ct2].mToName[0]);
216+
if (mNodes[ct].mInput[ct2].mToName[0] == null) {
217+
kernelIn = mNodes[ct].mInput[ct2].mInternalAllocation;
218+
break;
219+
}
220+
}
221+
222+
Allocation kernelOut= null;
223+
for (int ct2=0; ct2 < mNodes[ct].mOutputCount; ct2++) {
224+
android.util.Log.v("RSR", " kout " + ct2 + ", from " + mNodes[ct].mOutput[ct2].mFrom);
225+
if (mNodes[ct].mOutput[ct2].mFrom != null) {
226+
kernelOut = mNodes[ct].mOutput[ct2].mInternalAllocation;
227+
break;
228+
}
229+
}
230+
if (kernelOut == null) {
231+
for (int ct2=0; ct2 < mOutputs.length; ct2++) {
232+
if (mOutputs[ct2].mScript == mNodes[ct].mScript) {
233+
kernelOut = mOutputs[ct2].mAllocation;
234+
break;
235+
}
236+
}
237+
}
238+
239+
android.util.Log.v("RSR", "execute calling " + mNodes[ct] + ", with " + kernelIn);
240+
if (kernelIn != null) {
241+
try {
242+
243+
Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
244+
new Class[] { Allocation.class, Allocation.class });
245+
m.invoke(mNodes[ct].mScript, new Object[] {kernelIn, kernelOut} );
246+
} catch (Throwable t) {
247+
android.util.Log.e("RSR", "execute error " + t);
248+
}
249+
} else {
250+
try {
251+
Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
252+
new Class[] { Allocation.class });
253+
m.invoke(mNodes[ct].mScript, new Object[] {kernelOut} );
254+
} catch (Throwable t) {
255+
android.util.Log.e("RSR", "execute error " + t);
256+
}
257+
}
258+
259+
}
260+
}
261+
depth ++;
262+
}
263+
264+
}
265+
266+
267+
public static class Builder {
268+
RenderScript mRS;
269+
Node mFirstNode;
270+
int mConnectionCount = 0;
271+
int mNodeCount = 0;
272+
273+
public Builder(RenderScript rs) {
274+
mRS = rs;
275+
}
276+
277+
private void validateRecurse(Node n, int depth) {
278+
n.mSeen = true;
279+
if (depth > n.mDepth) {
280+
n.mDepth = depth;
281+
}
282+
283+
android.util.Log.v("RSR", " validateRecurse outputCount " + n.mOutputCount);
284+
for (int ct=0; ct < n.mOutputCount; ct++) {
285+
for (int ct2=0; ct2 < n.mOutput[ct].mTo.length; ct2++) {
286+
if (n.mOutput[ct].mTo[ct2].mSeen) {
287+
throw new RSInvalidStateException("Loops in group not allowed.");
288+
}
289+
validateRecurse(n.mOutput[ct].mTo[ct2], depth + 1);
290+
}
291+
}
292+
}
293+
294+
private void validate() {
295+
android.util.Log.v("RSR", "validate");
296+
Node n = mFirstNode;
297+
while (n != null) {
298+
n.mSeen = false;
299+
n.mDepth = 0;
300+
n = n.mNext;
301+
}
302+
303+
n = mFirstNode;
304+
while (n != null) {
305+
android.util.Log.v("RSR", "validate n= " + n);
306+
if ((n.mSeen == false) && (n.mInputCount == 0)) {
307+
android.util.Log.v("RSR", " recursing " + n);
308+
validateRecurse(n, 0);
309+
}
310+
n = n.mNext;
311+
}
312+
}
313+
314+
private Node findScript(Script s) {
315+
Node n = mFirstNode;
316+
while (n != null) {
317+
if (n.mScript == s) {
318+
return n;
319+
}
320+
n = n.mNext;
321+
}
322+
return null;
323+
}
324+
325+
private void addNode(Node n) {
326+
n.mNext = mFirstNode;
327+
mFirstNode = n;
328+
}
329+
330+
public Builder addConnection(Type t, Script output, Script input, String inputName) {
331+
android.util.Log.v("RSR", "addConnection " + t +", " + output + ", " + input);
332+
333+
// Look for existing output
334+
Node nout = findScript(output);
335+
Connection c;
336+
if (nout == null) {
337+
// Make new node
338+
android.util.Log.v("RSR", "addConnection new output node");
339+
nout = new Node(output);
340+
mNodeCount++;
341+
c = new Connection(nout, t);
342+
mConnectionCount++;
343+
nout.addOutput(c);
344+
addNode(nout);
345+
} else {
346+
// Add to existing node
347+
android.util.Log.v("RSR", "addConnection reuse output node");
348+
if (nout.mOutput[0] != null) {
349+
if (nout.mOutput[0].mFrom.mScript != output) {
350+
throw new RSInvalidStateException("Changed output of existing node");
351+
}
352+
if (nout.mOutput[0].mAllocationType != t) {
353+
throw new RSInvalidStateException("Changed output type of existing node");
354+
}
355+
}
356+
c = nout.mOutput[0];
357+
}
358+
// At this point we should have a connection attached to a script ouput.
359+
360+
// Find input
361+
Node nin = findScript(input);
362+
if (nin == null) {
363+
android.util.Log.v("RSR", "addConnection new input node");
364+
nin = new Node(input);
365+
mNodeCount++;
366+
addNode(nin);
367+
}
368+
c.addTo(nin, inputName);
369+
nin.addInput(c);
370+
371+
validate();
372+
return this;
373+
}
374+
375+
public ScriptGroup create() {
376+
ScriptGroup sg = new ScriptGroup(0, mRS);
377+
sg.mFirstNode = mFirstNode;
378+
mFirstNode = null;
379+
380+
android.util.Log.v("RSR", "create nodes= " + mNodeCount + ", Connections= " + mConnectionCount);
381+
382+
sg.init(mNodeCount, mConnectionCount);
383+
return sg;
384+
}
385+
386+
}
387+
388+
389+
}
390+
391+

0 commit comments

Comments
 (0)