|
Post by tbird on Aug 15, 2019 23:12:00 GMT -6
When eyfenna did the sprite sheet example it got me thinking about what I read before about using sprite sheets vs single images. On software rendering apparently there is no or so close to no difference in speed, but in the way hardware accelerated graphics calls work is multiple steps 4 I believe so switching between multiple images should be slower (please correct me if I am wrong), and sprite sheets are supposed to be more efficient. I prefer single images so I was wondering what the actual difference would be, I wrote a quick and ugly example using a sprite sheet and the respective images from the sheet cut up. I got 418ms for the sheet test and 520ms on the single test this is a test of 50,000 images so realistically the difference is negligible but interesting none the less.
Could you guys try it out and see the results and post what your running, I will run this on my gaming PC with a dedicated card tomorrow but this test was ran on my newly acquired crappy lappy
This test could also have a larger margin on more complicated or larger sprites.....will try that also.
i3 - 380m
Intel HD graphics
4GB ram Lubuntu 18.04 (maybe a windows run tomorrow also)
DIM MAX_CHECK MAX_CHECK = 100
DIM Sprite_Image$[MAX_CHECK] DIM Sprite_ID[MAX_CHECK]
DIM numOfSprites
'Load all the images Function LoadSprites() DIM nextEntry$[MAX_CHECK] firstSwitch = 0 tempEntry$ = "" nextSpot = 0 For f = 0 To MAX_CHECK - 1 If firstSwitch = 1 Then tempEntry$ = DirNext$() If Length(tempEntry$) >= 4 Then nextEntry$[f] = Right$(tempEntry$, 4) End If End If If firstSwitch = 0 Then tempEntry$ = DirFirst$() If Length(tempEntry$) >= 4 And firstSwitch = 0 Then nextEntry$[f] = Right$(tempEntry$, 4) End If firstSwitch = 1 End If If nextEntry$[f] = ".png" Or nextEntry$[f] = ".bmp" Or nextEntry$[f] = ".jpg" Then Sprite_Image$[nextSpot] = tempEntry$ Print "Current ID: " +STR$(nextSpot) Print "Current Image: " + tempEntry$ Sprite_ID[nextSpot] = nextSpot LoadImage(Sprite_ID[nextSpot], Sprite_Image[nextSpot]) numOfSprites = nextSpot nextSpot = nextSpot + 1 End If Next End Function
Function FindSpriteID(theSprite$) 'Expensive function run before game loop to locate whatever entities you need direct control over For e = 0 To numOfSprites If Sprite_Image$[e] = theSprite$ Then Return e Exit For End If Next End Function
DIM sheetID sheetID = FindSpriteID("skeleton_sheet.png")
DIM sheetX[50] DIM sheetY[50] DIM cellSize cellSize = 32
Function PrepSpriteSheet() For x = 0 To 9 For y = 0 To 4 sheetX[x] = (x * cellSize) sheetY[y] = (y * cellSize) Next Next End Function
DIM zrnicFont$
If OS = "WINDOWS" Then zrnicFont$ = Dir + "\\zrnic rg.ttf" Else zrnicFont$ = Dir + "/zrnic rg.ttf" End If
LoadFont(1, zrnicFont$, 16) SetColor(RGB(200, 100, 100)) Font(1)
WindowOpen(0, "Single VS Sheet", 0, 0, 1024, 768, 0) CanvasOpen(0, 1024, 768, 0, 0, 1024, 768, 1)
LoadSprites() PrepSpriteSheet()
DIM phase$ phase$ = "sheet"
DIM testStart DIM testTimer_Start DIM testTimer_Stop DIM sheetFinalTime DIM singleFinalTime testStart = 0
DIM counter counter = 0
While NOT Key(K_ESCAPE) ClearCanvas() While phase$ = "sheet" ClearCanvas() If testStart = 0 Then DrawText("Press 'Return' to start sprite sheet test.", 100, 100) If Key(K_RETURN) Then testStart = 1 testTimer_Start = Timer() For i = 0 To 49000 DrawImage_Blit(sheetID, Rand(980), Rand(700), sheetX[counter], sheetY[counter], cellSize, cellSize) counter = counter + 1 If counter = 50 Then counter = 0 End If Next testTimer_Stop = Timer() sheetFinalTime = testTimer_Stop - testTimer_Start testStart = 0 phase$ = "single" End If End If Update() Wend
While phase$ = "single" ClearCanvas() If testStart = 0 Then DrawText("Press 'Space' to start sprite single test.", 100, 100) If Key(K_SPACE) Then testStart = 1 testTimer_Start = Timer() For i = 0 To 49000 DrawImage(Sprite_ID[counter] , Rand(980), Rand(700)) counter = counter + 1 If counter = 50 Then counter = 0 End If Next testTimer_Stop = Timer() singleFinalTime = testTimer_Stop - testTimer_Start phase$ = "done" End If End If Update() Wend
DrawText("Time for sheet test: " + STR$(sheetFinalTime), 100, 100) DrawText("Time for single test: " + STR$(singleFinalTime), 100, 130) DrawText("Press 'Escape' to exit.", 100, 160) Update() Wend
|
|
|
Post by johnno56 on Aug 16, 2019 3:51:02 GMT -6
My PC specs:
i5-4460 @ 3.2gh x 4 8 gb ram Linux Mint 18.3 (64 bit)
Ran the test 10 times. Average "sprite sheet" time:112.2 (fastest 107, slowest 118) Average "single" time: 111.8 (fastest 107, slowest 121)
I hope this helps.
J
|
|
|
Post by eyfenna on Aug 16, 2019 7:06:58 GMT -6
I do the test when I get home from work, though when I coded the spritesheet texample I had decrease of coding time in mind and totally forgot about execution time. Thanks for thinking about latter and writing a test.
|
|
|
Post by tbird on Aug 16, 2019 7:30:30 GMT -6
My PC specs: i5-4460 @ 3.2gh x 4 8 gb ram Linux Mint 18.3 (64 bit) Ran the test 10 times. Average "sprite sheet" time:112.2 (fastest 107, slowest 118) Average "single" time: 111.8 (fastest 107, slowest 121) I hope this helps. J johnno56 do you have a dedicated video card or integrated? What if you run the test with 490,000 iterations what are your results? eyfenna this test is probably much more pointless then your tutorial lol. Strictly for curiosity about the draw call speed between the two. Oddly enough johnno56 there is basically no difference.
|
|
|
Post by tbird on Aug 16, 2019 8:37:35 GMT -6
So interestingly enough I just changed the code to now include the ClearCanvas & Update functions in the smaller while loops and the times are exactly the same, 8144ms through multiple tests, for both, why is that?? So there is clearly a difference and that's because of switching images in the first code, but when actually rendered to screen, its exactly the same.
DIM MAX_CHECK MAX_CHECK = 100
DIM Sprite_Image$[MAX_CHECK] DIM Sprite_ID[MAX_CHECK]
DIM numOfSprites
'Load all the images Function LoadSprites() DIM nextEntry$[MAX_CHECK] firstSwitch = 0 tempEntry$ = "" nextSpot = 0 For f = 0 To MAX_CHECK - 1 If firstSwitch = 1 Then tempEntry$ = DirNext$() If Length(tempEntry$) >= 4 Then nextEntry$[f] = Right$(tempEntry$, 4) End If End If If firstSwitch = 0 Then tempEntry$ = DirFirst$() If Length(tempEntry$) >= 4 And firstSwitch = 0 Then nextEntry$[f] = Right$(tempEntry$, 4) End If firstSwitch = 1 End If If nextEntry$[f] = ".png" Or nextEntry$[f] = ".bmp" Or nextEntry$[f] = ".jpg" Then Sprite_Image$[nextSpot] = tempEntry$ Print "Current ID: " +STR$(nextSpot) Print "Current Image: " + tempEntry$ Sprite_ID[nextSpot] = nextSpot LoadImage(Sprite_ID[nextSpot], Sprite_Image[nextSpot]) numOfSprites = nextSpot nextSpot = nextSpot + 1 End If Next End Function
Function FindSpriteID(theSprite$) 'Expensive function run before game loop to locate whatever entities you need direct control over For e = 0 To numOfSprites If Sprite_Image$[e] = theSprite$ Then Return e Exit For End If Next End Function
DIM sheetID sheetID = FindSpriteID("skeleton_sheet.png")
DIM sheetX[50] DIM sheetY[50] DIM cellSize cellSize = 32
Function PrepSpriteSheet() For x = 0 To 9 For y = 0 To 4 sheetX[x] = (x * cellSize) sheetY[y] = (y * cellSize) Next Next End Function
DIM zrnicFont$
If OS = "WINDOWS" Then zrnicFont$ = Dir + "\\zrnic rg.ttf" Else zrnicFont$ = Dir + "/zrnic rg.ttf" End If
LoadFont(1, zrnicFont$, 16) SetColor(RGB(200, 100, 100)) Font(1)
WindowOpen(0, "Single VS Sheet", 0, 0, 1024, 768, 0) CanvasOpen(0, 1024, 768, 0, 0, 1024, 768, 1)
LoadSprites() PrepSpriteSheet()
DIM phase$ phase$ = "sheet"
DIM testStart DIM testTimer_Start DIM testTimer_Stop DIM sheetFinalTime DIM singleFinalTime testStart = 0
DIM counter counter = 0
While NOT Key(K_ESCAPE) ClearCanvas() While phase$ = "sheet" ClearCanvas() If testStart = 0 Then DrawText("Press 'Return' to start sprite sheet test.", 100, 100) If Key(K_RETURN) Then testStart = 1 testTimer_Start = Timer() For i = 0 To 490 ClearCanvas() DrawImage_Blit(sheetID, Rand(980), Rand(700), sheetX[counter], sheetY[counter], cellSize, cellSize) counter = counter + 1 If counter = 50 Then counter = 0 End If Update() Next testTimer_Stop = Timer() sheetFinalTime = testTimer_Stop - testTimer_Start testStart = 0 phase$ = "single" End If End If Update() Wend
While phase$ = "single" ClearCanvas() If testStart = 0 Then DrawText("Press 'Space' to start sprite single test.", 100, 100) If Key(K_SPACE) Then testStart = 1 testTimer_Start = Timer() For i = 0 To 490 ClearCanvas() DrawImage(Sprite_ID[counter] , Rand(980), Rand(700)) counter = counter + 1 If counter = 50 Then counter = 0 End If Update() Next testTimer_Stop = Timer() singleFinalTime = testTimer_Stop - testTimer_Start phase$ = "done" End If End If Update() Wend
DrawText("Time for sheet test: " + STR$(sheetFinalTime), 100, 100) DrawText("Time for single test: " + STR$(singleFinalTime), 100, 130) DrawText("Press 'Escape' to exit.", 100, 160) Update() Wend
|
|
|
Post by johnno56 on Aug 16, 2019 8:55:55 GMT -6
490000 = 1074 for sheet and 1092 for single.
I am using a slightly flakey Nvidia GF108 card as my previous card had died...
|
|
|
Post by eyfenna on Aug 16, 2019 9:47:33 GMT -6
first benchmark: sprite sheet: 95 single sprite: 116
second test
sprite sheet: 8117 single sprite: 8227 second time second test: both 8177
further times running the second benchmark gives outcome of second time running the test.
on:
Laptop Window 10
Procesor: intel core i5-5200U (3 cores) Ram 8GB
Graphic card: Nvidia GeForce 930M
Now I don't want to throw technical stuff around and sound as a know-it-all which I am not. I have some rough ideas of why yet I had to benchmark wade through each one to prove them right or wrong.
What suprises me is not that jhonno's graphic card is way faster than my mobile card yet that it runs slower than the Intel HD graphics of tbird.
|
|
|
Post by tbird on Aug 16, 2019 10:56:48 GMT -6
Well I am a little surprised also I thought this would have been a very straightforward test, faster the graphics capabilities the faster the execution.... So I am a little lost. The first test maybe that is just making the call but not actually rendering maybe has nothing to do with graphics just speed of processing. The second test though I would have thought would have been a huge difference but it's so similar, maybe something to do with RC being synced at 60fps
|
|
|
Post by johnno56 on Aug 16, 2019 18:04:14 GMT -6
I may have an answer... I think...
I was just looking through the program and noticed something strange. Both "sheet" and "single" loops are supposed to display the sprites, right? Either my old eyes didn't see them on the screen or it didn't happen. So, the timing, could be the time it takes to go through each loop... Just a thought.
Did anyone's tests actually display any sprites?
J
|
|
|
Post by johnno56 on Aug 16, 2019 18:11:32 GMT -6
Nah. Disregard the previous post. It was my eyes... I inserted a slight pause after each loop... Voila! ... Well, that was embarrassing....
J
|
|
|
Post by tbird on Aug 16, 2019 20:35:19 GMT -6
Which test are you referring to johnno56 the first test was just testing the function call speed and the second was actually testing the rendering speed. Although the weird thing is the time is basically the same in mine and eyfenna machines....on the second test. What is the time you get on the second test johnno56
|
|
|
Post by johnno56 on Aug 17, 2019 0:24:55 GMT -6
Well, I'm confused... I thought the displaying of the "sheet" and "single" sprites were the two tests... The times I gave earlier (1074 and 1092) were the times for "sheet" and "single" respectively. After all, the timer results, displayed "singlefinaltime' and 'sheetfinaltime'. What other test were you referring too? Now my brain hurts again....
|
|
|
Post by eyfenna on Aug 17, 2019 1:47:20 GMT -6
Hum tbird how did you conclude that it might be 60 fps?
|
|
|
Post by johnno56 on Aug 17, 2019 4:54:58 GMT -6
Put print fps() within a loop will give you the answer you need....
J
|
|
|
Post by tbird on Aug 17, 2019 6:55:48 GMT -6
johnno56 You are correct the first post of code was 2 tests within, there is also a second block of code which is slightly different, and renders the images to screen.
eyfenna The second test is running @ 60 fps because 490 / 8.1 = 60. If you change the iterations to 600 then it will complete in 10 seconds or just under. So in actuality a better future test would be drawing a large number of sprites changing all at the same time, instead of just one at a time, RC is just running at full speed.
|
|