Renderscript Изображение Processign Nexus 6 Зефир выпуск

Я использую Renderscript для обработки живого изображения (предварительный просмотр камеры). У меня возникла проблема с Nexus 6 Marshmallow 6.1, когда некоторые из моих скриптов не будут работать более пары кадров (работает ядро ​​rs). Те же самые скрипты работают на Nexus 4 Lollipop 5.1 без нареканий.

Симптомы: скрипт работает на несколько запусков (сборок). При n-ом запуске некоторый скрипт перестает работать, как ожидалось, и все последующие запуски показывают вышеуказанную проблему. Я не смог установить какую-то конкретную операцию в коде, которая вызывает проблему. Это кажется совершенно случайным, по крайней мере, из того, что я могу собрать.

Что я попробовал:

  • Перезагрузка телефона, удаление приложения, очистка проектов, аннулирование кэшей в Android Studio не дают результатов.
  • Добавление rsDebug() за этот пост:
    Код RenderScript, не работающий без rsDebug, похоже, решил проблему, но после нескольких сборок проблема снова появилась.
  • Добавление rsDebug() в коде и на самом деле ведение журнала, по-видимому, запускает сценарий, как и предполагалось, но само собой разумеется, что это не решение, поскольку оно замедляет выполнение сценариев.
  • Удаление #pragma rs_fp_relaxed похоже, исправил проблему, но после нескольких сборок проблема снова появилась.
  • adb shell setprop debug.rs.default-CPU-driver 1 решает проблему, но весь смысл использования Renderscript заключался в использовании гетерогенных вычислений

Я использую эту подпись ядра uchar4 __attribute__((kernel)) filter(uchar4 v_in, uint32_t x, uint32_t y), хотя RS_KERNEL вызывает ту же проблему.

Спасибо за любую помощь и идеи.

Пример уязвимого кода: (демонстрационный код Google здесь: 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);
}

2 ответа

Решение

После долгих исследований я решил, что это, скорее всего, проблема с драйвером графического процессора. Сказав это, я упомянул выше, что я пытался удалить #pragma rs_fp_relaxed который, казалось, решил проблему временно. Теперь я считаю, что это была игра с выбором fp Точность, которую использовал RS, и это было причиной того, что иногда она работала, а иногда нет. Я пришел к такому выводу, когда я явно установить #pragma rs_fp_full который, кажется, устранил проблему навсегда, так как он, наряду с native функции, должны быть аппаратно-поддерживаемые вычисления (пока работает для всех сценариев, которые вызвали проблемы на Nexus 6).

В Интернете я обнаружил несколько случаев, когда люди решали проблемы с RS, устанавливая новые драйверы, но для меня это неприемлемо.

Напомним: я явно задал #pragma rs_fp_full,

Можете ли вы дважды проверить, что изображение, на которое вы пишете, не смотрит на альфа-канал, или попытаться установить его явно. (Это скорее комментарий, но мне не хватает очков)

Другие вопросы по тегам