HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HdRenderThread Class Reference

#include <renderThread.h>

Public Member Functions

HD_API HdRenderThread ()
 
HD_API ~HdRenderThread ()
 
API for thread management

Methods to configure, start, and stop the render thread. These functions are not threadsafe.

HD_API void SetRenderCallback (std::function< void()> renderCallback)
 Set the rendering callback for the render thread to use. More...
 
HD_API void SetShutdownCallback (std::function< void()> shutdownCallback)
 
HD_API void StartThread ()
 
HD_API void StopThread ()
 
HD_API bool IsThreadRunning ()
 
API for hydra threads

Methods for the render thread to communicate with hydra. These should only be called from the render thread, from inside the render callback.

HD_API void StartRender ()
 
HD_API void StopRender ()
 
HD_API bool IsRendering ()
 
HD_API void PauseRender ()
 
HD_API void ResumeRender ()
 
HD_API bool IsStopRequested ()
 
HD_API bool IsPauseRequested ()
 
HD_API bool IsPauseDirty ()
 
API for both hydra and render threads

Methods for both hydra and the render threads to synchronize access to other data.

HD_API std::unique_lock
< std::mutex > 
LockFramebuffer ()
 

Detailed Description

HdRenderThread is a utility that specific render delegates can choose to use depending on their needs. It provides a system for rendering in a background thread, and synchronizing between hydra (either in the main thread, or the sync threadpool) and the rendering thread.

State Machine

The render thread is implemented in terms of a state machine, and hydra requests to the render thread are implemented in terms of transitions on that state machine.

States:

  • StateInitial - indicates the render thread hasn't been started.
  • StateIdle - indicates the render thread is running, but not rendering.
  • StateRendering - indicates the render thread is rendering.
  • StateTerminated - indicates the render thread is shutting down.

Transitions:

Example Usage

class ExampleRenderDelegate : HdRenderDelegate {
public:
ExampleRenderDelegate() {
_renderThread.SetRenderCallback(
std::bind(&ExampleRenderDelegate::_RenderCallback, this));
_renderThread.StartThread();
}
~ExampleRenderDelegate() {
_renderThread.StopThread();
}
private:
void _RenderCallback() {
bool renderComplete = false;
while(!renderComplete) {
// Check if we have been asked to pause.
while(_renderThread.IsPauseRequested()) {
if(_renderThread.IsStopRequested()) {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
if(_renderThread.IsStopRequested()) {
break;
}
// generate N pixels.
auto lock = _renderThread.LockFramebuffer();
// resolve pixels to shared buffer.
// Set renderComplete = true when finished rendering.
}
}
HdRenderThread _renderThread;
};
class ExampleRenderParam : HdRenderParam {
public:
ExampleRenderParam(HdRenderThread* renderThread, SceneData *scene);
SceneData* AcquireSceneForEdit() {
_renderThread->StopRender();
return _scene;
}
};
class ExamplePrim : HdMesh {
public:
void Sync(...) {
SceneData *scene = renderParam->AcquireSceneForEdit();
...
}
};
class ExampleRenderPass : HdRenderPass {
public:
ExampleRenderPass(HdRenderThread *renderThread);
protected:
void _Execute(...) {
_renderThread->StartRendering();
auto lock = _renderThread->LockFramebuffer();
// blit pixels from shared to application buffer.
}
};

Having a locked and shared framebuffer is important if you want to avoid tearing, or if the rendering API disallows multithreaded access to buffers (for example, if your framebuffers are on a GPU). It might be unnecessary for some renderers.

Stopping the render only when you're about to make a scene edit means that long-running renders aren't interrupted if the scene is static. Hiding the renderer's scene data handle behind AcquireSceneForEdit helps callers use the synchronization mechanisms correctly.

The render is restarted at the last possible second, in the render pass, after we know scene edits are done.

The render callback should use IsStopRequested() as a cancellation mechanism.

Definition at line 146 of file renderThread.h.

Constructor & Destructor Documentation

HD_API HdRenderThread::HdRenderThread ( )
HD_API HdRenderThread::~HdRenderThread ( )

Member Function Documentation

HD_API bool HdRenderThread::IsPauseDirty ( )

Query whether the pause/resume state has changed since the last time we called IsPauseDirty.

HD_API bool HdRenderThread::IsPauseRequested ( )

Query whether hydra has asked to pause rendering. This will continue to return true until a request has been made for rendering to resume. Remember to check for a stop request while paused.

HD_API bool HdRenderThread::IsRendering ( )

Query whether the render thread is currently rendering. This is set by StartRender() and reset after the render callback exits, or reset by StopRender() if the render callback never runs. This does not block, and is fully threadsafe.

HD_API bool HdRenderThread::IsStopRequested ( )

Query whether hydra has asked to interrupt the current frame since the last time StartRender() was called. The render callback can check this to determine whether to cancel rendering.

HD_API bool HdRenderThread::IsThreadRunning ( )

Check whether the background thread is running (i.e. StartThread was called successfully, but StopThread has not been).

HD_API std::unique_lock<std::mutex> HdRenderThread::LockFramebuffer ( )

Return a scoped lock on the render delegate's framebuffer. Hydra and the render thread can use this to synchronize blits between render-thread owned resources, and application-owned resources.

HD_API void HdRenderThread::PauseRender ( )

Ask the render thread to pause rendering. The speed at which the renderer actually enters the pause state depends on the delegate.

HD_API void HdRenderThread::ResumeRender ( )

Ask the render thread to resume rendering. Pause and Resume calls do not need to be paired. The last call (to Pause or Resume) decides the current state.

HD_API void HdRenderThread::SetRenderCallback ( std::function< void()>  renderCallback)

Set the rendering callback for the render thread to use.

HD_API void HdRenderThread::SetShutdownCallback ( std::function< void()>  shutdownCallback)

Set the shutdown callback for the render thread to use. This will be called once, right before the render thread exits, regardless of whether the render callback has been called. This can be used to clean up thread-specific rendering resources.

HD_API void HdRenderThread::StartRender ( )

Ask the render thread to start rendering. This call is a no-op if the render thread is already rendering. Otherwise, it may block briefly. This is threadsafe against the render thread, but it shouldn't be called at the same time as StopRender(), and it shouldn't be called from multiple hydra threads at once.

HD_API void HdRenderThread::StartThread ( )

Start the rendering background thread. Note: it's an error to call this function when the render thread is already running, but it's acceptable to stop the render thread and then start it again.

HD_API void HdRenderThread::StopRender ( )

Ask the render thread to stop rendering, and block until the render thread is idle. This is fully threadsafe, and can be called from multiple hydra threads at once.

HD_API void HdRenderThread::StopThread ( )

Stop the rendering background thread. This function will ask the render thread to transition to StateTerminated, and then join on the thread, so it will block. After this function returns, the rendering state machine will be back in its initial state, and the render thread can be started again.


The documentation for this class was generated from the following file: