Возможно, эта тема поднималась здесь уже раз сто, но я что-то не нашел... Кде взять или кто может запостить реально оптимизированный (быстрее уже никак) SUBJ для R5G6B5 цвета и отдельно хранящейся маски (в любом удобном формате)? Я искал исходники и кое-что нашел, но это далеко не оптимальные варианты, а некоторые откровенно примитивны (во всех отнощениях). Я пробовал писать свой на MMX, но опыта пока маловато и возникли некоторые вопросы: почему чтение / запись системной памяти работают так медленно (4 movq работают в 3 раза медленнее 27 математических и / или логических инструкций) и можно ли как-нибудь убыстрить их. И можно ли пока читаются следующие пиксели обрабатывать математикой предыидущие, что ли? Система, на всякий случай AMD-K6-2-500, 256 MB SDRAM. Такой же вопрос я запостил в общие вопросы на всякий случай...
Вот мои, сильно не оптимизированы на www.win32asmcommunity.net на верно есть по лучше Код (Text): blit32: mov eax,[fwidth] shl eax,2 mov edx,[fheight] sub [lockrc.Pitch],eax .line: mov ecx,[fwidth] rep movsd add edi,[lockrc.Pitch] dec edx jg .line retn ;##################################################################### ##### blit16: mov eax,[fwidth] add eax,eax mov edx,[fheight] sub [lockrc.Pitch],eax .line: mov ecx,[fwidth] .pixel: mov eax,[esi] ; red mov ebx,[esi] ; green mov ebp,[esi] ; blue shr eax,08h shr ebx,05h shr ebp,03h and eax,0000F800h and ebx,000007E0h and ebp,0000001Fh add ebx,ebp add eax,ebx stosw add esi,04h loop .pixel add edi,[lockrc.Pitch] dec edx jg .line retn ;##################################################################### ##### blit32a: push ebp mov [stackp],esp mov esp,$00FF00FF mov ebp,$0000FF00 sub edi,4 mov eax,[fwidth] shl eax,2 mov edx,[fheight] sub [lockrc.Pitch],eax mov [y],edx .line: mov eax,[fwidth] mov [x],eax .pixel: movzx edx,byte [esi+03h] ; A--- u mov eax,[esi] ; -R-B v mov ecx,[esi] ; --G- u and eax,esp ; v and ecx,ebp ; u imul eax,edx ; v imul ecx,edx ; u and eax,$FF00FF00 ; u and ecx,$00FF0000 ; u add edi,4 ; v add ecx,eax ; u xor edx,$FF ; v mov eax,[edi] ; u mov ebx,[edi] ; v and eax,esp ; -R-B u and ebx,ebp ; --G- v imul eax,edx ; u imul ebx,edx ; v and eax,$FF00FF00 ; u and ebx,$00FF0000 ; v add eax,ecx ; u add esi,4 ; v add eax,ebx ; u shr eax,8 ; u dec [x] ; v mov [edi],eax ; u jg .pixel add edi,[lockrc.Pitch] dec [y] jg .line mov esp,[stackp] pop ebp retn ;##################################################################### ##### blit32ammx: push ebp sub edi,08h mov eax,[fwidth] shl eax,2 mov edx,[fheight] sub [lockrc.Pitch],eax .line: mov eax,[fwidth] .x: add edi,08h movq mm6,[esi] movq mm0,mm6 ; alpha0 movq mm3,mm6 ; alpha1 pxor mm1,mm1 ; src0 pxor mm4,mm4 ; src1 pxor mm2,mm2 ; dest0 pxor mm5,mm5 ; dest1 pshufw mm0,mm0,01010101b ; spread alpha0 pshufw mm3,mm3,11111111b ; spread alpha1 punpcklbw mm1,mm6 ; unpack src0 punpckhbw mm4,mm6 ; unpack src1 punpcklbw mm2,[edi] ; unpack dest0 punpckhbw mm5,[edi] ; unpack dest1 pand mm0,[mmx_mulmask] ; isolate alpha0 pand mm3,[mmx_mulmask] ; isolate alpha1 pand mm1,[mmx_rgbmask] ; isolate src0 pand mm4,[mmx_rgbmask] ; isolate src1 pand mm2,[mmx_rgbmask] ; isolate dest0 pand mm5,[mmx_rgbmask] ; isolate dest1 pmulhuw mm1,mm0 ; src0*alpha0 pmulhuw mm4,mm3 ; src1*alpha1 pxor mm0,[mmx_mulmask] ; reverse alpha0 pxor mm3,[mmx_mulmask] ; reverse alpha1 pmulhuw mm2,mm0 ; dest0*alpha0 pmulhuw mm5,mm3 ; dest1*alpha1 paddw mm1,mm2 ; src0+dest0 paddw mm4,mm5 ; src1+dest1 psrlw mm1,8 ; truncate res0 psrlw mm4,8 ; truncate res1 packuswb mm1,mm4 ; res0+res1 add esi,08h sub eax,02h movq [edi],mm1 jg .x dec edx jg .line emms pop ebp retn ;##################################################################### ##### blit16a: push ebp mov [stackp],esp sub edi,2 mov eax,[fwidth] add eax,eax mov edx,[fheight] sub [lockrc.Pitch],eax mov [y],edx .line: mov eax,[fwidth] mov [x],eax .pixel: movzx edx,byte [esi+03h] ; A--- u mov eax,[esi] ; -R-B mov ecx,[esi] ; --G- and eax,$00FF00FF and ecx,$0000FF00 imul eax,edx imul ecx,edx mov ebx,eax shr ecx,13 shr eax,11 shr ebx,16 and ecx,$07E0 and eax,$001F and ebx,$F800 xor edx,$FF add ecx,eax add edi,2 add ecx,ebx shr edx,2 movzx eax,word [edi] ; -R-B movzx ebx,word [edi] ; --G- and eax,$F81F and ebx,$07E0 imul eax,edx imul ebx,edx and eax,$F81F shl 6 and ebx,$07E0 shl 6 add eax,ebx add esi,4 shr eax,6 add eax,ecx dec [x] mov [edi],ax jg .pixel add edi,[lockrc.Pitch] dec [y] jg .line mov esp,[stackp] pop ebp retn
забыл Код (Text): mmx_rgbmask dq $0000FF00FF00FF00 mmx_mulmask dq $FF00FF00FF00FF00 fwidth = ширина fheight = высота lockrc.Pitch = scanline (width * bytes_per_pixel) почему code таги на этом борде используют variable-width font? нужно fixed-width font, типа courier new (или лучше Код (Text): )
AMD-K6-2 говоришь? а ты вообще не замечал что простая запись в память там медленнее чем чтение? дело в том что когда ты что нибудь пытаешься скэшировать, а строк в кэше нету(все модифицированы) то по вине девелоперов камня инструкция ждет сперва сохранения ячейки а потом загрузки. то есть ожидание вдвое больше что и вызывает остановку конвейера. попробуй юзать prefetchw задолго до обращения к предвыбираемой памяти.
если тебе надо запись в память поставь PWT+WC для страниц буфера. тогда строка кэша оказывается записаной сразу. но тогда трабла - WC ставится через MTRR а их всего 2 там. один под оперативку другой под видеоадаптерную память.
2 Comrade: спасибо, но я свой на MMX написал и он лучше работает. 2 Narkomanius: насчет последнего поста - ничего не понял... 2 All: мне бы такой, чтобы он либо на всех процессорах работал, либо на P3, P4, AthlonXP, а не только на AMD-K6-2-500 - это уже антиквариат. Вообще, не пойму, как сделан такой быстрый блиттер, например, в Ricochet Extreme / Lost Worlds, ну или ещё много игр могу привести в пример. Ведь там все 100% софтварное на DDraw'e сделано. Понимаю, там использовали Dirty Rectangles, чтобы не весь кадр перерисовывать, ну и анимация там 10 - 20 раз в секунду в основном для всех спрайтов, но все равно быстрее моего работает раз в сто. Вообще, если кому надо, могу запостить свой код...
В общем, все понятно... Производители памяти обещают гигабайты, а я с трудом могу переслать 64 (ш) х 64 (в) х 2 (16 бпп) х 4 (сурс, альфа и два раза бэк) х 12 (штук) х 30 (фпс) = 11,25 МБайт / сек. Да?
На athlon@266MHz FSB за секунду можно скопировать 900Mb. Причём эта цифра от частоты ядра почти не зависит.
WC- write combining, задержка данных во внутренних буферах для лучшей утилизации шины. тогда запись имеет больше шансов идти 8байтными блоками а не так как пишет прога - 1,2,4 байта. просто байты попадающие в одну восьмерку комбинированно записываются за одно обращение(2 цикла шины на К6-2 без #HOLD #WT) PTW pagewritethrough -сквозная запись, когда данные записанные в кэш, сразу же помещаются в буфер записи. при write-back режиме буфер записи не заполняется, и запись идет по мере вытеснения строк из кэша. то есть когда тебе захочется прочесть что нибудь в кэш, окажется что сперва надо произвести запись, что ведет к росту латентности и остановке планировщика. Данным синдромом страдают все АМДшные процы, у интеловских Write-backа _НЕТУ_. даже если они пишут что есть. у них просто сквозная запись отложенная получается. чем PWT крут? тем что записав в строку кэша, ты можешь не беспокоиться о том что когда надо будет её вытеснить она будет можифицирована. такие строки немодифицированы по определению, и просто затираются. WC - не нужен если ты будешь производить запись кусками по 8 байт. запись будет неконвейеризована! но потери в скорости будут меньше. Надеюсь я ответил на твой вопрос, почему ты на своем К6-2 получил такое низкое быстродействие записи?