Main Menu

Speed UP???

Started by ScottieB, May 24, 2014, 09:42:44 AM

Previous topic - Next topic

ScottieB

Is there a way to speed up this crude code and difficulty of tons of pixels???
It would be real usefully to know in demo effects such as water and fire ect...
Thanks

PlayBASIC Code: [Select]
X_Res = 320
Y_Res = 200

Dim Buffer_1#(X_Res,Y_Res)
Dim Buffer_2#(X_Res,Y_Res)

Buffer_1#(X_Res / 2,Y_Res / 2) = 100

Do

Cls

For Y = 1 To Y_Res - 1
For X = 1 To X_Res - 1

Buffer_2#(X,Y) = (Buffer_1#(X - 1,Y) + Buffer_1#(X + 1,Y) + Buffer_1#(X,Y - 1) + Buffer_1#(X,Y + 1)) / 2 - Buffer_2#(X,Y)

Buffer_2#(X,Y) = Buffer_2#(X,Y) * 0.99

Ink RgbFade(Rgb(255,255,255),Buffer_2#(X,Y))

Dot X,Y

Next X
Next Y

Sync

SwapArray Buffer_2#(),Buffer_1#()

Loop




monkeybot

lockbuffer and unlockbuffer

kevin


   The most obvious speeds ups are, locking the buffers, using a more appropriate 'dot' function and removing the redundancy inside the inner loop. 

   Even at 320*200 there's six 2d array accesses inside the inner loop, all of which have multiples inside them as well as  clipping (ie 'play nice' behaviors) inside the debug VM / runtimes.   Doing this approximately 64000 times introduces a lot of overhead.   

   Some others hint that might apply, could be,
   
     * 1D arrays has 30->40% less over head than a 2D array.

     * direct access of the array data (Peek/Poke)
   
     * loop unrolling     

     * variable caching in the diamond filter.


PlayBASIC Code: [Select]
   X_Res = 320
Y_Res = 200

Dim Buffer_1#(X_Res,Y_Res)
Dim Buffer_2#(X_Res,Y_Res)

Buffer_1#(X_Res / 2,Y_Res / 2) = 100

Do

Cls $112233

lockbuffer
ThisRGB=Point(0,0)
For Y = 1 To Y_Res - 1

Yminus1 =Y-1
Yplus1 =Y+1

For X = 1 To X_Res - 1

RGB2# =Buffer_2#(X,Y)

RGB2# = (Buffer_1#(X - 1,Y) + Buffer_1#(X + 1,Y) + Buffer_1#(X,Yminus1) + Buffer_1#(X,Yplus1)) / 2 - RGB2#

Buffer_2#(X,Y) = RGB2# * 0.99

FastDot X,Y,RgbFade(Rgb(255,255,255),RGB2#)

Next X

Next Y

unlockbuffer


if NextDropTime<Timer()
for lp=0 to 10
x=rndrange(1,X_Res-1)
y=rndrange(1,Y_Res-1)
Buffer_1#(X,Y) = 100
next
NextDropTime=Timer()+rndrange(1,10)*10
endif

Sync

SwapArray Buffer_2#(),Buffer_1#()

Loop









kevin

#3
  PB2DLL - Water Demo

     Attached you'll find a machine code version of the above demo tweaked up and run through PlayBASIC2DLL ..  This version is floating point, it's likely to be even faster converted to pure integer..



monkeybot

woo! much better.
Can you do a version with the pd2dll  and show us the difference kev?

kevin


you mean like the one attached the previous post ?? 


ScottieB

#6
Wow!  Holy Crap,  These speedups are so much better.
Kevin I'm not sure how to run the dll what do I need to do?
Do I need an updated playbasic?
I was gonna ask if anyone knew how to increase the resolution as well but it looks like you did in the dll.
Just do know how to make it work?


I always had the problem from time to time about optimisations so this is really kewl.
Thank for the help people.

as for the texture beneath this puddle of water how about if someone can incorporate this.


X_Offset# = Buffer_2#(X - 1,Y) - Buffer_2#(X + 1,Y)
Y_Offset# = Buffer_2#(X,Y - 1) - Buffer_2#(X,Y + 1)

Shading# = X_Offset#

T# = Texture#(X + X_Offset#,Y + Y_Offset#)

P# = T# + Shading#


Now, Plot every pixel at colour P#


***********************************

I'm working through a old school tutorial that always caught my eye but
had trouble make this all run fast enough.
Some as I remember we a super nice face shot of a women with the water on top also
Some one took it further with tangent function doing ray traced water with reflections and refractions.
But I'm still happy for the help so far So
Thanks!


monkeybot

#7
Quote from: kevin on May 25, 2014, 06:54:36 AM

you mean like the one attached the previous post ??  



hmm i suppose my page hadn't refreshed...


impressive stuff!

ScottieB

To my knowledge I also seem to remember how using a pre-calculated colour lookup table/charts
of the pictures pixels elements rangeing from pixels orginal color to darker of lighter could also
possible be a faster optimization.

Back in the days of magic mode 13h or 320x200 was great for something like this so I wondering how
can we possible bring it to lower resolutions now adays with things like double/dual screens interlaced screen modes???

kevin

#9
QuoteWow!  Holy Crap,  These speedups are so much better.
Kevin I'm not sure how to run the dll what do I need to do?
Do I need an updated playbasic?
I was gonna ask if anyone knew how to increase the resolution as well but it looks like you did in the dll.
Just do know how to make it work?

   Load and run it V1.64P


Quote
To my knowledge I also seem to remember how using a pre-calculated colour lookup table/charts
of the pictures pixels elements rangeing from pixels orginal color to darker of lighter could also
possible be a faster optimization.

   Most effects start out with the naive solution, which is a proof of concept version that's generally accurate, but dead slow.  Then to make things faster we're sacrificing something in the method, be it accuracy or some flexibility that can be precomputed out or isn't necessary for the usage.  


ScottieB

Kevin,  Wow! That speeds up everything!
But Mine seems to crash after running for awhile would you know how to fix this?
And also wheres the tool play2dll to turn basic progs into dlls?
Is it easy to run and create the .dlls?
Any help would be great thanks.

ScottieB

Here's the second speedup with texture added.
Kevin it would nice if you could add this to your .dll
Still waiting for replies.

kevin

Quote
And also wheres the tool play2dll to turn basic progs into dlls?
Is it easy to run and create the .dlls?

  see-> PB2DLL blogs..



PlayBASIC Code: [Select]
Dim Texture#(X_Res,Y_Res)

LoadImage "women.jpg",1
DrawImage 1,0,0,0

X_Res = 320
Y_Res = 200

Dim Buffer_1#(X_Res,Y_Res)
Dim Buffer_2#(X_Res,Y_Res)

Buffer_1#(X_Res / 2,Y_Res / 2) = 50

Buffer_1#(X_Res / 2 - 1,Y_Res / 2) = 50
Buffer_1#(X_Res / 2 + 1,Y_Res / 2) = 50

Buffer_1#(X_Res / 2,Y_Res / 2 - 1) = 50
Buffer_1#(X_Res / 2,Y_Res / 2 + 1) = 50

Dim Texture#(X_Res,Y_Res)

For Y = 0 To Y_Res
For X = 0 To X_Res

Texture#(X,Y) = Point(X,Y)

Next X
Next Y





   This is an extremely poor solution to loading the image into an array.   Pretty much everything you need to know is in the previous comments above. 

   Why is the texture array floating point ?  when colours are integer.

PlayBASIC Code: [Select]
                  FastDot X,Y,RgbFade(Rgb(RgbR(Texture#(X,Y)),RgbG(Texture#(X,Y)),RgbB(Texture#(X,Y))),Buffer_2#(X,Y) + 50)





    Here you're reading a 2d floating point array 3 times, when all that is needed is once. 

PlayBASIC Code: [Select]
                  Texel =Texture#(X,Y)

FastDot X,Y,RgbFade(Rgb(RgbR(Texel),RgbG(Texel),RgbB(Texel)),Buffer_2#(X,Y) + 50)




       Next, why  splitting the colour apart to only reconstruct it to get the same result.

        ThisRGB = $223355
        R=RgbR(ThisRGB)
        G=RgbG(ThisRGB)
        B=RgbB(ThisRGB)

        NewRGB=RGB(R,G,B)

        ThisRGB and NewRGB  are the same value. 


        So this line can be further simplified to,

PlayBASIC Code: [Select]
                  Texel =Texture#(X,Y)

FastDot X,Y,RgbFade(Texel,Buffer_2#(X,Y) + 50)





     
        The array access Buffer_2#(X,Y) also isn't needed.  So this line can be further simplified to,

PlayBASIC Code: [Select]
                  Texel =Texture#(X,Y)

FastDot X,Y,RgbFade(Texel,RGB2# + 50)