Amiga blitter vs Archimedes ARM power ;-)
-
quelle est la différence d’occupation mémoire entre une routine «boucle + data» classique, et la version générée (unrolled) ?
je n’avais pas répondu
la différence est très importante, mais l’idée c’est d’avoir ton générateur de sprites compilés dans ton jeu, pour appeler la génération du sprite compilé au moment opportun, puis libérer la mémoire quand tu n’as plus besoin de ce sprite compilé.
Ensuite, bien comprendre que si tu as un sprite avec beaucoup de vide,tu peux avoir un sprite compilé qui va prendre moins de place que ce sprite là, car le sprite compilé ne traite que le plein, pas le vide.
Au final pas évident de donner un chiffre, comme ça.
Ca va être du cas par cas.Prenons un cas extrême.
Imagine tu as une animation d’étoiles, en forme de croix, disons çette forme :
+
3 pixels de haut et 3 de large
et tu en as un nuage de 4 ou 5,
tout ça dans une animation qui va tenir dans une succession de rectangles 32×32
ben là en sprites compilés non seulement c’est plus rapide pour les afficher que la méthode classique,
mais ça prendra aussi nettement moins de place.Je pousse le trait exprès, par soucis de pédagogie.
Rappel : pas besoin de masque avec les sprites compilés, ça fait un sacré gain de place.
Ni vide ( je simplifie, il y en a quand même un peu au niveau des bords des segments horizontaux composant le sprite), ni masque.Si tu veux faire des tests voici les gfx de Battle Squadron, il y a aussi d’autres jeux.
http://amiga.lychesis.net/game/BattleSquadron.htmlMerci pour le lien.
Je pourrais déjà piquer une des animations d’explosions, pour l’explosion des boules ( en réadaptant les couleurs avec mon choix de 16 couleurs )Les sprites n’ont « pas besoin de masque », et c’est donc pour cela que tu en a mis un sur ton avatar 🙂
Samuel.
Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
A500 Vampire V2+ ^8^ 🙂
(mais aussi TO8, TO8D, TO9. Groupe PULS.)je ne sais pas quelle place prend l’opcode move sur un archimedes, ni même si c’est à taille variable. Mais c’est vraiment rentable à tous les coups ? Car les objets (sprites ou objets blittés) ont quand même tendance à occuper l’espace , ne serait-ce que pour des raisons de tests de collision (pour les objets, pour les sprites effectivement pas d’importance).
Mettons qu’un move prenne un octet, il faut aussi l’adresse de destination, avec surement un adressage indexé (base avec un registre + offset sur 16 bits). Donc mettons que comme sur certains RISC, on peut encoder le registre sur quelques bits de l’offset pour gagner un peu de place, ça nous fait minimum 4 octets par move (opcode + offset + donnée).
Ça me parait moins rentable, à moins d’avoir un sprite qui n’occupe que 25% de sa surface totale. Un projectile par exemple. Mais dans un cas de figure typique, , je pense que nous sommes plus prêt des 75% d’occupation du tableau dédié à l’objet.Bon je m’amuse avec tous ces calculs, pure spéculation d’ailleurs, donc ne t’embête pas à répondre. Mais si tu veux t’embêter 🙂 tu peux poster par exemple le code généré pour une boule, avec la taille prise, et la méthode classique avec également la taille que ça prendrait. Tu peux même poster un dump après compilation, du moment qu’il y a les adresses mémoire, je sais faire les soustractions 🙂
Je ne penses pas avoir vu la réponse dans ce thread mais comment est organisé la mémoire vidéo de l’archi ? c’est un genre de chunky ou c’est du bitplane à la Amiga ?
Tout est chunky.
@ Modulo
Suis nase ce soir mais je te réponds.
Enespérant ne pas écrire n’importe nawak.
Toutes les instructions sur l’ARM prennent 4 octets ( ça aide pour générer du code )Quand tu plottes un pixel ( donc 1 octet en mode 256 couleurs ), tu peux avoir un offset en pré incrémentation ou post incrémentation dans l’instruction, et le coût est de 0 cycle si c’est une constante.
Mettre ! fait que l’incrémentation avec l’offset reste en sortie d’opération.
Cette valeur peut aller de -4096 à + 4096.
Ca prend 0 cycle supplémentaire tout ça.
Ecrire 1 octet avec STRB coûte 4 cycles.
Reprenons l’exemple de l’étoile qui ressemble à + et fait 3×3
Pour l’afficher :
on va dire que R14 est l’adresse mémoire en haut à gauche du rectangle dans lequel est est inscrite.
Disons aussi qu’elle est monochrome, de couleur 255.
Ca donnera, en mode 320 x 256 256 couleursmov r0,#255 ; 1 cycle
strb r0,[r14,#1]! ; 4 cycles
strb r0,[r14,#320-1]! ; 4 cycles
strb r0,[r14,#1]! ; 4 cycles
strb r0,[r14,#1] ; 4 cycles
strb r0,[r14,#320] ; 4 cyclesmov 0,#32*1024*1024 ; 1 cycle
ldr pc,[0,#-4) ; 4 + 4 cycles si je ne dis pas de conneries32 octets pour un truc qui fait 3*3 soit 9 octets, et encore 9 octets pour son masque, soit 18 octets, ça ne semble pas terrible. ( je ne prend pas en compte la taille du code utilisant la méthode générique d’affichage, puisqu’elle va servir pour tous les affichages )
Certes.
Sauf que si ton rectangle ne fait pas 3×3 mais 64×64 parce que tu as plusieurs étoiles et tu en as une en haut à gauche et une bien en bas à droite, ça change la donne.
Imagine que tu en as 10 là-dedans
Le code ci dessus *10 prendra 24*10 + 2*4 = 248 octets ( s’il n’y a jamais plus de 4096 octets d’écart entre le bas d’une étoile, et le haut de la suivante )
Ton sprite lui qui fait 64×64 prend 4096 octets, et encore 4096 octets pour son masque.A noter que STRB est la pire des instructions car elle prend 4 cycles.
STM ( écriture multi registres ) prend 4 cycles sur le 1er registre de la liste de transfert, puis 1 cycle pour chaque registre suivant, donc pour l’Archie plus un sprite est gros, et plus il est plein, plus le ratio pixels transférés par cycle est élevé.
Tous les registres sont 32 bits, pour rappel.Je n’ai pas pris en compte le coût pour la routine appelante de faire
mov #0,32*1024*1024
str pc,[0,#-4] ; le program counter vaut adresse courante + 8 à cause du pipeline de l’ARM
ldr pc, addresse de la routine d’affichagej’espère ne pas avoir écrit trop n’importe quoi
Pas pratique de rédiger là.Je mets toujours mes variables à 32*1024*1024 – qqchose, j’expliquerai pourquoi si vous voulez.
En fait cette méthode de « sprite en code » (sprite compilé) ne marche que pour des pixels chunky ou alors sur un seul bitplan bref n’a pas trop d’intérêt sur Amiga classic…
Tu peut faire un move 32 bits et écrire 4 pixels dans la partie solide du sprite ?
Tu ne peux pas faire un MOV avec n’importe quelle valeur 32 bits, puisque l’instruction est codée sur 32 bits, comme toutes les instructions de l’ARM.
Ce que tu feras c’est que tu chargeras avec une seule instruction LDMIA, jusqu’à 12 registres, et là tu pourras faire tes STR si tu veux écrire 4 pixels.
Mais en aucun cas tu ne feras une répétition de STR pour écrire un segment.
Tu utiliseras STMIA destination!,{liste de registres}et attention on n’opère que sur des adresses multiples de 4 avec LDM et STM (*), et STR aussi, ça oblige à avoir 4 codes, et 4 copies du contenu du sprite, shifté à chaque fois de 1 pixel.
LDRB et STRB eux opèrent sur n’importe quelle adresse.
Vous comprenez mieux j’imagine pourquoi il faut avoir un moteur qui crée à loisir le sprite compilé quand il va y en avoir besoin, puis libère son espace jusqu’à la prochaine fois où on aura besoin de lui.
On ne garde en permanence en mémoire qu’une copie du sprite.
Les seuls sprites compilés en permanence en mémoire vont être ceux qui reviennent tout le temps à l’écran.(*) les 2 instructions ignorent les 2 bits de poids faible de l’adresse utilisée
Je ne penses pas avoir vu la réponse dans ce thread mais comment est organisé la mémoire vidéo de l’archi ? c’est un genre de chunky ou c’est du bitplane à la Amiga ?
Sisi il faut regarder mieux plus haut
@AThellier: oui ca ne marche plus si on doit travailler sur des bouts d’octets (faire du décalage au niveau bit variable d’un sprite à l’autre, ce que le blitter amiga fait de base.. recopier les données sans décalage est clairement sous-optimal). Mais en chunky on s’en fiche un peu (on travaille sur des octets pleins). Même en chunky 16bits on ne s’embête pas avec des 1/2 octets, car je suppose qu’on contourne le pb en ayant 2 sprites: un pour les positions paires, l’autre pour les impaires.
A ne pas oublier: sur risc les instructions sont de taille fixe (le coldfire aussi au passage je crois me souvenir). Ici c’est 32bits, donc on ne peut pas charger 32bits d’un coup. Cela se fait sur sparc (et ARM aussi j’imagine) en deux chargement: l’un pour la partie haute, l’autre pour la partie basse. Bref charger 32bits est super couteux (2 instructions), donc on a intéret à réutiliser les valeurs 32bits déjà chargées dans les registres tant qu’on peut (Normalement ca va, il y en a 32) quitte à afficher le sprite « dans le désordre » suivant la présence du même motif 32bits (4 couleurs en chunky256) en divers endroits du sprite.
Samuel.
Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
A500 Vampire V2+ ^8^ 🙂
(mais aussi TO8, TO8D, TO9. Groupe PULS.)oui c’est mon avis aussi.
Il y a une autre solution, si on veut éviter d’avoir un moteur dans le jeu qui génére les sprites compilés.
Ce serait de compresser le code de ces sprites compilés.
Ca devrait se compresser très bien, car
° on utilise quasi toujours les mêmes instructions( LDR, STR, LDMIA, STMIA, STMIB, STMDB, ADD, MOV )
° il n’y a pas besoin d’avoir de tests dans le code de ces sprites compilés, hors chaque instruction ARM est conditionnelle, et le champs dans l’instruction qui détermine l’exécution conditionnelle prend déjà 4 bits sur les 32 bits de l’instruction.Oui mais la décompression du code en ram va te faire perdre du temps, donc le gain en espace memoire sera converti en perte de vitesse. Le grand classique!
Samuel.
Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
A500 Vampire V2+ ^8^ 🙂
(mais aussi TO8, TO8D, TO9. Groupe PULS.)Oui mais la décompression du code en ram va te faire perdre du temps, donc le gain en espace memoire sera converti en perte de vitesse. Le grand classique!
Tu fais ta décompression à l’avance, petit à petit, exactement comme lorsque dans la version ‘moteur’ tu générais ton sprite compilé à l’avance, petit à petit, tant que tu avais des cycles dispo par 1 50iè de seconde, pour que ton frame rate ne chute pas.
Perso je trouve ça très jouable.
Je ne vois aucune preuve que ça ne fonctionnerait pas très bien.Je l’ai dit déjà : il faut une gestion fine de ce qui risque de devoir être prochainement affiché, au fur et à mesure de ta progression dans le jeu, pour avoir le sprite compilé dispo au moment où il faudra afficher ce sprite.
En permanence en mémoire tu n’as que les sprites compilés de ce qui sert tout le temps ( ton personnage, les tirs, les explosions, les ennemis communs, les éléments communs de décor ).
- Vous devez être connecté pour répondre à ce sujet.
› Forums › AmigaOS, MorphOS et AROS › Développement › Amiga blitter vs Archimedes ARM power ;-)