Need fast tile-rendering

SGDK only sub forum

Moderator: Stef

Post Reply
alko
Very interested
Posts: 155
Joined: Thu Aug 07, 2014 9:31 am
Location: Russian Federation

Need fast tile-rendering

Post by alko » Thu Jan 24, 2019 6:33 am

15 frames per second by this code:

Code: Select all

#include <genesis.h>

int main()
{
    SYS_disableInts();

    VDP_setScreenWidth320();
    VDP_setScreenHeight224();

    SYS_enableInts();

    while (TRUE)
    {
        VDP_showFPS(TRUE);
        for (int y = 0; y < 28; y++) {
            for (int x = 0; x < 40; x++) {
                u16 tileIndex = random() % 16;
                VDP_setTileMapXY(PLAN_B, TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, tileIndex), x, y);
            }
        }
        VDP_waitVSync();
    }

    return 0;
}
Image


how to speed up rendering 40*28 tiles?
Image

mix256
Very interested
Posts: 189
Joined: Thu Jan 25, 2018 2:08 pm
Location: Sweden
Contact:

Re: Need fast tile-rendering

Post by mix256 » Thu Jan 24, 2019 8:05 am

This will give you 30fps:

Code: Select all

    u16 tiles[40 * 28];
    while (TRUE)
    {
        VDP_showFPS(TRUE);
        for (int i = 0; i < 28 * 40; i++) {
            tiles[i] = TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, random() % 16);
        }
        VDP_setTileMapDataRect(PLAN_B, tiles, 0,0, 40,28);
        VDP_waitVSync();
    }
This is slightly faster. But still 30fps:

Code: Select all

    u16 tiles[28][40];
    while (TRUE)
    {
        VDP_showFPS(TRUE);
        for (int y = 0; y < 28; y++) {
            for (int x = 0; x < 40; x++) {
                tiles[y][x] = TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, random() % 16);
            }
            VDP_setTileMapData(VDP_PLAN_B, tiles[y], y * 64, 40, DMA_QUEUE);
        }
        VDP_waitVSync();
    }
With reservation that these might not do what I think they do, though. :)

EDIT: If you don't generate the tiles (random) you get over 200 fps on the last one.
Last edited by mix256 on Thu Jan 24, 2019 8:12 am, edited 1 time in total.

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Need fast tile-rendering

Post by tryphon » Thu Jan 24, 2019 8:08 am

At least, use DMA (you put your tilemap data somewhere in RAM, and use DMA_queue() to transfer it).

Stef
Very interested
Posts: 3034
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Need fast tile-rendering

Post by Stef » Thu Jan 24, 2019 9:40 am

The last method given by mix256 is almost the fastest, here is my code to reach 60 FPS (just a bit above it), i needed to simplify the random() method and use a longer map to do a single DMA transfer :

Code: Select all

static u16 rand();
static u16 seed = 0xB6CE;

int main()
{
    u16 tiles[64*28];

    while (TRUE)
    {
        u16 x, y;
        u16* dst;

        VDP_showFPS(FALSE);

        dst = tiles;
        for(y = 0; y < 28; y++)
        {
            for(x = 0; x < 40; x++)
                *dst++ = TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, rand() & 0xF);

            // bypass unused map area
            dst += 64-40;
        }

        // single DMA
        VDP_setTileMapData(VDP_PLAN_B, tiles, 0, 64*28, DMA_QUEUE);

        VDP_waitVSync();
    }

    return 0;
}

static u16 rand()
{
    seed = (seed << 1) ^ GET_HVCOUNTER;

    return seed;
}
Still i think it's better to accept 30 FPS here with a better random and smaller map :)

I've to admit i'm a bit surprised by the poor performance of the compiler here : filling a map with random value is taking a full frame, i'm certain we could achieve it in a much smaller time using good assembly code (less than half of the frame should be possible).

Miquel
Very interested
Posts: 494
Joined: Sat Jul 30, 2016 12:33 am

Re: Need fast tile-rendering

Post by Miquel » Thu Jan 24, 2019 2:33 pm

Accessing VDP during display time is slow since CPU is blocked until VDP has a free time slice.
Help. Spanish TVs are brain washing people to be hostile to me.

Stef
Very interested
Posts: 3034
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Need fast tile-rendering

Post by Stef » Thu Jan 24, 2019 9:04 pm

Here we take care of that of course... and still getting 60 FPS is definitely not easy, just to fill the map randomly.

