OldComp.cz

Komunitní diskuzní fórum pro fanoušky historických počítačů

Zptky do minulosti!

Právě je 22.04.2021, 20:00

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]




Odeslat nové téma Odpovědět na téma  [ Příspěvků: 14 ] 
Autor Zpráva
PříspěvekNapsal: 31.12.2020, 14:54 
Offline
Pan Štábní
Uživatelský avatar

Registrován: 18.05.2013, 14:56
Příspěvky: 1608
Has thanked: 198 times
Been thanked: 372 times
pwramp píše:
Pardon, abych z té diskuze něco měl, mohli byste mě, HW lopatě, vysvětlit, co je to vykreslování spritů přes zásobník? Ideálně s příkladem? Proč je nejrychlejší mazání RAM přes push?
Spočítej si takty v těchto dvou příkladech.

Kód:
CLS     ld      hl,16384
        ld      de,16385
        ld      bc,6144
        ld      (hl),0
        ldir
        ld      bc,767
CLS2    ld      a,13
        ld      (hl),a
        ldir
        ret
ldir trvá 21T * (BC - 1) + 16T, tj. mazání výše bude trvat nejméně 6143*21+16+767*21+16 = 145142T, tj. zhruba 145142/3500000 = .0414s + nějaká režie s nastavením registrů okolo, voláním atd... ale pořád se používá, pokud chci krátký kód, co sice trvá, ale zabere málo místa.

Chceme-li smazat obrazovku za méně než 1/50s je nutné se vejít do 0.02s

Příklad se zásobníkem
Kód:
CLS_FAST        ld      (CLS_FAST_3 + 1),sp     ; 20T - store original stack address
                ld      hl,23296                ; 10T - address of last byte in VRAM
                ld      sp,hl                   ; 6T
CLS_FAST_2      ld      a,56                    ; 7T  - color (default INT 0, PAPER 7, BRIGHT 0)
                ld      b,24                    ; 7T  - 24 text lines
                ld      h,a                     ; 4T  - in H & L colors from A
                ld      l,a                     ; 4T
CLS_FAST_0      push    hl                      ; 10T - 16x (will store 32 bytes)
                push    hl                      ;       in total 16*10*24 = 3840T
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                djnz    CLS_FAST_0              ; djnz will take 23 * 13 + 8 = 307T
                ld      h,b                     ; 4T  - B = 0, it is convenient, let's copy it in H & L
                ld      l,b                     ; 4T
                ld      b,192                   ; 7T  - number of pixel lines
CLS_FAST_1      push    hl                      ; 10T - 16x (32 bytes)
                push    hl                      ;       in total 16*10*192 = 30720T
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                push    hl
                djnz    CLS_FAST_1              ; djnz will take 191*13+8 = 2491T
CLS_FAST_3      ld      sp,0                    ; 20T restore original address of stack
                ret                             ; 10T
                                                ; total T
                                                ; 20+10+6+7+7+4+4+3840+307+4+4+7+30720+2491+20 = 37451T  cca 0.01s
Takže celkem pouhých 37451T, tj. cca 37451/3500000=0.01067s

Docela rozdíl, ne?

Věřím, že někdo vyhrabe i další příklady... tohle jsem měl první při ruce a je to asi nejvýraznější.

_________________
https://cygnus.speccy.cz ZX Spectrum 128k, Betadisk, DivIDE, ESXDOS


Nahoru
 Profil  
 
PříspěvekNapsal: 31.12.2020, 17:37 
Online
Pan Generální

