Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[Manta] Re: Threading questions


Chronological Thread 
  • From: Abe Stephens < >
  • To:
  • Subject: [Manta] Re: Threading questions
  • Date: Tue, 21 Oct 2008 11:43:54 -0600


Hi, Comments inline:

On Oct 21, 2008, at 10:25 AM, Bo Huang wrote:

1)
In the middle of RTRT::internalRenderLoop(),
 
channel->display->displayImage(myContext, image);
 
draws the ray traced image via glDrawPixels(), provided myContext.proc == 0.
 
Could it be possible that any non-primary thread (proc!=0) that has reached rendering calculation code:
 
currentImageTraverser->renderImage(myContext, image);
 
would contaminate the ray traced image buffer prior to glDrawPixels() finish? I don’t know if I have missed seeing Barrier objects or other synchronization safe guards between those these blocks.

The architecture is pipelined with multiple frames in flight, so that when the current frame is being ray traced by renderImage(...), the previous thread is being displayed by displayImage(...). This avoids a serial bottleneck during image display. (In the code all of the threads call displayImage, but in most implementations all but the first thread return immediately.)


2)
I am creating a new management thread (a different Runnable class than Worker) that listens to system level events. And it is in this thread the ray traced buffer should be blit to screen via channel->display->displayImage(myContext, image), which calls glDrawPixels().
 
Simultaneously, all other threads would be in RTRT::internalRenderLoop() focusing exclusively on the rendering of the tiles as assigned by LoadBalancer.
 
While this tentatively works, related to 1), I don’t see a clear mechanism that lets the management thread finish glDrawPixels(), while blocking the other rendering only threads from contaminating the image. (Indeed, I am seeing tiles from the current and next frames simultaneously on screen if the scene is in motion).

In the unmodified pipeline, there is a separate Image for each active frame in the pipeline, one for the frame that is currently being traced, and another for the previous frame being displayed. If image display takes longer than ray tracing, all of the ray tracing threads will loop back to the barrier at the beginning of the internal rendering loop and wait for the image display thread to join them.


3)
I see a lot of if( proc == 0), or if( firstFrame ) special cases. I wish to eventually refactor them into my management thread. Would this be disadvantageous (along with the management thread idea), as the current architecture has all threads running the same internalRenderLoop() function, perhaps so they can easily be managed by Barrier objects?

Those special cases are mostly there to handle situations when the total number of threads changes during runtime. It gets a bit complicated, but it works ;-)

I think it's useful to have a management thread, or perhaps a GUI/GL thread, but I don't think it should be necessary to refactor or make changes to the engine.  Here's what I've done in the past, to create a GUI display class with three callback methods: 

class GUIDisplay : public ImageDisplay, public GUIGLDisplay {
  void animationCallback( int, int, bool & ) { // Called by Manta animation callback.
    barrier.Wait();      // Synchronize with the GL thread at the beginning of the pipeline.
    output_ready.Down(); // Semaphore, indicates GUI finished displaying previous frame.
  }
  void displayImage(&context, *image) { // Called by Manta ImageDisplay
    if (context.proc == 0) myoutput = image;
  }
  ///////////////////////////////////////////////////////////////
  void GLDisplay() { // Called by GUI thread.
    barrier.Wait(); // Synchronize with Manta at start of frame.
    copy_to_gpu( myoutput );
    output_ready.Up(); // Indicate finished displaying frame.
    display_and_post_process();
  }
};

I've used this design to combine GL rasterization with ray tracing in Manta, it ends up being quite scalable and requires no changes to the Manta code itself. 

The first two methods are called by the Manta thread, as an animation callback and as an image display. The third method is called by the GL thread. The class should contain other methods, e.g. to pass window resize events to Manta via transactions, or pause the animation clock in Manta etc. If the scene is animated, the animation update callback should be added to the engine before the GUIDisplay animationCallback above. The design also assumes that the GLDisplay method is called by the GUI at some high rate, like 200 fps. Obviously it would be possible to pause the renderer by not calling the GLDisplay method and refreshing the current image using some other technique. It's also possible to pause animation, but continue to refresh the image, by stopping the Manta timer.

Abe







Archive powered by MHonArc 2.6.16.

Top of page