MSX Village forum

La Place des Développeurs Coder en C avec SDCC

ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5555

Le 21/01/2021 à 20h47

Reprise du message précédent

@aoineko
Je 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 :D
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 :lol Edité par ericb59 Le 21/01/2021 à 21h00


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2890

Le 21/01/2021 à 21h18
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.


On est toujours ignorant avant de savoir.
Github    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1502

Le 22/01/2021 à 13h30
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


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

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5555

Le 22/01/2021 à 14h59
@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.
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


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2890

Le 22/01/2021 à 16h23
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.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5555

Le 22/01/2021 à 17h30
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é ! :siffle


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.


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 :lol Edité par ericb59 Le 22/01/2021 à 17h31


banniere-ericb59e
Site web    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5555

Le 22/01/2021 à 18h04
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
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 :lol )

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


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2890

Le 22/01/2021 à 18h08
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 :lol


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.
Github    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2890

Le 22/01/2021 à 18h28
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 :lol


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 ;)


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.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5555

Le 22/01/2021 à 19h18
Ha oui mais en precalculé c’est de la triche :lol
Ça je sais le faire tout seul mais ça bouffe de la ram quoi... au pire 192 octets.


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2890

Le 22/01/2021 à 19h43
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é.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5555

Le 22/01/2021 à 20h07
Citation :
A mon avis y a pas besoin de plus 8-10 octets

Humpf ? :hum


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) :fou

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é.

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


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 ... :hum


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


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2890

Le 22/01/2021 à 21h08
ericb59 :
J'ai réfléchi à ce que tu dis, mais je ne pige pas ...
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.
Github    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1502

Le 22/01/2021 à 21h13
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 :
  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
Edité par Metalion Le 22/01/2021 à 21h16


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

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2890

Le 22/01/2021 à 21h34
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.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5555

Le 23/01/2021 à 16h05
Citation :
the number of counts (NYB), when the screen edge is fetched


Qu'est-ce que cela veut dire au juste ? :hum


banniere-ericb59e
Site web    
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie