La Place des Développeurs Coder en C avec SDCC
ericb59
Membre non connecté
Conseiller Municipal
Reprise du message précédent
@aoinekoJe ne retrouve pas l'endroit où l'on avait parlé de la routine de print graphique... Et du petit "concours" d'optimisation ...
J'ai continué à optimiser de mon coté tout ca, sans ajouter toutes les fonctionnalités que tu as implémenté de ton coté.
Le texte que j'avais soumis à l'époque, je l'affiche maintenant en 16 cycles
Quelque soit le mode graphique, avec ou sans transparence. (Sans changement de couleurs)
ou bien 26 lignes de 32 caractère (remplissage de l'écran) en 98 cycles. La commande du Bios mets 170 cycles pour la même chose.
J'suis content Edité par ericb59 Le 21/01/2021 à 21h00
aoineko
Membre non connecté
Conseiller Municipal
C'était sur le fil du projet GOS.
16 frames, c'est bien, mais ça reste énorme pour afficher quelques lignes.
Avec une version VRAM, ça prendra surement moins d'1 frame.
16 frames, c'est bien, mais ça reste énorme pour afficher quelques lignes.
Avec une version VRAM, ça prendra surement moins d'1 frame.
On est toujours ignorant avant de savoir.
Une commande HMMM peut réaliser une copie 8x8 (32 octets) en 320 cycles. Et il faut 300 cycles pour l'initialiser.
En gros, la commande VDP absorbe le code d'initialisation de la suivante (méthode sandwich).
Si on ajoute le code nécessaire entre chaque caractère, il faut donc, à la grosse, 360 cycles par caractère.
Pour un texte de 24x32, il faut donc 276 480 cycles, ce qui représente un peu moins de 4 frames.
Edité par Metalion Le 22/01/2021 à 13h36
En gros, la commande VDP absorbe le code d'initialisation de la suivante (méthode sandwich).
Si on ajoute le code nécessaire entre chaque caractère, il faut donc, à la grosse, 360 cycles par caractère.
Pour un texte de 24x32, il faut donc 276 480 cycles, ce qui représente un peu moins de 4 frames.
Edité par Metalion Le 22/01/2021 à 13h36
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
ericb59
Membre non connecté
Conseiller Municipal
@metalion. Tu l'auras compris je pense, quand je parle de cyles, je veux dire "cycle VDP" ou frames. Je vais desormais plutôt utiliser ce terme.
Je ne sais pas trop si ma routine ASM pour le HMMM / LMMM est encore optimisable plus que ça...
Elle est optimisée pour copier des blocs de 8*8 bytes.
J'y entre l'adresse où se trouve les données en RAM (*address_Data) qui se retrouve tout de suite dans HL
#_VDPcmd dans le code ASM, correspond à l'adresse RAM où se treouve les données d'initialisation, dans l'ordre des registres.
Tu crois qu'il y a encore des points d'obtimisation ? Edité par ericb59 Le 22/01/2021 à 15h02
Je ne sais pas trop si ma routine ASM pour le HMMM / LMMM est encore optimisable plus que ça...
Elle est optimisée pour copier des blocs de 8*8 bytes.
J'y entre l'adresse où se trouve les données en RAM (*address_Data) qui se retrouve tout de suite dans HL
#_VDPcmd dans le code ASM, correspond à l'adresse RAM où se treouve les données d'initialisation, dans l'ordre des registres.
Code C :
void FastChar(void *address_data) __z88dk_fastcall __naked { address_data; __asm ex de,hl ld hl,#_VDPcmd ; VDPCMD parameters address ld bc,#4 add hl,bc di fvdpWait1: ld a,#2 out (#0x99),a ld a,#128+#15 out (#0x99),a in a,(#0x99) rrca jp c, fvdpWait1 ; wait CE ld a,#36 ; Start with Reg 36 out (#0x99),a ld a,#128+#17 out (#0x99),a ;R#17 := 36 ld bc,#0x0b9b ; c=9b b=0b otir ld a,#128+#44 out (#0x99),a ld a,#128+#17 out (#0x99),a ; VDP(17)<=44 ex de,hl ld b,#64 ; Number of bytes to send otir ;exit xor a out (#0x99),a ld a,#0x8f ei out (#0x99),a ret __endasm; }
Tu crois qu'il y a encore des points d'obtimisation ? Edité par ericb59 Le 22/01/2021 à 15h02
aoineko
Membre non connecté
Conseiller Municipal
Pour toutes les commandes VDP, comme on connait le nombre de registre à écrire, tu peux "dérouler" (unroll) les otir avec des outi pour gagner un peu.
L'autre astuce, mais c'est à plus haut niveau, c'est que comme tu envois des caractères les uns derrières les autres par une suite de commandes, y a toute une partie des données de buffer de commande qui vont pas changer et que tu gagnerais à ne pas réinitialiser.
L'autre astuce, mais c'est à plus haut niveau, c'est que comme tu envois des caractères les uns derrières les autres par une suite de commandes, y a toute une partie des données de buffer de commande qui vont pas changer et que tu gagnerais à ne pas réinitialiser.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
aoineko :
Pour toutes les commandes VDP, comme on connait le nombre de registre à écrire, tu peux "dérouler" (unroll) les otir avec des outi pour gagner un peu.
Ha oui c'est vrai... Je l'ai fait pour une autre fonction, et pas poiur celle-ci .... ouoblié !
aoineko :
L'autre astuce, mais c'est à plus haut niveau, c'est que comme tu envois des caractères les uns derrières les autres par une suite de commandes, y a toute une partie des données de buffer de commande qui vont pas changer et que tu gagnerais à ne pas réinitialiser.
L'autre astuce, mais c'est à plus haut niveau, c'est que comme tu envois des caractères les uns derrières les autres par une suite de commandes, y a toute une partie des données de buffer de commande qui vont pas changer et que tu gagnerais à ne pas réinitialiser.
Oui, alors j'y ai pensé, mais à minima j'ai DX et DY à modifier à chaque caractère, ou SX,SY et DX,DY à modifier pour la version copie VDP->VDP. Je me suis dit que ca ne valait pas forcément la peine...
est-ce que passer de 11 OUTI à 4 OUTI ca va valoir le coup ... ?
Je connais déjà ta réponse en fait Edité par ericb59 Le 22/01/2021 à 17h31
ericb59
Membre non connecté
Conseiller Municipal
Dis moi aoineko, pour faire la routine BITMAP PRINT, depuis une table de caractères en VRAM en utilisant LMMM ou HMMM
quelle méthode utilises-tu pour calculer les coordonnées de la lettre à copier depuis ta table en VRAM.
(BitmapFont.letter = Numero du caractère à aller chercher dans la table.
Ma methode par calcul
Ma methode par test, qui s'avère plus rapide que la méthode par calcul. (les Divisions et les modulos en 8bits c'est pas trop le kif )
as tu une autre méthode de la mort ?
Je suis certain que oui Edité par ericb59 Le 22/01/2021 à 18h05
quelle méthode utilises-tu pour calculer les coordonnées de la lettre à copier depuis ta table en VRAM.
(BitmapFont.letter = Numero du caractère à aller chercher dans la table.
Ma methode par calcul
Code C :
VDPcmd.sy=base_addr+((BitmapFont.letter/32))*8; VDPcmd.sx=(BitmapFont.letter % 32)*8;
Ma methode par test, qui s'avère plus rapide que la méthode par calcul. (les Divisions et les modulos en 8bits c'est pas trop le kif )
Code C :
if (BitmapFont.letter<=32) { VDPcmd.sy=base_addr; VDPcmd.sx= BitmapFont.letter*8; } if (BitmapFont.letter<=64) { VDPcmd.sy=base_addr+8; VDPcmd.sx=(BitmapFont.letter-32)*8; } else { VDPcmd.sy=base_addr+16; VDPcmd.sx=(BitmapFont.letter-64)*8; } }
as tu une autre méthode de la mort ?
Je suis certain que oui Edité par ericb59 Le 22/01/2021 à 18h05
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
Oui, alors j'y ai pensé, mais à minima j'ai DX et DY à modifier à chaque caractère, ou SX,SY et DX,DY à modifier pour la version copie VDP->VDP. Je me suis dit que ca ne valait pas forcément la peine...
est-ce que passer de 11 OUTI à 4 OUTI ca va valoir le coup ... ?
Je connais déjà ta réponse en fait
est-ce que passer de 11 OUTI à 4 OUTI ca va valoir le coup ... ?
Je connais déjà ta réponse en fait
Pour la version du print avec décodage de la font en temps-réel, ça sert pas à grand chose d'optimiser l'affichage car c'est le CPU qui est à la traine.
Par contre, pour la version du print VRAM to VRAM, là ça va faire gagner pas mal de perf.
Note que je l'ai pas encore fait.
Pour mon projet GOS, je vais utiliser j'ai juste besoin de la version du print via les Sprites.
Quand j'aurai des autres versions, je ferais surement une passe d'optim.
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
Oui, alors j'y ai pensé, mais à minima j'ai DX et DY à modifier à chaque caractère, ou SX,SY et DX,DY à modifier pour la version copie VDP->VDP. Je me suis dit que ca ne valait pas forcément la peine...
est-ce que passer de 11 OUTI à 4 OUTI ca va valoir le coup ... ?
Je connais déjà ta réponse en fait
est-ce que passer de 11 OUTI à 4 OUTI ca va valoir le coup ... ?
Je connais déjà ta réponse en fait
Pour la version du print avec décodage de la font en temps-réel, ça sert pas à grand chose d'optimiser l'affichage car c'est le CPU qui est à la traine.
Par contre, pour la version du print VRAM to VRAM, là ça va faire gagner pas mal de perf.
Note que je l'ai pas encore fait.
Pour mon projet GOS, j'ai juste besoin de la version du print via les Sprites pour le moment.
Quand j'aurai besoin des autres versions, je ferais surement une passe d'optim.
ericb59 :
as tu une autre méthode de la mort ?
Je suis certain que oui
Je suis certain que oui
J'ai jeté un œil à ma fonction DrawChar_VRAM(u8 chr) (https://github.com/aoineko-fr/cmsx/blob/master/cmsx/src/print.c) et pour le moment, y a un gros :
Code C :
// @todo To optimize (pre-compute + fixed width/height cases)
Avec la version avec taille de font fixe, quasiment tout pourra être précalc et on aura plus besoin de faire qu'un AND sur les X et un Shift sur les Y.
Pour la version avec taille variable (qui te concerne pas pour le moment), ça va être plus compliqué ; je pense que le plus optimal serait d'utiliser la largeur (8 px max) comme index dans un tableau précalc.
Je te dirais si j'ai la foi de m'en occuper bientôt.
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
A mon avis y a pas besoin de plus 8-10 octets pour toutes les données à pré-calc.
Et pour la RAM, je t'en avais déjà parlé, mais tu devrais mettre des defines pour laisser l'utilisateur choisir ce qu'il veut inclure ou non dans son programme.
Cf. https://github.com/aoineko-fr/cmsx/blob/master/proj/samples/cmsx_config.h
Ca permet d'avoir une double granularité :
- Pouvoir choisir les modules qu'on souhaite inclure (via la liste de modules à build),
- Pouvoir configurer les modules (pour n'embarquer que les fonctionnalités dont on a besoin).
Par ex., si tu mets USE_PRINT_VRAM à 0 dans la config, ça va éliminer toutes les fonctions et tous les datas qu'utilisent cette fonctionnalité.
Et pour la RAM, je t'en avais déjà parlé, mais tu devrais mettre des defines pour laisser l'utilisateur choisir ce qu'il veut inclure ou non dans son programme.
Cf. https://github.com/aoineko-fr/cmsx/blob/master/proj/samples/cmsx_config.h
Ca permet d'avoir une double granularité :
- Pouvoir choisir les modules qu'on souhaite inclure (via la liste de modules à build),
- Pouvoir configurer les modules (pour n'embarquer que les fonctionnalités dont on a besoin).
Par ex., si tu mets USE_PRINT_VRAM à 0 dans la config, ça va éliminer toutes les fonctions et tous les datas qu'utilisent cette fonctionnalité.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Citation :
A mon avis y a pas besoin de plus 8-10 octets
Humpf ?
Je viens d'essayer avec toutes les coordonnées précalculées dans un tableau en global.
Ben... C'est pas plus rapide que mes 3 conditions (voir plus haut)
Citation :
si tu mets USE_PRINT_VRAM à 0 dans la config, ça va éliminer toutes les fonctions et tous les datas qu'utilisent cette fonctionnalité.
si tu mets USE_PRINT_VRAM à 0 dans la config, ça va éliminer toutes les fonctions et tous les datas qu'utilisent cette fonctionnalité.
En scindant le code de chacune de mes fonctions Fusion-c (Pas comme tu as vu la première fois), je t'assure que le linker n'intègre que les fonctions utilisées.
Citation :
Par contre, pour la version du print VRAM to VRAM, là ça va faire gagner pas mal de perf.
Note que je l'ai pas encore fait
Note que je l'ai pas encore fait
J'ai réfléchi à ce que tu dis, mais je ne pige pas ...
Comment veux tu optimiser ça ?
Sur les 15 données à envoyer au VDP, les 15 sont obligatoires au premier caractère.
Je suis d'accord que pour le second caractère, seuls 4 données changent, SX,SY,DX,DY
Soit les registres R#32 à R#39
R#40 à R#45 n'ont pas besoin d'être modifiés,
Mais il faut envoyer une donnée dans R#46 pour lancer la commande. En mode d'accès indirect tu ne peux pas zapper les Registres R#40 à R#45, et repasser en mode d'accès direct ferait perdre tout le gain potentiel ...
Code C :
void FastVDPChar(void *Params) __z88dk_fastcall __naked //LMMM or HMMM { Params; __asm di fvdpWait2: ld a,#2 out (#0x99),a ld a,#128+#15 out (#0x99),a in a,(#0x99) rrca jp c, fvdpWait2 ; wait CE ld a,#32 ; Start with Reg 32 out (#0x99),a ld a,#128+#17 out (#0x99),a ;R#17 := 32 ld bc,#0x0f9b ; c=9b b=0f OUTI ; SX low R#32 OUTI ; SX high OUTI ; SY low OUTI ; SY high OUTI ; DX low OUTI ; DX High OUTI ; DY low OUTI ; DY high OUTI ; NX Low OUTI ; NX high OUTI ; NY low OUTI ; NY high OUTI ; Col OUTI ; Param OUTI ; CMD R#46 ;exit xor a out (#0x99),a ld a,#0x8f ei out (#0x99),a ret __endasm; }
PS : Pour info, je mets 4 frames pour afficher mon texte de référence avec la copie VDP Edité par ericb59 Le 22/01/2021 à 20h16
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
J'ai réfléchi à ce que tu dis, mais je ne pige pas ...
Comment veux tu optimiser ça ?
Comment veux tu optimiser ça ?
Tu peux faire un outi sur 8 premiers registres (SX/Y, DX/Y) puis faire un out simple sur CMD.
Tu retires 5 outi (-90 cc) et tu dois ajouter un ld a,(hl) ; out(nn),a (+20 cc ; à noter que HL a déjà la bonne valeur)
Donc tu gagnes 70 cc à chaque caractère (soit ~3000 cc sur le texte qui fait une quarantaine de caractères).
Mais surtout, faut pas oublier le temps de setup ta structure (Params) ; le fait de pas remettre à jour NX, NY, CLR et ARG à chaque caractère va faire gagner beaucoup aussi.
ericb59 :
PS : Pour info, je mets 4 frames pour afficher mon texte de référence avec la copie VDP
Idem avec la version pour les fonts de taille fixe (sans optim).
On est toujours ignorant avant de savoir.
ericb59 :
Je suis d'accord que pour le second caractère, seuls 4 données changent, SX,SY,DX,DY
Attention que certains registres sont modifiés par la commande VDP, et ne gardent pas leur valeur d'origine.
Code :
Edité par
Metalion
Le 22/01/2021 à 21h16
Table 4.7 Register status at command termination
----------------------------------------------------------------------------
| command name | SX | SY | DX | DY | NX | NY | CLR |CMR H|CMR L| ARG |
----------------------------------------------------------------------------
| HMMC | --- | --- | --- | . | --- | # | --- | 0 | --- | --- |
----------------------------------------------------------------------------
| YMMM | --- | . | --- | . | --- | # | --- | 0 | --- | --- |
----------------------------------------------------------------------------
| HMMM | --- | . | --- | . | --- | # | --- | 0 | --- | --- |
----------------------------------------------------------------------------
| HMMV | --- | --- | --- | . | --- | # | --- | 0 | --- | --- |
----------------------------------------------------------------------------
----------------------------------------------------------------------------
| LMMC | --- | --- | --- | . | --- | # | --- | 0 | --- | --- |
----------------------------------------------------------------------------
| LMCM | --- | . | --- | --- | --- | # | . | 0 | --- | --- |
----------------------------------------------------------------------------
| LMMM | --- | . | --- | . | --- | # | --- | 0 | --- | --- |
----------------------------------------------------------------------------
| LMMV | --- | --- | --- | . | --- | # | --- | 0 | --- | --- |
----------------------------------------------------------------------------
--- : no change
. : coordinate (SY*, DY*) and the colour code at the command termination
# : the number of counts (NYB), when the screen edge is fetched
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
aoineko
Membre non connecté
Conseiller Municipal
Metalion :
Attention que certains registres sont modifiés par la commande VDP, et ne gardent pas leur valeur d'origine.
Ah oui... j'avais complétement oublié !
Ca marche pas très bien avec les contraintes de l'affichage du texte du coup.
Autant envoyer tout le buffer de commande.
Reste qu'on peut au moins ne pas update tout notre buffer à chaque commande.
On est toujours ignorant avant de savoir.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie