53 #define WINDOWS_LEAN_AND_MEAN 56 #undef WINDOWS_LEAN_AND_MEAN 65 PStatCollector GraphicsEngine::_wait_pcollector(
"Wait:Thread sync");
67 PStatCollector GraphicsEngine::_app_pcollector(
"App:Show code:General");
68 PStatCollector GraphicsEngine::_render_frame_pcollector(
"App:render_frame");
72 PStatCollector GraphicsEngine::_cull_setup_pcollector(
"Cull:Setup");
77 PStatCollector GraphicsEngine::_flip_begin_pcollector(
"Wait:Flip:Begin");
78 PStatCollector GraphicsEngine::_flip_end_pcollector(
"Wait:Flip:End");
79 PStatCollector GraphicsEngine::_transform_states_pcollector(
"TransformStates");
80 PStatCollector GraphicsEngine::_transform_states_unused_pcollector(
"TransformStates:Unused");
81 PStatCollector GraphicsEngine::_render_states_pcollector(
"RenderStates");
82 PStatCollector GraphicsEngine::_render_states_unused_pcollector(
"RenderStates:Unused");
83 PStatCollector GraphicsEngine::_cyclers_pcollector(
"PipelineCyclers");
84 PStatCollector GraphicsEngine::_dirty_cyclers_pcollector(
"Dirty PipelineCyclers");
88 PStatCollector GraphicsEngine::_sw_sprites_pcollector(
"SW Sprites");
89 PStatCollector GraphicsEngine::_vertex_data_small_pcollector(
"Vertex Data:Small");
90 PStatCollector GraphicsEngine::_vertex_data_independent_pcollector(
"Vertex Data:Independent");
91 PStatCollector GraphicsEngine::_vertex_data_pending_pcollector(
"Vertex Data:Pending");
92 PStatCollector GraphicsEngine::_vertex_data_resident_pcollector(
"Vertex Data:Resident");
93 PStatCollector GraphicsEngine::_vertex_data_compressed_pcollector(
"Vertex Data:Compressed");
94 PStatCollector GraphicsEngine::_vertex_data_unused_disk_pcollector(
"Vertex Data:Disk:Unused");
95 PStatCollector GraphicsEngine::_vertex_data_used_disk_pcollector(
"Vertex Data:Disk:Used");
99 PStatCollector GraphicsEngine::_cnode_volume_pcollector(
"Collision Volumes:CollisionNode");
100 PStatCollector GraphicsEngine::_gnode_volume_pcollector(
"Collision Volumes:GeomNode");
101 PStatCollector GraphicsEngine::_geom_volume_pcollector(
"Collision Volumes:Geom");
102 PStatCollector GraphicsEngine::_node_volume_pcollector(
"Collision Volumes:PandaNode");
103 PStatCollector GraphicsEngine::_volume_pcollector(
"Collision Volumes:CollisionSolid");
104 PStatCollector GraphicsEngine::_test_pcollector(
"Collision Tests:CollisionSolid");
105 PStatCollector GraphicsEngine::_volume_polygon_pcollector(
"Collision Volumes:CollisionPolygon");
106 PStatCollector GraphicsEngine::_test_polygon_pcollector(
"Collision Tests:CollisionPolygon");
107 PStatCollector GraphicsEngine::_volume_plane_pcollector(
"Collision Volumes:CollisionPlane");
108 PStatCollector GraphicsEngine::_test_plane_pcollector(
"Collision Tests:CollisionPlane");
109 PStatCollector GraphicsEngine::_volume_sphere_pcollector(
"Collision Volumes:CollisionSphere");
110 PStatCollector GraphicsEngine::_test_sphere_pcollector(
"Collision Tests:CollisionSphere");
111 PStatCollector GraphicsEngine::_volume_box_pcollector(
"Collision Volumes:CollisionBox");
112 PStatCollector GraphicsEngine::_test_box_pcollector(
"Collision Tests:CollisionBox");
113 PStatCollector GraphicsEngine::_volume_capsule_pcollector(
"Collision Volumes:CollisionCapsule");
114 PStatCollector GraphicsEngine::_test_capsule_pcollector(
"Collision Tests:CollisionCapsule");
115 PStatCollector GraphicsEngine::_volume_inv_sphere_pcollector(
"Collision Volumes:CollisionInvSphere");
116 PStatCollector GraphicsEngine::_test_inv_sphere_pcollector(
"Collision Tests:CollisionInvSphere");
117 PStatCollector GraphicsEngine::_volume_geom_pcollector(
"Collision Volumes:CollisionGeom");
118 PStatCollector GraphicsEngine::_test_geom_pcollector(
"Collision Tests:CollisionGeom");
119 PStatCollector GraphicsEngine::_occlusion_untested_pcollector(
"Occlusion results:Not tested");
120 PStatCollector GraphicsEngine::_occlusion_passed_pcollector(
"Occlusion results:Visible");
121 PStatCollector GraphicsEngine::_occlusion_failed_pcollector(
"Occlusion results:Occluded");
122 PStatCollector GraphicsEngine::_occlusion_tests_pcollector(
"Occlusion tests");
131 INLINE
static bool operator < (
const CullKey &a,
const CullKey &b) {
132 if (a._gsg != b._gsg) {
133 return a._gsg < b._gsg;
135 if (a._camera != b._camera) {
136 return a._camera < b._camera;
138 return a._lens_index < b._lens_index;
150 _lock(
"GraphicsEngine::_lock"),
151 _loaded_textures_lock(
"GraphicsEngine::_loaded_textures_lock")
153 if (_pipeline ==
nullptr) {
157 _windows_sorted =
true;
158 _window_sort_index = 0;
163 <<
"Using threading model " << _threading_model <<
"\n";
165 _auto_flip = auto_flip;
166 _portal_enabled =
false;
167 _flip_state = FS_flip;
169 _singular_warning_last_frame =
false;
170 _singular_warning_this_frame =
false;
180 if (_app_pcollector.is_started()) {
181 _app_pcollector.stop();
195 if (!Thread::is_threading_supported()) {
196 if (!threading_model.is_single_threaded()) {
197 display_cat.warning()
198 <<
"Threading model " << threading_model
199 <<
" requested but threading is not available. Ignoring.\n";
204 #ifndef THREADED_PIPELINE 205 if (!threading_model.is_single_threaded()) {
206 display_cat.warning()
207 <<
"Threading model " << threading_model
208 <<
" requested but multithreaded render pipelines not enabled in build.\n";
209 if (!allow_nonpipeline_threads) {
210 display_cat.warning()
211 <<
"Ignoring requested threading model.\n";
214 display_cat.warning()
215 <<
"Danger! Creating requested render threads anyway!\n";
217 #endif // THREADED_PIPELINE 219 _threading_model = threading_model;
227 get_threading_model()
const {
231 result = _threading_model;
254 const string &name,
int sort,
286 int x_size = 0, y_size = 0;
291 if ((x_size == 0)&&(y_size == 0)) {
292 flags |= GraphicsPipe::BF_size_track_host;
294 if (host !=
nullptr) {
302 if (host ==
nullptr) {
303 if (gsg !=
nullptr) {
312 if ((host->
get_gsg()==
nullptr)||
314 (!host->
get_gsg()->is_valid())||
315 (host->
get_gsg()->needs_reset())) {
318 if ((host->
get_gsg()==
nullptr)||
320 (!host->
get_gsg()->is_valid())||
321 (host->
get_gsg()->needs_reset())) {
331 nassertr(pipe !=
nullptr,
nullptr);
332 if (gsg !=
nullptr) {
333 nassertr(pipe == gsg->
get_pipe(),
nullptr);
338 if ((flags & GraphicsPipe::BF_require_callback_window)!=0) {
340 if (this_gsg ==
nullptr) {
343 this_gsg = pipe->make_callback_gsg(
this);
345 if (this_gsg !=
nullptr) {
347 window->_sort = sort;
348 do_add_window(window);
349 do_add_gsg(window->
get_gsg(), pipe);
350 display_cat.info() <<
"Created output of type CallbackGraphicsWindow\n";
361 bool can_use_parasite =
false;
362 if ((host !=
nullptr)&&
363 ((flags&GraphicsPipe::BF_require_window)==0)&&
364 ((flags&GraphicsPipe::BF_require_callback_window)==0)&&
365 ((flags&GraphicsPipe::BF_refuse_parasite)==0)&&
366 ((flags&GraphicsPipe::BF_can_bind_color)==0)&&
367 ((flags&GraphicsPipe::BF_can_bind_every)==0)&&
368 ((flags&GraphicsPipe::BF_rtt_cumulative)==0)&&
369 ((flags&GraphicsPipe::BF_can_bind_layered)==0)) {
370 if ((flags&GraphicsPipe::BF_fb_props_optional) ||
372 can_use_parasite =
true;
381 if ((prefer_parasite_buffer) &&
382 (can_use_parasite) &&
383 (x_size <= host->get_x_size())&&
384 (y_size <= host->get_y_size())&&
387 buffer->_sort = sort;
388 do_add_window(buffer);
389 do_add_gsg(host->
get_gsg(), pipe);
390 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
397 if (force_parasite_buffer && can_use_parasite) {
399 buffer->_sort = sort;
400 do_add_window(buffer);
401 do_add_gsg(host->
get_gsg(), pipe);
402 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
408 for (
int retry=0; retry<10; retry++) {
409 bool precertify =
false;
411 pipe->make_output(name, fb_prop, win_prop, flags,
this, gsg, host, retry, precertify);
412 if (window !=
nullptr) {
413 window->_sort = sort;
414 if (precertify && gsg !=
nullptr && window->
get_gsg() == gsg) {
415 do_add_window(window);
417 <<
"Created output of type " << window->get_type() <<
"\n";
420 do_add_window(window);
422 if (window->is_valid()) {
424 <<
"Created output of type " << window->get_type() <<
"\n";
426 if (window->get_fb_properties().subsumes(fb_prop)) {
429 if (flags & GraphicsPipe::BF_fb_props_optional) {
430 display_cat.warning()
431 <<
"FrameBufferProperties available less than requested.\n";
432 display_cat.warning(
false)
433 <<
" requested: " << fb_prop <<
"\n" 434 <<
" got: " << window->get_fb_properties() <<
"\n";
438 <<
"Could not get requested FrameBufferProperties; abandoning window.\n";
439 display_cat.error(
false)
440 <<
" requested: " << fb_prop <<
"\n" 441 <<
" got: " << window->get_fb_properties() <<
"\n";
445 << window->get_type() <<
" wouldn't open; abandoning.\n";
446 display_cat.debug(
false)
447 <<
" requested: " << fb_prop <<
"\n";
458 if (can_use_parasite) {
460 buffer->_sort = sort;
461 do_add_window(buffer);
462 do_add_gsg(host->
get_gsg(), pipe);
463 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
486 nassertr(window !=
nullptr,
false);
487 nassertr(
this == window->
get_engine(),
false);
489 window->_sort = sort;
490 do_add_window(window);
493 <<
"Added output of type " << window->get_type() <<
"\n";
517 nassertr(window !=
nullptr,
false);
518 Thread *current_thread = Thread::get_current_thread();
525 if (!_windows_sorted) {
528 count = _windows.erase(ptwin);
533 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
534 size_t old_size = _new_windows.size();
535 _new_windows.erase(std::remove(_new_windows.begin(), _new_windows.end(), ptwin), _new_windows.end());
536 if (count == 0 && _new_windows.size() < old_size) {
546 do_remove_window(window, current_thread);
549 if (gsg !=
nullptr) {
551 if (pgo !=
nullptr) {
553 bool any_common =
false;
556 Windows::iterator wi;
557 for (wi = _windows.
begin(); wi != _windows.
end() && !any_common; ++wi) {
559 if (gsg2 !=
nullptr &&
576 nassertr(count == 1,
true);
586 Thread *current_thread = Thread::get_current_thread();
595 old_windows.
swap(_windows);
597 nassertv(win !=
nullptr);
598 do_remove_window(win, current_thread);
600 if (gsg !=
nullptr) {
606 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
608 nassertv(win !=
nullptr);
609 do_remove_window(win, current_thread);
611 if (gsg !=
nullptr) {
615 _new_windows.clear();
618 _app.do_close(
this, current_thread);
619 _app.do_pending(
this, current_thread);
620 terminate_threads(current_thread);
637 PStatClient::get_global_pstats()->disconnect();
651 Windows::iterator wi;
652 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
665 return _windows.
empty();
672 get_num_windows()
const {
673 return _windows.
size();
681 nassertr(n >= 0 && n < (
int)_windows.
size(),
nullptr);
683 if (!_windows_sorted) {
695 Thread *current_thread = Thread::get_current_thread();
705 _render_frame_pcollector.start();
706 if (_app_pcollector.is_started()) {
707 _app_pcollector.stop();
720 if (display_cat.is_spam()) {
722 <<
"render_frame() - frame " << global_clock->
get_frame_count() <<
"\n";
728 if (!_windows_sorted) {
732 if (sync_flip && _flip_state != FS_flip) {
733 do_flip_frame(current_thread);
739 Windows::iterator wi;
740 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
742 nassertv(win !=
nullptr);
744 do_remove_window(win, current_thread);
754 int num_drs = win->get_num_active_display_regions();
755 for (
int i = 0; i < num_drs; ++i) {
762 if (scene.is_empty()) {
763 scene = camera_np.
get_top(current_thread);
765 if (!scene.is_empty()) {
766 scene.get_bounds(current_thread);
773 _windows.
swap(new_windows);
779 LoadedTextures::iterator lti;
780 for (lti = _loaded_textures.begin(); lti != _loaded_textures.end(); ++lti) {
781 LoadedTexture < = (*lti);
782 if (lt._tex->get_image_modified() == lt._image_modified) {
783 lt._tex->texture_uploaded();
786 _loaded_textures.clear();
791 _app.do_frame(
this, current_thread);
796 PStatTimer timer(_wait_pcollector, current_thread);
797 Threads::const_iterator ti;
798 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
799 RenderThread *thread = (*ti).second;
800 thread->_cv_mutex.acquire();
802 while (thread->_thread_state != TS_wait) {
803 thread->_cv_done.wait();
808 #if defined(THREADED_PIPELINE) && defined(DO_PSTATS) 809 _cyclers_pcollector.set_level(_pipeline->get_num_cyclers());
810 _dirty_cyclers_pcollector.set_level(_pipeline->get_num_dirty_cyclers());
814 _pipeline->iterate_all_cycler_types(pstats_count_cycler_type,
this);
815 _pipeline->iterate_dirty_cycler_types(pstats_count_dirty_cycler_type,
this);
817 #endif // DEBUG_THREADS 819 #endif // THREADED_PIPELINE && DO_PSTATS 824 TransformState::flush_level();
828 #ifdef THREADED_PIPELINE 830 PStatTimer timer(_cycle_pcollector, current_thread);
833 #endif // THREADED_PIPELINE 835 global_clock->
tick(current_thread);
837 throw_event(
"clock_error");
841 PStatClient::main_tick();
844 CullTraverser::_nodes_pcollector.clear_level();
845 CullTraverser::_geom_nodes_pcollector.clear_level();
846 CullTraverser::_geoms_pcollector.clear_level();
847 GeomCacheManager::_geom_cache_active_pcollector.clear_level();
848 GeomCacheManager::_geom_cache_record_pcollector.clear_level();
849 GeomCacheManager::_geom_cache_erase_pcollector.clear_level();
850 GeomCacheManager::_geom_cache_evict_pcollector.clear_level();
852 GraphicsStateGuardian::init_frame_pstats();
854 _transform_states_pcollector.set_level(TransformState::get_num_states());
856 if (pstats_unused_states) {
857 _transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states());
861 _sw_sprites_pcollector.clear_level();
863 _cnode_volume_pcollector.clear_level();
864 _gnode_volume_pcollector.clear_level();
865 _geom_volume_pcollector.clear_level();
866 _node_volume_pcollector.clear_level();
867 _volume_pcollector.clear_level();
868 _test_pcollector.clear_level();
869 _volume_polygon_pcollector.clear_level();
870 _test_polygon_pcollector.clear_level();
871 _volume_plane_pcollector.clear_level();
872 _test_plane_pcollector.clear_level();
873 _volume_sphere_pcollector.clear_level();
874 _test_sphere_pcollector.clear_level();
875 _volume_box_pcollector.clear_level();
876 _test_box_pcollector.clear_level();
877 _volume_capsule_pcollector.clear_level();
878 _test_capsule_pcollector.clear_level();
879 _volume_inv_sphere_pcollector.clear_level();
880 _test_inv_sphere_pcollector.clear_level();
881 _volume_geom_pcollector.clear_level();
882 _test_geom_pcollector.clear_level();
883 _occlusion_untested_pcollector.clear_level();
884 _occlusion_passed_pcollector.clear_level();
885 _occlusion_failed_pcollector.clear_level();
886 _occlusion_tests_pcollector.clear_level();
899 _vertex_data_small_pcollector.set_level(small_buf);
900 _vertex_data_independent_pcollector.set_level(independent);
901 _vertex_data_pending_pcollector.set_level(pending);
902 _vertex_data_resident_pcollector.set_level(resident);
903 _vertex_data_compressed_pcollector.set_level(compressed);
904 _vertex_data_unused_disk_pcollector.set_level(total_disk - used_disk);
905 _vertex_data_used_disk_pcollector.set_level(used_disk);
913 Threads::const_iterator ti;
914 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
915 RenderThread *thread = (*ti).second;
916 if (thread->_thread_state == TS_wait) {
917 thread->_thread_state = TS_do_frame;
918 thread->_cv_start.notify();
920 thread->_cv_mutex.release();
925 _flip_state = _auto_flip ? FS_flip : FS_draw;
930 if (yield_timeslice) {
933 PStatTimer timer(_yield_pcollector, current_thread);
935 }
else if (!Thread::is_true_threads()) {
936 PStatTimer timer(_yield_pcollector, current_thread);
942 _app_pcollector.start();
943 _render_frame_pcollector.stop();
956 Thread *current_thread = Thread::get_current_thread();
962 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
963 if (_new_windows.empty()) {
967 for (
auto it = _new_windows.begin(); it != _new_windows.end(); ++it) {
970 WindowRenderer *cull =
973 WindowRenderer *draw =
978 cull->add_window(cull->_cull, window);
979 draw->add_window(draw->_draw, window);
981 cull->add_window(cull->_cdraw, window);
993 switch (window->
get_pipe()->get_preferred_window_thread()) {
994 case GraphicsPipe::PWT_app:
995 _app.add_window(_app._window, window);
998 case GraphicsPipe::PWT_draw:
999 draw->add_window(draw->_window, window);
1007 new_windows.swap(_new_windows);
1010 do_resort_windows();
1013 for (
int i = 0; i < 2; ++i) {
1014 _app.do_windows(
this, current_thread);
1015 _app.do_pending(
this, current_thread);
1017 PStatTimer timer(_wait_pcollector, current_thread);
1018 Threads::const_iterator ti;
1019 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1020 RenderThread *thread = (*ti).second;
1021 thread->_cv_mutex.acquire();
1023 while (thread->_thread_state != TS_wait) {
1024 thread->_cv_done.wait();
1027 thread->_thread_state = TS_do_windows;
1028 thread->_cv_start.notify();
1029 thread->_cv_mutex.release();
1034 for (
auto it = new_windows.begin(); it != new_windows.end(); ++it) {
1052 Thread *current_thread = Thread::get_current_thread();
1055 if (_flip_state == FS_draw) {
1056 do_sync_frame(current_thread);
1073 Thread *current_thread = Thread::get_current_thread();
1076 if (_flip_state == FS_draw) {
1077 do_ready_flip(current_thread);
1088 Thread *current_thread = Thread::get_current_thread();
1091 if (_flip_state != FS_flip) {
1092 do_flip_frame(current_thread);
1122 if (draw_name.empty()) {
1129 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1130 RenderThread *thread = (RenderThread *)wr;
1133 while (thread->_thread_state != TS_wait) {
1134 thread->_cv_done.wait();
1138 int pipeline_stage = Thread::get_current_pipeline_stage();
1139 int draw_pipeline_stage = thread->get_pipeline_stage();
1140 thread->set_pipeline_stage(pipeline_stage);
1144 thread->_texture = tex;
1145 thread->_thread_state = TS_do_extract;
1146 thread->_cv_start.notify();
1147 thread->_cv_mutex.release();
1148 thread->_cv_mutex.acquire();
1151 while (thread->_thread_state != TS_wait) {
1152 thread->_cv_done.wait();
1155 thread->set_pipeline_stage(draw_pipeline_stage);
1156 thread->_gsg =
nullptr;
1157 thread->_texture =
nullptr;
1158 return thread->_result;
1177 const Shader *shader = sattr->get_shader();
1178 nassertv(shader !=
nullptr);
1179 nassertv(gsg !=
nullptr);
1183 CPT(
RenderState) state = RenderState::make(sattr);
1186 if (draw_name.empty()) {
1191 gsg->pop_group_marker();
1196 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1197 RenderThread *thread = (RenderThread *)wr;
1200 while (thread->_thread_state != TS_wait) {
1201 thread->_cv_done.wait();
1205 int pipeline_stage = Thread::get_current_pipeline_stage();
1206 int draw_pipeline_stage = thread->get_pipeline_stage();
1207 thread->set_pipeline_stage(pipeline_stage);
1211 thread->_state = state.p();
1212 thread->_work_groups = work_groups;
1213 thread->_thread_state = TS_do_compute;
1214 thread->_cv_start.notify();
1215 thread->_cv_mutex.release();
1216 thread->_cv_mutex.acquire();
1219 while (thread->_thread_state != TS_wait) {
1220 thread->_cv_done.wait();
1223 thread->set_pipeline_stage(draw_pipeline_stage);
1224 thread->_gsg =
nullptr;
1225 thread->_state =
nullptr;
1234 if (_global_ptr ==
nullptr) {
1255 _loaded_textures.push_back(LoadedTexture());
1256 LoadedTexture < = _loaded_textures.back();
1273 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1274 RenderThread *thread = (RenderThread *)wr;
1277 while (thread->_thread_state != TS_wait) {
1278 thread->_cv_done.wait();
1282 thread->_region = region;
1283 thread->_thread_state = TS_do_screenshot;
1284 thread->_cv_start.notify();
1285 thread->_cv_mutex.release();
1286 thread->_cv_mutex.acquire();
1289 while (thread->_thread_state != TS_wait) {
1290 thread->_cv_done.wait();
1293 PT(
Texture) tex = std::move(thread->_texture);
1294 thread->_region =
nullptr;
1295 thread->_texture =
nullptr;
1309 trav->set_cull_handler(cull_handler);
1312 trav->set_view_frustum(
nullptr);
1313 if (view_frustum_cull) {
1321 if (bv !=
nullptr && !bv->is_infinite() &&
1322 bv->as_geometric_bounding_volume() !=
nullptr) {
1325 local_frustum = bv->make_copy()->as_geometric_bounding_volume();
1326 nassertv(!local_frustum.is_null());
1331 local_frustum->xform(cull_center_transform->get_mat());
1333 trav->set_view_frustum(local_frustum);
1338 trav->end_traverse();
1346 bool GraphicsEngine::
1347 scene_root_func(
const PandaNode *node) {
1348 return _global_ptr->is_scene_root(node);
1355 bool GraphicsEngine::
1359 Windows::const_iterator wi;
1360 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
1363 int num_display_regions = win->get_num_active_display_regions();
1364 for (
int i = 0; i < num_display_regions; i++) {
1366 if (dr !=
nullptr) {
1373 DCAST_INTO_R(camera_node, camera.
node(),
false);
1383 scene_root = camera.
get_top(current_thread);
1386 if (scene_root.
node() == node) {
1403 void GraphicsEngine::
1406 window->_sort = sort;
1407 _windows_sorted =
false;
1416 void GraphicsEngine::
1418 Thread *current_thread) {
1419 PStatTimer timer(_cull_pcollector, current_thread);
1421 size_t wlist_size = wlist.
size();
1422 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1427 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1431 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1436 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1440 gsg->push_group_marker(
"Clear");
1441 win->
clear(current_thread);
1442 gsg->pop_group_marker();
1445 int num_display_regions = win->get_num_active_display_regions();
1446 for (
int i = 0; i < num_display_regions; i++) {
1448 if (dr !=
nullptr) {
1449 cull_and_draw_together(win, dr, current_thread);
1452 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1457 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1461 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1474 void GraphicsEngine::
1476 Thread *current_thread) {
1478 nassertv(gsg !=
nullptr);
1489 if (dr_reader.is_any_clear_active()) {
1494 scene_setup = setup_scene(gsg, &dr_reader);
1497 if (scene_setup ==
nullptr) {
1503 }
else if (!gsg->
set_scene(scene_setup)) {
1506 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
1512 if (cbobj !=
nullptr) {
1521 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1528 gsg->pop_group_marker();
1536 void GraphicsEngine::
1538 PStatTimer timer(_cull_pcollector, current_thread);
1540 _singular_warning_last_frame = _singular_warning_this_frame;
1541 _singular_warning_this_frame =
false;
1546 AlreadyCulled already_culled;
1548 size_t wlist_size = wlist.
size();
1549 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1554 int num_display_regions = win->get_num_active_display_regions();
1555 for (
int i = 0; i < num_display_regions; ++i) {
1557 if (dr !=
nullptr) {
1562 PStatTimer timer(_cull_setup_pcollector, current_thread);
1564 scene_setup = setup_scene(gsg, &dr_reader);
1565 if (scene_setup ==
nullptr) {
1570 key._camera = dr_reader.get_camera();
1571 key._lens_index = dr_reader.get_lens_index();
1574 AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(std::move(key),
nullptr)).first;
1575 if ((*aci).second ==
nullptr) {
1579 if (cull_result !=
nullptr) {
1580 cull_result = cull_result->make_next();
1586 cull_to_bins(win, gsg, dr, scene_setup, cull_result, current_thread);
1600 dr->
set_cull_result(std::move(cull_result), MOVE(scene_setup), current_thread);
1610 void GraphicsEngine::
1617 if (cbobj !=
nullptr) {
1626 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1629 PStatTimer timer(_cull_sort_pcollector, current_thread);
1630 cull_result->
finish_cull(scene_setup, current_thread);
1638 void GraphicsEngine::
1642 size_t wlist_size = wlist.
size();
1643 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1654 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1658 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1663 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1670 win->
get_gsg()->push_group_marker(
"Clear");
1671 win->
clear(current_thread);
1672 win->
get_gsg()->pop_group_marker();
1675 if (display_cat.is_spam()) {
1677 <<
"Drawing window " << win->
get_name() <<
"\n";
1679 int num_display_regions = win->get_num_active_display_regions();
1680 for (
int i = 0; i < num_display_regions; ++i) {
1682 if (dr !=
nullptr) {
1683 do_draw(win, gsg, dr, current_thread);
1687 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1693 gsg->issue_timer_query(GraphicsStateGuardian::_command_latency_pcollector.get_index());
1701 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1705 PStatGPUTimer timer(gsg, GraphicsEngine::_flip_end_pcollector, current_thread);
1712 if (display_cat.is_spam()) {
1714 <<
"Not drawing window " << win->
get_name() <<
"\n";
1719 if (display_cat.is_spam()) {
1721 <<
"Window " << win->
get_name() <<
" is inactive\n";
1731 void GraphicsEngine::
1733 Windows::const_iterator wi;
1734 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1736 if (win->
begin_frame(GraphicsOutput::FM_refresh, current_thread)) {
1737 win->
end_frame(GraphicsOutput::FM_refresh, current_thread);
1747 void GraphicsEngine::
1752 for (
size_t i = 0; i < wlist.
size(); ++i) {
1753 wlist[i]->process_events();
1762 void GraphicsEngine::
1764 size_t num_windows = wlist.
size();
1766 size_t warray_count = 0;
1770 for (i = 0; i < num_windows; ++i) {
1773 nassertv(warray_count < num_windows);
1774 warray[warray_count] = win;
1777 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1782 for (i = 0; i < warray_count; ++i) {
1784 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1794 void GraphicsEngine::
1796 Windows::const_iterator wi;
1797 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1800 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1810 void GraphicsEngine::
1811 do_sync_frame(
Thread *current_thread) {
1815 PStatTimer timer(_sync_pcollector, current_thread);
1817 nassertv(_flip_state == FS_draw);
1821 Threads::const_iterator ti;
1822 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1823 RenderThread *thread = (*ti).second;
1824 thread->_cv_mutex.acquire();
1825 thread->_cv_mutex.release();
1828 _flip_state = FS_sync;
1835 void GraphicsEngine::
1836 do_ready_flip(
Thread *current_thread) {
1840 PStatTimer timer(_sync_pcollector, current_thread);
1842 nassertv(_flip_state == FS_draw);
1846 Threads::const_iterator ti;
1847 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1848 RenderThread *thread = (*ti).second;
1849 thread->_cv_mutex.acquire();
1850 thread->_cv_mutex.release();
1852 _app.do_ready_flip(
this,current_thread);
1853 _flip_state = FS_sync;
1860 void GraphicsEngine::
1861 do_flip_frame(
Thread *current_thread) {
1865 PStatTimer timer(_flip_pcollector, current_thread);
1867 nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
1873 PStatTimer timer(_wait_pcollector, current_thread);
1874 Threads::const_iterator ti;
1875 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1876 RenderThread *thread = (*ti).second;
1877 thread->_cv_mutex.acquire();
1879 while (thread->_thread_state != TS_wait) {
1880 thread->_cv_done.wait();
1886 _app.do_flip(
this, current_thread);
1889 Threads::const_iterator ti;
1890 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1891 RenderThread *thread = (*ti).second;
1892 nassertv(thread->_thread_state == TS_wait);
1893 thread->_thread_state = TS_do_flip;
1894 thread->_cv_start.notify();
1895 thread->_cv_mutex.release();
1899 _flip_state = FS_flip;
1909 Thread *current_thread = dr->get_current_thread();
1910 PStatTimer timer(_cull_setup_pcollector, current_thread);
1915 nassertr(window !=
nullptr,
nullptr);
1924 DCAST_INTO_R(camera_node, camera.
node(),
nullptr);
1944 scene_root = camera.
get_top(current_thread);
1960 if (camera_transform->is_invalid()) {
1962 if (!_singular_warning_last_frame) {
1963 display_cat.warning()
1964 <<
"Scene " << scene_root <<
" has net scale (" 1966 _singular_warning_this_frame =
true;
1971 if (world_transform->is_invalid()) {
1973 if (!_singular_warning_last_frame) {
1974 display_cat.warning()
1975 <<
"Camera " << camera <<
" has net scale (" 1978 _singular_warning_this_frame =
true;
1982 CPT(
RenderState) initial_state = camera_node->get_initial_state();
1992 initial_state = initial_state->compose(get_invert_polygon_state());
2001 scene_setup->set_initial_state(initial_state);
2008 CPT(
TransformState) cs_world_transform = cs_transform->compose(world_transform);
2017 void GraphicsEngine::
2028 cull_result = cdata->_cull_result;
2029 scene_setup = cdata->_scene_setup;
2038 if (dr_reader.is_any_clear_active()) {
2040 gsg->
clear(dr_reader.get_object());
2043 cbobj = dr_reader.get_draw_callback();
2046 if (cbobj !=
nullptr) {
2051 static CPT(
RenderState) state = RenderState::make(
2052 DepthTestAttrib::make(DepthTestAttrib::M_none));
2062 }
else if (cull_result ==
nullptr || scene_setup ==
nullptr) {
2072 }
else if (!gsg->
set_scene(scene_setup)) {
2075 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
2079 cull_result->
draw(current_thread);
2084 gsg->pop_group_marker();
2092 void GraphicsEngine::
2094 nassertv(window !=
nullptr);
2101 window->_internal_sort_index = _window_sort_index;
2102 ++_window_sort_index;
2104 if (display_cat.is_debug()) {
2106 <<
"Created " << window->get_type() <<
" " << (
void *)window <<
"\n";
2110 _new_windows.push_back(window);
2118 void GraphicsEngine::
2120 nassertv(gsg !=
nullptr);
2124 gsg->_threading_model = _threading_model;
2125 if (!_default_loader.is_null()) {
2129 auto_adjust_capabilities(gsg);
2131 WindowRenderer *draw =
2143 void GraphicsEngine::
2145 nassertv(window !=
nullptr);
2149 if (!_windows_sorted) {
2150 do_resort_windows();
2154 _app.remove_window(window);
2155 Threads::const_iterator ti;
2156 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2157 RenderThread *thread = (*ti).second;
2158 thread->remove_window(window);
2163 _app.do_pending(
this, current_thread);
2165 if (display_cat.is_debug()) {
2167 <<
"Removed " << window->get_type() <<
" " << (
void *)window <<
"\n";
2175 void GraphicsEngine::
2176 do_resort_windows() {
2177 _windows_sorted =
true;
2179 _app.resort_windows();
2180 Threads::const_iterator ti;
2181 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2182 RenderThread *thread = (*ti).second;
2183 thread->resort_windows();
2209 void GraphicsEngine::
2231 if (textures_auto_power_2 && (textures_power_2 == ATS_none)) {
2233 <<
"Invalid panda config file: if you set the config-variable\n" 2234 <<
"textures_auto_power_2 to true, you must set the config-variable" 2235 <<
"textures_power_2 to 'up' or 'down'.\n";
2236 textures_power_2 = ATS_down;
2253 <<
"The 'textures_power_2' configuration is set to 'none', meaning \n" 2254 <<
"that non-power-of-two texture support is required, but the video \n" 2255 <<
"driver I'm trying to use does not support non-power-of-two textures.\n";
2257 if (textures_power_2 != ATS_none) {
2259 <<
"The 'none' did not come from the config file. In other words,\n" 2260 <<
"the variable 'textures_power_2' was altered procedurally.\n";
2262 if (textures_auto_power_2) {
2264 <<
"It is possible that it was set by panda's automatic mechanisms,\n" 2265 <<
"which are currently enabled, because 'textures_auto_power_2' is\n" 2266 <<
"true. Panda's automatic mechanisms assume that if one\n" 2267 <<
"window supports non-power-of-two textures, then they all will.\n" 2268 <<
"This assumption works for most games, but not all.\n" 2269 <<
"In particular, it can fail if the game creates multiple windows\n" 2270 <<
"on multiple displays with different video cards.\n";
2279 void GraphicsEngine::
2280 terminate_threads(
Thread *current_thread) {
2285 PStatTimer timer(_wait_pcollector, current_thread);
2289 Threads::const_iterator ti;
2290 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2291 RenderThread *thread = (*ti).second;
2292 thread->_cv_mutex.acquire();
2296 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2297 RenderThread *thread = (*ti).second;
2298 thread->_thread_state = TS_terminate;
2299 thread->_cv_start.notify();
2300 thread->_cv_mutex.release();
2304 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2305 RenderThread *thread = (*ti).second;
2318 void GraphicsEngine::
2319 pstats_count_cycler_type(
TypeHandle type,
int count,
void *data) {
2321 CyclerTypeCounters::iterator ci =
self->_all_cycler_types.find(type);
2322 if (ci == self->_all_cycler_types.end()) {
2324 ci =
self->_all_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2326 (*ci).second.set_level(count);
2335 void GraphicsEngine::
2336 pstats_count_dirty_cycler_type(
TypeHandle type,
int count,
void *data) {
2338 CyclerTypeCounters::iterator ci =
self->_dirty_cycler_types.find(type);
2339 if (ci == self->_dirty_cycler_types.end()) {
2341 ci =
self->_dirty_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2343 (*ci).second.set_level(count);
2353 get_invert_polygon_state() {
2357 if (state ==
nullptr) {
2358 state = RenderState::make(CullFaceAttrib::make_reverse());
2372 GraphicsEngine::WindowRenderer *GraphicsEngine::
2373 get_window_renderer(
const string &name,
int pipeline_stage) {
2380 Threads::iterator ti = _threads.find(name);
2381 if (ti != _threads.end()) {
2382 return (*ti).second.p();
2385 PT(RenderThread) thread =
new RenderThread(name,
this);
2386 thread->set_min_pipeline_stage(pipeline_stage);
2389 bool started = thread->start(TP_normal,
true);
2390 nassertr(started, thread.p());
2391 _threads[name] = thread;
2393 nassertr(thread->get_pipeline_stage() < _pipeline->
get_num_stages(), thread.p());
2401 GraphicsEngine::WindowRenderer::
2402 WindowRenderer(
const string &name) :
2403 _wl_lock(string(
"GraphicsEngine::WindowRenderer::_wl_lock ") + name)
2410 void GraphicsEngine::WindowRenderer::
2420 void GraphicsEngine::WindowRenderer::
2423 wlist.insert(window);
2431 void GraphicsEngine::WindowRenderer::
2433 nassertv(window !=
nullptr);
2438 _cdraw.erase(ptwin);
2441 Windows::iterator wi;
2443 wi = _window.find(ptwin);
2444 if (wi != _window.end()) {
2454 if (ptwin->is_valid()) {
2455 _pending_close.push_back(ptwin);
2465 void GraphicsEngine::WindowRenderer::
2474 if (display_cat.is_debug()) {
2476 <<
"Windows resorted:";
2477 Windows::const_iterator wi;
2478 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2480 display_cat.debug(
false)
2483 display_cat.debug(
false)
2486 for (wi = _draw.begin(); wi != _draw.end(); ++wi) {
2488 display_cat.debug(
false)
2491 display_cat.debug(
false)
2501 void GraphicsEngine::WindowRenderer::
2503 PStatTimer timer(engine->_do_frame_pcollector, current_thread);
2506 engine->cull_to_bins(_cull, current_thread);
2507 engine->cull_and_draw_together(_cdraw, current_thread);
2508 engine->draw_bins(_draw, current_thread);
2509 engine->process_events(_window, current_thread);
2513 if (any_done_gsgs()) {
2516 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2521 engine->close_gsg(pipe, gsg);
2524 new_gsgs.insert(gsg);
2528 _gsgs.swap(new_gsgs);
2538 void GraphicsEngine::WindowRenderer::
2542 engine->process_events(_window, current_thread);
2544 engine->make_contexts(_cdraw, current_thread);
2545 engine->make_contexts(_draw, current_thread);
2551 void GraphicsEngine::WindowRenderer::
2554 engine->flip_windows(_cdraw, current_thread);
2555 engine->flip_windows(_draw, current_thread);
2561 void GraphicsEngine::WindowRenderer::
2564 engine->ready_flip_windows(_cdraw, current_thread);
2565 engine->ready_flip_windows(_draw, current_thread);
2572 void GraphicsEngine::WindowRenderer::
2575 Windows::iterator wi;
2576 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2584 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2589 engine->close_gsg(pipe, gsg);
2592 new_gsgs.insert(gsg);
2596 _gsgs.swap(new_gsgs);
2603 void GraphicsEngine::WindowRenderer::
2607 if (!_pending_close.empty()) {
2608 if (display_cat.is_debug()) {
2610 <<
"_pending_close.size() = " << _pending_close.size() <<
"\n";
2616 Windows::iterator wi;
2617 Windows pending_close;
2618 _pending_close.swap(pending_close);
2619 for (wi = pending_close.begin(); wi != pending_close.end(); ++wi) {
2631 bool GraphicsEngine::WindowRenderer::
2632 any_done_gsgs()
const {
2633 GSGs::const_iterator gi;
2634 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2635 if ((*gi)->get_ref_count() == 1) {
2646 GraphicsEngine::RenderThread::
2649 WindowRenderer(name),
2651 _cv_mutex(string(
"GraphicsEngine::RenderThread ") + name),
2652 _cv_start(_cv_mutex),
2655 _thread_state = TS_wait;
2662 void GraphicsEngine::RenderThread::
2668 nassertv(_cv_mutex.debug_is_locked());
2670 switch (_thread_state) {
2675 do_pending(_engine, current_thread);
2676 do_frame(_engine, current_thread);
2680 do_flip(_engine, current_thread);
2684 do_pending(_engine, current_thread);
2688 do_windows(_engine, current_thread);
2689 do_pending(_engine, current_thread);
2693 nassertd(_gsg !=
nullptr && _state !=
nullptr) break;
2696 _state->get_attrib(sattr);
2697 _gsg->push_group_marker(std::string(
"Compute ") + sattr->get_shader()->get_filename(Shader::ST_compute).get_basename());
2698 _gsg->set_state_and_transform(_state, TransformState::make_identity());
2699 _gsg->dispatch_compute(_work_groups[0], _work_groups[1], _work_groups[2]);
2700 _gsg->pop_group_marker();
2705 nassertd(_gsg !=
nullptr && _texture !=
nullptr) break;
2706 _result = _gsg->extract_texture_data(_texture);
2709 case TS_do_screenshot:
2710 nassertd(_region !=
nullptr) break;
2711 _texture = _region->get_screenshot();
2715 do_pending(_engine, current_thread);
2716 do_close(_engine, current_thread);
2717 _thread_state = TS_done;
2727 _thread_state = TS_wait;
2731 PStatTimer timer(_wait_pcollector, current_thread);
size_t get_total_size() const
Returns the total size of all objects currently active on the LRU.
set_scene
Sets the SceneSetup object that indicates the initial camera position, etc.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void flush_global_index()
If there is a global BamCache object, calls flush_index() on it.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
void set_camera_node(Camera *camera_node)
Specifies the camera used to render the scene.
void tick(Thread *current_thread=Thread::get_current_thread())
Instructs the clock that a new frame has just begun.
int cleanup_aux_scene_data(Thread *current_thread=Thread::get_current_thread())
Walks through the list of currently-assigned AuxSceneData objects and releases any that are past thei...
virtual void request_close()
This is called by the GraphicsEngine to request that the window (or whatever) close itself or,...
A basic node of the scene graph or data graph.
get_ref_count
Returns the current reference count.
static void set_textures_power_2(AutoTextureScale scale)
Set this flag to ATS_none, ATS_up, ATS_down, or ATS_pad to control the scaling of textures in general...
void set_cull_result(PT(CullResult) cull_result, PT(SceneSetup) scene_setup, Thread *current_thread)
Stores the result of performing a cull operation on this DisplayRegion.
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
A temporary file to hold the vertex data that has been evicted from memory and written to disk.
static SimpleLru * get_small_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that are deemed too...
static void flush_level()
Flushes the PStatCollectors used during traversal.
This is our own Panda specialization on the default STL map.
static int get_num_states()
Returns the total number of unique RenderState objects allocated in the world.
virtual GraphicsOutput * get_host()
This is normally called only from within make_texture_buffer().
void set_display_region(DisplayRegion *display_region)
Specifies the display region for the scene.
static void flush_level()
Flushes the PStatCollectors used during traversal.
get_pipe
Returns the graphics pipe on which this GSG was created.
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_cull_traverser
Returns the CullTraverser that will be used to draw the contents of this DisplayRegion.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_empty() const
Returns true if there are no windows or buffers managed by the engine, false if there is at least one...
void flip_frame()
Waits for all the threads that started drawing their last frame to finish drawing,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
A base class for any number of different kinds of lenses, linear and otherwise.
get_supports_tex_non_pow2
Returns true if this GSG can handle non power of two sized textures.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_gsg
Returns the nth GSG in the universe.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
bool is_empty() const
Returns true if the NodePath contains no nodes.
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
void change_scenes(DisplayRegionPipelineReader *new_dr)
Called by the GraphicsEngine when the window is about to change to another DisplayRegion.
is_active
Returns true if the window is ready to be rendered into, false otherwise.
size_type_0 size() const
Returns the number of elements in the ordered vector.
void set_cs_world_transform(const TransformState *cs_world_transform)
Specifies the position from the starting node relative to the camera, in the GSG's internal coordinat...
void set_world_transform(const TransformState *world_transform)
Specifies the position of the starting node relative to the camera.
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, GraphicsStateGuardian *gsg, Thread *current_thread)
Fires off a cull traversal using the indicated camera.
get_sort
Returns the sorting order of this particular GraphicsOutput.
static void consider_flush_global_index()
If there is a global BamCache object, calls consider_flush_index() on it.
bool verify_list() const
Maps to verify_list_unique().
void release_all()
Releases all prepared objects.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_window
Returns the nth window or buffers managed by the engine, in sorted order.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void dispatch_compute(int size_x, int size_y, int size_z)
Dispatches a currently bound compute shader using the given work group counts.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
void dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, GraphicsStateGuardian *gsg)
Asks the indicated GraphicsStateGuardian to dispatch the compute shader in the given ShaderAttrib usi...
void set_cs_transform(const TransformState *cs_transform)
Specifies the transform from the camera's coordinate system to the GSG's internal coordinate system.
bool is_default() const
Returns true if the threading model is the default, cull-then-draw single- threaded model,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsEngine(Pipeline *pipeline=nullptr)
Creates a new GraphicsEngine object.
static void prepare_for_exit()
Should be called by the main thread just before exiting the program, this blocks until any remaining ...
void open_windows()
Fully opens (or closes) any windows that have recently been requested open or closed,...
bool get_cull_sorting() const
Returns true if the model involves a separate cull pass, or false if culling happens implicitly,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename get_filename(ShaderType type=ST_none) const
Return the Shader's filename for the given shader type.
void set_lens(const Lens *lens)
Indicates the particular Lens used for rendering.
get_parent
Returns the NodePath to the parent of the referenced node: that is, this NodePath,...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void finish_cull(SceneSetup *scene_setup, Thread *current_thread)
Called after all the geoms have been added, this indicates that the cull process is finished for this...
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
set_loader
Sets the Loader object that will be used by this GSG to load textures when necessary,...
static void flush_level()
Flushes the PStatCollectors used during traversal.
static SimpleLru * get_global_lru(RamClass rclass)
Returns a pointer to the global LRU object that manages the VertexDataPage's with the indicated RamCl...
bool remove_window(GraphicsOutput *window)
Removes the indicated window or offscreen buffer from the set of windows that will be processed when ...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
void reserve(size_type_0 n)
Informs the vector of a planned change in size; ensures that the capacity of the vector is greater th...
A table of objects that are saved within the graphics context for reference by handle later.
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame.
static void lru_epoch()
Marks that an epoch has passed in each LRU.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(Texture) GraphicsEngine
Called by DisplayRegion::do_get_screenshot.
PStatCollector & get_clear_window_pcollector()
Returns a PStatCollector for timing the clear operation for just this GraphicsOutput.
This specialization on CallbackData is passed when the callback is initiated from the cull traversal,...
size_t get_total_file_size() const
Returns the amount of space consumed by the save file, including unused portions.
is_active
Returns the current setting of the active flag on the camera.
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
get_name
Returns the name of the type.
get_engine
Returns the graphics engine that created this output.
void ready_flip()
Waits for all the threads that started drawing their last frame to finish drawing.
void texture_uploaded(Texture *tex)
This method is called by the GraphicsStateGuardian after a texture has been successfully uploaded to ...
GraphicsOutput * make_output(GraphicsPipe *pipe, const std::string &name, int sort, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg=nullptr, GraphicsOutput *host=nullptr)
Creates a new window (or buffer) and returns it.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
void swap(ordered_vector< Key, Compare, Vector > &other)
Exchanges the contents of this vector and the other vector, in constant time (e.g....
This is a special type of PStatTimer that also uses a timer query on the GSG to measure how long a ta...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
PStatCollector & get_cull_region_pcollector()
Returns a PStatCollector for timing the cull operation for just this DisplayRegion.
NodePath get_camera() const
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
Lens * get_lens(int index=0) const
Returns a pointer to the particular Lens associated with this LensNode, or NULL if there is not yet a...
This is our own Panda specialization on the default STL vector.
void reset_all_windows(bool swapchain)
Resets the framebuffer of the current window.
PStatCollector & get_draw_window_pcollector()
Returns a PStatCollector for timing the draw operation for just this GraphicsOutput.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
~GraphicsEngine()
Gracefully cleans up the graphics engine and its related threads and windows.
get_cull_callback
Returns the CallbackObject set by set_cull_callback().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_used_file_size() const
Returns the amount of space within the save file that is currently in use.
A lightweight class that represents a single element that may be timed and/or counted via stats.
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general.
virtual void do_callback(CallbackData *cbdata)
This method called when the callback is triggered; it *replaces* the original function.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
virtual void set_close_now()
This is called by the GraphicsEngine to insist that the output be closed immediately.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void cycle()
Flows all the pipeline data down to the next stage.
get_current_thread
Returns a pointer to the currently-executing Thread object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
CullResult * get_cull_result(Thread *current_thread) const
Returns the CullResult value that was stored on this DisplayRegion, presumably by the last successful...
virtual void clear_pipe()
Sets the window's _pipe pointer to NULL; this is generally called only as a precursor to deleting the...
virtual void request_open()
This is called by the GraphicsEngine to request that the window (or whatever) open itself or,...
This special window object doesn't represent a window in its own right, but instead hooks into some t...
virtual void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
bool get_delete_flag() const
Returns the current setting of the delete flag.
void stop_threads()
Stops any threads that are currently running.
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
int get_pixel_width(int i=0) const
Returns the width of the DisplayRegion in pixels.
This is a special GraphicsOutput type that acts a lot like a GraphicsBuffer, effectively allowing ren...
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
virtual void clear_state_and_transform()
Forgets the current graphics state and current transform, so that the next call to set_state_and_tran...
bool debug_is_locked() const
Returns true if the current thread has locked the ReMutex, false otherwise.
int get_cull_stage() const
Returns the pipeline stage from which the cull thread should access data.
const std::string & get_cull_name() const
Returns the name of the thread that will handle culling in this model.
void set_camera_path(const NodePath &camera_path)
Specifies the NodePath to the camera.
void sync_frame()
Waits for all the threads that started drawing their last frame to finish drawing.
is_valid
Returns true if the GSG has been correctly initialized within a graphics context, false if there has ...
const NodePath & get_scene_root() const
Returns the root node of the scene.
get_pipe
Returns the GraphicsPipe that this window is associated with.
A ClockObject keeps track of elapsed real time and discrete time.
static int get_num_unused_states()
Returns the total number of RenderState objects that have been allocated but have no references outsi...
bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg)
Asks the indicated GraphicsStateGuardian to retrieve the texture memory image of the indicated textur...
static SimpleLru * get_pending_lru()
Returns a pointer to the global LRU object that manages the VertexDataPage's that are pending process...
An object to create GraphicsOutputs that share a particular 3-D API.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PStatCollector & get_draw_region_pcollector()
Returns a PStatCollector for timing the draw operation for just this DisplayRegion.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void sort()
Maps to sort_unique().
get_scene
Returns the scene that will be rendered by the camera.
This CullHandler sends all of the geoms it receives into a CullResult object, for binning (and later ...
void set_camera_transform(const TransformState *camera_transform)
Specifies the position of the camera relative to the starting node.
get_timer_queries_active
Returns true if timer queries are currently enabled on this GSG.
set_threading_model
Specifies how future objects created via make_gsg(), make_buffer(), and make_window() will be threade...
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool add_window(GraphicsOutput *window, int sort)
This can be used to add a newly-created GraphicsOutput object (and its GSG) to the engine's list of w...
get_incomplete_render
Returns the incomplete_render flag.
This specialization on CallbackData is passed when the callback is initiated from the draw traversal,...
Similar to MutexHolder, but for a reentrant mutex.
static Pipeline * get_render_pipeline()
Returns a pointer to the global render pipeline.
static void set_scene_root_func(SceneRootFunc *func)
This is used by the GraphicsEngine to hook in a pointer to the scene_root_func(), the function to det...
int get_draw_stage() const
Returns the pipeline stage from which the draw thread should access data.
bool get_lens_active(int index) const
Returns the active flag for the nth lens.
This is a base class for the various different classes that represent the result of a frame of render...
Similar to MutexHolder, but for a light reentrant mutex.
This represents the user's specification of how a particular frame is handled by the various threads.
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
void set_scene_root(const NodePath &scene_root)
Specifies the root node of the scene.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_basename() const
Returns the basename part of the filename.
virtual void reset_window(bool swapchain)
Resets the window framebuffer from its derived children.
const std::string & get_draw_name() const
Returns the name of the thread that will handle sending the actual graphics primitives to the graphic...
get_inverted
Returns the current setting of the inverted flag.
void remove_all_windows()
Removes and closes all windows from the engine.
void set_inverted(bool inverted)
Changes the current setting of the inverted flag.
This is a generic object that can be assigned to a callback at various points in the rendering proces...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void ready_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
void render_frame()
Renders the next frame in all the registered windows, and flips all of the frame buffers.
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
static void stop_threads()
Call this to stop the paging threads, if they were started.
void set_viewport_size(int width, int height)
Specifies the size of the viewport (display region), in pixels.
static SimpleLru * get_independent_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that have not (yet)...
virtual bool is_any_clear_active() const
Returns true if any of the clear types (so far there are just color or depth) have been set active,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This special kind of CullHandler immediately draws its contents as soon as it receives them.
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed.
get_name
Returns the name that was passed to the GraphicsOutput constructor.
PandaNode * node() const
Returns the referenced node of the path.
int get_num_stages() const
Returns the number of stages required for the pipeline.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void begin_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
Encapsulates all the communication with a particular instance of a given rendering backend.
static void flush_level()
Flushes the PStatCollectors used during traversal.
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath get_top(Thread *current_thread=Thread::get_current_thread()) const
Returns a singleton NodePath that represents the top of the path, or empty NodePath if this path is e...
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise.
const std::string & get_debug_name() const
Returns a unique name used for debugging.
get_image_modified
Returns a sequence number which is guaranteed to change at least every time the texture image data (i...
A rectangular subregion within a window for rendering into.
bool needs_reset() const
Returns true if the gsg is marked as needing a reset.
int get_pixel_height(int i=0) const
Returns the height of the DisplayRegion in pixels.
void draw(Thread *current_thread)
Asks all the bins to draw themselves in the correct order.
get_prepared_objects
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
virtual bool flip_ready() const
Returns true if a frame has been rendered and needs to be flipped, false otherwise.
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
This class is the main interface to controlling the render process.
PStatCollector & get_cull_window_pcollector()
Returns a PStatCollector for timing the cull operation for just this GraphicsOutput.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
DisplayRegion * get_display_region() const
Returns the display region for the scene.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool check_errors(Thread *current_thread)
Returns true if a clock error was detected since the last time check_errors() was called.
TypeHandle is the identifier used to differentiate C++ class types.
static bool has_textures_power_2()
If true, then get_textures_power_2 has been set using set_textures_power_2.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
This object holds the camera position, etc., and other general setup information for rendering a part...
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
int get_lens_index() const
Gets the index into a lens_node lens array.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_gsg
Returns the GSG that is associated with this window.
has_size
Returns true if the window size has been specified, false otherwise.
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame.
virtual bool extract_texture_data(Texture *tex)
This method should only be called by the GraphicsEngine.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
void set_min_stages(int min_stages)
Ensures that at least the indicated number of stages are in the pipeline.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const GraphicsThreadingModel & get_threading_model() const
Returns the threading model that was used to create this GSG.
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
void release_all()
Releases all prepared objects of all kinds at once.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.