26

Chodzi o to, że jesli odpowiadasz pod postem bezposrednio, to jego cytowanie jest zbedne, jesli nie odwolujesz sie do jakiejs konkretnej wypowiedzi a do calosci :) Na tym forum dba sie o porzadek i bardzo dobrze, jest czytelniej, latwo cos znalezc ;)

The problem is not the problem; the problem is your attitude about the problem

27 Ostatnio edytowany przez Cyprian (2015-03-16 17:30:58)

Tomasz Wachowiak napisał/a:

Nie bądź taki skromny... :) Te kilkanaście linijek jest przykładem na to, jak myśląc w nieszablonowy sposób można uzyskać świetne rezultaty. Jak dla mnie, to numer jeden od naprawdę długiego czasu.

:)

Tomasz Wachowiak napisał/a:

Myślę jeszcze o czymś innym :) Tyle, że dużo roboty i muszę cały kod napisać, żeby się przekonać, czy będzie szybciej. A krótkich linii bym nie ruszał, bo kod blittera jest zbyt piękny, żeby go prymitywną motorolą zastępować :P

zapodawaj :)

widzę jeszcze miejsce na drobne optymalizacje, typu:
- Jeśli ekran jest w obrębie 16bitowej strony to można:
"move.l a4,dstAddr(a6)        ; Destination Addr" --> "move.w a4,dstAddr+2(a6)        ; Destination Addr"

- zmienić adresowanie dla kodu blittera z:

    move.w    D0,hop(A6)
...
    move.w #0,endmsk3(a6)        ; EndMask3
    move.w    #-6,dstYinc(a6)        ; DestYInc
    move.l a4,dstAddr(a6)        ; Destination Addr
    move.w #2,xCount(a6)        ; xCount
    move.w d4,yCount(a6)        ; yCount
    move.b D7,lineNum(a6)        ; Do Blit, start with 3rd Half-Tone

na:

    lea        $FFFF8A3A.w,A6    ;HOP
    move.w    D0,(A6)
...
    move.w d4,-(a6)    ; yCount
    move.w #2,-(a6)        ; xCount
    move.l a4,-(a6)        ; Destination Addr
    move.w #-6,-(a6)        ; DestYInc
    move.w #0,-2(a6)        ; EndMask3

    move.b D7,$10(a6)        ; Do Blit, start with 3rd Half-Tone

Ale to urywa zaledwie kilkanaście cykli na linię.

Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org

Trochę czasu mi na to zejdzie. Muszę całe liczenie trójkąta przepisać, a im więcej o tym myślę, tym mniej pewne wydają mi się oszczędności czasowe. :( Myślę, że do ostatecznej wersji fillera warto zaproponowane przez ciebie zmiany jeszcze wprowadzić.

Znalazłem metodę przygotowywania danych do wypełniania trójkąta, która jest szybsza od stosowanej dotychczas. Niestety mam kłopot z pewnymi rodzajami trójkątów. Kurde widzę już koniec, a zarazem go nie widzę. :P

30

No ciekawe. Chodzi o usprawnienie compute_triangle_dx?

Jakby co to mam ideę na zmianę w fill_triangle_line_loop. BLiTTER, na podstawie leftEdge/rightEdge może wygenerować left mask/right mask. Koszt to 34 cykle szyny na inicjalizację rejestrów Halftone a potem tylko 2 cykle szyny na maskę.
A jeszcze jakby udało się przeorganizować tablice leftEdge/rightEdge na taką:

REPT rezY
 ds.w leftEdge, rightEdge, leftMask, right Mask. 
ENDR

to w fill_triangle_line_loop można by jednym zgrabnym "movem.w    (A0)+,D0-D3" ładować od razu wszystkie potrzebne dane.

Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org

31 Ostatnio edytowany przez Tomasz Wachowiak (2015-03-20 02:11:26)

W weekend powinienem mieć już jakąś działającą wersję. Jestem w trakcie realizacji pomysłu na wyliczanie współrzędnych do wypełniania bez wpisywania ich do tablicy i późniejszego odczytywania. Jeśli wszystko pójdzie po mojej myśli, to na bazie tego kodu będzie można wprowadzić już ostateczne zmiany do pętli wypełniającej o których właśnie wspomniałeś.

Edit: Kurrrrr.... Czasowo i jedna i druga procka wypadają podobnie. Szlag, szlag, szlag...

Cyprian napisał/a:

Jakby co to mam ideę na zmianę w fill_triangle_line_loop. BLiTTER, na podstawie leftEdge/rightEdge może wygenerować left mask/right mask. Koszt to 34 cykle szyny na inicjalizację rejestrów Halftone a potem tylko 2 cykle szyny na maskę.

Hmm... 2? A nie 4? A co z danymi do wypełniania zawartymi w halftonach?

Cyprian napisał/a:

to w fill_triangle_line_loop można by jednym zgrabnym "movem.w    (A0)+,D0-D3" ładować od razu wszystkie potrzebne dane.

Tylko pamiętaj, że na lsrze stracisz. Ja poszedłem w drugą stronę i zrobiłem oddzielne tablice dla prawej i lewej strony, dzięki czemu zamieniłem lsra na dwa addy. No i sam movem sporo zabiera.

33 Ostatnio edytowany przez Cyprian (2015-03-20 16:31:21)

Tomasz Wachowiak napisał/a:

Hmm... 2? A nie 4? A co z danymi do wypełniania zawartymi w halftonach?

cykl szyny (z punktu widzenia CPU/BLiTTERa) czyli 4 cykle CPU :)
17 cykli szyny na załadowanie danych z pamięci do D0-D7 i drugie 17 na przesłanie z D0-D7 do Halftone

