Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Value of FastPlot library
#1
Is the FastPlot library really going to be faster than a compiled PLOT instruction? Since you've optimised your own PRINT implementation, I would assume that PLOT and DRAW compile to pretty lean machine code do they not? I did some very basic testing comparison of filling using DRAW commands versus looping through FastPlots instead and it seemed roughly the same. Is it perhaps that some libraries are old, and now the compiler is as good with native commands in terms of performance?
Reply
#2
(01-28-2021, 06:39 PM)patters Wrote: Is the FastPlot library really going to be faster than a compiled PLOT instruction? Since you've optimised your own PRINT implementation, I would assume that PLOT and DRAW compile to pretty lean machine code do they not? I did some very basic testing comparison of filling using DRAW commands versus looping through FastPlots instead and it seemed roughly the same. Is it perhaps that some libraries are old, and now the compiler is as good with native commands in terms of performance?

PLOT, DRAW and CIRCLE are no longer ROM ones. They're definitely much faster.
Not sure where did you get "FastPlot" from, because many people have contributed their own libraries, etc.

On the contrary, PRINT is almost as slow as the ROM, because it tries to mimic all the behaviour. If you need "fast sprites", use Putchar (it's not in the library, but it's in the Wiki). I'm trying to optimize it, but it's hard without dropping compatibility or extended features (BOLD, ITALIC, OVER 2 and OVER 3).
Reply
#3
Yes, I suspected it may be a library left over from before the compiler used its own graphics routines. It's advertised in the wiki here:
https://zxbasic.readthedocs.io/en/docs/library/

So, the regular PLOT should be around about as fast after compilation, making this library redundant?
Reply
#4
(01-28-2021, 10:43 PM)patters Wrote: Yes, I suspected it may be a library left over from before the compiler used its own graphics routines. It's advertised in the wiki here:
https://zxbasic.readthedocs.io/en/docs/library/

So, the regular PLOT should be around about as fast after compilation, making this library redundant?

There was an effort to make an even faster plot using a lookup table (256 x 2) bytes, that contains the screen address but it does not speeded up that much. I don't know where the code is. I think Britlion (in this forum) was the author of it.
Reply
#5
The wiki page for FastPlot contains both the regular FastPlot and the lookup table one. The lookup-based one is meant to be 17.6% faster. The code says to use the lookup table from HRPrintFast.bas, but the code in that wiki entry does not contain the lookup table. It offers a link to a download but it's from before the forum migration so it's a dead link:
http://boriel.com/mybb/showthread.php?ti...18#pid3318

You didn't answer my question though. Is it safe to assume that the current ZX BASIC PLOT command is as efficient as the regular FastPlot library function (without lookup table), given that neither use the ROM?
Reply
#6
I've never tried fastplot, to be honest. You can ask Britlion (who contributed all of this). Have a look at https://www.boriel.com/forum/showthread.php?tid=161
Can you try a test with FastPlot vs PLOT?
Just time it with FRAMES counter.
Reply
#7
FastPlot does appear to be faster than the compiler's current PLOT implementation. It can fill the screen in 416 ticks versus 535 ticks for the compiler implementation - a 22.2% improvement. I used this listing to compare:

Code:
#include "zxbasic/library/fastPlot.bas"

FUNCTION timerTicks() AS ULONG
    RETURN INT(65536*PEEK(23674)+256*PEEK(23673)+PEEK(23672))
END FUNCTION

DIM x,y AS UBYTE

CLS
BORDER 6
DO
    FOR y=0 to 191
        'PLOT x,y
        fastPlot(x,y)
    NEXT y
    x=x+1
LOOP UNTIL x=0 '255+1 will overstep the UBYTE to 0

PRINT timerTicks()

Modifying the list to DRAW 255 vertical lines to fill the screen takes 183 ticks - about twice as fast as using FastPlot to plot all the pixels individually.


The reason I was interested in this was because I wanted to find the fastest way to draw a chequerboard fill of a landscape in my game. Using FastPlot.bas I can fill the screen with alternating dots in 225 ticks, only a little bit slower than filling with vertical lines via DRAW. If x and y are INTEGER rather than UBYTE then it slows to 262 ticks. See below:

Code:
#include "zxbasic/library/fastPlot.bas"

FUNCTION timerTicks() AS ULONG
    RETURN INT(65536*PEEK(23674)+256*PEEK(23673)+PEEK(23672))
END FUNCTION

DIM x,y AS UBYTE

CLS
BORDER 6
DO
    FOR y=0 to 191 STEP 2
        fastPlot(x,y)
    NEXT y
    FOR y=1 to 191 STEP 2
        fastPlot(x+1,y)
    NEXT y
    x=x+2
LOOP UNTIL x=0 '254+2 will overstep the UBYTE back to 0

PRINT timerTicks()



Do you have the ability to retrieve attachments from the backup of the old forum before the move to myBB?
http://boriel.com/mybb/showthread.php?ti...18#pid3318 is where the lookup table was for as used by HRPrintFast.bas and for FastPlot's even faster method. It's not in the wiki.
Reply
#8
(02-01-2021, 05:18 PM)patters Wrote: FastPlot does appear to be faster than the compiler's current PLOT implementation. It can fill the screen in 416 ticks versus 535 ticks for the compiler implementation - a 22.2% improvement. I used this listing to compare:

Code:
#include "zxbasic/library/fastPlot.bas"

FUNCTION timerTicks() AS ULONG
    RETURN INT(65536*PEEK(23674)+256*PEEK(23673)+PEEK(23672))
END FUNCTION

DIM x,y AS UBYTE

CLS
BORDER 6
DO
    FOR y=0 to 191
        'PLOT x,y
        fastPlot(x,y)
    NEXT y
    x=x+1
LOOP UNTIL x=0 '255+1 will overstep the UBYTE to 0

PRINT timerTicks()

Modifying the list to DRAW 255 vertical lines to fill the screen takes 183 ticks - about twice as fast as using FastPlot to plot all the pixels individually.


The reason I was interested in this was because I wanted to find the fastest way to draw a chequerboard fill of a landscape in my game. Using FastPlot.bas I can fill the screen with alternating dots in 225 ticks, only a little bit slower than filling with vertical lines via DRAW. If x and y are INTEGER rather than UBYTE then it slows to 262 ticks. See below:

Code:
#include "zxbasic/library/fastPlot.bas"

FUNCTION timerTicks() AS ULONG
    RETURN INT(65536*PEEK(23674)+256*PEEK(23673)+PEEK(23672))
END FUNCTION

DIM x,y AS UBYTE

CLS
BORDER 6
DO
    FOR y=0 to 191 STEP 2
        fastPlot(x,y)
    NEXT y
    FOR y=1 to 191 STEP 2
        fastPlot(x+1,y)
    NEXT y
    x=x+2
LOOP UNTIL x=0 '254+2 will overstep the UBYTE back to 0

PRINT timerTicks()



Do you have the ability to retrieve attachments from the backup of the old forum before the move to myBB?
http://boriel.com/mybb/showthread.php?ti...18#pid3318 is where the lookup table was for as used by HRPrintFast.bas and for FastPlot's even faster method. It's not in the wiki.

Fastplot is almost identical to Compilers PLOT. Fastplot is slightly faster because it does not deal with INVERSE ("erase"), OVER (XOR) and ROM TMP Attributes.
In other words:  INK 4; PAPER 2: PLOT INK 7; PAPER 5; x, y  must remove INK 7; PAPER 5 attributes and restore INK 4: PAPER 2 and other attributes back.

This is why there are 2 fastplot implementations (one specific for XOR / OVER 1, another for OVER 0 and none for inverse) and they use the attribute color directly.

The idea for PLOT is to keep compatibility as much as possible with the original PLOT (as with INPUT or PRINT).

Can you put an example of what do you mean with a "checkerboard" fill, please?
To fill areas with patterns, consider using SPFill for irregular surfaces or DRAW as you said (fastest):
https://github.com/boriel/zxbasic/blob/m...spfill.bas
Reply
#9
(02-01-2021, 05:18 PM)patters Wrote: FastPlot does appear to be faster than the compiler's current PLOT implementation. It can fill the screen in 416 ticks versus 535 ticks for the compiler implementation - a 22.2% improvement. I used this listing to compare:

Code:
#include "zxbasic/library/fastPlot.bas"

FUNCTION timerTicks() AS ULONG
    RETURN INT(65536*PEEK(23674)+256*PEEK(23673)+PEEK(23672))
END FUNCTION

DIM x,y AS UBYTE

CLS
BORDER 6
DO
    FOR y=0 to 191
        'PLOT x,y
        fastPlot(x,y)
    NEXT y
    x=x+1
LOOP UNTIL x=0 '255+1 will overstep the UBYTE to 0

PRINT timerTicks()

Modifying the list to DRAW 255 vertical lines to fill the screen takes 183 ticks - about twice as fast as using FastPlot to plot all the pixels individually.


The reason I was interested in this was because I wanted to find the fastest way to draw a chequerboard fill of a landscape in my game. Using FastPlot.bas I can fill the screen with alternating dots in 225 ticks, only a little bit slower than filling with vertical lines via DRAW. If x and y are INTEGER rather than UBYTE then it slows to 262 ticks. See below:

Code:
#include "zxbasic/library/fastPlot.bas"

FUNCTION timerTicks() AS ULONG
    RETURN INT(65536*PEEK(23674)+256*PEEK(23673)+PEEK(23672))
END FUNCTION

DIM x,y AS UBYTE

CLS
BORDER 6
DO
    FOR y=0 to 191 STEP 2
        fastPlot(x,y)
    NEXT y
    FOR y=1 to 191 STEP 2
        fastPlot(x+1,y)
    NEXT y
    x=x+2
LOOP UNTIL x=0 '254+2 will overstep the UBYTE back to 0

PRINT timerTicks()



Do you have the ability to retrieve attachments from the backup of the old forum before the move to myBB?
http://boriel.com/mybb/showthread.php?ti...18#pid3318 is where the lookup table was for as used by HRPrintFast.bas and for FastPlot's even faster method. It's not in the wiki.

Not sure...
I helped britlion to implement fastplot here (in 2015!):
https://www.boriel.com/forum/showthread....45#pid4345

This routine includes the lookup table, but I guess it's wrong.
I contacted him and the code seems to be lost.
I'll let you know if I find it...

EDIT: Found the attachment here!!
https://www.boriel.com/forum/showthread....24#pid2624

I will upload those .asm files into the wiki to preserve them.
Reply
#10
(02-01-2021, 08:22 PM)boriel Wrote: Fastplot is almost identical to Compilers PLOT. Fastplot is slightly faster because it does not deal with INVERSE ("erase"), OVER (XOR) and ROM TMP Attributes.
In other words:  INK 4; PAPER 2: PLOT INK 7; PAPER 5; x, y  must remove INK 7; PAPER 5 attributes and restore INK 4: PAPER 2 and other attributes back.

Yes I have run into this limitation already and it's probably worth the slight speed penalty to use the compiler version's more complete feature support

(02-01-2021, 08:22 PM)boriel Wrote: This is why there are 2 fastplot implementations (one specific for XOR / OVER 1, another for OVER 0 and none for inverse) and they use the attribute color directly.

Can you upload those to the wiki too? I only found the over 0 one.

(02-01-2021, 08:22 PM)boriel Wrote: Can you put an example of what do you mean with a "checkerboard" fill, please?
To fill areas with patterns, consider using SPFill for irregular surfaces or DRAW as you said (fastest):
https://github.com/boriel/zxbasic/blob/m...spfill.bas

This kind of shading for the landscape:
[Image: attachment.php?aid=310]

I see that in src/arch/zx48k/library/SP only fill.bas is present, but this file contains includes which are missing:
Code:
#include once <SP/PixelUp.asm>
#include once <SP/PixelDown.asm>
#include once <SP/CharLeft.asm>
#include once <SP/CharRight.asm>
#include once <SP/GetScrnAddr.asm>
 
EDIT - ah nm, I see they're in src/arch/zx48k/library-asm/SP

I'm not sure this fill algorithm would work in my case since it needs some kind of hard boundaries, and my landscape is quite a jagged elevation map which can vary by sometimes more than even 8 y pixels for each x increment. I achieved what you see in the screenshot by FOR looping from the bottom to the terrain elevation in pairs of vertical slices - one odd spaced, one even spaced.


Attached Files
.png   fill.png (Size: 6.74 KB / Downloads: 137)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)