rsCpuScript.cpp revision 47935ac8e3dd619f758abd576605a564e33bb59c
1/* 2 * Copyright (C) 2011-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 18 19#include "rsCpuCore.h" 20 21#include "rsCpuScript.h" 22//#include "rsdRuntime.h" 23//#include "rsdAllocation.h" 24//#include "rsCpuIntrinsics.h" 25 26#ifndef RS_SERVER 27#include "utils/Vector.h" 28#include "utils/Timers.h" 29#include "utils/StopWatch.h" 30#endif 31 32#ifdef RS_COMPATIBILITY_LIB 33 #include <dlfcn.h> 34 #include <stdio.h> 35 #include <string.h> 36#else 37 #include <bcc/BCCContext.h> 38 #include <bcc/Renderscript/RSCompilerDriver.h> 39 #include <bcc/Renderscript/RSExecutable.h> 40 #include <bcc/Renderscript/RSInfo.h> 41 #include <cutils/properties.h> 42#endif 43 44#ifndef RS_COMPATIBILITY_LIB 45namespace { 46static bool is_force_recompile() { 47#ifdef RS_SERVER 48 return false; 49#else 50 char buf[PROPERTY_VALUE_MAX]; 51 52 // Re-compile if floating point precision has been overridden. 53 property_get("debug.rs.precision", buf, ""); 54 if (buf[0] != '\0') { 55 return true; 56 } 57 58 // Re-compile if debug.rs.forcerecompile is set. 59 property_get("debug.rs.forcerecompile", buf, "0"); 60 if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) { 61 return true; 62 } else { 63 return false; 64 } 65#endif // RS_SERVER 66} 67} // namespace 68#endif // !defined(RS_COMPATIBILITY_LIB) 69 70namespace android { 71namespace renderscript { 72 73 74#ifdef RS_COMPATIBILITY_LIB 75#define MAXLINE 500 76#define MAKE_STR_HELPER(S) #S 77#define MAKE_STR(S) MAKE_STR_HELPER(S) 78#define EXPORT_VAR_STR "exportVarCount: " 79#define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR) 80#define EXPORT_FUNC_STR "exportFuncCount: " 81#define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR) 82#define EXPORT_FOREACH_STR "exportForEachCount: " 83#define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR) 84#define OBJECT_SLOT_STR "objectSlotCount: " 85#define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR) 86 87// Copy up to a newline or size chars from str -> s, updating str 88// Returns s when successful and NULL when '\0' is finally reached. 89static char* strgets(char *s, int size, const char **ppstr) { 90 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) { 91 return NULL; 92 } 93 94 int i; 95 for (i = 0; i < (size - 1); i++) { 96 s[i] = **ppstr; 97 (*ppstr)++; 98 if (s[i] == '\0') { 99 return s; 100 } else if (s[i] == '\n') { 101 s[i+1] = '\0'; 102 return s; 103 } 104 } 105 106 // size has been exceeded. 107 s[i] = '\0'; 108 109 return s; 110} 111#endif 112 113RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) { 114 mCtx = ctx; 115 mScript = s; 116 117#ifdef RS_COMPATIBILITY_LIB 118 mScriptSO = NULL; 119 mInvokeFunctions = NULL; 120 mForEachFunctions = NULL; 121 mFieldAddress = NULL; 122 mFieldIsObject = NULL; 123 mForEachSignatures = NULL; 124#else 125 mCompilerContext = NULL; 126 mCompilerDriver = NULL; 127 mExecutable = NULL; 128#endif 129 130 mRoot = NULL; 131 mRootExpand = NULL; 132 mInit = NULL; 133 mFreeChildren = NULL; 134 135 136 mBoundAllocs = NULL; 137 mIntrinsicData = NULL; 138 mIsThreadable = true; 139} 140 141 142bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, 143 uint8_t const *bitcode, size_t bitcodeSize, 144 uint32_t flags) { 145 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc); 146 //ALOGE("rsdScriptInit %p %p", rsc, script); 147 148 mCtx->lockMutex(); 149 150#ifndef RS_COMPATIBILITY_LIB 151 bcc::RSExecutable *exec = NULL; 152 153 mCompilerContext = NULL; 154 mCompilerDriver = NULL; 155 mExecutable = NULL; 156 157 mCompilerContext = new bcc::BCCContext(); 158 if (mCompilerContext == NULL) { 159 ALOGE("bcc: FAILS to create compiler context (out of memory)"); 160 mCtx->unlockMutex(); 161 return false; 162 } 163 164 mCompilerDriver = new bcc::RSCompilerDriver(); 165 if (mCompilerDriver == NULL) { 166 ALOGE("bcc: FAILS to create compiler driver (out of memory)"); 167 mCtx->unlockMutex(); 168 return false; 169 } 170 171 mCompilerDriver->setRSRuntimeLookupFunction(lookupRuntimeStub); 172 mCompilerDriver->setRSRuntimeLookupContext(this); 173 174 // Run any compiler setup functions we have been provided with. 175 RSSetupCompilerCallback setupCompilerCallback = 176 mCtx->getSetupCompilerCallback(); 177 if (setupCompilerCallback != NULL) { 178 setupCompilerCallback(mCompilerDriver); 179 } 180 181 const char *core_lib = NULL; 182 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback(); 183 if (selectRTCallback != NULL) { 184 core_lib = selectRTCallback((const char *)bitcode, bitcodeSize); 185 } 186 187 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) { 188 // Use the libclcore_debug.bc instead of the default library. 189 core_lib = bcc::RSInfo::LibCLCoreDebugPath; 190 mCompilerDriver->setDebugContext(true); 191 // Skip the cache lookup 192 } else if (!is_force_recompile()) { 193 // Attempt to just load the script from cache first if we can. 194 exec = mCompilerDriver->loadScript(cacheDir, resName, 195 (const char *)bitcode, bitcodeSize); 196 } 197 198 // TODO(srhines): This is being refactored, but it simply wraps the 199 // build (compile) and load steps together. 200 if (exec == NULL) { 201 bool built = mCompilerDriver->build(*mCompilerContext, cacheDir, 202 resName, (const char *)bitcode, 203 bitcodeSize, core_lib, 204 mCtx->getLinkRuntimeCallback()); 205 if (built) { 206 exec = mCompilerDriver->loadScript(cacheDir, resName, 207 (const char *)bitcode, 208 bitcodeSize); 209 } 210 } 211 212 if (exec == NULL) { 213 ALOGE("bcc: FAILS to prepare executable for '%s'", resName); 214 mCtx->unlockMutex(); 215 return false; 216 } 217 218 mExecutable = exec; 219 220 exec->setThreadable(mIsThreadable); 221 if (!exec->syncInfo()) { 222 ALOGW("bcc: FAILS to synchronize the RS info file to the disk"); 223 } 224 225 mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root")); 226 mRootExpand = 227 reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand")); 228 mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init")); 229 mFreeChildren = 230 reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor")); 231 232 233 const bcc::RSInfo *info = &mExecutable->getInfo(); 234 if (info->getExportVarNames().size()) { 235 mBoundAllocs = new Allocation *[info->getExportVarNames().size()]; 236 memset(mBoundAllocs, 0, sizeof(void *) * info->getExportVarNames().size()); 237 } 238 239#else 240 241#ifndef RS_SERVER 242 String8 scriptSOName(cacheDir); 243 scriptSOName = scriptSOName.getPathDir(); 244 scriptSOName.appendPath("lib"); 245 scriptSOName.append("/librs."); 246#else 247 String8 scriptSOName("lib"); 248#endif 249 scriptSOName.append(resName); 250 scriptSOName.append(".so"); 251 252 //script->mHal.drv = drv; 253 254 //ALOGV("Opening up shared object: %s", scriptSOName.string()); 255 mScriptSO = dlopen(scriptSOName.string(), RTLD_NOW | RTLD_LOCAL); 256 if (mScriptSO == NULL) { 257 ALOGE("Unable to open shared library (%s): %s", 258 scriptSOName.string(), dlerror()); 259 260 // One final attempt to find the library in "/system/lib". 261 // We do this to allow bundled applications to use the compatibility 262 // library fallback path. Those applications don't have a private 263 // library path, so they need to install to the system directly. 264 String8 scriptSONameSystem("/system/lib/librs."); 265 scriptSONameSystem.append(resName); 266 scriptSONameSystem.append(".so"); 267 mScriptSO = dlopen(scriptSONameSystem.string(), RTLD_NOW | RTLD_LOCAL); 268 if (mScriptSO == NULL) { 269 ALOGE("Unable to open system shared library (%s): %s", 270 scriptSONameSystem.string(), dlerror()); 271 goto error; 272 } 273 } 274 275 if (mScriptSO) { 276 char line[MAXLINE]; 277 mRoot = (RootFunc_t) dlsym(mScriptSO, "root"); 278 if (mRoot) { 279 //ALOGE("Found root(): %p", mRoot); 280 } 281 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand"); 282 if (mRootExpand) { 283 //ALOGE("Found root.expand(): %p", mRootExpand); 284 } 285 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init"); 286 if (mInit) { 287 //ALOGE("Found init(): %p", mInit); 288 } 289 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor"); 290 if (mFreeChildren) { 291 //ALOGE("Found .rs.dtor(): %p", mFreeChildren); 292 } 293 294 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info"); 295 if (rsInfo) { 296 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo); 297 } 298 299 size_t varCount = 0; 300 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 301 goto error; 302 } 303 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) { 304 ALOGE("Invalid export var count!: %s", line); 305 goto error; 306 } 307 308 mExportedVariableCount = varCount; 309 //ALOGE("varCount: %zu", varCount); 310 if (varCount > 0) { 311 // Start by creating/zeroing this member, since we don't want to 312 // accidentally clean up invalid pointers later (if we error out). 313 mFieldIsObject = new bool[varCount]; 314 if (mFieldIsObject == NULL) { 315 goto error; 316 } 317 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject)); 318 mFieldAddress = new void*[varCount]; 319 if (mFieldAddress == NULL) { 320 goto error; 321 } 322 for (size_t i = 0; i < varCount; ++i) { 323 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 324 goto error; 325 } 326 char *c = strrchr(line, '\n'); 327 if (c) { 328 *c = '\0'; 329 } 330 mFieldAddress[i] = dlsym(mScriptSO, line); 331 if (mFieldAddress[i] == NULL) { 332 ALOGE("Failed to find variable address for %s: %s", 333 line, dlerror()); 334 // Not a critical error if we don't find a global variable. 335 } 336 else { 337 //ALOGE("Found variable %s at %p", line, 338 //mFieldAddress[i]); 339 } 340 } 341 } 342 343 size_t funcCount = 0; 344 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 345 goto error; 346 } 347 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) { 348 ALOGE("Invalid export func count!: %s", line); 349 goto error; 350 } 351 352 mExportedFunctionCount = funcCount; 353 //ALOGE("funcCount: %zu", funcCount); 354 355 if (funcCount > 0) { 356 mInvokeFunctions = new InvokeFunc_t[funcCount]; 357 if (mInvokeFunctions == NULL) { 358 goto error; 359 } 360 for (size_t i = 0; i < funcCount; ++i) { 361 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 362 goto error; 363 } 364 char *c = strrchr(line, '\n'); 365 if (c) { 366 *c = '\0'; 367 } 368 369 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line); 370 if (mInvokeFunctions[i] == NULL) { 371 ALOGE("Failed to get function address for %s(): %s", 372 line, dlerror()); 373 goto error; 374 } 375 else { 376 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]); 377 } 378 } 379 } 380 381 size_t forEachCount = 0; 382 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 383 goto error; 384 } 385 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) { 386 ALOGE("Invalid export forEach count!: %s", line); 387 goto error; 388 } 389 390 if (forEachCount > 0) { 391 392 mForEachSignatures = new uint32_t[forEachCount]; 393 if (mForEachSignatures == NULL) { 394 goto error; 395 } 396 mForEachFunctions = new ForEachFunc_t[forEachCount]; 397 if (mForEachFunctions == NULL) { 398 goto error; 399 } 400 for (size_t i = 0; i < forEachCount; ++i) { 401 unsigned int tmpSig = 0; 402 char tmpName[MAXLINE]; 403 404 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 405 goto error; 406 } 407 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s", 408 &tmpSig, tmpName) != 2) { 409 ALOGE("Invalid export forEach!: %s", line); 410 goto error; 411 } 412 413 // Lookup the expanded ForEach kernel. 414 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName)); 415 mForEachSignatures[i] = tmpSig; 416 mForEachFunctions[i] = 417 (ForEachFunc_t) dlsym(mScriptSO, tmpName); 418 if (i != 0 && mForEachFunctions[i] == NULL) { 419 // Ignore missing root.expand functions. 420 // root() is always specified at location 0. 421 ALOGE("Failed to find forEach function address for %s: %s", 422 tmpName, dlerror()); 423 goto error; 424 } 425 else { 426 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]); 427 } 428 } 429 } 430 431 size_t objectSlotCount = 0; 432 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 433 goto error; 434 } 435 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) { 436 ALOGE("Invalid object slot count!: %s", line); 437 goto error; 438 } 439 440 if (objectSlotCount > 0) { 441 rsAssert(varCount > 0); 442 for (size_t i = 0; i < objectSlotCount; ++i) { 443 uint32_t varNum = 0; 444 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 445 goto error; 446 } 447 if (sscanf(line, "%u", &varNum) != 1) { 448 ALOGE("Invalid object slot!: %s", line); 449 goto error; 450 } 451 452 if (varNum < varCount) { 453 mFieldIsObject[varNum] = true; 454 } 455 } 456 } 457 458 if (varCount > 0) { 459 mBoundAllocs = new Allocation *[varCount]; 460 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs)); 461 } 462 463 if (mScriptSO == (void*)1) { 464 //rsdLookupRuntimeStub(script, "acos"); 465 } 466 } 467#endif 468 469 mCtx->unlockMutex(); 470 return true; 471 472#ifdef RS_COMPATIBILITY_LIB 473error: 474 475 mCtx->unlockMutex(); 476 delete[] mInvokeFunctions; 477 delete[] mForEachFunctions; 478 delete[] mFieldAddress; 479 delete[] mFieldIsObject; 480 delete[] mForEachSignatures; 481 delete[] mBoundAllocs; 482 if (mScriptSO) { 483 dlclose(mScriptSO); 484 } 485 return false; 486#endif 487} 488 489void RsdCpuScriptImpl::populateScript(Script *script) { 490#ifndef RS_COMPATIBILITY_LIB 491 const bcc::RSInfo *info = &mExecutable->getInfo(); 492 493 // Copy info over to runtime 494 script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size(); 495 script->mHal.info.exportedVariableCount = info->getExportVarNames().size(); 496 script->mHal.info.exportedForeachFuncList = info->getExportForeachFuncs().array(); 497 script->mHal.info.exportedPragmaCount = info->getPragmas().size(); 498 script->mHal.info.exportedPragmaKeyList = 499 const_cast<const char**>(mExecutable->getPragmaKeys().array()); 500 script->mHal.info.exportedPragmaValueList = 501 const_cast<const char**>(mExecutable->getPragmaValues().array()); 502 503 if (mRootExpand) { 504 script->mHal.info.root = mRootExpand; 505 } else { 506 script->mHal.info.root = mRoot; 507 } 508#else 509 // Copy info over to runtime 510 script->mHal.info.exportedFunctionCount = mExportedFunctionCount; 511 script->mHal.info.exportedVariableCount = mExportedVariableCount; 512 script->mHal.info.exportedPragmaCount = 0; 513 script->mHal.info.exportedPragmaKeyList = 0; 514 script->mHal.info.exportedPragmaValueList = 0; 515 516 // Bug, need to stash in metadata 517 if (mRootExpand) { 518 script->mHal.info.root = mRootExpand; 519 } else { 520 script->mHal.info.root = mRoot; 521 } 522#endif 523} 524 525 526typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t); 527 528void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout, 529 const void * usr, uint32_t usrLen, 530 const RsScriptCall *sc, 531 MTLaunchStruct *mtls) { 532 533 memset(mtls, 0, sizeof(MTLaunchStruct)); 534 535 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface 536 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) { 537 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 538 return; 539 } 540 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) { 541 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 542 return; 543 } 544 545 if (ain) { 546 mtls->fep.dimX = ain->getType()->getDimX(); 547 mtls->fep.dimY = ain->getType()->getDimY(); 548 mtls->fep.dimZ = ain->getType()->getDimZ(); 549 //mtls->dimArray = ain->getType()->getDimArray(); 550 } else if (aout) { 551 mtls->fep.dimX = aout->getType()->getDimX(); 552 mtls->fep.dimY = aout->getType()->getDimY(); 553 mtls->fep.dimZ = aout->getType()->getDimZ(); 554 //mtls->dimArray = aout->getType()->getDimArray(); 555 } else { 556 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 557 return; 558 } 559 560 if (!sc || (sc->xEnd == 0)) { 561 mtls->xEnd = mtls->fep.dimX; 562 } else { 563 rsAssert(sc->xStart < mtls->fep.dimX); 564 rsAssert(sc->xEnd <= mtls->fep.dimX); 565 rsAssert(sc->xStart < sc->xEnd); 566 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart); 567 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd); 568 if (mtls->xStart >= mtls->xEnd) return; 569 } 570 571 if (!sc || (sc->yEnd == 0)) { 572 mtls->yEnd = mtls->fep.dimY; 573 } else { 574 rsAssert(sc->yStart < mtls->fep.dimY); 575 rsAssert(sc->yEnd <= mtls->fep.dimY); 576 rsAssert(sc->yStart < sc->yEnd); 577 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart); 578 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd); 579 if (mtls->yStart >= mtls->yEnd) return; 580 } 581 582 if (!sc || (sc->zEnd == 0)) { 583 mtls->zEnd = mtls->fep.dimZ; 584 } else { 585 rsAssert(sc->zStart < mtls->fep.dimZ); 586 rsAssert(sc->zEnd <= mtls->fep.dimZ); 587 rsAssert(sc->zStart < sc->zEnd); 588 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart); 589 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd); 590 if (mtls->zStart >= mtls->zEnd) return; 591 } 592 593 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd); 594 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd); 595 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd); 596 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd); 597 598 rsAssert(!ain || (ain->getType()->getDimZ() == 0)); 599 600 mtls->rsc = mCtx; 601 mtls->ain = ain; 602 mtls->aout = aout; 603 mtls->fep.usr = usr; 604 mtls->fep.usrLen = usrLen; 605 mtls->mSliceSize = 1; 606 mtls->mSliceNum = 0; 607 608 mtls->fep.ptrIn = NULL; 609 mtls->fep.eStrideIn = 0; 610 mtls->isThreadable = mIsThreadable; 611 612 if (ain) { 613 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr; 614 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes(); 615 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride; 616 } 617 618 mtls->fep.ptrOut = NULL; 619 mtls->fep.eStrideOut = 0; 620 if (aout) { 621 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr; 622 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes(); 623 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride; 624 } 625} 626 627 628void RsdCpuScriptImpl::invokeForEach(uint32_t slot, 629 const Allocation * ain, 630 Allocation * aout, 631 const void * usr, 632 uint32_t usrLen, 633 const RsScriptCall *sc) { 634 635 MTLaunchStruct mtls; 636 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls); 637 forEachKernelSetup(slot, &mtls); 638 639 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 640 mCtx->launchThreads(ain, aout, sc, &mtls); 641 mCtx->setTLS(oldTLS); 642} 643 644void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) { 645 mtls->script = this; 646 mtls->fep.slot = slot; 647#ifndef RS_COMPATIBILITY_LIB 648 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size()); 649 mtls->kernel = reinterpret_cast<ForEachFunc_t>( 650 mExecutable->getExportForeachFuncAddrs()[slot]); 651 rsAssert(mtls->kernel != NULL); 652 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second; 653#else 654 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]); 655 rsAssert(mtls->kernel != NULL); 656 mtls->sig = mForEachSignatures[slot]; 657#endif 658} 659 660int RsdCpuScriptImpl::invokeRoot() { 661 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 662 int ret = mRoot(); 663 mCtx->setTLS(oldTLS); 664 return ret; 665} 666 667void RsdCpuScriptImpl::invokeInit() { 668 if (mInit) { 669 mInit(); 670 } 671} 672 673void RsdCpuScriptImpl::invokeFreeChildren() { 674 if (mFreeChildren) { 675 mFreeChildren(); 676 } 677} 678 679void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params, 680 size_t paramLength) { 681 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength); 682 683 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 684 reinterpret_cast<void (*)(const void *, uint32_t)>( 685#ifndef RS_COMPATIBILITY_LIB 686 mExecutable->getExportFuncAddrs()[slot])(params, paramLength); 687#else 688 mInvokeFunctions[slot])(params, paramLength); 689#endif 690 mCtx->setTLS(oldTLS); 691} 692 693void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) { 694 //rsAssert(!script->mFieldIsObject[slot]); 695 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 696 697 //if (mIntrinsicID) { 698 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength); 699 //return; 700 //} 701 702#ifndef RS_COMPATIBILITY_LIB 703 int32_t *destPtr = reinterpret_cast<int32_t *>( 704 mExecutable->getExportVarAddrs()[slot]); 705#else 706 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 707#endif 708 if (!destPtr) { 709 //ALOGV("Calling setVar on slot = %i which is null", slot); 710 return; 711 } 712 713 memcpy(destPtr, data, dataLength); 714} 715 716void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) { 717 //rsAssert(!script->mFieldIsObject[slot]); 718 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 719 720#ifndef RS_COMPATIBILITY_LIB 721 int32_t *srcPtr = reinterpret_cast<int32_t *>( 722 mExecutable->getExportVarAddrs()[slot]); 723#else 724 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 725#endif 726 if (!srcPtr) { 727 //ALOGV("Calling setVar on slot = %i which is null", slot); 728 return; 729 } 730 memcpy(data, srcPtr, dataLength); 731} 732 733 734void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength, 735 const Element *elem, 736 const size_t *dims, size_t dimLength) { 737 738#ifndef RS_COMPATIBILITY_LIB 739 int32_t *destPtr = reinterpret_cast<int32_t *>( 740 mExecutable->getExportVarAddrs()[slot]); 741#else 742 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 743#endif 744 if (!destPtr) { 745 //ALOGV("Calling setVar on slot = %i which is null", slot); 746 return; 747 } 748 749 // We want to look at dimension in terms of integer components, 750 // but dimLength is given in terms of bytes. 751 dimLength /= sizeof(int); 752 753 // Only a single dimension is currently supported. 754 rsAssert(dimLength == 1); 755 if (dimLength == 1) { 756 // First do the increment loop. 757 size_t stride = elem->getSizeBytes(); 758 const char *cVal = reinterpret_cast<const char *>(data); 759 for (size_t i = 0; i < dims[0]; i++) { 760 elem->incRefs(cVal); 761 cVal += stride; 762 } 763 764 // Decrement loop comes after (to prevent race conditions). 765 char *oldVal = reinterpret_cast<char *>(destPtr); 766 for (size_t i = 0; i < dims[0]; i++) { 767 elem->decRefs(oldVal); 768 oldVal += stride; 769 } 770 } 771 772 memcpy(destPtr, data, dataLength); 773} 774 775void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) { 776 777 //rsAssert(!script->mFieldIsObject[slot]); 778 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data); 779 780#ifndef RS_COMPATIBILITY_LIB 781 int32_t *destPtr = reinterpret_cast<int32_t *>( 782 mExecutable->getExportVarAddrs()[slot]); 783#else 784 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 785#endif 786 if (!destPtr) { 787 //ALOGV("Calling setVar on slot = %i which is null", slot); 788 return; 789 } 790 791 void *ptr = NULL; 792 mBoundAllocs[slot] = data; 793 if(data) { 794 ptr = data->mHal.drvState.lod[0].mallocPtr; 795 } 796 memcpy(destPtr, &ptr, sizeof(void *)); 797} 798 799void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) { 800 801 //rsAssert(script->mFieldIsObject[slot]); 802 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data); 803 804 //if (mIntrinsicID) { 805 //mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot, alloc); 806 //return; 807 //} 808 809#ifndef RS_COMPATIBILITY_LIB 810 int32_t *destPtr = reinterpret_cast<int32_t *>( 811 mExecutable->getExportVarAddrs()[slot]); 812#else 813 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 814#endif 815 if (!destPtr) { 816 //ALOGV("Calling setVar on slot = %i which is null", slot); 817 return; 818 } 819 820 rsrSetObject(mCtx->getContext(), (ObjectBase **)destPtr, data); 821} 822 823RsdCpuScriptImpl::~RsdCpuScriptImpl() { 824#ifndef RS_COMPATIBILITY_LIB 825 if (mExecutable) { 826 Vector<void *>::const_iterator var_addr_iter = 827 mExecutable->getExportVarAddrs().begin(); 828 Vector<void *>::const_iterator var_addr_end = 829 mExecutable->getExportVarAddrs().end(); 830 831 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter = 832 mExecutable->getInfo().getObjectSlots().begin(); 833 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end = 834 mExecutable->getInfo().getObjectSlots().end(); 835 836 while ((var_addr_iter != var_addr_end) && 837 (is_object_iter != is_object_end)) { 838 // The field address can be NULL if the script-side has optimized 839 // the corresponding global variable away. 840 ObjectBase **obj_addr = 841 reinterpret_cast<ObjectBase **>(*var_addr_iter); 842 if (*is_object_iter) { 843 if (*var_addr_iter != NULL) { 844 rsrClearObject(mCtx->getContext(), obj_addr); 845 } 846 } 847 var_addr_iter++; 848 is_object_iter++; 849 } 850 } 851 852 if (mCompilerContext) { 853 delete mCompilerContext; 854 } 855 if (mCompilerDriver) { 856 delete mCompilerDriver; 857 } 858 if (mExecutable) { 859 delete mExecutable; 860 } 861 if (mBoundAllocs) { 862 delete[] mBoundAllocs; 863 } 864#else 865 if (mFieldIsObject) { 866 for (size_t i = 0; i < mExportedVariableCount; ++i) { 867 if (mFieldIsObject[i]) { 868 if (mFieldAddress[i] != NULL) { 869 ObjectBase **obj_addr = 870 reinterpret_cast<ObjectBase **>(mFieldAddress[i]); 871 rsrClearObject(mCtx->getContext(), obj_addr); 872 } 873 } 874 } 875 } 876 877 if (mInvokeFunctions) delete[] mInvokeFunctions; 878 if (mForEachFunctions) delete[] mForEachFunctions; 879 if (mFieldAddress) delete[] mFieldAddress; 880 if (mFieldIsObject) delete[] mFieldIsObject; 881 if (mForEachSignatures) delete[] mForEachSignatures; 882 if (mBoundAllocs) delete[] mBoundAllocs; 883 if (mScriptSO) { 884 dlclose(mScriptSO); 885 } 886#endif 887} 888 889Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const { 890 if (!ptr) { 891 return NULL; 892 } 893 894 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) { 895 Allocation *a = mBoundAllocs[ct]; 896 if (!a) continue; 897 if (a->mHal.drvState.lod[0].mallocPtr == ptr) { 898 return a; 899 } 900 } 901 ALOGE("rsGetAllocation, failed to find %p", ptr); 902 return NULL; 903} 904 905 906} 907} 908