Potem generowanie leftMask/rightMask na podstawie Halftone i leftEdge/rightEdge - 2 cykle szyny (Jeden odczyt i Jeden zapis) - 8 cykli procesora na jedną maskę


Tomasz Wachowiak napisał/a:

Tylko pamiętaj, że na lsrze stracisz. Ja poszedłem w drugą stronę i zrobiłem oddzielne tablice dla prawej i lewej strony, dzięki czemu zamieniłem lsra na dwa addy. No i sam movem sporo zabiera.

Chodziło mi o to by BLiTTER na podstawie leftEdge/rightEdge wygenerował tablicę leftMask/rightMask,
oraz by uniknąć lsl/addów BLiTTER dokonał na leftEdge/rightEdge operacji - AND $FFF0 i rotacji o 3 bity w prawo.


Najprościej będzie jak w wolnej chwili siądę do assemblera i sprawdzę czy to działa.
A tutaj napisany z palca, tak na szybko, szkic kodu fill_triangle_line_loop:

fill_triangle_line_loop
    movem.w    (A0)+,D0-D3          ; D0 - left; D1 - right
                                    ; D2 - left mask; D3 - right mask

    move.l    D6,A4                 ; current line address
    add.l    #160,D6                ; next line address
    lea        (A4,D0.w),a4         ; add line x offset


    sub.w    D0,D1                  ; line width

    asr.w    #1,D1                  ; words number
    bgt.s    .multi_words

    and.w    D2,D3
    move.w    D3,endmsk1(a6)        ;only mask
...
Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org

34 Ostatnio edytowany przez Tomasz Wachowiak (2015-03-20 18:28:42)

Dzisiaj, najpóźniej jutro wrzucę kod bazowy do naszych dalszych modyfikacji. Trochę przekonfigurowałem liczenie linii - teraz jest wszystko czytelniejsze. Zostawiłem stary sposób liczenia linii, niestety nowy pomysł nie wypalił - głównie z powodu braku możliwości zastosowania mojego ulubionego addx'a.

35 Ostatnio edytowany przez Tomasz Wachowiak (2015-03-20 21:27:51)

Wrzucam ostatnią inkarnację kodu. Najlepiej byłoby wszystkie modyfikacje robić właśnie na niej. Tak na szybko udało mi się zamienić to:

    move.w    #-6,D0
    move.w    D3,D1
    subq.w    #2,D1
    lsl.w    #3,D1
    sub.w    D1,D0            ;    0-6+((xCount-2)*8)
    move.w    D0,dstYinc(a6)                ; DestYInc

na coś takiego:

    move.w    d3,d0
    add.w    d0,d0
    move.w    blitDstYIncTab(pc,d0.w),dstYinc(a6)  ;-6-((xCount-2)*8)

No i poprawiłem opis dstYInca, bo wartości tam maleją, a nie rosną. :)

Oczywiście można zamienić jeszcze tablicę offsetów i masek na tablicę lewą i prawą, dzięki czemu pozbędziemy się lsrów z początku, ale czekam na modyfikację zaproponowane przez Cypriana.

