1 Ostatnio edytowany przez śmigło .::. (2005-09-11 11:04:15)

Tak sobie myślę, że operowanie na 4-bajtowych wartościach w mode 9 jest niezbyt szybkie, a i wygoda pisania wszelakich operacji

na obrazie w trybach tego typu pozostawia do życzenia. Nasunął mi się więc banalny pomysł, żeby zrobić dwa tylne bufory - jeden

standardowy, a drugi z jednobajtowymi wartościami kolorów pikseli. Nie wiem czy jasno tłumaczę: jeśli normalnie mamy dla dwóch

punktów coś takiego:

#$AF

to w back-backbufferze jest to rozpisane jako:

#AA, #$FF

Tak więc proces chunk2nibble przebiega w następujący sposób:

    ldx #59        ;59
yeh    ldy cnt2        ;licznik dla chunkbufora

kp    lda (c_bufpnt),y
    and #$F0        ;lewy nibble
    sta lewy
    iny        ;next bajt
    lda (c_bufpnt),y
    and #$0F        ;prawy nibble
    ora lewy        ;sklej
    iny
    sty cnt2
    ldy cnt1        ;licznik dla ekranu
    sta (scrpnt),y    ;na bufor, tudzież ekran

    iny
    sty cnt1
    cpy #40
    bne yeh

Do tego dochodzi oczywiście przeładowanie adresów, które też zabija sporo cykli (nawet jeśli na raz załatwimy więcej niż jedną

linię, jak w przykładzie). Jeśli za pomocą tej procki przerzucam chunk'a bezpośrednio na screen, to niestety widać jak wszystko się

rysuje, a dodatkowego bufora nie chcę angażować. W związku z tym dwa pytania:

1. Jak to zrobić żeby chodziło w jednej ramce (niekoniecznie optymalizując mój kod - może stosując inne techniki?)
2. Czy to ma wogóle sens?

Z góry jak zawsze THC.

2

szybciej bedzie jak rozpiszesz petle, ostatnio moim ulubionym sposobem jest rozpisanie petli dla pionowgo pasa ekranu czy tez bufora, a potem przesuwamy sie w obrebie tego bufora modyfikujac np. rejestr Y.

Twoja metoda wykorzystujaca dodatkowe bufory bedzie zawsze wolna, musisz rozpisac tworzenie piksli ekranu tak aby od razu trafialy na ekran, bez posrednikow, np. tworzenie ekranu w trybie 15OS, czyli 4 piksle na 1 bajt, teksture rozpisujemy na 4 bufory, co 1 piksel kazdy i otrzymujemy:

loop

 ldx tab0,y
 lda tex0,x

 ldx tab1,y
 ora tex1,x

 ldx tab2,y
 ora tex2,x

 ldx tab3,y
 ora tex3,x

 sta ekran,y
 iny
 bne loop

W duzym uproszczeniu, pozostaje kwestia modyfikacji adresow dla kazdej linii itd., ale pokazuje to sposob w jaki mozna przyspieszyc cala operacje, bez rozkazow "AND #" itp.

*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

3

    ldx backbuf
    lda mul16tb,x
    ora backbuf+1
    sta screen

    ldx backbuf+2
    lda mul16tb,x
    ora backbuf+3
    sta screen+1

    ldx backbuf+4
    lda mul16tb,x
    ora backbuf+5
    sta screen+2

    ...

mul16tb    dta $00,$10,$20,$30,$40,$50,$60,$70
    dta $80,$90,$a0,$b0,$c0,$d0,$e0,$f0

zamiast wpisywac do bufora $aa, $99 itp wpisujesz: $0a, $09 dzieki czemu nie trzeba bedzie uzywac operacj AND.
backbuf to tylni bufor gdzie zapisany jest obraz w formacie 1pixel/bajt
screen to adres pamieci obrazu, tak rozpisana procka powinna bez klopotu zmiescic sie w 1 ramce (umieszczajac tablice mul16tb na stronie zerowej zyskasz o 1920bajtow krotsza procedure i o tyle samo cykli szybsza (dla rozdzielczosci 80x48))

tak z ciekawosci po co Ci cos takiego?
przeciez przez taka orgazniacje bufora wszystkie operacje beda prawie 2 razy wolniejsze (pomijajac procedure chunk2nibble), bo zamiast wypelniania 2cykli/pixel bedziesz miec 4cykle/pixel, prosciej mowiac zeby postawic 4 pixele trzeba:

sta buffor
sta buffor+1
sta buffor+2
sta buffor+3

zamiast

sta screen
sta screen+1

operacje na nibblach sa bardzo proste i szybkie nawet dla 6502 wiedz nie widze wogole sensu robienia czegos takiego

4

pr0be:

"zamiast wypelniania 2cykli/pixel bedziesz miec 4cykle/pixel"

No, to jest prawda. Ale trzeba jeszcze spojrzeć wstecz na proces obróbki piksela. Chcemy np. postawić zapalić punkt o zadanych współrzędnych. Zabawa z połówkami bajtów oczywiście nie jest przesadnie ciężka, ale czy dla nibble'ów da się zrobić równie szybką (i prostą na dodatek) procedurkę jak:

    lda kolor
    ldy x_pos
    sta (line_adr),y

Jeszcze więcej zalet ukazuje chunk przy efektach typu blur (przynajmniej póki nie zna się sensownych tricków, które dałyby speeda). Pozostaje więc troska o szybką prockę do przerzucenia bufora... Twoja zdaje się niezła.

tebe:

Jeśli masz jakiś prosty programik z wykorzystaniem tego egzotyka, to mile widziany! Trochę ciężko sobie wyobrazić jak działa.

pr0be & tebe:

Dzięki chłopaki!

5 Ostatnio edytowany przez pr0be (2005-09-12 09:19:49)

oczywiscie wszystko zalezy jaka to bedzie "obrobka". Teksturowanie napewno bedzie wolniejsze bo juz je testowalem jakis czas temu ;) co do blur'a to sie nie wypowiem, wszystko zalezy od algorytmu, dla dokladniejszego blur'a prawdopodobnie sposob z buforem 1bajt/pixel bedzie szybszy i wygodniejszy, poniewaz trzeba bedzie odczytywac kilka pixeli (co napewno bedzie szybsze niz bawic sie z nibblami), w sumi gdyby sie zastanowic to mozna dojsc do wniosku ,ze wszystkie algorytmy ktore wymagaja odczytu zawartosci pixela powinny dzialac szybciej z buforem 1bajt/pixel, bo caly klopot to wlasnie odczyt pixela z bufora (trzeba ANDowac albo uzywac do tego tablic) a nie zapis...

jedno jest pewne, taka organizacja ekranu jest "ladna" z punktu widzenia programisty bo wtedy bardzo przyjemnie sie pisze program, z szybkoscia bywa roznie ;)

trzeba jeszcze wziosc pod uwage, ze czyszczenie takiego bufora zajmuje 2 razy wiecej czasu niz czyszczenie ekranu, poniewaz bufor bedzie 2 razy wiekszy niz pamiec ekranu...

a co do:

lda kolor
ldy pos_x
sta (screenp),y

policzmy cykle: 3+3+6=12cykli na zapis do bufora, teraz dodamy jeszcze cykle jakie sa potrzebne zeby "skonwertowac" pixel:

ldx backbuf
lda mul16tb,x
ora backbuf+1
sta screen

mamy 4+3+4+4=15cykli/per two pixels, czyli srednio 8cykli na pixel, dodajmy to 12+8=20 cyki, do tego jeszcze dochodza 4 dodatkowe cykle na czyszczenie bufora, 10+4=24 i tyle potrzeba cykli aby postawic 1 pixel.

teraz normalna procka do stawiania pixeli (na nibblach):

ldx pos_x
ldy div2tab,x
lda (scr),y
and maska,x
ora kolor,x
sta (scr),y

3+4+5+4+4+6=26cykli

hmm czyli teoretycznie wyglada na to ,jesli dobrze wszystko obliczylem ,ze stawianie pojedynczych pixeli jest szybsze w trybie "chunk" o 2 cykli T___T, ale napewno jest wolniejsze niz stawianie kilku pixeli na raz, bo procka na nibblach by wygladala mniej wiecej tak:

ldx kolorpixelapierwszego
lda mul16tb,x
ora kolorpixeladrugiego
sta (scr),y
iny
...

co by dawalo 3+3+3+6+2=17cykli/per two pixels, czyli 8/9 cykli na pixel

a w "chunk" wygladalo by to tak:

lda kolorpixelapierwszego
sta (scr),y
iny
lda kolorpixeladrugiego
sta (scr),y
iny

3+6+2 + 3+6+2 = 22cykli na zapis do bufora + 8 cykli na wyczyszczenie bufora + 15cykli na konwersje, czyli mamy razem 35cykli/per two pixels!!! czyli 17-18cykli na pixel!!! co jest dwa razy wolniejsze niz ta sama procedura na niblach....