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;
39 class FrameBufferProperties;
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,
169 DisplayRegionPipelineReader *dr);
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
ConditionVar
A condition variable, usually used to communicate information about changing state to a thread that i...
Definition: conditionVar.h:43
CullHandler
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
Definition: cullHandler.h:28
CullResult
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
Definition: cullResult.h:44
DisplayRegionPipelineReader
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
Definition: displayRegion.h:311
DisplayRegion
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:57
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
GraphicsThreadingModel
This represents the user's specification of how a particular frame is handled by the various threads.
Definition: graphicsThreadingModel.h:23
IndirectLess
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
Definition: indirectLess.h:25
LightReMutex
A lightweight reentrant mutex.
Definition: lightReMutex.h:32
Loader
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
Mutex
A standard mutex, or mutual exclusion lock.
Definition: pmutex.h:40
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
Pipeline
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
Definition: pipeline.h:38
ReMutex
A reentrant mutex.
Definition: reMutex.h:34
ReferenceCount
A base class for all things that want to be reference-counted.
Definition: referenceCount.h:38
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
SceneSetup
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
ShaderAttrib
Definition: shaderAttrib.h:39
Texture
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
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
UpdateSeq
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
WindowProperties
A container for the various kinds of properties we might ask to have on a graphics window before we o...
Definition: windowProperties.h:29
ov_set
A specialization of ordered_vector that emulates a standard STL set: one copy of each element is allo...
Definition: ordered_vector.h:269
pmap
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
pset
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
conditionVar.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
frameBufferProperties.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
graphicsBuffer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
graphicsEngine.I
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
graphicsThreadingModel.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
graphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
indirectLess.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightReMutex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
loader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ordered_vector.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatCollector.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pandabase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pmutex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pointerTo.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pset.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
reMutex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
referenceCount.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
sceneSetup.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
thread.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.