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