rsdCore.cpp revision 3815badf95a7dca8aa278e3e12f07a3924a82319
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 rsdScriptSetGlobalVar, 64 rsdScriptSetGlobalBind, 65 rsdScriptSetGlobalObj, 66 rsdScriptDestroy 67 }, 68 69 { 70 rsdAllocationInit, 71 rsdAllocationDestroy, 72 rsdAllocationResize, 73 rsdAllocationSyncAll, 74 rsdAllocationMarkDirty, 75 rsdAllocationData1D, 76 rsdAllocationData2D, 77 rsdAllocationData3D, 78 rsdAllocationData1D_alloc, 79 rsdAllocationData2D_alloc, 80 rsdAllocationData3D_alloc, 81 rsdAllocationElementData1D, 82 rsdAllocationElementData2D 83 }, 84 85 86 { 87 rsdProgramStoreInit, 88 rsdProgramStoreSetActive, 89 rsdProgramStoreDestroy 90 }, 91 92 { 93 rsdProgramRasterInit, 94 rsdProgramRasterSetActive, 95 rsdProgramRasterDestroy 96 }, 97 98 { 99 rsdProgramVertexInit, 100 rsdProgramVertexSetActive, 101 rsdProgramVertexDestroy 102 }, 103 104 { 105 rsdProgramFragmentInit, 106 rsdProgramFragmentSetActive, 107 rsdProgramFragmentDestroy 108 }, 109 110 { 111 rsdMeshInit, 112 rsdMeshDraw, 113 rsdMeshDestroy 114 }, 115 116 { 117 rsdSamplerInit, 118 rsdSamplerDestroy 119 }, 120 121 { 122 rsdFrameBufferInit, 123 rsdFrameBufferSetActive, 124 rsdFrameBufferDestroy 125 }, 126 127}; 128 129pthread_key_t rsdgThreadTLSKey = 0; 130uint32_t rsdgThreadTLSKeyCount = 0; 131pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER; 132 133 134static void * HelperThreadProc(void *vrsc) { 135 Context *rsc = static_cast<Context *>(vrsc); 136 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 137 138 139 uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount); 140 141 //LOGV("RS helperThread starting %p idx=%i", rsc, idx); 142 143 dc->mWorkers.mLaunchSignals[idx].init(); 144 dc->mWorkers.mNativeThreadId[idx] = gettid(); 145 146 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 147 if (status) { 148 LOGE("pthread_setspecific %i", status); 149 } 150 151#if 0 152 typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t; 153 cpu_set_t cpuset; 154 memset(&cpuset, 0, sizeof(cpuset)); 155 cpuset.bits[idx / 64] |= 1ULL << (idx % 64); 156 int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx], 157 sizeof(cpuset), &cpuset); 158 LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret)); 159#endif 160 161 while (!dc->mExit) { 162 dc->mWorkers.mLaunchSignals[idx].wait(); 163 if (dc->mWorkers.mLaunchCallback) { 164 dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx); 165 } 166 android_atomic_dec(&dc->mWorkers.mRunningCount); 167 dc->mWorkers.mCompleteSignal.set(); 168 } 169 170 //LOGV("RS helperThread exited %p idx=%i", rsc, idx); 171 return NULL; 172} 173 174void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) { 175 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 176 177 dc->mWorkers.mLaunchData = data; 178 dc->mWorkers.mLaunchCallback = cbk; 179 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 180 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 181 dc->mWorkers.mLaunchSignals[ct].set(); 182 } 183 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 184 dc->mWorkers.mCompleteSignal.wait(); 185 } 186} 187 188bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) { 189 rsc->mHal.funcs = FunctionTable; 190 191 RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal)); 192 if (!dc) { 193 LOGE("Calloc for driver hal failed."); 194 return false; 195 } 196 rsc->mHal.drv = dc; 197 198 pthread_mutex_lock(&rsdgInitMutex); 199 if (!rsdgThreadTLSKeyCount) { 200 int status = pthread_key_create(&rsdgThreadTLSKey, NULL); 201 if (status) { 202 LOGE("Failed to init thread tls key."); 203 pthread_mutex_unlock(&rsdgInitMutex); 204 return false; 205 } 206 } 207 rsdgThreadTLSKeyCount++; 208 pthread_mutex_unlock(&rsdgInitMutex); 209 210 initForEach(dc->mForEachLaunch); 211 212 dc->mTlsStruct.mContext = rsc; 213 dc->mTlsStruct.mScript = NULL; 214 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 215 if (status) { 216 LOGE("pthread_setspecific %i", status); 217 } 218 219 220 int cpu = sysconf(_SC_NPROCESSORS_ONLN); 221 LOGV("RS Launching thread(s), reported CPU count %i", cpu); 222 if (cpu < 2) cpu = 0; 223 224 dc->mWorkers.mCount = (uint32_t)cpu; 225 dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t)); 226 dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t)); 227 dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount]; 228 dc->mWorkers.mLaunchCallback = NULL; 229 230 dc->mWorkers.mCompleteSignal.init(); 231 232 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 233 android_atomic_release_store(0, &dc->mWorkers.mLaunchCount); 234 235 pthread_attr_t threadAttr; 236 status = pthread_attr_init(&threadAttr); 237 if (status) { 238 LOGE("Failed to init thread attribute."); 239 return false; 240 } 241 242 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 243 status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc); 244 if (status) { 245 dc->mWorkers.mCount = ct; 246 LOGE("Created fewer than expected number of RS threads."); 247 break; 248 } 249 } 250 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 251 usleep(100); 252 } 253 254 pthread_attr_destroy(&threadAttr); 255 return true; 256} 257 258 259void SetPriority(const Context *rsc, int32_t priority) { 260 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 261 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 262 setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority); 263 } 264} 265 266void Shutdown(Context *rsc) { 267 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 268 269 dc->mExit = true; 270 dc->mWorkers.mLaunchData = NULL; 271 dc->mWorkers.mLaunchCallback = NULL; 272 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 273 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 274 dc->mWorkers.mLaunchSignals[ct].set(); 275 } 276 int status; 277 void *res; 278 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 279 status = pthread_join(dc->mWorkers.mThreadId[ct], &res); 280 } 281 rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0); 282 283 // Global structure cleanup. 284 pthread_mutex_lock(&rsdgInitMutex); 285 --rsdgThreadTLSKeyCount; 286 if (!rsdgThreadTLSKeyCount) { 287 pthread_key_delete(rsdgThreadTLSKey); 288 } 289 pthread_mutex_unlock(&rsdgInitMutex); 290 291} 292 293static void rsdForEach17(const void *vRoot, 294 const android::renderscript::RsForEachStubParamStruct *p) { 295 typedef void (*fe)(const void *, uint32_t); 296 (*(fe*)vRoot)(p->in, p->y); 297} 298 299static void rsdForEach18(const void *vRoot, 300 const android::renderscript::RsForEachStubParamStruct *p) { 301 typedef void (*fe)(void *, uint32_t); 302 (*(fe*)vRoot)(p->out, p->y); 303} 304 305static void rsdForEach19(const void *vRoot, 306 const android::renderscript::RsForEachStubParamStruct *p) { 307 typedef void (*fe)(const void *, void *, uint32_t); 308 (*(fe*)vRoot)(p->in, p->out, p->y); 309} 310 311static void rsdForEach21(const void *vRoot, 312 const android::renderscript::RsForEachStubParamStruct *p) { 313 typedef void (*fe)(const void *, const void *, uint32_t); 314 (*(fe*)vRoot)(p->in, p->usr, p->y); 315} 316 317static void rsdForEach22(const void *vRoot, 318 const android::renderscript::RsForEachStubParamStruct *p) { 319 typedef void (*fe)(void *, const void *, uint32_t); 320 (*(fe*)vRoot)(p->out, p->usr, p->y); 321} 322 323static void rsdForEach23(const void *vRoot, 324 const android::renderscript::RsForEachStubParamStruct *p) { 325 typedef void (*fe)(const void *, void *, const void *, uint32_t); 326 (*(fe*)vRoot)(p->in, p->out, p->usr, p->y); 327} 328 329static void rsdForEach25(const void *vRoot, 330 const android::renderscript::RsForEachStubParamStruct *p) { 331 typedef void (*fe)(const void *, uint32_t, uint32_t); 332 (*(fe*)vRoot)(p->in, p->x, p->y); 333} 334 335static void rsdForEach26(const void *vRoot, 336 const android::renderscript::RsForEachStubParamStruct *p) { 337 typedef void (*fe)(void *, uint32_t, uint32_t); 338 (*(fe*)vRoot)(p->out, p->x, p->y); 339} 340 341static void rsdForEach27(const void *vRoot, 342 const android::renderscript::RsForEachStubParamStruct *p) { 343 typedef void (*fe)(const void *, void *, uint32_t, uint32_t); 344 (*(fe*)vRoot)(p->in, p->out, p->x, p->y); 345} 346 347static void rsdForEach29(const void *vRoot, 348 const android::renderscript::RsForEachStubParamStruct *p) { 349 typedef void (*fe)(const void *, const void *, uint32_t, uint32_t); 350 (*(fe*)vRoot)(p->in, p->usr, p->x, p->y); 351} 352 353static void rsdForEach30(const void *vRoot, 354 const android::renderscript::RsForEachStubParamStruct *p) { 355 typedef void (*fe)(void *, const void *, uint32_t, uint32_t); 356 (*(fe*)vRoot)(p->out, p->usr, p->x, p->y); 357} 358 359static void rsdForEach31(const void *vRoot, 360 const android::renderscript::RsForEachStubParamStruct *p) { 361 typedef void (*fe)(const void *, void *, const void *, uint32_t, uint32_t); 362 (*(fe*)vRoot)(p->in, p->out, p->usr, p->x, p->y); 363} 364 365 366static void initForEach(outer_foreach_t* forEachLaunch) { 367 rsAssert(forEachLaunch); 368 forEachLaunch[0x00] = NULL; 369 forEachLaunch[0x01] = rsdForEach31; // in 370 forEachLaunch[0x02] = rsdForEach30; // out 371 forEachLaunch[0x03] = rsdForEach31; // in, out 372 forEachLaunch[0x04] = NULL; 373 forEachLaunch[0x05] = rsdForEach29; // in, usr 374 forEachLaunch[0x06] = rsdForEach30; // out, usr 375 forEachLaunch[0x07] = rsdForEach31; // in, out, usr 376 forEachLaunch[0x08] = NULL; 377 forEachLaunch[0x09] = rsdForEach25; // in, x 378 forEachLaunch[0x0a] = rsdForEach26; // out, x 379 forEachLaunch[0x0b] = rsdForEach27; // in, out, x 380 forEachLaunch[0x0c] = NULL; 381 forEachLaunch[0x0d] = rsdForEach29; // in, usr, x 382 forEachLaunch[0x0e] = rsdForEach30; // out, usr, x 383 forEachLaunch[0x0f] = rsdForEach31; // in, out, usr, x 384 forEachLaunch[0x10] = NULL; 385 forEachLaunch[0x11] = rsdForEach17; // in y 386 forEachLaunch[0x12] = rsdForEach18; // out, y 387 forEachLaunch[0x13] = rsdForEach19; // in, out, y 388 forEachLaunch[0x14] = NULL; 389 forEachLaunch[0x15] = rsdForEach21; // in, usr, y 390 forEachLaunch[0x16] = rsdForEach22; // out, usr, y 391 forEachLaunch[0x17] = rsdForEach23; // in, out, usr, y 392 forEachLaunch[0x18] = NULL; 393 forEachLaunch[0x19] = rsdForEach25; // in, x, y 394 forEachLaunch[0x1a] = rsdForEach26; // out, x, y 395 forEachLaunch[0x1b] = rsdForEach27; // in, out, x, y 396 forEachLaunch[0x1c] = NULL; 397 forEachLaunch[0x1d] = rsdForEach29; // in, usr, x, y 398 forEachLaunch[0x1e] = rsdForEach30; // out, usr, x, y 399 forEachLaunch[0x1f] = rsdForEach31; // in, out, usr, x, y 400} 401 402