From 83a6c42496c3e5d005774db16c42fec6a06dcb27 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 16 Mar 2006 21:26:56 +0000 Subject: [PATCH] better pstats tracking of texture/vbuffer memory --- panda/src/display/graphicsStateGuardian.cxx | 138 +-------------- panda/src/display/graphicsStateGuardian.h | 35 ---- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 56 +++---- panda/src/dxgsg8/dxIndexBufferContext8.cxx | 4 +- panda/src/dxgsg8/dxIndexBufferContext8.h | 2 +- panda/src/dxgsg8/dxTextureContext8.cxx | 119 +++++++------ panda/src/dxgsg8/dxTextureContext8.h | 2 +- panda/src/dxgsg8/dxVertexBufferContext8.cxx | 4 +- panda/src/dxgsg8/dxVertexBufferContext8.h | 2 +- panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 55 +++--- panda/src/dxgsg9/dxIndexBufferContext9.cxx | 4 +- panda/src/dxgsg9/dxIndexBufferContext9.h | 2 +- panda/src/dxgsg9/dxTextureContext9.cxx | 123 +++++++------- panda/src/dxgsg9/dxTextureContext9.h | 2 +- panda/src/dxgsg9/dxVertexBufferContext9.cxx | 4 +- panda/src/dxgsg9/dxVertexBufferContext9.h | 2 +- panda/src/express/pipelineCyclerLinks.I | 8 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 89 +++++++--- .../src/glstuff/glGraphicsStateGuardian_src.h | 1 + panda/src/glstuff/glIndexBufferContext_src.I | 4 +- panda/src/glstuff/glIndexBufferContext_src.h | 3 +- panda/src/glstuff/glTextureContext_src.I | 5 +- panda/src/glstuff/glTextureContext_src.cxx | 17 -- panda/src/glstuff/glTextureContext_src.h | 6 +- panda/src/glstuff/glVertexBufferContext_src.I | 4 +- panda/src/glstuff/glVertexBufferContext_src.h | 3 +- panda/src/gobj/Sources.pp | 9 + panda/src/gobj/bufferContext.I | 158 ++++++++++++++++++ panda/src/gobj/bufferContext.cxx | 36 ++++ panda/src/gobj/bufferContext.h | 97 +++++++++++ panda/src/gobj/bufferContextChain.I | 73 ++++++++ panda/src/gobj/bufferContextChain.cxx | 62 +++++++ panda/src/gobj/bufferContextChain.h | 61 +++++++ panda/src/gobj/bufferResidencyTracker.I | 58 +++++++ panda/src/gobj/bufferResidencyTracker.cxx | 92 ++++++++++ panda/src/gobj/bufferResidencyTracker.h | 92 ++++++++++ panda/src/gobj/config_gobj.cxx | 2 + panda/src/gobj/gobj_composite1.cxx | 4 +- panda/src/gobj/indexBufferContext.I | 43 ++--- panda/src/gobj/indexBufferContext.h | 16 +- panda/src/gobj/preparedGraphicsObjects.I | 12 ++ panda/src/gobj/preparedGraphicsObjects.cxx | 80 +++++---- panda/src/gobj/preparedGraphicsObjects.h | 19 ++- panda/src/gobj/texture.I | 12 ++ panda/src/gobj/texture.cxx | 73 ++------ panda/src/gobj/texture.h | 22 +-- panda/src/gobj/textureContext.I | 93 ++++------- panda/src/gobj/textureContext.h | 29 ++-- panda/src/gobj/vertexBufferContext.I | 43 ++--- panda/src/gobj/vertexBufferContext.h | 17 +- panda/src/pstatclient/pStatProperties.cxx | 16 +- panda/src/putil/Sources.pp | 3 + panda/src/putil/linkedListNode.I | 108 ++++++++++++ panda/src/putil/linkedListNode.cxx | 19 +++ panda/src/putil/linkedListNode.h | 50 ++++++ panda/src/putil/putil_composite1.cxx | 1 + 56 files changed, 1370 insertions(+), 724 deletions(-) create mode 100644 panda/src/gobj/bufferContext.I create mode 100644 panda/src/gobj/bufferContext.cxx create mode 100644 panda/src/gobj/bufferContext.h create mode 100644 panda/src/gobj/bufferContextChain.I create mode 100755 panda/src/gobj/bufferContextChain.cxx create mode 100755 panda/src/gobj/bufferContextChain.h create mode 100644 panda/src/gobj/bufferResidencyTracker.I create mode 100644 panda/src/gobj/bufferResidencyTracker.cxx create mode 100644 panda/src/gobj/bufferResidencyTracker.h create mode 100644 panda/src/putil/linkedListNode.I create mode 100644 panda/src/putil/linkedListNode.cxx create mode 100644 panda/src/putil/linkedListNode.h diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 8989d61ff2..5931a3e680 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -39,10 +39,6 @@ #include #include -PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage"); -PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active"); -PStatCollector GraphicsStateGuardian::_texture_count_pcollector("Prepared Textures"); -PStatCollector GraphicsStateGuardian::_active_texture_count_pcollector("Prepared Textures:Active"); PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex"); PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index"); PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer"); @@ -51,15 +47,6 @@ PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Tra PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer"); PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture"); PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred"); -PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms"); -PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active"); -PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex buffer size"); -PStatCollector GraphicsStateGuardian::_active_vertex_buffers_pcollector("Vertex buffer size:Active vertex"); -PStatCollector GraphicsStateGuardian::_active_index_buffers_pcollector("Vertex buffer size:Active index"); -PStatCollector GraphicsStateGuardian::_total_geom_node_pcollector("Prepared GeomNodes"); -PStatCollector GraphicsStateGuardian::_active_geom_node_pcollector("Prepared GeomNodes:Active"); -PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory"); -PStatCollector GraphicsStateGuardian::_used_texmem_pcollector("Texture memory:In use"); PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager"); PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident"); PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector("Primitive batches"); @@ -964,11 +951,7 @@ prepare_lens() { //////////////////////////////////////////////////////////////////// bool GraphicsStateGuardian:: begin_frame() { - // Now we know the GSG is the currently active context, so this is a - // good time to release any textures or geoms that had been queued - // up to release in the past frame, and load up any newly requested - // textures. - _prepared_objects->update(this); + _prepared_objects->begin_frame(this); #ifdef DO_PSTATS // For Pstats to track our current texture memory usage, we have to @@ -1005,6 +988,7 @@ begin_frame() { //////////////////////////////////////////////////////////////////// bool GraphicsStateGuardian:: begin_scene() { + _prepared_objects->end_frame(); return true; } @@ -1879,7 +1863,6 @@ determine_light_color_scale() { } #ifdef DO_PSTATS - //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::init_frame_pstats // Access: Protected @@ -1889,16 +1872,7 @@ determine_light_color_scale() { void GraphicsStateGuardian:: init_frame_pstats() { if (PStatClient::is_connected()) { - _current_textures.clear(); - _current_geoms.clear(); - _current_vertex_buffers.clear(); - _current_index_buffers.clear(); - _active_texusage_pcollector.clear_level(); _data_transferred_pcollector.clear_level(); - _active_geom_pcollector.clear_level(); - _active_geom_node_pcollector.clear_level(); - _active_vertex_buffers_pcollector.clear_level(); - _active_index_buffers_pcollector.clear_level(); _vertex_buffer_switch_pcollector.clear_level(); _index_buffer_switch_pcollector.clear_level(); @@ -1918,114 +1892,6 @@ init_frame_pstats() { _texture_state_pcollector.clear_level(); } } - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::add_to_texture_record -// Access: Protected -// Description: Records that the indicated texture has been applied -// this frame, and thus must be present in current -// texture memory. This function is only used to update -// the PStats current_texmem collector; it gets compiled -// out if we aren't using PStats. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -add_to_texture_record(TextureContext *tc) { - if (PStatClient::is_connected()) { - if (_current_textures.insert(tc).second) { - _active_texusage_pcollector.add_level(tc->estimate_texture_memory()); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::add_to_geom_record -// Access: Protected -// Description: Records that the indicated Geom has been drawn this -// frame. This function is only used to update the -// PStats active_geom collector; it gets compiled out -// if we aren't using PStats. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -add_to_geom_record(GeomContext *gc) { - if (PStatClient::is_connected()) { - if (gc != (GeomContext *)NULL && _current_geoms.insert(gc).second) { - _active_geom_pcollector.add_level(1); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::add_to_vertex_buffer_record -// Access: Protected -// Description: Records that the indicated data array has been drawn -// this frame. This function is only used to update the -// PStats active_vertex_buffers collector; it gets -// compiled out if we aren't using PStats. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -add_to_vertex_buffer_record(VertexBufferContext *vbc) { - if (vbc != (VertexBufferContext *)NULL) { - if (PStatClient::is_connected()) { - _vertex_buffer_switch_pcollector.add_level(1); - if (_current_vertex_buffers.insert(vbc).second) { - _active_vertex_buffers_pcollector.add_level(vbc->get_data()->get_data_size_bytes()); - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::add_to_index_buffer_record -// Access: Protected -// Description: Records that the indicated data array has been drawn -// this frame. This function is only used to update the -// PStats active_index_buffers collector; it gets compiled out -// if we aren't using PStats. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -add_to_index_buffer_record(IndexBufferContext *ibc) { - if (ibc != (IndexBufferContext *)NULL) { - if (PStatClient::is_connected()) { - _index_buffer_switch_pcollector.add_level(1); - if (_current_index_buffers.insert(ibc).second) { - _active_index_buffers_pcollector.add_level(ibc->get_data()->get_data_size_bytes()); - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::add_to_total_buffer_record -// Access: Protected -// Description: Records that the indicated data array has been loaded -// this frame. This function is only used to update the -// PStats total_buffers collector; it gets -// compiled out if we aren't using PStats. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -add_to_total_buffer_record(VertexBufferContext *vbc) { - if (vbc != (VertexBufferContext *)NULL) { - int delta = vbc->get_data()->get_data_size_bytes() - vbc->get_data_size_bytes(); - _total_buffers_pcollector.add_level(delta); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::add_to_total_buffer_record -// Access: Protected -// Description: Records that the indicated data array has been loaded -// this frame. This function is only used to update the -// PStats total_buffers collector; it gets -// compiled out if we aren't using PStats. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -add_to_total_buffer_record(IndexBufferContext *ibc) { - if (ibc != (IndexBufferContext *)NULL) { - int delta = ibc->get_data()->get_data_size_bytes() - ibc->get_data_size_bytes(); - _total_buffers_pcollector.add_level(delta); - } -} - #endif // DO_PSTATS //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 2e72ccf0e0..7f1be8e15c 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -247,29 +247,7 @@ protected: INLINE void set_properties(const FrameBufferProperties &properties); #ifdef DO_PSTATS - // These functions are used to update the active texture memory - // usage record (and other frame-based measurements) in Pstats. void init_frame_pstats(); - void add_to_texture_record(TextureContext *tc); - void add_to_geom_record(GeomContext *gc); - void add_to_vertex_buffer_record(VertexBufferContext *vbc); - void add_to_index_buffer_record(IndexBufferContext *ibc); - void add_to_total_buffer_record(VertexBufferContext *vbc); - void add_to_total_buffer_record(IndexBufferContext *ibc); - - pset _current_textures; - pset _current_geoms; - pset _current_vertex_buffers; - pset _current_index_buffers; -#else - INLINE void init_frame_pstats() { } - INLINE void add_to_texture_record(TextureContext *) { } - INLINE void add_to_geom_record(GeomContext *) { } - INLINE void record_state_change(TypeHandle) { } - INLINE void add_to_vertex_buffer_record(VertexBufferContext *) { } - INLINE void add_to_index_buffer_record(IndexBufferContext *) { } - INLINE void add_to_total_buffer_record(VertexBufferContext *) { }; - INLINE void add_to_total_buffer_record(IndexBufferContext *) { }; #endif static CPT(RenderState) get_unlit_state(); @@ -374,10 +352,6 @@ protected: public: // Statistics - static PStatCollector _total_texusage_pcollector; - static PStatCollector _active_texusage_pcollector; - static PStatCollector _texture_count_pcollector; - static PStatCollector _active_texture_count_pcollector; static PStatCollector _vertex_buffer_switch_pcollector; static PStatCollector _index_buffer_switch_pcollector; static PStatCollector _load_vertex_buffer_pcollector; @@ -386,15 +360,6 @@ public: static PStatCollector _create_index_buffer_pcollector; static PStatCollector _load_texture_pcollector; static PStatCollector _data_transferred_pcollector; - static PStatCollector _total_geom_pcollector; - static PStatCollector _active_geom_pcollector; - static PStatCollector _total_buffers_pcollector; - static PStatCollector _active_vertex_buffers_pcollector; - static PStatCollector _active_index_buffers_pcollector; - static PStatCollector _total_geom_node_pcollector; - static PStatCollector _active_geom_node_pcollector; - static PStatCollector _total_texmem_pcollector; - static PStatCollector _used_texmem_pcollector; static PStatCollector _texmgrmem_total_pcollector; static PStatCollector _texmgrmem_resident_pcollector; static PStatCollector _primitive_batches_pcollector; diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 932878522b..fc80082317 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -147,11 +147,11 @@ DXGraphicsStateGuardian8:: //////////////////////////////////////////////////////////////////// TextureContext *DXGraphicsStateGuardian8:: prepare_texture(Texture *tex) { - DXTextureContext8 *dtc = new DXTextureContext8(tex); + DXTextureContext8 *dtc = new DXTextureContext8(_prepared_objects, tex); if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) { dxgsg8_cat.error() - << *dtc->_texture << " is stored in an unsupported compressed format.\n"; + << *dtc->get_texture() << " is stored in an unsupported compressed format.\n"; return NULL; } @@ -178,30 +178,17 @@ apply_texture(int i, TextureContext *tc) { return; } -#ifdef DO_PSTATS - add_to_texture_record(tc); -#endif + tc->set_active(true); DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc); - int dirty = dtc->get_dirty_flags(); - // If the texture image has changed, or if its use of mipmaps has - // changed, we need to re-create the image. Ignore other types of - // changes, which aren't significant for DX. + // changed, we need to re-create the image. - if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) { - // If this is *only* because of a mipmap change, issue a - // warning--it is likely that this change is the result of an - // error or oversight. - if ((dirty & Texture::DF_image) == 0) { - dxgsg8_cat.warning() - << *dtc->_texture << " has changed mipmap state.\n"; - } - - if (!get_supports_compressed_texture_format(tc->_texture->get_ram_image_compression())) { + if (dtc->was_modified()) { + if (!get_supports_compressed_texture_format(tc->get_texture()->get_ram_image_compression())) { dxgsg8_cat.error() - << *dtc->_texture << " is stored in an unsupported compressed format.\n"; + << *dtc->get_texture() << " is stored in an unsupported compressed format.\n"; _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE); return; } @@ -209,13 +196,13 @@ apply_texture(int i, TextureContext *tc) { if (!dtc->create_texture(*_screen)) { // Oops, we can't re-create the texture for some reason. dxgsg8_cat.error() - << "Unable to re-create texture " << *dtc->_texture << endl; + << "Unable to re-create texture " << *dtc->get_texture() << endl; _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE); return; } } - Texture *tex = tc->_texture; + Texture *tex = tc->get_texture(); Texture::WrapMode wrap_u, wrap_v, wrap_w; wrap_u = tex->get_wrap_u(); wrap_v = tex->get_wrap_v(); @@ -303,7 +290,7 @@ release_texture(TextureContext *tc) { //////////////////////////////////////////////////////////////////// VertexBufferContext *DXGraphicsStateGuardian8:: prepare_vertex_buffer(GeomVertexArrayData *data) { - DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(data); + DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(_prepared_objects, data); return dvbc; } @@ -327,14 +314,13 @@ apply_vertex_buffer(VertexBufferContext *vbc) { if (dvbc->_vbuffer != NULL) { dvbc->upload_data(); - add_to_total_buffer_record(dvbc); dvbc->mark_loaded(); _d3d_device->SetStreamSource (0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride()); _active_vbuffer = dvbc; _active_ibuffer = NULL; - add_to_vertex_buffer_record(dvbc); + dvbc->set_active(true); } else { _active_vbuffer = NULL; @@ -349,8 +335,6 @@ apply_vertex_buffer(VertexBufferContext *vbc) { } dvbc->upload_data(); - - add_to_total_buffer_record(dvbc); dvbc->mark_loaded(); _active_vbuffer = NULL; } @@ -360,7 +344,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) { (0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride()); _active_vbuffer = dvbc; _active_ibuffer = NULL; - add_to_vertex_buffer_record(dvbc); + dvbc->set_active(true); } } @@ -403,7 +387,7 @@ release_vertex_buffer(VertexBufferContext *vbc) { //////////////////////////////////////////////////////////////////// IndexBufferContext *DXGraphicsStateGuardian8:: prepare_index_buffer(GeomPrimitive *data) { - DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(data); + DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(_prepared_objects, data); return dibc; } @@ -423,12 +407,11 @@ apply_index_buffer(IndexBufferContext *ibc) { if (dibc->_ibuffer != NULL) { dibc->upload_data(); - add_to_total_buffer_record(dibc); dibc->mark_loaded(); _d3d_device->SetIndices(dibc->_ibuffer, 0); _active_ibuffer = dibc; - add_to_index_buffer_record(dibc); + dibc->set_active(true); } else { _d3d_device->SetIndices(NULL, 0); @@ -445,7 +428,6 @@ apply_index_buffer(IndexBufferContext *ibc) { dibc->upload_data(); - add_to_total_buffer_record(dibc); dibc->mark_loaded(); _active_ibuffer = NULL; } @@ -453,7 +435,7 @@ apply_index_buffer(IndexBufferContext *ibc) { if (_active_ibuffer != dibc) { _d3d_device->SetIndices(dibc->_ibuffer, 0); _active_ibuffer = dibc; - add_to_index_buffer_record(dibc); + dibc->set_active(true); } } } @@ -1396,7 +1378,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, if (!dtc->create_texture(*_screen)) { // Oops, we can't re-create the texture for some reason. dxgsg8_cat.error() - << "Unable to re-create texture " << *dtc->_texture << endl; + << "Unable to re-create texture " << *dtc->get_texture() << endl; return; } hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0); @@ -1415,7 +1397,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, // If it's still the wrong size, it's because driver can't create size // that we want. In that case, there's no helping it, we have to give up. dxgsg8_cat.error() - << "Unable to copy to texture, texture is wrong size: " << *dtc->_texture << endl; + << "Unable to copy to texture, texture is wrong size: " << *dtc->get_texture() << endl; SAFE_RELEASE(tex_level_0); return; } @@ -3435,7 +3417,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, release_all_vertex_buffers(); release_all_index_buffers(); - _prepared_objects->update(this); + _prepared_objects->begin_frame(this); hr = _d3d_device->Reset(&_presentation_reset); if (FAILED(hr)) { @@ -3493,7 +3475,7 @@ check_cooperative_level() { _dx_is_ready = false; // call this just in case - _prepared_objects->update (this); + _prepared_objects->begin_frame(this); hr = reset_d3d_device(&_screen->_presentation_params); if (FAILED(hr)) { diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.cxx b/panda/src/dxgsg8/dxIndexBufferContext8.cxx index f8e9e9c8f4..5dc4f2be8c 100644 --- a/panda/src/dxgsg8/dxIndexBufferContext8.cxx +++ b/panda/src/dxgsg8/dxIndexBufferContext8.cxx @@ -31,8 +31,8 @@ TypeHandle DXIndexBufferContext8::_type_handle; // Description: //////////////////////////////////////////////////////////////////// DXIndexBufferContext8:: -DXIndexBufferContext8(GeomPrimitive *data) : - IndexBufferContext(data), +DXIndexBufferContext8(PreparedGraphicsObjects *pgo, GeomPrimitive *data) : + IndexBufferContext(pgo, data), _ibuffer(NULL) { } diff --git a/panda/src/dxgsg8/dxIndexBufferContext8.h b/panda/src/dxgsg8/dxIndexBufferContext8.h index ca1249106f..6a1d3874ef 100644 --- a/panda/src/dxgsg8/dxIndexBufferContext8.h +++ b/panda/src/dxgsg8/dxIndexBufferContext8.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX DXIndexBufferContext8 : public IndexBufferContext { public: - DXIndexBufferContext8(GeomPrimitive *data); + DXIndexBufferContext8(PreparedGraphicsObjects *pgo, GeomPrimitive *data); virtual ~DXIndexBufferContext8(); void create_ibuffer(DXScreenData &scrn); diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index 5a78fd6a61..56a45722a6 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -35,8 +35,8 @@ static const DWORD g_LowByteMask = 0x000000FF; // Description: //////////////////////////////////////////////////////////////////// DXTextureContext8:: -DXTextureContext8(Texture *tex) : - TextureContext(tex) { +DXTextureContext8(PreparedGraphicsObjects *pgo, Texture *tex) : + TextureContext(pgo, tex) { if (dxgsg8_cat.is_spam()) { dxgsg8_cat.spam() @@ -59,7 +59,7 @@ DXTextureContext8:: ~DXTextureContext8() { if (dxgsg8_cat.is_spam()) { dxgsg8_cat.spam() - << "Deleting texture context for " << _texture->get_name() << "\n"; + << "Deleting texture context for " << get_texture()->get_name() << "\n"; } delete_texture(); TextureContext::~TextureContext(); @@ -82,32 +82,31 @@ create_texture(DXScreenData &scrn) { D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN; bool needs_luminance = false; - nassertr(IS_VALID_PTR(_texture), false); + nassertr(IS_VALID_PTR(get_texture()), false); delete_texture(); - - clear_dirty_flags(Texture::DF_image | Texture::DF_mipmap); + mark_loaded(); // bpp indicates requested fmt, not texture fmt - DWORD target_bpp = get_bits_per_pixel(_texture->get_format(), &num_alpha_bits); - DWORD num_color_channels = _texture->get_num_components(); + DWORD target_bpp = get_bits_per_pixel(get_texture()->get_format(), &num_alpha_bits); + DWORD num_color_channels = get_texture()->get_num_components(); //PRINT_REFCNT(dxgsg8, scrn._d3d8); - DWORD orig_width = (DWORD)_texture->get_x_size(); - DWORD orig_height = (DWORD)_texture->get_y_size(); - DWORD orig_depth = (DWORD)_texture->get_z_size(); + DWORD orig_width = (DWORD)get_texture()->get_x_size(); + DWORD orig_height = (DWORD)get_texture()->get_y_size(); + DWORD orig_depth = (DWORD)get_texture()->get_z_size(); - if ((_texture->get_format() == Texture::F_luminance_alpha)|| - (_texture->get_format() == Texture::F_luminance_alphamask) || - (_texture->get_format() == Texture::F_luminance)) { + if ((get_texture()->get_format() == Texture::F_luminance_alpha)|| + (get_texture()->get_format() == Texture::F_luminance_alphamask) || + (get_texture()->get_format() == Texture::F_luminance)) { needs_luminance = true; } if (num_alpha_bits > 0) { if (num_color_channels == 3) { dxgsg8_cat.error() - << "texture " << _texture->get_name() + << "texture " << get_texture()->get_name() << " has no inherent alpha channel, but alpha format is requested!\n"; } } @@ -145,7 +144,7 @@ create_texture(DXScreenData &scrn) { DWORD filter_caps; - switch (_texture->get_texture_type()) { + switch (get_texture()->get_texture_type()) { case Texture::TT_1d_texture: case Texture::TT_2d_texture: filter_caps = scrn._d3dcaps.TextureFilterCaps; @@ -239,15 +238,15 @@ create_texture(DXScreenData &scrn) { if (orig_width != target_width || orig_height != target_height || orig_depth != target_depth) { - if (_texture->get_texture_type() == Texture::TT_3d_texture) { + if (get_texture()->get_texture_type() == Texture::TT_3d_texture) { dxgsg8_cat.info() - << "Reducing size of " << _texture->get_name() + << "Reducing size of " << get_texture()->get_name() << " from " << orig_width << "x" << orig_height << "x" << orig_depth << " to " << target_width << "x" << target_height << "x" << target_depth << "\n"; } else { dxgsg8_cat.info() - << "Reducing size of " << _texture->get_name() + << "Reducing size of " << get_texture()->get_name() << " from " << orig_width << "x" << orig_height << " to " << target_width << "x" << target_height << "\n"; } @@ -457,7 +456,7 @@ create_texture(DXScreenData &scrn) { // if we've gotten here, haven't found a match dxgsg8_cat.error() - << error_message << ": " << _texture->get_name() << endl + << error_message << ": " << get_texture()->get_name() << endl << "NumColorChannels: " << num_color_channels << "; NumAlphaBits: " << num_alpha_bits << "; targetbpp: " <get_match_framebuffer_format()) { + if (get_texture()->get_match_framebuffer_format()) { // Instead of creating a texture with the found format, we will // need to make one that exactly matches the framebuffer's // format. Look up what that format is. @@ -505,7 +504,7 @@ create_texture(DXScreenData &scrn) { Texture::FilterType ft; - ft = _texture->get_magfilter(); + ft = get_texture()->get_magfilter(); if ((ft != Texture::FT_linear) && ft != Texture::FT_nearest) { // mipmap settings make no sense for magfilter if (ft == Texture::FT_nearest_mipmap_nearest) { @@ -519,10 +518,10 @@ create_texture(DXScreenData &scrn) { (filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) { ft = Texture::FT_nearest; } - _texture->set_magfilter(ft); + get_texture()->set_magfilter(ft); // figure out if we are mipmapping this texture - ft = _texture->get_minfilter(); + ft = get_texture()->get_minfilter(); _has_mipmaps = false; if (!dx_ignore_mipmaps) { // set if no HW mipmap capable @@ -540,11 +539,11 @@ create_texture(DXScreenData &scrn) { if (ft != Texture::FT_linear_mipmap_linear) { dxgsg8_cat.spam() << "Forcing trilinear mipmapping on DX texture [" - << _texture->get_name() << "]\n"; + << get_texture()->get_name() << "]\n"; } } ft = Texture::FT_linear_mipmap_linear; - _texture->set_minfilter(ft); + get_texture()->set_minfilter(ft); } } else if ((ft == Texture::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types @@ -596,23 +595,23 @@ create_texture(DXScreenData &scrn) { break; } - _texture->set_minfilter(ft); + get_texture()->set_minfilter(ft); uint aniso_degree; aniso_degree = 1; if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) { - aniso_degree = _texture->get_anisotropic_degree(); + aniso_degree = get_texture()->get_anisotropic_degree(); if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) || dx_force_anisotropic_filtering) { aniso_degree = scrn._d3dcaps.MaxAnisotropy; } } - _texture->set_anisotropic_degree(aniso_degree); + get_texture()->set_anisotropic_degree(aniso_degree); #ifdef _DEBUG dxgsg8_cat.spam() - << "create_texture: setting aniso degree for " << _texture->get_name() + << "create_texture: setting aniso degree for " << get_texture()->get_name() << " to: " << aniso_degree << endl; #endif @@ -624,7 +623,7 @@ create_texture(DXScreenData &scrn) { if (dxgsg8_cat.is_debug()) { dxgsg8_cat.debug() - << "create_texture: generating mipmaps for " << _texture->get_name() + << "create_texture: generating mipmaps for " << get_texture()->get_name() << endl; } } else { @@ -634,7 +633,7 @@ create_texture(DXScreenData &scrn) { DWORD usage; D3DPOOL pool; - if (_texture->get_render_to_texture ()) { + if (get_texture()->get_render_to_texture ()) { // REQUIRED pool = D3DPOOL_DEFAULT; usage = D3DUSAGE_RENDERTARGET; @@ -646,7 +645,7 @@ create_texture(DXScreenData &scrn) { usage = 0; } - switch (_texture->get_texture_type()) { + switch (get_texture()->get_texture_type()) { case Texture::TT_1d_texture: case Texture::TT_2d_texture: hr = scrn._d3d_device->CreateTexture @@ -678,7 +677,7 @@ create_texture(DXScreenData &scrn) { if (dxgsg8_cat.is_debug()) { dxgsg8_cat.debug() - << "create_texture: " << _texture->get_name() + << "create_texture: " << get_texture()->get_name() << " converting panda equivalent of " << D3DFormatStr(_d3d_format) << " => " << D3DFormatStr(target_pixel_format) << endl; } @@ -984,14 +983,14 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, //////////////////////////////////////////////////////////////////// HRESULT DXTextureContext8:: fill_d3d_texture_pixels() { - if (_texture->get_texture_type() == Texture::TT_3d_texture) { + if (get_texture()->get_texture_type() == Texture::TT_3d_texture) { return fill_d3d_volume_texture_pixels(); } HRESULT hr = E_FAIL; - nassertr(IS_VALID_PTR(_texture), E_FAIL); + nassertr(IS_VALID_PTR(get_texture()), E_FAIL); - CPTA_uchar image = _texture->get_ram_image(); + CPTA_uchar image = get_texture()->get_ram_image(); if (image.is_null()) { // The texture doesn't have an image to load. That's ok; it // might be a texture we've rendered to by frame buffer @@ -1003,13 +1002,13 @@ fill_d3d_texture_pixels() { nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL); - DWORD orig_width = (DWORD) _texture->get_x_size(); - DWORD orig_height = (DWORD) _texture->get_y_size(); - DWORD orig_depth = (DWORD) _texture->get_z_size(); - DWORD num_color_channels = _texture->get_num_components(); + DWORD orig_width = (DWORD) get_texture()->get_x_size(); + DWORD orig_height = (DWORD) get_texture()->get_y_size(); + DWORD orig_depth = (DWORD) get_texture()->get_z_size(); + DWORD num_color_channels = get_texture()->get_num_components(); D3DFORMAT source_format = _d3d_format; BYTE *image_pixels = (BYTE*)image.p(); - int component_width = _texture->get_component_width(); + int component_width = get_texture()->get_component_width(); nassertr(IS_VALID_PTR(image_pixels), E_FAIL); @@ -1018,10 +1017,10 @@ fill_d3d_texture_pixels() { BYTE *pixels = NULL; for (unsigned int di = 0; di < orig_depth; di++) { - pixels = image_pixels + di * _texture->get_expected_ram_page_size(); + pixels = image_pixels + di * get_texture()->get_expected_ram_page_size(); mip_level_0 = NULL; - if (_texture->get_texture_type() == Texture::TT_cube_map) { + if (get_texture()->get_texture_type() == Texture::TT_cube_map) { nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL); hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)di, 0, &mip_level_0); } else { @@ -1031,7 +1030,7 @@ fill_d3d_texture_pixels() { if (FAILED(hr)) { dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr); return E_FAIL; } @@ -1085,7 +1084,7 @@ fill_d3d_texture_pixels() { // original image, but dx8 doesn't support high-precision images // anyway. - int num_components = _texture->get_num_components(); + int num_components = get_texture()->get_num_components(); int num_pixels = orig_width * orig_height * num_components; BYTE *temp_buffer = new BYTE[num_pixels]; if (!IS_VALID_PTR(temp_buffer)) { @@ -1113,7 +1112,7 @@ fill_d3d_texture_pixels() { &source_size, level_0_filter, (D3DCOLOR)0x0); if (FAILED(hr)) { dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } @@ -1131,7 +1130,7 @@ fill_d3d_texture_pixels() { mip_filter_flags); if (FAILED(hr)) { dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXFilterTex failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } @@ -1159,9 +1158,9 @@ fill_d3d_texture_pixels() { HRESULT DXTextureContext8:: fill_d3d_volume_texture_pixels() { HRESULT hr = E_FAIL; - nassertr(IS_VALID_PTR(_texture), E_FAIL); + nassertr(IS_VALID_PTR(get_texture()), E_FAIL); - CPTA_uchar image = _texture->get_ram_image(); + CPTA_uchar image = get_texture()->get_ram_image(); if (image.is_null()) { // The texture doesn't have an image to load. That's ok; it // might be a texture we've rendered to by frame buffer @@ -1172,15 +1171,15 @@ fill_d3d_volume_texture_pixels() { PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector); nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL); - nassertr(_texture->get_texture_type() == Texture::TT_3d_texture, E_FAIL); + nassertr(get_texture()->get_texture_type() == Texture::TT_3d_texture, E_FAIL); - DWORD orig_width = (DWORD) _texture->get_x_size(); - DWORD orig_height = (DWORD) _texture->get_y_size(); - DWORD orig_depth = (DWORD) _texture->get_z_size(); - DWORD num_color_channels = _texture->get_num_components(); + DWORD orig_width = (DWORD) get_texture()->get_x_size(); + DWORD orig_height = (DWORD) get_texture()->get_y_size(); + DWORD orig_depth = (DWORD) get_texture()->get_z_size(); + DWORD num_color_channels = get_texture()->get_num_components(); D3DFORMAT source_format = _d3d_format; BYTE *image_pixels = (BYTE*)image.p(); - int component_width = _texture->get_component_width(); + int component_width = get_texture()->get_component_width(); nassertr(IS_VALID_PTR(image_pixels), E_FAIL); @@ -1193,7 +1192,7 @@ fill_d3d_volume_texture_pixels() { if (FAILED(hr)) { dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr); return E_FAIL; } @@ -1252,7 +1251,7 @@ fill_d3d_volume_texture_pixels() { // original image, but dx8 doesn't support high-precision images // anyway. - int num_components = _texture->get_num_components(); + int num_components = get_texture()->get_num_components(); int num_pixels = orig_width * orig_height * orig_depth * num_components; BYTE *temp_buffer = new BYTE[num_pixels]; if (!IS_VALID_PTR(temp_buffer)) { @@ -1281,7 +1280,7 @@ fill_d3d_volume_texture_pixels() { &source_size, level_0_filter, (D3DCOLOR)0x0); if (FAILED(hr)) { dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } @@ -1299,7 +1298,7 @@ fill_d3d_volume_texture_pixels() { mip_filter_flags); if (FAILED(hr)) { dxgsg8_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXFilterTex failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } diff --git a/panda/src/dxgsg8/dxTextureContext8.h b/panda/src/dxgsg8/dxTextureContext8.h index 9222344316..2a2adf1ec1 100644 --- a/panda/src/dxgsg8/dxTextureContext8.h +++ b/panda/src/dxgsg8/dxTextureContext8.h @@ -29,7 +29,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX DXTextureContext8 : public TextureContext { public: - DXTextureContext8(Texture *tex); + DXTextureContext8(PreparedGraphicsObjects *pgo, Texture *tex); virtual ~DXTextureContext8(); bool create_texture(DXScreenData &scrn); diff --git a/panda/src/dxgsg8/dxVertexBufferContext8.cxx b/panda/src/dxgsg8/dxVertexBufferContext8.cxx index aec593eafe..c4eea445d2 100644 --- a/panda/src/dxgsg8/dxVertexBufferContext8.cxx +++ b/panda/src/dxgsg8/dxVertexBufferContext8.cxx @@ -33,8 +33,8 @@ TypeHandle DXVertexBufferContext8::_type_handle; // Description: //////////////////////////////////////////////////////////////////// DXVertexBufferContext8:: -DXVertexBufferContext8(GeomVertexArrayData *data) : - VertexBufferContext(data), +DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) : + VertexBufferContext(pgo, data), _vbuffer(NULL) { // Now fill in the FVF code. diff --git a/panda/src/dxgsg8/dxVertexBufferContext8.h b/panda/src/dxgsg8/dxVertexBufferContext8.h index 4d9e04b1f1..67c85ca1dd 100644 --- a/panda/src/dxgsg8/dxVertexBufferContext8.h +++ b/panda/src/dxgsg8/dxVertexBufferContext8.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX DXVertexBufferContext8 : public VertexBufferContext { public: - DXVertexBufferContext8(GeomVertexArrayData *data); + DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data); virtual ~DXVertexBufferContext8(); void create_vbuffer(DXScreenData &scrn); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index b571a9e7d1..7eabe534c1 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -190,11 +190,11 @@ DXGraphicsStateGuardian9:: //////////////////////////////////////////////////////////////////// TextureContext *DXGraphicsStateGuardian9:: prepare_texture(Texture *tex) { - DXTextureContext9 *dtc = new DXTextureContext9(tex); + DXTextureContext9 *dtc = new DXTextureContext9(_prepared_objects, tex); if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) { dxgsg9_cat.error() - << *dtc->_texture << " is stored in an unsupported compressed format.\n"; + << *dtc->get_texture() << " is stored in an unsupported compressed format.\n"; return NULL; } @@ -221,9 +221,7 @@ apply_texture(int i, TextureContext *tc) { return; } -#ifdef DO_PSTATS - add_to_texture_record(tc); -#endif + tc->set_active(true); DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc); @@ -232,24 +230,13 @@ apply_texture(int i, TextureContext *tc) { _lru -> access_page (dtc -> _lru_page); } - int dirty = dtc->get_dirty_flags(); - // If the texture image has changed, or if its use of mipmaps has - // changed, we need to re-create the image. Ignore other types of - // changes, which aren't significant for DX. + // changed, we need to re-create the image. - if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) { - // If this is *only* because of a mipmap change, issue a - // warning--it is likely that this change is the result of an - // error or oversight. - if ((dirty & Texture::DF_image) == 0) { - dxgsg9_cat.warning() - << *dtc->_texture << " has changed mipmap state.\n"; - } - - if (!get_supports_compressed_texture_format(tc->_texture->get_ram_image_compression())) { + if (dtc->was_modified()) { + if (!get_supports_compressed_texture_format(tc->get_texture()->get_ram_image_compression())) { dxgsg9_cat.error() - << *dtc->_texture << " is stored in an unsupported compressed format.\n"; + << *dtc->get_texture() << " is stored in an unsupported compressed format.\n"; _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE); return; } @@ -257,13 +244,13 @@ apply_texture(int i, TextureContext *tc) { if (!dtc->create_texture(*_screen)) { // Oops, we can't re-create the texture for some reason. dxgsg9_cat.error() - << "Unable to re-create texture " << *dtc->_texture << endl; + << "Unable to re-create texture " << *dtc->get_texture() << endl; set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE); return; } } - Texture *tex = tc->_texture; + Texture *tex = tc->get_texture(); Texture::WrapMode wrap_u, wrap_v, wrap_w; DWORD address_u; @@ -388,7 +375,7 @@ release_shader(ShaderContext *sc) { //////////////////////////////////////////////////////////////////// VertexBufferContext *DXGraphicsStateGuardian9:: prepare_vertex_buffer(GeomVertexArrayData *data) { - DXVertexBufferContext9 *dvbc = new DXVertexBufferContext9(data, *(this -> _screen)); + DXVertexBufferContext9 *dvbc = new DXVertexBufferContext9(_prepared_objects, data, *(this -> _screen)); return dvbc; } @@ -427,7 +414,6 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context if (dvbc->_vbuffer != NULL) { dvbc->upload_data(); - add_to_total_buffer_record(dvbc); dvbc->mark_loaded(); set_stream_source = true; @@ -446,7 +432,6 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context dvbc->upload_data(); - add_to_total_buffer_record(dvbc); dvbc->mark_loaded(); _active_vbuffer = NULL; } @@ -467,7 +452,7 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context } _active_vbuffer = dvbc; _active_ibuffer = NULL; - add_to_vertex_buffer_record(dvbc); + dvbc->set_active(true); } if ((dvbc->_fvf != _last_fvf)) { @@ -558,7 +543,7 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context } _active_vbuffer = dvbc; _active_ibuffer = NULL; - add_to_vertex_buffer_record(dvbc); + dvbc->set_active(true); } if (dvbc -> _direct_3d_vertex_declaration) { @@ -603,7 +588,7 @@ release_vertex_buffer(VertexBufferContext *vbc) { //////////////////////////////////////////////////////////////////// IndexBufferContext *DXGraphicsStateGuardian9:: prepare_index_buffer(GeomPrimitive *data) { - DXIndexBufferContext9 *dibc = new DXIndexBufferContext9(data); + DXIndexBufferContext9 *dibc = new DXIndexBufferContext9(_prepared_objects, data); return dibc; } @@ -627,12 +612,11 @@ apply_index_buffer(IndexBufferContext *ibc) { if (dibc->_ibuffer != NULL) { dibc->upload_data(); - add_to_total_buffer_record(dibc); dibc->mark_loaded(); _d3d_device->SetIndices(dibc->_ibuffer); _active_ibuffer = dibc; - add_to_index_buffer_record(dibc); + dibc->set_active(true); } else { _d3d_device->SetIndices(NULL); @@ -649,7 +633,6 @@ apply_index_buffer(IndexBufferContext *ibc) { dibc->upload_data(); - add_to_total_buffer_record(dibc); dibc->mark_loaded(); _active_ibuffer = NULL; } @@ -657,7 +640,7 @@ apply_index_buffer(IndexBufferContext *ibc) { if (_active_ibuffer != dibc) { _d3d_device->SetIndices(dibc->_ibuffer); _active_ibuffer = dibc; - add_to_index_buffer_record(dibc); + dibc->set_active(true); } } } @@ -1902,7 +1885,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, if (!dtc->create_texture(*_screen)) { // Oops, we can't re-create the texture for some reason. dxgsg9_cat.error() - << "Unable to re-create texture " << *dtc->_texture << endl; + << "Unable to re-create texture " << *dtc->get_texture() << endl; return; } hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0); @@ -1921,7 +1904,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, // If it's still the wrong size, it's because driver can't create size // that we want. In that case, there's no helping it, we have to give up. dxgsg9_cat.error() - << "Unable to copy to texture, texture is wrong size: " << *dtc->_texture << endl; + << "Unable to copy to texture, texture is wrong size: " << *dtc->get_texture() << endl; SAFE_RELEASE(tex_level_0); return; } @@ -4460,7 +4443,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, release_all_index_buffers(); // must be called before reset - _prepared_objects->update(this); + _prepared_objects->begin_frame(this); hr = _d3d_device->Reset(&_presentation_reset); if (FAILED(hr)) { @@ -4518,7 +4501,7 @@ check_cooperative_level() { _dx_is_ready = false; // call this just in case - _prepared_objects->update (this); + _prepared_objects->begin_frame(this); hr = reset_d3d_device(&_screen->_presentation_params); if (FAILED(hr)) { diff --git a/panda/src/dxgsg9/dxIndexBufferContext9.cxx b/panda/src/dxgsg9/dxIndexBufferContext9.cxx index 46fe79385f..9b86cbaeff 100755 --- a/panda/src/dxgsg9/dxIndexBufferContext9.cxx +++ b/panda/src/dxgsg9/dxIndexBufferContext9.cxx @@ -32,8 +32,8 @@ TypeHandle DXIndexBufferContext9::_type_handle; // Description: //////////////////////////////////////////////////////////////////// DXIndexBufferContext9:: -DXIndexBufferContext9(GeomPrimitive *data) : - IndexBufferContext(data), +DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data) : + IndexBufferContext(pgo, data), _ibuffer(NULL) { _managed = -1; diff --git a/panda/src/dxgsg9/dxIndexBufferContext9.h b/panda/src/dxgsg9/dxIndexBufferContext9.h index 3655e3fb1d..2bce12c7e3 100755 --- a/panda/src/dxgsg9/dxIndexBufferContext9.h +++ b/panda/src/dxgsg9/dxIndexBufferContext9.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX DXIndexBufferContext9 : public IndexBufferContext { public: - DXIndexBufferContext9(GeomPrimitive *data); + DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data); virtual ~DXIndexBufferContext9(); void free_ibuffer(void); diff --git a/panda/src/dxgsg9/dxTextureContext9.cxx b/panda/src/dxgsg9/dxTextureContext9.cxx index bb97422ca8..c3387d8363 100755 --- a/panda/src/dxgsg9/dxTextureContext9.cxx +++ b/panda/src/dxgsg9/dxTextureContext9.cxx @@ -37,8 +37,8 @@ static const DWORD g_LowByteMask = 0x000000FF; // Description: //////////////////////////////////////////////////////////////////// DXTextureContext9:: -DXTextureContext9(Texture *tex) : - TextureContext(tex) { +DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex) : + TextureContext(pgo, tex) { if (dxgsg9_cat.is_spam()) { dxgsg9_cat.spam() @@ -63,7 +63,7 @@ DXTextureContext9:: ~DXTextureContext9() { if (dxgsg9_cat.is_spam()) { dxgsg9_cat.spam() - << "Deleting texture context for " << _texture->get_name() << "\n"; + << "Deleting texture context for " << get_texture()->get_name() << "\n"; } if (_lru_page) @@ -94,32 +94,31 @@ create_texture(DXScreenData &scrn) { D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN; bool needs_luminance = false; - nassertr(IS_VALID_PTR(_texture), false); + nassertr(IS_VALID_PTR(get_texture()), false); delete_texture(); - - clear_dirty_flags(Texture::DF_image | Texture::DF_mipmap); + mark_loaded(); // bpp indicates requested fmt, not texture fmt - DWORD target_bpp = get_bits_per_pixel(_texture->get_format(), &num_alpha_bits); - DWORD num_color_channels = _texture->get_num_components(); + DWORD target_bpp = get_bits_per_pixel(get_texture()->get_format(), &num_alpha_bits); + DWORD num_color_channels = get_texture()->get_num_components(); //PRINT_REFCNT(dxgsg9, scrn._d3d9); - DWORD orig_width = (DWORD)_texture->get_x_size(); - DWORD orig_height = (DWORD)_texture->get_y_size(); - DWORD orig_depth = (DWORD)_texture->get_z_size(); + DWORD orig_width = (DWORD)get_texture()->get_x_size(); + DWORD orig_height = (DWORD)get_texture()->get_y_size(); + DWORD orig_depth = (DWORD)get_texture()->get_z_size(); - if ((_texture->get_format() == Texture::F_luminance_alpha)|| - (_texture->get_format() == Texture::F_luminance_alphamask) || - (_texture->get_format() == Texture::F_luminance)) { + if ((get_texture()->get_format() == Texture::F_luminance_alpha)|| + (get_texture()->get_format() == Texture::F_luminance_alphamask) || + (get_texture()->get_format() == Texture::F_luminance)) { needs_luminance = true; } if (num_alpha_bits > 0) { if (num_color_channels == 3) { dxgsg9_cat.error() - << "texture " << _texture->get_name() + << "texture " << get_texture()->get_name() << " has no inherent alpha channel, but alpha format is requested!\n"; } } @@ -157,7 +156,7 @@ create_texture(DXScreenData &scrn) { DWORD filter_caps; - switch (_texture->get_texture_type()) { + switch (get_texture()->get_texture_type()) { case Texture::TT_1d_texture: case Texture::TT_2d_texture: filter_caps = scrn._d3dcaps.TextureFilterCaps; @@ -251,15 +250,15 @@ create_texture(DXScreenData &scrn) { if (orig_width != target_width || orig_height != target_height || orig_depth != target_depth) { - if (_texture->get_texture_type() == Texture::TT_3d_texture) { + if (get_texture()->get_texture_type() == Texture::TT_3d_texture) { dxgsg9_cat.info() - << "Reducing size of " << _texture->get_name() + << "Reducing size of " << get_texture()->get_name() << " from " << orig_width << "x" << orig_height << "x" << orig_depth << " to " << target_width << "x" << target_height << "x" << target_depth << "\n"; } else { dxgsg9_cat.info() - << "Reducing size of " << _texture->get_name() + << "Reducing size of " << get_texture()->get_name() << " from " << orig_width << "x" << orig_height << " to " << target_width << "x" << target_height << "\n"; } @@ -469,7 +468,7 @@ create_texture(DXScreenData &scrn) { // if we've gotten here, haven't found a match dxgsg9_cat.error() - << error_message << ": " << _texture->get_name() << endl + << error_message << ": " << get_texture()->get_name() << endl << "NumColorChannels: " << num_color_channels << "; NumAlphaBits: " << num_alpha_bits << "; targetbpp: " <get_match_framebuffer_format()) { + if (get_texture()->get_match_framebuffer_format()) { // Instead of creating a texture with the found format, we will // need to make one that exactly matches the framebuffer's // format. Look up what that format is. @@ -520,7 +519,7 @@ create_texture(DXScreenData &scrn) { Texture::FilterType ft; - ft = _texture->get_magfilter(); + ft = get_texture()->get_magfilter(); if ((ft != Texture::FT_linear) && ft != Texture::FT_nearest) { // mipmap settings make no sense for magfilter if (ft == Texture::FT_nearest_mipmap_nearest) { @@ -534,10 +533,10 @@ create_texture(DXScreenData &scrn) { (filter_caps & D3DPTFILTERCAPS_MAGFLINEAR) == 0) { ft = Texture::FT_nearest; } - _texture->set_magfilter(ft); + get_texture()->set_magfilter(ft); // figure out if we are mipmapping this texture - ft = _texture->get_minfilter(); + ft = get_texture()->get_minfilter(); _has_mipmaps = false; if (!dx_ignore_mipmaps) { // set if no HW mipmap capable @@ -555,11 +554,11 @@ create_texture(DXScreenData &scrn) { if (ft != Texture::FT_linear_mipmap_linear) { dxgsg9_cat.spam() << "Forcing trilinear mipmapping on DX texture [" - << _texture->get_name() << "]\n"; + << get_texture()->get_name() << "]\n"; } } ft = Texture::FT_linear_mipmap_linear; - _texture->set_minfilter(ft); + get_texture()->set_minfilter(ft); } } else if ((ft == Texture::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types @@ -611,23 +610,23 @@ create_texture(DXScreenData &scrn) { break; } - _texture->set_minfilter(ft); + get_texture()->set_minfilter(ft); uint aniso_degree; aniso_degree = 1; if (scrn._d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) { - aniso_degree = _texture->get_anisotropic_degree(); + aniso_degree = get_texture()->get_anisotropic_degree(); if ((aniso_degree>scrn._d3dcaps.MaxAnisotropy) || dx_force_anisotropic_filtering) { aniso_degree = scrn._d3dcaps.MaxAnisotropy; } } - _texture->set_anisotropic_degree(aniso_degree); + get_texture()->set_anisotropic_degree(aniso_degree); #ifdef _DEBUG dxgsg9_cat.spam() - << "create_texture: setting aniso degree for " << _texture->get_name() + << "create_texture: setting aniso degree for " << get_texture()->get_name() << " to: " << aniso_degree << endl; #endif @@ -639,7 +638,7 @@ create_texture(DXScreenData &scrn) { if (dxgsg9_cat.is_debug()) { dxgsg9_cat.debug() - << "create_texture: generating mipmaps for " << _texture->get_name() + << "create_texture: generating mipmaps for " << get_texture()->get_name() << endl; } } else { @@ -649,7 +648,7 @@ create_texture(DXScreenData &scrn) { DWORD usage; D3DPOOL pool; - if (_texture->get_render_to_texture ( )) { + if (get_texture()->get_render_to_texture ( )) { // REQUIRED PARAMETERS _managed = false; pool = D3DPOOL_DEFAULT; @@ -752,7 +751,7 @@ create_texture(DXScreenData &scrn) { { data_size = (int) ((float) data_size * 1.3f); } - if (_texture->get_texture_type() == Texture::TT_cube_map) + if (get_texture()->get_texture_type() == Texture::TT_cube_map) { data_size *= 6; } @@ -762,7 +761,7 @@ create_texture(DXScreenData &scrn) { attempts = 0; do { - switch (_texture->get_texture_type()) { + switch (get_texture()->get_texture_type()) { case Texture::TT_1d_texture: case Texture::TT_2d_texture: hr = scrn._d3d_device->CreateTexture @@ -800,7 +799,7 @@ create_texture(DXScreenData &scrn) { if (DEBUG_TEXTURES && dxgsg9_cat.is_debug()) { dxgsg9_cat.debug() - << "create_texture: " << _texture->get_name() + << "create_texture: " << get_texture()->get_name() << " converting panda equivalent of " << D3DFormatStr(_d3d_format) << " => " << D3DFormatStr(target_pixel_format) << endl; } @@ -814,7 +813,7 @@ create_texture(DXScreenData &scrn) { // must not put render to texture into LRU - if (_lru_page == 0 && _managed == false && _texture->get_render_to_texture ( ) == false) + if (_lru_page == 0 && _managed == false && get_texture()->get_render_to_texture ( ) == false) { Lru *lru; @@ -1130,14 +1129,14 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface, //////////////////////////////////////////////////////////////////// HRESULT DXTextureContext9:: fill_d3d_texture_pixels() { - if (_texture->get_texture_type() == Texture::TT_3d_texture) { + if (get_texture()->get_texture_type() == Texture::TT_3d_texture) { return fill_d3d_volume_texture_pixels(); } HRESULT hr = E_FAIL; - nassertr(IS_VALID_PTR(_texture), E_FAIL); + nassertr(IS_VALID_PTR(get_texture()), E_FAIL); - CPTA_uchar image = _texture->get_ram_image(); + CPTA_uchar image = get_texture()->get_ram_image(); if (image.is_null()) { // The texture doesn't have an image to load. That's ok; it // might be a texture we've rendered to by frame buffer @@ -1149,13 +1148,13 @@ fill_d3d_texture_pixels() { nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL); - DWORD orig_width = (DWORD) _texture->get_x_size(); - DWORD orig_height = (DWORD) _texture->get_y_size(); - DWORD orig_depth = (DWORD) _texture->get_z_size(); - DWORD num_color_channels = _texture->get_num_components(); + DWORD orig_width = (DWORD) get_texture()->get_x_size(); + DWORD orig_height = (DWORD) get_texture()->get_y_size(); + DWORD orig_depth = (DWORD) get_texture()->get_z_size(); + DWORD num_color_channels = get_texture()->get_num_components(); D3DFORMAT source_format = _d3d_format; BYTE *image_pixels = (BYTE*)image.p(); - int component_width = _texture->get_component_width(); + int component_width = get_texture()->get_component_width(); nassertr(IS_VALID_PTR(image_pixels), E_FAIL); @@ -1164,10 +1163,10 @@ fill_d3d_texture_pixels() { BYTE *pixels = NULL; for (unsigned int di = 0; di < orig_depth; di++) { - pixels = image_pixels + di * _texture->get_expected_ram_page_size(); + pixels = image_pixels + di * get_texture()->get_expected_ram_page_size(); mip_level_0 = NULL; - if (_texture->get_texture_type() == Texture::TT_cube_map) { + if (get_texture()->get_texture_type() == Texture::TT_cube_map) { nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL); hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)di, 0, &mip_level_0); } else { @@ -1177,7 +1176,7 @@ fill_d3d_texture_pixels() { if (FAILED(hr)) { dxgsg9_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr); return E_FAIL; } @@ -1231,7 +1230,7 @@ fill_d3d_texture_pixels() { // original image, but dx8 doesn't support high-precision images // anyway. - int num_components = _texture->get_num_components(); + int num_components = get_texture()->get_num_components(); int num_pixels = orig_width * orig_height * num_components; BYTE *temp_buffer = new BYTE[num_pixels]; if (!IS_VALID_PTR(temp_buffer)) { @@ -1259,7 +1258,7 @@ fill_d3d_texture_pixels() { &source_size, level_0_filter, (D3DCOLOR)0x0); if (FAILED(hr)) { dxgsg9_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } @@ -1277,7 +1276,7 @@ fill_d3d_texture_pixels() { mip_filter_flags); if (FAILED(hr)) { dxgsg9_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXFilterTex failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } @@ -1308,9 +1307,9 @@ fill_d3d_texture_pixels() { HRESULT DXTextureContext9:: fill_d3d_volume_texture_pixels() { HRESULT hr = E_FAIL; - nassertr(IS_VALID_PTR(_texture), E_FAIL); + nassertr(IS_VALID_PTR(get_texture()), E_FAIL); - CPTA_uchar image = _texture->get_ram_image(); + CPTA_uchar image = get_texture()->get_ram_image(); if (image.is_null()) { // The texture doesn't have an image to load. That's ok; it // might be a texture we've rendered to by frame buffer @@ -1321,15 +1320,15 @@ fill_d3d_volume_texture_pixels() { PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector); nassertr(IS_VALID_PTR(_d3d_texture), E_FAIL); - nassertr(_texture->get_texture_type() == Texture::TT_3d_texture, E_FAIL); + nassertr(get_texture()->get_texture_type() == Texture::TT_3d_texture, E_FAIL); - DWORD orig_width = (DWORD) _texture->get_x_size(); - DWORD orig_height = (DWORD) _texture->get_y_size(); - DWORD orig_depth = (DWORD) _texture->get_z_size(); - DWORD num_color_channels = _texture->get_num_components(); + DWORD orig_width = (DWORD) get_texture()->get_x_size(); + DWORD orig_height = (DWORD) get_texture()->get_y_size(); + DWORD orig_depth = (DWORD) get_texture()->get_z_size(); + DWORD num_color_channels = get_texture()->get_num_components(); D3DFORMAT source_format = _d3d_format; BYTE *image_pixels = (BYTE*)image.p(); - int component_width = _texture->get_component_width(); + int component_width = get_texture()->get_component_width(); nassertr(IS_VALID_PTR(image_pixels), E_FAIL); @@ -1342,7 +1341,7 @@ fill_d3d_volume_texture_pixels() { if (FAILED(hr)) { dxgsg9_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", GetSurfaceLevel failed" << D3DERRORSTRING(hr); return E_FAIL; } @@ -1401,7 +1400,7 @@ fill_d3d_volume_texture_pixels() { // original image, but dx8 doesn't support high-precision images // anyway. - int num_components = _texture->get_num_components(); + int num_components = get_texture()->get_num_components(); int num_pixels = orig_width * orig_height * orig_depth * num_components; BYTE *temp_buffer = new BYTE[num_pixels]; if (!IS_VALID_PTR(temp_buffer)) { @@ -1430,7 +1429,7 @@ fill_d3d_volume_texture_pixels() { &source_size, level_0_filter, (D3DCOLOR)0x0); if (FAILED(hr)) { dxgsg9_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXLoadVolumeFromMem failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } @@ -1448,7 +1447,7 @@ fill_d3d_volume_texture_pixels() { mip_filter_flags); if (FAILED(hr)) { dxgsg9_cat.error() - << "FillDDSurfaceTexturePixels failed for " << _texture->get_name() + << "FillDDSurfaceTexturePixels failed for " << get_texture()->get_name() << ", D3DXFilterTex failed" << D3DERRORSTRING(hr); goto exit_FillDDSurf; } diff --git a/panda/src/dxgsg9/dxTextureContext9.h b/panda/src/dxgsg9/dxTextureContext9.h index 890d5abb37..64a1003a23 100755 --- a/panda/src/dxgsg9/dxTextureContext9.h +++ b/panda/src/dxgsg9/dxTextureContext9.h @@ -31,7 +31,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX DXTextureContext9 : public TextureContext { public: - DXTextureContext9(Texture *tex); + DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex); virtual ~DXTextureContext9(); bool create_texture(DXScreenData &scrn); diff --git a/panda/src/dxgsg9/dxVertexBufferContext9.cxx b/panda/src/dxgsg9/dxVertexBufferContext9.cxx index b5fd0678e4..904ed30b38 100755 --- a/panda/src/dxgsg9/dxVertexBufferContext9.cxx +++ b/panda/src/dxgsg9/dxVertexBufferContext9.cxx @@ -34,8 +34,8 @@ TypeHandle DXVertexBufferContext9::_type_handle; // Description: //////////////////////////////////////////////////////////////////// DXVertexBufferContext9:: -DXVertexBufferContext9(GeomVertexArrayData *data, DXScreenData &scrn) : - VertexBufferContext(data), +DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data, DXScreenData &scrn) : + VertexBufferContext(pgo, data), _vbuffer(NULL) { // Now fill in the FVF code. diff --git a/panda/src/dxgsg9/dxVertexBufferContext9.h b/panda/src/dxgsg9/dxVertexBufferContext9.h index 9e14d23e65..0159005255 100755 --- a/panda/src/dxgsg9/dxVertexBufferContext9.h +++ b/panda/src/dxgsg9/dxVertexBufferContext9.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX DXVertexBufferContext9 : public VertexBufferContext { public: - DXVertexBufferContext9(GeomVertexArrayData *data, DXScreenData &scrn); + DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data, DXScreenData &scrn); virtual ~DXVertexBufferContext9(); void free_vbuffer(void); diff --git a/panda/src/express/pipelineCyclerLinks.I b/panda/src/express/pipelineCyclerLinks.I index 07d2337c6c..3bf53811d2 100644 --- a/panda/src/express/pipelineCyclerLinks.I +++ b/panda/src/express/pipelineCyclerLinks.I @@ -20,7 +20,7 @@ #ifdef THREADED_PIPELINE //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerLinks::Constructor -// Access: Public +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// INLINE PipelineCyclerLinks:: @@ -35,7 +35,7 @@ PipelineCyclerLinks() { #ifdef THREADED_PIPELINE //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerLinks::Destructor -// Access: Public +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// INLINE PipelineCyclerLinks:: @@ -47,7 +47,7 @@ INLINE PipelineCyclerLinks:: #ifdef THREADED_PIPELINE //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerLinks::remove_from_list -// Access: Private +// Access: Protected // Description: Removes a PipelineCyclerLinks record from the // doubly-linked list. //////////////////////////////////////////////////////////////////// @@ -66,7 +66,7 @@ remove_from_list() { #ifdef THREADED_PIPELINE //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerLinks::insert_before -// Access: Private +// Access: Protected // Description: Adds a PipelineCyclerLinks record before the indicated // node in the doubly-linked list. //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 48ebd5f04e..6a772689cb 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1236,8 +1236,20 @@ end_frame() { GLP(Flush)(); } +#ifdef DO_PSTATS + // Check for textures, etc., that are no longer resident. + check_nonresident_texture(_prepared_objects->_texture_residency.get_inactive_resident()); + check_nonresident_texture(_prepared_objects->_texture_residency.get_active_resident()); + + // OpenGL provides no methods for querying whether a buffer object + // (vertex buffer) is resident. In fact, the API appears geared + // towards the assumption that such buffers are always resident. + // OK. +#endif + report_my_gl_errors(); } + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::begin_draw_primitives @@ -2117,7 +2129,7 @@ prepare_texture(Texture *tex) { break; } - CLP(TextureContext) *gtc = new CLP(TextureContext)(tex); + CLP(TextureContext) *gtc = new CLP(TextureContext)(_prepared_objects, tex); GLP(GenTextures)(1, >c->_index); report_my_gl_errors(); @@ -2529,7 +2541,7 @@ record_deleted_display_list(GLuint index) { VertexBufferContext *CLP(GraphicsStateGuardian):: prepare_vertex_buffer(GeomVertexArrayData *data) { if (_supports_buffers) { - CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(data); + CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(_prepared_objects, data); _glGenBuffers(1, &gvbc->_index); if (GLCAT.is_debug()) { @@ -2566,7 +2578,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) { } _glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index); _current_vbuffer_index = gvbc->_index; - add_to_vertex_buffer_record(gvbc); + gvbc->set_active(true); } if (gvbc->was_modified()) { @@ -2589,7 +2601,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) { } _data_transferred_pcollector.add_level(num_bytes); } - add_to_total_buffer_record(gvbc); + gvbc->mark_loaded(); } @@ -2696,7 +2708,7 @@ setup_array_data(const GeomVertexArrayData *data) { IndexBufferContext *CLP(GraphicsStateGuardian):: prepare_index_buffer(GeomPrimitive *data) { if (_supports_buffers) { - CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(data); + CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(_prepared_objects, data); _glGenBuffers(1, &gibc->_index); if (GLCAT.is_debug()) { @@ -2734,7 +2746,7 @@ apply_index_buffer(IndexBufferContext *ibc) { } _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gibc->_index); _current_ibuffer_index = gibc->_index; - add_to_index_buffer_record(gibc); + gibc->set_active(true); } if (gibc->was_modified()) { @@ -2757,7 +2769,6 @@ apply_index_buffer(IndexBufferContext *ibc) { } _data_transferred_pcollector.add_level(num_bytes); } - add_to_total_buffer_record(gibc); gibc->mark_loaded(); } @@ -6239,25 +6250,19 @@ void CLP(GraphicsStateGuardian):: apply_texture(TextureContext *tc) { CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - add_to_texture_record(gtc); - GLenum target = get_texture_target(gtc->_texture->get_texture_type()); + gtc->set_active(true); + GLenum target = get_texture_target(gtc->get_texture()->get_texture_type()); if (target == GL_NONE) { return; } GLP(BindTexture)(target, gtc->_index); - int dirty = gtc->get_dirty_flags(); - if ((dirty & (Texture::DF_wrap | Texture::DF_filter | Texture::DF_border)) != 0) { - // We need to re-specify the texture properties. - specify_texture(gtc->_texture); - } - if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) { - // We need to re-upload the image. + if (gtc->was_modified()) { + specify_texture(gtc->get_texture()); upload_texture(gtc); + gtc->mark_loaded(); } - gtc->clear_dirty_flags(); - report_my_gl_errors(); } @@ -6272,7 +6277,7 @@ apply_texture(TextureContext *tc) { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: upload_texture(CLP(TextureContext) *gtc) { - Texture *tex = gtc->_texture; + Texture *tex = gtc->get_texture(); CPTA_uchar image = tex->get_ram_image(); if (image.is_null()) { return false; @@ -6451,7 +6456,7 @@ upload_texture(CLP(TextureContext) *gtc) { gtc->_depth = depth; #ifdef DO_PSTATS - gtc->_texture_memory_size = get_texture_memory_size(tex); + gtc->update_data_size_bytes(get_texture_memory_size(tex)); #endif #ifndef NDEBUG @@ -6502,7 +6507,7 @@ upload_texture_image(CLP(TextureContext) *gtc, #endif #ifndef NDEBUG if (CLP(show_mipmaps) && target == GL_TEXTURE_2D) { - build_phony_mipmaps(gtc->_texture); + build_phony_mipmaps(gtc->get_texture()); report_my_gl_errors(); return true; @@ -6552,10 +6557,10 @@ upload_texture_image(CLP(TextureContext) *gtc, if (GLCAT.is_debug()) { if (image_compression != Texture::CM_off) { GLCAT.debug() - << "loading pre-compressed texture " << gtc->_texture->get_name() << "\n"; + << "loading pre-compressed texture " << gtc->get_texture()->get_name() << "\n"; } else if (is_compressed_format(internal_format)) { GLCAT.debug() - << "compressing texture " << gtc->_texture->get_name() << "\n"; + << "compressing texture " << gtc->get_texture()->get_name() << "\n"; } } @@ -6640,7 +6645,7 @@ upload_texture_image(CLP(TextureContext) *gtc, if (error_code != GL_NO_ERROR) { const GLubyte *error_string = GLUP(ErrorString)(error_code); GLCAT.error() - << "GL texture creation failed for " << gtc->_texture->get_name(); + << "GL texture creation failed for " << gtc->get_texture()->get_name(); if (error_string != (const GLubyte *)NULL) { GLCAT.error(false) << " : " << error_string; @@ -6737,6 +6742,42 @@ get_texture_memory_size(Texture *tex) const { return result; } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::check_nonresident_texture +// Access: Private +// Description: Checks the list of resident texture objects to see if +// any have recently been evicted. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +check_nonresident_texture(BufferContextChain &chain) { + size_t num_textures = chain.get_count(); + CLP(TextureContext) **gtc_list = (CLP(TextureContext) **)alloca(num_textures * sizeof(CLP(TextureContext) *)); + GLuint *texture_list = (GLuint *)alloca(num_textures * sizeof(GLuint)); + size_t ti = 0; + BufferContext *node = chain.get_first(); + while (node != (BufferContext *)NULL) { + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), node); + gtc_list[ti] = gtc; + texture_list[ti] = gtc->_index; + node = node->get_next(); + ++ti; + } + nassertv(ti == num_textures); + GLboolean *results = (GLboolean *)alloca(num_textures * sizeof(GLboolean)); + bool all_resident = (glAreTexturesResident(num_textures, texture_list, results) != 0); + + report_my_gl_errors(); + + if (!all_resident) { + // Some are now nonresident. + for (ti = 0; ti < num_textures; ++ti) { + if (!results[ti]) { + gtc_list[ti]->set_resident(false); + } + } + } +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::do_point_size // Access: Protected diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index e900ae0db4..c38c040509 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -278,6 +278,7 @@ protected: Texture::CompressionMode image_compression); size_t get_texture_memory_size(Texture *tex) const; + void check_nonresident_texture(BufferContextChain &chain); void do_point_size(); diff --git a/panda/src/glstuff/glIndexBufferContext_src.I b/panda/src/glstuff/glIndexBufferContext_src.I index 664324389f..f6b1424646 100644 --- a/panda/src/glstuff/glIndexBufferContext_src.I +++ b/panda/src/glstuff/glIndexBufferContext_src.I @@ -23,8 +23,8 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE CLP(IndexBufferContext):: -CLP(IndexBufferContext)(GeomPrimitive *data) : - IndexBufferContext(data) +CLP(IndexBufferContext)(PreparedGraphicsObjects *pgo, GeomPrimitive *data) : + IndexBufferContext(pgo, data) { _index = 0; } diff --git a/panda/src/glstuff/glIndexBufferContext_src.h b/panda/src/glstuff/glIndexBufferContext_src.h index 46cd354a94..2409c89445 100644 --- a/panda/src/glstuff/glIndexBufferContext_src.h +++ b/panda/src/glstuff/glIndexBufferContext_src.h @@ -26,7 +26,8 @@ //////////////////////////////////////////////////////////////////// class EXPCL_GL CLP(IndexBufferContext) : public IndexBufferContext { public: - INLINE CLP(IndexBufferContext)(GeomPrimitive *data); + INLINE CLP(IndexBufferContext)(PreparedGraphicsObjects *pgo, + GeomPrimitive *data); // This is the GL "name" of the data object. GLuint _index; diff --git a/panda/src/glstuff/glTextureContext_src.I b/panda/src/glstuff/glTextureContext_src.I index c062ed4302..a1a55a319f 100644 --- a/panda/src/glstuff/glTextureContext_src.I +++ b/panda/src/glstuff/glTextureContext_src.I @@ -23,10 +23,9 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE CLP(TextureContext):: -CLP(TextureContext)(Texture *tex) : - TextureContext(tex) +CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex) : + TextureContext(pgo, tex) { _index = 0; _already_applied = false; - _texture_memory_size = 0; } diff --git a/panda/src/glstuff/glTextureContext_src.cxx b/panda/src/glstuff/glTextureContext_src.cxx index 70434ff12d..3793d16419 100644 --- a/panda/src/glstuff/glTextureContext_src.cxx +++ b/panda/src/glstuff/glTextureContext_src.cxx @@ -19,20 +19,3 @@ #include "notify.h" TypeHandle CLP(TextureContext)::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: GLTextureContext::estimate_texture_memory -// Access: Public, Virtual -// Description: Estimates the amount of texture memory that will be -// consumed by loading this texture. This is mainly -// useful for debugging and reporting purposes. -// -// Returns a value in bytes. -//////////////////////////////////////////////////////////////////// -size_t CLP(TextureContext):: -estimate_texture_memory() { - if (_texture_memory_size == 0) { - return TextureContext::estimate_texture_memory(); - } - return _texture_memory_size; -} diff --git a/panda/src/glstuff/glTextureContext_src.h b/panda/src/glstuff/glTextureContext_src.h index 57a0f60bac..83b294bf91 100644 --- a/panda/src/glstuff/glTextureContext_src.h +++ b/panda/src/glstuff/glTextureContext_src.h @@ -25,9 +25,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_GL CLP(TextureContext) : public TextureContext { public: - INLINE CLP(TextureContext)(Texture *tex); - - virtual size_t estimate_texture_memory(); + INLINE CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex); // This is the GL "name" of the texture object. GLuint _index; @@ -41,8 +39,6 @@ public: GLsizei _height; GLsizei _depth; - size_t _texture_memory_size; - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/glstuff/glVertexBufferContext_src.I b/panda/src/glstuff/glVertexBufferContext_src.I index c5ac7d5122..c11b951b7b 100644 --- a/panda/src/glstuff/glVertexBufferContext_src.I +++ b/panda/src/glstuff/glVertexBufferContext_src.I @@ -23,8 +23,8 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE CLP(VertexBufferContext):: -CLP(VertexBufferContext)(GeomVertexArrayData *data) : - VertexBufferContext(data) +CLP(VertexBufferContext)(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) : + VertexBufferContext(pgo, data) { _index = 0; } diff --git a/panda/src/glstuff/glVertexBufferContext_src.h b/panda/src/glstuff/glVertexBufferContext_src.h index da3634c889..8246a22b09 100644 --- a/panda/src/glstuff/glVertexBufferContext_src.h +++ b/panda/src/glstuff/glVertexBufferContext_src.h @@ -26,7 +26,8 @@ //////////////////////////////////////////////////////////////////// class EXPCL_GL CLP(VertexBufferContext) : public VertexBufferContext { public: - INLINE CLP(VertexBufferContext)(GeomVertexArrayData *data); + INLINE CLP(VertexBufferContext)(PreparedGraphicsObjects *pgo, + GeomVertexArrayData *data); // This is the GL "name" of the data object. GLuint _index; diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index cca6352591..4357fb678a 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -11,6 +11,9 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define SOURCES \ + bufferContext.I bufferContext.h \ + bufferContextChain.I bufferContextChain.h \ + bufferResidencyTracker.I bufferResidencyTracker.h \ config_gobj.h \ geom.h geom.I \ geomContext.I geomContext.h \ @@ -61,6 +64,9 @@ videoTexture.I videoTexture.h #define INCLUDED_SOURCES \ + bufferContext.cxx \ + bufferContextChain.cxx \ + bufferResidencyTracker.cxx \ config_gobj.cxx \ geomContext.cxx \ geom.cxx \ @@ -108,6 +114,9 @@ videoTexture.cxx #define INSTALL_HEADERS \ + bufferContext.I bufferContext.h \ + bufferContextChain.I bufferContextChain.h \ + bufferResidencyTracker.I bufferResidencyTracker.h \ config_gobj.h \ geom.I geom.h \ textureContext.I textureContext.h \ diff --git a/panda/src/gobj/bufferContext.I b/panda/src/gobj/bufferContext.I new file mode 100644 index 0000000000..16439a6b0f --- /dev/null +++ b/panda/src/gobj/bufferContext.I @@ -0,0 +1,158 @@ +// Filename: bufferContext.I +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BufferContext:: +BufferContext(BufferResidencyTracker *residency) : + _residency(residency), + _residency_state(0), + _data_size_bytes(0), + _owning_chain(&residency->_chains[0]) +{ +#ifdef DO_PSTATS + ++(_owning_chain->_count); + insert_before(_owning_chain); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::get_data_size_bytes +// Access: Public +// Description: Returns the number of bytes previously reported for +// the data object. This is used to track changes in +// the data object's allocated size; if it changes from +// this, we need to create a new buffer. This is also +// used to track memory utilization in PStats. +//////////////////////////////////////////////////////////////////// +INLINE size_t BufferContext:: +get_data_size_bytes() const { + return _data_size_bytes; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::get_modified +// Access: Public +// Description: Returns the UpdateSeq that was recorded the last time +// mark_loaded() was called. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq BufferContext:: +get_modified() const { + return _modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::set_active +// Access: Public +// Description: Changes the active flag associated with this object. +// An object is considered "active" if it was rendered +// in the current frame. +//////////////////////////////////////////////////////////////////// +INLINE void BufferContext:: +set_active(bool flag) { +#ifdef DO_PSTATS + if (flag) { + _residency_state |= BufferResidencyTracker::S_active; + // Assume that rendering the object automatically makes it + // resident. + _residency_state |= BufferResidencyTracker::S_resident; + } else { + _residency_state &= ~BufferResidencyTracker::S_active; + } + set_owning_chain(&_residency->_chains[_residency_state]); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::set_resident +// Access: Public +// Description: Changes the resident flag associated with this +// object. An object is considered "resident" if it +// appears to be resident in texture memory. +//////////////////////////////////////////////////////////////////// +INLINE void BufferContext:: +set_resident(bool flag) { +#ifdef DO_PSTATS + if (flag) { + _residency_state |= BufferResidencyTracker::S_resident; + } else { + _residency_state &= ~BufferResidencyTracker::S_resident; + } + set_owning_chain(&_residency->_chains[_residency_state]); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::get_next +// Access: Public +// Description: This can be used along with +// BufferContextChain::get_first() to walk through the +// list of objects stored on a tracker. +//////////////////////////////////////////////////////////////////// +INLINE BufferContext *BufferContext:: +get_next() const { + if ((BufferContextChain *)_next == _owning_chain) { + return NULL; + } + return (BufferContext *)_next; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::update_data_size_bytes +// Access: Public +// Description: Should be called (usually by a derived class) when +// the on-card size of this object has changed. +//////////////////////////////////////////////////////////////////// +INLINE void BufferContext:: +update_data_size_bytes(size_t new_data_size_bytes) { + _owning_chain->adjust_bytes((int)new_data_size_bytes - (int)_data_size_bytes); + _data_size_bytes = new_data_size_bytes; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::update_modified +// Access: Public +// Description: Should be called (usually by a derived class) when +// the modified counter for this object has changed. +//////////////////////////////////////////////////////////////////// +INLINE void BufferContext:: +update_modified(UpdateSeq new_modified) { + _modified = new_modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::set_owning_chain +// Access: Private +// Description: Moves this object to a different BufferContextChain. +//////////////////////////////////////////////////////////////////// +INLINE void BufferContext:: +set_owning_chain(BufferContextChain *chain) { + if (chain != _owning_chain) { + --(_owning_chain->_count); + _owning_chain->adjust_bytes(-(int)_data_size_bytes); + remove_from_list(); + _owning_chain = chain; + ++(_owning_chain->_count); + _owning_chain->adjust_bytes((int)_data_size_bytes); + insert_before(_owning_chain); + } +} diff --git a/panda/src/gobj/bufferContext.cxx b/panda/src/gobj/bufferContext.cxx new file mode 100644 index 0000000000..7f53ca0078 --- /dev/null +++ b/panda/src/gobj/bufferContext.cxx @@ -0,0 +1,36 @@ +// Filename: bufferContext.cxx +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "bufferContext.h" + +TypeHandle BufferContext::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: BufferContext::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +BufferContext:: +~BufferContext() { +#ifdef DO_PSTATS + --(_owning_chain->_count); + _owning_chain->adjust_bytes(-(int)_data_size_bytes); + remove_from_list(); +#endif // DO_PSTATS + _owning_chain = NULL; +} diff --git a/panda/src/gobj/bufferContext.h b/panda/src/gobj/bufferContext.h new file mode 100644 index 0000000000..b239b40a74 --- /dev/null +++ b/panda/src/gobj/bufferContext.h @@ -0,0 +1,97 @@ +// Filename: bufferContext.h +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef BUFFERCONTEXT_H +#define BUFFERCONTEXT_H + +#include "pandabase.h" + +#include "savedContext.h" +#include "updateSeq.h" +#include "linkedListNode.h" +#include "bufferContextChain.h" +#include "bufferResidencyTracker.h" + +class PreparedGraphicsObjects; + +//////////////////////////////////////////////////////////////////// +// Class : BufferContext +// Description : This is a base class for those kinds of SavedContexts +// that occupy an easily-measured (and substantial) +// number of bytes in the video card's frame buffer +// memory or AGP memory. At the present, this includes +// most of the SavedContext types: VertexBufferContext +// and IndexBufferContext, as well as TextureContext. +// +// This class provides methods for tracking the video +// memory utilization, as well as residency of each +// object, via PStats. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA BufferContext : public SavedContext, private LinkedListNode { +public: + INLINE BufferContext(BufferResidencyTracker *residency); + virtual ~BufferContext(); + + INLINE size_t get_data_size_bytes() const; + INLINE UpdateSeq get_modified() const; + + INLINE void set_active(bool flag); + INLINE void set_resident(bool flag); + + INLINE BufferContext *get_next() const; + + INLINE void update_data_size_bytes(size_t new_data_size_bytes); + INLINE void update_modified(UpdateSeq new_modified); + +private: + INLINE void set_owning_chain(BufferContextChain *chain); + +private: + BufferResidencyTracker *_residency; + int _residency_state; + + size_t _data_size_bytes; + UpdateSeq _modified; + BufferContextChain *_owning_chain; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + SavedContext::init_type(); + register_type(_type_handle, "BufferContext", + SavedContext::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + + friend class PreparedGraphicsObjects; + friend class BufferResidencyTracker; + friend class BufferContextChain; +}; + +#include "bufferContext.I" + +#endif + diff --git a/panda/src/gobj/bufferContextChain.I b/panda/src/gobj/bufferContextChain.I new file mode 100644 index 0000000000..d9739c13ad --- /dev/null +++ b/panda/src/gobj/bufferContextChain.I @@ -0,0 +1,73 @@ +// Filename: bufferContextChain.I +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: BufferContextChain::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BufferContextChain:: +BufferContextChain() : + LinkedListNode(true), // This object is the root of a list of BufferContexts. + _total_size(0), + _count(0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContextChain::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BufferContextChain:: +~BufferContextChain() { + nassertv(_total_size == 0 && _count == 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContextChain::get_total_size +// Access: Public +// Description: Returns the total number of bytes represented by the +// BufferContexts currently assigned to this tracker. +//////////////////////////////////////////////////////////////////// +INLINE size_t BufferContextChain:: +get_total_size() const { + return _total_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContextChain::get_count +// Access: Public +// Description: Returns the total number of BufferContexts currently +// assigned to this tracker. +//////////////////////////////////////////////////////////////////// +INLINE int BufferContextChain:: +get_count() const { + return _count; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContextChain::adjust_bytes +// Access: Private +// Description: Adds or removes some from the total byte count. +//////////////////////////////////////////////////////////////////// +INLINE void BufferContextChain:: +adjust_bytes(int delta) { + _total_size += delta; +} diff --git a/panda/src/gobj/bufferContextChain.cxx b/panda/src/gobj/bufferContextChain.cxx new file mode 100755 index 0000000000..db987bf2eb --- /dev/null +++ b/panda/src/gobj/bufferContextChain.cxx @@ -0,0 +1,62 @@ +// Filename: bufferContextChain.cxx +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "bufferContextChain.h" +#include "bufferContext.h" + +//////////////////////////////////////////////////////////////////// +// Function: BufferContextChain::get_first +// Access: Public +// Description: Returns the first BufferContext object stored in the +// tracker. You can walk through the entire list of +// objects stored on the tracker by calling get_next() +// on each returned object, until the return value is +// NULL. +//////////////////////////////////////////////////////////////////// +BufferContext *BufferContextChain:: +get_first() { + // This method is declared non-inline so we can include + // bufferContext.h, which is necessary for proper downcasting of the + // _next pointer. + if (_next == this) { + return NULL; + } + return (BufferContext *)_next; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferContextChain::take_from +// Access: Public +// Description: Moves all of the BufferContexts from the other +// tracker onto this one. +//////////////////////////////////////////////////////////////////// +void BufferContextChain:: +take_from(BufferContextChain &other) { + _total_size += other._total_size; + _count += other._count; + other._total_size = 0; + other._count = 0; + + LinkedListNode *llnode = other._next; + while (llnode != &other) { + ((BufferContext *)llnode)->_owning_chain = this; + llnode = ((BufferContext *)llnode)->_next; + } + + take_list_from(&other); +} diff --git a/panda/src/gobj/bufferContextChain.h b/panda/src/gobj/bufferContextChain.h new file mode 100755 index 0000000000..c7985f1ae5 --- /dev/null +++ b/panda/src/gobj/bufferContextChain.h @@ -0,0 +1,61 @@ +// Filename: bufferContextChain.h +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef BUFFERCONTEXTCHAIN_H +#define BUFFERCONTEXTCHAIN_H + +#include "pandabase.h" +#include "linkedListNode.h" + +class BufferContext; + +//////////////////////////////////////////////////////////////////// +// Class : BufferContextChain +// Description : This class maintains a linked list of BufferContexts +// that might be allocated on the graphics card in some +// context. There is a different BufferContextChain for +// resident textures, active textures, evicted textures, +// etc. +// +// The primary purpose of this class is to facilitate +// PStats reporting of graphics memory usage. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA BufferContextChain : private LinkedListNode { +public: + INLINE BufferContextChain(); + INLINE ~BufferContextChain(); + + INLINE size_t get_total_size() const; + INLINE int get_count() const; + + BufferContext *get_first(); + + void take_from(BufferContextChain &other); + +private: + INLINE void adjust_bytes(int delta); + size_t _total_size; + int _count; + + friend class BufferContext; +}; + +#include "bufferContextChain.I" + +#endif + diff --git a/panda/src/gobj/bufferResidencyTracker.I b/panda/src/gobj/bufferResidencyTracker.I new file mode 100644 index 0000000000..c5dcf8f66c --- /dev/null +++ b/panda/src/gobj/bufferResidencyTracker.I @@ -0,0 +1,58 @@ +// Filename: bufferResidencyTracker.I +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::get_inactive_nonresident +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BufferContextChain &BufferResidencyTracker:: +get_inactive_nonresident() { + return _chains[S_inactive_nonresident]; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::get_active_nonresident +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BufferContextChain &BufferResidencyTracker:: +get_active_nonresident() { + return _chains[S_active_nonresident]; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::get_inactive_resident +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BufferContextChain &BufferResidencyTracker:: +get_inactive_resident() { + return _chains[S_inactive_resident]; +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::get_active_resident +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BufferContextChain &BufferResidencyTracker:: +get_active_resident() { + return _chains[S_active_resident]; +} diff --git a/panda/src/gobj/bufferResidencyTracker.cxx b/panda/src/gobj/bufferResidencyTracker.cxx new file mode 100644 index 0000000000..a8e32dadfc --- /dev/null +++ b/panda/src/gobj/bufferResidencyTracker.cxx @@ -0,0 +1,92 @@ +// Filename: bufferResidencyTracker.cxx +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "bufferResidencyTracker.h" +#include "clockObject.h" + +PStatCollector BufferResidencyTracker::_gmem_collector("Graphics memory"); + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +BufferResidencyTracker:: +BufferResidencyTracker(const string &pgo_name, const string &type_name) : + _pgo_collector(_gmem_collector, pgo_name), + _active_resident_collector(PStatCollector(_pgo_collector, "Active"), type_name), + _active_nonresident_collector(PStatCollector(_pgo_collector, "Thrashing"), type_name), + _inactive_resident_collector(PStatCollector(_pgo_collector, "Inactive"), type_name), + _inactive_nonresident_collector(PStatCollector(_pgo_collector, "Nonresident"), type_name), + _active_frame(0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::begin_frame +// Access: Public +// Description: To be called at the beginning of a frame, this +// initializes the active/inactive status. +//////////////////////////////////////////////////////////////////// +void BufferResidencyTracker:: +begin_frame() { +#ifdef DO_PSTATS + int this_frame = ClockObject::get_global_clock()->get_frame_count(); + if (_active_frame != this_frame) { + _active_frame = this_frame; + + // Move all of the previously "active" objects into "inactive". + // They'll get re-added to "active" as they get rendered. + move_inactive(_chains[S_inactive_nonresident], + _chains[S_active_nonresident]); + move_inactive(_chains[S_inactive_resident], + _chains[S_active_resident]); + } +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::end_frame +// Access: Public +// Description: To be called at the end of a frame, this +// updates the PStatCollectors appropriately. +//////////////////////////////////////////////////////////////////// +void BufferResidencyTracker:: +end_frame() { + _inactive_nonresident_collector.set_level(_chains[S_inactive_nonresident].get_total_size()); + _active_nonresident_collector.set_level(_chains[S_active_nonresident].get_total_size()); + _inactive_resident_collector.set_level(_chains[S_inactive_resident].get_total_size()); + _active_resident_collector.set_level(_chains[S_active_resident].get_total_size()); +} + +//////////////////////////////////////////////////////////////////// +// Function: BufferResidencyTracker::move_inactive +// Access: Private +// Description: Moves all of the "active" objects into "inactive". +//////////////////////////////////////////////////////////////////// +void BufferResidencyTracker:: +move_inactive(BufferContextChain &inactive, BufferContextChain &active) { + BufferContext *node = active.get_first(); + while (node != (BufferContext *)NULL) { + nassertv((node->_residency_state & S_active) != 0); + node->_residency_state &= ~S_active; + node = node->get_next(); + } + + inactive.take_from(active); +} diff --git a/panda/src/gobj/bufferResidencyTracker.h b/panda/src/gobj/bufferResidencyTracker.h new file mode 100644 index 0000000000..44fee92e3b --- /dev/null +++ b/panda/src/gobj/bufferResidencyTracker.h @@ -0,0 +1,92 @@ +// Filename: bufferResidencyTracker.h +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef BUFFERRESIDENCYTRACKER_H +#define BUFFERRESIDENCYTRACKER_H + +#include "pandabase.h" +#include "bufferContextChain.h" +#include "pStatCollector.h" + +class BufferContext; + +//////////////////////////////////////////////////////////////////// +// Class : BufferResidencyTracker +// Description : This class is used to keep track of the current state +// of all the BufferContexts for a particular graphics +// context: whether each one is active (rendered this +// frame) or inactive (not rendered this frame), and +// whether it is resident or nonresident in video +// memory. +// +// The primary purpose of this class is to facilitate +// PStats reporting of video card memory usage. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA BufferResidencyTracker { +public: + BufferResidencyTracker(const string &pgo_name, const string &type_name); + + void begin_frame(); + void end_frame(); + + INLINE BufferContextChain &get_inactive_nonresident(); + INLINE BufferContextChain &get_active_nonresident(); + INLINE BufferContextChain &get_inactive_resident(); + INLINE BufferContextChain &get_active_resident(); + +private: + void move_inactive(BufferContextChain &inactive, BufferContextChain &active); + +private: + enum State { + // Individual bits. + S_active = 0x01, + S_resident = 0x02, + + // Aggregate bits: unions of the above. + S_inactive_nonresident = 0x00, + S_active_nonresident = 0x01, + S_inactive_resident = 0x02, + S_active_resident = 0x03, + + // The total number of different states. + S_num_states = 4, + }; + + // One chain for each of the possible states, ordered as above. + BufferContextChain _chains[S_num_states]; + + // A couple of PStatCollectors just to organize names. + static PStatCollector _gmem_collector; + PStatCollector _pgo_collector; + + // One PStatCollector for each state. These are ordered in reverse + // order that we would like them to appear in the PStats graph. + PStatCollector _active_resident_collector; + PStatCollector _active_nonresident_collector; + PStatCollector _inactive_resident_collector; + PStatCollector _inactive_nonresident_collector; + + // The frame number currently considered "active". + int _active_frame; + friend class BufferContext; +}; + +#include "bufferResidencyTracker.I" + +#endif diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 190dae0911..dd9b65cabc 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -16,6 +16,7 @@ // //////////////////////////////////////////////////////////////////// +#include "bufferContext.h" #include "config_util.h" #include "config_gobj.h" #include "geom.h" @@ -238,6 +239,7 @@ ConfigVariableDouble default_keystone ConfigureFn(config_gobj) { + BufferContext::init_type(); Geom::init_type(); GeomMunger::init_type(); GeomPrimitive::init_type(); diff --git a/panda/src/gobj/gobj_composite1.cxx b/panda/src/gobj/gobj_composite1.cxx index 453cd874a8..80609e645f 100644 --- a/panda/src/gobj/gobj_composite1.cxx +++ b/panda/src/gobj/gobj_composite1.cxx @@ -1,4 +1,6 @@ - +#include "bufferContext.cxx" +#include "bufferContextChain.cxx" +#include "bufferResidencyTracker.cxx" #include "geom.cxx" #include "geomContext.cxx" #include "geomEnums.cxx" diff --git a/panda/src/gobj/indexBufferContext.I b/panda/src/gobj/indexBufferContext.I index 18a65a4149..d647e00bbc 100644 --- a/panda/src/gobj/indexBufferContext.I +++ b/panda/src/gobj/indexBufferContext.I @@ -23,11 +23,9 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE IndexBufferContext:: -IndexBufferContext(GeomPrimitive *data) : - _data(data), - // Initially, the number of bytes is zero, until the data has been - // loaded (and mark_loaded() is called). - _data_size_bytes(0) +IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data) : + BufferContext(&pgo->_ibuffer_residency), + _data(data) { } @@ -42,19 +40,6 @@ get_data() const { return _data; } -//////////////////////////////////////////////////////////////////// -// Function: IndexBufferContext::get_data_size_bytes -// Access: Public -// Description: Returns the number of bytes previously reported for -// the data object. This is used to track changes in -// the data object's allocated size; if it changes from -// this, we need to create a new buffer. -//////////////////////////////////////////////////////////////////// -INLINE int IndexBufferContext:: -get_data_size_bytes() const { - return _data_size_bytes; -} - //////////////////////////////////////////////////////////////////// // Function: IndexBufferContext::changed_size // Access: Public @@ -63,7 +48,7 @@ get_data_size_bytes() const { //////////////////////////////////////////////////////////////////// INLINE bool IndexBufferContext:: changed_size() const { - return get_data_size_bytes() != _data->get_data_size_bytes(); + return get_data_size_bytes() != (size_t)_data->get_data_size_bytes(); } //////////////////////////////////////////////////////////////////// @@ -85,18 +70,7 @@ changed_usage_hint() const { //////////////////////////////////////////////////////////////////// INLINE bool IndexBufferContext:: was_modified() const { - return _modified != _data->get_modified(); -} - -//////////////////////////////////////////////////////////////////// -// Function: IndexBufferContext::get_modified -// Access: Public -// Description: Returns the UpdateSeq that was recorded the last time -// mark_loaded() was called. -//////////////////////////////////////////////////////////////////// -INLINE UpdateSeq IndexBufferContext:: -get_modified() const { - return _modified; + return get_modified() != _data->get_modified(); } //////////////////////////////////////////////////////////////////// @@ -108,7 +82,10 @@ get_modified() const { //////////////////////////////////////////////////////////////////// INLINE void IndexBufferContext:: mark_loaded() { - _data_size_bytes = _data->get_data_size_bytes(); + update_data_size_bytes(_data->get_data_size_bytes()); + update_modified(_data->get_modified()); _usage_hint = _data->get_usage_hint(); - _modified = _data->get_modified(); + + // Assume the buffer is now resident. + set_resident(true); } diff --git a/panda/src/gobj/indexBufferContext.h b/panda/src/gobj/indexBufferContext.h index 3bd81838af..dbbb1e67a9 100644 --- a/panda/src/gobj/indexBufferContext.h +++ b/panda/src/gobj/indexBufferContext.h @@ -21,9 +21,9 @@ #include "pandabase.h" -#include "savedContext.h" -#include "updateSeq.h" +#include "bufferContext.h" #include "geomPrimitive.h" +#include "preparedGraphicsObjects.h" //////////////////////////////////////////////////////////////////// // Class : IndexBufferContext @@ -36,17 +36,15 @@ // allocate a vertex buffer for the array. OpenGL can // create a buffer object. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA IndexBufferContext : public SavedContext { +class EXPCL_PANDA IndexBufferContext : public BufferContext { public: - INLINE IndexBufferContext(GeomPrimitive *data); + INLINE IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data); INLINE GeomPrimitive *get_data() const; - INLINE int get_data_size_bytes() const; INLINE bool changed_size() const; INLINE bool changed_usage_hint() const; INLINE bool was_modified() const; - INLINE UpdateSeq get_modified() const; INLINE void mark_loaded(); @@ -55,8 +53,6 @@ private: // the GSG both own their IndexBufferContexts! That would create a // circular reference count. GeomPrimitive *_data; - UpdateSeq _modified; - int _data_size_bytes; GeomEnums::UsageHint _usage_hint; public: @@ -64,9 +60,9 @@ public: return _type_handle; } static void init_type() { - SavedContext::init_type(); + BufferContext::init_type(); register_type(_type_handle, "IndexBufferContext", - SavedContext::get_class_type()); + BufferContext::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/gobj/preparedGraphicsObjects.I b/panda/src/gobj/preparedGraphicsObjects.I index 9b6ec4d189..83dca00140 100644 --- a/panda/src/gobj/preparedGraphicsObjects.I +++ b/panda/src/gobj/preparedGraphicsObjects.I @@ -17,6 +17,18 @@ //////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +// Function: PreparedGraphicsObjects::get_name +// Access: Public +// Description: Returns the name of the PreparedGraphicsObjects +// structure. This is an arbitrary name that serves +// mainly to uniquify the context for PStats reporting. +//////////////////////////////////////////////////////////////////// +INLINE const string &PreparedGraphicsObjects:: +get_name() const { + return _name; +} + //////////////////////////////////////////////////////////////////// // Function: PreparedGraphicsObjects::release_all // Access: Public diff --git a/panda/src/gobj/preparedGraphicsObjects.cxx b/panda/src/gobj/preparedGraphicsObjects.cxx index abb1908056..5d3e1e7e96 100644 --- a/panda/src/gobj/preparedGraphicsObjects.cxx +++ b/panda/src/gobj/preparedGraphicsObjects.cxx @@ -27,8 +27,7 @@ #include "shaderExpansion.h" #include "reMutexHolder.h" -PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage"); -PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffer size"); +int PreparedGraphicsObjects::_name_index = 0; //////////////////////////////////////////////////////////////////// // Function: PreparedGraphicsObjects::Constructor @@ -36,7 +35,12 @@ PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffer // Description: //////////////////////////////////////////////////////////////////// PreparedGraphicsObjects:: -PreparedGraphicsObjects() { +PreparedGraphicsObjects() : + _name(init_name()), + _texture_residency(_name, "texture"), + _vbuffer_residency(_name, "vbuffer"), + _ibuffer_residency(_name, "ibuffer") +{ } //////////////////////////////////////////////////////////////////// @@ -58,8 +62,7 @@ PreparedGraphicsObjects:: tci != _prepared_textures.end(); ++tci) { TextureContext *tc = (*tci); - _total_texusage_pcollector.sub_level(tc->estimate_texture_memory()); - tc->_texture->clear_prepared(this); + tc->get_texture()->clear_prepared(this); } _prepared_textures.clear(); @@ -95,7 +98,6 @@ PreparedGraphicsObjects:: vbci != _prepared_vertex_buffers.end(); ++vbci) { VertexBufferContext *vbc = (*vbci); - _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes()); vbc->_data->clear_prepared(this); } @@ -108,7 +110,6 @@ PreparedGraphicsObjects:: ibci != _prepared_index_buffers.end(); ++ibci) { IndexBufferContext *ibc = (*ibci); - _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes()); ibc->_data->clear_prepared(this); } @@ -175,8 +176,7 @@ void PreparedGraphicsObjects:: release_texture(TextureContext *tc) { ReMutexHolder holder(_lock); - tc->_texture->clear_prepared(this); - _total_texusage_pcollector.sub_level(tc->estimate_texture_memory()); + tc->get_texture()->clear_prepared(this); // We have to set the Texture pointer to NULL at this point, since // the Texture itself might destruct at any time after it has been @@ -208,8 +208,7 @@ release_all_textures() { tci != _prepared_textures.end(); ++tci) { TextureContext *tc = (*tci); - tc->_texture->clear_prepared(this); - _total_texusage_pcollector.sub_level(tc->estimate_texture_memory()); + tc->get_texture()->clear_prepared(this); tc->_texture = (Texture *)NULL; _released_textures.insert(tc); @@ -255,8 +254,6 @@ prepare_texture_now(Texture *tex, GraphicsStateGuardianBase *gsg) { if (tc != (TextureContext *)NULL) { bool prepared = _prepared_textures.insert(tc).second; nassertr(prepared, tc); - - _total_texusage_pcollector.add_level(tc->estimate_texture_memory()); } return tc; @@ -600,7 +597,6 @@ release_vertex_buffer(VertexBufferContext *vbc) { ReMutexHolder holder(_lock); vbc->_data->clear_prepared(this); - _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes()); // We have to set the Data pointer to NULL at this point, since // the Data itself might destruct at any time after it has been @@ -633,7 +629,6 @@ release_all_vertex_buffers() { ++vbci) { VertexBufferContext *vbc = (*vbci); vbc->_data->clear_prepared(this); - _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes()); vbc->_data = (GeomVertexArrayData *)NULL; _released_vertex_buffers.insert(vbc); @@ -679,11 +674,6 @@ prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase * if (vbc != (VertexBufferContext *)NULL) { bool prepared = _prepared_vertex_buffers.insert(vbc).second; nassertr(prepared, vbc); - - // The size has already been counted by - // GraphicsStateGuardian::add_to_vertex_buffer_record(); we don't need to - // count it again here. - //_total_buffers_pcollector.add_level(vbc->get_data_size_bytes()); } return vbc; @@ -747,7 +737,6 @@ release_index_buffer(IndexBufferContext *ibc) { ReMutexHolder holder(_lock); ibc->_data->clear_prepared(this); - _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes()); // We have to set the Data pointer to NULL at this point, since // the Data itself might destruct at any time after it has been @@ -780,7 +769,6 @@ release_all_index_buffers() { ++ibci) { IndexBufferContext *ibc = (*ibci); ibc->_data->clear_prepared(this); - _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes()); ibc->_data = (GeomPrimitive *)NULL; _released_index_buffers.insert(ibc); @@ -826,22 +814,17 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) { if (ibc != (IndexBufferContext *)NULL) { bool prepared = _prepared_index_buffers.insert(ibc).second; nassertr(prepared, ibc); - - // The size has already been counted by - // GraphicsStateGuardian::add_to_index_buffer_record(); we don't need to - // count it again here. - //_total_buffers_pcollector.add_level(ibc->get_data_size_bytes()); } return ibc; } //////////////////////////////////////////////////////////////////// -// Function: PreparedGraphicsObjects::update +// Function: PreparedGraphicsObjects::begin_frame // Access: Public // Description: This is called by the GraphicsStateGuardian to -// indicate that it is in a state to load or release -// textures. +// indicate that it is about to begin processing of the +// frame. // // Any texture contexts that were previously passed to // release_texture() are actually passed to the GSG to @@ -849,7 +832,7 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) { // passed to prepare_texture are actually loaded. //////////////////////////////////////////////////////////////////// void PreparedGraphicsObjects:: -update(GraphicsStateGuardianBase *gsg) { +begin_frame(GraphicsStateGuardianBase *gsg) { ReMutexHolder holder(_lock); // First, release all the textures, geoms, and buffers awaiting @@ -904,6 +887,11 @@ update(GraphicsStateGuardianBase *gsg) { _released_index_buffers.clear(); + // Reset the residency trackers. + _texture_residency.begin_frame(); + _vbuffer_residency.begin_frame(); + _ibuffer_residency.begin_frame(); + // Now prepare all the textures, geoms, and buffers awaiting // preparation. EnqueuedTextures::iterator qti; @@ -956,3 +944,33 @@ update(GraphicsStateGuardianBase *gsg) { _enqueued_index_buffers.clear(); } + +//////////////////////////////////////////////////////////////////// +// Function: PreparedGraphicsObjects::end_frame +// Access: Public +// Description: This is called by the GraphicsStateGuardian to +// indicate that it has finished processing of the +// frame. +//////////////////////////////////////////////////////////////////// +void PreparedGraphicsObjects:: +end_frame() { + ReMutexHolder holder(_lock); + + _texture_residency.end_frame(); + _vbuffer_residency.end_frame(); + _ibuffer_residency.end_frame(); +} + +//////////////////////////////////////////////////////////////////// +// Function: PreparedGraphicsObjects::init_name +// Access: Private, Static +// Description: Returns a new, unique name for a newly-constructed +// object. +//////////////////////////////////////////////////////////////////// +string PreparedGraphicsObjects:: +init_name() { + ++_name_index; + ostringstream strm; + strm << "context" << _name_index; + return strm.str(); +} diff --git a/panda/src/gobj/preparedGraphicsObjects.h b/panda/src/gobj/preparedGraphicsObjects.h index a20154db36..89b3edd000 100644 --- a/panda/src/gobj/preparedGraphicsObjects.h +++ b/panda/src/gobj/preparedGraphicsObjects.h @@ -30,6 +30,7 @@ #include "pStatCollector.h" #include "pset.h" #include "reMutex.h" +#include "bufferResidencyTracker.h" class TextureContext; class GeomContext; @@ -62,6 +63,8 @@ public: PreparedGraphicsObjects(); ~PreparedGraphicsObjects(); + INLINE const string &get_name() const; + INLINE void release_all(); void enqueue_texture(Texture *tex); @@ -103,7 +106,11 @@ public: prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg); - void update(GraphicsStateGuardianBase *gsg); + void begin_frame(GraphicsStateGuardianBase *gsg); + void end_frame(); + +private: + static string init_name(); private: typedef phash_set Textures; @@ -118,6 +125,7 @@ private: typedef phash_set< PT(GeomPrimitive) > EnqueuedIndexBuffers; ReMutex _lock; + string _name; Textures _prepared_textures, _released_textures; EnqueuedTextures _enqueued_textures; Geoms _prepared_geoms, _released_geoms; @@ -129,8 +137,13 @@ private: IndexBuffers _prepared_index_buffers, _released_index_buffers; EnqueuedIndexBuffers _enqueued_index_buffers; - static PStatCollector _total_texusage_pcollector; - static PStatCollector _total_buffers_pcollector; +public: + BufferResidencyTracker _texture_residency; + BufferResidencyTracker _vbuffer_residency; + BufferResidencyTracker _ibuffer_residency; + +private: + static int _name_index; friend class GraphicsStateGuardian; }; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 1b05eba9a6..0b0cee37cb 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -542,6 +542,18 @@ set_keep_ram_image(bool keep_ram_image) { _keep_ram_image = keep_ram_image; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_modified +// Access: Published +// Description: Returns a sequence number which is guaranteed to +// change at least every time the texture data or +// properties are modified. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq Texture:: +get_modified() const { + return _modified; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::set_filename // Access: Published diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 1b8c2c4dbc..ce85034adb 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -61,7 +61,6 @@ Texture(const string &name) : _wrap_w = WM_repeat; _anisotropic_degree = 1; _keep_ram_image = true; - _all_dirty_flags = 0; _border_color.set(0.0f, 0.0f, 0.0f, 1.0f); _compression = CM_default; _ram_image_compression = CM_off; @@ -115,7 +114,6 @@ Texture(const Texture ©) : _border_color(copy._border_color), _compression(copy._compression), _match_framebuffer_format(copy._match_framebuffer_format), - _all_dirty_flags(0), _ram_image(copy._ram_image), _ram_image_compression(copy._ram_image_compression), _ram_page_size(copy._ram_page_size) @@ -157,10 +155,10 @@ operator = (const Texture ©) { _border_color = copy._border_color; _compression = copy._compression; _match_framebuffer_format = copy._match_framebuffer_format; - _all_dirty_flags = 0; _ram_image = copy._ram_image; _ram_image_compression = copy._ram_image_compression; _ram_page_size = copy._ram_page_size; + ++_modified; } //////////////////////////////////////////////////////////////////// @@ -915,7 +913,7 @@ load(const PNMImage &pnmimage, int z) { nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false); } - mark_dirty(DF_image); + ++_modified; return true; } @@ -1037,7 +1035,7 @@ load_related(const PT(InternalName) &suffix) const { void Texture:: set_wrap_u(Texture::WrapMode wrap) { if (_wrap_u != wrap) { - mark_dirty(DF_wrap); + ++_modified; _wrap_u = wrap; } } @@ -1050,7 +1048,7 @@ set_wrap_u(Texture::WrapMode wrap) { void Texture:: set_wrap_v(Texture::WrapMode wrap) { if (_wrap_v != wrap) { - mark_dirty(DF_wrap); + ++_modified; _wrap_v = wrap; } } @@ -1063,7 +1061,7 @@ set_wrap_v(Texture::WrapMode wrap) { void Texture:: set_wrap_w(Texture::WrapMode wrap) { if (_wrap_w != wrap) { - mark_dirty(DF_wrap); + ++_modified; _wrap_w = wrap; } } @@ -1076,11 +1074,7 @@ set_wrap_w(Texture::WrapMode wrap) { void Texture:: set_minfilter(Texture::FilterType filter) { if (_minfilter != filter) { - if (is_mipmap(_minfilter) != is_mipmap(filter)) { - mark_dirty(DF_filter | DF_mipmap); - } else { - mark_dirty(DF_filter); - } + ++_modified; _minfilter = filter; } } @@ -1093,7 +1087,7 @@ set_minfilter(Texture::FilterType filter) { void Texture:: set_magfilter(Texture::FilterType filter) { if (_magfilter != filter) { - mark_dirty(DF_filter); + ++_modified; _magfilter = filter; } } @@ -1110,7 +1104,7 @@ set_magfilter(Texture::FilterType filter) { void Texture:: set_anisotropic_degree(int anisotropic_degree) { if (_anisotropic_degree != anisotropic_degree) { - mark_dirty(DF_filter); + ++_modified; _anisotropic_degree = anisotropic_degree; } } @@ -1126,7 +1120,7 @@ set_anisotropic_degree(int anisotropic_degree) { void Texture:: set_border_color(const Colorf &color) { if (_border_color != color) { - mark_dirty(DF_border); + ++_modified; _border_color = color; } } @@ -1153,7 +1147,7 @@ set_border_color(const Colorf &color) { void Texture:: set_compression(Texture::CompressionMode compression) { if (_compression != compression) { - mark_dirty(DF_image); + ++_modified; _compression = compression; } } @@ -1254,7 +1248,7 @@ modify_ram_image() { make_ram_image(); } - mark_dirty(DF_image); + ++_modified; _keep_ram_image = true; return _ram_image; } @@ -1272,7 +1266,7 @@ PTA_uchar Texture:: make_ram_image() { _ram_image = PTA_uchar::empty_array(get_expected_ram_image_size()); _ram_image_compression = CM_off; - mark_dirty(DF_image); + ++_modified; _keep_ram_image = true; return _ram_image; } @@ -1299,7 +1293,7 @@ set_ram_image(PTA_uchar image, Texture::CompressionMode compression, if (page_size == 0) { _ram_page_size = image.size(); } - mark_dirty(DF_image); + ++_modified; } _keep_ram_image = true; } @@ -1685,12 +1679,6 @@ prepare_now(PreparedGraphicsObjects *prepared_objects, _contexts[prepared_objects] = tc; if (tc != (TextureContext *)NULL) { - // Now that we have a new TextureContext with zero dirty flags, our - // intersection of all dirty flags must be zero. This doesn't mean - // that some other contexts aren't still dirty, but at least one - // context isn't. - _all_dirty_flags = 0; - if (!keep_texture_ram && !_keep_ram_image) { // Once we have prepared the texture, we can generally safely // remove the pixels from main RAM. The GSG is now responsible @@ -1706,41 +1694,6 @@ prepare_now(PreparedGraphicsObjects *prepared_objects, return tc; } -//////////////////////////////////////////////////////////////////// -// Function: Texture::mark_dirty -// Access: Public -// Description: Sets the indicated dirty bits on for all texture -// contexts that share this Texture. Does not change -// the bits that are not on. This presumably will -// inform the GSG that the texture properties have -// changed. See also TextureContext::mark_dirty(). -// -// Normally, this does not need to be called directly; -// changing the properties on the texture will -// automatically call this. However, if you fiddle with -// the texture image directly, you may need to -// explicitly call mark_dirty(Texture::DF_image). -//////////////////////////////////////////////////////////////////// -void Texture:: -mark_dirty(int flags_to_set) { - if ((_all_dirty_flags & flags_to_set) == flags_to_set) { - // If all the texture contexts already share these bits, no need - // to do anything else. - return; - } - - // Otherwise, iterate through the contexts and mark them all dirty. - Contexts::iterator ci; - for (ci = _contexts.begin(); ci != _contexts.end(); ++ci) { - TextureContext *tc = (*ci).second; - if (tc != (TextureContext *)NULL) { - tc->mark_dirty(flags_to_set); - } - } - - _all_dirty_flags |= flags_to_set; -} - //////////////////////////////////////////////////////////////////// // Function: Texture::has_cull_callback // Access: Public, Virtual diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index e74a85dda1..13cfe49afc 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -26,6 +26,7 @@ #include "namable.h" #include "internalName.h" #include "graphicsStateGuardianBase.h" +#include "updateSeq.h" #include "pmap.h" class PNMImage; @@ -267,6 +268,8 @@ PUBLISHED: INLINE void set_keep_ram_image(bool keep_ram_image); virtual bool get_keep_ram_image() const; + INLINE UpdateSeq get_modified() const; + void prepare(PreparedGraphicsObjects *prepared_objects); bool release(PreparedGraphicsObjects *prepared_objects); int release_all(); @@ -307,19 +310,6 @@ public: TextureContext *prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg); - // These bits are used as parameters to Texture::mark_dirty() and - // also TextureContext::mark_dirty() (and related functions in - // TextureContext). - enum DirtyFlags { - DF_image = 0x001, // The image pixels have changed. - DF_wrap = 0x002, // The wrap properties have changed. - DF_filter = 0x004, // The minfilter or magfilter have changed. - DF_mipmap = 0x008, // The use of mipmaps or not has changed. - DF_border = 0x010, // The border has changed. - }; - - void mark_dirty(int flags_to_set); - virtual bool has_cull_callback() const; virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; @@ -415,15 +405,11 @@ protected: typedef pmap RelatedTextures; RelatedTextures _related_textures; - // This value represents the intersection of all the dirty flags of - // the various TextureContexts that might be associated with this - // texture. - int _all_dirty_flags; - PTA_uchar _ram_image; CompressionMode _ram_image_compression; size_t _ram_page_size; + UpdateSeq _modified; // Datagram stuff public: diff --git a/panda/src/gobj/textureContext.I b/panda/src/gobj/textureContext.I index 3908e60b54..5c1bb4066d 100644 --- a/panda/src/gobj/textureContext.I +++ b/panda/src/gobj/textureContext.I @@ -23,70 +23,49 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE TextureContext:: -TextureContext(Texture *tex) : +TextureContext(PreparedGraphicsObjects *pgo, Texture *tex) : + BufferContext(&pgo->_texture_residency), _texture(tex) { - _dirty_flags = ~0; +#ifdef DO_PSTATS + update_data_size_bytes(estimate_texture_memory()); +#endif } //////////////////////////////////////////////////////////////////// -// Function: TextureContext::mark_dirty +// Function: TextureContext::get_texture // Access: Public -// Description: Marks the context "dirty", i.e. its properties are -// different from the last time the GSG has seen them. -// Presumably, the GSG will respond by updating the -// properties and clearing the dirty bits the next time -// it renders the texture. -// -// The value is the union of all the bits that are to be -// set dirty; bits that are not set in this parameter -// are left unchanged. See Texture::DirtyFlags for a -// list of available bits. -// -// Usually this function is not called directly, but -// rather is called by Texture::mark_dirty() as a result -// of changing properties directly on the texture. +// Description: Returns the pointer to the associated Texture +// object. +//////////////////////////////////////////////////////////////////// +INLINE Texture *TextureContext:: +get_texture() const { + return _texture; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureContext::was_modified +// Access: Public +// Description: Returns true if the texture has been modified since the +// last time mark_loaded() was called. +//////////////////////////////////////////////////////////////////// +INLINE bool TextureContext:: +was_modified() const { + return get_modified() != _texture->get_modified(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureContext::mark_loaded +// Access: Public +// Description: Should be called after the TextureContext has been +// loaded into graphics memory, this updates the +// internal flags for changed_size() and modified(). //////////////////////////////////////////////////////////////////// INLINE void TextureContext:: -mark_dirty(int flags_to_set) { - _dirty_flags |= flags_to_set; -} +mark_loaded() { + // _data_size_bytes = _data->get_texture_size_bytes(); + update_modified(_texture->get_modified()); -//////////////////////////////////////////////////////////////////// -// Function: TextureContext::clear_dirty_flags -// Access: Public -// Description: Removes the indicated flags from the "dirty" bits. -// See mark_dirty(). -// -// The value is the union of all the bits that are to be -// cleared; if a bit is set in the parameter, it will be -// removed from the dirty set. Bits that are not set in -// this parameter are left unchanged. -// -// This function is intended to be called by the GSG -// after it has updated the texture parameters. -//////////////////////////////////////////////////////////////////// -INLINE void TextureContext:: -clear_dirty_flags(int flags_to_clear) { - _dirty_flags &= ~flags_to_clear; - _texture->_all_dirty_flags &= ~flags_to_clear; + // Assume the texture is now resident. + set_resident(true); } - -//////////////////////////////////////////////////////////////////// -// Function: TextureContext::get_dirty_flags -// Access: Public -// Description: Returns the current state of the dirty flags. If -// this is non-zero, it represents the union of all -// properties that have been changed since the last call -// to clear_dirty_flags(). -// -// This function is intended to be called by the GSG to -// determine what properties need to be updated. See -// Texture::DirtyFlags for a list of possible bits. -//////////////////////////////////////////////////////////////////// -INLINE int TextureContext:: -get_dirty_flags() const { - _texture->reconsider_dirty(); - return _dirty_flags; -} - diff --git a/panda/src/gobj/textureContext.h b/panda/src/gobj/textureContext.h index 006e64b149..074c963f13 100644 --- a/panda/src/gobj/textureContext.h +++ b/panda/src/gobj/textureContext.h @@ -21,8 +21,9 @@ #include "pandabase.h" -#include "savedContext.h" +#include "bufferContext.h" #include "texture.h" +#include "preparedGraphicsObjects.h" //////////////////////////////////////////////////////////////////// // Class : TextureContext @@ -37,33 +38,31 @@ // texture and store it here. The texture stores all of // these handles internally. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA TextureContext : public SavedContext { +class EXPCL_PANDA TextureContext : public BufferContext { public: - INLINE TextureContext(Texture *tex); + INLINE TextureContext(PreparedGraphicsObjects *pgo, Texture *tex); + + INLINE Texture *get_texture() const; + + INLINE bool was_modified() const; + INLINE void mark_loaded(); virtual size_t estimate_texture_memory(); +private: // This cannot be a PT(Texture), because the texture and the GSG // both own their TextureContexts! That would create a circular // reference count. Texture *_texture; - - INLINE void mark_dirty(int flags_to_set); - INLINE void clear_dirty_flags(int flags_to_clear = ~0); - INLINE int get_dirty_flags() const; - -private: - int _dirty_flags; - - + public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - SavedContext::init_type(); + BufferContext::init_type(); register_type(_type_handle, "TextureContext", - SavedContext::get_class_type()); + BufferContext::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); @@ -72,6 +71,8 @@ public: private: static TypeHandle _type_handle; + + friend class PreparedGraphicsObjects; }; #include "textureContext.I" diff --git a/panda/src/gobj/vertexBufferContext.I b/panda/src/gobj/vertexBufferContext.I index c60cf88dcc..155c766703 100644 --- a/panda/src/gobj/vertexBufferContext.I +++ b/panda/src/gobj/vertexBufferContext.I @@ -23,11 +23,9 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE VertexBufferContext:: -VertexBufferContext(GeomVertexArrayData *data) : - _data(data), - // Initially, the number of bytes is zero, until the data has been - // loaded (and mark_loaded() is called). - _data_size_bytes(0) +VertexBufferContext(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) : + BufferContext(&pgo->_vbuffer_residency), + _data(data) { } @@ -42,19 +40,6 @@ get_data() const { return _data; } -//////////////////////////////////////////////////////////////////// -// Function: VertexBufferContext::get_data_size_bytes -// Access: Public -// Description: Returns the number of bytes previously reported for -// the data object. This is used to track changes in -// the data object's allocated size; if it changes from -// this, we need to create a new buffer. -//////////////////////////////////////////////////////////////////// -INLINE int VertexBufferContext:: -get_data_size_bytes() const { - return _data_size_bytes; -} - //////////////////////////////////////////////////////////////////// // Function: VertexBufferContext::changed_size // Access: Public @@ -63,7 +48,7 @@ get_data_size_bytes() const { //////////////////////////////////////////////////////////////////// INLINE bool VertexBufferContext:: changed_size() const { - return get_data_size_bytes() != _data->get_data_size_bytes(); + return get_data_size_bytes() != (size_t)_data->get_data_size_bytes(); } //////////////////////////////////////////////////////////////////// @@ -85,18 +70,7 @@ changed_usage_hint() const { //////////////////////////////////////////////////////////////////// INLINE bool VertexBufferContext:: was_modified() const { - return _modified != _data->get_modified(); -} - -//////////////////////////////////////////////////////////////////// -// Function: VertexBufferContext::get_modified -// Access: Public -// Description: Returns the UpdateSeq that was recorded the last time -// mark_loaded() was called. -//////////////////////////////////////////////////////////////////// -INLINE UpdateSeq VertexBufferContext:: -get_modified() const { - return _modified; + return get_modified() != _data->get_modified(); } //////////////////////////////////////////////////////////////////// @@ -108,7 +82,10 @@ get_modified() const { //////////////////////////////////////////////////////////////////// INLINE void VertexBufferContext:: mark_loaded() { - _data_size_bytes = _data->get_data_size_bytes(); + update_data_size_bytes(_data->get_data_size_bytes()); + update_modified(_data->get_modified()); _usage_hint = _data->get_usage_hint(); - _modified = _data->get_modified(); + + // Assume the buffer is now resident. + set_resident(true); } diff --git a/panda/src/gobj/vertexBufferContext.h b/panda/src/gobj/vertexBufferContext.h index f0df684c8c..cac9292dcc 100644 --- a/panda/src/gobj/vertexBufferContext.h +++ b/panda/src/gobj/vertexBufferContext.h @@ -21,9 +21,9 @@ #include "pandabase.h" -#include "savedContext.h" -#include "updateSeq.h" +#include "bufferContext.h" #include "geomVertexArrayData.h" +#include "preparedGraphicsObjects.h" //////////////////////////////////////////////////////////////////// // Class : VertexBufferContext @@ -36,17 +36,16 @@ // allocate a vertex buffer for the array. OpenGL can // create a buffer object. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA VertexBufferContext : public SavedContext { +class EXPCL_PANDA VertexBufferContext : public BufferContext { public: - INLINE VertexBufferContext(GeomVertexArrayData *data); + INLINE VertexBufferContext(PreparedGraphicsObjects *pgo, + GeomVertexArrayData *data); INLINE GeomVertexArrayData *get_data() const; - INLINE int get_data_size_bytes() const; INLINE bool changed_size() const; INLINE bool changed_usage_hint() const; INLINE bool was_modified() const; - INLINE UpdateSeq get_modified() const; INLINE void mark_loaded(); @@ -55,8 +54,6 @@ private: // the GSG both own their VertexBufferContexts! That would create a // circular reference count. GeomVertexArrayData *_data; - UpdateSeq _modified; - int _data_size_bytes; GeomEnums::UsageHint _usage_hint; public: @@ -64,9 +61,9 @@ public: return _type_handle; } static void init_type() { - SavedContext::init_type(); + BufferContext::init_type(); register_type(_type_handle, "VertexBufferContext", - SavedContext::get_class_type()); + BufferContext::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index a482a51424..88422dd665 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -154,21 +154,7 @@ static TimeCollectorProperties time_properties[] = { }; static LevelCollectorProperties level_properties[] = { - { 1, "Texture usage", { 1.0, 0.0, 0.5 }, "MB", 12, 1048576 }, - { 1, "Texture usage:Active", { 0.5, 1.0, 0.8 } }, - { 1, "Texture memory", { 0.0, 0.0, 1.0 }, "MB", 12, 1048576 }, - { 1, "Texture memory:In use", { 0.0, 1.0, 1.0 } }, - { 1, "Texture manager", { 1.0, 0.0, 0.0 }, "MB", 12, 1048576 }, - { 1, "Texture manager:Resident", { 1.0, 1.0, 0.0 } }, - { 1, "Prepared Textures", { 0.6, 0.8, 0.0 }, "", 500 }, - { 1, "Prepared Textures:Active", { 0.0, 0.6, 0.8 } }, - { 1, "Prepared Geoms", { 1.0, 0.0, 0.5 }, "", 500 }, - { 1, "Prepared Geoms:Active", { 0.5, 1.0, 0.8 } }, - { 1, "Prepared GeomNodes", { 1.0, 0.0, 0.5 }, "", 500 }, - { 1, "Prepared GeomNodes:Active", { 0.5, 1.0, 0.8 } }, - { 1, "Vertex buffer size", { 0.0, 0.0, 1.0 }, "MB", 12, 1048576 }, - { 1, "Vertex buffer size:Active vertex", { 1.0, 0.0, 0.5 } }, - { 1, "Vertex buffer size:Active index" , { 0.5, 0.6, 1.0 } }, + { 1, "Graphics memory", { 0.0, 0.0, 1.0 }, "MB", 64, 1048576 }, { 1, "Vertex buffer switch", { 0.0, 0.6, 0.8 }, "", 500 }, { 1, "Vertex buffer switch:Vertex", { 0.8, 0.0, 0.6 } }, { 1, "Vertex buffer switch:Index", { 0.8, 0.6, 0.3 } }, diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index 7ec6a9c17a..cf50d46232 100644 --- a/panda/src/putil/Sources.pp +++ b/panda/src/putil/Sources.pp @@ -39,6 +39,7 @@ ioPtaDatagramFloat.h ioPtaDatagramInt.h \ ioPtaDatagramShort.h keyboardButton.h lineStream.I \ lineStream.h lineStreamBuf.I lineStreamBuf.h \ + linkedListNode.I linkedListNode.h \ load_prc_file.h \ modifierButtons.I modifierButtons.h mouseButton.h \ mouseData.I mouseData.h nameUniquifier.I nameUniquifier.h \ @@ -75,6 +76,7 @@ ioPtaDatagramFloat.cxx \ ioPtaDatagramInt.cxx ioPtaDatagramShort.cxx \ keyboardButton.cxx lineStream.cxx lineStreamBuf.cxx \ + linkedListNode.cxx \ load_prc_file.cxx \ modifierButtons.cxx mouseButton.cxx mouseData.cxx \ nameUniquifier.cxx \ @@ -119,6 +121,7 @@ ioPtaDatagramFloat.h ioPtaDatagramInt.h \ ioPtaDatagramShort.h iterator_types.h keyboardButton.h lineStream.I \ lineStream.h lineStreamBuf.I lineStreamBuf.h \ + linkedListNode.I linkedListNode.h \ load_prc_file.h \ modifierButtons.I \ modifierButtons.h mouseButton.h mouseData.I mouseData.h \ diff --git a/panda/src/putil/linkedListNode.I b/panda/src/putil/linkedListNode.I new file mode 100644 index 0000000000..25a2c8948d --- /dev/null +++ b/panda/src/putil/linkedListNode.I @@ -0,0 +1,108 @@ +// Filename: linkedListNode.I +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: LinkedListNode::Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LinkedListNode:: +LinkedListNode() { +#ifndef NDEBUG + _next = NULL; + _prev = NULL; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: LinkedListNode::Constructor 2 +// Access: Protected +// Description: This constructor should be invoked for any +// LinkedListNodes that will be used to serve as the +// root of a list. It sets up the pointers as an empty +// list. +//////////////////////////////////////////////////////////////////// +INLINE LinkedListNode:: +LinkedListNode(bool) { + _next = this; + _prev = this; +} + +//////////////////////////////////////////////////////////////////// +// Function: LinkedListNode::Destructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LinkedListNode:: +~LinkedListNode() { + nassertv((_next == NULL && _prev == NULL) || (_next == this && _prev == this)); +} + +//////////////////////////////////////////////////////////////////// +// Function: LinkedListNode::remove_from_list +// Access: Protected +// Description: Removes a LinkedListNode record from the +// doubly-linked list. +//////////////////////////////////////////////////////////////////// +INLINE void LinkedListNode:: +remove_from_list() { + nassertv(_prev->_next == this && _next->_prev == this); + _prev->_next = _next; + _next->_prev = _prev; +#ifndef NDEBUG + _next = NULL; + _prev = NULL; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: LinkedListNode::insert_before +// Access: Protected +// Description: Adds a LinkedListNode record before the indicated +// node in the doubly-linked list. +//////////////////////////////////////////////////////////////////// +INLINE void LinkedListNode:: +insert_before(LinkedListNode *node) { + nassertv(node->_prev != NULL && node->_prev->_next == node && node->_next->_prev == node); + nassertv(_prev == (LinkedListNode *)NULL && + _next == (LinkedListNode *)NULL); + _prev = node->_prev; + _next = node; + _prev->_next = this; + node->_prev = this; +} + +//////////////////////////////////////////////////////////////////// +// Function: LinkedListNode::take_list_from +// Access: Protected +// Description: Given that this LinkedListNode represents the root of +// a list, and the other pointer represents the root of +// a different list, move all of the nodes (except the +// root itself) from other_root onto this list. +//////////////////////////////////////////////////////////////////// +INLINE void LinkedListNode:: +take_list_from(LinkedListNode *other_root) { + other_root->_next->_prev = _prev; + _prev->_next = other_root->_next; + other_root->_prev->_next = this; + _prev = other_root->_prev; + + other_root->_next = other_root; + other_root->_prev = other_root; +} diff --git a/panda/src/putil/linkedListNode.cxx b/panda/src/putil/linkedListNode.cxx new file mode 100644 index 0000000000..cfc0f81856 --- /dev/null +++ b/panda/src/putil/linkedListNode.cxx @@ -0,0 +1,19 @@ +// Filename: linkedListNode.cxx +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "linkedListNode.h" diff --git a/panda/src/putil/linkedListNode.h b/panda/src/putil/linkedListNode.h new file mode 100644 index 0000000000..54cfe66a2d --- /dev/null +++ b/panda/src/putil/linkedListNode.h @@ -0,0 +1,50 @@ +// Filename: linkedListNode.h +// Created by: drose (16Mar06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef LINKEDLISTNODE_H +#define LINKEDLISTNODE_H + +#include "pandabase.h" + +//////////////////////////////////////////////////////////////////// +// Class : LinkedListNode +// Description : This just stores the pointers to implement a +// doubly-linked list of some kind of object. There are +// occasions when a hand-rolled linked list is more +// appropriate than an STL container. +// +// Typically, each node of the linked list, as well as +// the root of the list, will inherit from this class. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA LinkedListNode { +protected: + INLINE LinkedListNode(); + INLINE LinkedListNode(bool); + INLINE ~LinkedListNode(); + + INLINE void remove_from_list(); + INLINE void insert_before(LinkedListNode *node); + + INLINE void take_list_from(LinkedListNode *other_root); + + LinkedListNode *_prev, *_next; +}; + +#include "linkedListNode.I" + +#endif diff --git a/panda/src/putil/putil_composite1.cxx b/panda/src/putil/putil_composite1.cxx index bda7a36219..a433aad4f4 100644 --- a/panda/src/putil/putil_composite1.cxx +++ b/panda/src/putil/putil_composite1.cxx @@ -23,4 +23,5 @@ #include "keyboardButton.cxx" #include "lineStream.cxx" #include "lineStreamBuf.cxx" +#include "linkedListNode.cxx" #include "load_prc_file.cxx"