User Tag List

Página 1 de 2 12 ÚltimoÚltimo
Resultados 1 al 15 de 17

Tema: Rendimiento de pintado en GP2X con SDL

  1. #1

    Fecha de ingreso
    Oct 2009
    Mensajes
    5
    Mencionado
    0 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    0
    Agradecer Thanks Received 
    0
    Thanked in
    Agradecido 0 veces en [ARG:2 UNDEFINED] posts

    Rendimiento de pintado en GP2X con SDL

    Hola a todos,

    Tengo una duda acerca del rendimiento de la GP2X a la hora de pintar tiles en pantalla. Antes de empezar, daré las especificaciones técnicas de mi consola, por si es relevante: Firm: 2.1.1, Modelo: - F100. Mi proyecto básicamente es un port del Mario homebrew para correr en esta consola. Al ver que el framerate era irrisorio, he preparado una versión ultra-reducida del problema, que es el que os presento a continuación, y sólo contiene lo esencial. Funciona bajo SDL, tal como indica el título.

    Mi problema, a grosso modo es el siguiente: Mi bucle de juego, en el que ahora mismo no hago más que un render de un mapa, ejecutado en la portátil, me corre a 19 fps. Teniendo en cuenta que quiero pintar un fondo, un par de personajes, ejecutar la lógica de juego y las colisiones, auguro que esto va a ser catastrófico en un futuro. Así pues, antes de continuar, quiero corregir cual sea el error que tenga para subir el rendimiento al máximo posible.

    Mi bucle de pintado es el siguiente:
    Código:
    	void render()
    	{
    		if(!sheet)
    		{
    			fprintf(stderr, "No MapSheet for map rendering.. Aborting Render\n");
    			return;
    		}
    		for(int i = 0; i < m_TilesW; i++)
    		{
    			for(int j = 0; j < m_TilesH; j++)
    			{
    				SDL_Rect rect_src, rect_dst;
    				int u = (info[i][j] * 16) % 256;
    				int v = ((info[i][j] / 16) * 16);
    				
    				rect_src.x = u;
    				rect_src.y = v;
    				rect_src.w = 16;
    				rect_src.h = 16;
    				rect_dst.x = i * 16;
    				rect_dst.y = j * 16;
    				rect_dst.w = 16;
    				rect_dst.h = 16;
    				SDL_BlitSurface(sheet, &rect_src, screen, &rect_dst);
    			}
    		}
    	}
    Obviamente, para el ejemplo simplificado, m_TilesW = 21 y m_TilesH = 16, de forma que cubre exactamente la pantalla de la gp2x y no pinto nada más de lo necesario. De aquí no se me ocurre qué tocar.

    Para la inicialización de la consola:
    Código:
        SDL_Init(SDL_INIT_EVERYTHING);
        screen = SDL_SetVideoMode(320, 240, 8, SDL_HWSURFACE);
        if (screen == NULL) {
    		fprintf (stderr, "Couldn't set the video mode: %s\n", SDL_GetError ());
    		return false;
    	}
        SDL_EnableUNICODE(1);
        SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
        SDL_Joystick *joystick = SDL_JoystickOpen(0);
        
        if(TTF_Init() == 0)
    	{
    		debug_font = TTF_OpenFont("arial.ttf", 10);
    	}
    	else
    	{
    		return false;
    	}
    Lo que se me ocurre es intentar cambiar los parámetros de SetVideoMode, pero ninguno me ha dado un resultado mejor.

    La función de render es la siguiente:
    Código:
    void renderDebugText(const char *msg, int x, int y)
    {
    	SDL_Rect rect_src, rect_dst;
    
    	SDL_Color c; c.r = 255; c.g = 255; c.b = 255;
    	SDL_Surface *s = TTF_RenderText_Solid(debug_font, msg, c);
    	SDL_Surface *last_texture = picture;
    	
    	rect_dst.x = x;
    	rect_dst.y = y;
    	rect_dst.h = s->h;
    	rect_dst.w = s->w;
    	rect_src = rect_dst;
    	rect_src.x = 0;
    	rect_src.y = 0;
    	SDL_BlitSurface(s, &rect_src, screen, &rect_dst);
    	
    	SDL_FreeSurface(s);
    	return;
    }
    
    CMap map;
    
    static int frames = 0;
    static int last_frame_counter = 0;
    CTimer timer;
    
    void Render()
    {
    	frames ++;
    	map.render();
    	char msg[32];
    	sprintf(msg, "FPS: %d\0", last_frame_counter);
    	renderDebugText(msg, 0, 0);
    	SDL_Flip(screen);
    	
    	if(timer.GetElapsed() > 1000)
    	{
    		timer.Start();
    		last_frame_counter = frames;
    		frames = 0;
    	}
    }
    Nada raro aquí, que yo sepa. Lo único es el RenderDebugText que pide memoria y la libera en tiempo de ejecución para una surface. No supone ningún cambio significativo en el proyecto principal.

    No se me ocurre nada más. Dejo el .c, los archivos auxiliares y el .gpe listo para correr en una GP2X. Cualquier sugerencia es bienvenida.

    Atentamente, nokto.-
    Archivos adjuntados Archivos adjuntados

  2. #2

    Fecha de ingreso
    Mar 2007
    Ubicación
    Barna
    Mensajes
    10,341
    Mencionado
    93 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    368
    Agradecer Thanks Received 
    1,791
    Thanked in
    Agradecido 944 veces en [ARG:2 UNDEFINED] posts
    SDL_Flip(screen) pinta toooda la pantalla, lo que suele ser mala idea en SDL. Tienes que usar SDL_Update() pintando solo las partes de la pantalla que hayan sido modificadas, lo que suele complicar bastante la lógica del juego

    Por otro lado, usa las librerías SDL aceleradas que hay por ahí. No mejoran mucho pero algo hacen. Y si realmente tienes un problema de velocidad plantéate pasar de las SDL y pintar directamente en el framebuffer, utilizando por ejemplo la minilib.

  3. #3

    Fecha de ingreso
    Jan 2008
    Ubicación
    Madrid
    Mensajes
    4,447
    Mencionado
    14 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    86
    Agradecer Thanks Received 
    155
    Thanked in
    Agradecido 91 veces en [ARG:2 UNDEFINED] posts
    A primera vista no estás haciendo nada mal y te debería ir bien de velocidad. No tanto como en el PC, pero vamos que eso se hace en muchos juegos y va bien. Lo que se me ocurre es que estás usando un modo de paleta de 8 bits y eso puede hacer que al pintarse las superficies se realice una conversión. Si tus gráficos por ejemplo tienen 24 bits se están convirtiendo cada vez, ya que la pantalla tiene diferente "formato de píxel". Prueba esta función, que convierte el formato de las superficies a la pantalla, así quedan ya preparadas para pintarse de forma óptima.

    Código:
    SDL_Surface *origen = SDL_LoadBMP("grafico.bmp");
    SDL_Surface *optima = SDL_DisplayFormat(origen);
    SDL_FreeSurface(origen);
    P.D. Es verdad juanvvc, pintar toda la pantalla ralentiza bastante. Y las SDL aceleradas de Paeryn también ayudan a ganar más velocidad.
    Última edición por hardyx; 07/10/2009 a las 01:38

  4. #4

    Fecha de ingreso
    Jun 2004
    Ubicación
    Pinto (MADRID)
    Mensajes
    1,077
    Mencionado
    12 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5
    Agradecer Thanks Received 
    150
    Thanked in
    Agradecido 102 veces en [ARG:2 UNDEFINED] posts
    Aunque pintar toda la pantalla tarda más, en Escape From Minos lo hago así porque los tiles se solapan y en GP2X va bastante bien de velocidad.
    Yo hago lo que ha dicho hardyx, cargar los gráficos con la paleta preparada y usar las librerías aceleradas. Creo que debería bastar.

  5. #5

    Fecha de ingreso
    Oct 2009
    Mensajes
    5
    Mencionado
    0 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    0
    Agradecer Thanks Received 
    0
    Thanked in
    Agradecido 0 veces en [ARG:2 UNDEFINED] posts
    Gracias a todos por vuestras respuestas tan tempranas, no sabéis lo bien que me va.

    @juanvvc
    Al tratarse de un Mario, la pantalla se mueve entera el 99% del tiempo de juego, así que no hay otra que actualizarla de principio a fin. Lo de escribir directamente en el framebuffer me llama bastante la atención; al final, si no lo he entendido mal, sería una aceleración por hardware hecha por mi mismo, cierto?

    @hardyx
    Cierto, olvidé modificar esto. Mi código de carga de imágenes es ahora tal cual el tuyo, con la diferencia que uso sdl_image.h para cargar .png's. Ahora mi framerate es de 80 aprox.

    Segunda pregunta: Todavía no me he pasado a las librerías de aceleración por hardware de Paeryn, pero tal cual está el código (y gracias a un error de copy-paste que hice al montar el .c del archivo que he subido), he descubierto que corre *mucho* mejor bajo 16 bits de profundidad y SDL_SWSURFACE como flag que con 8 bits y SDL_HWSURFACE. Alguien me sabe decir por qué?

    Atentamente, nokto.-

  6. #6

    Fecha de ingreso
    Jan 2008
    Ubicación
    Madrid
    Mensajes
    4,447
    Mencionado
    14 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    86
    Agradecer Thanks Received 
    155
    Thanked in
    Agradecido 91 veces en [ARG:2 UNDEFINED] posts
    Cita Iniciado por nokto
    he descubierto que corre *mucho* mejor bajo 16 bits de profundidad y SDL_SWSURFACE como flag que con 8 bits y SDL_HWSURFACE. Alguien me sabe decir por qué?
    La placa de la GP2X está optimizada para manejar modos de 16 bits, ya que con una palabra de 32 bits lee dos pixels, mientras que en los modos de 8 bits, el color real que se está pintando es un índice a la paleta. Puede que sea más óptimo leer palabras que leer bytes uno a uno.

    Además, no me hagas mucho caso, pero creo que en el SDK oficial las superficies software usan doble buffer y se pintan más rápido.
    Última edición por hardyx; 07/10/2009 a las 23:56

  7. #7

    Fecha de ingreso
    Aug 2003
    Ubicación
    Madrid (Getafe)
    Mensajes
    13,901
    Mencionado
    48 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5
    Agradecer Thanks Received 
    221
    Thanked in
    Agradecido 164 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    2
    Cita Iniciado por juanvvc Ver mensaje
    SDL_Flip(screen) pinta toooda la pantalla, lo que suele ser mala idea en SDL.
    lo bueno de sdl_flip, es que pintes 1 cosa en pantalla o 1 millon sabes que vas a tardar lo mismo pues pinta la pantalla entera y el tema es que muchos juegos usan flip y funcionan a una velocidad decente.

    a mi me huele mas a lo que te dicen de los 8 bits, para mi que te esta convirtiendo en cada pasada todas las superficies a 16 bits para manejarlas internamente.


    haz una prueba cutre con unos tiles a 16 bits y compara el rendimiento.
    Aiken
    < - >
    Cita Iniciado por nokto Ver mensaje
    he descubierto que corre *mucho* mejor bajo 16 bits de profundidad y SDL_SWSURFACE como flag que con 8 bits y SDL_HWSURFACE. Alguien me sabe decir por qué?Atentamente, nokto.-
    pues creo que por lo que te hemos dicho, porque las sdl de gp2x internamente tratan todo a 16bits, con lo que si pones otra profundidad tiene que estar convirtiendo las superficies a 16bits y eso ralentiza un huevo.

    Aiken
    Última edición por Aiken; 08/10/2009 a las 03:19 Razón: Edición automática anti doble-post.

  8. #8

    Fecha de ingreso
    Aug 2004
    Mensajes
    411
    Mencionado
    0 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    0
    Agradecer Thanks Received 
    0
    Thanked in
    Agradecido 0 veces en [ARG:2 UNDEFINED] posts
    Ya te va a 80 FPS, no? Pintas solo los tiles que se ven en pantalla o en cada frame los pintas todos?

  9. #9

    Fecha de ingreso
    Oct 2009
    Mensajes
    5
    Mencionado
    0 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    0
    Agradecer Thanks Received 
    0
    Thanked in
    Agradecido 0 veces en [ARG:2 UNDEFINED] posts
    Hola a todos de nuevo,

    Gracias a vuestra ayuda, he sido capaz de desarrollar mi port del Mario sin más sobresaltos, aprendiendo mucho del desarrollo en consola portátil. Como muestra, os dejo un par o 3 de imágenes para que veais qué se cuece por aquí. Sí! todo lo que veis es funcional!

    Sin embargo, ahora tengo otro problemilla que está afectando de manera indiscriminada mi rendimiento. No tiene mucho que ver con el pintado, pero lo pongo aquí para no abrir un hilo nuevo. Resulta que he empezado a implementar el sonido del juego, usando SDL_mixer como recomiendan los tutoriales que he leído.

    Código:
    bool CSoundManager::Init()
    {
    	int i = Mix_OpenAudio(22050, AUDIO_U16SYS, 2, 1024);
    	if(i == 0)  i = Mix_AllocateChannels(16);
    	return i == 16;
    }
    Hasta aquí todo bien, pero lo dejo como referencia. El problema viene en las siguientes líneas:

    Código:
    void CSoundManager::PlayBGMusic(const std::string &name)
    {
    	Mix_Music *mus;
    	mus = Mix_LoadMUS(name.c_str());
    	m_pBackgroundMusic = mus;
    	Mix_VolumeMusic(64);
    	int res = Mix_PlayMusic(mus, -1);
    }
    Ahí está. Estoy intentando cargar un .ogg como música de fondo, con estas líneas de código. Sin embargo, el contador de frames me baja de 48 a 33 cuando no tengo el limitador activado, lo cual significa un -30% de rendimiento, cosa que no puedo permitirme. He intentado cargar un .mid (que para el caso...), pero la GP2X no parece tragarse de ninguna de las maneras, y un MP3 tampoco me iba bien. El .ogg que cargo tiene, obviamente, un sample rate de 22050KHz y 2 canales de sonido. Aunque también he probado de hacerlo con un solo canal, sin tocar la configuración del motor (ya que mis efectos de sonido son estéreo).

    Cuál es la mejor forma (i.e. más óptima) de hacerlo?

    Muchas gracias a todos por adelantado,
    nokto.-
    Imágenes adjuntadas Imágenes adjuntadas    

  10. #10

    Fecha de ingreso
    May 2008
    Ubicación
    A tu lado, en tus sueños
    Mensajes
    22,309
    Mencionado
    145 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    319
    Agradecer Thanks Received 
    552
    Thanked in
    Agradecido 424 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    3
    Bueno, Bennu utiliza tambien la misma libreria de sonido (que es donde yo uso los ogg's). No entiendo muy bien cuando dices lo del limitador activado. Necesitas reservar 16 canales de sonido ? Por cierto esta quedando de maravilla. Que SDK utilizas y como lo configuraste ?, llevo tiempo queriendo montar el entorno pero aún no tengo claro la mejor opcion.

  11. #11

    Fecha de ingreso
    Aug 2003
    Ubicación
    Madrid (Getafe)
    Mensajes
    13,901
    Mencionado
    48 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5
    Agradecer Thanks Received 
    221
    Thanked in
    Agradecido 164 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    2
    Cita Iniciado por nokto Ver mensaje
    Cuál es la mejor forma (i.e. más óptima) de hacerlo?
    un .mod es mucho mas ligero de memoria y de proceso que un mp3 o un ogg, o incluso que un midi, y ademas no creo que tengas muchos problemas en conseguir .mods de mario.

    Aiken

  12. #12

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,202
    Mencionado
    247 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    675
    Agradecer Thanks Received 
    1,847
    Thanked in
    Agradecido 1,264 veces en [ARG:2 UNDEFINED] posts
    Creo que el problema es que para MIDI necesitas el complemento timidity, o los instrumentos, no estoy seguro. Eso lo puedes mirar, por ejemplo en OLDPLAY de la 2x, que reproduce midi si le añades esos archivos (son unos 32MB y no se que tal va el tema legal).
    De todos modos, si no va OGG (raro, porque con Fenix apenas se nota en el rendimiento) puedes usar como te dicen mod, que son como los MIDI, pero añadiendo los instrumentos, pero se supone que gastan más CPU... pero es raro lo que te pasa con los OGG.
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  13. #13

    Fecha de ingreso
    Jan 2008
    Ubicación
    Madrid
    Mensajes
    4,447
    Mencionado
    14 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    86
    Agradecer Thanks Received 
    155
    Thanked in
    Agradecido 91 veces en [ARG:2 UNDEFINED] posts
    La razón es que la la librería SDL_mixer de la GP2X no incluye soporte para midi ni para mp3. Para ello necesitas otras librerías adicionales. Mira este hilo sobre el tema de la música.

    Además, aunque te parezca raro la GP2X ejecuta más rápido un .ogg (al margen de que ocupe más) que un .mid o un .s3m, porque no tiene canales de instrumentos y lo tiene que hacer todo con emulación. Pero aún así, la música te va a quitar algo de cpu.

  14. #14

    Fecha de ingreso
    Oct 2007
    Ubicación
    Madrid
    Mensajes
    3,441
    Mencionado
    112 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    329
    Agradecer Thanks Received 
    1,183
    Thanked in
    Agradecido 586 veces en [ARG:2 UNDEFINED] posts
    Está quedando muy bien.

    Supongo que lo estarás haciendo, si redibujas la pantalla en cada cuadro, no dibujes los tiles "negros", vamos los que no contienen nada, deja vacía de gráficos la pantalla, pintas los tiles que contengan gráficos y luego los sprites. Al menos en Fénix esto me da mucho más rendimiento en la fase 2 (pantallas fijas de tiles) y fase 3 (scroll horizontal de tiles, aquí hago agrupamiento de tiles para reducir el número de procesos en lugar de vaciar la pantalla, pero claro que Fénix es diferente a C+SDL, pero tampoco dibujo los tiles vacios) del Viaje.

    Si los .ogg te ralentizan mucho, prueba a cargar la música en.wav haciendo "stream", como la música descomprimida ocupa mucho, reserva un buffer circular de al menos 768KB y carga una parte del wav, empieza a reproducirlo y cuando queden unos 100KB o 50KB recarga datos en el buffer, al ser circular con mantener un índice para la reproducción y otro para la escritura en el buffer te bastas.
    Última edición por masteries; 15/12/2009 a las 18:20

  15. #15

    Fecha de ingreso
    Oct 2009
    Mensajes
    5
    Mencionado
    0 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    0
    Agradecer Thanks Received 
    0
    Thanked in
    Agradecido 0 veces en [ARG:2 UNDEFINED] posts
    Gracias a todos. Realmente, me suponía que la cosa iría por ahí. Dado que sigo pensando que voy muy corto de framerate, aprovecharé estas vacaciones para intentar investigar sobre la posibilidad de relegar esta funcionalidad al segundo core. Y si tengo dudas al respecto, que las tendré, ya abriré un segundo hilo.

    Cita Iniciado por GameMaster Ver mensaje
    Bueno, Bennu utiliza tambien la misma libreria de sonido (que es donde yo uso los ogg's). No entiendo muy bien cuando dices lo del limitador activado. Necesitas reservar 16 canales de sonido ? Por cierto esta quedando de maravilla. Que SDK utilizas y como lo configuraste ?, llevo tiempo queriendo montar el entorno pero aún no tengo claro la mejor opcion.
    Realmente no sé con certeza si necesito los 16 canales, pero sé que con 8 puedo quedarme corto. Resulta que Mario es un estilo de juego con un montón de soniditos sonando a la vez, y quiero que se escuchen todos, ya que es gran parte de la gracia del juego. Por otra parte, mi SDK es el que te viene configurado directamente para windows en un IDE de Dev-C++. Si no recuerdo mal, se podía descargar de la wiki de gp2x. Que, por cierto, espero que no sea la mejor opción por que desde luego para hacer según qué cosas (debugar...), Dev-C++ es una auténtica basura... ^^u


    nokto.-

    EDIT: Con "limitador", quería decir "limitador de framerate", es decir, hacer que el juego se pinte como demasía a 30fps. Si no está activado, correrá a la velocidad de la máquina.
    Última edición por nokto; 21/12/2009 a las 15:56

Página 1 de 2 12 ÚltimoÚltimo

Etiquetas para este tema

Permisos de publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •