repstosw 18 21 марта, 2019 Опубликовано 21 марта, 2019 · Жалоба И снова здравствуйте! Реализую билинейную фильтрацию, алгоритм отладил. Теперь хочу перенести его на SIMD инструкции. Исходные цветовые компоненты хранятся в памяти так: 0:R:G:B= 8:8:8:8 бит Текстура 128x128 Необходимо в реальном времени считать билинейную фильтрацию. Работа с четыремя исходными пикселями. Алгоритм такой: #define FRAC(x) _fabsf((x)-((float)_spint(x))) /* Дробная часть. Есть ли intrising Для C6745 ??? */ #define MIX(A,B,t) (((t)*(B))+((1.0F-(t))*(A))) /* Интерполяция. Интрисинк есть??? */ //Тело цыкла: register float rz=_rcpsp(z); register float p=v*rz; register float q=u*rz; register s32 sp=_spint(p); register s32 sq=_spint(q); register s32 t00=pt[(( sp &(MaxU-1))*MaxU)+( sq &(MaxV-1))]; //исходные 4 пиксела в формате 0RGB по 8 бит каждый register s32 t01=pt[(( sp &(MaxU-1))*MaxU)+((sq+1)&(MaxV-1))]; register s32 t10=pt[(((sp+1)&(MaxU-1))*MaxU)+( sq &(MaxV-1))]; register s32 t11=pt[(((sp+1)&(MaxU-1))*MaxU)+((sq+1)&(MaxV-1))]; register float A=FRAC(p); register float B=FRAC(q); register float q0r; register float q0g; register float q0b; register float q1r; register float q1g; register float q1b; if(sp>0) { q0r=MIX((float)( t00>>16 ),(float)( t10>>16 ),A); //Покомпонентно интерполируем по X: top и bottom q0g=MIX((float)((t00>> 8)&0xFF),(float)((t10>> 8)&0xFF),A); q0b=MIX((float)( t00 &0xFF),(float)( t10 &0xFF),A); q1r=MIX((float)( t01>>16 ),(float)( t11>>16 ),A); q1g=MIX((float)((t01>> 8)&0xFF),(float)((t11>> 8)&0xFF),A); q1b=MIX((float)( t01 &0xFF),(float)( t11 &0xFF),A); } else { q0r=MIX((float)( t10>>16 ),(float)( t00>>16 ),A); q0g=MIX((float)((t10>> 8)&0xFF),(float)((t00>> 8)&0xFF),A); q0b=MIX((float)( t10 &0xFF),(float)( t00 &0xFF),A); q1r=MIX((float)( t11>>16 ),(float)( t01>>16 ),A); q1g=MIX((float)((t11>> 8)&0xFF),(float)((t01>> 8)&0xFF),A); q1b=MIX((float)( t11 &0xFF),(float)( t01 &0xFF),A); } register float q2r; register float q2g; register float q2b; if(sq>0) { q2r=MIX(q0r,q1r,B); //Покомпонентно интерполируем по Y q2g=MIX(q0g,q1g,B); q2b=MIX(q0b,q1b,B); } else { q2r=MIX(q1r,q0r,B); q2g=MIX(q1g,q0g,B); q2b=MIX(q1b,q0b,B); } *vb++=((_spint(q2r)&0xF8)<<8)|((_spint(q2g)&0xFC)<<3)|(_spint(q2b)>>3); //Собираем итоговый пиксел с конверсией 0:8:8:8 в 5:6:5 z=z+dz; u=u+du; v=v+dv; Есть ли интрисинки чтоб на SIMD переложить алгоритм для 6545-го ? Надо чтоб с 4 float работал (умножение сложение) и с 4 int ещё _x128_t для C6745 не поддерживается даже со включенным <c6x.h> Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
thermit 1 22 марта, 2019 Опубликовано 22 марта, 2019 · Жалоба Не. Это только начиная с 66xx. simd на 674+ только с 16-бит данными. 6545 это что? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 22 марта, 2019 Опубликовано 22 марта, 2019 · Жалоба 1 hour ago, thermit said: Не. Это только начиная с 66xx. simd на 674+ только с 16-бит данными. 6545 это что? TMS320C6745 Выжал 88 кадров в секунду с реалтайм билинейной фильтрации. При этом формат пикселя 8:8:8 конвертится на лету в 5:6:5 и кидается DMA на дисплей. Всю программу и текстуру 128x128 32 bit per pixel - расположил в L2. Кеш 2 evtymibk c 256 кБ до 128 кБ. Во внешней SDRAM только 2 видеобуфера - один читает DMA в другой рендерит CPU. Без размещения текстуры во внутреней памяти было 80 кадров в секунду (зато кеш L2 в 2 раза больше доступен ) - +8 FPS прибавка . Долго не мог реализовать возврат дробной части вещественного числа - вначале делал так: _fabs(x - (float)_spint(x)) - была лажа местами из-за ошибок точности. Позже свой вариант написал - весьма заумный. Текст программы ниже - кадр 400 x 240 16 bpp - даёт 88 кадров в секунду с реал-тайм билинейной фильтрацией текстуры 128x128 32bit. union tc { u32 t; u8 c[4]; }; #pragma DATA_ALIGN(t0,4) union tc t0; #pragma DATA_ALIGN(t1,4) union tc t1; #pragma DATA_ALIGN(t2,4) union tc t2; #pragma DATA_ALIGN(t3,4) union tc t3; inline void Line(void) { register s32 a=_spint(x1); register s32 b=_spint(x2); //............... register u16 * restrict vb=(u16*)(SwitchBuffer[0]+(((y*MaxX)+a)<<1)); register u32 const * restrict pt=(u32 const*)TUNNEL; b-=a-1; _nassert(b>=2); #pragma MUST_ITERATE(2,,) do { register float rz=_rcpsp(z); register float p=u*rz; register float q=v*rz; register s32 sp=_spint(p); register s32 sq=_spint(q); register u32 a0=(( sp &(MaxU-1))*MaxU); register u32 a1=(((sp+1)&(MaxU-1))*MaxU); register u32 a2= ( sq &(MaxV-1)); register u32 a3= ((sq+1)&(MaxV-1)); t0.t=pt[a0+a2]; t1.t=pt[a0+a3]; t2.t=pt[a1+a2]; t3.t=pt[a1+a3]; *vb++=((_spint(MIX(MIX(t0.c[2],t2.c[2],p),MIX(t1.c[2],t3.c[2],p),q))&0xF8)<<8)| ((_spint(MIX(MIX(t0.c[1],t2.c[1],p),MIX(t1.c[1],t3.c[1],p),q))&0xFC)<<3)| ( _spint(MIX(MIX(t0.c[0],t2.c[0],p),MIX(t1.c[0],t3.c[0],p),q)) >>3); z=z+dz; u=u+du; v=v+dv; } while(--b); } Как бы ещё чего придумать чтоб быстрее было? И вот это можно написать более оптимальнее? Или может intrinsic есть? #define FRAC(t) (((float)(_spint(/*_fabsf*/(t)*256.0F)&0xFF))*0.00390625F) /* дробная часть : 256 градаций */ #define MIX(A,B,t) ((((B)-(A))*FRAC(t))+(A)) /* Интерполяция */ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 22 марта, 2019 Опубликовано 22 марта, 2019 · Жалоба Видео. Как-то так. Разрешение 400x240. Мигрировал на другой дисплей, более лучшего качества матрицы: https://www.youtube.com/watch?v=sBq2i1dVWh8 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться