blob: 45a53e48c2bc8174854d6d62f93d00485c8d97a1 [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 }
Yong Chen61d5ed52015-01-16 09:05:18 +080039
40 for (auto input : mInputs) {
41 input->mAlloc.clear();
42 }
43
44 for (auto output : mOutputs) {
45 output->mAlloc.clear();
46 }
Jason Samsdbe66d62012-09-17 13:54:41 -070047}
48
49ScriptGroup::IO::IO(const ScriptKernelID *kid) {
50 mKernel = kid;
51}
52
53ScriptGroup::Node::Node(Script *s) {
54 mScript = s;
55 mSeen = false;
56 mOrder = 0;
57}
58
59ScriptGroup::Node * ScriptGroup::findNode(Script *s) const {
Chris Wailes93d6bc82014-07-28 16:54:38 -070060 for (auto node : mNodes) {
61 for (auto kernelRef : node->mKernels) {
62 if (kernelRef->mScript == s) {
63 return node;
Jason Samsdbe66d62012-09-17 13:54:41 -070064 }
65 }
66 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070067
Chris Wailes44bef6f2014-08-12 13:51:10 -070068 return nullptr;
Jason Samsdbe66d62012-09-17 13:54:41 -070069}
70
Chris Wailes93d6bc82014-07-28 16:54:38 -070071bool ScriptGroup::calcOrderRecurse(Node *node0, int depth) {
72 node0->mSeen = true;
73 if (node0->mOrder < depth) {
74 node0->mOrder = depth;
Jason Samsdbe66d62012-09-17 13:54:41 -070075 }
76 bool ret = true;
Chris Wailes93d6bc82014-07-28 16:54:38 -070077
78 for (auto link : node0->mOutputs) {
Chris Wailes44bef6f2014-08-12 13:51:10 -070079 Node *node1 = nullptr;
Chris Wailes93d6bc82014-07-28 16:54:38 -070080 if (link->mDstField.get()) {
81 node1 = findNode(link->mDstField->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -070082 } else {
Chris Wailes93d6bc82014-07-28 16:54:38 -070083 node1 = findNode(link->mDstKernel->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -070084 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070085 if (node1->mSeen) {
Jason Samsdbe66d62012-09-17 13:54:41 -070086 return false;
87 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070088 ret &= calcOrderRecurse(node1, node0->mOrder + 1);
Jason Samsdbe66d62012-09-17 13:54:41 -070089 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070090
Jason Samsdbe66d62012-09-17 13:54:41 -070091 return ret;
92}
93
Jason Samsdbe66d62012-09-17 13:54:41 -070094bool ScriptGroup::calcOrder() {
95 // Make nodes
Chris Wailes93d6bc82014-07-28 16:54:38 -070096
97 for (auto kernelRef : mKernels) {
98 const ScriptKernelID *kernel = kernelRef.get();
99 Node *node = findNode(kernel->mScript);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700100 if (node == nullptr) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700101 node = new Node(kernel->mScript);
102 mNodes.push_back(node);
Jason Samsdbe66d62012-09-17 13:54:41 -0700103 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700104 node->mKernels.push_back(kernel);
Jason Samsdbe66d62012-09-17 13:54:41 -0700105 }
106
107 // add links
Chris Wailes93d6bc82014-07-28 16:54:38 -0700108 for (auto link : mLinks) {
109 Node *node = findNode(link->mSource->mScript);
110 node->mOutputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700111
Chris Wailes93d6bc82014-07-28 16:54:38 -0700112 if (link->mDstKernel.get()) {
113 node = findNode(link->mDstKernel->mScript);
114 node->mInputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700115 } else {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700116 node = findNode(link->mDstField->mScript);
117 node->mInputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700118 }
119 }
120
Jason Samsdbe66d62012-09-17 13:54:41 -0700121 // Order nodes
122 bool ret = true;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700123 for (auto n0 : mNodes) {
124 if (n0->mInputs.size() == 0) {
125 for (auto n1 : mNodes) {
126 n1->mSeen = false;
Jason Samsdbe66d62012-09-17 13:54:41 -0700127 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700128 ret &= calcOrderRecurse(n0, 1);
Jason Samsdbe66d62012-09-17 13:54:41 -0700129 }
130 }
131
Chris Wailes93d6bc82014-07-28 16:54:38 -0700132 for (auto kernelRef : mKernels) {
133 const ScriptKernelID *kernel = kernelRef.get();
134 const Node *node = findNode(kernel->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -0700135
Chris Wailes93d6bc82014-07-28 16:54:38 -0700136 if (kernel->mHasKernelOutput) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700137 bool found = false;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700138 for (auto output : node->mOutputs) {
139 if (output->mSource.get() == kernel) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700140 found = true;
141 break;
142 }
143 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700144
Jason Samsdbe66d62012-09-17 13:54:41 -0700145 if (!found) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700146 mOutputs.push_back(new IO(kernel));
Jason Samsdbe66d62012-09-17 13:54:41 -0700147 }
148 }
149
Chris Wailes93d6bc82014-07-28 16:54:38 -0700150 if (kernel->mHasKernelInput) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700151 bool found = false;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700152 for (auto input : node->mInputs) {
153 if (input->mDstKernel.get() == kernel) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700154 found = true;
155 break;
156 }
157 }
158 if (!found) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700159 mInputs.push_back(new IO(kernel));
Jason Samsdbe66d62012-09-17 13:54:41 -0700160 }
161 }
162 }
163
164 // sort
Chris Wailes93d6bc82014-07-28 16:54:38 -0700165 std::stable_sort(mNodes.begin(), mNodes.end(),
166 [](const ScriptGroup::Node* lhs,
167 const ScriptGroup::Node* rhs) {
168 return lhs->mOrder < rhs->mOrder;
169 });
Jason Samsdbe66d62012-09-17 13:54:41 -0700170
171 return ret;
172}
173
174ScriptGroup * ScriptGroup::create(Context *rsc,
175 ScriptKernelID ** kernels, size_t kernelsSize,
176 ScriptKernelID ** src, size_t srcSize,
177 ScriptKernelID ** dstK, size_t dstKSize,
178 ScriptFieldID ** dstF, size_t dstFSize,
179 const Type ** type, size_t typeSize) {
180
181 size_t kernelCount = kernelsSize / sizeof(ScriptKernelID *);
182 size_t linkCount = typeSize / sizeof(Type *);
183
184 //ALOGE("ScriptGroup::create kernels=%i links=%i", (int)kernelCount, (int)linkCount);
185
186
187 // Start by counting unique kernel sources
188
189 ScriptGroup *sg = new ScriptGroup(rsc);
190
191 sg->mKernels.reserve(kernelCount);
192 for (size_t ct=0; ct < kernelCount; ct++) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700193 sg->mKernels.push_back(kernels[ct]);
Jason Samsdbe66d62012-09-17 13:54:41 -0700194 }
195
196 sg->mLinks.reserve(linkCount);
197 for (size_t ct=0; ct < linkCount; ct++) {
198 Link *l = new Link();
199 l->mType = type[ct];
200 l->mSource = src[ct];
201 l->mDstField = dstF[ct];
202 l->mDstKernel = dstK[ct];
Chris Wailes93d6bc82014-07-28 16:54:38 -0700203 sg->mLinks.push_back(l);
Jason Samsdbe66d62012-09-17 13:54:41 -0700204 }
205
206 sg->calcOrder();
207
208 // allocate links
209 for (size_t ct=0; ct < sg->mNodes.size(); ct++) {
210 const Node *n = sg->mNodes[ct];
211 for (size_t ct2=0; ct2 < n->mOutputs.size(); ct2++) {
212 Link *l = n->mOutputs[ct2];
213 if (l->mAlloc.get()) {
214 continue;
215 }
216 const ScriptKernelID *k = l->mSource.get();
217
218 Allocation * alloc = Allocation::createAllocation(rsc,
219 l->mType.get(), RS_ALLOCATION_USAGE_SCRIPT);
220 l->mAlloc = alloc;
221
222 for (size_t ct3=ct2+1; ct3 < n->mOutputs.size(); ct3++) {
223 if (n->mOutputs[ct3]->mSource.get() == l->mSource.get()) {
224 n->mOutputs[ct3]->mAlloc = alloc;
225 }
226 }
227 }
228 }
229
230 if (rsc->mHal.funcs.scriptgroup.init) {
231 rsc->mHal.funcs.scriptgroup.init(rsc, sg);
232 }
Stephen Hines61c86952013-04-09 17:34:43 -0700233 sg->incUserRef();
Jason Samsdbe66d62012-09-17 13:54:41 -0700234 return sg;
235}
236
237void ScriptGroup::setInput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700238 for (auto input : mInputs) {
239 if (input->mKernel == kid) {
240 input->mAlloc = a;
Jason Samsdbe66d62012-09-17 13:54:41 -0700241
242 if (rsc->mHal.funcs.scriptgroup.setInput) {
243 rsc->mHal.funcs.scriptgroup.setInput(rsc, this, kid, a);
244 }
245 return;
246 }
247 }
248 rsAssert(!"ScriptGroup:setInput kid not found");
249}
250
251void ScriptGroup::setOutput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700252 for (auto output : mOutputs) {
253 if (output->mKernel == kid) {
254 output->mAlloc = a;
Jason Samsdbe66d62012-09-17 13:54:41 -0700255
256 if (rsc->mHal.funcs.scriptgroup.setOutput) {
257 rsc->mHal.funcs.scriptgroup.setOutput(rsc, this, kid, a);
258 }
259 return;
260 }
261 }
262 rsAssert(!"ScriptGroup:setOutput kid not found");
263}
264
Yang Ni5f6f16f2014-07-25 13:51:09 -0700265bool ScriptGroup::validateInputAndOutput(Context *rsc) {
266 for(size_t i = 0; i < mInputs.size(); i++) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700267 if (mInputs[i]->mAlloc.get() == nullptr) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700268 rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing input.");
269 return false;
270 }
271 }
272
273 for(size_t i = 0; i < mOutputs.size(); i++) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700274 if (mOutputs[i]->mAlloc.get() == nullptr) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700275 rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing output.");
276 return false;
277 }
278 }
279
280 return true;
281}
282
Jason Samsdbe66d62012-09-17 13:54:41 -0700283void ScriptGroup::execute(Context *rsc) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700284 if (!validateInputAndOutput(rsc)) {
285 return;
286 }
287
Jason Samsdbe66d62012-09-17 13:54:41 -0700288 if (rsc->mHal.funcs.scriptgroup.execute) {
289 rsc->mHal.funcs.scriptgroup.execute(rsc, this);
290 return;
291 }
292
Chris Wailes93d6bc82014-07-28 16:54:38 -0700293 for (auto node : mNodes) {
294 for (auto kernel : node->mKernels) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700295 Allocation *ain = nullptr;
296 Allocation *aout = nullptr;
Jason Samsdbe66d62012-09-17 13:54:41 -0700297
Chris Wailes93d6bc82014-07-28 16:54:38 -0700298 for (auto nodeInput : node->mInputs) {
299 if (nodeInput->mDstKernel.get() == kernel) {
300 ain = nodeInput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700301 }
302 }
303
Chris Wailes93d6bc82014-07-28 16:54:38 -0700304 for (auto sgInput : mInputs) {
305 if (sgInput->mKernel == kernel) {
306 ain = sgInput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700307 }
308 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700309
310 for (auto nodeOutput : node->mOutputs) {
311 if (nodeOutput->mDstKernel.get() == kernel) {
312 aout = nodeOutput->mAlloc.get();
313 }
314 }
315
316 for (auto sgOutput : mOutputs) {
317 if (sgOutput->mKernel == kernel) {
318 aout = sgOutput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700319 }
320 }
321
Chris Wailes44bef6f2014-08-12 13:51:10 -0700322 if (ain == nullptr) {
323 node->mScript->runForEach(rsc, kernel->mSlot, nullptr, 0, aout,
324 nullptr, 0);
Chris Wailesf3712132014-07-16 15:18:30 -0700325 } else {
326 const Allocation *ains[1] = {ain};
Chris Wailes93d6bc82014-07-28 16:54:38 -0700327 node->mScript->runForEach(rsc, kernel->mSlot, ains,
328 sizeof(ains) / sizeof(RsAllocation),
Chris Wailes44bef6f2014-08-12 13:51:10 -0700329 aout, nullptr, 0);
Chris Wailesf3712132014-07-16 15:18:30 -0700330 }
Jason Samsdbe66d62012-09-17 13:54:41 -0700331 }
Jason Samsdbe66d62012-09-17 13:54:41 -0700332 }
333
334}
335
Jason Samsdbe66d62012-09-17 13:54:41 -0700336ScriptGroup::Link::Link() {
337}
338
339ScriptGroup::Link::~Link() {
340}
341
342namespace android {
343namespace renderscript {
344
345
346RsScriptGroup rsi_ScriptGroupCreate(Context *rsc,
347 RsScriptKernelID * kernels, size_t kernelsSize,
348 RsScriptKernelID * src, size_t srcSize,
349 RsScriptKernelID * dstK, size_t dstKSize,
350 RsScriptFieldID * dstF, size_t dstFSize,
351 const RsType * type, size_t typeSize) {
352
353
354 return ScriptGroup::create(rsc,
355 (ScriptKernelID **) kernels, kernelsSize,
356 (ScriptKernelID **) src, srcSize,
357 (ScriptKernelID **) dstK, dstKSize,
358 (ScriptFieldID **) dstF, dstFSize,
359 (const Type **) type, typeSize);
360}
361
362
363void rsi_ScriptGroupSetInput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
364 RsAllocation alloc) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700365 ScriptGroup *s = (ScriptGroup *)sg;
366 s->setInput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
367}
368
369void rsi_ScriptGroupSetOutput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
370 RsAllocation alloc) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700371 ScriptGroup *s = (ScriptGroup *)sg;
372 s->setOutput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
373}
374
375void rsi_ScriptGroupExecute(Context *rsc, RsScriptGroup sg) {
Yang Ni1ffd86b2015-01-07 09:16:40 -0800376 ScriptGroupBase *s = (ScriptGroupBase *)sg;
Jason Samsdbe66d62012-09-17 13:54:41 -0700377 s->execute(rsc);
378}
379
380}
381}