Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pixel drawing is slow #36

Open
Aloz1 opened this issue May 12, 2016 · 10 comments
Open

Pixel drawing is slow #36

Aloz1 opened this issue May 12, 2016 · 10 comments

Comments

@Aloz1
Copy link
Contributor

Aloz1 commented May 12, 2016

Currently pixel drawing is very slow in Swingame, to the point where drawing each pixel once on a 800x600 window results in a desperate of approximately 1-10 frames per second (dependant on the computer).

Having explored ideas, it seems that drawing all pixel changes to an SDL_Surface then moving those changes to a texture once per frame will dramatically increase the speed.

@Aloz1
Copy link
Contributor Author

Aloz1 commented May 12, 2016

I've tested this so far by adding a new data type named sg_pixbuf_be and have compared it's speed to the current method of drawing pixels directly to a window of size 800x600 pixels.

Drawing directly to the window yields a speed of 134ms per frame on my laptop, whilst drawing to a pixbuf which is then drawn to the screen is approximately 42ms per frame.

Whilst creating a new datatype called pixbuf proves that it would be advantageous to draw in this way, I'm thinking modifying bitmap such that it can act similar to a pixbuf would be a better approach. Bitmap already has both a surface and a texture, bitmap can already have shapes drawn to it, and modifying bitmap would be less intrusive and would continue to work with already existing games/programs.

@macite, any additional comments or thoughts before I go ahead?

@macite
Copy link
Owner

macite commented May 12, 2016

Yeah, this is interesting. If you changed the bitmap then all drawing operations would need to be changed to use that approach -- draw changes to the surface then render to each texture on its draw. There was a reason we didn't do it this way... I remember. Drawing rotated and scaled bitmaps onto other bitmaps.

It may be better to have the pixel buffer and only support something like put pixel.... what else did you want to support for this?

@Aloz1
Copy link
Contributor Author

Aloz1 commented May 12, 2016

I was thinking about having an enum in the bitmap which determines if the last drawing operation was to a SDL_Surface or to a SDL_Texture and syncs one with the other periodically if the next operation was to the opposite data type. For example, if the last drawing operation was a Texture operation and the next one was a Surface operation, then the surface would be synced with the texture.

This would allow multiple pixels to be drawn to a surface relatively quickly, then for the surface to only be transferred to textures once a texture based operation occurs. You'll still get slow cases, like when you draw a pixel, then a shape, then another pixel and another shape. But this seems like a rather odd thing to do anyway and should end up being the same speed as what we've already got.

@jgardner8
Copy link
Contributor

May I suggest a DrawPixelBatch() function that takes an array of pixels and does the surface/texture handling internally? That would mean that the feature is entirely insulated from the rest of the codebase, and it will be clearer that you have to draw all your pixels at once for efficiency.


From: Aloz1 [email protected]
Sent: Thursday, 12 May 2016 2:44:49 PM
To: macite/swingame
Subject: Re: [macite/swingame] Pixel drawing is slow (#36)

I was thinking about having an enum in the bitmap which determines if the last drawing operation was to a SDL_Surface or to a SDL_Texture and syncs one with the other periodically if the next operation was to the opposite data type. For example, if the last drawing operation was a Texture operation and the next one was a Surface operation, then the surface would be synced with the texture.

This would allow multiple pixels to be drawn to a surface relatively quickly, then for the surface to only be transferred to textures once a texture based operation occurs. You'll still get slow cases, like when you draw a pixel, then a shape, then another pixel and another shape. But this seems like a rather odd thing to do anyway and should end up being the same speed as what we've already got.

You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHubhttps://github.com//issues/36#issuecomment-218659129

@macite
Copy link
Owner

macite commented May 12, 2016

Draw Pixel Batch sounds like a good idea in this case. Parameters? May need a PixelBatch type, to avoid issues mapping this between languages.

@jgardner8
Copy link
Contributor

I envisioned it as multiple sets of whatever DrawPixel takes. Then it would be akin to calling DrawPixel in a loop but with efficiency gains. I've not looked at it too closely to be honest, so there may be details to work out -- a PixelBatch type sounds like one of them.


From: Andrew Cain [email protected]
Sent: Thursday, 12 May 2016 4:10:06 PM
To: macite/swingame
Cc: James Gardner; Comment
Subject: Re: [macite/swingame] Pixel drawing is slow (#36)

Draw Pixel Batch sounds like a good idea in this case. Parameters? May need a PixelBatch type, to avoid issues mapping this between languages.

You are receiving this because you commented.
Reply to this email directly or view it on GitHubhttps://github.com//issues/36#issuecomment-218668625

@Aloz1
Copy link
Contributor Author

Aloz1 commented May 12, 2016

That's essentially what I've done by creating sg_pixbuf_be. But after thinking about it, I figured it would be quicker to only update pixels in the texture when they're needed, and only those that have changed...not once every frame (what I've implemented), or by individually transferring pixels across (which is what is currently in swingame).

The way you'd do this is by introducing a SDL_Texture into each pixbuf, then calling either SDL_UpdateTexture or SDL_LockTexture once you've finished drawing pixels to transfer the changes across to the GPU.

Once you've done this however, there is very little difference between sg_pixbuf_bg and sg_bitmap_be...just that one is way faster with pixels...and the other has shape drawing functionality. Hence why my train of thought led to merging sg_pixbuf_be and sg_bitmap_be.

We could keep the two separate, but I felt it would be more convenient and more beneficial to merge the functionality together.

I'll experiment some more and let you know what the numbers are like for speed regarding SDL_UpdateTexture and SDL_LockTexture. I'm currently creating a new texture each frame from the surface data, so there is definitely room for improvement.

@macite
Copy link
Owner

macite commented May 12, 2016

Also make sure you are on the quality/splash-kit-prep branch... branches need to be sorted before we move but this is the current develop branch.

@macite
Copy link
Owner

macite commented May 12, 2016

Branches are tidied up now... work off develop.

@Aloz1
Copy link
Contributor Author

Aloz1 commented Aug 4, 2016

Finally finished both versions. Sorry it took so long, I've been busy with work and had to rebase everything (as well as fix up some small bugs) as I'd unfortunately been developing under the old v4_backend branch. I'll create pull requests for both methods so you can comment on them and see what you think.

As an aside, the way I've implemented this under the bitmap_be version means that bitmap_be always has a surface as well as textures, and remembers where it last drew to so it can keep things in sync. This also ties in quite nicely with how swingame currently keeps bitmaps open without a window.

This was referenced Aug 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants