10 Replies - 11637 Views - Last Post: 30 August 2013 - 01:26 AM Rate Topic: -----

#1 Mr_Fraggs  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 89
  • Joined: 17-June 12

SDL2 Rendering

Posted 25 August 2013 - 05:41 PM

Hey guys, how's everyone doing today?

So, I've been working on a component/entity system, and i'm almost ready to get it running. My latest problem, which I can't find any resources for for some reason, is rendering in SDL. Yes, it's easy to find basic rendering talk around the internet, but for some reason, I can't find much on double buffering in SDL.

So, as soon as I put in almost enough tiles to cover the screen (using a tile map), rendering them slows the program down substantially. Way down. Maybe around 20 FPS or lower.

I've tracked it down into my Rendering code, which basically just calls SDL_RenderCopy or SDL_RenderCopyEx and copys the part of the texture to draw right into the renderer. I'm using sprite sheets to just draw a portion of the texture, and not the whole thing.

So, my first thought was, is SDL2 using double buffering by default? I tend to think not, but I can't find a way to confirm or deny this. This could be my problem in the first place, but i'm not sure. Secondly, I thought that maybe it was just SDL2 not being fast enough to render 2D graphics. I'm pretty sure this ISN'T the case, especially when I initialize SDL using the SDL_RENDERER_ACCELERATED flag. I thought about using OpenGL rendering, but i'm also pretty sure SDL2 takes care of using OpenGL or DirectX by itself under the hood.

I've been using SDL_Textures to hold the images, so I hope it isn't a problem with the textures living in RAM, and using software rendering to draw everything.

So basically, my questions boil down to, does SDL2 use double buffering by default? If not, I was going to try rendering all my graphics to a texture, then presenting it to the screen, pretty much manually using double buffering. If that isn't the problem, looks like i'm stuck and might need some other advice. Thanks guys!

Is This A Good Question/Topic? 0
  • +

Replies To: SDL2 Rendering

#2 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1011
  • View blog
  • Posts: 4,215
  • Joined: 14-February 08

Re: SDL2 Rendering

Posted 27 August 2013 - 02:08 AM

There could be many reasons for the slowing down of your game, but without some code we will never know ;)
Was This Post Helpful? 0
  • +
  • -

#3 Mr_Fraggs  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 89
  • Joined: 17-June 12

Re: SDL2 Rendering

Posted 27 August 2013 - 01:31 PM

I figured as much, but I wanted to check to see if this was a problem to be solved without having to increase my post length :P/> I'll throw in the basic setup of my rendering, from start to finish. I'm assuming you don't need to see the calls to SDL's IMG_LoadTexture() function for loading the images, so i'll leave those out for now.

As for the actual process, an SDL_Texture* is put into a Texture object that I created, which just holds a SDL_Texture*, along with a list of SDL_Rects to keep track of the frame information. Those are loaded in as a shared_ptr, and when a Renderable Component is created, it is given a shared_ptr to that texture object, giving it a reference. Then, the Render System has a list of Render Components and Position Components, and uses the Texture object in each Render Component to draw the texture, with the Position Component telling the System where to draw the picture. Most of this code (specifically in the Render System) might need some cleaning up, but i'm trying to fix the problem before I make it clean!

Rendering Initialization and Process.
Spoiler


When I don't draw anything (just by taking the SDL_RenderCopy calls out, letting the logic keep running), I do get a small increase in performance. I know the problem is either in actually drawing the images, or it could be the system iterating through each component taking too much time. I have my main loop set up as so:

Spoiler


Which what i'm hoping is limiting the updates per second to 60 (which it is always at, except when rendering takes WAY too long), and the frame rate is uncontrolled for now, just so I can see what happens when it's above 60 FPS. When not rendering anything, I get about 5000 FPS, which I know isn't going to stay like that when I start drawing. When I come close to filling the screen with tiles, i'm looking at about 200 FPS, and when not rendering, but still running the logic, i'm getting about 300. 200-300 FPS is still pretty high, but i'm worried that once I start adding more systems or entities, that the frame rate will slow down below an acceptable rate, which is what I had happen on my last attempt at making an entity/component system.

This post has been edited by Mr_Fraggs: 27 August 2013 - 01:38 PM

Was This Post Helpful? 0
  • +
  • -

#4 Mr_Fraggs  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 89
  • Joined: 17-June 12

Re: SDL2 Rendering

Posted 27 August 2013 - 01:52 PM

And a little update. When using the code above, I commented the entire while loop in the RenderSystem, and just added some code to directly draw the same amount of textures in Render System, and my frame rate goes up to about 1500. I've had an idea that the problem could be in the time it takes to go through each systems' list of Components, and that was the problem and not rendering for a while now, even longer than the actual Rendering being the problem. Does that sound like a possibility?

When just running through the while loop in Render System, without any logic aside from incrementing each iterator to the next element and not doing any drawing logic, i'm getting about 480-500 FPS. It's still an increase, but i'm starting to see that the problem IS in looping through each list using an iterator. Should I be using a faster way to constantly loop through all of the systems' lists of components aside from just using an iterator and while loop? I only have two, sometimes three systems working on the number of components it takes to almost fill a screen with size 1280/720 with 32x32 size tiles, so when I start putting more content and more systems in, I see this number plummeting even more.
Was This Post Helpful? 0
  • +
  • -

#5 Mr_Fraggs  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 89
  • Joined: 17-June 12

Re: SDL2 Rendering

Posted 27 August 2013 - 10:21 PM

So, I think I confirmed that I DON'T have double buffering enabled, because testing some animation code, with simple colored circles I could see tearing. So I was thinking of somehow drawing my pixels onto a texture, then present that texture? I know SDL 1.2 had a double buffer flag you could set, but I know they took that out in this version. How would one go about setting up double buffering in SDL 2? I've looked everywhere online and I can't seem to find any resources on it. Anywhere. Ever.
Was This Post Helpful? 0
  • +
  • -

#6 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 841
  • View blog
  • Posts: 2,472
  • Joined: 20-March 10

Re: SDL2 Rendering

Posted 28 August 2013 - 10:32 AM

View PostMr_Fraggs, on 26 August 2013 - 12:41 AM, said:

I've been using SDL_Textures to hold the images, so I hope it isn't a problem with the textures living in RAM, and using software rendering to draw everything.

So basically, my questions boil down to, does SDL2 use double buffering by default? If not, I was going to try rendering all my graphics to a texture, then presenting it to the screen, pretty much manually using double buffering. If that isn't the problem, looks like i'm stuck and might need some other advice. Thanks guys!


No sdl2 does not use double buffering, its using depending on your system OpenGL or Direct3D to render 2D environments.

The best way to do this is to render all your tiles to one screen texture which holds everything then render that to screen using

sdlTexture = SDL_CreateTexture(sdlRenderer,
                               SDL_PIXELFORMAT_ARGB8888,
                               SDL_TEXTUREACCESS_STREAMING,
                               640, 480);




SDL_TEXTUREACCESS_STREAMING tells SDL that this texture's contents are going to change frequently.

or if you want to have individual sprites or tiles as you did in sdl1.2 do this

sdlTexture = SDL_CreateTexture(sdlRenderer,
                               SDL_PIXELFORMAT_ARGB8888,
                               SDL_TEXTUREACCESS_STATIC,
                               myWidth, myHeight);
.....

//Create textures for all tiles then render.



SDL_TEXTUREACCESS_STATIC says we want to draw this once not over and over again which is probably what you are doing.

Rendering has totally changed in sdl2.0 and is closer to DirectX kind of thinking,

there is no SDL_Flip to do double buffering but its better in sdl2.0 all you have to do is this.

SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &sdlWindow, &sdlRenderer);

.....

SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255);
SDL_RenderClear(sdlRenderer);
SDL_RenderPresent(sdlRenderer);



You have a renderer now, but you have to take care of it and change your mindset, if you were doing a 2D platform game in DirectX
you would always draw everything in graphics memory first by that I mean the whole screen and then render it to the screen, giving really fast results.

SDL and other libraries shield you away from all the headaches of actually writing directX or OpenGL code but in this version they are asking you to think a little like what these two systems are actually doing under the hood.

