I just started working on my first 2D game project with SDL, and I am using a mix of software rendering (the game is low-res) and hardware-accelerated rendering on textures for speed. I suppose that in theory I could also try to implement the software rendering portions as GPU shaders, but I have 0 experience using shaders and would probably only consider this after the project is finalized due to the effort involved.
From a purely technical perspective, my understanding is that the software rendering approach is basically infeasible when using OpenGL, because the only way to update texture data is to reupload the texture from system RAM to VRAM via the graphics driver, which is what SDL_UpdateTexture() does and what is dreadfully slow. Direct3D on the other hand allows the CPU to directly access the GPU texture data (this is what happens when calling SDL_LockTexture() when using the D3D11 driver), and performance is generally quite good.
The other important advantage of Direct3D in my case is that it allows to alternate between CPU accesses via locking and rendering to the texture using the GPU.
However in SDL, textures with CPU access (SDL_TEXTUREACCESS_STREAMING) and render-to-texture capability (SDL_TEXTUREACCESS_TARGET) are mutually exclusive. So I cannot, to my knowledge, render to a texture and then modify the contents of the the texture via locking, which is what I need in many instances. (The reverse, writing pixels to a texture with the CPU and then rendering to it via the GPU is of course possible by simply rendering a SDL_TEXTUREACCESS_STREAMING texture to a SDL_TEXTUREACCESS_TARGET texture and continuing from there).
I suppose one of the reasons for this decision in SDL is that when using the OpenGL renderer, where “locking” of a texture is basically implemented by keeping a copy of the texture in system ram, which is reuploaded when “unlocking” the texture, the system ram texture may become outdated when the GPU texture is being rendered to. However, in SDL_LockTexture() it already states that “As an optimization, the pixels made available for editing don’t necessarily contain the old texture data.”, so currently this is not guaranteed anyway and I am not entirely sure if this limitation is only by accident.
Anyway, currently I am considering three options:
- Modifying the D3D11 SDL_CreateTexture() function to allow for both flags SDL_TEXTUREACCESS_STREAMING and SDL_TEXTUREACCESS_TARGET
- Porting the project from SDL to D3D
- Writing my own renderer using shaders and only using SDL for basic I/O (although I don’t really know how to do that yet)
I just wanted to post this here to see if somebody has any suggestions for me, or even might shed a bit more light on why SDL_TEXTUREACCESS_STREAMING and SDL_TEXTUREACCESS_TARGET are mutually exclusive.