rsdCore.cpp revision 4ee16ffbd9d1d72e1757c9b26715597fdc044117
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "rsdCore.h" 18#include "rsdAllocation.h" 19#include "rsdBcc.h" 20#include "rsdGL.h" 21#include "rsdProgramStore.h" 22#include "rsdProgramRaster.h" 23#include "rsdProgramVertex.h" 24#include "rsdProgramFragment.h" 25#include "rsdMesh.h" 26#include "rsdSampler.h" 27#include "rsdFrameBuffer.h" 28 29#include <malloc.h> 30#include "rsContext.h" 31 32#include <sys/types.h> 33#include <sys/resource.h> 34#include <sched.h> 35#include <cutils/properties.h> 36#include <cutils/sched_policy.h> 37#include <sys/syscall.h> 38#include <string.h> 39#include <bcc/bcc.h> 40 41using namespace android; 42using namespace android::renderscript; 43 44static void Shutdown(Context *rsc); 45static void SetPriority(const Context *rsc, int32_t priority); 46static void initForEach(outer_foreach_t* forEachLaunch); 47 48static RsdHalFunctions FunctionTable = { 49 rsdGLInit, 50 rsdGLShutdown, 51 rsdGLSetSurface, 52 rsdGLSwap, 53 54 Shutdown, 55 NULL, 56 SetPriority, 57 { 58 rsdScriptInit, 59 rsdScriptInvokeFunction, 60 rsdScriptInvokeRoot, 61 rsdScriptInvokeForEach, 62 rsdScriptInvokeInit, 63 rsdScriptInvokeFreeChildren, 64 rsdScriptSetGlobalVar, 65 rsdScriptSetGlobalBind, 66 rsdScriptSetGlobalObj, 67 rsdScriptDestroy 68 }, 69 70 { 71 rsdAllocationInit, 72 rsdAllocationDestroy, 73 rsdAllocationResize, 74 rsdAllocationSyncAll, 75 rsdAllocationMarkDirty, 76 rsdAllocationData1D, 77 rsdAllocationData2D, 78 rsdAllocationData3D, 79 rsdAllocationData1D_alloc, 80 rsdAllocationData2D_alloc, 81 rsdAllocationData3D_alloc, 82 rsdAllocationElementData1D, 83 rsdAllocationElementData2D 84 }, 85 86 87 { 88 rsdProgramStoreInit, 89 rsdProgramStoreSetActive, 90 rsdProgramStoreDestroy 91 }, 92 93 { 94 rsdProgramRasterInit, 95 rsdProgramRasterSetActive, 96 rsdProgramRasterDestroy 97 }, 98 99 { 100 rsdProgramVertexInit, 101 rsdProgramVertexSetActive, 102 rsdProgramVertexDestroy 103 }, 104 105 { 106 rsdProgramFragmentInit, 107 rsdProgramFragmentSetActive, 108 rsdProgramFragmentDestroy 109 }, 110 111 { 112 rsdMeshInit, 113 rsdMeshDraw, 114 rsdMeshDestroy 115 }, 116 117 { 118 rsdSamplerInit, 119 rsdSamplerDestroy 120 }, 121 122 { 123 rsdFrameBufferInit, 124 rsdFrameBufferSetActive, 125 rsdFrameBufferDestroy 126 }, 127 128}; 129 130pthread_key_t rsdgThreadTLSKey = 0; 131uint32_t rsdgThreadTLSKeyCount = 0; 132pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER; 133 134 135static void * HelperThreadProc(void *vrsc) { 136 Context *rsc = static_cast<Context *>(vrsc); 137 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 138 139 140 uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount); 141 142 //LOGV("RS helperThread starting %p idx=%i", rsc, idx); 143 144 dc->mWorkers.mLaunchSignals[idx].init(); 145 dc->mWorkers.mNativeThreadId[idx] = gettid(); 146 147 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 148 if (status) { 149 LOGE("pthread_setspecific %i", status); 150 } 151 152#if 0 153 typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t; 154 cpu_set_t cpuset; 155 memset(&cpuset, 0, sizeof(cpuset)); 156 cpuset.bits[idx / 64] |= 1ULL << (idx % 64); 157 int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx], 158 sizeof(cpuset), &cpuset); 159 LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret)); 160#endif 161 162 while (!dc->mExit) { 163 dc->mWorkers.mLaunchSignals[idx].wait(); 164 if (dc->mWorkers.mLaunchCallback) { 165 dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx); 166 } 167 android_atomic_dec(&dc->mWorkers.mRunningCount); 168 dc->mWorkers.mCompleteSignal.set(); 169 } 170 171 //LOGV("RS helperThread exited %p idx=%i", rsc, idx); 172 return NULL; 173} 174 175void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) { 176 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 177 178 dc->mWorkers.mLaunchData = data; 179 dc->mWorkers.mLaunchCallback = cbk; 180 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 181 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 182 dc->mWorkers.mLaunchSignals[ct].set(); 183 } 184 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 185 dc->mWorkers.mCompleteSignal.wait(); 186 } 187} 188 189bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) { 190 rsc->mHal.funcs = FunctionTable; 191 192 RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal)); 193 if (!dc) { 194 LOGE("Calloc for driver hal failed."); 195 return false; 196 } 197 rsc->mHal.drv = dc; 198 199 pthread_mutex_lock(&rsdgInitMutex); 200 if (!rsdgThreadTLSKeyCount) { 201 int status = pthread_key_create(&rsdgThreadTLSKey, NULL); 202 if (status) { 203 LOGE("Failed to init thread tls key."); 204 pthread_mutex_unlock(&rsdgInitMutex); 205 return false; 206 } 207 } 208 rsdgThreadTLSKeyCount++; 209 pthread_mutex_unlock(&rsdgInitMutex); 210 211 initForEach(dc->mForEachLaunch); 212 213 dc->mTlsStruct.mContext = rsc; 214 dc->mTlsStruct.mScript = NULL; 215 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 216 if (status) { 217 LOGE("pthread_setspecific %i", status); 218 } 219 220 221 int cpu = sysconf(_SC_NPROCESSORS_ONLN); 222 LOGV("RS Launching thread(s), reported CPU count %i", cpu); 223 if (cpu < 2) cpu = 0; 224 225 dc->mWorkers.mCount = (uint32_t)cpu; 226 dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t)); 227 dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t)); 228 dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount]; 229 dc->mWorkers.mLaunchCallback = NULL; 230 231 dc->mWorkers.mCompleteSignal.init(); 232 233 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 234 android_atomic_release_store(0, &dc->mWorkers.mLaunchCount); 235 236 pthread_attr_t threadAttr; 237 status = pthread_attr_init(&threadAttr); 238 if (status) { 239 LOGE("Failed to init thread attribute."); 240 return false; 241 } 242 243 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 244 status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc); 245 if (status) { 246 dc->mWorkers.mCount = ct; 247 LOGE("Created fewer than expected number of RS threads."); 248 break; 249 } 250 } 251 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 252 usleep(100); 253 } 254 255 pthread_attr_destroy(&threadAttr); 256 return true; 257} 258 259 260void SetPriority(const Context *rsc, int32_t priority) { 261 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 262 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 263 setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority); 264 } 265} 266 267void Shutdown(Context *rsc) { 268 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 269 270 dc->mExit = true; 271 dc->mWorkers.mLaunchData = NULL; 272 dc->mWorkers.mLaunchCallback = NULL; 273 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 274 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 275 dc->mWorkers.mLaunchSignals[ct].set(); 276 } 277 int status; 278 void *res; 279 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 280 status = pthread_join(dc->mWorkers.mThreadId[ct], &res); 281 } 282 rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0); 283 284 // Global structure cleanup. 285 pthread_mutex_lock(&rsdgInitMutex); 286 --rsdgThreadTLSKeyCount; 287 if (!rsdgThreadTLSKeyCount) { 288 pthread_key_delete(rsdgThreadTLSKey); 289 } 290 pthread_mutex_unlock(&rsdgInitMutex); 291 292} 293 294static void rsdForEach17(const void *vRoot, 295 const android::renderscript::RsForEachStubParamStruct *p) { 296 typedef void (*fe)(const void *, uint32_t); 297 (*(fe*)vRoot)(p->in, p->y); 298} 299 300static void rsdForEach18(const void *vRoot, 301 const android::renderscript::RsForEachStubParamStruct *p) { 302 typedef void (*fe)(void *, uint32_t); 303 (*(fe*)vRoot)(p->out, p->y); 304} 305 306static void rsdForEach19(const void *vRoot, 307 const android::renderscript::RsForEachStubParamStruct *p) { 308 typedef void (*fe)(const void *, void *, uint32_t); 309 (*(fe*)vRoot)(p->in, p->out, p->y); 310} 311 312static void rsdForEach21(const void *vRoot, 313 const android::renderscript::RsForEachStubParamStruct *p) { 314 typedef void (*fe)(const void *, const void *, uint32_t); 315 (*(fe*)vRoot)(p->in, p->usr, p->y); 316} 317 318static void rsdForEach22(const void *vRoot, 319 const android::renderscript::RsForEachStubParamStruct *p) { 320 typedef void (*fe)(void *, const void *, uint32_t); 321 (*(fe*)vRoot)(p->out, p->usr, p->y); 322} 323 324static void rsdForEach23(const void *vRoot, 325 const android::renderscript::RsForEachStubParamStruct *p) { 326 typedef void (*fe)(const void *, void *, const void *, uint32_t); 327 (*(fe*)vRoot)(p->in, p->out, p->usr, p->y); 328} 329 330static void rsdForEach25(const void *vRoot, 331 const android::renderscript::RsForEachStubParamStruct *p) { 332 typedef void (*fe)(const void *, uint32_t, uint32_t); 333 (*(fe*)vRoot)(p->in, p->x, p->y); 334} 335 336static void rsdForEach26(const void *vRoot, 337 const android::renderscript::RsForEachStubParamStruct *p) { 338 typedef void (*fe)(void *, uint32_t, uint32_t); 339 (*(fe*)vRoot)(p->out, p->x, p->y); 340} 341 342static void rsdForEach27(const void *vRoot, 343 const android::renderscript::RsForEachStubParamStruct *p) { 344 typedef void (*fe)(const void *, void *, uint32_t, uint32_t); 345 (*(fe*)vRoot)(p->in, p->out, p->x, p->y); 346} 347 348static void rsdForEach29(const void *vRoot, 349 const android::renderscript::RsForEachStubParamStruct *p) { 350 typedef void (*fe)(const void *, const void *, uint32_t, uint32_t); 351 (*(fe*)vRoot)(p->in, p->usr, p->x, p->y); 352} 353 354static void rsdForEach30(const void *vRoot, 355 const android::renderscript::RsForEachStubParamStruct *p) { 356 typedef void (*fe)(void *, const void *, uint32_t, uint32_t); 357 (*(fe*)vRoot)(p->out, p->usr, p->x, p->y); 358} 359 360static void rsdForEach31(const void *vRoot, 361 const android::renderscript::RsForEachStubParamStruct *p) { 362 typedef void (*fe)(const void *, void *, const void *, uint32_t, uint32_t); 363 (*(fe*)vRoot)(p->in, p->out, p->usr, p->x, p->y); 364} 365 366 367static void initForEach(outer_foreach_t* forEachLaunch) { 368 rsAssert(forEachLaunch); 369 forEachLaunch[0x00] = NULL; 370 forEachLaunch[0x01] = rsdForEach31; // in 371 forEachLaunch[0x02] = rsdForEach30; // out 372 forEachLaunch[0x03] = rsdForEach31; // in, out 373 forEachLaunch[0x04] = NULL; 374 forEachLaunch[0x05] = rsdForEach29; // in, usr 375 forEachLaunch[0x06] = rsdForEach30; // out, usr 376 forEachLaunch[0x07] = rsdForEach31; // in, out, usr 377 forEachLaunch[0x08] = NULL; 378 forEachLaunch[0x09] = rsdForEach25; // in, x 379 forEachLaunch[0x0a] = rsdForEach26; // out, x 380 forEachLaunch[0x0b] = rsdForEach27; // in, out, x 381 forEachLaunch[0x0c] = NULL; 382 forEachLaunch[0x0d] = rsdForEach29; // in, usr, x 383 forEachLaunch[0x0e] = rsdForEach30; // out, usr, x 384 forEachLaunch[0x0f] = rsdForEach31; // in, out, usr, x 385 forEachLaunch[0x10] = NULL; 386 forEachLaunch[0x11] = rsdForEach17; // in y 387 forEachLaunch[0x12] = rsdForEach18; // out, y 388 forEachLaunch[0x13] = rsdForEach19; // in, out, y 389 forEachLaunch[0x14] = NULL; 390 forEachLaunch[0x15] = rsdForEach21; // in, usr, y 391 forEachLaunch[0x16] = rsdForEach22; // out, usr, y 392 forEachLaunch[0x17] = rsdForEach23; // in, out, usr, y 393 forEachLaunch[0x18] = NULL; 394 forEachLaunch[0x19] = rsdForEach25; // in, x, y 395 forEachLaunch[0x1a] = rsdForEach26; // out, x, y 396 forEachLaunch[0x1b] = rsdForEach27; // in, out, x, y 397 forEachLaunch[0x1c] = NULL; 398 forEachLaunch[0x1d] = rsdForEach29; // in, usr, x, y 399 forEachLaunch[0x1e] = rsdForEach30; // out, usr, x, y 400 forEachLaunch[0x1f] = rsdForEach31; // in, out, usr, x, y 401} 402 403