Registrován: 22.05.2013, 21:14
Příspěvky: 2965
Bydliště: Bratislava
Has thanked: 307 times
Been thanked: 574 times
pwramp píše:
Pardon, abych z té diskuze něco měl, mohli byste mě, HW lopatě, vysvětlit, co je to vykreslování spritů přes zásobník?
Pokial chcem vykreslovat poctive maskovane sprajty, je nutne kazdy bajt z videoram nacitat, vyANDovat maskou a zORovat s kresbou sprajtu:
Kód:
ld  a,(de) ; Bajt z obrazovky
and maska
or  kresba
ld  (de),a ; Ulozenie nazad do obrazovky
A teraz ide o to ze vsetky masky a kresby celeho sprajtu mame ulozene v pameti, a musime ich nejak postupne nacitavat z pameti.
Dal by sa na to pouzit napriklad register HL ktory na zaciatku ukazuje na definiciu sprajtu:
Kód:
ld  a,(de)
and (hl)
inc l
or  (hl)
inc l
ld  (de),a
Na vykreslenie jedneho bajtu sprajtu potrebujeme 36 taktov.
Ale ked masku a kresbu nacitame cez zasobnik:
Kód:
pop bc
ld  a,(de)
and b
or  c
ld  (de),a
tak sa nam to zrychli na 32 taktov.
Nie je to na prvy pohlad sice moc velky rozdiel, ale moze to znamenat zmenu z 25 FPS na 50 FPS co je uz dost vyznamne.


Nahoru
 Profil  
 
PříspěvekNapsal: 01.01.2021, 19:09 
Offline
Radil

Registrován: 06.02.2019, 11:47
Příspěvky: 531
Has thanked: 11 times
Been thanked: 81 times
Keď som písal Pacman-a pre Ondru, tak som potreboval zmazať a vykresliť 5 sprajtov (16x16) počas jedného zatemnenia, aby nedošlo k ich blikaniu.
Zatemnenie trvá len 56 liniek (312-256), avšak je potrebné čakať na VSYNC, čím sa minie ešte 16 liniek, zostáva teda asi 5000T (39 / 312 * 0,02s / 0,5us). Jediné riešenie bolo použiť zásobník.
Grafické dáta sú pripravené vopred v RAM a natlačené do zásobníka formou 2 bajty adresa sprajtu, 2 bajty grafické dáta. Keďže Ondra má veľmi zvláštne zvislé adresovanie VideoRAM, bolo vloženie adresy na zásobník najrýchlejším riešením oproti zmene adresy výpočtom (Ondra potrebuje RR L, DEC L, RL L pre ďalší mikroriadok). Použitím zásobníka trvá vykreľovanie jedného sprajtu len 16 x 38T = 608T. A samozrejme rovnaký čas trvá aj zmazanie (teda vrátenie pôvodného pozadia).
Kód:
SPRALL: LD      (STACK), SP     ; uloz SP
        LD      SP, HL          ; nastav ukazatel fronty
SPRAL0: POP     HL              ; 10T adresa vo VRAM
        POP     DE              ; 10T nacitanie grafiky
        LD      (HL), D         ;  7T zobraz
        INC     H               ;  4T adresa bajtu vlavo vo VRAM
        LD      (HL), E         ;  7T zobraz     Spolu 38T (pre jeden mikroriadok)
...
        POP     HL
        POP     DE
        LD      (HL), D
        INC     H
        LD      (HL), E
        DJNZ    SPRAL0          ; 13T opakuj pre celu frontu
        LD      SP, (STACK)     ; obnov zasobnik
        RET


Nahoru
 Profil  
 
PříspěvekNapsal: 01.01.2021, 21:27 
Offline
Radil

Registrován: 18.10.2014, 23:10
Příspěvky: 254
Has thanked: 16 times
Been thanked: 63 times
Tiež som už bol nútený použiť zásobník na mazanie obrazovky, ale to nijako nebráni prerušeniu a návratová adresa sa môže uložiť aj do obrazovky a po návrate sa premaže. Problém je len pri poslednej inštrukcii PUSH, ktorú treba nahradiť klasickým zápisom do pamete.
V prerušeni sa hneď mení zásobník za vlastný, takže sa môže normálne používať.
Kód:
Clr:      LD   HL,0
          LD   (ClrSP+1),SP
          LD   SP,Screen+ScrLen
          PUSH HL
 ;push hl  repeat ScrLen/2-1

ClrSP:    LD   SP,0
          LD   (Screen),HL    ;instead last PUSH HL
          RET

Int:      LD   (IntSP+1),SP
          LD   SP,StackInt
          PUSH AF
;-------
          POP  AF
IntSP:    LD   SP,0
          EI
          RET


Nahoru
 Profil  
 
PříspěvekNapsal: 01.01.2021, 22:06 
Offline
Kecálek

Registrován: 10.07.2014, 01:57
Příspěvky: 123
Has thanked: 9 times
Been thanked: 113 times
Martin1 píše:
Grafické dáta sú pripravené vopred v RAM a natlačené do zásobníka formou 2 bajty adresa sprajtu, 2 bajty grafické dáta. Keďže Ondra má veľmi zvláštne zvislé adresovanie VideoRAM, bolo vloženie adresy na zásobník najrýchlejším riešením oproti zmene adresy výpočtom (Ondra potrebuje RR L, DEC L, RL L pre ďalší mikroriadok).


len upresnim dve veci.

jedna je, ze na modifikaciu adresy pre posun o mikroriadok dolu treba RLC L; DEC L; RRC L. (RR L rotuje 9 bitov [a este k tomu opacnym smerom ako chceme], my potrebujeme rotovat len 8)

druha je ze v skutocnosti na vykreslovanie sprite-ov o velkosti 16x16 px nie je nutne predpocitavat adresy vram a davat ich na zasobnik, staci si len uvedomit, ze v sprite mozme najskor vykreslit neparne mikroriadky (po ktorych sa posuva jednoduchym DEC L), a ked su neparne vykreslene, urobit jeden presun na parny mikroriadok (nutnost pridat aj tie rotacie) a nasledne dokreslit parne mikroriadky sprite-u (s posunom INC L). samozrejme je potom nutne spravne pred-interlace-ovat predlohu sprite-u, ale to je 'compile-time' zalezitost.

vykreslovanie 16x16 px sprite-u potom pojde v tomto "hadikovom" poradi:
Kód:
 0  1
31 30
 3  2
28 29
 4  5
27 26
 7  6
24 25
 8  9
23 22
11 10
20 21
12 13
19 18
15 14
16 17


urcite ste si vsimli, ze kazdy druhy neparny mikroriadok je vykresleny opacne (napr. '3 2' miesto '2 3'), to je dalsie usetrenie, netreba sa pred kazdym druhym neparnym mikroriadkom vracat na lavu stranu sprite-u. cize, prvy neparny kreslime zlava doprava a druhy neparny zprava dolava, cim sa vratime na lavu stranu a mozme ist zasa dalsi zlava doprava a dalsi zprava dolava.. a takto cely sprite.

rutinka by potom mohla vypadat nejak takto:
Kód:
   rept    4
   
   pop   de

   ld   (hl),e
   dec   h
   ld   (hl),d
   ;inc   h      ;optimizacia, nepotrebny navrat na lavu stranu sprite-u

   dec   l
   
   pop   de

   ld   (hl),e
   inc   h      ;az tu sa spravi navrat na lavu stranu
   ld   (hl),d

   dec   l
   
   endm
   
   rlc   l
   dec   l
   rrc   l

   rept    4
   
   pop   de

   inc   l

   ld   (hl),e
   dec   h
   ld   (hl),d
   ;inc   h      ;optimizacia, nepotrebny navrat na lavu stranu sprite-u
   
   pop   de

   inc   l

   ld   (hl),e
   inc   h      ;az tu sa spravi navrat na lavu stranu
   ld   (hl),d
   
   endm


samozrejme, ak sa nam nechce predpocitavat poprehadzovane poradie bajtov (vid. '3 2' vs. '2 3'), da sa to spravit aj bez prehadzovania v datach, bez spomalenia/zvacsenia kodu, len zmenou poradia kreslenia D a E - v prvom casti rept kreslit najskor E a potom D v druhej casti najskor kreslit D a potom E, potom mozu byt pripravene data uniformne zlava doprava.

rutina sa da este drobne skratit vyhodenim nadbytocnych DEC L/INC L: znizenim poctu opakovani REPT o 1 a posledny/prvy prechod REPT nakopirovat zvlast, bez nepotrebneho DEC L/INC L (nenapisal som to tak, aby ten priklad nebol moc dlhy)


Nahoru
 Profil  
 
PříspěvekNapsal: 01.01.2021, 23:13 
Online
Radil

Registrován: 28.07.2018, 14:37
Příspěvky: 359
Has thanked: 5 times
Been thanked: 146 times
Tyhle "posuny" pomocí inkrementace registru L, kdy se nejprve kreslí sudé řádky a pak liché a zároveň se střídá směr kreslení zleva doprava a opačně, jsem použil u řady her. U větších obrázků to má ale jednu velkou nevýhodu. Pokud obvody rozkladu TV obrazu vykreslí obrázek někde v polovině kreslení sprite, tedy mezi sudými a lichými mikrořádky, tak se na 20ms zakonzervuje na obrazovce pouze polovina sprite (tedy ty sudé mikrořádky) a je to hodně viditelné. Při pohybu sprite do stran to pak vytváří takový hřeben na bočních stranách sprite. Procentuální pravděpodobnost "hřebenování" je řádově dána dobou kreslení sprite ku době trvání jednoho snímku (tedy 20ms). Zmíněná velikost 16x16 by ještě měla být v pohodě, sprite 32x32 ovšem už začíná vytvářet ty hřebenové struktury. Popsané vlastnosti jsou odpozorovány na PMD-85, ovšem princip je stejný.


Nahoru
 Profil  
 
PříspěvekNapsal: 01.01.2021, 23:39 
Online
Radil

Registrován: 28.07.2018, 14:37
Příspěvky: 359
Has thanked: 5 times
Been thanked: 146 times
Tak jsem vygeneroval tu příšernost: výška 39pix, šířka 6 bajtů (na PMD-85 ekvivalent 36 pixelů). Ten hřeben, to je postava hráče...


Přílohy:
pop.png
pop.png [ 57.16 KiB | Zobrazeno 892 krát ]
Nahoru
 Profil  
 
PříspěvekNapsal: 02.01.2021, 01:07 
Offline
Radil

Registrován: 18.10.2014, 23:10
Příspěvky: 254
Has thanked: 16 times
Been thanked: 63 times
A keď sa kreslí normálne riadok po riadku, tak to tiež nebude na 100% . Nebude to síce hrebeň, ale horná časť môže byť posunutá oproti spodnej s predchádzajúceho snímku.


Nahoru
 Profil  
 
PříspěvekNapsal: 02.01.2021, 08:26 
Online
Radil

Registrován: 28.07.2018, 14:37
Příspěvky: 359
Has thanked: 5 times
Been thanked: 146 times
To je pravda. Ale není to tak viditelné jako ten hřeben. Já mám v uvedeném programu podmíněnou kompilaci - buď rychle nebo pěkně. Takže ten rozdíl mohu bezprostředně porovnat za stejných podmínek. A ten rozdíl je diametrální. Ten hřeben se objeví při dané velikosti sprite odhadem tak každý třetí frame. Dost to degraduje tu animaci. Oproti tomu lineární kreslení sprite nepůsobí vizuální defekty, přestože se tímto způsobem sprite kreslí déle a tudíž je ještě větší pravděpodobnost jeho rozfázování. Asi to bude tím, že to uskočení sprite je jen jedno.

Ale tam, kde se sprite nepohybuje, například cihly v Arkanoidu, tam si myslím, že si člověk toho střídavého kreslení mikrořádků nevšimne. Ovšem pohyblivé objekty o šířce 3 bajtů (18 pixelů) a výšce 16 pixelů už se ve stejné hře raději kreslí lineárně.

Ale nic nelze paušalizovat. Za různých podmínek jsou ty výsledky různé. Vždy je nutné kreslicí proceduru optimalizovat pro dané použití a nepřebírat hotová řešení. Sice to pak funguje, ovšem ty univerzální procedury sebou nesou balast z předchozích aplikací a zpomalují program. Vždy je lepší využít vzorový algoritmus pouze pro inspiraci. Taky záleží na tom, jak je celá herní smyčka dlouhá ve smyslu času, a zda nedochází ke stroboskopickému efektu ve vztahu k vykreslovací frekvenci obrazu. U zmíněného Arkanoidu mi někdy vozík na pár vteřin postupně zmizel a za pár vteřin se postupně začal objevovat. To když se délka herní smyčky velice přesně přiblížila 20ms.


Nahoru
 Profil  
 
PříspěvekNapsal: 02.01.2021, 09:24 
Offline
Radil

Registrován: 06.02.2019, 11:47
Příspěvky: 531
Has thanked: 11 times
Been thanked: 81 times
ub880d píše:
jedna je, ze na modifikaciu adresy pre posun o mikroriadok dolu treba RLC L; DEC L; RRC L. (RR L rotuje 9 bitov [a este k tomu opacnym smerom ako chceme], my potrebujeme rotovat len 8)
Máš pravdu, nepozrel som sa do kódu, písal som to z hlavy, je to už 5 rokov...
ub880d píše:
v skutocnosti na vykreslovanie sprite-ov o velkosti 16x16 px nie je nutne predpocitavat adresy vram a davat ich na zasobnik, staci si len uvedomit, ze v sprite mozme najskor vykreslit neparne mikroriadky (po ktorych sa posuva jednoduchym DEC L), a ked su neparne vykreslene, urobit jeden presun na parny mikroriadok (nutnost pridat aj tie rotacie) a nasledne dokreslit parne mikroriadky sprite-u (s posunom INC L).
Super, vidím že rubikova kocka prospieva, škoda že mi to s tou kockou nejde :-)
Suma sumárum ušetril si 74T, čiže 14 * 32T + 2 * 28T + 20T + 10T = 534T oproti mojim 608T.
Predloha sprajtu by sa v mojom prípade meniť nemusela, rovnakým spôsobom by sa to do fronty natlačilo (sprajty skladám kvôli možnému prekrytiu vopred v inej časti pamäte).

Libor L.A. píše:
Pokud obvody rozkladu TV obrazu vykreslí obrázek někde v polovině kreslení sprite, tedy mezi sudými a lichými mikrořádky, tak se na 20ms zakonzervuje na obrazovce pouze polovina sprite (tedy ty sudé mikrořádky) a je to hodně viditelné.
Preto kreslím spajty iba počas zatemnenia, čo na Ondrovi inak ani nejde, len je treba dostať celé kreslenie do jediného zatemnenia. PMD ak si pamätám nejde synchronizovať so zatemnením.
M1


Nahoru
 Profil  
 
PříspěvekNapsal: 02.01.2021, 11:30 
Online
Radil

Registrován: 28.07.2018, 14:37
Příspěvky: 359
Has thanked: 5 times
Been thanked: 146 times
Když se vrátím k původnímu dotazu ohledně smyslu použití PUSH pro "kreslení", tak mohu posloužit obrázkem, jak vypadá závod několika postaviček, kdy každá je kreslena jiným algoritmem. Z toho si lze udělat obrázek o výkonnostním přínosu jednotlivých technologií kreslení. Ovšem všechno má své meze. Maximálně optimalizované kreslení je "pouze" třikrát rychlejší než naprosto neoptimalizované kreslení. Je to moc, nebo málo? Někdy to, jak už psal výše Busy, může být zásadní rozdíl v možnosti hru vůbec na dané platformě implementovat.


Přílohy:
showbmp.PNG
showbmp.PNG [ 11.77 KiB | Zobrazeno 798 krát ]
Nahoru
 Profil  
 
PříspěvekNapsal: 02.01.2021, 11:35 
Online
Pan Generální

Registrován: 22.05.2013, 21:14
Příspěvky: 2965
Bydliště: Bratislava
Has thanked: 307 times
Been thanked: 574 times
Libor L.A. píše:
Tyhle "posuny" pomocí inkrementace registru L, kdy se nejprve kreslí sudé řádky a pak liché a zároveň se střídá směr kreslení zleva doprava a opačně, jsem použil u řady her. U větších obrázků to má ale jednu velkou nevýhodu. Pokud obvody rozkladu TV obrazu vykreslí obrázek někde v polovině kreslení sprite, tedy mezi sudými a lichými mikrořádky, tak se na 20ms zakonzervuje na obrazovce pouze polovina sprite (tedy ty sudé mikrořádky) a je to hodně viditelné. Při pohybu sprite do stran to pak vytváří takový hřeben na bočních stranách sprite. Procentuální pravděpodobnost "hřebenování" je řádově dána dobou kreslení sprite ku době trvání jednoho snímku (tedy 20ms).
Presne tento problem castokrat nastava pri digitalizacii interlaced videa, kde sa standartny prekladany PAL signal prenasajuci najprv neparne a potom parne snimky musi vyskladat do jedneho celkoveho obrazu a ked to zrovna nesadne, tiez to robi take hrebene pri rychlejsich pohyboch. Niektore televizory mavali na toto tzv. hrebenovy filter, ktory toto mal riesit.

Takze do takej hry / dema, kde moze nastat tento jav, treba napisat doporucene, ze sa doporucuje sledovanie na TV s hrebenovym filtrom :)
(ale aj tak sa obavam, ze ten filter vie vychytat iba 2x vyssie rozlisenie (parne/neparne snimky) a na nase osembity, ktore do telky posielaju iba same neparne snimky, sa hrebenove filtre nechytia)


Nahoru
 Profil  
 
PříspěvekNapsal: 02.01.2021, 15:27 
Online
Radil

Registrován: 28.07.2018, 14:37
Příspěvky: 359
Has thanked: 5 times
Been thanked: 146 times
Tak já Ti nevím... Já myslel, že číslicový hřebenový filtr v TV je nazýván hřebenovým podle tvaru frekvenční odezvy, která má tvar hřebene, protože se periodicky opakuje v intervalu 0-2Pi. Ale ruku do ohně bych za to nedal. Svou určitě ne, leda tak cizí, tu jo.


Nahoru
 Profil  
 
PříspěvekNapsal: 02.01.2021, 15:55 
Online
Pan Generální

Registrován: 22.05.2013, 21:14
Příspěvky: 2965
Bydliště: Bratislava
Has thanked: 307 times
Been thanked: 574 times
Aha, ano, mas pravdu. Pozrel som poriadne a naozaj, hrebenom sa nazyva preto lebo jeho frekvencna charakteristika pripomina zuby hrebena.
Mali sme TV s hrebenovym filtrom, a ked som cital v anglictine o deinterlaci signalu tak som si myslel ze to co tam popisuju sa slovensky oznacuje prave ten hrebenovy filter.


Nahoru
 Profil  
 
Zobrazit příspěvky za předchozí:  Seřadit podle  
Odeslat nové téma Odpovědět na téma  [ Příspěvků: 14 ] 

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 1 návštěvník


Nemůžete zakládat nová témata v tomto fóru
Nemůžete odpovídat v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete přikládat soubory v tomto fóru

Hledat:
Přejít na:  
Založeno na phpBB® Forum Software © phpBB Group
Český překlad – phpBB.cz