Post's attachments

TriangFi.zip 6.33 kb, liczba pobrań: 3 (od 2015-03-20) 

Tylko zalogowani mogą pobierać załączniki.

36 Ostatnio edytowany przez Tomasz Wachowiak (2015-03-21 00:09:58)

Jednak dodałem oddzielne tablice dla masek blittera. :) Zmodyfikowałem makro na tryb współdzielony - teraz znowu mamy 90% wydajności trybu hog.
Edit: I jeszcze małe poprawki w kodzie. Wrzucam nową wersję na miejsce starej.

Post's attachments

TriangFi.zip 6.35 kb, liczba pobrań: 3 (od 2015-03-21) 

Tylko zalogowani mogą pobierać załączniki.

Jest prosta metoda, jak znowu zrobić fillera na wybraną ilość planów (nawet uproszczą się halftony). W wolnej chwili zmodyfikuję źródło.

38

Niestety dopiero wieczorem będę miał więcej czasu, siądę do Twojego ostatniego kodu i zrobię parę testów.

Jeśli chodzi o wybraną ilość planów to jasne, zapodawaj :)
Jakby co to też mam kod, tylko jeszcze go nie publikowałem. W sumie są to kosmetyczne zmiany do aktualnej procedury blittera.

Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org

Zmiana na poszczególne plany była w zasadzie banalna. Znacznie uprościłem halftony - teraz potrzebne są tylko 4 linie, nie jest potrzebna tablica blitterLineOP, wyliczenie dstYInc to teraz:

    add.w    d3,d3
    move.w    blitDstYIncTab(pc,d3.w),dstYinc(a6)    

Kurde. Panowie. Mamy RAKIETĘ :D a chyba można jeszcze trochę zakombinować :)

Post's attachments

TriangFi.zip 6.32 kb, liczba pobrań: 4 (od 2015-03-21) 

Tylko zalogowani mogą pobierać załączniki.

Wydaję mi się, że dla linii mniejszych od 16 punktów (i mieszczących się w tym samym offsecie ekranu) będzie można wypełniać tylko jedno słowo, zamiast obecnych dwóch. Będzie trzeba dorobić oddzielną tablicę kolorów dla halftonów (też 4 linie) i stosować ją razem ze zerowym dstYInc. Sprawdzę, jak znajdę trochę czasu.

41

Te dwa słowa na linię w przypadku 16 punktowych linii wynikało z tego że rejestry Halftone inicjowałem tylko jeden raz, ale za to wartościami dla wszystkich kolorów.

By wypełnić cztery bitplany w jednym strzale (z uwzględnieniem Mask1/Mask3) musiałem dać ujemne dstYinc, co powoduje że Halftone są dekrementowane. Działa to dobrze w "multi_words" ale nie w wariancie z tylko jednym słowem (<=16 punktów) na bitplan. Tak więc dla linii 16 punktowej musiałem zwiększyć szerokość linii do dwóch słów by móc zastosować ujemne dstYinc.

Widzę że w 5_C inicjujesz Halftone częściej, ale za to tylko jednym kolorem. To daje możliwośc poprawienia 16 punktowych linii.

Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org

Zgadza się. Kolor jest inicjowany raz na trójkąt, ale dzięki temu mamy do dyspozycji 12 wolnych linii halftonów i możliwość rezygnacji z tablicy lineOPów, więc szybkościowo wychodzi bardzo podobnie. Tak, czy inaczej twoje ujemne dstYInc otworzyło mi oczy na wiele spraw :D za co oczywiście serdecznie ci dziękuję. :)

43 Ostatnio edytowany przez Tomasz Wachowiak (2015-03-23 20:27:43)

Wrzucam wersję z zoptymalizowanym wypełnianiem dla linii mniejszych od 16 pixeli. Chyba powoli dochodzimy do ściany, wykorzystanie blitterowego 'skew' do generowania masek (jak sugerował Cyprian) może być kosztowne inicjalizacyjnie (chyba, że czegoś nie widzę/nie wiem).

Post's attachments

TriangFi.zip 6.39 kb, liczba pobrań: 2 (od 2015-03-23) 

Tylko zalogowani mogą pobierać załączniki.

44 Ostatnio edytowany przez Tomasz Wachowiak (2015-03-25 11:49:09)

Ok. Chyba pójdziemy dalej. Co byście powiedzieli gdybyśmy małymi krokami doszli do jakiegoś ładnego, kręcącego się obiektu? :D Kolejną rzeczą, którą warto zrobić jest rozszerzenie procedury na rysowanie czworokątów (a może nawet wszystkich wielokątów wypukłych? :P). Jeśli to się uda, będzie można (w razie konieczności) dodać clipping (algorytm Sutherland-Hodgman). W wolnej chwili pochylę się nad problemem - przy obecnym stanie kodu chyba nie powinno to być zbyt trudne. Prawdopodobnie połączę procedury generowania współrzędnych i rysowania w jedną wspólną prockę (będzie przejrzyściej) - kilka instrukcji też pewno wyleci. Dodatkowo można wrzucić w tablicę kod wyliczający t, czyli (x2-x1)/(y2-y1), dzięki czemu pozbędziemy się dzielenia i przesuwania bitów. Uff..

45

Naprawdę słuszna koncepcja :)

jeśli chodzi o moją część to, mam działający kod ale niestety nie miałem jeszcze czasu zintegrować go z trianglefi. Muszę jeszcze raz przemyśleć użycie rejestrów gdyż w trianglefi większośc jest wykorzystana.

Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org

No ciekawy jestem, co udało ci się jeszcze wymyślić, bo mało miejsca zostało na optymalizację... :P

Zgodnie z obietnicą zamieszczam kolejne rozwinięcie wypełniania. Połączyłem procedurę generowania współrzędnych i wypełniania trójkąta w jedną zbiorczą funkcję, 't' jest teraz odczytywane z tablicy, dzięki czemu w kodzie nie ostało się żadne dzielenie. :D Minusem rozwiązania jest prawie pół megowa tablica i 4 sekundowy czas jej generowania. Pomimo wszystko proponuję wykorzystać tą inkarnację kodu do dalszych modyfikacji.

Post's attachments

TriangFi.zip 6.51 kb, liczba pobrań: 3 (od 2015-03-25) 

Tylko zalogowani mogą pobierać załączniki.

48

Pół mega? Dlaczego tak dużo? Nie miałem czasu zerknąć w Twój kod... ale limitująć dx do 0-255 a dy do 0-127 co już powinno wystarczyć do "życiowych trójkątów" to masz 256*128*2b = 64K - zakladajac ze wynik jest word'em. 64k jest fajne bo mozna to zalignowac i dostęp jest wygodny... No chyba, że ta tablica u Ciebie to co innego niż myśle, albo potrzebujesz większej precyzji niż ja (ja u siebie mam obie delty limitowane do 0-127 czyli 32k i taka precyzja mi wystarcza).

Maciek
--------
Atari 65XE + Ultimate 1MB + Stereo + SIO2SD | Atari 520STE + 4MB + UltraSatan | Atari Falcon 030 + CT60e + 14MB ST + 256MB TT + 68882  + CF + Netusbee | Amiga 500 + 1MB + Gotek | Amiga 600 + 2MB Chip + 8MB Fast + CF

Przy liczeniu współrzędnych linii korzystam z addx.l , dzięki czemu kod liczący wygląda tak:

    move.w    d0,(a6)+
    addx.l    d2,d0

Zdecydowanie najszybsze, co można wymyślić... :D

Tablica zrobiona jest pod wzór: t = (x2-x1)/(y2-y1), gdzie dx może mieć wartość ujemną. Nie chciałem ograniczać się do, jak to fajnie nazwałeś "życiowych trójkątów", ale wyliczyć wszystkie możliwe wartości, a to daje 2*320*200*4 bajtów. :P

Oczywiście jeśli nie są potrzebne wielkie trójkąty można zmodyfikować tablicę pod swoje potrzeby. :)

50

Rozumiem, to u mnie jest trochę inaczej. Ja nie tablicuję przypadków ujemnych tylko jakby co je neguję - parę operacji więcej mam przez to.

Maciek
--------
Atari 65XE + Ultimate 1MB + Stereo + SIO2SD | Atari 520STE + 4MB + UltraSatan | Atari Falcon 030 + CT60e + 14MB ST + 256MB TT + 68882  + CF + Netusbee | Amiga 500 + 1MB + Gotek | Amiga 600 + 2MB Chip + 8MB Fast + CF