# GP2XMy Software Triangle Rasterizer

#### hmw

##### Still Fresh
rixed said:
Trenki said:
What I still don't know is wheter I should take the block based approach or going the scanline based way.
A block based renderer may be affected by the fact that memory writes are slower when far away (when not in the same "bank", I would say).

Refer to this thread on that topic :

http://www.gp32x.de/board/index.php?showtopic=32088

Requires testing to be sure, though.

Or, it can take advantage of this by aligning block storage with cache-lines... Defintively works for depth and stencil buffer, and might be worthwhile for the color buffer as well if your blit-to-screen code is written correctly. Quite similar to what all the tiled graphics accelerators for mobile phones are doing, BTW.

- HM

Last edited by a moderator:

#### una-i

##### Certified Guru
Trenki said:
What I still don't know is wheter I should take the block based approach or going the scanline based way.
About that, I implemented this one or two years ago with the excellent Nicolas Capens article, (I think you both should give him more credits in your source files).

Any way, back to the topic, I used 8x4 blocks and made some extra optimizations over yours. One that I miss is that you are calculating the plane equation at every corner of the block with multiplications and it can be done incrementally adding the proper deltas to the previous plane equation evaluation.

In my current code there is no multiplication inside the blocks loop all is done using increments.

CODE

// Evaluate half-space functions
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;

Here you really only need to sub DY12 from one block to the nect on the right, also you dont need to calculate for th four corners as the next block right plane equations are current block plane equations.
Same applies for perspective correct interpolands, and for one block an the one in the same X position on the next line.

This two things speed up a lot all the process.

Also something a it "clever" than;

CODE

// Loop through blocks
for(int y = miny; y < maxy; y += BLOCK_SIZE)
{
for(int x = minx; x < maxx; x += BLOCK_SIZE)
{
}
}

On the cache think I had my zbuffer stored by tiles instead of scans and that helped a lot to the cache coherency, also using tilled textures helps.

For "pixel shaders" having a function pointer was a problem in the gp32 were I developed that. but I used a template functor and the call was for a block plus a bit field of affected pixels in a block.

Well hope this helps a bit.

Last edited by a moderator:

#### Trenki

##### Member
I'm now in the process of coding up a small demo for the GBAX 2007 competition and hope to put something together in time. I currently have some problems :

The following function computes step values from the plane equations which have been computed earlier for each interpolant.

CODE

template <int block_size>
inline void compute_stepvalues(int64_t plane[4], int step[3])
{
if (plane[2] != 0) {
// precompute how much to step for block_size pixels in x and y
step[0] = (int)((plane[0] * (block_size<<4)) / -plane[2]);
step[1] = (int)((plane[1] * (block_size<<4)) / -plane[2]);
step[2] = (int)(plane[3] / -plane[2]);
} else step[0] = step[1] = step[2] = 0;
}

In this code I have 3 times the 64 bit division by -plane[2] which actually holds the triangles area. I figured i could compute 1/-plane[2] in fixed point once and then use only a multiplication instead of a division.
Also looking at the source of the Vincent 3d library it is done by taking the inverse of the area and then doint the multiplication.

I've tried to do so using a 4.28 fixed point value for the inverse area and modifying the source accordingly also getting rid of the redundancies in the compute_plane function but this way I get z buffering artifacts.
@hmw Did you also have such problems in the Vincent library? How did you solve them?

For now I don't have a good solution as all the values seem to come out incorrectly...

Edit: Now I got it working without the divides and and the z buffering problems are also gone!! This gave another ~30% speed improvement!

#### Trenki

##### Member
Hi fellows!

My demo for GBAX2007 is now complete and now also the renderer/rasterizer is a complete solution which now can also do point and line rendering. I will release the final source of the rasterizer after GBAX to everyone who wants to have it!

My next endeavour is to utilize the second CPU. Hopefully I will get the rasterizer to work on both CPUs in parallel which could potentially double the speed.

#### Trenki

##### Member
I've now got a website where I uploaded a vastly improved version of my renderer: www.trenki.net. Check it out if you are interested.

The newest renderer is not block based any more and this gave an additional speed boost.

#### xhyldazhk

##### Still Fresh
Interesting. I saw your postings in gamedev.net too, downloaded the renderer and its really fast. The only thing with your renderer (isnt really an issue) is that its written in C++ instead of C, so isn't possible to use it to code onboard (yet). But great renderer... will you make some games with it?

#### Trenki

##### Member
xhyldazhk said:
Interesting. I saw your postings in gamedev.net too, downloaded the renderer and its really fast. The only thing with your renderer (isnt really an issue) is that its written in C++ instead of C, so isn't possible to use it to code onboard (yet). But great renderer... will you make some games with it?
Writing it in C++ is a much better option. This way I use C++ templates which allows me to write one single triangle rasterization function and specialize it with template parameters. So the number of source lines and thus the amount of code to maintain is low. This is in contrast to renderers which use macros to specialize code or even do dynamic code generation. With C++ templates optimized specialized code can be generated automatically and it can potentially be optimized better than dynamically generated code. And its a lot easier.

I would like to make some simple game, but that is such a big amount of work so I don't have any plans right now.

Currently I'm working on something for the second CPU and eventually I intend to make a dual cpu renderer which could improve speed dramatically.

Last edited by a moderator:

#### hmw

##### Still Fresh
Trenki said:
I've now got a website where I uploaded a vastly improved version of my renderer: www.trenki.net. Check it out if you are interested.

The newest renderer is not block based any more and this gave an additional speed boost.

Nice work! I'll see if and how this can be merged back into Vincent 2.0. If you don't mind...

- HM

Last edited by a moderator:

#### Trenki

##### Member
hmw said:
Trenki said:
I've now got a website where I uploaded a vastly improved version of my renderer: www.trenki.net. Check it out if you are interested.

The newest renderer is not block based any more and this gave an additional speed boost.

Nice work! I'll see if and how this can be merged back into Vincent 2.0. If you don't mind...

- HM

Go ahead if you wan't to do so. I'd like to be keep up to date on this then. I think it is definitly possible to write an OpenGL|ES or whatever layer on top of it. I suppose in Vincent 2.0 you wan't to have support for the OpenGL shading language? This would be quite some amount of work. Doesn't OpenGL|ES 2.0 require floating point precision? I hope to be able to start with my dual core rendering project soon.

Last edited by a moderator:

#### hmw

##### Still Fresh
Trenki said:
Go ahead if you wan't to do so. I'd like to be keep up to date on this then. I think it is definitly possible to write an OpenGL|ES or whatever layer on top of it. I suppose in Vincent 2.0 you wan't to have support for the OpenGL shading language? This would be quite some amount of work. Doesn't OpenGL|ES 2.0 require floating point precision? I hope to be able to start with my dual core rendering project soon.
Yes, Vincent 2.0 has a shading language compiler (which I am currently debugging). You are right about the need for floating support; at least 16-bit floating point numbers for the rasterizer and downstream. My primary target for Vincent 2.0 are actually FPGA based systems, and I have those floating point units already coded up in Verilog.

Cheers,
HM

Last edited by a moderator:

#### GernotFrisch

##### Member
Bringing this back to life:
I'd like to start using this thing. But I don't understand how to use the matrix stuff.
Can you provide glFrustum/glViewport/glMultMatrix like functions?

#### Trenki

##### Member
KungPhoo said:
Bringing this back to life:
I'd like to start using this thing. But I don't understand how to use the matrix stuff.
Can you provide glFrustum/glViewport/glMultMatrix like functions?
Hi!

I updated the software rasterizer in the last few days, so you might wan't to check out the newest version.
There is now also a second example displaying a 5000 triangle model of a cow with custom per vertex lighting. It uses my vector_math library together wich my fixed point library. They are specifically optimized to work well together.
The vector_math library provides all functions to contruct frustum, perspective, translation, rotation etc. matrices. glMultMatrix does nothing more than just current_matrix *= new_matrix;
Instead of glViewPort you would set the viewport by calling the appropriate function from the GeometryProcessor class.
It is generally best to take a look at the examples applications provided to see a how to use the rasterizer.

For further questions you can send me an email, or a PM, or maybe we will meet on IRC.

Last edited by a moderator:

Replies
24
Views
9K
Replies
68
Views
40K
Replies
2
Views
1K
Replies
4
Views
1K
Replies
7
Views
3K