Page 1 of 2

DSA faster in VidMem or in MainMem - Point() via DSA?

Posted: Thu Sep 04, 2008 10:12 pm
by Kaeru Gaman
Old Title
Drawing problem: mixed circle and plot slows down


we just discovered an issue I wasn't aware before:

mixing Plot and Circle in the same step of a loop can significantly slow down the execution.

this testcode was hacked together by three people:

Code: Select all

;   ========================================================================
   Enumeration
      #myWindowID
   EndEnumeration

   #myWindowWidth = 800 : #myWindowHeight = 600 : #myStarsQuantity =  150
   #myStarSpeedF  = 1.5 : #myStarSpeedM   =   1 : #myStarSpeedB    =  0.5

;   ========================================================================
   Structure ntStarType
      PositionX.f
      PositionY.f
   EndStructure

   Global Dim StarsLayerF.ntStarType(#myStarsQuantity)
   Global Dim StarsLayerM.ntStarType(#myStarsQuantity)
   Global Dim StarsLayerB.ntStarType(#myStarsQuantity)

   Global myEvent.l    = 0 : Global myKeyPressed.l = 0
   Global myCounterA.w = 0

;   ========================================================================
Procedure.f FpS2()
  Static Start_Zeit, Frames, SendFrames.f
  Zeit_akt = GetTickCount_()
  Frames + 1
  ZeitU = Zeit_akt - Start_Zeit
  If ZeitU
    SendFrames = Frames / ZeitU
  EndIf 
  If Zeit_akt >= Start_Zeit + 10000
    Start_Zeit = Zeit_akt
    Frames = 0
  EndIf
  ProcedureReturn SendFrames * 1000
EndProcedure
;   ========================================================================
   Procedure StarsCalculate()
      For myCounterA = 0 To #myStarsQuantity Step 1
         If (StarsLayerB(myCounterA)\PositionX - #myStarSpeedB) < 0
            StarsLayerB(myCounterA)\PositionX = #myWindowWidth -1
            StarsLayerB(myCounterA)\PositionY = Int(Random(#myWindowHeight -1))
         Else
            StarsLayerB(myCounterA)\PositionX = StarsLayerB(myCounterA)\PositionX - #myStarSpeedB
         EndIf
         
         If (StarsLayerM(myCounterA)\PositionX - #myStarSpeedM) < 0
            StarsLayerM(myCounterA)\PositionX = #myWindowWidth -1
            StarsLayerM(myCounterA)\PositionY = Int(Random(#myWindowHeight - 1))
         Else
            StarsLayerM(myCounterA)\PositionX = StarsLayerM(myCounterA)\PositionX - #myStarSpeedM
         EndIf
         
         If (StarsLayerF(myCounterA)\PositionX - #myStarSpeedF) < 0
            StarsLayerF(myCounterA)\PositionX = #myWindowWidth -1
            StarsLayerF(myCounterA)\PositionY = Int(Random(#myWindowHeight - 1))
         Else
            StarsLayerF(myCounterA)\PositionX = StarsLayerF(myCounterA)\PositionX - #myStarSpeedF
         EndIf
      Next myCounterA
   EndProcedure

   Procedure StarsDraw1()
      ClearScreen(RGB(0, 0, 0))
      StartDrawing(ScreenOutput())
         For myCounterA = 0 To #myStarsQuantity Step 1
            Plot(StarsLayerB(myCounterA)\PositionX, StarsLayerB(myCounterA)\PositionY, RGB(100, 100, 100))
            Plot(StarsLayerM(myCounterA)\PositionX, StarsLayerM(myCounterA)\PositionY, RGB(150, 150, 150))
            Plot(StarsLayerF(myCounterA)\PositionX, StarsLayerF(myCounterA)\PositionY, RGB(200, 200, 200))
         Next myCounterA
         DrawText(0, 0, StrF(FpS2()))
      StopDrawing()
      FlipBuffers()
   EndProcedure

  Procedure StarsDraw2()
     ClearScreen(RGB(0, 0, 0))
     StartDrawing(ScreenOutput())
        For myCounterA = 0 To #myStarsQuantity Step 1
           Circle(StarsLayerB(myCounterA)\PositionX, StarsLayerB(myCounterA)\PositionY, 1, RGB(100, 100, 100))
           Circle(StarsLayerM(myCounterA)\PositionX, StarsLayerM(myCounterA)\PositionY, 1, RGB(150, 150, 150))
           Circle(StarsLayerF(myCounterA)\PositionX, StarsLayerF(myCounterA)\PositionY, 2, RGB(200, 200, 200))
        Next myCounterA
        DrawText(0, 0, StrF(FpS2()))
     StopDrawing()
     FlipBuffers()
  EndProcedure

  Procedure StarsDraw3()
     ClearScreen(RGB(0, 0, 0))
     StartDrawing(ScreenOutput())
        For myCounterA = 0 To #myStarsQuantity Step 1
           Plot(StarsLayerB(myCounterA)\PositionX, StarsLayerB(myCounterA)\PositionY, RGB(100, 100, 100))
           Plot(StarsLayerM(myCounterA)\PositionX, StarsLayerM(myCounterA)\PositionY, RGB(150, 150, 150))
           Circle(StarsLayerF(myCounterA)\PositionX, StarsLayerF(myCounterA)\PositionY, 2, RGB(200, 200, 200))
        Next myCounterA
        DrawText(0, 0, StrF(FpS2()))
     StopDrawing()
     FlipBuffers()
  EndProcedure

   Procedure StarsDraw4()
      ClearScreen(RGB(0, 0, 0))
      StartDrawing(ScreenOutput())
         For myCounterA = 0 To #myStarsQuantity Step 1
            Plot(StarsLayerB(myCounterA)\PositionX, StarsLayerB(myCounterA)\PositionY, RGB(100, 100, 100))
            Plot(StarsLayerM(myCounterA)\PositionX, StarsLayerM(myCounterA)\PositionY, RGB(150, 150, 150))
            Circle(StarsLayerF(myCounterA)\PositionX, StarsLayerF(myCounterA)\PositionY, 2, RGB(200, 200, 200))
         Next myCounterA
         DrawText(0, 0, StrF(FpS2()))
      StopDrawing()
      FlipBuffers()
   EndProcedure

  Procedure StarsDraw5()
     ClearScreen(RGB(0, 0, 0))
     StartDrawing(ScreenOutput())
        For myCounterA = 0 To #myStarsQuantity Step 1
            Plot(StarsLayerB(myCounterA)\PositionX, StarsLayerB(myCounterA)\PositionY, RGB(100, 100, 100))
           Circle(StarsLayerM(myCounterA)\PositionX, StarsLayerM(myCounterA)\PositionY, 1, RGB(150, 150, 150))
           Circle(StarsLayerF(myCounterA)\PositionX, StarsLayerF(myCounterA)\PositionY, 2, RGB(200, 200, 200))
        Next myCounterA
        DrawText(0, 0, StrF(FpS2()))
     StopDrawing()
     FlipBuffers()
  EndProcedure


;   ========================================================================
   If Not InitSprite()
      MessageRequester("Sternenfeld", "Es ist ein DirectX Fehler aufgetreten - InitSprite( )", #PB_MessageRequester_Ok ) : End
   EndIf

   If Not InitKeyboard()
      MessageRequester("Sternenfeld", "Es ist ein DirectX Fehler aufgetreten - InitKeyboard( )", #PB_MessageRequester_Ok ) : End
   EndIf

   If Not OpenWindow(#myWindowID, 0, 0, #myWindowWidth, #myWindowHeight, "Sternenfeld", #PB_Window_ScreenCentered|#PB_Window_BorderLess)
      MessageRequester("Sternenfeld", "Es ist ein Fehler aufgetreten - OpenWindow( )", #PB_MessageRequester_Ok ) : End
   EndIf

   If Not OpenWindowedScreen(WindowID(#myWindowID), 0, 0, #myWindowWidth, #myWindowHeight, 0, 0, 0)
      MessageRequester("Sternenfeld", "Es ist ein Fehler aufgetreten - OpenWindowedScreen( )", #PB_MessageRequester_Ok ) : End
   EndIf

;   ========================================================================
   For myCounterA = 0 To #myStarsQuantity Step 1
      StarsLayerB(myCounterA)\PositionX = Int(Random(#myWindowWidth - 1))
      StarsLayerB(myCounterA)\PositionY = Int(Random(#myWindowHeight - 1))

      StarsLayerM(myCounterA)\PositionX = Int(Random(#myWindowWidth -1))
      StarsLayerM(myCounterA)\PositionY = Int(Random(#myWindowHeight - 1))

      StarsLayerF(myCounterA)\PositionX = Int(Random(#myWindowWidth -1))
      StarsLayerF(myCounterA)\PositionY = Int(Random(#myWindowHeight -1))
   Next myCounterA

;   ========================================================================
   SetFrameRate(1000)
;   ========================================================================

   Repeat
      ;myEvent = WindowEvent()
      ExamineKeyboard()
      If KeyboardPushed(#PB_Key_Escape)
         myKeyPressed = #PB_Key_Escape
      EndIf
      StarsCalculate()
      StarsDraw1()
   Until myKeyPressed = #PB_Key_Escape

;   ========================================================================
   End

;   ========================================================================
change the Number of the Draw routine in the mainloop.

on a CRT the result was 240, 80, 40, 40, 40 FpS, on a TFT it was 120, 60, 4, 4, 4

4 FpS when altering circle and plot in the same loopstep, really strange.


could others please test and confirm, disprove or explain?

Posted: Thu Sep 04, 2008 10:24 pm
by Derek
Confirmed and I have no idea why it is happening, I tried changing the order of circle and plot in routine 3 but it didn't help. I'll keep trying.

Posted: Thu Sep 04, 2008 10:42 pm
by Anonymous
I confirm too , it's very strange :?

Posted: Thu Sep 04, 2008 10:50 pm
by Fred
It's becasue Plot(x,y, color) is accelerated fro direct surafce access, so there is a context switch (from DC to raw surface access). As circle is not, it siwtches again. and again. Better use Plot(x,y) instead as it uses DC standard plot function.

Posted: Fri Sep 05, 2008 1:16 am
by Kaeru Gaman
ah! thanks for that explanation.
I already suspected there was something like a DC change,
but I wondered why because both accesses should aim the same DC.
now that is clear.

so the solution is, either use Plot without color when needing to mix commands up,
or do all plots devided from the other drawings.

this opens another question...
if I have, say, a thousand plots with the same color...
are they faster via Plot(x,y,color), meaning DSA, or with Plot(x,y), meaning DC...?

Posted: Fri Sep 05, 2008 8:10 pm
by Rook Zimbabwe
Reading FRED I would say Plot(x,y)... if you had a great many... then change colors and do the next batch!

:shock: You hacked three people to make that source code... I usually just sacrifice a chicken and dance naked around in my backyard! :shock: :D

Posted: Fri Sep 05, 2008 8:17 pm
by Kaeru Gaman
"by" not "out of"... seems here in Gerany we speak better English than in Texas... ;)

... are you practicing Woodoo?

Reading FRED I would say Plot(x,y)...
well, no, this was not implementet in this answer.

I would read it the other way round:
"Plot(x,y, color) is accelerated for direct surafce access"
thus it is faster than "Plot(x,y) instead ... uses DC standard plot function"

Posted: Fri Sep 05, 2008 8:25 pm
by Demivec
Kaeru Gaman wrote:
Reading FRED I would say Plot(x,y)...
well, no, this was not implementet in this answer.

I would read it the other way round:
"Plot(x,y, color) is accelerated for direct surafce access"
thus it is faster than "Plot(x,y) instead ... uses DC standard plot function"
Actually, if you are mixing in Circle() you would be better off, in your loop examples to use Plot(x,y) instead so that it doesn't have to change DC's .

For instance, this is about twice as fast after you make these changes to keep the DC's from being flipped:

Code: Select all

Procedure StarsDraw5()
  ClearScreen(RGB(0, 0, 0))
  StartDrawing(ScreenOutput())
    FrontColor(RGB(100, 100, 100)) ;added
    For myCounterA = 0 To #myStarsQuantity Step 1
      ;Plot(StarsLayerB(myCounterA)\PositionX, StarsLayerB(myCounterA)\PositionY, RGB(100, 100, 100))
      Plot(StarsLayerB(myCounterA)\PositionX, StarsLayerB(myCounterA)\PositionY)
      Circle(StarsLayerM(myCounterA)\PositionX, StarsLayerM(myCounterA)\PositionY, 1, RGB(150, 150, 150))
      Circle(StarsLayerF(myCounterA)\PositionX, StarsLayerF(myCounterA)\PositionY, 2, RGB(200, 200, 200))
    Next myCounterA
    DrawText(0, 0, StrF(FpS2()))
  StopDrawing()
  FlipBuffers()
EndProcedure

Posted: Fri Sep 05, 2008 8:32 pm
by Kaeru Gaman
Demivec wrote:Actually, if you are mixing in Circle() you would be better off, in your loop examples to use Plot(x,y) instead so that it doesn't have to change DC's .
this was the starting question that was already answered by Fred.


now I'm talking about
Kaeru Gaman wrote:if I have, say, a thousand plots with the same color...
are they faster via Plot(x,y,color), meaning DSA, or with Plot(x,y), meaning DC...?

Posted: Fri Sep 05, 2008 8:37 pm
by Demivec
Kaeru Gaman wrote:
Demivec wrote:Actually, if you are mixing in Circle() you would be better off, in your loop examples to use Plot(x,y) instead so that it doesn't have to change DC's .
this was the starting question that was already answered by Fred.


now I'm talking about
Kaeru Gaman wrote:if I have, say, a thousand plots with the same color...
are they faster via Plot(x,y,color), meaning DSA, or with Plot(x,y), meaning DC...?
You are correct if you are only plotting, to use Plot(x,y,color) for faster results. I thought the conversation was continuing the idea of mixing circles and plots still. My appologies for misconstruing the ideas.

I get a a difference, in the loops you used of 230 fps with Plot(x,y,color) to 214fps with Plot(x,y).

Posted: Fri Sep 05, 2008 8:48 pm
by Kaeru Gaman
hey, no problem...
I also happen sometimes not to read each and every sentence in a thread. ;)
thanks for your support in so much cases, anyways. :)

Posted: Fri Sep 05, 2008 10:03 pm
by Rook Zimbabwe
are you practicing Woodoo?
No I just hate chickens and like to dance naked... :wink: It does, however, explain my coding style!

DemiVec that is a nice example!

Posted: Fri Sep 05, 2008 10:36 pm
by Kaeru Gaman
Demivec wrote:I get a a difference, in the loops you used of 230 fps with Plot(x,y,color) to 214fps with Plot(x,y).
since I do not trust not specialized tests, I wrote one.
I get a really significant difference:
DC: 9718ms DSA: 63ms

...hope I didn't make a mistake...

run with debugger disabled.

Code: Select all

InitSprite()
InitKeyboard()
OpenWindow(0,0,0,800,600,"test")
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)
Define n, x, y, timer1, timer2

; clear the eventqueue to minimize errors
While WindowEvent() : Wend
Delay(100)

FlipBuffers()

StartDrawing(ScreenOutput())
timer1 = ElapsedMilliseconds()
For n=0 To 9
  FrontColor($FFFFFF)
  For y = 0 To 599
    For x = 0 To 799
      Plot(x,y)
    Next
  Next
Next
timer1 = ElapsedMilliseconds()-timer1
StopDrawing()

FlipBuffers()

StartDrawing(ScreenOutput())
timer2 = ElapsedMilliseconds()
For n=0 To 9
  For y = 0 To 599
    For x = 0 To 799
      Plot(x,y,$FFFFFF)
    Next
  Next
Next
timer2 = ElapsedMilliseconds()-timer2
StopDrawing()

out$ = "Testet 4,800,000 Plots" + #CRLF$
out$ + "DC: "+Str(timer1)+"ms" +#CRLF$
out$ + "DSA: "+Str(timer2)+"ms"

CloseWindow(0)

MessageRequester("Result",out$)

Posted: Fri Sep 05, 2008 11:04 pm
by Demivec
Kaeru Gaman wrote:
Demivec wrote:I get a a difference, in the loops you used of 230 fps with Plot(x,y,color) to 214fps with Plot(x,y).
since I do not trust not specialized tests, I wrote one.
I get a really significant difference:
DC: 9718ms DSA: 63ms

...hope I didn't make a mistake...
I got DC: 6047ms DSA: 47ms ( I must have a slower machine...)

Posted: Fri Sep 05, 2008 11:11 pm
by Kaeru Gaman
yours is faster... it's duration time.