63.htm 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <!--
  2. demo.design 3D programming FAQ
  3. Idea, texts, screenshots:
  4. Andrew A. Aksyonoff,
  5. shodan@chat.ru
  6. Web-design, illustrations:
  7. Andrey Samoilov,
  8. asy@sense.simbirsk.su
  9. -->
  10. <html>
  11. <head>
  12. <title>demo.design 3D programming FAQ. Оптимизация. Использование инструкций MMX.</title>
  13. <link rel=stylesheet href="../style.css" type="text/css">
  14. </head>
  15. <script language="javascript">
  16. <!--//
  17. browser = navigator.appName;
  18. version = parseFloat(navigator.appVersion);
  19. if (browser == "Netscape" && version >= 3.0) { jsenabled = 1; } else
  20. if (browser == "Microsoft Internet Explorer" && version >= 3.0) { jsenabled = 1; } else { jsenabled = 0; }
  21. function swap(img,ref) { if (jsenabled) {document.images[img].src = ref;} }
  22. function loadtocache(img,ref) { cache[img] = new Image(); cache[img].src = ref; }
  23. if (jsenabled) {
  24. cache = new Array();
  25. loadtocache(0,"../img/xdl.gif");
  26. loadtocache(1,"../img/xfaq.gif");
  27. loadtocache(2,"../img/xlinks.gif");
  28. loadtocache(3,"../img/xauthor.gif");
  29. loadtocache(4,"../img/xe.gif");
  30. loadtocache(5,"../img/xprev.gif");
  31. loadtocache(6,"../img/xnext.gif");}
  32. //-->
  33. </script>
  34. <body bgcolor=white><center>
  35. <!-- Title -->
  36. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  37. <img src="../img/t.gif" width=500 height=1 alt=""><br>
  38. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  39. <img src="../img/t.gif" width=500 height=2 alt=""><br>
  40. <table width=500 cellpadding=0 cellspacing=0 border=0>
  41. <td><img src="../img/t.gif" width=5 height=1 alt=""><a href="../main.htm" onmouseover="swap('logo','../img/xe.gif');" onmouseout="swap('logo','../img/e.gif');"><img src="../img/e.gif" name=logo width=60 height=50 hspace=10 border=0 alt=" в самое начало "></a></td>
  42. <td><p class=pagetitle><img src="../img/t.gif" width=265 height=1 alt=""><br>demo.design<br>3D programming FAQ</td>
  43. <td align=center><p class=navy><a href="../download.htm" onmouseover="swap('dl','../img/xdl.gif');" onmouseout="swap('dl','../img/dl.gif');"><img src="../img/dl.gif" name=dl width=40 height=40 border=0 hspace=5 alt=" download "></a><br>download</td>
  44. <td align=center><p class=navy><a href="../links.htm" onmouseover="swap('links','../img/xlinks.gif');" onmouseout="swap('links','../img/links.gif');"><img src="../img/links.gif" name=links width=40 height=40 border=0 hspace=5 alt=" коллекция линков "></a><br>links</td>
  45. <td align=center><p class=navy><a href="../author.htm" onmouseover="swap('author','../img/xauthor.gif');" onmouseout="swap('author','../img/author.gif');"><img src="../img/author.gif" name=author width=40 height=40 border=0 hspace=5 alt=" автора! "></a><br>author</td>
  46. </table>
  47. <img src="../img/t.gif" width=500 height=4 alt=""><br><img src="../img/b.gif" width=500 height=1 alt=""><br>
  48. <!-- Head -->
  49. <table width=500 cellpadding=0 cellspacing=10 border=0><td><div align=justify>
  50. <p class=title>
  51. <img src="../img/b6.gif" width=70 height=70 align=left hspace=0 alt="">
  52. <img src="../img/t.gif" width=5 height=70 align=left hspace=0 alt="">
  53. ОПТИМИЗАЦИЯ<br>6.3. Использование инструкций MMX
  54. <!-- Article -->
  55. <p>Если вкратце (а по-другому и не выйдет) с помощью MMX можно довольно неплохо
  56. разогнать некоторые медленные операции - например, сделать RGB-освещение. Или
  57. текстурирование с билинейной фильтрацией. Здесь я только продемонстрирую эти
  58. два примера; всяческие дальнейшие применения - на откуп читателю.
  59. <p>Пример внутреннего цикла с освещением через инструкции MMX:
  60. <pre class=source>
  61. mov eax,u ; 24:8 fixedpoint
  62. mov ebx,v ; 24:8 fixedpoint
  63. mov ecx,length
  64. xor edx,edx
  65. mov esi,texture
  66. mov edi,outputbuffer
  67. movq mm1,light ; RGB-освещенность, qword
  68. ; (4 штуки 0:9 fixedpoint)
  69. movq mm2,delta_light ; изменение освещенности
  70. inner:
  71. mov dl,ah ; dl = (u >> 8)
  72. add eax,du ; u += du
  73. mov dh,bh ; dh = (v >> 8)
  74. add ebx,dv ; v += dv
  75. movd mm0,[esi+4*edx] ; грузим пиксел
  76. punpcklbw mm0,mm0 ; распаковываем пиксел
  77. psrlw mm0,1 ; для того, чтобы были
  78. ; беззнаковые числа
  79. pmulhw mm0,mm1 ; умножаем RGB на RGB-освещенность
  80. add edi,4
  81. dec ecx
  82. packuswb mm0,mm0 ; пакуем пиксел обратно
  83. paddw mm1,mm2 ; light += delta_light
  84. movd [edi-4],mm0
  85. jnz inner
  86. </pre>
  87. <p>Этот цикл дает после некоторой дальнейшей оптимизации 7 тактов на
  88. пиксел - зато с текстурированием и полноценным RGB-освещением. Собственно
  89. освещение занимает лишь 2 такта. Не очень плохо.
  90. <p>Пример внутреннего цикла с билинейной фильтрацией через инструкции MMX:
  91. <pre class=source>
  92. mov eax,u ; 24:8 fixedpoint
  93. mov ebx,v ; 24:8 fixedpoint
  94. mov ebp,length
  95. xor ecx,ecx
  96. xor edx,edx
  97. mov esi,texture
  98. mov edi,outputbuffer
  99. inner:
  100. mov dl,ah ; dl = (u >> 8)
  101. add eax,du ; u += du
  102. mov dh,bh ; dh = (v >> 8)
  103. add ebx,dv ; v += dv
  104. mov cl,al ; ecx = (u & 0xFF) = fu - дробная
  105. ; часть u
  106. movd mm0,[esi+4*edx] ; грузим пикселы
  107. movd mm1,[esi+4*edx+4]
  108. movd mm2,[esi+4*edx+4*256]
  109. movd mm3,[esi+4*edx+4*257]
  110. punpcklbw mm0,mm0 ; распаковываем пикселы
  111. punpcklbw mm1,mm1
  112. punpcklbw mm2,mm2
  113. punpcklbw mm3,mm3
  114. psrlw mm0,1 ; для того, чтобы были беззнаковые
  115. psrlw mm1,1 ; числа и pmulhw (знаковое
  116. psrlw mm2,1 ; умножение) работало нормально
  117. psrlw mm3,1
  118. psubw mm1,mm0 ; mm1 = tex[v+1][u]-tex[v][u]
  119. psubw mm3,mm2 ; mm3 = tex[v+1][u+1]-tex[v][u+1]
  120. pmulhw mm1,tab[8*ecx] ; mm1 *= fu
  121. pmulhw mm3,tab[8*ecx] ; mm3 *= fu
  122. add esi,4
  123. add edi,4
  124. psllw mm1,7 ; корректируем результат умножения
  125. psllw mm3,7
  126. paddsw mm0,mm1 ; mm0 = tex[v][u] + mm1
  127. paddsw mm2,mm3 ; mm2 = tex[v][u+1] + mm3
  128. mov cl,bl ; ecx = (v & 0xFF) = fv - дробная
  129. ; часть v
  130. psubw mm2,mm0 ; mm2 -= mm0
  131. pmulhw mm2,tab[8*ecx] ; mm2 *= fv
  132. psrlw mm0,7 ; корректируем результат умножения
  133. paddsw mm0,mm2 ; mm0 += mm2 - отфильтрованное
  134. ; значение
  135. packuswb mm0,mm0 ; пакуем пиксел
  136. movd [edi-4],mm0 ; записываем его
  137. dec ebp
  138. jnz inner
  139. </pre>
  140. <p>Отдельного упоминания и разъяснение требует табличка tab. Это просто табличка
  141. дробных частей в готовом для MMX-умножения виде:
  142. <pre class=source>
  143. tab label qword
  144. dw 0,0,0,0
  145. dw 1,1,1,1
  146. dw 2,2,2,2
  147. ; ...
  148. dw 255,255,255,255
  149. </pre>
  150. <p>То есть в данном примере tab[8*ecx] = [cl, cl, cl, cl] - как раз готовая для
  151. использования в MMX-инструкциях дробная часть.
  152. <p>Здесь получается уже довольно приличное количество тактов на пиксел, порядка
  153. двадцати. Но несмотря на это, вышеприведенный цикл уронил fps на моей любимой
  154. тестовой сцене всего лишь в 1.5 раза по сравнению с обычным текстурированием.
  155. Тоже не очень плохо. В общем, успехов в использовании. Только не забывайте
  156. включать поддержку не-MMX режима для тех, у кого MMX нет, и, соответственно,
  157. детектор наличия MMX-инструкций.
  158. </div>
  159. </td></table>
  160. <!-- Bottom Navigation -->
  161. <img src="../img/b.gif" width=500 height=1 alt=""><br><img src="../img/t.gif" width=500 height=2 alt=""><br>
  162. <table width=500 cellpadding=0 cellspacing=0 border=0>
  163. <td><img src="../img/t.gif" width=5 height=1 alt=""><a href="../main.htm" onmouseover="swap('logo2','../img/xe.gif');" onmouseout="swap('logo2','../img/e.gif');"><img src="../img/e.gif" name=logo2 width=60 height=50 hspace=10 border=0 alt=" в самое начало "></a></td>
  164. <td><p class=pagetitle><img src="../img/t.gif" width=265 height=1 alt=""><br>demo.design<br>3D programming FAQ</td>
  165. <td align=center><p class=navy><a href="62.htm" onmouseover="swap('prev','../img/xprev.gif');" onmouseout="swap('prev','../img/prev.gif');"><img src="../img/prev.gif" name=prev width=40 height=40 border=0 hspace=5 alt=" предыдущая статья "></a><br>previous</td>
  166. <td align=center><p class=navy><a href="../content.htm" onmouseover="swap('faq','../img/xfaq.gif');" onmouseout="swap('faq','../img/faq.gif');"><img src="../img/faq.gif" name=faq width=40 height=40 border=0 hspace=5 alt=" содержание "></a><br>content</td>
  167. <td align=center><p class=navy><a href="64.htm" onmouseover="swap('next','../img/xnext.gif');" onmouseout="swap('next','../img/next.gif');"><img src="../img/next.gif" name=next width=40 height=40 border=0 hspace=5 alt=" следующая статья "></a><br>next</td>
  168. </table>
  169. <img src="../img/t.gif" width=500 height=4 alt=""><br>
  170. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  171. <img src="../img/t.gif" width=500 height=1 alt=""><br>
  172. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  173. </center></body>
  174. </html>