Its a change in thinking but not a massive sea change they are still wrapping this stuff up for you so you dont have to worry about it.

Regards

Snoopy.
Was This Post Helpful? 1
  • +
  • -

#7 Mr_Fraggs  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 89
  • Joined: 17-June 12

Re: SDL2 Rendering

Posted 28 August 2013 - 12:43 PM

Thanks Snoopy! That was mostly what I was looking for. I found plenty of ways to do it using versions of SDL prior to 2.0, but I haven't been able to find anything on the new version regarding double buffering. I've been going through the documentation trying to piece together myself how to do it, but re-reading SDL_SetRenderTarget and other methods over and over looking for the info I needed only got me so far :P
Was This Post Helpful? 0
  • +
  • -

#8 Mr_Fraggs  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 89
  • Joined: 17-June 12

Re: SDL2 Rendering

Posted 28 August 2013 - 04:39 PM

So, in working on implementing double buffering, I just came across a few questions that I can't seem to find answers to. It's SDL Questions, not really code questions.

1. How would I go about getting pixels from an SDL_Texture* that holds the image, to a SDL_Surface, so that I can then just take all the pixels in the surface and put them on the SDL_Texture backBuffer? I know I can do something along the lines of just call SDL_RenderCopy, set the target of the render to the back buffer texture, then use that, but doesn't that kind of remove the point of using the back buffer if we are still calling RenderCopy for each graphic that needs to render? I was under the understanding that actually copying the pixels from the source texture to a main back buffer texture, then just calling RenderCopy on ONLY the back buffer texture to present it to the screen was the key to speeding up the rendering and reduce tearing?

2. I believe that storing the loaded in images into SDL_Textures, and not SDL_Surfaces which would just let me access the pixels is the proper way to handle image loading. Is this true? If not, then I can just load all images as SDL_Surfaces and access the pixels that way.

I have my SDL_Texture* BackBuffer set up, and have the render function render that texture to the screen, I just need to figure out how to get the pixels that I want to draw from one texture, to a surface, to another. I could be adding in extra steps that I don't need, but the only resource I can find on the matter aside from here is http://wiki.libsdl.org/MigrationGuide, which I have been looking at for a few days now in regards to double buffering. It has a pretty good section on actually setting up the back buffer, but nothing on copying the pixels from the source texture to the back buffer. Thanks!

This post has been edited by Mr_Fraggs: 28 August 2013 - 04:47 PM

Was This Post Helpful? 0
  • +
  • -

#9 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 841
  • View blog
  • Posts: 2,472
  • Joined: 20-March 10

Re: SDL2 Rendering

Posted 28 August 2013 - 06:39 PM

Hi,

No you would use Pixels from SDL_Surface then use SDL_UpdateTexture.

SDL_UpdateTexture(sdlTexture, NULL, Pixels, 640 * sizeof (Uint32));

to update the texture. there is no backbuffer you are still thinking in outdated terms there is just a framebuffer.

This will upload your pixels to GPU memory.

Snoopy.
Was This Post Helpful? 0
  • +
  • -

#10 Mr_Fraggs  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 89
  • Joined: 17-June 12

Re: SDL2 Rendering

Posted 28 August 2013 - 07:29 PM

Alright so I figured that was the best way to do things, and i've been working on getting everything up and running. I'm working on setting up a blank surface in the rendering system, which will hold each individual image drawn in the correct spots. Hopefully should have it done soon, i'll let you know how it turns out!
Was This Post Helpful? 0
  • +
  • -

#11 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1011
  • View blog
  • Posts: 4,215
  • Joined: 14-February 08

Re: SDL2 Rendering

Posted 30 August 2013 - 01:26 AM

As snoopy11 has pointed out, SDL2 will always try to utilise your graphics hardware in the right way. Passing data in the form of buffers to the GPU, the preferred way for your graphics hardware to handle data.

Incidentally, I really like the new rendering system in SDL2, it really makes things a lot easier to squeeze performance. To be honest I can see the issue being with something that you have set up, as rendering data from a texture should be pretty nippy.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1