преобразование глубины с помощью неоновых присадок ARM - PullRequest
1 голос
/ 26 февраля 2012

Я пытаюсь обернуть голову вокруг сущности NEON и решил, что могу начать с примера и задать несколько вопросов.

В этом эксперименте я хочу преобразовать 32-битный RGB в 16-битный BGR.Что было бы хорошим началом для преобразования следующего кода для использования встроенных функций NEON?Проблема, с которой я столкнулся здесь, заключается в том, что 16-битная система не соответствует какой-либо внутренней характеристике, которую я вижу.Есть 16х4, 16х8 и т. Д., Но мне просто не везет, когда я обдумываю, как мне к этому подойти.Любые советы?

Вот код, который я пытаюсь преобразовать.

typedef struct {
    uint16_t b:5, g:6, r:5;
} _color16;

static int depth_transform_32_to_16_c (VisVideo *dest, VisVideo *src)
{
    int x, y;
    int w;
    int h;

    _color16 *dbuf = visual_video_get_pixels (dest);
    uint8_t *sbuf = visual_video_get_pixels (src);

    uint16x8

    int ddiff;
    int sdiff;

    depth_transform_get_smallest (dest, src, &w, &h);

    ddiff = (dest->pitch / dest->bpp) - w;
    sdiff = src->pitch - (w * src->bpp);

    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            dbuf->b = *(sbuf++) >> 3;
            dbuf->g = *(sbuf++) >> 2;
            dbuf->r = *(sbuf++) >> 3;

            dbuf++;
            sbuf++;
        }

        dbuf += ddiff;
        sbuf += sdiff;
    }

    return VISUAL_OK;
}

Редактировать: о, почему-то я смотрел на это с учетом 16x3 бит, но мы смотрим на5,6,5 = 16 бит.Я понимаю, что мне нужны смены.Хм.

1 Ответ

4 голосов
/ 26 февраля 2012

NEON использует 128-битные регистры, так что концептуально, что вы хотите сделать, это прочитать в четырех пикселях 32-битного RGB, использовать побитовые операции с ними и в конечном итоге записать ваши 16-битные пиксели.Одним из наблюдений является то, что для лучшей производительности вы можете объединить два 128-битных входа (8 32-битных пикселей) и создать один 128-битный выход.Это сделает доступ к вашей памяти более эффективным.

Еще один способ подумать об этом заключается в том, что вы берете содержимое внутреннего цикла и выполняете четыре пикселя параллельно.Причина, по которой немного сложно работать с исходным кодом, заключается в том, что часть «магии» скрыта, потому что вы используете битовые поля.Если вы переписали свой код C для работы с 32-битных на 16-битные и использовали сдвиги / и / или этот код переводил бы в SIMD более естественным образом, и вы можете визуализировать, как вы будете работать с несколькими данными в этом контексте.

Если вы просто посмотрите на каждый 32-битный компонент -> 16-битные преобразования:

00000000RRRRRRRRGGGGGGGGBBBBBBBB
0000000000000000BBBBBGGGGGGRRRRR

Это может помочь вам визуализировать, что вам нужно делать параллельно для четырех пикселей.Сдвиг, извлечение и объединение.Вы можете думать об этом как о 4 32-битных дорожках, хотя для некоторых битовых операций ширина регистров не имеет значения (например, если 4 32-битных регистра или 8 16-битных регистров одинаковы).

Грубый псевдокод:

  • Чтение (вектор загрузка ) 128-битный регистр = 4 32-битных пикселя.
  • Сдвиг зеленый (все четыре компонента) в правильное положение бита.
  • Маскировать зеленый цвет (используя маску И ) в другой регистр.(концептуально все еще в 4x32-битном «режиме»)
  • Сдвиг красного (все четыре компонента) в правильное положение бита.
  • Маскировка красного в еще один регистр.
  • Сдвиг синего в правую битовую позицию.
  • Маскировка синего в другой регистр.
  • Сдвиг красного и синего в правую битовую позицию.
  • Для объединения используйте битовое значение ИЛИ .
  • Теперь у вас будет 4 16-битных значения с 32-битным выравниванием.(все пока концептуально, как 4x32 бит)
  • Повторите с другим набором из 4 пикселей.
  • Объедините эти два набора с помощью NEON unzip ( VUZP ), чтобы получить одинРегистр 128 бит / 8 пикселей.
  • Запись (вектор сохранение ) этих пикселей.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...