Chilly Willy
Very interested
Posts: 2845
Joined: Fri Aug 17, 2007 9:33 pm

Re: Need fast tile-rendering

Post by Chilly Willy » Fri Jan 25, 2019 3:22 pm

It's almost certainly the random function and the macro to put together the word. I'd pre-make the rest of the word, then just OR in the randomized value to store in ram. Make the random inline, and use the common shift-xor pseudo-random method to generate the random value.

Stef
Very interested
Posts: 3034
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Need fast tile-rendering

Post by Stef » Fri Jan 25, 2019 4:20 pm

i think the code i posted is already quite minimal (we could replace the HV counter read just using xor-shift only operations for random) and normally GCC 6 isn't too bad at optimizing... but anyway yeah of course we can always push optimization a bit more (unrolling loop, inline all methods, pre-loading values in registers...) :D

alko
Very interested
Posts: 155
Joined: Thu Aug 07, 2014 9:31 am
Location: Russian Federation

Re: Need fast tile-rendering

Post by alko » Sat Jan 26, 2019 9:11 pm

Stef wrote:
Thu Jan 24, 2019 9:40 am
The last method given by mix256 is almost the fastest, here is my code to reach 60 FPS (just a bit above it), i needed to simplify the random() method and use a longer map to do a single DMA transfer :
How to convert this linear addressing to X Y coordinates?
Image

Miquel
Very interested
Posts: 494
Joined: Sat Jul 30, 2016 12:33 am

Re: Need fast tile-rendering

Post by Miquel » Mon Jan 28, 2019 3:31 pm

Stef wrote:
Thu Jan 24, 2019 9:04 pm
and still getting 60 FPS is definitely not easy, just to fill the map randomly.
Here:
viewtopic.php?f=22&t=2892
I do exactly that, and while it takes an appreciable chunk of cpu time, still there is at least 50% of time free. Probably about 60-80%, I don't really remember.

But hey, ingenuity has been always the best friend of game developers; I can think of several options to produce the same effect with MUCH less cpu time. In fact, I can think of one with nearly no cpu time, just two calls to random() per frame. Some others are pretty obvious.

I'm beginning to see lots of "I told you so" on the headers, time to retreat. Have fun developing, that's the key.
Help. Spanish TVs are brain washing people to be hostile to me.

alko
Very interested
Posts: 155
Joined: Thu Aug 07, 2014 9:31 am
Location: Russian Federation

Re: Need fast tile-rendering

Post by alko » Tue Jan 29, 2019 7:40 pm

I want to do tiled raycasting on SMD, but i'm not programmer.
Can anyone help me?

Image
Image

Sik
Very interested
Posts: 920
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Need fast tile-rendering

Post by Sik » Tue Jan 29, 2019 10:20 pm

Look here? (you'd be drawing tiles instead of RGB pixels but the basic concepts apply)
https://lodev.org/cgtutor/raycasting.html
Sik is pronounced as "seek", not as "sick".

alko
Very interested
Posts: 155
Joined: Thu Aug 07, 2014 9:31 am
Location: Russian Federation

Re: Need fast tile-rendering

Post by alko » Wed Jan 30, 2019 6:51 pm

I saw this example
but for me it will be difficult remade math to limited variables fix16
And I still do not understand how to translate linear addressing of tiles into XY-coordinates
Image

Chilly Willy
Very interested
Posts: 2845
Joined: Fri Aug 17, 2007 9:33 pm

Re: Need fast tile-rendering

Post by Chilly Willy » Thu Jan 31, 2019 3:27 pm

Since you're raycasting, I imagine you want the other way around - convert the x/y coords from the ray into a tile address.

Let's assume you use a row-centric arrangement for your tiles to make the bitmap. I.e.,
0 1 2 ... 39
40 41 42...79
80
etc

Let's assume you use two pixels together as a single pixel to simulate more colors via blending side-by-side pixels. This also makes the drawing much easier as you're dealing with bytes instead of nibbles.

Then tiles are 4 bytes wide by 8 lines tall.

Tile_Pixel = (x&3) + (x&~3)*8 + (y&7)*8 + (y&~7)*4*40;

If you make the bitmap column-centric, you can derive the address in a similar manner.

EDIT: Of course, the fastest way to convert from coords to tile address is a simple look-up table. x and y aren't that big (128 or 160 by 224 or 240). I'd just use y<<8 + x as the index.

Post Reply