Tuesday, April 14, 2009

Bucketeer

I've been "silently" developing RibRender (RibTools ? whatever should be called !).

OS X version doesn't compile anymore...  because after porting it to Visual Studio, things with include paths got really messy.

Specifically, Xcode doesn't seem very good at handling partial include paths:


#include "DMath.h"

..will work, but..

#include "DMath/include/DMath.h"

..not really.

I tried playing with settings, but I gave up when setting a path to "." would actually try to scan for the whole harddisk or so.. because it would give me an error message about a found path too long to be handled, and that path was outside the project's folder !

On PC, the development is smoother, but now I hit a difficult problem: bucketing !

REYES pushes the idea of processing one bucked of primitives at once. The screen is subdivided into rectangular areas and each of those will process the primitives (or micro-polygon grids) that hit that bucket.

This adds some extra complexity but it's very memory efficient and possibly better for performance as one is restricted to a small portion of micro-polygons and to a small region of memory at once.
Even better is the fact that, with that system in place, multi-threading becomes much simpler: process N buckets at once, each with a separate thread.

The problem however is that those micro-polygon grids.. that basically correspond to a primitive (or a sub-primitive cut by U,V ranges) will often overlap more than one rectangular bucket.

I read somewhere about splitting the primitive until it doesn't hit other buckets so much (and discard what falls out). However splits naturally happen oriented with the primitive UVs while buckets are screen-oriented... that's a lot of unnecessary splits.
The Production Rendering book talks about dicing the primitives in one bucket and then assign micro-polygons to other buckets if they fall into other buckets.

Either way, this is not very clean to thread. I found this old Open Source RenderMan renderer, called Pixie.
I snooped into the source and it seems to do something similar to what Production Rendering says.. it's also pretty heavy on thread locks, it even used Mutexes instead of the more efficient Critical Sections.
I don't really want to have communicating buckets sending data to each other..

This also raises the question: how is initially decided to which bucket is a primitive assigned ?
Perhaps a primitive should be assigned to all buckets it touches.
The primitive would also have a reference count that counts the number of buckets still to process that are touched by that primitive... but that's one shared piece of information per primitive right there. It could be handled with an InterlockedAdd but I would like to avoid contention at the primitives level if possible.

...I'm not sure what I'll end up doing, but this is a sensitive matter because it will make a big difference when the time will come to use multiple threads. And, in fact, I'd like to start using multiple threads as soon as possible !

ummmummm