Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Алгоритмы / Графика / demodesign 3D programming FAQ /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Оптимизация - Программирование от RIN.RU
Оптимизация



Использование инструкций MMX


Если вкратце (а по-другому и не выйдет) с помощью MMX можно довольно неплохо разогнать некоторые медленные операции - например, сделать RGB-освещение. Или текстурирование с билинейной фильтрацией. Здесь я только продемонстрирую эти два примера; всяческие дальнейшие применения - на откуп читателю.


Пример внутреннего цикла с освещением через инструкции MMX:


mov eax,u ; 24:8 fixedpoint
mov ebx,v ; 24:8 fixedpoint
mov ecx,length
xor edx,edx
mov esi,texture
mov edi,outputbuffer
movq mm1,light ; RGB-освещенность, qword
; (4 штуки 0:9 fixedpoint)
movq mm2,delta_light ; изменение освещенности
inner:
mov dl,ah ; dl = (u >> 8)
add eax,du ; u += du
mov dh,bh ; dh = (v >> 8)
add ebx,dv ; v += dv
movd mm0,[esi+4*edx] ; грузим пиксел
punpcklbw mm0,mm0 ; распаковываем пиксел
psrlw mm0,1 ; для того, чтобы были
; беззнаковые числа
pmulhw mm0,mm1 ; умножаем RGB на RGB-освещенность
add edi,4
dec ecx
packuswb mm0,mm0 ; пакуем пиксел обратно
paddw mm1,mm2 ; light += delta_light
movd [edi-4],mm0
jnz inner


Этот цикл дает после некоторой дальнейшей оптимизации 7 тактов на пиксел - зато с текстурированием и полноценным RGB-освещением. Собственно освещение занимает лишь 2 такта. Не очень плохо.


Пример внутреннего цикла с билинейной фильтрацией через инструкции MMX:


mov eax,u ; 24:8 fixedpoint
mov ebx,v ; 24:8 fixedpoint
mov ebp,length
xor ecx,ecx
xor edx,edx
mov esi,texture
mov edi,outputbuffer
inner:
mov dl,ah ; dl = (u >> 8)
add eax,du ; u += du
mov dh,bh ; dh = (v >> 8)
add ebx,dv ; v += dv
mov cl,al ; ecx = (u & 0xFF) = fu - дробная
; часть u
movd mm0,[esi+4*edx] ; грузим пикселы
movd mm1,[esi+4*edx+4]
movd mm2,[esi+4*edx+4*256]
movd mm3,[esi+4*edx+4*257]
punpcklbw mm0,mm0 ; распаковываем пикселы
punpcklbw mm1,mm1
punpcklbw mm2,mm2
punpcklbw mm3,mm3
psrlw mm0,1 ; для того, чтобы были беззнаковые
psrlw mm1,1 ; числа и pmulhw (знаковое
psrlw mm2,1 ; умножение) работало нормально
psrlw mm3,1
psubw mm1,mm0 ; mm1 = tex[v+1][u]-tex[v][u]
psubw mm3,mm2 ; mm3 = tex[v+1][u+1]-tex[v][u+1]
pmulhw mm1,tab[8*ecx] ; mm1 *= fu
pmulhw mm3,tab[8*ecx] ; mm3 *= fu
add esi,4
add edi,4
psllw mm1,7 ; корректируем результат умножения
psllw mm3,7
paddsw mm0,mm1 ; mm0 = tex[v][u] + mm1
paddsw mm2,mm3 ; mm2 = tex[v][u+1] + mm3
mov cl,bl ; ecx = (v & 0xFF) = fv - дробная
; часть v
psubw mm2,mm0 ; mm2 -= mm0
pmulhw mm2,tab[8*ecx] ; mm2 *= fv
psrlw mm0,7 ; корректируем результат умножения
paddsw mm0,mm2 ; mm0 += mm2 - отфильтрованное
; значение
packuswb mm0,mm0 ; пакуем пиксел
movd [edi-4],mm0 ; записываем его
dec ebp
jnz inner


Отдельного упоминания и разъяснение требует табличка tab. Это просто табличка дробных частей в готовом для MMX-умножения виде:


tab label qword
dw 0,0,0,0
dw 1,1,1,1
dw 2,2,2,2
; ...
dw 255,255,255,255


То есть в данном примере tab[8*ecx] = [cl, cl, cl, cl] - как раз готовая для использования в MMX-инструкциях дробная часть.


Здесь получается уже довольно приличное количество тактов на пиксел, порядка двадцати. Но несмотря на это, вышеприведенный цикл уронил fps на моей любимой тестовой сцене всего лишь в 1.5 раза по сравнению с обычным текстурированием. Тоже не очень плохо. В общем, успехов в использовании. Только не забывайте включать поддержку не-MMX режима для тех, у кого MMX нет, и, соответственно, детектор наличия MMX-инструкций.


<<<  НазадВперед  >>>
 1  2  3  4  5 


 8  Комментарии к статье  8 8  Обсудить в чате

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь