Compiler avec GCC sur Sam440 :Comment optimiser?
-
thellier : Après avoir réfléchi et expérimenté à nouveau, tant bien que mal (malheureusement, j’ai peur que des photos où je suis en train de « réfléchir » circulent sur Internet), sur le MicroAOne, j’obtiens 13 fps au lieu de 10, et je descends à 50% de temps passé dans Wazp3D, avec 240 hits, dont 52 dans la fonction PixelsOut16.
On essaie sur la Sam440, 6 fps sans option spéciale … et ma version modifiée semble ne pas fonctionner
Nouvelles du matin :
– En jouant avec les options, il y a eu une exception DSI en cliquant sur ‘5’. addr2line indique la ligne 647 : zname est un buffer de 5 caractères alors que suivant l’option, on y copie plus de 5 octets.
– Sur la Sam440 d’Olrick, on a 5 fps avec un écran 32 bits et 6 fps en 16 bits, 7 fps après ma modif, 32 fps avec Warp3D hardware.
– Sur la Sam460 d’Elwood, on a 7 fps avec un écran 32 bits, 8 fps en 16 bits avec ma version.
– Sur la Sam440 overclockée de K-L (733 MHz), on a … 3 fps sur un écran 32 bits, même carte graphique qu’Olrick, les 2 ont appliqué le patch sam440_setup.
Donc je ne comprends pas :
– l’écart entre les 2 Sam440 !
– pourquoi ça va 2 fois plus vite sur mon MicroAOne
OK vraiment mercis les gars
tout ce que vous ecrivez est hyper interessant
Je vais faire ces modifs lundi
La je suis dans le train et je reponds en bref car depuis 1 telephone
btw comment je trouve ou sont les hits?
sinon si vous etes en 24/32bits alors vous utilisez pax pixelsou16
faut aussi voir que wazp a ete concu pour la jit de winuae =>Instructiond simples et cache important
ENCORE MERCI
Alain
thellier: Je peux t’envoyer ma fonction modifiée si tu veux.
Sinon, pour les hits, j’utilise Hieronymus … mon profiler mais malheureusement il ne fonctionne toujours pas sur Sam440.
Ton exemple est hyper intéressant et quelque part, ça valide un peu plus Hieronymus. Après ma modif, j’obtiens :
Percent | Program
12 | SYS:Kickstart/newlib.library.kmod
4 | SYS:Kickstart/timer.device.kmod
65 | LIBS:Warp3D.library
3 | SYS:Kickstart/rtg.library
6 | SYS:Kickstart/kernel
6 | Cow3D-Amiga-ppc
1 | SYS:Kickstart/ATIRadeon.chip
1 | LIBS:Picasso96/emulation.library
0 | LIBS:bsdsocket.library
0 | SYS:Kickstart/graphics.library.kmod
count = 0312, percent = 65, name = LIBS:Warp3D.library
Offset = 0x000540c8, Count = 0002, Function =
Offset = 0x000083c8, Count = 0073, Function = PixelsOut16
Offset = 0x0004bec8, Count = 0026, Function = GetVertex
Offset = 0x00020a74, Count = 0019, Function = Fill_Tex
Offset = 0x000467c0, Count = 0017, Function = Edge_Tex
Offset = 0x00044d5c, Count = 0001, Function = ZbufferCheck
Offset = 0x00045a28, Count = 0011, Function = DrawPolyPix
Offset = 0x00044a34, Count = 0040, Function = SOFT3D_ClearZBuffer
Offset = 0x0000762c, Count = 0034, Function = Ztest_zless_update
Offset = 0x00045510, Count = 0002, Function = PrintPix
Offset = 0x000460dc, Count = 0010, Function = Poly_Persp0_Tex
Offset = 0x00050b9c, Count = 0017, Function = DrawPolyP
Offset = 0x00007644, Count = 0005, Function = Ztest_zgequal_update
Offset = 0x00017aa0, Count = 0009, Function = PixelsTex32ToBuffer
Offset = 0x0000e894, Count = 0001, Function = PrintError
Offset = 0x0004f3c4, Count = 0009, Function = ClipPoly
Offset = 0x0001ab08, Count = 0006, Function = SOFT3D_Flush
Offset = 0x00020fa8, Count = 0010, Function = SetTexStates
Offset = 0x00052c34, Count = 0003, Function = DrawPrimitive
Offset = 0x00051c70, Count = 0010, Function = SOFT3D_DrawPrimitive
Offset = 0x00053f24, Count = 0001, Function = W3D_DrawPoint
Offset = 0x00008408, Count = 0001, Function = PixelsIn8
Offset = 0x000127dc, Count = 0002, Function = SelectMipMap
Offset = 0x00053ebc, Count = 0001, Function = W3D_DrawTriangle
Offset = 0x0001e9f0, Count = 0001, Function = SetDrawFunctions
Offset = 0x00004d94, Count = 0001, Function = LibW3D_DrawTriangle
Donc il semble qu’on passe 2 fois moins de temps dans PixelsOut16 mais que du fait qu’on mette un peu moins de pression sur cette fonction … d’autres fonctions en profitent ! La charge se répartit au sein de l’appli mais elle reste à bloc.
Une autre fonction à regarder pourrait être ClearZBuffer … A ce propos, si le zbuffer n’utilise pas les float, alors MAXZ défini à 0.99999, converti en USHORT … je pense que ça va écrire des zéros.
Si dans ClearZBuffer, on peut tout mettre à zéro, alors le PPC peut bénéficier de l’instruction de clear de cache. Je ne sais pas si c’est vraiment conseillé mais bon … (et il faut faire attention, la taille d’une ligne de cache est usuellement 32 octets, mais 64 sur X1000 et 128 sur G5 je crois).
Salut Alain,
En fait tu travailles par quart de buffer.
Et tu modifies le test > ou < en conséquence. Voila ma fonction qui gère le schmilblik sous AmiDARK Engine :
void UpdateZTrickMode( int ZTrickADD ){
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
// Mode 0 = Aucune optimisation de gestion du ZBuffer.
if ( Core.ZTrick == 0 ){
if ( ZTrickADD != 0 ){ glClear( GL_DEPTH_BUFFER_BIT ); }
glDepthRange( (GLclampd)0.0f, (GLclampd)1.0f );
glDepthFunc( GL_LEQUAL );
}else{
// Mode 1 = Optimisation du ZBuffer par cadrans de 1/4 du buffer total
Core.ZFrameID = Core.ZFrameID + ZTrickADD;
switch( Core.ZFrameID ){
case 1:
glDepthRange( (GLclampd)0.5, (GLclampd)0.75 );
glDepthFunc( GL_LEQUAL ); // Default mode less or equal
break;
case 2:
glDepthRange( (GLclampd)0.25, (GLclampd)0.5 );
glDepthFunc( GL_LEQUAL ); // Default mode less or equal
break;
case 3:
glDepthRange( (GLclampd)0.0, (GLclampd)0.25 );
glDepthFunc( GL_LEQUAL ); // Default mode less or equal
break;
case 4:
glDepthRange( (GLclampd)0.5, (GLclampd)0.25 );
glDepthFunc( GL_GEQUAL );
break;
case 5:
glDepthRange( (GLclampd)0.75, (GLclampd)0.5 );
glDepthFunc( GL_GEQUAL );
break;
case 6:
glDepthRange( (GLclampd)1.0, (GLclampd)0.75 );
glDepthFunc( GL_GEQUAL );
Core.ZFrameID = 0;
break;
case 7:
glClear( GL_DEPTH_BUFFER_BIT );
glDepthFunc( GL_GEQUAL );
glDepthRange( (GLclampd)1.0, (GLclampd)0.75 );
Core.ZFrameID = 0;
default:
break;
}
}
}
Cela permet d’utiliser le ZBuffer sans l’effacer et sans avoir aucun problème.
Si tu as besoin de plus d’explications sur le principe, n’hésite pas à demander
Si tu as besoin de plus de précisions, tu peux travailler en 1/2 de buffer total au lieu de 1/4
@ +
AmiDARK
Hello
C pas bête du tout : Merci
je vois l’idée tu exploite un quart de la profondeur du zbuffer
à chaque frame et toutes les 4 frames tu vide tout le zbuffer
Par contre que je capte pas c’est « Pourquoi y a 7 cases ? »
moi j’aurai fait 4 cases
0: de 0.00 à 0.25 + glClear( GL_DEPTH_BUFFER_BIT );
1: de 0.25 à 0.50
2: de 0.50 à 0.75
3: de 0.75 à 1.00
A la limite on peut faire le truc en 6 lignes :
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
glDepthFunc( GL_GEQUAL );
n= Core.ZFrameID % 4;
if(n==0) glClear( GL_DEPTH_BUFFER_BIT );
glDepthRange(n*0.25,(n+1)*0.25 );
Alain
En fait, c’est pire, je ne le vide jamais…
Je le vide à l’initialisation pour être sûr que tout soit à 0
puis :
7 = Initialisation du ZBuffer.
La commande système qui initialise l’activation du ZTrick active le ZFrameID = 6 (résultat, au 1er appel il passe à 7 et initialise le ZBuffer en le vidant). Puis ça le mets à 0 (compteur qui sera automatiquement à 1 à la prochaine boucle via Core.ZFrameID = Core.ZFrameID + ZTrickAdd )
Puis ça boucle entre 1 à 6:
1. de 0.50 à 0.75 ( 0.50 = proche, 0.75 = loin ) GL_LEQUAL : Less or Equal
2. de 0.25 à 0.50 ( 0.25 = proche, 0.50 = loin ) GL_LEQUAL : Less or Equal
3. de 0.00 à 0.25 ( 0.00 = proche, 0.25 = loin ) GL_LEQUAL : Less or Equal
4. de 0.50 à 0.25 ( 0.50 = proche, 0.25 = loin ) GL_GEQUAL : Greater or Equal
5. de 0.75 à 0.50 ( 0.75 = proche, 0.50 = loin ) GL_GEQUAL : greater or Equal
6. de 1.00 à 0.75 ( 1.00 = proche, 0.75 = loin ) GL_GEQUAL : Greater or Equal + Remise à 0 du pointeur de ZFrameID (compteur qui sera automatiquement à 1 à la prochaine boucle via Core.ZFrameID = Core.ZFrameID + ZTrickAdd )
Donc, j’utilise le ZBuffer dans les 2 sens … Résultat, aucun besoin de le vider. Les valeurs de la gestion précédente étant toujours en dehors du nouveau RANGE et considérée comme distances + loin que la maxi de la nouvelle frame … Aucun besoin de le vider :p
Voila
Maintenant, cette idée ne vient pas de moi … je crois que c’est Corto qui m’en avait parlé (enfin, du principe) et on avait vu ensemble pour optimiser cela :p
@ +
AmiDARK
thellier : Un aperçu de la désormais fameuse vache tournante le week-end dernier
trop fort
>Quel était l’objectif à atteindre derrière cette 3DCow ?
http://thellier.free.fr/Cow3D-stars.png
1) faire un source C de démonstration de comment programmer Warp3D sans dépendances à MiniGL ou StormMesa ni Glut (en pur Warp3d.library + graphics.library)
2) Fournir un programme de test des fonctionnalités de Warp3D qui soit mieux écrit/plus beau/plus complet que le classique WarpTest
3) Servir éventuellement de benchmark d’une machine à l’autre: malheureusement ceci est pas trop le cas car sur Os4(=Warp3D v5) le W3D_DrawElements() (=fonction rapide) se refuse à marcher (=bug) comme sur les autres OS (Warp3d v4) donc j’utilise sur os4 le lent W3D_DrawTriangle()
En bref sur Os4 mon Cow3D est plus lent que ce qu’il devrait être…
Bref ça peut servir à
comparer des machines Os4 entre elles
OU
comparer des machines Os3 ,WinUAE, Aros entre elles
A l’occasion il faudra que je corrige ça….
Alain Thellier
@Thellier : Ok.
Interessant effectivement.
Sinon, j’ai du mal à voir sur les photos et avec le shot que tu as mis en lien.
La vache est un objet 3D ou une texture plaquée (genre un objet 3D plain) ?
PS : Ca m’intéresserait de voir le code source si il est prévu qu’il soit public
@ +
AmiDARK
- Vous devez être connecté pour répondre à ce sujet.
› Forums › AmigaOS, MorphOS et AROS › Développement › Compiler avec GCC sur Sam440 :Comment optimiser?