简体   繁体   中英

Renderscript image processign Nexus 6 Marshmallow issue

I am using renderscript for live image processing (camera preview). I am having an issue on Nexus 6 Marshmallow 6.1 where some of my scripts won't run for more than a couple of frames (rs kernel runs). Those same scripts work flawlessly on Nexus 4 Lollipop 5.1.

Symptoms: Script works for several runs (builds). On an nth run some script ceases to work as expected and all subsequent runs exhibit the above issue. I haven't been able to establish some particular operation in code which causes the issue. It appears completely random, at least from what I can gather.

What iv'e tried:

  • Rebooting phone, uninstalling app, cleaning the projects, invalidating caches in Android Studio produce no results.
  • Adding rsDebug() per this post:
    RenderScript code not working without rsDebug seemed to have fixed the problem, but after a few builds problem reappeared.
  • Adding rsDebug() in code and actually logging appears to run the script as intended, but needless to say this is no solution since it slows the scripts down to a halt.
  • Removing #pragma rs_fp_relaxed seemed to have fixed the problem, but after a few builds problem reappeared.
  • adb shell setprop debug.rs.default-CPU-driver 1 fixes the problem, but the whole point of using renderscript was to utilize heterogeneous computing

I am using this kernel signature uchar4 __attribute__((kernel)) filter(uchar4 v_in, uint32_t x, uint32_t y) , although RS_KERNEL causes the same issue.

Thanks for any help and ideas.

Sample of affected code: (Google demo code from here: https://android.googlesource.com/platform/frameworks/rs/+/master/java/tests/ImageProcessing2/src/com/android/rs/image/ )

static float sr = 0.f;
static float sg = 0.f;
static float sb = 0.f;

void prepareBwFilter(uint32_t rw, uint32_t gw, uint32_t bw) {

    sr = rw;
    sg = gw;
    sb = bw;

    float imageMin = min(sg,sb);
    imageMin = fmin(sr,imageMin);
    float imageMax = max(sg,sb);
    imageMax = fmax(sr,imageMax);
    float avg = (imageMin + imageMax)/2;
    sb /= avg;
    sg /= avg;
    sr /= avg;

}

void bwFilterKernel(const uchar4 *in, uchar4 *out) {
    float r = in->r * sr;
    float g = in->g * sg;
    float b = in->b * sb;
    float localMin, localMax, avg;
    localMin = fmin(g,b);
    localMin = fmin(r,localMin);
    localMax = fmax(g,b);
    localMax = fmax(r,localMax);
    avg = (localMin+localMax) * 0.5f;
    out->r = out->g = out->b = rsClamp(avg, 0, 255);
}

Can you double check the image you are writing to is not looking at the alpha channel or try to set it explicitly. (This is more of a comment, but I don't have enough points)

After quite a bit of research I decided that this is most probably a GPU driver issue. Having said that, I mentioned above that I tried removing #pragma rs_fp_relaxed which appeared to have solved the problem temporarily. I now believe that it was a gamble with the choice of fp precision RS was using and that that was the reason it sometimes worked and sometimes not. I came to this conclusion when i explicitly set #pragma rs_fp_full which seems to have fixed the issue permanently since it, along with native functions, should be a hardware backed calculation (so far works for all scripts that caused problems on Nexus 6).

I found a few cases on the web with people solving RS issues by flashing new drivers, but this is unacceptable for me.

To recap: I explicitly set #pragma rs_fp_full .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM