How can I reduce texture locking overhead?

I am software rendering on very slow processors (<300mhz), it’s custom software rendering, not SDL-based. I use SDL in this process to ultimately present the image to the screen. While testing, I noticed there is a non-trivial amount of frametime being spent in the SDL’s texture locking.

My actual software rendering code is extremely cheap, it takes on average 2-3ms per frame at 1000mhz. However once I add in the texture-locking code needed (so I don’t get a black screen), that overhead becomes a bit of an issue once you reach very low CPU clocks.

My code:

/* init */
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
screen_texture = SDL_CreateTexture(ren, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, w, h);
/* process frame */
int pitch = self->width*4;
SDL_LockTexture(screen_texture, NULL, &screen_pixels, &pitch);
/* render to screen_pixels */
SDL_RenderCopy(ren, screen_texture, NULL, NULL);

SDL_UpdateTexture does not help (I originally used that, but replaced it with texture locking), as does adding/removing the SDL_RENDERER_ACCELERATED flag.

How can I reduce the overhead of texture locking? Even by a little bit? Do I need to use a different technique for putting my final pixel data on the screen entirely, if I want reduced overhead?

I don’t know, but I wonder if your extremely slow CPU is converting the RGB888 data to RGBA8888 before uploading.

Failing that: is SDL using OpenGL to get it to the screen (and is that OpenGL not actually using hardware acceleration?). There might be a faster path to the screen, depending on the details of the platform.

I don’t know, but I wonder if your extremely slow CPU is converting the RGB888 data to RGBA8888 before uploading.

How would I check for that?

Actually, looking at SDL’s code, if it’s using the OpenGL backend, it only accepts one format natively, ARGB8888, so it’s definitely going to convert the thing on the CPU during the SDL_UnlockTexture() call.

And then you’re still gambling that the OpenGL backend is actually using a GPU (do you have a GPU on this hardware?). It might be “Software Mesa” or something, which means more CPU time. This is worth investigating.

As a sanity check, you can call SDL_GetRendererInfo() and look at the field to see what backend you got from SDL (“opengl” or “software” or whatever), so we can track this down further.

But to answer the question: (assuming you are using OpenGL behind the scenes) change your pixel format and texture locking overhead should drop dramatically. Just change the SDL_PIXELFORMAT_RGB888 in the SDL_CreateTexture call to SDL_PIXELFORMAT_ARGB8888. The rendering will be incorrect until you fix up the order you write pixel data, but you should be able to see if it’s faster without the conversion happening during UnlockTexture.

1 Like