Elements: Rendering/Threading

Normen… I got the impression that you wanted rendering to participate in the element threading process, apparently so that rendering or a specific viewport could happen as soon as all the elements on that viewport were done updating. Is this still something you are interested in ??



My current take on making that happen would require making element wrappers or extensions for ViewPort and Spacial, and having a separate thread pool for the render manager that would go through those 3 lists in order with a mutex so that one one can actually render at a time. (unless rendering is already thread safe ??)

Ascendion said:

Normen... I got the impression that you wanted rendering to participate in the element threading process, apparently so that rendering or a specific viewport could happen as soon as all the elements on that viewport were done updating. Is this still something you are interested in ??

My current take on making that happen would require making element wrappers or extensions for ViewPort and Spacial, and having a separate thread pool for the render manager that would go through those 3 lists in order with a mutex so that one one can actually render at a time. (unless rendering is already thread safe ??)

As I said, if we could use something then its a generalized "elements" system that we can use in the engine to define such logic. Letting you implement a new render update logic when you dont even know about the current one seems a little dangerous :P If and how we integrate it remains to be seen then. 

I just spend a couple of hours reading over the rendering system code, all the way down to the renderer interface, so I have at least something of a handle on what its doing.



Note: while I am doing all this as a separate layer independent of the core, and doing some extra work to clone existing functionality, there is no reason that, after it has been tested and refined, that the logic embodied cannot be ported into the core should you so desire. You can cherry-pick the portions that you want in the core. We have ALL sorts of options here, and doing it this way keeps me out of the core code for the moment so I do not have to deal with conflicts that may arise.



So lets run down the scenario.



The rendering manager "depends" on its viewports being ready to render, viewports depend on their spacials being ready, spacials may depend on other things being processed (most notably the input system)…



the rendering system has 3 rendering priorities hard coded as lists of viewports to render, and while there is no reason that I can think of that processing the viewport dependencies needs to be handled in sequence, we are constrained to render them in priority order.



What I'm thinking is to create an UpdateThreadPool class that will manage the entire update process. At the start of a frame cycle, the entire dependency tree will be walked, and each element will be registered with the update pool. If there is a thread free and the element indicates that it is ready to update, then the update for that element will be launched. If no thread is available, the element will be added to the "ready" list, elements that are not ready go in the not-ready list of course.



As threads become free, the first element in the ready list will be kicked off until the ready list is empty, at which point the entire not-ready list will be scanned, and any that have become ready will be moved to the ready list, and the first of the newly ready elements handed off to a thread for processing.



The render manager is responsible for starting this entire cycle, and once it has triggered the update cascade, it sits on the main thread waiting for viewports to become ready, at which time it renders them if all the viewports in the earlier priorities have already rendered. I still haven't quite figured out exactly how I want the viewports to signal readiness to the render manager, probably with a semaphore in the render manager that the main thread can wait on, then each time the semaphore is triggered by a viewport completing its update, the render manager can run through the priority lists until it finds a viewport that is ready to render.



I'd previously mentioned having each element call BeginUpdate on any prerequisite elements, and having the begin update code stall the calling thread until the update completes, but I realized that could require as many threads as there are elements to be updated in a worst case scenario, so I cooked this up instead.


Sounds like you could use Fork and Join (i mean from jsr166y). Start with update of root, add start updates of childs and after all are completed actual update of root.