Panda3D
graphicsEngine.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file graphicsEngine.h
10  * @author drose
11  * @date 2002-02-24
12  */
13 
14 #ifndef GRAPHICSENGINE_H
15 #define GRAPHICSENGINE_H
16 
17 #include "pandabase.h"
18 #include "graphicsWindow.h"
19 #include "graphicsBuffer.h"
20 #include "frameBufferProperties.h"
21 #include "graphicsThreadingModel.h"
22 #include "sceneSetup.h"
23 #include "pointerTo.h"
24 #include "thread.h"
25 #include "pmutex.h"
26 #include "reMutex.h"
27 #include "lightReMutex.h"
28 #include "conditionVar.h"
29 #include "pStatCollector.h"
30 #include "pset.h"
31 #include "ordered_vector.h"
32 #include "indirectLess.h"
33 #include "loader.h"
34 #include "referenceCount.h"
35 
36 class Pipeline;
37 class DisplayRegion;
38 class GraphicsPipe;
40 class Texture;
41 
42 /**
43  * This class is the main interface to controlling the render process. There
44  * is typically only one GraphicsEngine in an application, and it synchronizes
45  * rendering to all all of the active windows; although it is possible to have
46  * multiple GraphicsEngine objects if multiple synchronicity groups are
47  * required.
48  *
49  * The GraphicsEngine is responsible for managing the various cull and draw
50  * threads. The application simply calls engine->render_frame() and considers
51  * it done.
52  */
53 class EXPCL_PANDA_DISPLAY GraphicsEngine : public ReferenceCount {
54 PUBLISHED:
55  explicit GraphicsEngine(Pipeline *pipeline = nullptr);
56  BLOCKING ~GraphicsEngine();
57 
58  void set_threading_model(const GraphicsThreadingModel &threading_model);
59  GraphicsThreadingModel get_threading_model() const;
60  MAKE_PROPERTY(threading_model, get_threading_model, set_threading_model);
61 
62  INLINE const ReMutex &get_render_lock() const;
63  MAKE_PROPERTY(render_lock, get_render_lock);
64 
65  INLINE void set_auto_flip(bool auto_flip);
66  INLINE bool get_auto_flip() const;
67  MAKE_PROPERTY(auto_flip, get_auto_flip, set_auto_flip);
68 
69  INLINE void set_portal_cull(bool value);
70  INLINE bool get_portal_cull() const;
71  MAKE_PROPERTY(portal_cull, get_portal_cull, set_portal_cull);
72 
73  INLINE void set_default_loader(Loader *loader);
74  INLINE Loader *get_default_loader() const;
75  MAKE_PROPERTY(default_loader, get_default_loader, set_default_loader);
76 
77  GraphicsOutput *make_output(GraphicsPipe *pipe,
78  const std::string &name, int sort,
79  const FrameBufferProperties &fb_prop,
80  const WindowProperties &win_prop,
81  int flags, GraphicsStateGuardian *gsg = nullptr,
82  GraphicsOutput *host = nullptr);
83 
84  // Syntactic shorthand versions of make_output
85  INLINE GraphicsOutput *make_buffer(GraphicsOutput *host,
86  const std::string &name, int sort,
87  int x_size, int y_size);
88  INLINE GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg,
89  const std::string &name, int sort,
90  int x_size, int y_size);
91  INLINE GraphicsOutput *make_parasite(GraphicsOutput *host,
92  const std::string &name, int sort,
93  int x_size, int y_size);
94 
95  bool add_window(GraphicsOutput *window, int sort);
96  bool remove_window(GraphicsOutput *window);
97  BLOCKING void remove_all_windows();
98  void reset_all_windows(bool swapchain);
99 
100  bool is_empty() const;
101  int get_num_windows() const;
102  GraphicsOutput *get_window(int n) const;
103  MAKE_SEQ(get_windows, get_num_windows, get_window);
104  MAKE_SEQ_PROPERTY(windows, get_num_windows, get_window);
105 
106  BLOCKING void render_frame();
107  BLOCKING void open_windows();
108  BLOCKING void sync_frame();
109  BLOCKING void ready_flip();
110  BLOCKING void flip_frame();
111 
112  bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg);
113  void dispatch_compute(const LVecBase3i &work_groups,
114  const ShaderAttrib *sattr,
115  GraphicsStateGuardian *gsg);
116 
117  static GraphicsEngine *get_global_ptr();
118 
119 public:
120  enum ThreadState {
121  TS_wait,
122  TS_do_frame,
123  TS_do_flip,
124  TS_do_release,
125  TS_do_windows,
126  TS_do_compute,
127  TS_do_extract,
128  TS_do_screenshot,
129  TS_terminate,
130  TS_done
131  };
132 
133  void texture_uploaded(Texture *tex);
134  PT(Texture) do_get_screenshot(DisplayRegion *region, GraphicsStateGuardian *gsg);
135 
136 public:
137  static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
138  GraphicsStateGuardian *gsg, Thread *current_thread);
139 
140 private:
141  typedef ov_set< PT(GraphicsOutput), IndirectLess<GraphicsOutput> > Windows;
142  typedef pset< PT(GraphicsStateGuardian) > GSGs;
143 
144  static bool scene_root_func(const PandaNode *node);
145  bool is_scene_root(const PandaNode *node);
146 
147  void set_window_sort(GraphicsOutput *window, int sort);
148 
149  void cull_and_draw_together(Windows wlist, Thread *current_thread);
150  void cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
151  Thread *current_thread);
152 
153  void cull_to_bins(Windows wlist, Thread *current_thread);
154  void cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
155  DisplayRegion *dr, SceneSetup *scene_setup,
156  CullResult *cull_result, Thread *current_thread);
157  void draw_bins(const Windows &wlist, Thread *current_thread);
158  void make_contexts(const Windows &wlist, Thread *current_thread);
159 
160  void process_events(const Windows &wlist, Thread *current_thread);
161  void ready_flip_windows(const Windows &wlist, Thread *current_thread);
162  void flip_windows(const Windows &wlist, Thread *current_thread);
163  void do_sync_frame(Thread *current_thread);
164  void do_ready_flip(Thread *current_thread);
165  void do_flip_frame(Thread *current_thread);
166  INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
167 
168  PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg,
170  void do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg,
171  DisplayRegion *dr, Thread *current_thread);
172 
173  void do_add_window(GraphicsOutput *window);
174  void do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe);
175  void do_remove_window(GraphicsOutput *window, Thread *current_thread);
176  void do_resort_windows();
177  void terminate_threads(Thread *current_thread);
178  void auto_adjust_capabilities(GraphicsStateGuardian *gsg);
179 
180 #ifdef DO_PSTATS
181  typedef std::map<TypeHandle, PStatCollector> CyclerTypeCounters;
182  CyclerTypeCounters _all_cycler_types;
183  CyclerTypeCounters _dirty_cycler_types;
184  static void pstats_count_cycler_type(TypeHandle type, int count, void *data);
185  static void pstats_count_dirty_cycler_type(TypeHandle type, int count, void *data);
186 #endif // DO_PSTATS
187 
188  static const RenderState *get_invert_polygon_state();
189 
190  // The WindowRenderer class records the stages of the pipeline that each
191  // thread (including the main thread, a.k.a. "app") should process, and the
192  // list of windows for each stage.
193 
194  // There is one WindowRenderer instance for app, and another instance for
195  // each thread (the thread-specific WindowRenderers are actually instances
196  // of RenderThread, below, which inherits from WindowRenderer).
197 
198  // The idea is that each window is associated with one or more
199  // WindowRenderer objects, according to the threads in which its rendering
200  // tasks (window, cull, and draw) are divided into.
201 
202  // The "window" task is responsible for doing any updates to the window
203  // itself, such as size and placement, and is wholly responsible for any API
204  // calls to the windowing system itself, unrelated to OpenGL-type calls.
205  // This is normally done in app (the design of X-Windows is such that all X
206  // calls must be issued in the same thread).
207 
208  // The "cull" task is responsible for crawling through the scene graph and
209  // discovering all of the Geoms that are within the viewing frustum. It
210  // assembles all such Geoms, along with their computed net state and
211  // transform, in a linked list of CullableObjects, which it stores for the
212  // "draw" task, next.
213 
214  // The "draw" task is responsible for walking through the list of
215  // CullableObjects recorded by the cull task, and issuing the appropriate
216  // graphics commands to draw them.
217 
218  // There is an additional task, not often used, called "cdraw". This task,
219  // if activated, will crawl through the scene graph and issue graphics
220  // commands immediately, as each Geom is discovered. It is only rarely used
221  // because it cannot perform sorting beyond basic scene graph order, making
222  // it less useful than a separate cull and draw task.
223 
224  // It is possible for all three of the normal tasks: window, cull, and draw,
225  // to be handled by the same thread. This is the normal, single-threaded
226  // model: all tasks are handled by the app thread. In this case, the window
227  // will be added to _app's _window, _cull, and _draw lists.
228 
229 /*
230  * On the other hand, a window's tasks may also be distributed among as many
231  * as three threads. For instance, if the window is listed on _app's _window
232  * list, but on thread A's _cull list, and thread B's _draw list, then the
233  * window task will be handled in the app thread, while the cull task will be
234  * handled by thread A, and the draw task will be handled (in parallel) by
235  * thread B. (In order for this to work, it will be necessary that thread A
236  * and B are configured to view different stages of the graphics pipeline.
237  * This is a more advanced topic than there is room to discuss in this
238  * comment.)
239  */
240 
241  // Manipulation of the various window lists in each WindowRenderer object is
242  // always performed in the app thread. The auxiliary threads are slaves to
243  // the app thread, and they can only perform one of a handful of specified
244  // tasks, none of which includes adding or removing windows from its lists.
245  // The full set of tasks that a WindowRenderer may perform is enumerated in
246  // ThreadState, above; see RenderThread::thread_main().
247 
248 /*
249  * There is a pair of condition variables for each thread, _cv_start and
250  * _cv_done, that is used to synchronize requests made by app to a particular
251  * thread. The usual procedure to request a thread to perform a particular
252  * task is the following: the app thread waits on the thread's _cv_done
253  * variable, stores the value corresponding to the desired task in the
254  * thread's _thread_state value, then signals the thread's _cv_start variable.
255  * The thread, in turn, will perform its requested task, set its _thread_state
256  * to TS_wait, and signal _cv_done. See examples in the code, e.g.
257  * open_windows(), for more details on this process.
258  */
259 
260  // It is of course not necessary to signal any threads in order to perform
261  // tasks listed in the _app WindowRenderer. For this object only, we simply
262  // call the appropriate methods on _app when we want the tasks to be
263  // performed.
264 
265  class WindowRenderer {
266  public:
267  WindowRenderer(const std::string &name);
268 
269  void add_gsg(GraphicsStateGuardian *gsg);
270  void add_window(Windows &wlist, GraphicsOutput *window);
271  void remove_window(GraphicsOutput *window);
272  void resort_windows();
273  void do_frame(GraphicsEngine *engine, Thread *current_thread);
274  void do_windows(GraphicsEngine *engine, Thread *current_thread);
275  void do_ready_flip(GraphicsEngine *engine, Thread *current_thread);
276  void do_flip(GraphicsEngine *engine, Thread *current_thread);
277  void do_release(GraphicsEngine *engine, Thread *current_thread);
278  void do_close(GraphicsEngine *engine, Thread *current_thread);
279  void do_pending(GraphicsEngine *engine, Thread *current_thread);
280  bool any_done_gsgs() const;
281 
282  public:
283  Windows _cull; // cull stage
284  Windows _cdraw; // cull-and-draw-together stage
285  Windows _draw; // draw stage
286  Windows _window; // window stage, i.e. process windowing events
287 
288  // These are not kept sorted.
289  Windows _pending_close; // moved from _window, pending close.
290 
291  GSGs _gsgs; // draw stage
292 
293  LightReMutex _wl_lock;
294  };
295 
296  class RenderThread : public Thread, public WindowRenderer {
297  public:
298  RenderThread(const std::string &name, GraphicsEngine *engine);
299  virtual void thread_main();
300 
301  GraphicsEngine *_engine;
302  Mutex _cv_mutex;
303  ConditionVar _cv_start;
304  ConditionVar _cv_done;
305  ThreadState _thread_state;
306 
307  // These are stored for extract_texture_data and dispatch_compute.
308  GraphicsStateGuardian *_gsg;
309  PT(Texture) _texture;
310  const RenderState *_state;
311  DisplayRegion *_region;
312  LVecBase3i _work_groups;
313  bool _result;
314  };
315 
316  WindowRenderer *get_window_renderer(const std::string &name, int pipeline_stage);
317 
318  Pipeline *_pipeline;
319  Windows _windows;
320  bool _windows_sorted;
321 
322  // This lock protects the next two fields.
323  Mutex _new_windows_lock;
324  unsigned int _window_sort_index;
325  pvector<PT(GraphicsOutput)> _new_windows;
326 
327  WindowRenderer _app;
328  typedef pmap<std::string, PT(RenderThread) > Threads;
329  Threads _threads;
330  GraphicsThreadingModel _threading_model;
331  bool _auto_flip;
332  bool _portal_enabled; //toggle to portal culling on/off
333  PT(Loader) _default_loader;
334 
335  enum FlipState {
336  FS_draw, // Still drawing.
337  FS_sync, // All windows are done drawing.
338  FS_flip, // All windows are done drawing and have flipped.
339  };
340  FlipState _flip_state;
341 
342  bool _singular_warning_last_frame;
343  bool _singular_warning_this_frame;
344 
345  ReMutex _lock;
346  ReMutex _public_lock;
347 
348  class LoadedTexture {
349  public:
350  PT(Texture) _tex;
351  UpdateSeq _image_modified;
352  };
353  typedef pvector<LoadedTexture> LoadedTextures;
354  LoadedTextures _loaded_textures;
355  Mutex _loaded_textures_lock;
356 
357  static PT(GraphicsEngine) _global_ptr;
358 
359  static PStatCollector _wait_pcollector;
360  static PStatCollector _cycle_pcollector;
361  static PStatCollector _app_pcollector;
362  static PStatCollector _render_frame_pcollector;
363  static PStatCollector _do_frame_pcollector;
364  static PStatCollector _yield_pcollector;
365  static PStatCollector _cull_pcollector;
366  static PStatCollector _cull_setup_pcollector;
367  static PStatCollector _cull_sort_pcollector;
368  static PStatCollector _draw_pcollector;
369  static PStatCollector _sync_pcollector;
370  static PStatCollector _flip_pcollector;
371  static PStatCollector _flip_begin_pcollector;
372  static PStatCollector _flip_end_pcollector;
373  static PStatCollector _transform_states_pcollector;
374  static PStatCollector _transform_states_unused_pcollector;
375  static PStatCollector _render_states_pcollector;
376  static PStatCollector _render_states_unused_pcollector;
377  static PStatCollector _cyclers_pcollector;
378  static PStatCollector _dirty_cyclers_pcollector;
379  static PStatCollector _delete_pcollector;
380 
381  static PStatCollector _sw_sprites_pcollector;
382  static PStatCollector _vertex_data_small_pcollector;
383  static PStatCollector _vertex_data_independent_pcollector;
384  static PStatCollector _vertex_data_pending_pcollector;
385  static PStatCollector _vertex_data_resident_pcollector;
386  static PStatCollector _vertex_data_compressed_pcollector;
387  static PStatCollector _vertex_data_used_disk_pcollector;
388  static PStatCollector _vertex_data_unused_disk_pcollector;
389 
390  static PStatCollector _cnode_volume_pcollector;
391  static PStatCollector _gnode_volume_pcollector;
392  static PStatCollector _geom_volume_pcollector;
393  static PStatCollector _node_volume_pcollector;
394  static PStatCollector _volume_pcollector;
395  static PStatCollector _test_pcollector;
396  static PStatCollector _volume_polygon_pcollector;
397  static PStatCollector _test_polygon_pcollector;
398  static PStatCollector _volume_plane_pcollector;
399  static PStatCollector _test_plane_pcollector;
400  static PStatCollector _volume_sphere_pcollector;
401  static PStatCollector _test_sphere_pcollector;
402  static PStatCollector _volume_box_pcollector;
403  static PStatCollector _test_box_pcollector;
404  static PStatCollector _volume_capsule_pcollector;
405  static PStatCollector _test_capsule_pcollector;
406  static PStatCollector _volume_inv_sphere_pcollector;
407  static PStatCollector _test_inv_sphere_pcollector;
408  static PStatCollector _volume_geom_pcollector;
409  static PStatCollector _test_geom_pcollector;
410 
411  static PStatCollector _occlusion_untested_pcollector;
412  static PStatCollector _occlusion_passed_pcollector;
413  static PStatCollector _occlusion_failed_pcollector;
414  static PStatCollector _occlusion_tests_pcollector;
415 
416  friend class WindowRenderer;
417  friend class GraphicsOutput;
418 };
419 
420 #include "graphicsEngine.I"
421 
422 #endif
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
Definition: loader.h:42
A lightweight reentrant mutex.
Definition: lightReMutex.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A standard mutex, or mutual exclusion lock.
Definition: pmutex.h:38
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A specialization of ordered_vector that emulates a standard STL set: one copy of each element is allo...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
A condition variable, usually used to communicate information about changing state to a thread that i...
Definition: conditionVar.h:41
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
Definition: cullHandler.h:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a base class for the various different classes that represent the result of a frame of render...
This represents the user's specification of how a particular frame is handled by the various threads.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
Definition: pipeline.h:38
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
Definition: cullResult.h:44
A base class for all things that want to be reference-counted.
A thread; that is, a lightweight process.
Definition: thread.h:46
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Encapsulates all the communication with a particular instance of a given rendering backend.
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:57
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
This class is the main interface to controlling the render process.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
A reentrant mutex.
Definition: reMutex.h:32