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