blob: f4abe67facb4abab74e3f8397fbc6340ace6bd91 [file] [log] [blame]
Jason Sams709a0972012-11-15 18:18:04 -08001/*
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
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -07007 *
Jason Sams709a0972012-11-15 18:18:04 -08008 * 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
Jason Sams709a0972012-11-15 18:18:04 -080017#include "rsCpuCore.h"
Jason Sams709a0972012-11-15 18:18:04 -080018#include "rsCpuScript.h"
Jason Sams709a0972012-11-15 18:18:04 -080019
Jason Sams110f1812013-03-14 16:02:18 -070020#ifdef RS_COMPATIBILITY_LIB
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070021 #include <set>
22 #include <string>
Jason Sams110f1812013-03-14 16:02:18 -070023 #include <dlfcn.h>
24 #include <stdio.h>
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070025 #include <stdlib.h>
Jason Sams110f1812013-03-14 16:02:18 -070026 #include <string.h>
Stephen Hinesee48c0b2013-10-30 17:48:30 -070027 #include <sys/stat.h>
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070028 #include <unistd.h>
Stephen Hines7d774852014-10-01 12:57:57 -070029 #include <fstream>
30 #include <iostream>
Jason Sams110f1812013-03-14 16:02:18 -070031#else
32 #include <bcc/BCCContext.h>
Stephen Hines82e0a672014-05-05 15:40:56 -070033 #include <bcc/Config/Config.h>
Jason Sams110f1812013-03-14 16:02:18 -070034 #include <bcc/Renderscript/RSCompilerDriver.h>
35 #include <bcc/Renderscript/RSExecutable.h>
36 #include <bcc/Renderscript/RSInfo.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070037 #include <bcinfo/MetadataExtractor.h>
Stephen Hinesba17ae42013-06-05 17:18:04 -070038 #include <cutils/properties.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070039
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <unistd.h>
Stephen Hines00511322014-01-31 11:20:23 -080043
44 #include <string>
45 #include <vector>
Jason Sams110f1812013-03-14 16:02:18 -070046#endif
Jason Sams709a0972012-11-15 18:18:04 -080047
Stephen Hinesba17ae42013-06-05 17:18:04 -070048namespace {
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070049#ifdef RS_COMPATIBILITY_LIB
50
51// Create a len length string containing random characters from [A-Za-z0-9].
52static std::string getRandomString(size_t len) {
53 char buf[len + 1];
54 for (size_t i = 0; i < len; i++) {
55 uint32_t r = arc4random() & 0xffff;
56 r %= 62;
57 if (r < 26) {
58 // lowercase
59 buf[i] = 'a' + r;
60 } else if (r < 52) {
61 // uppercase
62 buf[i] = 'A' + (r - 26);
63 } else {
64 // Use a number
65 buf[i] = '0' + (r - 52);
66 }
67 }
68 buf[len] = '\0';
69 return std::string(buf);
70}
71
Stephen Hinesee48c0b2013-10-30 17:48:30 -070072// Check if a path exists and attempt to create it if it doesn't.
73static bool ensureCacheDirExists(const char *path) {
74 if (access(path, R_OK | W_OK | X_OK) == 0) {
75 // Done if we can rwx the directory
76 return true;
77 }
78 if (mkdir(path, 0700) == 0) {
79 return true;
80 }
81 return false;
82}
83
Stephen Hines7d774852014-10-01 12:57:57 -070084// Copy the file named \p srcFile to \p dstFile.
85// Return 0 on success and -1 if anything wasn't copied.
86static int copyFile(const char *dstFile, const char *srcFile) {
87 std::ifstream srcStream(srcFile);
88 if (!srcStream) {
89 ALOGE("Could not verify or read source file: %s", srcFile);
90 return -1;
91 }
92 std::ofstream dstStream(dstFile);
93 if (!dstStream) {
94 ALOGE("Could not verify or write destination file: %s", dstFile);
95 return -1;
96 }
97 dstStream << srcStream.rdbuf();
98 if (!dstStream) {
99 ALOGE("Could not write destination file: %s", dstFile);
100 return -1;
101 }
102
103 srcStream.close();
104 dstStream.close();
105
106 return 0;
107}
108
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700109// Attempt to load the shared library from origName, but then fall back to
Stephen Hines7d774852014-10-01 12:57:57 -0700110// creating a copy of the shared library if necessary (to ensure instancing).
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700111// This function returns the dlopen()-ed handle if successful.
112static void *loadSOHelper(const char *origName, const char *cacheDir,
113 const char *resName) {
114 // Keep track of which .so libraries have been loaded. Once a library is
Stephen Hines7d774852014-10-01 12:57:57 -0700115 // in the set (per-process granularity), we must instead make a copy of
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700116 // the original shared object (randomly named .so file) and load that one
117 // instead. If we don't do this, we end up aliasing global data between
118 // the various Script instances (which are supposed to be completely
119 // independent).
120 static std::set<std::string> LoadedLibraries;
121
Chris Wailes44bef6f2014-08-12 13:51:10 -0700122 void *loaded = nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700123
124 // Skip everything if we don't even have the original library available.
125 if (access(origName, F_OK) != 0) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700126 return nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700127 }
128
129 // Common path is that we have not loaded this Script/library before.
130 if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
131 loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
132 if (loaded) {
133 LoadedLibraries.insert(origName);
134 }
135 return loaded;
136 }
137
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700138 std::string newName(cacheDir);
Stephen Hinesee48c0b2013-10-30 17:48:30 -0700139 newName.append("/com.android.renderscript.cache/");
140
141 if (!ensureCacheDirExists(newName.c_str())) {
142 ALOGE("Could not verify or create cache dir: %s", cacheDir);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700143 return nullptr;
Stephen Hinesee48c0b2013-10-30 17:48:30 -0700144 }
145
Stephen Hines7d774852014-10-01 12:57:57 -0700146 // Construct an appropriately randomized filename for the copy.
Stephen Hinesee48c0b2013-10-30 17:48:30 -0700147 newName.append("librs.");
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700148 newName.append(resName);
149 newName.append("#");
150 newName.append(getRandomString(6)); // 62^6 potential filename variants.
151 newName.append(".so");
152
Stephen Hines7d774852014-10-01 12:57:57 -0700153 int r = copyFile(newName.c_str(), origName);
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700154 if (r != 0) {
Stephen Hines7d774852014-10-01 12:57:57 -0700155 ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
Chris Wailes44bef6f2014-08-12 13:51:10 -0700156 return nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700157 }
158 loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
159 r = unlink(newName.c_str());
160 if (r != 0) {
Stephen Hines7d774852014-10-01 12:57:57 -0700161 ALOGE("Could not unlink copy %s", newName.c_str());
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700162 }
163 if (loaded) {
164 LoadedLibraries.insert(newName.c_str());
165 }
166
167 return loaded;
168}
169
170// Load the shared library referred to by cacheDir and resName. If we have
Stephen Hines7d774852014-10-01 12:57:57 -0700171// already loaded this library, we instead create a new copy (in the
172// cache dir) and then load that. We then immediately destroy the copy.
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700173// This is required behavior to implement script instancing for the support
174// library, since shared objects are loaded and de-duped by name only.
175static void *loadSharedLibrary(const char *cacheDir, const char *resName) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700176 void *loaded = nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700177#ifndef RS_SERVER
178 std::string scriptSOName(cacheDir);
179 size_t cutPos = scriptSOName.rfind("cache");
180 if (cutPos != std::string::npos) {
181 scriptSOName.erase(cutPos);
182 } else {
183 ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
184 }
185 scriptSOName.append("/lib/librs.");
186#else
187 std::string scriptSOName("lib");
188#endif
189 scriptSOName.append(resName);
190 scriptSOName.append(".so");
191
192 // We should check if we can load the library from the standard app
193 // location for shared libraries first.
194 loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
195
Chris Wailes44bef6f2014-08-12 13:51:10 -0700196 if (loaded == nullptr) {
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700197 ALOGE("Unable to open shared library (%s): %s",
198 scriptSOName.c_str(), dlerror());
199
200 // One final attempt to find the library in "/system/lib".
201 // We do this to allow bundled applications to use the compatibility
202 // library fallback path. Those applications don't have a private
203 // library path, so they need to install to the system directly.
204 // Note that this is really just a testing path.
Chris Wailes93d6bc82014-07-28 16:54:38 -0700205 std::string scriptSONameSystem("/system/lib/librs.");
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700206 scriptSONameSystem.append(resName);
207 scriptSONameSystem.append(".so");
208 loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
209 resName);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700210 if (loaded == nullptr) {
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700211 ALOGE("Unable to open system shared library (%s): %s",
212 scriptSONameSystem.c_str(), dlerror());
213 }
214 }
215
216 return loaded;
217}
218
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700219#else // RS_COMPATIBILITY_LIB is not defined
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700220
Stephen Hinesba17ae42013-06-05 17:18:04 -0700221static bool is_force_recompile() {
222#ifdef RS_SERVER
223 return false;
224#else
225 char buf[PROPERTY_VALUE_MAX];
226
227 // Re-compile if floating point precision has been overridden.
228 property_get("debug.rs.precision", buf, "");
229 if (buf[0] != '\0') {
230 return true;
231 }
232
233 // Re-compile if debug.rs.forcerecompile is set.
234 property_get("debug.rs.forcerecompile", buf, "0");
235 if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
236 return true;
237 } else {
238 return false;
239 }
240#endif // RS_SERVER
241}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700242
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700243const static char *BCC_EXE_PATH = "/system/bin/bcc";
244
Chris Wailes6847e732014-08-11 17:30:51 -0700245static void setCompileArguments(std::vector<const char*>* args,
246 const std::string& bcFileName,
247 const char* cacheDir, const char* resName,
248 const char* core_lib, bool useRSDebugContext,
249 const char* bccPluginName) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700250 rsAssert(cacheDir && resName && core_lib);
251 args->push_back(BCC_EXE_PATH);
252 args->push_back("-o");
253 args->push_back(resName);
254 args->push_back("-output_path");
255 args->push_back(cacheDir);
256 args->push_back("-bclib");
257 args->push_back(core_lib);
258 args->push_back("-mtriple");
259 args->push_back(DEFAULT_TARGET_TRIPLE_STRING);
260
261 // Execute the bcc compiler.
262 if (useRSDebugContext) {
263 args->push_back("-rs-debug-ctx");
264 } else {
265 // Only load additional libraries for compiles that don't use
266 // the debug context.
267 if (bccPluginName && strlen(bccPluginName) > 0) {
268 args->push_back("-load");
269 args->push_back(bccPluginName);
270 }
271 }
272
Chris Wailes6847e732014-08-11 17:30:51 -0700273 args->push_back(bcFileName.c_str());
Chris Wailes44bef6f2014-08-12 13:51:10 -0700274 args->push_back(nullptr);
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700275}
276
Chris Wailes6847e732014-08-11 17:30:51 -0700277static bool compileBitcode(const std::string &bcFileName,
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700278 const char *bitcode,
279 size_t bitcodeSize,
Chris Wailes6847e732014-08-11 17:30:51 -0700280 const char **compileArguments,
281 const std::string &compileCommandLine) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700282 rsAssert(bitcode && bitcodeSize);
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700283
Chris Wailes6847e732014-08-11 17:30:51 -0700284 FILE *bcfile = fopen(bcFileName.c_str(), "w");
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700285 if (!bcfile) {
Chris Wailes6847e732014-08-11 17:30:51 -0700286 ALOGE("Could not write to %s", bcFileName.c_str());
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700287 return false;
288 }
289 size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
290 fclose(bcfile);
291 if (nwritten != bitcodeSize) {
292 ALOGE("Could not write %zu bytes to %s", bitcodeSize,
Chris Wailes6847e732014-08-11 17:30:51 -0700293 bcFileName.c_str());
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700294 return false;
295 }
296
297 pid_t pid = fork();
Stephen Hines00511322014-01-31 11:20:23 -0800298
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700299 switch (pid) {
300 case -1: { // Error occurred (we attempt no recovery)
301 ALOGE("Couldn't fork for bcc compiler execution");
302 return false;
303 }
304 case 0: { // Child process
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700305 ALOGV("Invoking BCC with: %s", compileCommandLine.c_str());
306 execv(BCC_EXE_PATH, (char* const*)compileArguments);
Stephen Hines00511322014-01-31 11:20:23 -0800307
Stephen Hines00511322014-01-31 11:20:23 -0800308 ALOGE("execv() failed: %s", strerror(errno));
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700309 abort();
310 return false;
311 }
312 default: { // Parent process (actual driver)
313 // Wait on child process to finish compiling the source.
314 int status = 0;
315 pid_t w = waitpid(pid, &status, 0);
316 if (w == -1) {
317 ALOGE("Could not wait for bcc compiler");
318 return false;
319 }
320
321 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
322 return true;
323 }
324
325 ALOGE("bcc compiler terminated unexpectedly");
326 return false;
327 }
328 }
329}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700330
Stephen Hinesba17ae42013-06-05 17:18:04 -0700331#endif // !defined(RS_COMPATIBILITY_LIB)
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700332} // namespace
Stephen Hinesba17ae42013-06-05 17:18:04 -0700333
Jason Sams709a0972012-11-15 18:18:04 -0800334namespace android {
335namespace renderscript {
336
Jason Sams110f1812013-03-14 16:02:18 -0700337#ifdef RS_COMPATIBILITY_LIB
338#define MAXLINE 500
339#define MAKE_STR_HELPER(S) #S
340#define MAKE_STR(S) MAKE_STR_HELPER(S)
341#define EXPORT_VAR_STR "exportVarCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700342#define EXPORT_FUNC_STR "exportFuncCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700343#define EXPORT_FOREACH_STR "exportForEachCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700344#define OBJECT_SLOT_STR "objectSlotCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700345
346// Copy up to a newline or size chars from str -> s, updating str
Chris Wailes44bef6f2014-08-12 13:51:10 -0700347// Returns s when successful and nullptr when '\0' is finally reached.
Jason Sams110f1812013-03-14 16:02:18 -0700348static char* strgets(char *s, int size, const char **ppstr) {
349 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700350 return nullptr;
Jason Sams110f1812013-03-14 16:02:18 -0700351 }
352
353 int i;
354 for (i = 0; i < (size - 1); i++) {
355 s[i] = **ppstr;
356 (*ppstr)++;
357 if (s[i] == '\0') {
358 return s;
359 } else if (s[i] == '\n') {
360 s[i+1] = '\0';
361 return s;
362 }
363 }
364
365 // size has been exceeded.
366 s[i] = '\0';
367
368 return s;
369}
370#endif
Jason Sams709a0972012-11-15 18:18:04 -0800371
372RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
373 mCtx = ctx;
374 mScript = s;
375
Jason Sams110f1812013-03-14 16:02:18 -0700376#ifdef RS_COMPATIBILITY_LIB
Chris Wailes44bef6f2014-08-12 13:51:10 -0700377 mScriptSO = nullptr;
378 mInvokeFunctions = nullptr;
379 mForEachFunctions = nullptr;
380 mFieldAddress = nullptr;
381 mFieldIsObject = nullptr;
382 mForEachSignatures = nullptr;
Jason Sams110f1812013-03-14 16:02:18 -0700383#else
Chris Wailes44bef6f2014-08-12 13:51:10 -0700384 mCompilerContext = nullptr;
385 mCompilerDriver = nullptr;
386 mExecutable = nullptr;
Jason Sams110f1812013-03-14 16:02:18 -0700387#endif
388
Tim Murraye195a3f2014-03-13 15:04:58 -0700389
Chris Wailes44bef6f2014-08-12 13:51:10 -0700390 mRoot = nullptr;
391 mRootExpand = nullptr;
392 mInit = nullptr;
393 mFreeChildren = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -0800394
Jason Sams709a0972012-11-15 18:18:04 -0800395
Chris Wailes44bef6f2014-08-12 13:51:10 -0700396 mBoundAllocs = nullptr;
397 mIntrinsicData = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -0800398 mIsThreadable = true;
399}
400
401
402bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
403 uint8_t const *bitcode, size_t bitcodeSize,
Stephen Hines00511322014-01-31 11:20:23 -0800404 uint32_t flags, char const *bccPluginName) {
Jason Sams709a0972012-11-15 18:18:04 -0800405 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
406 //ALOGE("rsdScriptInit %p %p", rsc, script);
407
408 mCtx->lockMutex();
Jason Sams110f1812013-03-14 16:02:18 -0700409#ifndef RS_COMPATIBILITY_LIB
Stephen Hines00511322014-01-31 11:20:23 -0800410 bool useRSDebugContext = false;
Jason Sams709a0972012-11-15 18:18:04 -0800411
Chris Wailes44bef6f2014-08-12 13:51:10 -0700412 mCompilerContext = nullptr;
413 mCompilerDriver = nullptr;
414 mExecutable = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -0800415
416 mCompilerContext = new bcc::BCCContext();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700417 if (mCompilerContext == nullptr) {
Jason Sams709a0972012-11-15 18:18:04 -0800418 ALOGE("bcc: FAILS to create compiler context (out of memory)");
419 mCtx->unlockMutex();
420 return false;
421 }
422
423 mCompilerDriver = new bcc::RSCompilerDriver();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700424 if (mCompilerDriver == nullptr) {
Jason Sams709a0972012-11-15 18:18:04 -0800425 ALOGE("bcc: FAILS to create compiler driver (out of memory)");
426 mCtx->unlockMutex();
427 return false;
428 }
429
Stephen Hines25e3af52014-05-21 21:23:08 -0700430 // Configure symbol resolvers (via compiler-rt and the RS runtime).
431 mRSRuntime.setLookupFunction(lookupRuntimeStub);
432 mRSRuntime.setContext(this);
433 mResolver.chainResolver(mCompilerRuntime);
434 mResolver.chainResolver(mRSRuntime);
Jason Sams709a0972012-11-15 18:18:04 -0800435
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700436 // Run any compiler setup functions we have been provided with.
437 RSSetupCompilerCallback setupCompilerCallback =
438 mCtx->getSetupCompilerCallback();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700439 if (setupCompilerCallback != nullptr) {
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700440 setupCompilerCallback(mCompilerDriver);
441 }
442
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700443 bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize);
444 if (!bitcodeMetadata.extract()) {
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700445 ALOGE("Could not extract metadata from bitcode");
Stephen Hinesf94e8db2014-06-26 11:55:29 -0700446 mCtx->unlockMutex();
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700447 return false;
448 }
449
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700450 const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize);
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700451
452 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
Stephen Hinesf47e8b42013-04-18 01:06:29 -0700453 mCompilerDriver->setDebugContext(true);
Stephen Hines00511322014-01-31 11:20:23 -0800454 useRSDebugContext = true;
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700455 }
Stephen Hinesba17ae42013-06-05 17:18:04 -0700456
Chris Wailes6847e732014-08-11 17:30:51 -0700457 std::string bcFileName(cacheDir);
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700458 bcFileName.append("/");
459 bcFileName.append(resName);
460 bcFileName.append(".bc");
461
462 std::vector<const char*> compileArguments;
463 setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
464 useRSDebugContext, bccPluginName);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700465 // The last argument of compileArguments ia a nullptr, so remove 1 from the size.
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700466 std::string compileCommandLine =
467 bcc::getCommandLine(compileArguments.size() - 1, compileArguments.data());
468
469 if (!is_force_recompile()) {
470 // Load the compiled script that's in the cache, if any.
471 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
472 bitcodeSize, compileCommandLine.c_str(),
473 mResolver);
474 }
475
476 // If we can't, it's either not there or out of date. We compile the bit code and try loading
477 // again.
Chris Wailes44bef6f2014-08-12 13:51:10 -0700478 if (mExecutable == nullptr) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700479 if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments.data(),
480 compileCommandLine)) {
481 ALOGE("bcc: FAILS to compile '%s'", resName);
482 mCtx->unlockMutex();
483 return false;
484 }
485 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
486 bitcodeSize, compileCommandLine.c_str(),
487 mResolver);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700488 if (mExecutable == nullptr) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700489 ALOGE("bcc: FAILS to load freshly compiled executable for '%s'", resName);
490 mCtx->unlockMutex();
491 return false;
Stephen Hinesba17ae42013-06-05 17:18:04 -0700492 }
493 }
Jason Sams709a0972012-11-15 18:18:04 -0800494
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700495 mExecutable->setThreadable(mIsThreadable);
496 if (!mExecutable->syncInfo()) {
Jason Sams709a0972012-11-15 18:18:04 -0800497 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
498 }
499
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700500 mRoot = reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root"));
Jason Sams709a0972012-11-15 18:18:04 -0800501 mRootExpand =
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700502 reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root.expand"));
503 mInit = reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress("init"));
Jason Sams709a0972012-11-15 18:18:04 -0800504 mFreeChildren =
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700505 reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress(".rs.dtor"));
Jason Sams709a0972012-11-15 18:18:04 -0800506
507
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700508 if (bitcodeMetadata.getExportVarCount()) {
509 mBoundAllocs = new Allocation *[bitcodeMetadata.getExportVarCount()];
510 memset(mBoundAllocs, 0, sizeof(void *) * bitcodeMetadata.getExportVarCount());
Tim Murray29809d12014-05-28 12:04:19 -0700511 }
512
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700513 for (size_t i = 0; i < bitcodeMetadata.getExportForEachSignatureCount(); i++) {
514 char* name = new char[strlen(bitcodeMetadata.getExportForEachNameList()[i]) + 1];
515 mExportedForEachFuncList.push_back(
516 std::make_pair(name, bitcodeMetadata.getExportForEachSignatureList()[i]));
Jason Sams709a0972012-11-15 18:18:04 -0800517 }
518
Jean-Luc Brouilletf4d216e2014-06-09 18:04:16 -0700519#else // RS_COMPATIBILITY_LIB is defined
Jason Sams110f1812013-03-14 16:02:18 -0700520
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700521 mScriptSO = loadSharedLibrary(cacheDir, resName);
Jason Sams110f1812013-03-14 16:02:18 -0700522
523 if (mScriptSO) {
524 char line[MAXLINE];
525 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
526 if (mRoot) {
527 //ALOGE("Found root(): %p", mRoot);
528 }
529 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
530 if (mRootExpand) {
531 //ALOGE("Found root.expand(): %p", mRootExpand);
532 }
533 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
534 if (mInit) {
535 //ALOGE("Found init(): %p", mInit);
536 }
537 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
538 if (mFreeChildren) {
539 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
540 }
541
542 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
543 if (rsInfo) {
544 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
545 }
546
547 size_t varCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700548 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700549 goto error;
550 }
551 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
552 ALOGE("Invalid export var count!: %s", line);
553 goto error;
554 }
555
556 mExportedVariableCount = varCount;
557 //ALOGE("varCount: %zu", varCount);
558 if (varCount > 0) {
559 // Start by creating/zeroing this member, since we don't want to
560 // accidentally clean up invalid pointers later (if we error out).
561 mFieldIsObject = new bool[varCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700562 if (mFieldIsObject == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700563 goto error;
564 }
565 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
566 mFieldAddress = new void*[varCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700567 if (mFieldAddress == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700568 goto error;
569 }
570 for (size_t i = 0; i < varCount; ++i) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700571 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700572 goto error;
573 }
574 char *c = strrchr(line, '\n');
575 if (c) {
576 *c = '\0';
577 }
578 mFieldAddress[i] = dlsym(mScriptSO, line);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700579 if (mFieldAddress[i] == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700580 ALOGE("Failed to find variable address for %s: %s",
581 line, dlerror());
582 // Not a critical error if we don't find a global variable.
583 }
584 else {
585 //ALOGE("Found variable %s at %p", line,
586 //mFieldAddress[i]);
587 }
588 }
589 }
590
591 size_t funcCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700592 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700593 goto error;
594 }
595 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
596 ALOGE("Invalid export func count!: %s", line);
597 goto error;
598 }
599
600 mExportedFunctionCount = funcCount;
601 //ALOGE("funcCount: %zu", funcCount);
602
603 if (funcCount > 0) {
604 mInvokeFunctions = new InvokeFunc_t[funcCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700605 if (mInvokeFunctions == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700606 goto error;
607 }
608 for (size_t i = 0; i < funcCount; ++i) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700609 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700610 goto error;
611 }
612 char *c = strrchr(line, '\n');
613 if (c) {
614 *c = '\0';
615 }
616
617 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700618 if (mInvokeFunctions[i] == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700619 ALOGE("Failed to get function address for %s(): %s",
620 line, dlerror());
621 goto error;
622 }
623 else {
624 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
625 }
626 }
627 }
628
629 size_t forEachCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700630 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700631 goto error;
632 }
633 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
634 ALOGE("Invalid export forEach count!: %s", line);
635 goto error;
636 }
637
638 if (forEachCount > 0) {
639
640 mForEachSignatures = new uint32_t[forEachCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700641 if (mForEachSignatures == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700642 goto error;
643 }
644 mForEachFunctions = new ForEachFunc_t[forEachCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700645 if (mForEachFunctions == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700646 goto error;
647 }
648 for (size_t i = 0; i < forEachCount; ++i) {
649 unsigned int tmpSig = 0;
650 char tmpName[MAXLINE];
651
Chris Wailes44bef6f2014-08-12 13:51:10 -0700652 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700653 goto error;
654 }
655 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
656 &tmpSig, tmpName) != 2) {
657 ALOGE("Invalid export forEach!: %s", line);
658 goto error;
659 }
660
661 // Lookup the expanded ForEach kernel.
662 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
663 mForEachSignatures[i] = tmpSig;
664 mForEachFunctions[i] =
665 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700666 if (i != 0 && mForEachFunctions[i] == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700667 // Ignore missing root.expand functions.
668 // root() is always specified at location 0.
Stephen Hinesef7481e2013-04-09 19:05:27 -0700669 ALOGE("Failed to find forEach function address for %s: %s",
670 tmpName, dlerror());
671 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700672 }
673 else {
674 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
675 }
676 }
677 }
678
679 size_t objectSlotCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700680 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700681 goto error;
682 }
683 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
684 ALOGE("Invalid object slot count!: %s", line);
685 goto error;
686 }
687
688 if (objectSlotCount > 0) {
689 rsAssert(varCount > 0);
690 for (size_t i = 0; i < objectSlotCount; ++i) {
691 uint32_t varNum = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700692 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700693 goto error;
694 }
695 if (sscanf(line, "%u", &varNum) != 1) {
696 ALOGE("Invalid object slot!: %s", line);
697 goto error;
698 }
699
700 if (varNum < varCount) {
701 mFieldIsObject[varNum] = true;
702 }
703 }
704 }
705
706 if (varCount > 0) {
707 mBoundAllocs = new Allocation *[varCount];
708 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
709 }
710
711 if (mScriptSO == (void*)1) {
712 //rsdLookupRuntimeStub(script, "acos");
713 }
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700714 } else {
715 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700716 }
717#endif
Jason Sams709a0972012-11-15 18:18:04 -0800718 mCtx->unlockMutex();
719 return true;
Jason Sams110f1812013-03-14 16:02:18 -0700720
721#ifdef RS_COMPATIBILITY_LIB
722error:
723
724 mCtx->unlockMutex();
725 delete[] mInvokeFunctions;
726 delete[] mForEachFunctions;
727 delete[] mFieldAddress;
728 delete[] mFieldIsObject;
729 delete[] mForEachSignatures;
730 delete[] mBoundAllocs;
731 if (mScriptSO) {
732 dlclose(mScriptSO);
733 }
734 return false;
735#endif
Jason Sams709a0972012-11-15 18:18:04 -0800736}
737
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700738#ifndef RS_COMPATIBILITY_LIB
739
740#ifdef __LP64__
741#define SYSLIBPATH "/system/lib64"
742#else
743#define SYSLIBPATH "/system/lib"
744#endif
745
746const char* RsdCpuScriptImpl::findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode,
747 size_t bitcodeSize) {
748 const char* defaultLib = SYSLIBPATH"/libclcore.bc";
749
750 // If we're debugging, use the debug library.
751 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
752 return SYSLIBPATH"/libclcore_debug.bc";
753 }
754
755 // If a callback has been registered to specify a library, use that.
756 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700757 if (selectRTCallback != nullptr) {
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700758 return selectRTCallback((const char*)bitcode, bitcodeSize);
759 }
760
761 // Check for a platform specific library
762#if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_CLCORE_NEON)
763 enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
Jean-Luc Brouilletf4d38362014-07-09 17:46:03 -0700764 if (prec == bcinfo::RS_FP_Relaxed) {
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700765 // NEON-capable ARMv7a devices can use an accelerated math library
766 // for all reduced precision scripts.
767 // ARMv8 does not use NEON, as ASIMD can be used with all precision
768 // levels.
769 return SYSLIBPATH"/libclcore_neon.bc";
770 } else {
771 return defaultLib;
772 }
773#elif defined(__i386__) || defined(__x86_64__)
774 // x86 devices will use an optimized library.
775 return SYSLIBPATH"/libclcore_x86.bc";
776#else
777 return defaultLib;
778#endif
779}
780
781#endif
782
Jason Sams709a0972012-11-15 18:18:04 -0800783void RsdCpuScriptImpl::populateScript(Script *script) {
Jason Sams110f1812013-03-14 16:02:18 -0700784#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800785 // Copy info over to runtime
Tim Murray29809d12014-05-28 12:04:19 -0700786 script->mHal.info.exportedFunctionCount = mExecutable->getExportFuncAddrs().size();
787 script->mHal.info.exportedVariableCount = mExecutable->getExportVarAddrs().size();
788 script->mHal.info.exportedForeachFuncList = &mExportedForEachFuncList[0];
789 script->mHal.info.exportedPragmaCount = mExecutable->getPragmaKeys().size();
Jason Sams709a0972012-11-15 18:18:04 -0800790 script->mHal.info.exportedPragmaKeyList =
Chris Wailes70d49712014-08-08 14:42:33 -0700791 const_cast<const char**>(&mExecutable->getPragmaKeys().front());
Jason Sams709a0972012-11-15 18:18:04 -0800792 script->mHal.info.exportedPragmaValueList =
Chris Wailes70d49712014-08-08 14:42:33 -0700793 const_cast<const char**>(&mExecutable->getPragmaValues().front());
Jason Sams709a0972012-11-15 18:18:04 -0800794
795 if (mRootExpand) {
796 script->mHal.info.root = mRootExpand;
797 } else {
798 script->mHal.info.root = mRoot;
799 }
Jason Sams110f1812013-03-14 16:02:18 -0700800#else
801 // Copy info over to runtime
802 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
803 script->mHal.info.exportedVariableCount = mExportedVariableCount;
804 script->mHal.info.exportedPragmaCount = 0;
805 script->mHal.info.exportedPragmaKeyList = 0;
806 script->mHal.info.exportedPragmaValueList = 0;
807
808 // Bug, need to stash in metadata
809 if (mRootExpand) {
810 script->mHal.info.root = mRootExpand;
811 } else {
812 script->mHal.info.root = mRoot;
813 }
814#endif
Jason Sams709a0972012-11-15 18:18:04 -0800815}
816
Jason Sams709a0972012-11-15 18:18:04 -0800817
818typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
819
Chris Wailesf3712132014-07-16 15:18:30 -0700820void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation ** ains,
821 uint32_t inLen,
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700822 Allocation * aout,
823 const void * usr, uint32_t usrLen,
824 const RsScriptCall *sc,
825 MTLaunchStruct *mtls) {
826
827 memset(mtls, 0, sizeof(MTLaunchStruct));
828
Chris Wailesf3712132014-07-16 15:18:30 -0700829 for (int index = inLen; --index >= 0;) {
830 const Allocation* ain = ains[index];
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700831
Chris Wailesf3712132014-07-16 15:18:30 -0700832 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
Chris Wailes44bef6f2014-08-12 13:51:10 -0700833 if (ain != nullptr &&
834 (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == nullptr) {
835
Chris Wailesf3712132014-07-16 15:18:30 -0700836 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
837 "rsForEach called with null in allocations");
838 return;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700839 }
840 }
841
Chris Wailes44bef6f2014-08-12 13:51:10 -0700842 if (aout &&
843 (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == nullptr) {
844
Chris Wailesf3712132014-07-16 15:18:30 -0700845 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
846 "rsForEach called with null out allocations");
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700847 return;
848 }
849
Chris Wailesf3712132014-07-16 15:18:30 -0700850 if (inLen > 0) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700851 const Allocation *ain0 = ains[0];
852 const Type *inType = ain0->getType();
853
854 mtls->fep.dimX = inType->getDimX();
855 mtls->fep.dimY = inType->getDimY();
856 mtls->fep.dimZ = inType->getDimZ();
857
858 for (int Index = inLen; --Index >= 1;) {
859 if (!ain0->hasSameDims(ains[Index])) {
860 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
861 "Failed to launch kernel; dimensions of input and output allocations do not match.");
862
863 return;
864 }
865 }
866
Chris Wailes44bef6f2014-08-12 13:51:10 -0700867 } else if (aout != nullptr) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700868 const Type *outType = aout->getType();
869
870 mtls->fep.dimX = outType->getDimX();
871 mtls->fep.dimY = outType->getDimY();
872 mtls->fep.dimZ = outType->getDimZ();
873
874 } else {
Chris Wailesf3712132014-07-16 15:18:30 -0700875 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
876 "rsForEach called with null allocations");
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700877 return;
878 }
879
Chris Wailes44bef6f2014-08-12 13:51:10 -0700880 if (inLen > 0 && aout != nullptr) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700881 if (!ains[0]->hasSameDims(aout)) {
882 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
883 "Failed to launch kernel; dimensions of input and output allocations do not match.");
884
885 return;
886 }
887 }
888
889 if (!sc || (sc->xEnd == 0)) {
890 mtls->xEnd = mtls->fep.dimX;
891 } else {
892 rsAssert(sc->xStart < mtls->fep.dimX);
893 rsAssert(sc->xEnd <= mtls->fep.dimX);
894 rsAssert(sc->xStart < sc->xEnd);
895 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
896 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
897 if (mtls->xStart >= mtls->xEnd) return;
898 }
899
900 if (!sc || (sc->yEnd == 0)) {
901 mtls->yEnd = mtls->fep.dimY;
902 } else {
903 rsAssert(sc->yStart < mtls->fep.dimY);
904 rsAssert(sc->yEnd <= mtls->fep.dimY);
905 rsAssert(sc->yStart < sc->yEnd);
906 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
907 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
908 if (mtls->yStart >= mtls->yEnd) return;
909 }
910
911 if (!sc || (sc->zEnd == 0)) {
912 mtls->zEnd = mtls->fep.dimZ;
913 } else {
914 rsAssert(sc->zStart < mtls->fep.dimZ);
915 rsAssert(sc->zEnd <= mtls->fep.dimZ);
916 rsAssert(sc->zStart < sc->zEnd);
917 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
918 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
919 if (mtls->zStart >= mtls->zEnd) return;
920 }
921
922 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
923 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
924 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
925 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
926
Chris Wailesf3712132014-07-16 15:18:30 -0700927 rsAssert(inLen == 0 || (ains[0]->getType()->getDimZ() == 0));
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700928
929 mtls->rsc = mCtx;
930 mtls->ains = ains;
931 mtls->aout = aout;
932 mtls->fep.usr = usr;
933 mtls->fep.usrLen = usrLen;
934 mtls->mSliceSize = 1;
935 mtls->mSliceNum = 0;
936
Chris Wailes44bef6f2014-08-12 13:51:10 -0700937 mtls->fep.inPtrs = nullptr;
938 mtls->fep.inStrides = nullptr;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700939 mtls->isThreadable = mIsThreadable;
940
Chris Wailesf3712132014-07-16 15:18:30 -0700941 if (inLen > 0) {
942
943 if (inLen <= RS_KERNEL_INPUT_THRESHOLD) {
944 mtls->fep.inPtrs = (const uint8_t**)mtls->inPtrsBuff;
945 mtls->fep.inStrides = mtls->inStridesBuff;
946 } else {
947 mtls->fep.heapAllocatedArrays = true;
948
949 mtls->fep.inPtrs = new const uint8_t*[inLen];
950 mtls->fep.inStrides = new StridePair[inLen];
951 }
952
953 mtls->fep.inLen = inLen;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700954
955 for (int index = inLen; --index >= 0;) {
956 const Allocation *ain = ains[index];
957
Chris Wailesf3712132014-07-16 15:18:30 -0700958 mtls->fep.inPtrs[index] =
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700959 (const uint8_t*)ain->mHal.drvState.lod[0].mallocPtr;
960
961 mtls->fep.inStrides[index].eStride =
962 ain->getType()->getElementSizeBytes();
963 mtls->fep.inStrides[index].yStride =
964 ain->mHal.drvState.lod[0].stride;
965 }
966 }
967
Chris Wailes44bef6f2014-08-12 13:51:10 -0700968 mtls->fep.outPtr = nullptr;
Chris Wailesf3712132014-07-16 15:18:30 -0700969 mtls->fep.outStride.eStride = 0;
970 mtls->fep.outStride.yStride = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700971 if (aout != nullptr) {
Chris Wailesf3712132014-07-16 15:18:30 -0700972 mtls->fep.outPtr = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
973
974 mtls->fep.outStride.eStride = aout->getType()->getElementSizeBytes();
975 mtls->fep.outStride.yStride = aout->mHal.drvState.lod[0].stride;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700976 }
977}
978
Jason Sams709a0972012-11-15 18:18:04 -0800979
980void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
Chris Wailesf3712132014-07-16 15:18:30 -0700981 const Allocation ** ains,
982 uint32_t inLen,
Jason Sams709a0972012-11-15 18:18:04 -0800983 Allocation * aout,
984 const void * usr,
985 uint32_t usrLen,
986 const RsScriptCall *sc) {
987
988 MTLaunchStruct mtls;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700989
990 forEachMtlsSetup(ains, inLen, aout, usr, usrLen, sc, &mtls);
991 forEachKernelSetup(slot, &mtls);
992
993 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
994 mCtx->launchThreads(ains, inLen, aout, sc, &mtls);
995 mCtx->setTLS(oldTLS);
996}
997
Jason Sams709a0972012-11-15 18:18:04 -0800998void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
Jason Sams709a0972012-11-15 18:18:04 -0800999 mtls->script = this;
1000 mtls->fep.slot = slot;
Jason Sams110f1812013-03-14 16:02:18 -07001001#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001002 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
1003 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
1004 mExecutable->getExportForeachFuncAddrs()[slot]);
Chris Wailes44bef6f2014-08-12 13:51:10 -07001005 rsAssert(mtls->kernel != nullptr);
Jason Sams709a0972012-11-15 18:18:04 -08001006 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
Jason Sams110f1812013-03-14 16:02:18 -07001007#else
1008 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
Chris Wailes44bef6f2014-08-12 13:51:10 -07001009 rsAssert(mtls->kernel != nullptr);
Jason Sams110f1812013-03-14 16:02:18 -07001010 mtls->sig = mForEachSignatures[slot];
1011#endif
Jason Sams709a0972012-11-15 18:18:04 -08001012}
1013
1014int RsdCpuScriptImpl::invokeRoot() {
1015 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1016 int ret = mRoot();
1017 mCtx->setTLS(oldTLS);
1018 return ret;
1019}
1020
1021void RsdCpuScriptImpl::invokeInit() {
1022 if (mInit) {
1023 mInit();
1024 }
1025}
1026
1027void RsdCpuScriptImpl::invokeFreeChildren() {
1028 if (mFreeChildren) {
1029 mFreeChildren();
1030 }
1031}
1032
1033void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
1034 size_t paramLength) {
1035 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
1036
1037 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1038 reinterpret_cast<void (*)(const void *, uint32_t)>(
Jason Sams110f1812013-03-14 16:02:18 -07001039#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001040 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
Jason Sams110f1812013-03-14 16:02:18 -07001041#else
1042 mInvokeFunctions[slot])(params, paramLength);
1043#endif
Jason Sams709a0972012-11-15 18:18:04 -08001044 mCtx->setTLS(oldTLS);
1045}
1046
1047void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
1048 //rsAssert(!script->mFieldIsObject[slot]);
1049 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1050
1051 //if (mIntrinsicID) {
1052 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
1053 //return;
1054 //}
1055
Jason Sams110f1812013-03-14 16:02:18 -07001056#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001057 int32_t *destPtr = reinterpret_cast<int32_t *>(
1058 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001059#else
1060 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1061#endif
Jason Sams709a0972012-11-15 18:18:04 -08001062 if (!destPtr) {
1063 //ALOGV("Calling setVar on slot = %i which is null", slot);
1064 return;
1065 }
1066
1067 memcpy(destPtr, data, dataLength);
1068}
1069
Tim Murray9c642392013-04-11 13:29:59 -07001070void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
1071 //rsAssert(!script->mFieldIsObject[slot]);
1072 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1073
1074#ifndef RS_COMPATIBILITY_LIB
1075 int32_t *srcPtr = reinterpret_cast<int32_t *>(
1076 mExecutable->getExportVarAddrs()[slot]);
1077#else
1078 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1079#endif
1080 if (!srcPtr) {
1081 //ALOGV("Calling setVar on slot = %i which is null", slot);
1082 return;
1083 }
1084 memcpy(data, srcPtr, dataLength);
1085}
1086
1087
Jason Sams709a0972012-11-15 18:18:04 -08001088void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
1089 const Element *elem,
Stephen Hinesac8d1462014-06-25 00:01:23 -07001090 const uint32_t *dims, size_t dimLength) {
Jason Sams709a0972012-11-15 18:18:04 -08001091
Jason Sams110f1812013-03-14 16:02:18 -07001092#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001093 int32_t *destPtr = reinterpret_cast<int32_t *>(
1094 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001095#else
1096 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1097#endif
Jason Sams709a0972012-11-15 18:18:04 -08001098 if (!destPtr) {
1099 //ALOGV("Calling setVar on slot = %i which is null", slot);
1100 return;
1101 }
1102
1103 // We want to look at dimension in terms of integer components,
1104 // but dimLength is given in terms of bytes.
1105 dimLength /= sizeof(int);
1106
1107 // Only a single dimension is currently supported.
1108 rsAssert(dimLength == 1);
1109 if (dimLength == 1) {
1110 // First do the increment loop.
1111 size_t stride = elem->getSizeBytes();
1112 const char *cVal = reinterpret_cast<const char *>(data);
Stephen Hinesac8d1462014-06-25 00:01:23 -07001113 for (uint32_t i = 0; i < dims[0]; i++) {
Jason Sams709a0972012-11-15 18:18:04 -08001114 elem->incRefs(cVal);
1115 cVal += stride;
1116 }
1117
1118 // Decrement loop comes after (to prevent race conditions).
1119 char *oldVal = reinterpret_cast<char *>(destPtr);
Stephen Hinesac8d1462014-06-25 00:01:23 -07001120 for (uint32_t i = 0; i < dims[0]; i++) {
Jason Sams709a0972012-11-15 18:18:04 -08001121 elem->decRefs(oldVal);
1122 oldVal += stride;
1123 }
1124 }
1125
1126 memcpy(destPtr, data, dataLength);
1127}
1128
1129void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
1130
1131 //rsAssert(!script->mFieldIsObject[slot]);
1132 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
1133
Jason Sams110f1812013-03-14 16:02:18 -07001134#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001135 int32_t *destPtr = reinterpret_cast<int32_t *>(
1136 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001137#else
1138 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1139#endif
Jason Sams709a0972012-11-15 18:18:04 -08001140 if (!destPtr) {
1141 //ALOGV("Calling setVar on slot = %i which is null", slot);
1142 return;
1143 }
1144
Chris Wailes44bef6f2014-08-12 13:51:10 -07001145 void *ptr = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -08001146 mBoundAllocs[slot] = data;
1147 if(data) {
1148 ptr = data->mHal.drvState.lod[0].mallocPtr;
1149 }
1150 memcpy(destPtr, &ptr, sizeof(void *));
1151}
1152
1153void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
1154
1155 //rsAssert(script->mFieldIsObject[slot]);
1156 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
1157
Jason Sams110f1812013-03-14 16:02:18 -07001158#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001159 int32_t *destPtr = reinterpret_cast<int32_t *>(
1160 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001161#else
1162 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1163#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001164
Jason Sams709a0972012-11-15 18:18:04 -08001165 if (!destPtr) {
1166 //ALOGV("Calling setVar on slot = %i which is null", slot);
1167 return;
1168 }
1169
Jason Sams05ef73f2014-08-05 14:59:22 -07001170 rsrSetObject(mCtx->getContext(), (rs_object_base *)destPtr, data);
Jason Sams709a0972012-11-15 18:18:04 -08001171}
1172
1173RsdCpuScriptImpl::~RsdCpuScriptImpl() {
Jason Sams110f1812013-03-14 16:02:18 -07001174#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001175 if (mExecutable) {
Chris Wailes70d49712014-08-08 14:42:33 -07001176 std::vector<void *>::const_iterator var_addr_iter =
Jason Sams709a0972012-11-15 18:18:04 -08001177 mExecutable->getExportVarAddrs().begin();
Chris Wailes70d49712014-08-08 14:42:33 -07001178 std::vector<void *>::const_iterator var_addr_end =
Jason Sams709a0972012-11-15 18:18:04 -08001179 mExecutable->getExportVarAddrs().end();
1180
1181 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
1182 mExecutable->getInfo().getObjectSlots().begin();
1183 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
1184 mExecutable->getInfo().getObjectSlots().end();
1185
1186 while ((var_addr_iter != var_addr_end) &&
1187 (is_object_iter != is_object_end)) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001188 // The field address can be nullptr if the script-side has optimized
Jason Sams709a0972012-11-15 18:18:04 -08001189 // the corresponding global variable away.
Jason Sams05ef73f2014-08-05 14:59:22 -07001190 rs_object_base *obj_addr =
1191 reinterpret_cast<rs_object_base *>(*var_addr_iter);
Jason Sams709a0972012-11-15 18:18:04 -08001192 if (*is_object_iter) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001193 if (*var_addr_iter != nullptr && mCtx->getContext() != nullptr) {
Jason Sams709a0972012-11-15 18:18:04 -08001194 rsrClearObject(mCtx->getContext(), obj_addr);
1195 }
1196 }
1197 var_addr_iter++;
1198 is_object_iter++;
1199 }
1200 }
1201
1202 if (mCompilerContext) {
1203 delete mCompilerContext;
1204 }
1205 if (mCompilerDriver) {
1206 delete mCompilerDriver;
1207 }
1208 if (mExecutable) {
1209 delete mExecutable;
1210 }
1211 if (mBoundAllocs) {
1212 delete[] mBoundAllocs;
1213 }
Tim Murraybee48d72014-06-13 12:44:47 -07001214
Tim Murray29809d12014-05-28 12:04:19 -07001215 for (size_t i = 0; i < mExportedForEachFuncList.size(); i++) {
1216 delete[] mExportedForEachFuncList[i].first;
1217 }
Jason Sams110f1812013-03-14 16:02:18 -07001218#else
1219 if (mFieldIsObject) {
1220 for (size_t i = 0; i < mExportedVariableCount; ++i) {
1221 if (mFieldIsObject[i]) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001222 if (mFieldAddress[i] != nullptr) {
Jason Sams05ef73f2014-08-05 14:59:22 -07001223 rs_object_base *obj_addr =
1224 reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
Jason Sams110f1812013-03-14 16:02:18 -07001225 rsrClearObject(mCtx->getContext(), obj_addr);
1226 }
1227 }
1228 }
1229 }
1230
1231 if (mInvokeFunctions) delete[] mInvokeFunctions;
1232 if (mForEachFunctions) delete[] mForEachFunctions;
1233 if (mFieldAddress) delete[] mFieldAddress;
1234 if (mFieldIsObject) delete[] mFieldIsObject;
1235 if (mForEachSignatures) delete[] mForEachSignatures;
1236 if (mBoundAllocs) delete[] mBoundAllocs;
1237 if (mScriptSO) {
1238 dlclose(mScriptSO);
1239 }
1240#endif
Jason Sams709a0972012-11-15 18:18:04 -08001241}
1242
1243Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
1244 if (!ptr) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001245 return nullptr;
Jason Sams709a0972012-11-15 18:18:04 -08001246 }
1247
1248 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
1249 Allocation *a = mBoundAllocs[ct];
1250 if (!a) continue;
1251 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
1252 return a;
1253 }
1254 }
1255 ALOGE("rsGetAllocation, failed to find %p", ptr);
Chris Wailes44bef6f2014-08-12 13:51:10 -07001256 return nullptr;
Jason Sams709a0972012-11-15 18:18:04 -08001257}
1258
Chris Wailesf3712132014-07-16 15:18:30 -07001259void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation ** ains,
1260 uint32_t inLen, Allocation * aout,
1261 const void * usr, uint32_t usrLen,
1262 const RsScriptCall *sc) {}
Jason Sams17e3cdc2013-09-09 17:32:16 -07001263
Chris Wailesf3712132014-07-16 15:18:30 -07001264void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation ** ains,
1265 uint32_t inLen, Allocation * aout,
1266 const void * usr, uint32_t usrLen,
1267 const RsScriptCall *sc) {}
Jason Sams17e3cdc2013-09-09 17:32:16 -07001268
Jason Sams709a0972012-11-15 18:18:04 -08001269
1270}
1271}