/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "rsCpuCore.h" #include "rsCpuScript.h" #include "rsScriptGroup.h" #include "rsCpuScriptGroup.h" //#include "rsdBcc.h" //#include "rsdAllocation.h" using namespace android; using namespace android::renderscript; CpuScriptGroupImpl::CpuScriptGroupImpl(RsdCpuReferenceImpl *ctx, const ScriptGroup *sg) { mCtx = ctx; mSG = sg; } CpuScriptGroupImpl::~CpuScriptGroupImpl() { } bool CpuScriptGroupImpl::init() { return true; } void CpuScriptGroupImpl::setInput(const ScriptKernelID *kid, Allocation *a) { } void CpuScriptGroupImpl::setOutput(const ScriptKernelID *kid, Allocation *a) { } typedef void (*ScriptGroupRootFunc_t)(const RsForEachStubParamStruct *p, uint32_t xstart, uint32_t xend, uint32_t instep, uint32_t outstep); void CpuScriptGroupImpl::scriptGroupRoot(const RsForEachStubParamStruct *p, uint32_t xstart, uint32_t xend, uint32_t instep, uint32_t outstep) { const ScriptList *sl = (const ScriptList *)p->usr; RsForEachStubParamStruct *mp = (RsForEachStubParamStruct *)p; const void *oldUsr = p->usr; for(size_t ct=0; ct < sl->count; ct++) { ScriptGroupRootFunc_t func; func = (ScriptGroupRootFunc_t)sl->fnPtrs[ct]; mp->usr = sl->usrPtrs[ct]; mp->ptrIn = NULL; mp->in = NULL; mp->ptrOut = NULL; mp->out = NULL; uint32_t istep = 0; uint32_t ostep = 0; if (sl->ins[ct]) { mp->ptrIn = (const uint8_t *)sl->ins[ct]->mHal.drvState.lod[0].mallocPtr; istep = sl->ins[ct]->mHal.state.elementSizeBytes; mp->in = mp->ptrIn; if (sl->inExts[ct]) { mp->in = mp->ptrIn + sl->ins[ct]->mHal.drvState.lod[0].stride * p->y; } else { if (sl->ins[ct]->mHal.drvState.lod[0].dimY > p->lid) { mp->in = mp->ptrIn + sl->ins[ct]->mHal.drvState.lod[0].stride * p->lid; } } } if (sl->outs[ct]) { mp->ptrOut = (uint8_t *)sl->outs[ct]->mHal.drvState.lod[0].mallocPtr; mp->out = mp->ptrOut; ostep = sl->outs[ct]->mHal.state.elementSizeBytes; if (sl->outExts[ct]) { mp->out = mp->ptrOut + sl->outs[ct]->mHal.drvState.lod[0].stride * p->y; } else { if (sl->outs[ct]->mHal.drvState.lod[0].dimY > p->lid) { mp->out = mp->ptrOut + sl->outs[ct]->mHal.drvState.lod[0].stride * p->lid; } } } //ALOGE("kernel %i %p,%p %p,%p", ct, mp->ptrIn, mp->in, mp->ptrOut, mp->out); func(p, xstart, xend, istep, ostep); } //ALOGE("script group root"); //ConvolveParams *cp = (ConvolveParams *)p->usr; mp->usr = oldUsr; } void CpuScriptGroupImpl::execute() { Vector<Allocation *> ins; Vector<bool> inExts; Vector<Allocation *> outs; Vector<bool> outExts; Vector<const ScriptKernelID *> kernels; bool fieldDep = false; for (size_t ct=0; ct < mSG->mNodes.size(); ct++) { ScriptGroup::Node *n = mSG->mNodes[ct]; Script *s = n->mKernels[0]->mScript; if (s->hasObjectSlots()) { // Disable the ScriptGroup optimization if we have global RS // objects that might interfere between kernels. fieldDep = true; } //ALOGE("node %i, order %i, in %i out %i", (int)ct, n->mOrder, (int)n->mInputs.size(), (int)n->mOutputs.size()); for (size_t ct2=0; ct2 < n->mInputs.size(); ct2++) { if (n->mInputs[ct2]->mDstField.get() && n->mInputs[ct2]->mDstField->mScript) { //ALOGE("field %p %zu", n->mInputs[ct2]->mDstField->mScript, n->mInputs[ct2]->mDstField->mSlot); s->setVarObj(n->mInputs[ct2]->mDstField->mSlot, n->mInputs[ct2]->mAlloc.get()); } } for (size_t ct2=0; ct2 < n->mKernels.size(); ct2++) { const ScriptKernelID *k = n->mKernels[ct2]; Allocation *ain = NULL; Allocation *aout = NULL; bool inExt = false; bool outExt = false; for (size_t ct3=0; ct3 < n->mInputs.size(); ct3++) { if (n->mInputs[ct3]->mDstKernel.get() == k) { ain = n->mInputs[ct3]->mAlloc.get(); break; } } if (ain == NULL) { for (size_t ct3=0; ct3 < mSG->mInputs.size(); ct3++) { if (mSG->mInputs[ct3]->mKernel == k) { ain = mSG->mInputs[ct3]->mAlloc.get(); inExt = true; break; } } } for (size_t ct3=0; ct3 < n->mOutputs.size(); ct3++) { if (n->mOutputs[ct3]->mSource.get() == k) { aout = n->mOutputs[ct3]->mAlloc.get(); if(n->mOutputs[ct3]->mDstField.get() != NULL) { fieldDep = true; } break; } } if (aout == NULL) { for (size_t ct3=0; ct3 < mSG->mOutputs.size(); ct3++) { if (mSG->mOutputs[ct3]->mKernel == k) { aout = mSG->mOutputs[ct3]->mAlloc.get(); outExt = true; break; } } } rsAssert((k->mHasKernelOutput == (aout != NULL)) && (k->mHasKernelInput == (ain != NULL))); ins.add(ain); inExts.add(inExt); outs.add(aout); outExts.add(outExt); kernels.add(k); } } MTLaunchStruct mtls; if(fieldDep) { for (size_t ct=0; ct < ins.size(); ct++) { Script *s = kernels[ct]->mScript; RsdCpuScriptImpl *si = (RsdCpuScriptImpl *)mCtx->lookupScript(s); uint32_t slot = kernels[ct]->mSlot; si->forEachMtlsSetup(ins[ct], outs[ct], NULL, 0, NULL, &mtls); si->forEachKernelSetup(slot, &mtls); si->preLaunch(slot, ins[ct], outs[ct], mtls.fep.usr, mtls.fep.usrLen, NULL); mCtx->launchThreads(ins[ct], outs[ct], NULL, &mtls); si->postLaunch(slot, ins[ct], outs[ct], NULL, 0, NULL); } } else { ScriptList sl; sl.ins = ins.array(); sl.outs = outs.array(); sl.kernels = kernels.array(); sl.count = kernels.size(); Vector<const void *> usrPtrs; Vector<const void *> fnPtrs; Vector<uint32_t> sigs; for (size_t ct=0; ct < kernels.size(); ct++) { Script *s = kernels[ct]->mScript; RsdCpuScriptImpl *si = (RsdCpuScriptImpl *)mCtx->lookupScript(s); si->forEachKernelSetup(kernels[ct]->mSlot, &mtls); fnPtrs.add((void *)mtls.kernel); usrPtrs.add(mtls.fep.usr); sigs.add(mtls.fep.usrLen); si->preLaunch(kernels[ct]->mSlot, ins[ct], outs[ct], mtls.fep.usr, mtls.fep.usrLen, NULL); } sl.sigs = sigs.array(); sl.usrPtrs = usrPtrs.array(); sl.fnPtrs = fnPtrs.array(); sl.inExts = inExts.array(); sl.outExts = outExts.array(); Script *s = kernels[0]->mScript; RsdCpuScriptImpl *si = (RsdCpuScriptImpl *)mCtx->lookupScript(s); si->forEachMtlsSetup(ins[0], outs[0], NULL, 0, NULL, &mtls); mtls.script = NULL; mtls.kernel = (void (*)())&scriptGroupRoot; mtls.fep.usr = &sl; mCtx->launchThreads(ins[0], outs[0], NULL, &mtls); for (size_t ct=0; ct < kernels.size(); ct++) { Script *s = kernels[ct]->mScript; RsdCpuScriptImpl *si = (RsdCpuScriptImpl *)mCtx->lookupScript(s); si->postLaunch(kernels[ct]->mSlot, ins[ct], outs[ct], NULL, 0, NULL); } } }