Optimising my renderer.

Started by
6 comments, last by Jason Z 14 years, 8 months ago
Hi I'm trying to improve upon my renderer that I created for my major project last year (Opengl and C++). Its deferred so overdraw isn't much of an issue. I'm currently trying to integrate instancing on as many pieces of drawn geometry as possible. I've had it before on specific objects such as terrain or vegetation, but now I really want to reduce the amount of special cases in the pipeline. Currently heres the pipeline: Geometry nodes are culled against the viewports bounding box. They are added to a list records of things to draw. This list can be sorted by distance depending on the complexity and overdraw expected. (My assumption is that more time would be wasted on the sort than on overdraw in the differed pipeline) Heres where I'm stuck. I was thinking that every time a record of a node is added to the list I check to see whether a draw call has already been made and just store its matrix and flag the record as instanced. I'm not totally sure I want to take that path however as the search through the list might end up taking more time if the scene complexity becomes too high. If I am storing distances however it would give me an easy way to break up the rendering into foreground, background and middleground lists. Which could speed the searches up. I'm sure theres a better way but Its 8.30am and I'm out of ideas. :P -Si
Advertisement
Instead of a list use a binary tree, that combines inserting and sorting, its then simply a case of rendering each node, left first then right, recursivly.
You could add some kind of RenderState for each node and watch for change in the insert function and then watch a hasChanged flag during rendering to see if you need to change the render state. Thats what I'm doing (sort of) with my renderer.
pushpork
Are you sure that you are CPU bound? If not, then your attention should be focused on the GPU side of things. If so, have you considered using multi-threading to help speed things up? You could do something like performing updating and scene traversal in one thread, then submit the draw operations to a command buffer which gets executed on another thread. This should minimize the CPU pinch point in your engine, and let you use whatever traversal techniques you want.

I think there was an article in ShaderX7 about doing this if you have a copy handy.
Funnily enough I do have shader 7 but I'm between houses and haven't got access to any of my books. >< Its probably why I'm struggling to be inspired. I will try to handle the command generation on another thread (I'm using openMP at the moment for simplicity). The system isn't particularly CPU bound just because of the scenes(http://www.blackskiesgame.com/vids/BlackSkies_hi.wmv) I've been rendering. But I'm currently trying to implement an AI system with hundreds of agents and I want to fix the problem before it occurs.

The binary tree is a very good idea. Its silly that I hadn't thought of that. There are a few other reasons why I'm using lists though. However the benefits of the sorted insertion outweighs my losses in this case.

Thanks guys. :)
Totally off topic I'm afraid but I just had to say your video looks fantastic (and the music really fits too).

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Yeah, I agree, totaly awesome...

@Jason Z:
What would that entail? would you have two command buffers and 'double-buffer' or maybe just a queue that the graphics thread looks at?

cheers
pushpork
is your render loop like

for all batches  lock vertexbuffer  lock indexbuffer   fill both  unlock both  render


some ppl who read quake map tutorial tend to do it in such suboptimal way, i just want to make sure you dont :D
Quote:Original post by JPulham
Yeah, I agree, totaly awesome...

@Jason Z:
What would that entail? would you have two command buffers and 'double-buffer' or maybe just a queue that the graphics thread looks at?

cheers
It depends on what types of command sequences you issue. You just want to make sure that your system works without locks - use the buffer to protect your rendering thread from any type of synchronization bottlenecks. If you double buffer it, then the command buffer would start with a 'begin' command and end with an 'end' command. The same thing could be done with a queue as well - the rendering thread would just watch until a begin/end sequence is in the queue, then grab the sequence between without interrupting the game thread.

I don't really use OpenGL, so I don't know what types of multithreading issues it may or may not have. The D3D11 runtime is specifically set up to allow such a scheme with minimal haggling with the API (that was a shameless plug for D3D11, but seriously - check it out!).

This topic is closed to new replies.

Advertisement