All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
renderThread.h
1 //
2 // Copyright 2018 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef HD_RENDER_THREAD_H
25 #define HD_RENDER_THREAD_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/imaging/hd/api.h"
29 
30 #include <atomic>
31 #include <condition_variable>
32 #include <functional>
33 #include <mutex>
34 #include <thread>
35 
36 PXR_NAMESPACE_OPEN_SCOPE
37 
38 
147 public:
148 
149  HD_API
150  HdRenderThread();
151 
152  HD_API
153  ~HdRenderThread();
154 
162 
164  HD_API
165  void SetRenderCallback(std::function<void()> renderCallback);
166 
171  HD_API
172  void SetShutdownCallback(std::function<void()> shutdownCallback);
173 
178  HD_API
179  void StartThread();
180 
186  HD_API
187  void StopThread();
188 
191  HD_API
192  bool IsThreadRunning();
193 
195 
203 
209  HD_API
210  void StartRender();
211 
215  HD_API
216  void StopRender();
217 
222  HD_API
223  bool IsRendering();
224 
227  HD_API
228  void PauseRender();
229 
233  HD_API
234  void ResumeRender();
235 
237 
245 
249  HD_API
250  bool IsStopRequested();
251 
255  HD_API
256  bool IsPauseRequested();
257 
260  HD_API
261  bool IsPauseDirty();
262 
264 
272 
276  HD_API
277  std::unique_lock<std::mutex> LockFramebuffer();
278 
280 
281 private:
282  // _RenderLoop implements the render thread's state machine; see
283  // \ref HdRenderThread_StateMachine for details. It runs in a background
284  // thread and manages synchronization with hydra. To implement rendering,
285  // it calls out to the render callback provided via SetRenderCallback.
286  void _RenderLoop();
287 
288  // _renderCallback is the render-delegate-provided function responsible for
289  // actually rendering. It's called from _RenderLoop.
290  std::function<void()> _renderCallback;
291 
292  // _shutdownCallback is the render-delegate-provided function responsible
293  // for cleaning up thread-specific resources. It's called once, right
294  // before _RenderLoop exits.
295  std::function<void()> _shutdownCallback;
296 
297  // A placeholder initial value for _renderCallback.
298  static void _DefaultRenderCallback();
299 
300  // A placeholder initial value for _shutdownCallback.
301  static void _DefaultShutdownCallback();
302 
303  // The state enumeration of the render thread state machine; see
304  // \ref HdRenderThread_StateMachine for details.
305  enum State {
306  // Initial constructed state. Render thread is not running.
307  StateInitial,
308  // Render thread is running and ready for scene edits. No rendering
309  // is taking place.
310  StateIdle,
311  // Render thread is running and rendering; no scene edits are allowed.
312  StateRendering,
313  // Render thread is shutting down.
314  StateTerminated,
315  };
316 
317  // _requestedState is set by hydra to direct the render thread's state
318  // machine; see \ref HdRenderThread_StateMachine for details.
319  // _requestedState is protected by a mutex/condition variable combination.
320  // The render thread holds _requestedStateMutex while rendering; the
321  // frequency with which it can give it up is the interruption frequency.
322  //
323  // StartRender() and StopRender() lock and write to _requestedState.
324  // _RenderLoop() locks and reads _requestedState.
325  State _requestedState;
326  std::mutex _requestedStateMutex;
327  std::condition_variable _requestedStateCV;
328 
329  // _enableRender provides an out-of-band way for hydra to cancel a
330  // render while the render thread is still holding _requestedStateMutex.
331  //
332  // StartRender() and StopRender() will write true/false to _enableRender.
333  // IsStopRequested() will read from _enableRender.
334  std::atomic_flag _enableRender;
335  // _stopRequested keeps track of whether _enableRender has gone low since
336  // the last time the render callback was called (since _enableRender is
337  // reset on read).
338  bool _stopRequested;
339 
340  // _pauseRender provides a properly locked boolean flag that holds the
341  // current pause state of the thread. Toggled by calling PauseRender and
342  // ResumeRender, tested by IsPauseRequested.
343  std::atomic<bool> _pauseRender;
344 
345  // _pauseDirty provides a properly locked boolean flag that holds the
346  // current dirtyness of the pause state of the thread. Toggled by
347  // calling PauseRender and ResumeRender, tested by IsPauseDirty.
348  std::atomic<bool> _pauseDirty;
349 
350  // _rendering records whether the render thread is currently inside the
351  // render callback, or planning to be inside the render callback.
352  // It is managed by StartRender(), StopRender(), and _RenderLoop().
353  // IsRendering() will read from _rendering.
354  std::atomic<bool> _rendering;
355 
356  // _renderThread is the background render thread; it runs _RenderLoop().
357  std::thread _renderThread;
358 
359  // _frameBufferMutex protects access to the render delegate's framebuffer,
360  // and provides an optional synchronization point for blits between the
361  // render thread's resources and the application's resources.
362  std::mutex _frameBufferMutex;
363 };
364 
365 
366 PXR_NAMESPACE_CLOSE_SCOPE
367 
368 #endif // HD_RENDER_THREAD_H
HD_API std::unique_lock< std::mutex > LockFramebuffer()
Return a scoped lock on the render delegate&#39;s framebuffer.
HD_API bool IsThreadRunning()
Check whether the background thread is running (i.e.
HD_API void SetRenderCallback(std::function< void()> renderCallback)
Set the rendering callback for the render thread to use.
HD_API void StartThread()
Start the rendering background thread.
HD_API void StartRender()
Ask the render thread to start rendering.
HD_API bool IsPauseDirty()
Query whether the pause/resume state has changed since the last time we called IsPauseDirty.
HD_API bool IsStopRequested()
Query whether hydra has asked to interrupt the current frame since the last time StartRender() was ca...
HD_API void StopThread()
Stop the rendering background thread.
HD_API void ResumeRender()
Ask the render thread to resume rendering.
HD_API void PauseRender()
Ask the render thread to pause rendering.
HD_API void SetShutdownCallback(std::function< void()> shutdownCallback)
Set the shutdown callback for the render thread to use.
HD_API bool IsRendering()
Query whether the render thread is currently rendering.
HD_API bool IsPauseRequested()
Query whether hydra has asked to pause rendering.
HD_API void StopRender()
Ask the render thread to stop rendering, and block until the render thread is idle.
HdRenderThread is a utility that specific render delegates can choose to use depending on their needs...
Definition: renderThread.h:146