blob: 791ab147e6906ca87c81768953e2f71b9bebf6f2 [file] [log] [blame]
Jason Samsdbe66d62012-09-17 13:54:41 -07001/*
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
Yang Ni1ffd86b2015-01-07 09:16:40 -080017#include "rsScriptGroup.h"
Chris Wailes93d6bc82014-07-28 16:54:38 -070018
Jason Samsdbe66d62012-09-17 13:54:41 -070019#include "rsContext.h"
Yang Ni1ffd86b2015-01-07 09:16:40 -080020#include "rsScriptGroup2.h"
21
22#include <algorithm>
Jason Samsdbe66d62012-09-17 13:54:41 -070023#include <time.h>
24
25using namespace android;
26using namespace android::renderscript;
27
Yang Ni1ffd86b2015-01-07 09:16:40 -080028ScriptGroup::ScriptGroup(Context *rsc) : ScriptGroupBase(rsc) {
Jason Samsdbe66d62012-09-17 13:54:41 -070029}
30
31ScriptGroup::~ScriptGroup() {
32 if (mRSC->mHal.funcs.scriptgroup.destroy) {
33 mRSC->mHal.funcs.scriptgroup.destroy(mRSC, this);
34 }
35
Chris Wailes93d6bc82014-07-28 16:54:38 -070036 for (auto link : mLinks) {
37 delete link;
Jason Samsdbe66d62012-09-17 13:54:41 -070038 }
39}
40
41ScriptGroup::IO::IO(const ScriptKernelID *kid) {
42 mKernel = kid;
43}
44
45ScriptGroup::Node::Node(Script *s) {
46 mScript = s;
47 mSeen = false;
48 mOrder = 0;
49}
50
51ScriptGroup::Node * ScriptGroup::findNode(Script *s) const {
Chris Wailes93d6bc82014-07-28 16:54:38 -070052 for (auto node : mNodes) {
53 for (auto kernelRef : node->mKernels) {
54 if (kernelRef->mScript == s) {
55 return node;
Jason Samsdbe66d62012-09-17 13:54:41 -070056 }
57 }
58 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070059
Chris Wailes44bef6f2014-08-12 13:51:10 -070060 return nullptr;
Jason Samsdbe66d62012-09-17 13:54:41 -070061}
62
Chris Wailes93d6bc82014-07-28 16:54:38 -070063bool ScriptGroup::calcOrderRecurse(Node *node0, int depth) {
64 node0->mSeen = true;
65 if (node0->mOrder < depth) {
66 node0->mOrder = depth;
Jason Samsdbe66d62012-09-17 13:54:41 -070067 }
68 bool ret = true;
Chris Wailes93d6bc82014-07-28 16:54:38 -070069
70 for (auto link : node0->mOutputs) {
Chris Wailes44bef6f2014-08-12 13:51:10 -070071 Node *node1 = nullptr;
Chris Wailes93d6bc82014-07-28 16:54:38 -070072 if (link->mDstField.get()) {
73 node1 = findNode(link->mDstField->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -070074 } else {
Chris Wailes93d6bc82014-07-28 16:54:38 -070075 node1 = findNode(link->mDstKernel->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -070076 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070077 if (node1->mSeen) {
Jason Samsdbe66d62012-09-17 13:54:41 -070078 return false;
79 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070080 ret &= calcOrderRecurse(node1, node0->mOrder + 1);
Jason Samsdbe66d62012-09-17 13:54:41 -070081 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070082
Jason Samsdbe66d62012-09-17 13:54:41 -070083 return ret;
84}
85
Jason Samsdbe66d62012-09-17 13:54:41 -070086bool ScriptGroup::calcOrder() {
87 // Make nodes
Chris Wailes93d6bc82014-07-28 16:54:38 -070088
89 for (auto kernelRef : mKernels) {
90 const ScriptKernelID *kernel = kernelRef.get();
91 Node *node = findNode(kernel->mScript);
Chris Wailes44bef6f2014-08-12 13:51:10 -070092 if (node == nullptr) {
Chris Wailes93d6bc82014-07-28 16:54:38 -070093 node = new Node(kernel->mScript);
94 mNodes.push_back(node);
Jason Samsdbe66d62012-09-17 13:54:41 -070095 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070096 node->mKernels.push_back(kernel);
Jason Samsdbe66d62012-09-17 13:54:41 -070097 }
98
99 // add links
Chris Wailes93d6bc82014-07-28 16:54:38 -0700100 for (auto link : mLinks) {
101 Node *node = findNode(link->mSource->mScript);
102 node->mOutputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700103
Chris Wailes93d6bc82014-07-28 16:54:38 -0700104 if (link->mDstKernel.get()) {
105 node = findNode(link->mDstKernel->mScript);
106 node->mInputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700107 } else {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700108 node = findNode(link->mDstField->mScript);
109 node->mInputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700110 }
111 }
112
Jason Samsdbe66d62012-09-17 13:54:41 -0700113 // Order nodes
114 bool ret = true;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700115 for (auto n0 : mNodes) {
116 if (n0->mInputs.size() == 0) {
117 for (auto n1 : mNodes) {
118 n1->mSeen = false;
Jason Samsdbe66d62012-09-17 13:54:41 -0700119 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700120 ret &= calcOrderRecurse(n0, 1);
Jason Samsdbe66d62012-09-17 13:54:41 -0700121 }
122 }
123
Chris Wailes93d6bc82014-07-28 16:54:38 -0700124 for (auto kernelRef : mKernels) {
125 const ScriptKernelID *kernel = kernelRef.get();
126 const Node *node = findNode(kernel->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -0700127
Chris Wailes93d6bc82014-07-28 16:54:38 -0700128 if (kernel->mHasKernelOutput) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700129 bool found = false;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700130 for (auto output : node->mOutputs) {
131 if (output->mSource.get() == kernel) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700132 found = true;
133 break;
134 }
135 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700136
Jason Samsdbe66d62012-09-17 13:54:41 -0700137 if (!found) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700138 mOutputs.push_back(new IO(kernel));
Jason Samsdbe66d62012-09-17 13:54:41 -0700139 }
140 }
141
Chris Wailes93d6bc82014-07-28 16:54:38 -0700142 if (kernel->mHasKernelInput) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700143 bool found = false;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700144 for (auto input : node->mInputs) {
145 if (input->mDstKernel.get() == kernel) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700146 found = true;
147 break;
148 }
149 }
150 if (!found) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700151 mInputs.push_back(new IO(kernel));
Jason Samsdbe66d62012-09-17 13:54:41 -0700152 }
153 }
154 }
155
156 // sort
Chris Wailes93d6bc82014-07-28 16:54:38 -0700157 std::stable_sort(mNodes.begin(), mNodes.end(),
158 [](const ScriptGroup::Node* lhs,
159 const ScriptGroup::Node* rhs) {
160 return lhs->mOrder < rhs->mOrder;
161 });
Jason Samsdbe66d62012-09-17 13:54:41 -0700162
163 return ret;
164}
165
166ScriptGroup * ScriptGroup::create(Context *rsc,
167 ScriptKernelID ** kernels, size_t kernelsSize,
168 ScriptKernelID ** src, size_t srcSize,
169 ScriptKernelID ** dstK, size_t dstKSize,
170 ScriptFieldID ** dstF, size_t dstFSize,
171 const Type ** type, size_t typeSize) {
172
173 size_t kernelCount = kernelsSize / sizeof(ScriptKernelID *);
174 size_t linkCount = typeSize / sizeof(Type *);
175
176 //ALOGE("ScriptGroup::create kernels=%i links=%i", (int)kernelCount, (int)linkCount);
177
178
179 // Start by counting unique kernel sources
180
181 ScriptGroup *sg = new ScriptGroup(rsc);
182
183 sg->mKernels.reserve(kernelCount);
184 for (size_t ct=0; ct < kernelCount; ct++) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700185 sg->mKernels.push_back(kernels[ct]);
Jason Samsdbe66d62012-09-17 13:54:41 -0700186 }
187
188 sg->mLinks.reserve(linkCount);
189 for (size_t ct=0; ct < linkCount; ct++) {
190 Link *l = new Link();
191 l->mType = type[ct];
192 l->mSource = src[ct];
193 l->mDstField = dstF[ct];
194 l->mDstKernel = dstK[ct];
Chris Wailes93d6bc82014-07-28 16:54:38 -0700195 sg->mLinks.push_back(l);
Jason Samsdbe66d62012-09-17 13:54:41 -0700196 }
197
198 sg->calcOrder();
199
200 // allocate links
201 for (size_t ct=0; ct < sg->mNodes.size(); ct++) {
202 const Node *n = sg->mNodes[ct];
203 for (size_t ct2=0; ct2 < n->mOutputs.size(); ct2++) {
204 Link *l = n->mOutputs[ct2];
205 if (l->mAlloc.get()) {
206 continue;
207 }
208 const ScriptKernelID *k = l->mSource.get();
209
210 Allocation * alloc = Allocation::createAllocation(rsc,
211 l->mType.get(), RS_ALLOCATION_USAGE_SCRIPT);
212 l->mAlloc = alloc;
213
214 for (size_t ct3=ct2+1; ct3 < n->mOutputs.size(); ct3++) {
215 if (n->mOutputs[ct3]->mSource.get() == l->mSource.get()) {
216 n->mOutputs[ct3]->mAlloc = alloc;
217 }
218 }
219 }
220 }
221
222 if (rsc->mHal.funcs.scriptgroup.init) {
223 rsc->mHal.funcs.scriptgroup.init(rsc, sg);
224 }
Stephen Hines61c86952013-04-09 17:34:43 -0700225 sg->incUserRef();
Jason Samsdbe66d62012-09-17 13:54:41 -0700226 return sg;
227}
228
229void ScriptGroup::setInput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700230 for (auto input : mInputs) {
231 if (input->mKernel == kid) {
232 input->mAlloc = a;
Jason Samsdbe66d62012-09-17 13:54:41 -0700233
234 if (rsc->mHal.funcs.scriptgroup.setInput) {
235 rsc->mHal.funcs.scriptgroup.setInput(rsc, this, kid, a);
236 }
237 return;
238 }
239 }
240 rsAssert(!"ScriptGroup:setInput kid not found");
241}
242
243void ScriptGroup::setOutput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700244 for (auto output : mOutputs) {
245 if (output->mKernel == kid) {
246 output->mAlloc = a;
Jason Samsdbe66d62012-09-17 13:54:41 -0700247
248 if (rsc->mHal.funcs.scriptgroup.setOutput) {
249 rsc->mHal.funcs.scriptgroup.setOutput(rsc, this, kid, a);
250 }
251 return;
252 }
253 }
254 rsAssert(!"ScriptGroup:setOutput kid not found");
255}
256
Yang Ni5f6f16f2014-07-25 13:51:09 -0700257bool ScriptGroup::validateInputAndOutput(Context *rsc) {
258 for(size_t i = 0; i < mInputs.size(); i++) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700259 if (mInputs[i]->mAlloc.get() == nullptr) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700260 rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing input.");
261 return false;
262 }
263 }
264
265 for(size_t i = 0; i < mOutputs.size(); i++) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700266 if (mOutputs[i]->mAlloc.get() == nullptr) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700267 rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing output.");
268 return false;
269 }
270 }
271
272 return true;
273}
274
Jason Samsdbe66d62012-09-17 13:54:41 -0700275void ScriptGroup::execute(Context *rsc) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700276 if (!validateInputAndOutput(rsc)) {
277 return;
278 }
279
Jason Samsdbe66d62012-09-17 13:54:41 -0700280 if (rsc->mHal.funcs.scriptgroup.execute) {
281 rsc->mHal.funcs.scriptgroup.execute(rsc, this);
282 return;
283 }
284
Chris Wailes93d6bc82014-07-28 16:54:38 -0700285 for (auto node : mNodes) {
286 for (auto kernel : node->mKernels) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700287 Allocation *ain = nullptr;
288 Allocation *aout = nullptr;
Jason Samsdbe66d62012-09-17 13:54:41 -0700289
Chris Wailes93d6bc82014-07-28 16:54:38 -0700290 for (auto nodeInput : node->mInputs) {
291 if (nodeInput->mDstKernel.get() == kernel) {
292 ain = nodeInput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700293 }
294 }
295
Chris Wailes93d6bc82014-07-28 16:54:38 -0700296 for (auto sgInput : mInputs) {
297 if (sgInput->mKernel == kernel) {
298 ain = sgInput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700299 }
300 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700301
302 for (auto nodeOutput : node->mOutputs) {
303 if (nodeOutput->mDstKernel.get() == kernel) {
304 aout = nodeOutput->mAlloc.get();
305 }
306 }
307
308 for (auto sgOutput : mOutputs) {
309 if (sgOutput->mKernel == kernel) {
310 aout = sgOutput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700311 }
312 }
313
Chris Wailes44bef6f2014-08-12 13:51:10 -0700314 if (ain == nullptr) {
315 node->mScript->runForEach(rsc, kernel->mSlot, nullptr, 0, aout,
316 nullptr, 0);
Chris Wailesf3712132014-07-16 15:18:30 -0700317 } else {
318 const Allocation *ains[1] = {ain};
Chris Wailes93d6bc82014-07-28 16:54:38 -0700319 node->mScript->runForEach(rsc, kernel->mSlot, ains,
320 sizeof(ains) / sizeof(RsAllocation),
Chris Wailes44bef6f2014-08-12 13:51:10 -0700321 aout, nullptr, 0);
Chris Wailesf3712132014-07-16 15:18:30 -0700322 }
Jason Samsdbe66d62012-09-17 13:54:41 -0700323 }
Jason Samsdbe66d62012-09-17 13:54:41 -0700324 }
325
326}
327
Jason Samsdbe66d62012-09-17 13:54:41 -0700328ScriptGroup::Link::Link() {
329}
330
331ScriptGroup::Link::~Link() {
332}
333
334namespace android {
335namespace renderscript {
336
337
338RsScriptGroup rsi_ScriptGroupCreate(Context *rsc,
339 RsScriptKernelID * kernels, size_t kernelsSize,
340 RsScriptKernelID * src, size_t srcSize,
341 RsScriptKernelID * dstK, size_t dstKSize,
342 RsScriptFieldID * dstF, size_t dstFSize,
343 const RsType * type, size_t typeSize) {
344
345
346 return ScriptGroup::create(rsc,
347 (ScriptKernelID **) kernels, kernelsSize,
348 (ScriptKernelID **) src, srcSize,
349 (ScriptKernelID **) dstK, dstKSize,
350 (ScriptFieldID **) dstF, dstFSize,
351 (const Type **) type, typeSize);
352}
353
354
355void rsi_ScriptGroupSetInput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
356 RsAllocation alloc) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700357 ScriptGroup *s = (ScriptGroup *)sg;
358 s->setInput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
359}
360
361void rsi_ScriptGroupSetOutput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
362 RsAllocation alloc) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700363 ScriptGroup *s = (ScriptGroup *)sg;
364 s->setOutput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
365}
366
367void rsi_ScriptGroupExecute(Context *rsc, RsScriptGroup sg) {
Yang Ni1ffd86b2015-01-07 09:16:40 -0800368 ScriptGroupBase *s = (ScriptGroupBase *)sg;
Jason Samsdbe66d62012-09-17 13:54:41 -0700369 s->execute(rsc);
370}
371
372}
373}