blob: bbf28366838641bd4f110b929a1f95ee4f13ce96 [file] [log] [blame]
Jason Samsbad80742011-03-16 16:29:28 -07001/*
2 * Copyright (C) 2011 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
18#include "rsdCore.h"
19#include "rsdBcc.h"
Jason Sams87fe59a2011-04-20 15:09:01 -070020#include "rsdRuntime.h"
Jason Samsbad80742011-03-16 16:29:28 -070021
22#include "rsContext.h"
23#include "rsScriptC.h"
24
25#include "utils/Timers.h"
26#include "utils/StopWatch.h"
27extern "C" {
28#include "libdex/ZipArchive.h"
29}
30
31
32using namespace android;
33using namespace android::renderscript;
34
35struct DrvScript {
36 int (*mRoot)();
37 void (*mInit)();
38
39 BCCScriptRef mBccScript;
40
41 uint32_t mInvokeFunctionCount;
42 InvokeFunc_t *mInvokeFunctions;
43 uint32_t mFieldCount;
44 void ** mFieldAddress;
45 bool * mFieldIsObject;
46
47 const uint8_t * mScriptText;
48 uint32_t mScriptTextLength;
49
50 //uint32_t * mObjectSlots;
51 //uint32_t mObjectSlotCount;
52
53 uint32_t mPragmaCount;
54 const char ** mPragmaKeys;
55 const char ** mPragmaValues;
56
57};
58
Jason Sams83c451a2011-04-21 11:46:50 -070059
Jason Samscdfdb8f2011-03-17 16:12:47 -070060static Script * setTLS(Script *sc) {
Jason Sams83c451a2011-04-21 11:46:50 -070061 ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey);
Jason Samscdfdb8f2011-03-17 16:12:47 -070062 rsAssert(tls);
63 Script *old = tls->mScript;
64 tls->mScript = sc;
65 return old;
66}
67
68
Jason Samsbad80742011-03-16 16:29:28 -070069bool rsdScriptInit(const Context *rsc,
70 ScriptC *script,
71 char const *resName,
72 char const *cacheDir,
73 uint8_t const *bitcode,
74 size_t bitcodeSize,
Jason Sams87fe59a2011-04-20 15:09:01 -070075 uint32_t flags) {
Jason Samsbad80742011-03-16 16:29:28 -070076 //LOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
77
Jason Sams83c451a2011-04-21 11:46:50 -070078 pthread_mutex_lock(&rsdgInitMutex);
Jason Samsbad80742011-03-16 16:29:28 -070079 char *cachePath = NULL;
80 uint32_t objectSlotCount = 0;
81
82 DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
83 if (drv == NULL) {
Jason Sams83c451a2011-04-21 11:46:50 -070084 goto error;
Jason Samsbad80742011-03-16 16:29:28 -070085 }
86 script->mHal.drv = drv;
87
88 drv->mBccScript = bccCreateScript();
89 script->mHal.info.isThreadable = true;
90 drv->mScriptText = bitcode;
91 drv->mScriptTextLength = bitcodeSize;
92
93 //LOGE("mBccScript %p", script->mBccScript);
94
Jason Sams87fe59a2011-04-20 15:09:01 -070095 if (bccRegisterSymbolCallback(drv->mBccScript, &rsdLookupRuntimeStub, script) != 0) {
Jason Samsbad80742011-03-16 16:29:28 -070096 LOGE("bcc: FAILS to register symbol callback");
97 goto error;
98 }
99
100 if (bccReadBC(drv->mBccScript,
101 resName,
102 (char const *)drv->mScriptText,
103 drv->mScriptTextLength, 0) != 0) {
104 LOGE("bcc: FAILS to read bitcode");
Jason Sams83c451a2011-04-21 11:46:50 -0700105 goto error;
Jason Samsbad80742011-03-16 16:29:28 -0700106 }
107
Jason Samsbad80742011-03-16 16:29:28 -0700108 if (bccLinkFile(drv->mBccScript, "/system/lib/libclcore.bc", 0) != 0) {
109 LOGE("bcc: FAILS to link bitcode");
Jason Sams83c451a2011-04-21 11:46:50 -0700110 goto error;
Jason Samsbad80742011-03-16 16:29:28 -0700111 }
Jason Samsbad80742011-03-16 16:29:28 -0700112
Logan Chienabfaab82011-07-11 15:32:24 +0800113 if (bccPrepareExecutableEx(drv->mBccScript, cacheDir, resName, 0) != 0) {
Jason Samsbad80742011-03-16 16:29:28 -0700114 LOGE("bcc: FAILS to prepare executable");
Jason Sams83c451a2011-04-21 11:46:50 -0700115 goto error;
Jason Samsbad80742011-03-16 16:29:28 -0700116 }
117
118 free(cachePath);
119
120 drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root"));
121 drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init"));
122
123 drv->mInvokeFunctionCount = bccGetExportFuncCount(drv->mBccScript);
124 if (drv->mInvokeFunctionCount <= 0)
125 drv->mInvokeFunctions = NULL;
126 else {
127 drv->mInvokeFunctions = (InvokeFunc_t*) calloc(drv->mInvokeFunctionCount, sizeof(InvokeFunc_t));
128 bccGetExportFuncList(drv->mBccScript, drv->mInvokeFunctionCount, (void **) drv->mInvokeFunctions);
129 }
130
131 drv->mFieldCount = bccGetExportVarCount(drv->mBccScript);
132 if (drv->mFieldCount <= 0) {
133 drv->mFieldAddress = NULL;
134 drv->mFieldIsObject = NULL;
135 } else {
136 drv->mFieldAddress = (void **) calloc(drv->mFieldCount, sizeof(void *));
137 drv->mFieldIsObject = (bool *) calloc(drv->mFieldCount, sizeof(bool));
138 bccGetExportVarList(drv->mBccScript, drv->mFieldCount, (void **) drv->mFieldAddress);
139 }
140
141 objectSlotCount = bccGetObjectSlotCount(drv->mBccScript);
142 if (objectSlotCount) {
143 uint32_t * slots = new uint32_t[objectSlotCount];
144 bccGetObjectSlotList(drv->mBccScript, objectSlotCount, slots);
145 for (uint32_t ct=0; ct < objectSlotCount; ct++) {
146 drv->mFieldIsObject[slots[ct]] = true;
147 }
148 delete [] slots;
149 }
150
151 uint32_t mPragmaCount;
152 const char ** mPragmaKeys;
153 const char ** mPragmaValues;
154
Jason Samsbad80742011-03-16 16:29:28 -0700155 drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript);
156 if (drv->mPragmaCount <= 0) {
157 drv->mPragmaKeys = NULL;
158 drv->mPragmaValues = NULL;
159 } else {
Logan Chien585f5542011-07-10 19:39:03 +0800160 drv->mPragmaKeys = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
161 drv->mPragmaValues = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
Jason Samsbad80742011-03-16 16:29:28 -0700162 bccGetPragmaList(drv->mBccScript, drv->mPragmaCount, drv->mPragmaKeys, drv->mPragmaValues);
163 }
164
165
166
167 // Copy info over to runtime
168 script->mHal.info.exportedFunctionCount = drv->mInvokeFunctionCount;
169 script->mHal.info.exportedVariableCount = drv->mFieldCount;
170 script->mHal.info.exportedPragmaCount = drv->mPragmaCount;
171 script->mHal.info.exportedPragmaKeyList = drv->mPragmaKeys;
172 script->mHal.info.exportedPragmaValueList = drv->mPragmaValues;
173 script->mHal.info.root = drv->mRoot;
174
175
Jason Sams83c451a2011-04-21 11:46:50 -0700176 pthread_mutex_unlock(&rsdgInitMutex);
Jason Samsbad80742011-03-16 16:29:28 -0700177 return true;
178
179error:
180
Jason Sams83c451a2011-04-21 11:46:50 -0700181 pthread_mutex_unlock(&rsdgInitMutex);
Jason Samsbad80742011-03-16 16:29:28 -0700182 free(drv);
183 return false;
184
185}
186
Jason Samscdfdb8f2011-03-17 16:12:47 -0700187typedef struct {
188 Context *rsc;
189 Script *script;
190 const Allocation * ain;
191 Allocation * aout;
192 const void * usr;
Jason Samsbad80742011-03-16 16:29:28 -0700193
Jason Samscdfdb8f2011-03-17 16:12:47 -0700194 uint32_t mSliceSize;
195 volatile int mSliceNum;
196
197 const uint8_t *ptrIn;
198 uint32_t eStrideIn;
199 uint8_t *ptrOut;
200 uint32_t eStrideOut;
201
202 uint32_t xStart;
203 uint32_t xEnd;
204 uint32_t yStart;
205 uint32_t yEnd;
206 uint32_t zStart;
207 uint32_t zEnd;
208 uint32_t arrayStart;
209 uint32_t arrayEnd;
210
211 uint32_t dimX;
212 uint32_t dimY;
213 uint32_t dimZ;
214 uint32_t dimArray;
215} MTLaunchStruct;
216typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
217
218static void wc_xy(void *usr, uint32_t idx) {
219 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
220
221 while (1) {
222 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
223 uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
224 uint32_t yEnd = yStart + mtls->mSliceSize;
225 yEnd = rsMin(yEnd, mtls->yEnd);
226 if (yEnd <= yStart) {
227 return;
228 }
229
230 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
231 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
232 for (uint32_t y = yStart; y < yEnd; y++) {
233 uint32_t offset = mtls->dimX * y;
234 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset);
235 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset);
236
237 for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) {
238 ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0);
239 xPtrIn += mtls->eStrideIn;
240 xPtrOut += mtls->eStrideOut;
241 }
242 }
243 }
Jason Samsbad80742011-03-16 16:29:28 -0700244}
245
Jason Samscdfdb8f2011-03-17 16:12:47 -0700246static void wc_x(void *usr, uint32_t idx) {
247 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
248
249 while (1) {
250 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
251 uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
252 uint32_t xEnd = xStart + mtls->mSliceSize;
253 xEnd = rsMin(xEnd, mtls->xEnd);
254 if (xEnd <= xStart) {
255 return;
256 }
257
258 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
259 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
260 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart);
261 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart);
262 for (uint32_t x = xStart; x < xEnd; x++) {
263 ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
264 xPtrIn += mtls->eStrideIn;
265 xPtrOut += mtls->eStrideOut;
266 }
267 }
268}
269
270void rsdScriptInvokeForEach(const Context *rsc,
271 Script *s,
Jason Sams35e429e2011-07-13 11:26:26 -0700272 uint32_t slot,
Jason Samscdfdb8f2011-03-17 16:12:47 -0700273 const Allocation * ain,
274 Allocation * aout,
275 const void * usr,
276 uint32_t usrLen,
277 const RsScriptCall *sc) {
278
Jason Sams87fe59a2011-04-20 15:09:01 -0700279 RsdHal * dc = (RsdHal *)rsc->mHal.drv;
Jason Samscdfdb8f2011-03-17 16:12:47 -0700280
281 MTLaunchStruct mtls;
282 memset(&mtls, 0, sizeof(mtls));
283
284 if (ain) {
285 mtls.dimX = ain->getType()->getDimX();
286 mtls.dimY = ain->getType()->getDimY();
287 mtls.dimZ = ain->getType()->getDimZ();
288 //mtls.dimArray = ain->getType()->getDimArray();
289 } else if (aout) {
290 mtls.dimX = aout->getType()->getDimX();
291 mtls.dimY = aout->getType()->getDimY();
292 mtls.dimZ = aout->getType()->getDimZ();
293 //mtls.dimArray = aout->getType()->getDimArray();
294 } else {
295 rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
296 return;
297 }
298
299 if (!sc || (sc->xEnd == 0)) {
300 mtls.xEnd = mtls.dimX;
301 } else {
302 rsAssert(sc->xStart < mtls.dimX);
303 rsAssert(sc->xEnd <= mtls.dimX);
304 rsAssert(sc->xStart < sc->xEnd);
305 mtls.xStart = rsMin(mtls.dimX, sc->xStart);
306 mtls.xEnd = rsMin(mtls.dimX, sc->xEnd);
307 if (mtls.xStart >= mtls.xEnd) return;
308 }
309
310 if (!sc || (sc->yEnd == 0)) {
311 mtls.yEnd = mtls.dimY;
312 } else {
313 rsAssert(sc->yStart < mtls.dimY);
314 rsAssert(sc->yEnd <= mtls.dimY);
315 rsAssert(sc->yStart < sc->yEnd);
316 mtls.yStart = rsMin(mtls.dimY, sc->yStart);
317 mtls.yEnd = rsMin(mtls.dimY, sc->yEnd);
318 if (mtls.yStart >= mtls.yEnd) return;
319 }
320
321 mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd);
322 mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd);
323 mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd);
324 mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd);
325
Stephen Hineseed1b152011-04-11 14:02:22 -0700326 rsAssert(!ain || (ain->getType()->getDimZ() == 0));
Jason Samscdfdb8f2011-03-17 16:12:47 -0700327
328 Context *mrsc = (Context *)rsc;
329 Script * oldTLS = setTLS(s);
330
331 mtls.rsc = mrsc;
332 mtls.ain = ain;
333 mtls.aout = aout;
334 mtls.script = s;
335 mtls.usr = usr;
336 mtls.mSliceSize = 10;
337 mtls.mSliceNum = 0;
338
339 mtls.ptrIn = NULL;
340 mtls.eStrideIn = 0;
341 if (ain) {
342 mtls.ptrIn = (const uint8_t *)ain->getPtr();
343 mtls.eStrideIn = ain->getType()->getElementSizeBytes();
344 }
345
346 mtls.ptrOut = NULL;
347 mtls.eStrideOut = 0;
348 if (aout) {
349 mtls.ptrOut = (uint8_t *)aout->getPtr();
350 mtls.eStrideOut = aout->getType()->getElementSizeBytes();
351 }
352
353 if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable) {
354 if (mtls.dimY > 1) {
355 rsdLaunchThreads(mrsc, wc_xy, &mtls);
356 } else {
357 rsdLaunchThreads(mrsc, wc_x, &mtls);
358 }
359
360 //LOGE("launch 1");
361 } else {
362 //LOGE("launch 3");
363 for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
364 for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) {
365 for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) {
366 uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar +
367 mtls.dimX * mtls.dimY * z +
368 mtls.dimX * y;
369 uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset);
370 const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset);
371
372 for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) {
373 ((rs_t)s->mHal.info.root) (xPtrIn, xPtrOut, usr, x, y, z, ar);
374 xPtrIn += mtls.eStrideIn;
375 xPtrOut += mtls.eStrideOut;
376 }
377 }
378 }
379 }
380 }
381
382 setTLS(oldTLS);
383}
384
385
386int rsdScriptInvokeRoot(const Context *dc, Script *script) {
387 DrvScript *drv = (DrvScript *)script->mHal.drv;
388
389 Script * oldTLS = setTLS(script);
390 int ret = drv->mRoot();
391 setTLS(oldTLS);
392
393 return ret;
394}
395
396void rsdScriptInvokeInit(const Context *dc, Script *script) {
Jason Samsbad80742011-03-16 16:29:28 -0700397 DrvScript *drv = (DrvScript *)script->mHal.drv;
398
399 if (drv->mInit) {
400 drv->mInit();
401 }
402}
403
404
Jason Samscdfdb8f2011-03-17 16:12:47 -0700405void rsdScriptInvokeFunction(const Context *dc, Script *script,
Jason Samsbad80742011-03-16 16:29:28 -0700406 uint32_t slot,
407 const void *params,
408 size_t paramLength) {
409 DrvScript *drv = (DrvScript *)script->mHal.drv;
410 //LOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
411
Jason Samscdfdb8f2011-03-17 16:12:47 -0700412 Script * oldTLS = setTLS(script);
Jason Samsbad80742011-03-16 16:29:28 -0700413 ((void (*)(const void *, uint32_t))
414 drv->mInvokeFunctions[slot])(params, paramLength);
Jason Samscdfdb8f2011-03-17 16:12:47 -0700415 setTLS(oldTLS);
Jason Samsbad80742011-03-16 16:29:28 -0700416}
417
418void rsdScriptSetGlobalVar(const Context *dc, const Script *script,
419 uint32_t slot, void *data, size_t dataLength) {
420 DrvScript *drv = (DrvScript *)script->mHal.drv;
421 //rsAssert(!script->mFieldIsObject[slot]);
422 //LOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
423
424 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot];
425 if (!destPtr) {
426 //LOGV("Calling setVar on slot = %i which is null", slot);
427 return;
428 }
429
430 memcpy(destPtr, data, dataLength);
431}
432
433void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, void *data) {
434 DrvScript *drv = (DrvScript *)script->mHal.drv;
435 //rsAssert(!script->mFieldIsObject[slot]);
436 //LOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
437
438 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot];
439 if (!destPtr) {
440 //LOGV("Calling setVar on slot = %i which is null", slot);
441 return;
442 }
443
444 memcpy(destPtr, &data, sizeof(void *));
445}
446
447void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) {
448 DrvScript *drv = (DrvScript *)script->mHal.drv;
449 //rsAssert(script->mFieldIsObject[slot]);
450 //LOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
451
452 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot];
453 if (!destPtr) {
454 //LOGV("Calling setVar on slot = %i which is null", slot);
455 return;
456 }
457
Jason Sams87fe59a2011-04-20 15:09:01 -0700458 rsrSetObject(dc, script, (ObjectBase **)destPtr, data);
Jason Samsbad80742011-03-16 16:29:28 -0700459}
460
461void rsdScriptDestroy(const Context *dc, Script *script) {
462 DrvScript *drv = (DrvScript *)script->mHal.drv;
463
464 if (drv->mFieldAddress) {
465 for (size_t ct=0; ct < drv->mFieldCount; ct++) {
466 if (drv->mFieldIsObject[ct]) {
Stephen Hines8d43eaf2011-03-24 20:03:49 -0700467 // The field address can be NULL if the script-side has
468 // optimized the corresponding global variable away.
469 if (drv->mFieldAddress[ct]) {
Jason Sams87fe59a2011-04-20 15:09:01 -0700470 rsrClearObject(dc, script, (ObjectBase **)drv->mFieldAddress[ct]);
Stephen Hines8d43eaf2011-03-24 20:03:49 -0700471 }
Jason Samsbad80742011-03-16 16:29:28 -0700472 }
473 }
474 delete [] drv->mFieldAddress;
475 delete [] drv->mFieldIsObject;
476 drv->mFieldAddress = NULL;
477 drv->mFieldIsObject = NULL;
478 drv->mFieldCount = 0;
479 }
480
481 if (drv->mInvokeFunctions) {
482 delete [] drv->mInvokeFunctions;
483 drv->mInvokeFunctions = NULL;
484 drv->mInvokeFunctionCount = 0;
485 }
486 free(drv);
487 script->mHal.drv = NULL;
488
489}
490
491