GOB! vs SDL2 commands | |
GreG | 20-Mar-2015/10:57:56+1:00 |
Je partage ici mes expériences sur l'extension SDL2 en R3. L'implémentation de R3 View est basée sur des GOB!. Chaque objet visible à l'écran est attaché à un GOB root qui est la fenetre affichée. A bas niveau, les GOB sont traités par le code C. Lorsqu'on utilise View, it y a un temps pour construire la structure de GOB (code Rebol) et un temps pour afficher ces GOB à l'écran (code C). Avec l'extension SDL2, l'affichage écran se fait par des commandes. Il n'est pas indispensable d'avoir une structure d'objets ou de Gob. J'ai fait un test comparatif entre la solution GOB et la solution SDL2. Pour cela, j'ai fait une fenetre de 1000x1000 en taille et remplie de carrés de 10x10 de couleur aléatoire. GOB based solution: probe dt [ for x-axis 0 1000 10 [ for y-axis 0 1000 10 [ append win g: make gob! [size: 10x10] g/offset: as-pair x-axis y-axis g/color: random 255.255.255 ] ] probe dt [show win] ] SDL2 extension solution: probe dt [ for x-axis 0 1000 10 [ for y-axis 0 1000 10 [ set-draw-color random 255.255.255 draw-fill-rect as-pair x-axis y-axis 10x10 ] ] refresh-screen ] GOB! results: speed: 20ms (show) 30ms (show + GOB structure) memory: 9156k SDL2ext results: speed: 27ms memory: 29132k (tests performed on Windows7) Il est difficile de faire une conclusion sur un seul scenario de test. Le fait que l'affichage des GOB! soit traité au niveau du C est un plus. La solution SDL2 consomme plus de mémoire, cette mémoire semble directement liée à la taille de la fenetre. On pourrait construire un block "similaire" à la structure de GOB! et le fournir à l'extension SDL2 mais ce serait au final moins souple que la manipulation des Gob. La motivation de cette extension SDL2 est d'apporter un View-like sur d'autres plateformes. Ici, nous avons compilé et testé sur Windows et OSX sans souci. Une autre approche pourrait etre de pluguer SDL2 derrière le rendering des GOB! de façon à tout garder compatible. | |
ldci | 20-Mar-2015/14:59:09+1:00 |
Toujours dans les tests que nous menons avec Greg, j'ai une bonne nouvelle. R2 peut utiliser des extensions écrites en R3 ! Cela n'a rien d'extraordinaire en soi puisque les extensions R3 ne sont rien d'autre qu'une bibliothèque dynamique, mais cela ouvre d'énormes possibilités. Les extensions pouvant être écrites avec tout langage compilé, on peut maintenant appeler à partir de R2 du code écrit en C++ par exemple. De la même façon, l'interface avec des libraries externes est beaucoup plus facile à écrire en R3 qu'en R2 grâce au superbe travail de Carl qui a conçu une excellente API entre le code Rebol et le code de la lib. Pour pouvoir accéder au code R3 avec R2 il suffit d'utiliser la fonction R2 suivante cvFunc: func [specs lib id] [make routine! specs lib id] qui rend vos appels R2 compatible avec la dll R3. Bien évidemment, vous n'avez pas à réécrire toute la lib: il sous suffit de n'utiliser QUE les fonctions dont vous avez besoin en les déclarant dans le code appelant. Je vous donne un exemple ci-dessous. Ici le code qui appelle les fonctions opencv est optimisé en R3 et néanmoins accessible à un code R2. Pas mal REBOL set 'appDir what-dir ocvDir: join appDir "libs/" picture: to-string to-local-file join appDir "lena.jpg"; ; nos libs R3 highgui: load/library to-file join ocvDir "libhighguiR3.dylib" core: load/library to-file join ocvDir "libcoreR3.dylib" ; la fonction mezzanine qui permet d'accéder à la lib R3 cvFunc: func [specs lib id] [make routine! specs lib id] ptr!: integer! ; les fonctions R3 qu'on va utiliser cvNamedWindow: cvFunc [name [string!] flag [integer!] return: [integer!]] highgui "cvNamedWindow" cvWaitKey: cvFunc [delay [integer!] return: [integer!]] highgui "cvWaitKey" cvLoadImage: cvFunc [name [string!] flag [integer!] return: [ptr!]] highgui"cvLoadImage" cvShowImage: cvFunc [name [string!] img [ptr!]] highgui "cvShowImage" cvDestroyWindow: cvFunc [name [string!]] highgui "cvDestroyWindow" ; le programme wName: "Image 1 [any key to continue]" w: cvNamedWindow wName 1 img: cvLoadImage picture 3 cvShowImage wName img cvWaitKey 0 cvDestroyWindow wName | |
GreG | 20-Mar-2015/15:16:55+1:00 |
Il fallait y penser! | |
ldci | 20-Mar-2015/15:47:01+1:00 |
Un petit bémol, quand même. Cette opération n'est réalisable que si votre DLL R3 utilise les types R2 acceptés dans les routines. Exemple: cvCreateImage: cvFunc [size [pair!] depth [integer!] channels [integer!]] core "cvCreateImage" ne fonctionnera pas car le type pair! n'est pas accepté dans une routine R2. C'est un peu dommage, mais rien ne nous empêche de créer notre lib R3 dans un format compatible R2: ça demande un peu plus de travail, mais on peut s'en sortir avec les raffinements. A creuser en tout cas! | |
ldci | 20-Mar-2015/15:54:45+1:00 |
Bon finalement on s'en sort sans problème ! Il suffit de remplacer le pair! par 2 integer! cvCreateImage: cvFunc [w [integer!] h [integer!] depth [integer!] channels [integer!] return: [ptr!]] core "cvCreateImage" J'avoue que ça me plait ce genre de sport ! Vive REBOL | |
DideC | 20-Mar-2015/17:02:52+1:00 |
Juste pour le fair-play, je pense que ta solution de créer 10000 Gob! de 10x10 n'est pas comparable au code de la SDL ! Il me parait plus correct de faire 10000 'box en code 'draw dans un seul gob! pour l'afficher. Même si ne pratiquant pas du tout R3 et les gob!, je viens de m'y casser les dents Voici mon code... qui ne marche pas ! rebol [] win: make gob! [ offset: 20x20 size: 1000x1000 draw: [] ] c: p: none for x-axis 0 1000 10 [ for y-axis 0 1000 10 [ append win/draw compose [ pen (c: random 255.255.255) fill-pen (c) box (p: as-pair x-axis y-axis) (p + 10x10) ] ] ] view win | |
GreG | 20-Mar-2015/17:51:30+1:00 |
En utilisant Draw:view/no-wait/options win: make gob! [ offset: 20x20 size: 1000x1000 ][offset: 'center] c: p: none tobe-draw: copy [] probe dt [ for x-axis 0 1000 10 [ for y-axis 0 1000 10 [ append tobe-draw compose/only [ pen (c: random 255.255.255) fill-pen (c) box (p: as-pair x-axis y-axis) (p + 10x10) 0 ] ] ] win/draw: bind/only tobe-draw import 'draw ] probe dt [show win] speed: 27ms (show) 37ms (show + draw) memory: 11632k | |
GreG | 23-Mar-2015/17:06:07+1:00 |
Une petite mise à jour basée sur un échantillon de 1000 "show" pour chaque solution (résultat en ms): DRAW: 0.267 GOB: 0.21 SDL2 loop: 0.10 SDL2 gob: 0.11 Je me suis aperçu que je pouvais utiliser les GOBs depuis mon extension, j'ai donc testé et curieusement cela ne va pas plus vite de traiter les GOBs coté C que d'appeler les commandes depuis R3. Bon, ça fait quand meme du 100FPS pour afficher 10000 carrés, c'est pas si mal! | |
shadwolf | 20-Aug-2015/16:26:30+2:00 |
Premierement bravo pour l extension de SDL2 a rebol. C est une experience qui je l espere te servira prochainement pour donner a rebol une extension a Vulkan. Moi ce que je retiens de ton comparatif c est que rebol est plus lent (50 ms contre 29ms) mais que SDL2 (opengl...) consomme 3 fois plus de memoire RAM... Oui je sais on est a l epoque des pc avec 32 GB de ram est il encore necessaire de se preocupe de l optimisation de la consommation de RAM? GOB! results: speed: 20ms (show) 30ms (show + GOB structure) memory: 9156k SDL2ext results: speed: 27ms memory: 29132k plus que GOB vs SDL, on a ici un affrontement AGG vs opengl ... sur le dessin 2D opengl est lamentable ce qui n est pas le cas d AGG parcontre il semblerai que Vulkan apportera une net et ennorme amelioration dans ce domaine. SDL est une API qui sur implemente une librairie par terrible pour le dessin 2D. | |
GreG | 2-Sep-2015/21:39:30+2:00 |
Merci Shad, Effectivement l'approche SDL2 s'oriente plus vers l'affichage de sprite alors que AGG est beaucoup plus graphique. J'ai du mettre en pause mon travail sur ce projet mais j'espere reprendre bientot. Tres formateur en tout cas! | |
Login required to Post. |