blob: a89e38dc404b975fa126483c7ed9453cad183590 [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>
Jason Sams110f1812013-03-14 16:02:18 -070029#else
30 #include <bcc/BCCContext.h>
Stephen Hines82e0a672014-05-05 15:40:56 -070031 #include <bcc/Config/Config.h>
Jason Sams110f1812013-03-14 16:02:18 -070032 #include <bcc/Renderscript/RSCompilerDriver.h>
33 #include <bcc/Renderscript/RSExecutable.h>
34 #include <bcc/Renderscript/RSInfo.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070035 #include <bcinfo/MetadataExtractor.h>
Stephen Hinesba17ae42013-06-05 17:18:04 -070036 #include <cutils/properties.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070037
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
Stephen Hines00511322014-01-31 11:20:23 -080041
42 #include <string>
43 #include <vector>
Jason Sams110f1812013-03-14 16:02:18 -070044#endif
Jason Sams709a0972012-11-15 18:18:04 -080045
Stephen Hinesba17ae42013-06-05 17:18:04 -070046namespace {
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070047#ifdef RS_COMPATIBILITY_LIB
48
49// Create a len length string containing random characters from [A-Za-z0-9].
50static std::string getRandomString(size_t len) {
51 char buf[len + 1];
52 for (size_t i = 0; i < len; i++) {
53 uint32_t r = arc4random() & 0xffff;
54 r %= 62;
55 if (r < 26) {
56 // lowercase
57 buf[i] = 'a' + r;
58 } else if (r < 52) {
59 // uppercase
60 buf[i] = 'A' + (r - 26);
61 } else {
62 // Use a number
63 buf[i] = '0' + (r - 52);
64 }
65 }
66 buf[len] = '\0';
67 return std::string(buf);
68}
69
Stephen Hinesee48c0b2013-10-30 17:48:30 -070070// Check if a path exists and attempt to create it if it doesn't.
71static bool ensureCacheDirExists(const char *path) {
72 if (access(path, R_OK | W_OK | X_OK) == 0) {
73 // Done if we can rwx the directory
74 return true;
75 }
76 if (mkdir(path, 0700) == 0) {
77 return true;
78 }
79 return false;
80}
81
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070082// Attempt to load the shared library from origName, but then fall back to
83// creating the symlinked shared library if necessary (to ensure instancing).
84// This function returns the dlopen()-ed handle if successful.
85static void *loadSOHelper(const char *origName, const char *cacheDir,
86 const char *resName) {
87 // Keep track of which .so libraries have been loaded. Once a library is
88 // in the set (per-process granularity), we must instead make a symlink to
89 // the original shared object (randomly named .so file) and load that one
90 // instead. If we don't do this, we end up aliasing global data between
91 // the various Script instances (which are supposed to be completely
92 // independent).
93 static std::set<std::string> LoadedLibraries;
94
Chris Wailes44bef6f2014-08-12 13:51:10 -070095 void *loaded = nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070096
97 // Skip everything if we don't even have the original library available.
98 if (access(origName, F_OK) != 0) {
Chris Wailes44bef6f2014-08-12 13:51:10 -070099 return nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700100 }
101
102 // Common path is that we have not loaded this Script/library before.
103 if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
104 loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
105 if (loaded) {
106 LoadedLibraries.insert(origName);
107 }
108 return loaded;
109 }
110
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700111 std::string newName(cacheDir);
Stephen Hinesee48c0b2013-10-30 17:48:30 -0700112 newName.append("/com.android.renderscript.cache/");
113
114 if (!ensureCacheDirExists(newName.c_str())) {
115 ALOGE("Could not verify or create cache dir: %s", cacheDir);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700116 return nullptr;
Stephen Hinesee48c0b2013-10-30 17:48:30 -0700117 }
118
119 // Construct an appropriately randomized filename for the symlink.
120 newName.append("librs.");
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700121 newName.append(resName);
122 newName.append("#");
123 newName.append(getRandomString(6)); // 62^6 potential filename variants.
124 newName.append(".so");
125
126 int r = symlink(origName, newName.c_str());
127 if (r != 0) {
128 ALOGE("Could not create symlink %s -> %s", newName.c_str(), origName);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700129 return nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700130 }
131 loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
132 r = unlink(newName.c_str());
133 if (r != 0) {
134 ALOGE("Could not unlink symlink %s", newName.c_str());
135 }
136 if (loaded) {
137 LoadedLibraries.insert(newName.c_str());
138 }
139
140 return loaded;
141}
142
143// Load the shared library referred to by cacheDir and resName. If we have
144// already loaded this library, we instead create a new symlink (in the
145// cache dir) and then load that. We then immediately destroy the symlink.
146// This is required behavior to implement script instancing for the support
147// library, since shared objects are loaded and de-duped by name only.
148static void *loadSharedLibrary(const char *cacheDir, const char *resName) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700149 void *loaded = nullptr;
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700150 //arc4random_stir();
151#ifndef RS_SERVER
152 std::string scriptSOName(cacheDir);
153 size_t cutPos = scriptSOName.rfind("cache");
154 if (cutPos != std::string::npos) {
155 scriptSOName.erase(cutPos);
156 } else {
157 ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
158 }
159 scriptSOName.append("/lib/librs.");
160#else
161 std::string scriptSOName("lib");
162#endif
163 scriptSOName.append(resName);
164 scriptSOName.append(".so");
165
166 // We should check if we can load the library from the standard app
167 // location for shared libraries first.
168 loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
169
Chris Wailes44bef6f2014-08-12 13:51:10 -0700170 if (loaded == nullptr) {
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700171 ALOGE("Unable to open shared library (%s): %s",
172 scriptSOName.c_str(), dlerror());
173
174 // One final attempt to find the library in "/system/lib".
175 // We do this to allow bundled applications to use the compatibility
176 // library fallback path. Those applications don't have a private
177 // library path, so they need to install to the system directly.
178 // Note that this is really just a testing path.
Chris Wailes93d6bc82014-07-28 16:54:38 -0700179 std::string scriptSONameSystem("/system/lib/librs.");
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700180 scriptSONameSystem.append(resName);
181 scriptSONameSystem.append(".so");
182 loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
183 resName);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700184 if (loaded == nullptr) {
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700185 ALOGE("Unable to open system shared library (%s): %s",
186 scriptSONameSystem.c_str(), dlerror());
187 }
188 }
189
190 return loaded;
191}
192
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700193#else // RS_COMPATIBILITY_LIB is not defined
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700194
Stephen Hinesba17ae42013-06-05 17:18:04 -0700195static bool is_force_recompile() {
196#ifdef RS_SERVER
197 return false;
198#else
199 char buf[PROPERTY_VALUE_MAX];
200
201 // Re-compile if floating point precision has been overridden.
202 property_get("debug.rs.precision", buf, "");
203 if (buf[0] != '\0') {
204 return true;
205 }
206
207 // Re-compile if debug.rs.forcerecompile is set.
208 property_get("debug.rs.forcerecompile", buf, "0");
209 if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
210 return true;
211 } else {
212 return false;
213 }
214#endif // RS_SERVER
215}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700216
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700217const static char *BCC_EXE_PATH = "/system/bin/bcc";
218
Chris Wailes6847e732014-08-11 17:30:51 -0700219static void setCompileArguments(std::vector<const char*>* args,
220 const std::string& bcFileName,
221 const char* cacheDir, const char* resName,
222 const char* core_lib, bool useRSDebugContext,
223 const char* bccPluginName) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700224 rsAssert(cacheDir && resName && core_lib);
225 args->push_back(BCC_EXE_PATH);
226 args->push_back("-o");
227 args->push_back(resName);
228 args->push_back("-output_path");
229 args->push_back(cacheDir);
230 args->push_back("-bclib");
231 args->push_back(core_lib);
232 args->push_back("-mtriple");
233 args->push_back(DEFAULT_TARGET_TRIPLE_STRING);
234
235 // Execute the bcc compiler.
236 if (useRSDebugContext) {
237 args->push_back("-rs-debug-ctx");
238 } else {
239 // Only load additional libraries for compiles that don't use
240 // the debug context.
241 if (bccPluginName && strlen(bccPluginName) > 0) {
242 args->push_back("-load");
243 args->push_back(bccPluginName);
244 }
245 }
246
Chris Wailes6847e732014-08-11 17:30:51 -0700247 args->push_back(bcFileName.c_str());
Chris Wailes44bef6f2014-08-12 13:51:10 -0700248 args->push_back(nullptr);
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700249}
250
Chris Wailes6847e732014-08-11 17:30:51 -0700251static bool compileBitcode(const std::string &bcFileName,
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700252 const char *bitcode,
253 size_t bitcodeSize,
Chris Wailes6847e732014-08-11 17:30:51 -0700254 const char **compileArguments,
255 const std::string &compileCommandLine) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700256 rsAssert(bitcode && bitcodeSize);
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700257
Chris Wailes6847e732014-08-11 17:30:51 -0700258 FILE *bcfile = fopen(bcFileName.c_str(), "w");
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700259 if (!bcfile) {
Chris Wailes6847e732014-08-11 17:30:51 -0700260 ALOGE("Could not write to %s", bcFileName.c_str());
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700261 return false;
262 }
263 size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
264 fclose(bcfile);
265 if (nwritten != bitcodeSize) {
266 ALOGE("Could not write %zu bytes to %s", bitcodeSize,
Chris Wailes6847e732014-08-11 17:30:51 -0700267 bcFileName.c_str());
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700268 return false;
269 }
270
271 pid_t pid = fork();
Stephen Hines00511322014-01-31 11:20:23 -0800272
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700273 switch (pid) {
274 case -1: { // Error occurred (we attempt no recovery)
275 ALOGE("Couldn't fork for bcc compiler execution");
276 return false;
277 }
278 case 0: { // Child process
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700279 ALOGV("Invoking BCC with: %s", compileCommandLine.c_str());
280 execv(BCC_EXE_PATH, (char* const*)compileArguments);
Stephen Hines00511322014-01-31 11:20:23 -0800281
Stephen Hines00511322014-01-31 11:20:23 -0800282 ALOGE("execv() failed: %s", strerror(errno));
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700283 abort();
284 return false;
285 }
286 default: { // Parent process (actual driver)
287 // Wait on child process to finish compiling the source.
288 int status = 0;
289 pid_t w = waitpid(pid, &status, 0);
290 if (w == -1) {
291 ALOGE("Could not wait for bcc compiler");
292 return false;
293 }
294
295 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
296 return true;
297 }
298
299 ALOGE("bcc compiler terminated unexpectedly");
300 return false;
301 }
302 }
303}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700304
Stephen Hinesba17ae42013-06-05 17:18:04 -0700305#endif // !defined(RS_COMPATIBILITY_LIB)
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700306} // namespace
Stephen Hinesba17ae42013-06-05 17:18:04 -0700307
Jason Sams709a0972012-11-15 18:18:04 -0800308namespace android {
309namespace renderscript {
310
Jason Sams110f1812013-03-14 16:02:18 -0700311#ifdef RS_COMPATIBILITY_LIB
312#define MAXLINE 500
313#define MAKE_STR_HELPER(S) #S
314#define MAKE_STR(S) MAKE_STR_HELPER(S)
315#define EXPORT_VAR_STR "exportVarCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700316#define EXPORT_FUNC_STR "exportFuncCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700317#define EXPORT_FOREACH_STR "exportForEachCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700318#define OBJECT_SLOT_STR "objectSlotCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700319
320// Copy up to a newline or size chars from str -> s, updating str
Chris Wailes44bef6f2014-08-12 13:51:10 -0700321// Returns s when successful and nullptr when '\0' is finally reached.
Jason Sams110f1812013-03-14 16:02:18 -0700322static char* strgets(char *s, int size, const char **ppstr) {
323 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700324 return nullptr;
Jason Sams110f1812013-03-14 16:02:18 -0700325 }
326
327 int i;
328 for (i = 0; i < (size - 1); i++) {
329 s[i] = **ppstr;
330 (*ppstr)++;
331 if (s[i] == '\0') {
332 return s;
333 } else if (s[i] == '\n') {
334 s[i+1] = '\0';
335 return s;
336 }
337 }
338
339 // size has been exceeded.
340 s[i] = '\0';
341
342 return s;
343}
344#endif
Jason Sams709a0972012-11-15 18:18:04 -0800345
346RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
347 mCtx = ctx;
348 mScript = s;
349
Jason Sams110f1812013-03-14 16:02:18 -0700350#ifdef RS_COMPATIBILITY_LIB
Chris Wailes44bef6f2014-08-12 13:51:10 -0700351 mScriptSO = nullptr;
352 mInvokeFunctions = nullptr;
353 mForEachFunctions = nullptr;
354 mFieldAddress = nullptr;
355 mFieldIsObject = nullptr;
356 mForEachSignatures = nullptr;
Jason Sams110f1812013-03-14 16:02:18 -0700357#else
Chris Wailes44bef6f2014-08-12 13:51:10 -0700358 mCompilerContext = nullptr;
359 mCompilerDriver = nullptr;
360 mExecutable = nullptr;
Jason Sams110f1812013-03-14 16:02:18 -0700361#endif
362
Tim Murraye195a3f2014-03-13 15:04:58 -0700363
Chris Wailes44bef6f2014-08-12 13:51:10 -0700364 mRoot = nullptr;
365 mRootExpand = nullptr;
366 mInit = nullptr;
367 mFreeChildren = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -0800368
Jason Sams709a0972012-11-15 18:18:04 -0800369
Chris Wailes44bef6f2014-08-12 13:51:10 -0700370 mBoundAllocs = nullptr;
371 mIntrinsicData = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -0800372 mIsThreadable = true;
373}
374
375
376bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
377 uint8_t const *bitcode, size_t bitcodeSize,
Stephen Hines00511322014-01-31 11:20:23 -0800378 uint32_t flags, char const *bccPluginName) {
Jason Sams709a0972012-11-15 18:18:04 -0800379 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
380 //ALOGE("rsdScriptInit %p %p", rsc, script);
381
382 mCtx->lockMutex();
Jason Sams110f1812013-03-14 16:02:18 -0700383#ifndef RS_COMPATIBILITY_LIB
Stephen Hines00511322014-01-31 11:20:23 -0800384 bool useRSDebugContext = false;
Jason Sams709a0972012-11-15 18:18:04 -0800385
Chris Wailes44bef6f2014-08-12 13:51:10 -0700386 mCompilerContext = nullptr;
387 mCompilerDriver = nullptr;
388 mExecutable = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -0800389
390 mCompilerContext = new bcc::BCCContext();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700391 if (mCompilerContext == nullptr) {
Jason Sams709a0972012-11-15 18:18:04 -0800392 ALOGE("bcc: FAILS to create compiler context (out of memory)");
393 mCtx->unlockMutex();
394 return false;
395 }
396
397 mCompilerDriver = new bcc::RSCompilerDriver();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700398 if (mCompilerDriver == nullptr) {
Jason Sams709a0972012-11-15 18:18:04 -0800399 ALOGE("bcc: FAILS to create compiler driver (out of memory)");
400 mCtx->unlockMutex();
401 return false;
402 }
403
Stephen Hines25e3af52014-05-21 21:23:08 -0700404 // Configure symbol resolvers (via compiler-rt and the RS runtime).
405 mRSRuntime.setLookupFunction(lookupRuntimeStub);
406 mRSRuntime.setContext(this);
407 mResolver.chainResolver(mCompilerRuntime);
408 mResolver.chainResolver(mRSRuntime);
Jason Sams709a0972012-11-15 18:18:04 -0800409
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700410 // Run any compiler setup functions we have been provided with.
411 RSSetupCompilerCallback setupCompilerCallback =
412 mCtx->getSetupCompilerCallback();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700413 if (setupCompilerCallback != nullptr) {
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700414 setupCompilerCallback(mCompilerDriver);
415 }
416
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700417 bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize);
418 if (!bitcodeMetadata.extract()) {
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700419 ALOGE("Could not extract metadata from bitcode");
Stephen Hinesf94e8db2014-06-26 11:55:29 -0700420 mCtx->unlockMutex();
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700421 return false;
422 }
423
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700424 const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize);
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700425
426 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
Stephen Hinesf47e8b42013-04-18 01:06:29 -0700427 mCompilerDriver->setDebugContext(true);
Stephen Hines00511322014-01-31 11:20:23 -0800428 useRSDebugContext = true;
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700429 }
Stephen Hinesba17ae42013-06-05 17:18:04 -0700430
Chris Wailes6847e732014-08-11 17:30:51 -0700431 std::string bcFileName(cacheDir);
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700432 bcFileName.append("/");
433 bcFileName.append(resName);
434 bcFileName.append(".bc");
435
436 std::vector<const char*> compileArguments;
437 setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
438 useRSDebugContext, bccPluginName);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700439 // The last argument of compileArguments ia a nullptr, so remove 1 from the size.
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700440 std::string compileCommandLine =
441 bcc::getCommandLine(compileArguments.size() - 1, compileArguments.data());
442
443 if (!is_force_recompile()) {
444 // Load the compiled script that's in the cache, if any.
445 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
446 bitcodeSize, compileCommandLine.c_str(),
447 mResolver);
448 }
449
450 // If we can't, it's either not there or out of date. We compile the bit code and try loading
451 // again.
Chris Wailes44bef6f2014-08-12 13:51:10 -0700452 if (mExecutable == nullptr) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700453 if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments.data(),
454 compileCommandLine)) {
455 ALOGE("bcc: FAILS to compile '%s'", resName);
456 mCtx->unlockMutex();
457 return false;
458 }
459 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
460 bitcodeSize, compileCommandLine.c_str(),
461 mResolver);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700462 if (mExecutable == nullptr) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700463 ALOGE("bcc: FAILS to load freshly compiled executable for '%s'", resName);
464 mCtx->unlockMutex();
465 return false;
Stephen Hinesba17ae42013-06-05 17:18:04 -0700466 }
467 }
Jason Sams709a0972012-11-15 18:18:04 -0800468
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700469 mExecutable->setThreadable(mIsThreadable);
470 if (!mExecutable->syncInfo()) {
Jason Sams709a0972012-11-15 18:18:04 -0800471 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
472 }
473
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700474 mRoot = reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root"));
Jason Sams709a0972012-11-15 18:18:04 -0800475 mRootExpand =
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700476 reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root.expand"));
477 mInit = reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress("init"));
Jason Sams709a0972012-11-15 18:18:04 -0800478 mFreeChildren =
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700479 reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress(".rs.dtor"));
Jason Sams709a0972012-11-15 18:18:04 -0800480
481
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700482 if (bitcodeMetadata.getExportVarCount()) {
483 mBoundAllocs = new Allocation *[bitcodeMetadata.getExportVarCount()];
484 memset(mBoundAllocs, 0, sizeof(void *) * bitcodeMetadata.getExportVarCount());
Tim Murray29809d12014-05-28 12:04:19 -0700485 }
486
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700487 for (size_t i = 0; i < bitcodeMetadata.getExportForEachSignatureCount(); i++) {
488 char* name = new char[strlen(bitcodeMetadata.getExportForEachNameList()[i]) + 1];
489 mExportedForEachFuncList.push_back(
490 std::make_pair(name, bitcodeMetadata.getExportForEachSignatureList()[i]));
Jason Sams709a0972012-11-15 18:18:04 -0800491 }
492
Jean-Luc Brouilletf4d216e2014-06-09 18:04:16 -0700493#else // RS_COMPATIBILITY_LIB is defined
Jason Sams110f1812013-03-14 16:02:18 -0700494
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700495 mScriptSO = loadSharedLibrary(cacheDir, resName);
Jason Sams110f1812013-03-14 16:02:18 -0700496
497 if (mScriptSO) {
498 char line[MAXLINE];
499 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
500 if (mRoot) {
501 //ALOGE("Found root(): %p", mRoot);
502 }
503 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
504 if (mRootExpand) {
505 //ALOGE("Found root.expand(): %p", mRootExpand);
506 }
507 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
508 if (mInit) {
509 //ALOGE("Found init(): %p", mInit);
510 }
511 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
512 if (mFreeChildren) {
513 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
514 }
515
516 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
517 if (rsInfo) {
518 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
519 }
520
521 size_t varCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700522 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700523 goto error;
524 }
525 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
526 ALOGE("Invalid export var count!: %s", line);
527 goto error;
528 }
529
530 mExportedVariableCount = varCount;
531 //ALOGE("varCount: %zu", varCount);
532 if (varCount > 0) {
533 // Start by creating/zeroing this member, since we don't want to
534 // accidentally clean up invalid pointers later (if we error out).
535 mFieldIsObject = new bool[varCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700536 if (mFieldIsObject == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700537 goto error;
538 }
539 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
540 mFieldAddress = new void*[varCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700541 if (mFieldAddress == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700542 goto error;
543 }
544 for (size_t i = 0; i < varCount; ++i) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700545 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700546 goto error;
547 }
548 char *c = strrchr(line, '\n');
549 if (c) {
550 *c = '\0';
551 }
552 mFieldAddress[i] = dlsym(mScriptSO, line);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700553 if (mFieldAddress[i] == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700554 ALOGE("Failed to find variable address for %s: %s",
555 line, dlerror());
556 // Not a critical error if we don't find a global variable.
557 }
558 else {
559 //ALOGE("Found variable %s at %p", line,
560 //mFieldAddress[i]);
561 }
562 }
563 }
564
565 size_t funcCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700566 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700567 goto error;
568 }
569 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
570 ALOGE("Invalid export func count!: %s", line);
571 goto error;
572 }
573
574 mExportedFunctionCount = funcCount;
575 //ALOGE("funcCount: %zu", funcCount);
576
577 if (funcCount > 0) {
578 mInvokeFunctions = new InvokeFunc_t[funcCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700579 if (mInvokeFunctions == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700580 goto error;
581 }
582 for (size_t i = 0; i < funcCount; ++i) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700583 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700584 goto error;
585 }
586 char *c = strrchr(line, '\n');
587 if (c) {
588 *c = '\0';
589 }
590
591 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700592 if (mInvokeFunctions[i] == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700593 ALOGE("Failed to get function address for %s(): %s",
594 line, dlerror());
595 goto error;
596 }
597 else {
598 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
599 }
600 }
601 }
602
603 size_t forEachCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700604 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700605 goto error;
606 }
607 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
608 ALOGE("Invalid export forEach count!: %s", line);
609 goto error;
610 }
611
612 if (forEachCount > 0) {
613
614 mForEachSignatures = new uint32_t[forEachCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700615 if (mForEachSignatures == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700616 goto error;
617 }
618 mForEachFunctions = new ForEachFunc_t[forEachCount];
Chris Wailes44bef6f2014-08-12 13:51:10 -0700619 if (mForEachFunctions == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700620 goto error;
621 }
622 for (size_t i = 0; i < forEachCount; ++i) {
623 unsigned int tmpSig = 0;
624 char tmpName[MAXLINE];
625
Chris Wailes44bef6f2014-08-12 13:51:10 -0700626 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700627 goto error;
628 }
629 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
630 &tmpSig, tmpName) != 2) {
631 ALOGE("Invalid export forEach!: %s", line);
632 goto error;
633 }
634
635 // Lookup the expanded ForEach kernel.
636 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
637 mForEachSignatures[i] = tmpSig;
638 mForEachFunctions[i] =
639 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700640 if (i != 0 && mForEachFunctions[i] == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700641 // Ignore missing root.expand functions.
642 // root() is always specified at location 0.
Stephen Hinesef7481e2013-04-09 19:05:27 -0700643 ALOGE("Failed to find forEach function address for %s: %s",
644 tmpName, dlerror());
645 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700646 }
647 else {
648 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
649 }
650 }
651 }
652
653 size_t objectSlotCount = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700654 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700655 goto error;
656 }
657 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
658 ALOGE("Invalid object slot count!: %s", line);
659 goto error;
660 }
661
662 if (objectSlotCount > 0) {
663 rsAssert(varCount > 0);
664 for (size_t i = 0; i < objectSlotCount; ++i) {
665 uint32_t varNum = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700666 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
Jason Sams110f1812013-03-14 16:02:18 -0700667 goto error;
668 }
669 if (sscanf(line, "%u", &varNum) != 1) {
670 ALOGE("Invalid object slot!: %s", line);
671 goto error;
672 }
673
674 if (varNum < varCount) {
675 mFieldIsObject[varNum] = true;
676 }
677 }
678 }
679
680 if (varCount > 0) {
681 mBoundAllocs = new Allocation *[varCount];
682 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
683 }
684
685 if (mScriptSO == (void*)1) {
686 //rsdLookupRuntimeStub(script, "acos");
687 }
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700688 } else {
689 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700690 }
691#endif
Jason Sams709a0972012-11-15 18:18:04 -0800692 mCtx->unlockMutex();
693 return true;
Jason Sams110f1812013-03-14 16:02:18 -0700694
695#ifdef RS_COMPATIBILITY_LIB
696error:
697
698 mCtx->unlockMutex();
699 delete[] mInvokeFunctions;
700 delete[] mForEachFunctions;
701 delete[] mFieldAddress;
702 delete[] mFieldIsObject;
703 delete[] mForEachSignatures;
704 delete[] mBoundAllocs;
705 if (mScriptSO) {
706 dlclose(mScriptSO);
707 }
708 return false;
709#endif
Jason Sams709a0972012-11-15 18:18:04 -0800710}
711
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700712#ifndef RS_COMPATIBILITY_LIB
713
714#ifdef __LP64__
715#define SYSLIBPATH "/system/lib64"
716#else
717#define SYSLIBPATH "/system/lib"
718#endif
719
720const char* RsdCpuScriptImpl::findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode,
721 size_t bitcodeSize) {
722 const char* defaultLib = SYSLIBPATH"/libclcore.bc";
723
724 // If we're debugging, use the debug library.
725 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
726 return SYSLIBPATH"/libclcore_debug.bc";
727 }
728
729 // If a callback has been registered to specify a library, use that.
730 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
Chris Wailes44bef6f2014-08-12 13:51:10 -0700731 if (selectRTCallback != nullptr) {
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700732 return selectRTCallback((const char*)bitcode, bitcodeSize);
733 }
734
735 // Check for a platform specific library
736#if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_CLCORE_NEON)
737 enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
Jean-Luc Brouilletf4d38362014-07-09 17:46:03 -0700738 if (prec == bcinfo::RS_FP_Relaxed) {
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700739 // NEON-capable ARMv7a devices can use an accelerated math library
740 // for all reduced precision scripts.
741 // ARMv8 does not use NEON, as ASIMD can be used with all precision
742 // levels.
743 return SYSLIBPATH"/libclcore_neon.bc";
744 } else {
745 return defaultLib;
746 }
747#elif defined(__i386__) || defined(__x86_64__)
748 // x86 devices will use an optimized library.
749 return SYSLIBPATH"/libclcore_x86.bc";
750#else
751 return defaultLib;
752#endif
753}
754
755#endif
756
Jason Sams709a0972012-11-15 18:18:04 -0800757void RsdCpuScriptImpl::populateScript(Script *script) {
Jason Sams110f1812013-03-14 16:02:18 -0700758#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800759 // Copy info over to runtime
Tim Murray29809d12014-05-28 12:04:19 -0700760 script->mHal.info.exportedFunctionCount = mExecutable->getExportFuncAddrs().size();
761 script->mHal.info.exportedVariableCount = mExecutable->getExportVarAddrs().size();
762 script->mHal.info.exportedForeachFuncList = &mExportedForEachFuncList[0];
763 script->mHal.info.exportedPragmaCount = mExecutable->getPragmaKeys().size();
Jason Sams709a0972012-11-15 18:18:04 -0800764 script->mHal.info.exportedPragmaKeyList =
Chris Wailes70d49712014-08-08 14:42:33 -0700765 const_cast<const char**>(&mExecutable->getPragmaKeys().front());
Jason Sams709a0972012-11-15 18:18:04 -0800766 script->mHal.info.exportedPragmaValueList =
Chris Wailes70d49712014-08-08 14:42:33 -0700767 const_cast<const char**>(&mExecutable->getPragmaValues().front());
Jason Sams709a0972012-11-15 18:18:04 -0800768
769 if (mRootExpand) {
770 script->mHal.info.root = mRootExpand;
771 } else {
772 script->mHal.info.root = mRoot;
773 }
Jason Sams110f1812013-03-14 16:02:18 -0700774#else
775 // Copy info over to runtime
776 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
777 script->mHal.info.exportedVariableCount = mExportedVariableCount;
778 script->mHal.info.exportedPragmaCount = 0;
779 script->mHal.info.exportedPragmaKeyList = 0;
780 script->mHal.info.exportedPragmaValueList = 0;
781
782 // Bug, need to stash in metadata
783 if (mRootExpand) {
784 script->mHal.info.root = mRootExpand;
785 } else {
786 script->mHal.info.root = mRoot;
787 }
788#endif
Jason Sams709a0972012-11-15 18:18:04 -0800789}
790
Jason Sams709a0972012-11-15 18:18:04 -0800791
792typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
793
Chris Wailesf3712132014-07-16 15:18:30 -0700794void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation ** ains,
795 uint32_t inLen,
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700796 Allocation * aout,
797 const void * usr, uint32_t usrLen,
798 const RsScriptCall *sc,
799 MTLaunchStruct *mtls) {
800
801 memset(mtls, 0, sizeof(MTLaunchStruct));
802
Chris Wailesf3712132014-07-16 15:18:30 -0700803 for (int index = inLen; --index >= 0;) {
804 const Allocation* ain = ains[index];
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700805
Chris Wailesf3712132014-07-16 15:18:30 -0700806 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
Chris Wailes44bef6f2014-08-12 13:51:10 -0700807 if (ain != nullptr &&
808 (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == nullptr) {
809
Chris Wailesf3712132014-07-16 15:18:30 -0700810 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
811 "rsForEach called with null in allocations");
812 return;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700813 }
814 }
815
Chris Wailes44bef6f2014-08-12 13:51:10 -0700816 if (aout &&
817 (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == nullptr) {
818
Chris Wailesf3712132014-07-16 15:18:30 -0700819 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
820 "rsForEach called with null out allocations");
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700821 return;
822 }
823
Chris Wailesf3712132014-07-16 15:18:30 -0700824 if (inLen > 0) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700825 const Allocation *ain0 = ains[0];
826 const Type *inType = ain0->getType();
827
828 mtls->fep.dimX = inType->getDimX();
829 mtls->fep.dimY = inType->getDimY();
830 mtls->fep.dimZ = inType->getDimZ();
831
832 for (int Index = inLen; --Index >= 1;) {
833 if (!ain0->hasSameDims(ains[Index])) {
834 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
835 "Failed to launch kernel; dimensions of input and output allocations do not match.");
836
837 return;
838 }
839 }
840
Chris Wailes44bef6f2014-08-12 13:51:10 -0700841 } else if (aout != nullptr) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700842 const Type *outType = aout->getType();
843
844 mtls->fep.dimX = outType->getDimX();
845 mtls->fep.dimY = outType->getDimY();
846 mtls->fep.dimZ = outType->getDimZ();
847
848 } else {
Chris Wailesf3712132014-07-16 15:18:30 -0700849 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
850 "rsForEach called with null allocations");
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700851 return;
852 }
853
Chris Wailes44bef6f2014-08-12 13:51:10 -0700854 if (inLen > 0 && aout != nullptr) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700855 if (!ains[0]->hasSameDims(aout)) {
856 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
857 "Failed to launch kernel; dimensions of input and output allocations do not match.");
858
859 return;
860 }
861 }
862
863 if (!sc || (sc->xEnd == 0)) {
864 mtls->xEnd = mtls->fep.dimX;
865 } else {
866 rsAssert(sc->xStart < mtls->fep.dimX);
867 rsAssert(sc->xEnd <= mtls->fep.dimX);
868 rsAssert(sc->xStart < sc->xEnd);
869 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
870 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
871 if (mtls->xStart >= mtls->xEnd) return;
872 }
873
874 if (!sc || (sc->yEnd == 0)) {
875 mtls->yEnd = mtls->fep.dimY;
876 } else {
877 rsAssert(sc->yStart < mtls->fep.dimY);
878 rsAssert(sc->yEnd <= mtls->fep.dimY);
879 rsAssert(sc->yStart < sc->yEnd);
880 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
881 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
882 if (mtls->yStart >= mtls->yEnd) return;
883 }
884
885 if (!sc || (sc->zEnd == 0)) {
886 mtls->zEnd = mtls->fep.dimZ;
887 } else {
888 rsAssert(sc->zStart < mtls->fep.dimZ);
889 rsAssert(sc->zEnd <= mtls->fep.dimZ);
890 rsAssert(sc->zStart < sc->zEnd);
891 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
892 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
893 if (mtls->zStart >= mtls->zEnd) return;
894 }
895
896 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
897 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
898 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
899 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
900
Chris Wailesf3712132014-07-16 15:18:30 -0700901 rsAssert(inLen == 0 || (ains[0]->getType()->getDimZ() == 0));
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700902
903 mtls->rsc = mCtx;
904 mtls->ains = ains;
905 mtls->aout = aout;
906 mtls->fep.usr = usr;
907 mtls->fep.usrLen = usrLen;
908 mtls->mSliceSize = 1;
909 mtls->mSliceNum = 0;
910
Chris Wailes44bef6f2014-08-12 13:51:10 -0700911 mtls->fep.inPtrs = nullptr;
912 mtls->fep.inStrides = nullptr;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700913 mtls->isThreadable = mIsThreadable;
914
Chris Wailesf3712132014-07-16 15:18:30 -0700915 if (inLen > 0) {
916
917 if (inLen <= RS_KERNEL_INPUT_THRESHOLD) {
918 mtls->fep.inPtrs = (const uint8_t**)mtls->inPtrsBuff;
919 mtls->fep.inStrides = mtls->inStridesBuff;
920 } else {
921 mtls->fep.heapAllocatedArrays = true;
922
923 mtls->fep.inPtrs = new const uint8_t*[inLen];
924 mtls->fep.inStrides = new StridePair[inLen];
925 }
926
927 mtls->fep.inLen = inLen;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700928
929 for (int index = inLen; --index >= 0;) {
930 const Allocation *ain = ains[index];
931
Chris Wailesf3712132014-07-16 15:18:30 -0700932 mtls->fep.inPtrs[index] =
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700933 (const uint8_t*)ain->mHal.drvState.lod[0].mallocPtr;
934
935 mtls->fep.inStrides[index].eStride =
936 ain->getType()->getElementSizeBytes();
937 mtls->fep.inStrides[index].yStride =
938 ain->mHal.drvState.lod[0].stride;
939 }
940 }
941
Chris Wailes44bef6f2014-08-12 13:51:10 -0700942 mtls->fep.outPtr = nullptr;
Chris Wailesf3712132014-07-16 15:18:30 -0700943 mtls->fep.outStride.eStride = 0;
944 mtls->fep.outStride.yStride = 0;
Chris Wailes44bef6f2014-08-12 13:51:10 -0700945 if (aout != nullptr) {
Chris Wailesf3712132014-07-16 15:18:30 -0700946 mtls->fep.outPtr = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
947
948 mtls->fep.outStride.eStride = aout->getType()->getElementSizeBytes();
949 mtls->fep.outStride.yStride = aout->mHal.drvState.lod[0].stride;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700950 }
951}
952
Jason Sams709a0972012-11-15 18:18:04 -0800953
954void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
Chris Wailesf3712132014-07-16 15:18:30 -0700955 const Allocation ** ains,
956 uint32_t inLen,
Jason Sams709a0972012-11-15 18:18:04 -0800957 Allocation * aout,
958 const void * usr,
959 uint32_t usrLen,
960 const RsScriptCall *sc) {
961
962 MTLaunchStruct mtls;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700963
964 forEachMtlsSetup(ains, inLen, aout, usr, usrLen, sc, &mtls);
965 forEachKernelSetup(slot, &mtls);
966
967 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
968 mCtx->launchThreads(ains, inLen, aout, sc, &mtls);
969 mCtx->setTLS(oldTLS);
970}
971
Jason Sams709a0972012-11-15 18:18:04 -0800972void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
Jason Sams709a0972012-11-15 18:18:04 -0800973 mtls->script = this;
974 mtls->fep.slot = slot;
Jason Sams110f1812013-03-14 16:02:18 -0700975#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800976 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
977 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
978 mExecutable->getExportForeachFuncAddrs()[slot]);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700979 rsAssert(mtls->kernel != nullptr);
Jason Sams709a0972012-11-15 18:18:04 -0800980 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
Jason Sams110f1812013-03-14 16:02:18 -0700981#else
982 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
Chris Wailes44bef6f2014-08-12 13:51:10 -0700983 rsAssert(mtls->kernel != nullptr);
Jason Sams110f1812013-03-14 16:02:18 -0700984 mtls->sig = mForEachSignatures[slot];
985#endif
Jason Sams709a0972012-11-15 18:18:04 -0800986}
987
988int RsdCpuScriptImpl::invokeRoot() {
989 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
990 int ret = mRoot();
991 mCtx->setTLS(oldTLS);
992 return ret;
993}
994
995void RsdCpuScriptImpl::invokeInit() {
996 if (mInit) {
997 mInit();
998 }
999}
1000
1001void RsdCpuScriptImpl::invokeFreeChildren() {
1002 if (mFreeChildren) {
1003 mFreeChildren();
1004 }
1005}
1006
1007void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
1008 size_t paramLength) {
1009 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
1010
1011 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1012 reinterpret_cast<void (*)(const void *, uint32_t)>(
Jason Sams110f1812013-03-14 16:02:18 -07001013#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001014 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
Jason Sams110f1812013-03-14 16:02:18 -07001015#else
1016 mInvokeFunctions[slot])(params, paramLength);
1017#endif
Jason Sams709a0972012-11-15 18:18:04 -08001018 mCtx->setTLS(oldTLS);
1019}
1020
1021void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
1022 //rsAssert(!script->mFieldIsObject[slot]);
1023 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1024
1025 //if (mIntrinsicID) {
1026 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
1027 //return;
1028 //}
1029
Jason Sams110f1812013-03-14 16:02:18 -07001030#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001031 int32_t *destPtr = reinterpret_cast<int32_t *>(
1032 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001033#else
1034 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1035#endif
Jason Sams709a0972012-11-15 18:18:04 -08001036 if (!destPtr) {
1037 //ALOGV("Calling setVar on slot = %i which is null", slot);
1038 return;
1039 }
1040
1041 memcpy(destPtr, data, dataLength);
1042}
1043
Tim Murray9c642392013-04-11 13:29:59 -07001044void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
1045 //rsAssert(!script->mFieldIsObject[slot]);
1046 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1047
1048#ifndef RS_COMPATIBILITY_LIB
1049 int32_t *srcPtr = reinterpret_cast<int32_t *>(
1050 mExecutable->getExportVarAddrs()[slot]);
1051#else
1052 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1053#endif
1054 if (!srcPtr) {
1055 //ALOGV("Calling setVar on slot = %i which is null", slot);
1056 return;
1057 }
1058 memcpy(data, srcPtr, dataLength);
1059}
1060
1061
Jason Sams709a0972012-11-15 18:18:04 -08001062void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
1063 const Element *elem,
Stephen Hinesac8d1462014-06-25 00:01:23 -07001064 const uint32_t *dims, size_t dimLength) {
Jason Sams709a0972012-11-15 18:18:04 -08001065
Jason Sams110f1812013-03-14 16:02:18 -07001066#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001067 int32_t *destPtr = reinterpret_cast<int32_t *>(
1068 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001069#else
1070 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1071#endif
Jason Sams709a0972012-11-15 18:18:04 -08001072 if (!destPtr) {
1073 //ALOGV("Calling setVar on slot = %i which is null", slot);
1074 return;
1075 }
1076
1077 // We want to look at dimension in terms of integer components,
1078 // but dimLength is given in terms of bytes.
1079 dimLength /= sizeof(int);
1080
1081 // Only a single dimension is currently supported.
1082 rsAssert(dimLength == 1);
1083 if (dimLength == 1) {
1084 // First do the increment loop.
1085 size_t stride = elem->getSizeBytes();
1086 const char *cVal = reinterpret_cast<const char *>(data);
Stephen Hinesac8d1462014-06-25 00:01:23 -07001087 for (uint32_t i = 0; i < dims[0]; i++) {
Jason Sams709a0972012-11-15 18:18:04 -08001088 elem->incRefs(cVal);
1089 cVal += stride;
1090 }
1091
1092 // Decrement loop comes after (to prevent race conditions).
1093 char *oldVal = reinterpret_cast<char *>(destPtr);
Stephen Hinesac8d1462014-06-25 00:01:23 -07001094 for (uint32_t i = 0; i < dims[0]; i++) {
Jason Sams709a0972012-11-15 18:18:04 -08001095 elem->decRefs(oldVal);
1096 oldVal += stride;
1097 }
1098 }
1099
1100 memcpy(destPtr, data, dataLength);
1101}
1102
1103void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
1104
1105 //rsAssert(!script->mFieldIsObject[slot]);
1106 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
1107
Jason Sams110f1812013-03-14 16:02:18 -07001108#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001109 int32_t *destPtr = reinterpret_cast<int32_t *>(
1110 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001111#else
1112 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1113#endif
Jason Sams709a0972012-11-15 18:18:04 -08001114 if (!destPtr) {
1115 //ALOGV("Calling setVar on slot = %i which is null", slot);
1116 return;
1117 }
1118
Chris Wailes44bef6f2014-08-12 13:51:10 -07001119 void *ptr = nullptr;
Jason Sams709a0972012-11-15 18:18:04 -08001120 mBoundAllocs[slot] = data;
1121 if(data) {
1122 ptr = data->mHal.drvState.lod[0].mallocPtr;
1123 }
1124 memcpy(destPtr, &ptr, sizeof(void *));
1125}
1126
1127void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
1128
1129 //rsAssert(script->mFieldIsObject[slot]);
1130 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
1131
Jason Sams110f1812013-03-14 16:02:18 -07001132#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001133 int32_t *destPtr = reinterpret_cast<int32_t *>(
1134 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001135#else
1136 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1137#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001138
Jason Sams709a0972012-11-15 18:18:04 -08001139 if (!destPtr) {
1140 //ALOGV("Calling setVar on slot = %i which is null", slot);
1141 return;
1142 }
1143
Jason Sams05ef73f2014-08-05 14:59:22 -07001144 rsrSetObject(mCtx->getContext(), (rs_object_base *)destPtr, data);
Jason Sams709a0972012-11-15 18:18:04 -08001145}
1146
1147RsdCpuScriptImpl::~RsdCpuScriptImpl() {
Jason Sams110f1812013-03-14 16:02:18 -07001148#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001149 if (mExecutable) {
Chris Wailes70d49712014-08-08 14:42:33 -07001150 std::vector<void *>::const_iterator var_addr_iter =
Jason Sams709a0972012-11-15 18:18:04 -08001151 mExecutable->getExportVarAddrs().begin();
Chris Wailes70d49712014-08-08 14:42:33 -07001152 std::vector<void *>::const_iterator var_addr_end =
Jason Sams709a0972012-11-15 18:18:04 -08001153 mExecutable->getExportVarAddrs().end();
1154
1155 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
1156 mExecutable->getInfo().getObjectSlots().begin();
1157 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
1158 mExecutable->getInfo().getObjectSlots().end();
1159
1160 while ((var_addr_iter != var_addr_end) &&
1161 (is_object_iter != is_object_end)) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001162 // The field address can be nullptr if the script-side has optimized
Jason Sams709a0972012-11-15 18:18:04 -08001163 // the corresponding global variable away.
Jason Sams05ef73f2014-08-05 14:59:22 -07001164 rs_object_base *obj_addr =
1165 reinterpret_cast<rs_object_base *>(*var_addr_iter);
Jason Sams709a0972012-11-15 18:18:04 -08001166 if (*is_object_iter) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001167 if (*var_addr_iter != nullptr && mCtx->getContext() != nullptr) {
Jason Sams709a0972012-11-15 18:18:04 -08001168 rsrClearObject(mCtx->getContext(), obj_addr);
1169 }
1170 }
1171 var_addr_iter++;
1172 is_object_iter++;
1173 }
1174 }
1175
1176 if (mCompilerContext) {
1177 delete mCompilerContext;
1178 }
1179 if (mCompilerDriver) {
1180 delete mCompilerDriver;
1181 }
1182 if (mExecutable) {
1183 delete mExecutable;
1184 }
1185 if (mBoundAllocs) {
1186 delete[] mBoundAllocs;
1187 }
Tim Murraybee48d72014-06-13 12:44:47 -07001188
Tim Murray29809d12014-05-28 12:04:19 -07001189 for (size_t i = 0; i < mExportedForEachFuncList.size(); i++) {
1190 delete[] mExportedForEachFuncList[i].first;
1191 }
Jason Sams110f1812013-03-14 16:02:18 -07001192#else
1193 if (mFieldIsObject) {
1194 for (size_t i = 0; i < mExportedVariableCount; ++i) {
1195 if (mFieldIsObject[i]) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001196 if (mFieldAddress[i] != nullptr) {
Jason Sams05ef73f2014-08-05 14:59:22 -07001197 rs_object_base *obj_addr =
1198 reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
Jason Sams110f1812013-03-14 16:02:18 -07001199 rsrClearObject(mCtx->getContext(), obj_addr);
1200 }
1201 }
1202 }
1203 }
1204
1205 if (mInvokeFunctions) delete[] mInvokeFunctions;
1206 if (mForEachFunctions) delete[] mForEachFunctions;
1207 if (mFieldAddress) delete[] mFieldAddress;
1208 if (mFieldIsObject) delete[] mFieldIsObject;
1209 if (mForEachSignatures) delete[] mForEachSignatures;
1210 if (mBoundAllocs) delete[] mBoundAllocs;
1211 if (mScriptSO) {
1212 dlclose(mScriptSO);
1213 }
1214#endif
Jason Sams709a0972012-11-15 18:18:04 -08001215}
1216
1217Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
1218 if (!ptr) {
Chris Wailes44bef6f2014-08-12 13:51:10 -07001219 return nullptr;
Jason Sams709a0972012-11-15 18:18:04 -08001220 }
1221
1222 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
1223 Allocation *a = mBoundAllocs[ct];
1224 if (!a) continue;
1225 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
1226 return a;
1227 }
1228 }
1229 ALOGE("rsGetAllocation, failed to find %p", ptr);
Chris Wailes44bef6f2014-08-12 13:51:10 -07001230 return nullptr;
Jason Sams709a0972012-11-15 18:18:04 -08001231}
1232
Chris Wailesf3712132014-07-16 15:18:30 -07001233void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation ** ains,
1234 uint32_t inLen, Allocation * aout,
1235 const void * usr, uint32_t usrLen,
1236 const RsScriptCall *sc) {}
Jason Sams17e3cdc2013-09-09 17:32:16 -07001237
Chris Wailesf3712132014-07-16 15:18:30 -07001238void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation ** ains,
1239 uint32_t inLen, Allocation * aout,
1240 const void * usr, uint32_t usrLen,
1241 const RsScriptCall *sc) {}
Jason Sams17e3cdc2013-09-09 17:32:16 -07001242
Jason Sams709a0972012-11-15 18:18:04 -08001243
1244}
1245}