rsScriptC.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Copyright (C) 2009-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. #include "rsContext.h"
  17. #include "rsScriptC.h"
  18. #if !defined(RS_COMPATIBILITY_LIB) && !defined(ANDROID_RS_SERIALIZE)
  19. #include <bcinfo/BitcodeTranslator.h>
  20. #include <bcinfo/BitcodeWrapper.h>
  21. #endif
  22. #include <sys/stat.h>
  23. #include <sstream>
  24. #include <string>
  25. #ifdef _WIN32
  26. /* Define the default path separator for the platform. */
  27. #define OS_PATH_SEPARATOR '\\'
  28. #define OS_PATH_SEPARATOR_STR "\\"
  29. #else /* not _WIN32 */
  30. /* Define the default path separator for the platform. */
  31. #define OS_PATH_SEPARATOR '/'
  32. #define OS_PATH_SEPARATOR_STR "/"
  33. #endif
  34. using android::renderscript::ScriptC;
  35. #define GET_TLS() Context::ScriptTLSStruct * tls = \
  36. (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
  37. Context * rsc = tls->mContext; \
  38. ScriptC * sc = (ScriptC *) tls->mScript
  39. ScriptC::ScriptC(Context *rsc) : Script(rsc) {
  40. }
  41. ScriptC::~ScriptC() {
  42. if (mInitialized) {
  43. mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
  44. mRSC->mHal.funcs.script.destroy(mRSC, this);
  45. }
  46. }
  47. #ifndef RS_COMPATIBILITY_LIB
  48. bool ScriptC::createCacheDir(const char *cacheDir) {
  49. std::string currentDir;
  50. const std::string cacheDirString(cacheDir);
  51. struct stat statBuf;
  52. int statReturn = stat(cacheDir, &statBuf);
  53. if (!statReturn) {
  54. return true;
  55. }
  56. // Start from the beginning of the cacheDirString.
  57. int currPos = 0;
  58. // Reserve space in currentDir for the entire cacheDir path.
  59. currentDir.reserve(cacheDirString.length());
  60. while (currPos >= 0) {
  61. /*
  62. * The character at currPos should be a path separator. We need to look
  63. * for the next one.
  64. */
  65. int nextPos = cacheDirString.find(OS_PATH_SEPARATOR, currPos + 1);
  66. if (nextPos > 0) {
  67. // A new path separator has been found.
  68. currentDir += cacheDirString.substr(currPos, nextPos - currPos);
  69. } else {
  70. // There are no more path separators.
  71. currentDir += cacheDirString.substr(currPos);
  72. }
  73. currPos = nextPos;
  74. statReturn = stat(currentDir.c_str(), &statBuf);
  75. if (statReturn) {
  76. if (errno == ENOENT) {
  77. if (mkdir(currentDir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR)) {
  78. ALOGE("Couldn't create cache directory: %s",
  79. currentDir.c_str());
  80. ALOGE("Error: %s", strerror(errno));
  81. return false;
  82. }
  83. } else {
  84. ALOGE("Stat error: %s", strerror(errno));
  85. return false;
  86. }
  87. }
  88. }
  89. return true;
  90. }
  91. #endif
  92. void ScriptC::setupScript(Context *rsc) {
  93. mEnviroment.mStartTimeMillis
  94. = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
  95. for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
  96. if (mSlots[ct].get() && !mTypes[ct].get()) {
  97. mTypes[ct].set(mSlots[ct]->getType());
  98. }
  99. if (!mTypes[ct].get())
  100. continue;
  101. rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, mSlots[ct].get());
  102. }
  103. }
  104. void ScriptC::setupGLState(Context *rsc) {
  105. #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
  106. if (mEnviroment.mFragmentStore.get()) {
  107. rsc->setProgramStore(mEnviroment.mFragmentStore.get());
  108. }
  109. if (mEnviroment.mFragment.get()) {
  110. rsc->setProgramFragment(mEnviroment.mFragment.get());
  111. }
  112. if (mEnviroment.mVertex.get()) {
  113. rsc->setProgramVertex(mEnviroment.mVertex.get());
  114. }
  115. if (mEnviroment.mRaster.get()) {
  116. rsc->setProgramRaster(mEnviroment.mRaster.get());
  117. }
  118. #endif
  119. }
  120. uint32_t ScriptC::run(Context *rsc) {
  121. if (mHal.info.root == nullptr) {
  122. rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
  123. return 0;
  124. }
  125. setupGLState(rsc);
  126. setupScript(rsc);
  127. uint32_t ret = 0;
  128. if (rsc->props.mLogScripts) {
  129. ALOGV("%p ScriptC::run invoking root, ptr %p", rsc, mHal.info.root);
  130. }
  131. ret = rsc->mHal.funcs.script.invokeRoot(rsc, this);
  132. if (rsc->props.mLogScripts) {
  133. ALOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
  134. }
  135. return ret;
  136. }
  137. void ScriptC::runForEach(Context *rsc,
  138. uint32_t slot,
  139. const Allocation ** ains,
  140. size_t inLen,
  141. Allocation * aout,
  142. const void * usr,
  143. size_t usrBytes,
  144. const RsScriptCall *sc) {
  145. if (slot >= mHal.info.exportedForEachCount) {
  146. rsc->setError(RS_ERROR_BAD_SCRIPT,
  147. "The forEach kernel index is out of bounds");
  148. return;
  149. }
  150. // Trace this function call.
  151. // To avoid overhead we only build the string if tracing is actually
  152. // enabled.
  153. std::stringstream ss;
  154. if (ATRACE_ENABLED()) {
  155. ss << "runForEach slot[" << slot << "]";
  156. }
  157. std::string msgStr(ss.str());
  158. ATRACE_NAME(msgStr.c_str());
  159. if (mRSC->hadFatalError()) return;
  160. Context::PushState ps(rsc);
  161. setupGLState(rsc);
  162. setupScript(rsc);
  163. if (rsc->props.mLogScripts) {
  164. ALOGV("%p ScriptC::runForEach invoking slot %i, ptr %p", rsc, slot, this);
  165. }
  166. if (rsc->mHal.funcs.script.invokeForEachMulti != nullptr) {
  167. rsc->mHal.funcs.script.invokeForEachMulti(rsc, this, slot, ains, inLen,
  168. aout, usr, usrBytes, sc);
  169. } else if (inLen == 1) {
  170. rsc->mHal.funcs.script.invokeForEach(rsc, this, slot, ains[0], aout,
  171. usr, usrBytes, sc);
  172. } else {
  173. rsc->setError(RS_ERROR_FATAL_DRIVER,
  174. "Driver support for multi-input not present");
  175. }
  176. }
  177. void ScriptC::runReduce(Context *rsc, uint32_t slot,
  178. const Allocation ** ains, size_t inLen,
  179. Allocation *aout, const RsScriptCall *sc) {
  180. // TODO: Record the name of the kernel in the tracing information.
  181. ATRACE_CALL();
  182. if (slot >= mHal.info.exportedReduceCount) {
  183. rsc->setError(RS_ERROR_BAD_SCRIPT, "The general reduce kernel index is out of bounds");
  184. return;
  185. }
  186. if (mRSC->hadFatalError()) return;
  187. setupScript(rsc);
  188. if (rsc->props.mLogScripts) {
  189. ALOGV("%p ScriptC::runReduce invoking slot %i, ptr %p", rsc, slot, this);
  190. }
  191. rsc->mHal.funcs.script.invokeReduce(rsc, this, slot, ains, inLen, aout, sc);
  192. }
  193. void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) {
  194. ATRACE_CALL();
  195. if (slot >= mHal.info.exportedFunctionCount) {
  196. rsc->setError(RS_ERROR_BAD_SCRIPT, "The invokable index is out of bounds");
  197. return;
  198. }
  199. if (mRSC->hadFatalError()) return;
  200. setupScript(rsc);
  201. if (rsc->props.mLogScripts) {
  202. ALOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, this);
  203. }
  204. rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len);
  205. }
  206. static const bool kDebugBitcode = false;
  207. #ifndef RS_COMPATIBILITY_LIB
  208. static bool dumpBitcodeFile(const char *cacheDir, const char *resName,
  209. const char *suffix, const uint8_t *bitcode,
  210. size_t bitcodeLen) {
  211. std::string f(cacheDir);
  212. f.append("/");
  213. f.append(resName);
  214. f.append("#");
  215. f.append(suffix);
  216. f.append(".bc");
  217. if (!ScriptC::createCacheDir(cacheDir)) {
  218. return false;
  219. }
  220. FILE *fp = fopen(f.c_str(), "we");
  221. if (!fp) {
  222. ALOGE("Could not open %s", f.c_str());
  223. return false;
  224. }
  225. size_t nWritten = fwrite(bitcode, 1, bitcodeLen, fp);
  226. fclose(fp);
  227. if (nWritten != bitcodeLen) {
  228. ALOGE("Could not write %s", f.c_str());
  229. return false;
  230. }
  231. return true;
  232. }
  233. #endif // !RS_COMPATIBILITY_LIB
  234. bool ScriptC::runCompiler(Context *rsc,
  235. const char *resName,
  236. const char *cacheDir,
  237. const uint8_t *bitcode,
  238. size_t bitcodeLen) {
  239. ATRACE_CALL();
  240. //ALOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
  241. #ifndef RS_COMPATIBILITY_LIB
  242. uint32_t sdkVersion = 0;
  243. bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeLen);
  244. if (!bcWrapper.unwrap()) {
  245. ALOGE("Bitcode is not in proper container format (raw or wrapper)");
  246. return false;
  247. }
  248. if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
  249. sdkVersion = bcWrapper.getTargetAPI();
  250. }
  251. if (sdkVersion == 0) {
  252. // This signals that we didn't have a wrapper containing information
  253. // about the bitcode.
  254. sdkVersion = rsc->getTargetSdkVersion();
  255. }
  256. // Save off the sdkVersion, so that we can handle broken cases later.
  257. // Bug 19734267
  258. mApiLevel = sdkVersion;
  259. bcinfo::BitcodeTranslator BT((const char *)bitcode, bitcodeLen,
  260. sdkVersion);
  261. if (!BT.translate()) {
  262. ALOGE("Failed to translate bitcode from version: %u", sdkVersion);
  263. return false;
  264. }
  265. bitcode = (const uint8_t *) BT.getTranslatedBitcode();
  266. bitcodeLen = BT.getTranslatedBitcodeSize();
  267. if (kDebugBitcode) {
  268. if (!dumpBitcodeFile(cacheDir, resName, "after", bitcode, bitcodeLen)) {
  269. return false;
  270. }
  271. }
  272. // Set the optimization level of bcc to be the same as the
  273. // optimization level used to compile the bitcode.
  274. rsc->setOptLevel(bcWrapper.getOptimizationLevel());
  275. if (!cacheDir) {
  276. // MUST BE FIXED BEFORE ANYTHING USING C++ API IS RELEASED
  277. cacheDir = getenv("EXTERNAL_STORAGE");
  278. ALOGV("Cache dir changed to %s", cacheDir);
  279. }
  280. // ensure that cache dir exists
  281. if (cacheDir && !createCacheDir(cacheDir)) {
  282. return false;
  283. }
  284. #endif
  285. if (!rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0)) {
  286. return false;
  287. }
  288. mInitialized = true;
  289. #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
  290. mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
  291. mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
  292. mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
  293. mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
  294. #endif
  295. rsc->mHal.funcs.script.invokeInit(rsc, this);
  296. for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) {
  297. const char * key = mHal.info.exportedPragmaKeyList[i];
  298. const char * value = mHal.info.exportedPragmaValueList[i];
  299. //ALOGE("pragma %s %s", keys[i], values[i]);
  300. if (!strcmp(key, "version")) {
  301. if (!strcmp(value, "1")) {
  302. continue;
  303. }
  304. ALOGE("Invalid version pragma value: %s\n", value);
  305. return false;
  306. }
  307. #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
  308. if (!strcmp(key, "stateVertex")) {
  309. if (!strcmp(value, "default")) {
  310. continue;
  311. }
  312. if (!strcmp(value, "parent")) {
  313. mEnviroment.mVertex.clear();
  314. continue;
  315. }
  316. ALOGE("Unrecognized value %s passed to stateVertex", value);
  317. return false;
  318. }
  319. if (!strcmp(key, "stateRaster")) {
  320. if (!strcmp(value, "default")) {
  321. continue;
  322. }
  323. if (!strcmp(value, "parent")) {
  324. mEnviroment.mRaster.clear();
  325. continue;
  326. }
  327. ALOGE("Unrecognized value %s passed to stateRaster", value);
  328. return false;
  329. }
  330. if (!strcmp(key, "stateFragment")) {
  331. if (!strcmp(value, "default")) {
  332. continue;
  333. }
  334. if (!strcmp(value, "parent")) {
  335. mEnviroment.mFragment.clear();
  336. continue;
  337. }
  338. ALOGE("Unrecognized value %s passed to stateFragment", value);
  339. return false;
  340. }
  341. if (!strcmp(key, "stateStore")) {
  342. if (!strcmp(value, "default")) {
  343. continue;
  344. }
  345. if (!strcmp(value, "parent")) {
  346. mEnviroment.mFragmentStore.clear();
  347. continue;
  348. }
  349. ALOGE("Unrecognized value %s passed to stateStore", value);
  350. return false;
  351. }
  352. #endif
  353. }
  354. mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount];
  355. mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount];
  356. return true;
  357. }
  358. namespace android {
  359. namespace renderscript {
  360. RsScript rsi_ScriptCCreate(Context *rsc,
  361. const char *resName, size_t resName_length,
  362. const char *cacheDir, size_t cacheDir_length,
  363. const char *text, size_t text_length)
  364. {
  365. ScriptC *s = new ScriptC(rsc);
  366. if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) {
  367. // Error during compile, destroy s and return null.
  368. ObjectBase::checkDelete(s);
  369. return nullptr;
  370. }
  371. s->incUserRef();
  372. return s;
  373. }
  374. } // namespace renderscript
  375. } // namespace android