1

im doing a graphic interface in SDL2 but if i create the renderer with the flags SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC i get a notable slowdown in comparation with the flag SDL_RENDERER_SOFTWARE what i think shouldn't be possible.

I can't use SDL_RENDERER_SOFTWARE because i need enable VSYNC for avoid the tearing and i need double buffer for that.

Actually i realize that the bottleneck is with the function SDL_CreateTextureFromSurface().

Like my code is pretty big i'll try to explain it instead of past everything here:

  1. Initialize SDL and create a SDL_Surface named screen_surface with SDL_CreateRGBSurface with the same size than my window where ill blit any other surface.
  2. I draw a big square in the middle of that surface with SDL_FillRect and draw a rack inside that square using two times SDL_FillRect for draw two squares, one 2 pixels more big than the next one and like that simulate a empty square (i know i can do the same with SDL_RenderDrawRect but i think is more optimal draw in a surface instead of the Render) for every cell of the rack until i have 4096 cells;

  3. now using SDL_TTF i write info in each cell for that i use TTF_RenderUTF8_Blended for get a surface for each cell and i use SDL_BlitSurface for 'fusion' this surfaces with the screen_surface

  4. And finally i want to go through the big square illuminating the cells that are being cheked for that i use SDL_FillRect for draw a little square that travel throught the rack.

  5. Finally i use the SDL_CreateTextureFromSurface for transform screen_surface in screen_texture followed for SDL_RenderCopy and SDL_RenderPresent

This five steps are inside of the main while with the event management and following the recomendations in the SDL_API i do SDL_RenderClear each loop for redraw everything another time.

Said all this how i said at the begining i realise that the bottleneck is step 5 independent from the another steps because if i take the steps 2 and 3 and i do them before the while leaving inside the while only the creation of the rack illumination on a black window (cause im not drawing anything) i get the same slowdown. Only if i manage to draw things without use textures the velocity increase notably.

There are my questions:

  1. Why could this happening? Teorically use double buffering shouldn't be faster than use Software Renderer?

  2. There is any form to simulate vsync in Software Renderer?

  3. Can i Render a Surface without build a Texture?

PD: I have read a bunch of post around the internet and im gonna answer some typical questions: i reutilize the screen_surface, i can't reutilize the surface that TTF returns, im creating and destroying the texture each loop (cause i think i can not reutilize it).

I let here my code

int main(int ac, char **av)
{
    t_data      data;

    init_data(&data) /* initialize SDL */
    ft_ini_font(data); /* Initialize TTF */
    ft_ini_interface(data); 
    main_loop(&data);
    ft_quit_graphics(data); /* Close SDL and TTF */
    free(data);
    return (0);
}

void                main_loop(t_data *data)
{
    while (data->running)
    {
        events(data);
        SDL_BlitSurface(data->rack_surface, NULL, data->screen_surface, &(SDL_Rect){data->rack_x, data->rack_y, data->rack_w, data->rack_h}); /* Insert the rack in the screen_surface */
        ft_write_info(data);
        ft_illum_celd(data);
        set_back_to_front(data);
    }
}

void                ft_ini_interface(t_data *data)
{
    data->screen_surface = SDL_CreateRGBSurface(0, data->w, data->h, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK)
    ...
    /* stuff for calculate rack dims */
    ...
    data->rack_surface = generate_rack_surface(data);

}

void        generate_rack_surface(t_data *data)
{
    int i;
    int j;
    int k;

    data->rack_surface = SDL_CreateRGBSurface(0, data->rack_w, data->rack_h, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK);
    SDL_FillRect(Graph->rack, NULL, 0x3D3D33FF);
    ...
    /* ini i, j, k for drawn the rack properly */
    ...
    while (all cells not drawn)
    {
        if (k && !i)
        {
            data->celd_y += Graph->data->celd_h - 1;
            data->celd_x = 0;
            k--;
        }
        SDL_FillRect(data->rack, &(SDL_Rect){data->celd_x - 1, data->celd_y - 1, data->celd_w + 2, data->celd_h + 2}, 0x1C1C15FF))
        SDL_FillRect(data->rack, &(SDL_Rect){data->celd_x, data->celd_y, data->celd_w, data->celd_h}, 0x3D3D33FF)
        data->celd_x += data->celd_w - 1;
        i--;
    }
}

 void       ft_write_info(t_data *data)
{  
    SDL_Color color;
    char *info;

    while (all info not written)
    {
        color = take_color(); /*take the color of the info (only 4 ifs) */
        info = take_info(data); /*take info from a source using malloc*/
        surf_byte = TTF_RenderUTF8_Blended(data->font, info, color);
        ...
        /*stuf for take the correct possition in the rack */
        ...
        SDL_BlitSurface(surf_byte, NULL, Graph->screen.screen, &(SDL_Rect){data->info_x, data->info_y, data->celd.w, data->celd.h});
        SDL_FreeSurface(surf_byte);
        free(info);
    }

        void    ft_illum_celd(t_data *data)
{
    int color;
    SDL_Rect    illum;

    illum = next_illum(data) /* return a SDL_Rect with the position of the info being read */
    SDL_FillRect(data->screen_surface, &pc, color);
}

    void            set_back_to_front(t_data *data)
{
    SDL_Texture *texture;

    texture = SDL_CreateTextureFromSurface(data->Renderer, data->screen_surface);
    SDL_RenderCopy(data->Renderer, texture, NULL, NULL);
    SDL_DestroyTexture(texture);
    SDL_RenderPresent(data->Renderer);
    SDL_RenderClear(data->Renderer);
}
  • 1
    You should definitely put a MVCE (even if its not that minimal), try to cut as much as you can. – aram Jul 19 '18 at 13:05
  • Make sure you're using [a pixel format that your Renderer backend likes](https://stackoverflow.com/a/33312056/44729). Others may incur slow conversions. Definitely seconding the [mcve] though. – genpfault Jul 19 '18 at 13:46
  • Im ussing [SDL_CreateTextureFromSurface](https://wiki.libsdl.org/SDL_CreateTextureFromSurface) and lookslike i can't select the pixelformat i have cheked [here](https://wiki.libsdl.org/SDL_QueryTexture) too but how i know what format my Render likes? – Jaume Garcia Sanchez Jul 19 '18 at 14:30
  • 1
    Your program doesn't compiles, how is that verifiable? – aram Jul 20 '18 at 03:49
  • @JaumeGarciaSanchez it would appear you don't use SDL rendering at all except final part when you convert your prepared surface to texture for displaying. `SDL_CreateTextureFromSurface` creates static texture; you might want to create single streaming texture, lock it, and update with surface pixels, although extra care have to be taken with texture/surface pixel formats. Or change your rendering approach and use textures for everything, possibly with pre-baking of composite static parts. – keltar Jul 20 '18 at 08:19
  • @genpfault i have been looking all the formats im using and maybe you are right but i realize that with `GetRenderInfo` i see that my render only have 6 formats and any of them is the format i want, how can i add formats? – Jaume Garcia Sanchez Jul 21 '18 at 08:42
  • Oh i have discovered SDL_MapRGBA okey now the velocity has increased notably looks like this was my problem. Thank you @genpfault – Jaume Garcia Sanchez Jul 21 '18 at 08:56

0 Answers0