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