First pass at memory-managed vertices. Might break threaded code.

This commit is contained in:
David Rose 2007-05-13 00:01:38 +00:00
parent ad4aa44a6b
commit b943c36fae
48 changed files with 1253 additions and 599 deletions

View File

@ -43,6 +43,7 @@
#include "objectDeletor.h"
#include "bamCache.h"
#include "cullableObject.h"
#include "geomVertexArrayData.h"
#if defined(WIN32)
#define WINDOWS_LEAN_AND_MEAN
@ -75,6 +76,12 @@ PStatCollector GraphicsEngine::_cyclers_pcollector("PipelineCyclers");
PStatCollector GraphicsEngine::_dirty_cyclers_pcollector("Dirty PipelineCyclers");
PStatCollector GraphicsEngine::_delete_pcollector("App:Delete");
PStatCollector GraphicsEngine::_sw_sprites_pcollector("SW Sprites");
PStatCollector GraphicsEngine::_vertex_data_resident_pcollector("Vertex Data:Resident");
PStatCollector GraphicsEngine::_vertex_data_compressed_pcollector("Vertex Data:Compressed");
PStatCollector GraphicsEngine::_vertex_data_disk_pcollector("Vertex Data:Disk");
// These are counted independently by the collision system; we
// redefine them here so we can reset them at each frame.
PStatCollector GraphicsEngine::_cnode_volume_pcollector("Collision Volumes:CollisionNode");
@ -95,7 +102,6 @@ PStatCollector GraphicsEngine::_volume_inv_sphere_pcollector("Collision Volumes:
PStatCollector GraphicsEngine::_test_inv_sphere_pcollector("Collision Tests:CollisionInvSphere");
PStatCollector GraphicsEngine::_volume_geom_pcollector("Collision Volumes:CollisionGeom");
PStatCollector GraphicsEngine::_test_geom_pcollector("Collision Tests:CollisionGeom");
PStatCollector GraphicsEngine::_sw_sprites_pcollector("SW Sprites");
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::Constructor
@ -672,6 +678,8 @@ render_frame() {
PStatTimer timer(_delete_pcollector, current_thread);
deletor->flush();
}
GeomVertexArrayData::lru_epoch();
GeomCacheManager::flush_level();
CullTraverser::flush_level();
@ -714,6 +722,11 @@ render_frame() {
_render_states_unused_pcollector.set_level(RenderState::get_num_unused_states());
}
_sw_sprites_pcollector.clear_level();
_vertex_data_resident_pcollector.set_level(GeomVertexArrayData::get_global_lru(GeomVertexArrayData::RC_resident)->get_total_size());
_vertex_data_compressed_pcollector.set_level(GeomVertexArrayData::get_global_lru(GeomVertexArrayData::RC_compressed)->get_total_size());
_vertex_data_disk_pcollector.set_level(GeomVertexArrayData::get_global_lru(GeomVertexArrayData::RC_disk)->get_total_size());
_cnode_volume_pcollector.clear_level();
_gnode_volume_pcollector.clear_level();
_geom_volume_pcollector.clear_level();
@ -732,7 +745,6 @@ render_frame() {
_test_inv_sphere_pcollector.clear_level();
_volume_geom_pcollector.clear_level();
_test_geom_pcollector.clear_level();
_sw_sprites_pcollector.clear_level();
#endif // DO_PSTATS

View File

@ -359,6 +359,11 @@ private:
static PStatCollector _dirty_cyclers_pcollector;
static PStatCollector _delete_pcollector;
static PStatCollector _sw_sprites_pcollector;
static PStatCollector _vertex_data_resident_pcollector;
static PStatCollector _vertex_data_compressed_pcollector;
static PStatCollector _vertex_data_disk_pcollector;
static PStatCollector _cnode_volume_pcollector;
static PStatCollector _gnode_volume_pcollector;
static PStatCollector _geom_volume_pcollector;
@ -377,7 +382,6 @@ private:
static PStatCollector _test_inv_sphere_pcollector;
static PStatCollector _volume_geom_pcollector;
static PStatCollector _test_geom_pcollector;
static PStatCollector _sw_sprites_pcollector;
friend class WindowRenderer;
friend class GraphicsOutput;

View File

@ -305,7 +305,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
apply_vertex_buffer(VertexBufferContext *vbc,
const GeomVertexArrayDataPipelineReader *reader) {
const GeomVertexArrayDataHandle *reader) {
DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc);
if (dvbc->_vbuffer == NULL) {
@ -807,7 +807,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
const GeomVertexFormat *format = _data_reader->get_format();
// The munger should have put the FVF data in the first array.
const GeomVertexArrayDataPipelineReader *data = _data_reader->get_array_reader(0);
const GeomVertexArrayDataHandle *data = _data_reader->get_array_reader(0);
VertexBufferContext *vbc = ((GeomVertexArrayData *)(data->get_object()))->prepare_now(get_prepared_objects(), this);
nassertr(vbc != (VertexBufferContext *)NULL, false);
@ -930,9 +930,9 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
(D3DPT_TRIANGLELIST,
min_vertex, max_vertex,
reader->get_num_primitives(),
reader->get_data(),
reader->get_pointer(),
index_type,
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
} else {
@ -949,7 +949,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(),
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}
@ -990,8 +990,8 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
(D3DPT_TRIANGLESTRIP,
min_vertex, max_vertex,
reader->get_num_vertices() - 2,
reader->get_data(), index_type,
_data_reader->get_array_reader(0)->get_data(),
reader->get_pointer(), index_type,
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
} else {
@ -1008,7 +1008,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
reader->get_num_vertices() - 2,
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}
@ -1050,9 +1050,9 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
} else {
// Indexed, client arrays, individual triangle strips.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
CPTA_uchar vertices = reader->get_data();
const unsigned char *vertices = reader->get_pointer();
D3DFORMAT index_type = get_index_type(reader->get_index_type());
unsigned int start = 0;
@ -1087,7 +1087,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
} else {
// Nonindexed, client arrays, individual triangle strips.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
unsigned int start = 0;
@ -1150,9 +1150,9 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
} else {
// Indexed, client arrays.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
CPTA_uchar vertices = reader->get_data();
const unsigned char *vertices = reader->get_pointer();
D3DFORMAT index_type = get_index_type(reader->get_index_type());
unsigned int start = 0;
@ -1187,7 +1187,7 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
} else {
// Nonindexed, client arrays.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
unsigned int start = 0;
@ -1238,9 +1238,9 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
(D3DPT_LINELIST,
min_vertex, max_vertex,
reader->get_num_primitives(),
reader->get_data(),
reader->get_pointer(),
index_type,
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
} else {
@ -1256,7 +1256,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(),
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}
@ -1299,7 +1299,7 @@ draw_points(const GeomPrimitivePipelineReader *reader) {
draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(),
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}

View File

@ -57,7 +57,7 @@ public:
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
void apply_vertex_buffer(VertexBufferContext *vbc,
const GeomVertexArrayDataPipelineReader *reader);
const GeomVertexArrayDataHandle *reader);
virtual void release_vertex_buffer(VertexBufferContext *vbc);
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);

View File

@ -131,7 +131,7 @@ upload_data(const GeomPrimitivePipelineReader *reader) {
}
GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
memcpy(local_pointer, reader->get_data(), data_size);
memcpy(local_pointer, reader->get_pointer(), data_size);
_ibuffer->Unlock();
}

View File

@ -189,7 +189,7 @@ DXVertexBufferContext8::
////////////////////////////////////////////////////////////////////
void DXVertexBufferContext8::
create_vbuffer(DXScreenData &scrn,
const GeomVertexArrayDataPipelineReader *reader) {
const GeomVertexArrayDataHandle *reader) {
nassertv(reader->get_object() == get_data());
Thread *current_thread = reader->get_current_thread();
@ -232,7 +232,7 @@ create_vbuffer(DXScreenData &scrn,
// DirectX.
////////////////////////////////////////////////////////////////////
void DXVertexBufferContext8::
upload_data(const GeomVertexArrayDataPipelineReader *reader) {
upload_data(const GeomVertexArrayDataHandle *reader) {
nassertv(reader->get_object() == get_data());
nassertv(_vbuffer != NULL);
Thread *current_thread = reader->get_current_thread();
@ -257,7 +257,7 @@ upload_data(const GeomVertexArrayDataPipelineReader *reader) {
}
GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
memcpy(local_pointer, reader->get_data(), data_size);
memcpy(local_pointer, reader->get_pointer(), data_size);
_vbuffer->Unlock();
}

View File

@ -34,8 +34,8 @@ public:
virtual ~DXVertexBufferContext8();
void create_vbuffer(DXScreenData &scrn,
const GeomVertexArrayDataPipelineReader *reader);
void upload_data(const GeomVertexArrayDataPipelineReader *reader);
const GeomVertexArrayDataHandle *reader);
void upload_data(const GeomVertexArrayDataHandle *reader);
IDirect3DVertexBuffer8 *_vbuffer;
int _fvf;

View File

@ -393,7 +393,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
void DXGraphicsStateGuardian9::
apply_vertex_buffer(VertexBufferContext *vbc,
CLP(ShaderContext) *shader_context,
const GeomVertexArrayDataPipelineReader *reader) {
const GeomVertexArrayDataHandle *reader) {
DXVertexBufferContext9 *dvbc = DCAST(DXVertexBufferContext9, vbc);
DBG_SH3 dxgsg9_cat.debug ( ) << "apply_vertex_buffer\n"; DBG_E
@ -1186,7 +1186,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
_vertex_array_shader_context = _current_shader_context;
const GeomVertexFormat *format = _data_reader->get_format ( );
const GeomVertexArrayDataPipelineReader *data;
const GeomVertexArrayDataHandle *data;
int number_of_arrays = _data_reader -> get_num_arrays ( );
if (_current_shader_context && number_of_arrays > 1) {
@ -1422,9 +1422,9 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
(D3DPT_TRIANGLELIST,
min_vertex, max_vertex,
reader->get_num_primitives(),
reader->get_data(),
reader->get_pointer(),
index_type,
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
} else {
@ -1446,7 +1446,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader) {
draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(),
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}
@ -1497,8 +1497,8 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
(D3DPT_TRIANGLESTRIP,
min_vertex, max_vertex,
reader->get_num_vertices() - 2,
reader->get_data(), index_type,
_data_reader->get_array_reader(0)->get_data(),
reader->get_pointer(), index_type,
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
} else {
@ -1518,7 +1518,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
reader->get_num_vertices() - 2,
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}
@ -1561,9 +1561,9 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
} else {
// Indexed, client arrays, individual triangle strips.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
CPTA_uchar vertices = reader->get_data();
const unsigned char *vertices = reader->get_pointer();
D3DFORMAT index_type = get_index_type(reader->get_index_type());
unsigned int start = 0;
@ -1598,7 +1598,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader) {
} else {
// Nonindexed, client arrays, individual triangle strips.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
unsigned int start = 0;
@ -1664,9 +1664,9 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
} else {
// Indexed, client arrays.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
CPTA_uchar vertices = reader->get_data();
const unsigned char *vertices = reader->get_pointer();
D3DFORMAT index_type = get_index_type(reader->get_index_type());
unsigned int start = 0;
@ -1701,7 +1701,7 @@ draw_trifans(const GeomPrimitivePipelineReader *reader) {
} else {
// Nonindexed, client arrays.
CPTA_uchar array_data = _data_reader->get_array_reader(0)->get_data();
const unsigned char *array_data = _data_reader->get_array_reader(0)->get_pointer();
int stride = _data_reader->get_format()->get_array(0)->get_stride();
unsigned int start = 0;
@ -1753,9 +1753,9 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
(D3DPT_LINELIST,
min_vertex, max_vertex,
reader->get_num_primitives(),
reader->get_data(),
reader->get_pointer(),
index_type,
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
} else {
@ -1771,7 +1771,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader) {
draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(),
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}
@ -1814,7 +1814,7 @@ draw_points(const GeomPrimitivePipelineReader *reader) {
draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(),
reader->get_first_vertex(),
reader->get_num_vertices(),
_data_reader->get_array_reader(0)->get_data(),
_data_reader->get_array_reader(0)->get_pointer(),
_data_reader->get_format()->get_array(0)->get_stride());
}
}
@ -2220,11 +2220,11 @@ bool vertex_buffer_page_in_function (LruPage *lru_page)
// allocate vertex buffer
Thread *current_thread = Thread::get_current_thread();
GeomVertexArrayDataPipelineReader reader(vertex_buffer->get_data(), current_thread);
vertex_buffer -> allocate_vbuffer (*(gsg->_screen), &reader);
CPT(GeomVertexArrayDataHandle) reader = vertex_buffer->get_data()->get_handle(current_thread);
vertex_buffer -> allocate_vbuffer (*(gsg->_screen), reader);
// update vertex buffer
vertex_buffer -> upload_data(&reader);
vertex_buffer -> upload_data(reader);
vertex_buffer -> set_resident(true);
if (DEBUG_LRU && dxgsg9_cat.is_debug())

View File

@ -94,7 +94,7 @@ public:
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
void apply_vertex_buffer(VertexBufferContext *vbc, CLP(ShaderContext) *shader_context,
const GeomVertexArrayDataPipelineReader *reader);
const GeomVertexArrayDataHandle *reader);
virtual void release_vertex_buffer(VertexBufferContext *vbc);
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);

View File

@ -237,7 +237,7 @@ upload_data(const GeomPrimitivePipelineReader *reader) {
}
GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
memcpy(local_pointer, reader->get_data(), data_size);
memcpy(local_pointer, reader->get_pointer(), data_size);
_ibuffer->Unlock();
}

View File

@ -459,7 +459,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
{
if (_vertex_element_array == 0) {
bool error;
const GeomVertexArrayDataPipelineReader *array_reader;
const GeomVertexArrayDataHandle *array_reader;
Geom::NumericType numeric_type;
int start, stride, num_values;
int nvarying = _expansion->_var_spec.size();

View File

@ -341,7 +341,7 @@ free_vbuffer(void) {
////////////////////////////////////////////////////////////////////
void DXVertexBufferContext9::
allocate_vbuffer(DXScreenData &scrn,
const GeomVertexArrayDataPipelineReader *reader) {
const GeomVertexArrayDataHandle *reader) {
int data_size;
HRESULT hr;
@ -393,7 +393,7 @@ allocate_vbuffer(DXScreenData &scrn,
////////////////////////////////////////////////////////////////////
void DXVertexBufferContext9::
create_vbuffer(DXScreenData &scrn,
const GeomVertexArrayDataPipelineReader *reader) {
const GeomVertexArrayDataHandle *reader) {
nassertv(reader->get_object() == get_data());
Thread *current_thread = reader->get_current_thread();
@ -442,7 +442,7 @@ create_vbuffer(DXScreenData &scrn,
// DirectX.
////////////////////////////////////////////////////////////////////
void DXVertexBufferContext9::
upload_data(const GeomVertexArrayDataPipelineReader *reader) {
upload_data(const GeomVertexArrayDataHandle *reader) {
nassertv(reader->get_object() == get_data());
nassertv(_vbuffer != NULL);
Thread *current_thread = reader->get_current_thread();
@ -473,7 +473,7 @@ upload_data(const GeomVertexArrayDataPipelineReader *reader) {
}
GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
memcpy(local_pointer, reader->get_data(), data_size);
memcpy(local_pointer, reader->get_pointer(), data_size);
_vbuffer->Unlock();
}

View File

@ -34,9 +34,9 @@ public:
virtual ~DXVertexBufferContext9();
void free_vbuffer();
void allocate_vbuffer(DXScreenData &scrn, const GeomVertexArrayDataPipelineReader *reader);
void create_vbuffer(DXScreenData &scrn, const GeomVertexArrayDataPipelineReader *reader);
void upload_data(const GeomVertexArrayDataPipelineReader *reader);
void allocate_vbuffer(DXScreenData &scrn, const GeomVertexArrayDataHandle *reader);
void create_vbuffer(DXScreenData &scrn, const GeomVertexArrayDataHandle *reader);
void upload_data(const GeomVertexArrayDataHandle *reader);
IDirect3DVertexBuffer9 *_vbuffer;
int _fvf;

View File

@ -1782,7 +1782,7 @@ update_standard_vertex_arrays() {
#endif // SUPPORT_IMMEDIATE_MODE
{
// We may use vertex arrays or buffers to render primitives.
const GeomVertexArrayDataPipelineReader *array_reader;
const GeomVertexArrayDataHandle *array_reader;
int num_values;
Geom::NumericType numeric_type;
int start;
@ -2697,7 +2697,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
apply_vertex_buffer(VertexBufferContext *vbc,
const GeomVertexArrayDataPipelineReader *reader) {
const GeomVertexArrayDataHandle *reader) {
nassertv(_supports_buffers);
nassertv(reader->get_modified() != UpdateSeq::initial());
@ -2724,12 +2724,12 @@ apply_vertex_buffer(VertexBufferContext *vbc,
if (num_bytes != 0) {
if (gvbc->changed_size(reader) || gvbc->changed_usage_hint(reader)) {
_glBufferData(GL_ARRAY_BUFFER, num_bytes,
reader->get_data(),
reader->get_pointer(),
get_usage(reader->get_usage_hint()));
} else {
_glBufferSubData(GL_ARRAY_BUFFER, 0, num_bytes,
reader->get_data());
reader->get_pointer());
}
_data_transferred_pcollector.add_level(num_bytes);
}
@ -2795,10 +2795,10 @@ release_vertex_buffer(VertexBufferContext *vbc) {
// in client memory, that is, the data array passed in.
////////////////////////////////////////////////////////////////////
const unsigned char *CLP(GraphicsStateGuardian)::
setup_array_data(const GeomVertexArrayDataPipelineReader *array_reader) {
setup_array_data(const GeomVertexArrayDataHandle *array_reader) {
if (!_supports_buffers) {
// No support for buffer objects; always render from client.
return array_reader->get_data();
return array_reader->get_pointer();
}
if (!vertex_buffers || _geom_display_list != 0 ||
array_reader->get_usage_hint() == Geom::UH_client) {
@ -2812,12 +2812,12 @@ setup_array_data(const GeomVertexArrayDataPipelineReader *array_reader) {
_glBindBuffer(GL_ARRAY_BUFFER, 0);
_current_vbuffer_index = 0;
}
return array_reader->get_data();
return array_reader->get_pointer();
}
// Prepare the buffer object and bind it.
VertexBufferContext *vbc = ((GeomVertexArrayData *)array_reader->get_object())->prepare_now(get_prepared_objects(), this);
nassertr(vbc != (VertexBufferContext *)NULL, array_reader->get_data());
nassertr(vbc != (VertexBufferContext *)NULL, array_reader->get_pointer());
apply_vertex_buffer(vbc, array_reader);
// NULL is the OpenGL convention for the first byte of the buffer object.
@ -2884,6 +2884,7 @@ apply_index_buffer(IndexBufferContext *ibc,
if (gibc->was_modified(reader)) {
PStatTimer timer(_load_index_buffer_pcollector, reader->get_current_thread());
int num_bytes = reader->get_data_size_bytes();
if (GLCAT.is_spam()) {
GLCAT.spam()
@ -2893,12 +2894,12 @@ apply_index_buffer(IndexBufferContext *ibc,
if (num_bytes != 0) {
if (gibc->changed_size(reader) || gibc->changed_usage_hint(reader)) {
_glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_bytes,
reader->get_data(),
reader->get_pointer(),
get_usage(reader->get_usage_hint()));
} else {
_glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, num_bytes,
reader->get_data());
reader->get_pointer());
}
_data_transferred_pcollector.add_level(num_bytes);
}
@ -2966,7 +2967,7 @@ const unsigned char *CLP(GraphicsStateGuardian)::
setup_primitive(const GeomPrimitivePipelineReader *reader) {
if (!_supports_buffers) {
// No support for buffer objects; always render from client.
return reader->get_data();
return reader->get_pointer();
}
if (!vertex_buffers || _geom_display_list != 0 ||
reader->get_usage_hint() == Geom::UH_client) {
@ -2980,12 +2981,12 @@ setup_primitive(const GeomPrimitivePipelineReader *reader) {
_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
_current_ibuffer_index = 0;
}
return reader->get_data();
return reader->get_pointer();
}
// Prepare the buffer object and bind it.
IndexBufferContext *ibc = ((GeomPrimitive *)reader->get_object())->prepare_now(get_prepared_objects(), this);
nassertr(ibc != (IndexBufferContext *)NULL, reader->get_data());
nassertr(ibc != (IndexBufferContext *)NULL, reader->get_pointer());
apply_index_buffer(ibc, reader);
// NULL is the OpenGL convention for the first byte of the buffer object.

View File

@ -131,9 +131,9 @@ public:
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
void apply_vertex_buffer(VertexBufferContext *vbc,
const GeomVertexArrayDataPipelineReader *reader);
const GeomVertexArrayDataHandle *reader);
virtual void release_vertex_buffer(VertexBufferContext *vbc);
const unsigned char *setup_array_data(const GeomVertexArrayDataPipelineReader *data);
const unsigned char *setup_array_data(const GeomVertexArrayDataHandle *data);
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);
void apply_index_buffer(IndexBufferContext *ibc,

View File

@ -218,7 +218,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
} else
#endif // SUPPORT_IMMEDIATE_MODE
{
const GeomVertexArrayDataPipelineReader *array_reader;
const GeomVertexArrayDataHandle *array_reader;
Geom::NumericType numeric_type;
int start, stride, num_values;
int nvarying = _expansion->_var_spec.size();

View File

@ -50,6 +50,7 @@
savedContext.I savedContext.h \
shaderContext.h shaderContext.I \
shaderExpansion.h shaderExpansion.I \
simpleLru.h simpleLru.I \
sliderTable.I sliderTable.h \
texture.I texture.h \
textureContext.I textureContext.h \
@ -106,6 +107,7 @@
savedContext.cxx \
shaderContext.cxx \
shaderExpansion.cxx \
simpleLru.cxx \
sliderTable.cxx \
texture.cxx textureContext.cxx texturePool.cxx \
texturePoolFilter.cxx \
@ -162,6 +164,7 @@
savedContext.I savedContext.h \
shaderContext.h shaderContext.I \
shaderExpansion.h shaderExpansion.I \
simpleLru.h simpleLru.I \
sliderTable.I sliderTable.h \
texture.I texture.h \
textureContext.I textureContext.h \

View File

@ -287,8 +287,7 @@ ConfigureFn(config_gobj) {
GeomTrifans::init_type();
GeomTristrips::init_type();
GeomVertexArrayData::init_type();
GeomVertexArrayDataPipelineReader::init_type();
GeomVertexArrayDataPipelineWriter::init_type();
GeomVertexArrayDataHandle::init_type();
GeomVertexArrayFormat::init_type();
GeomVertexData::init_type();
GeomVertexDataPipelineReader::init_type();

View File

@ -223,6 +223,10 @@ offset_vertices(const GeomVertexData *data, int offset) {
#ifndef NDEBUG
if (!prim->check_valid(data)) {
gobj_cat.warning()
<< *prim << " is invalid for " << *data << ":\n";
prim->write(gobj_cat.warning(false), 4);
all_is_valid = false;
}
#endif

View File

@ -210,6 +210,17 @@ PUBLISHED:
AT_hardware, // Hardware-accelerated animation on the graphics card.
};
// These are used to indicate the current residency state of vertex
// data, which may or may not have been temporarily evicted to
// satisfy memory requirements.
enum RamClass {
RC_resident,
RC_compressed,
RC_disk,
RC_end_of_list, // list marker; do not use
};
};
EXPCL_PANDA ostream &operator << (ostream &out, GeomEnums::NumericType numeric_type);

View File

@ -303,18 +303,6 @@ get_index_stride() const {
return reader.get_index_stride();
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_data
// Access: Public
// Description: A convenience function to return the actual data of
// the index array.
////////////////////////////////////////////////////////////////////
INLINE CPTA_uchar GeomPrimitive::
get_data() const {
nassertr(is_indexed(), CPTA_uchar());
return get_vertices()->get_data();
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_ends
// Access: Public
@ -486,8 +474,7 @@ GeomPrimitivePipelineReader(const GeomPrimitive *object,
_cdata->ref();
#endif // DO_PIPELINING
if (!_cdata->_vertices.is_null()) {
_vertices_reader =
new GeomVertexArrayDataPipelineReader(_cdata->_vertices.get_read_pointer(), _current_thread);
_vertices_reader = _cdata->_vertices.get_read_pointer()->get_handle();
}
}
@ -518,9 +505,6 @@ operator = (const GeomPrimitivePipelineReader &) {
////////////////////////////////////////////////////////////////////
INLINE GeomPrimitivePipelineReader::
~GeomPrimitivePipelineReader() {
if (_vertices_reader != (GeomVertexArrayDataPipelineReader *)NULL) {
delete _vertices_reader;
}
#ifdef _DEBUG
nassertv(_object->test_ref_count_nonzero());
#endif // _DEBUG
@ -671,19 +655,19 @@ get_index_stride() const {
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const GeomVertexArrayDataPipelineReader *GeomPrimitivePipelineReader::
INLINE const GeomVertexArrayDataHandle *GeomPrimitivePipelineReader::
get_vertices_reader() const {
return _vertices_reader;
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitivePipelineReader::get_data
// Function: GeomPrimitivePipelineReader::get_pointer
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CPTA_uchar GeomPrimitivePipelineReader::
get_data() const {
return _vertices_reader->get_data();
INLINE const unsigned char *GeomPrimitivePipelineReader::
get_pointer() const {
return _vertices_reader->get_pointer();
}
////////////////////////////////////////////////////////////////////

View File

@ -1314,7 +1314,8 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
}
} else {
for (int i = 0; i < num_vertices; ++i) {
reader.set_row(index.get_data1i());
int ii = index.get_data1i();
reader.set_row(ii);
const LVecBase3f &vertex = reader.get_data3f();
if (found_any) {

View File

@ -158,7 +158,6 @@ public:
void set_nonindexed_vertices(int first_vertex, int num_vertices);
INLINE int get_index_stride() const;
INLINE CPTA_uchar get_data() const;
INLINE CPTA_int get_ends() const;
PTA_int modify_ends();
@ -346,8 +345,8 @@ public:
INLINE UpdateSeq get_modified() const;
bool check_valid(const GeomVertexDataPipelineReader *data_reader) const;
INLINE int get_index_stride() const;
INLINE const GeomVertexArrayDataPipelineReader *get_vertices_reader() const;
INLINE CPTA_uchar get_data() const;
INLINE const GeomVertexArrayDataHandle *get_vertices_reader() const;
INLINE const unsigned char *get_pointer() const;
INLINE CPTA_int get_ends() const;
INLINE CPT(GeomVertexArrayData) get_mins() const;
INLINE CPT(GeomVertexArrayData) get_maxs() const;
@ -357,7 +356,7 @@ private:
Thread *_current_thread;
const GeomPrimitive::CData *_cdata;
GeomVertexArrayDataPipelineReader *_vertices_reader;
CPT(GeomVertexArrayDataHandle) _vertices_reader;
public:
static TypeHandle get_class_type() {

View File

@ -62,8 +62,7 @@ has_column(const InternalName *name) const {
////////////////////////////////////////////////////////////////////
INLINE int GeomVertexArrayData::
get_num_rows() const {
GeomVertexArrayDataPipelineReader reader(this, Thread::get_current_thread());
return reader.get_num_rows();
return get_handle()->get_num_rows();
}
////////////////////////////////////////////////////////////////////
@ -90,8 +89,7 @@ get_num_rows() const {
////////////////////////////////////////////////////////////////////
INLINE bool GeomVertexArrayData::
set_num_rows(int n) {
GeomVertexArrayDataPipelineWriter writer(this, true, Thread::get_current_thread());
return writer.set_num_rows(n);
return modify_handle()->set_num_rows(n);
}
////////////////////////////////////////////////////////////////////
@ -109,8 +107,7 @@ set_num_rows(int n) {
////////////////////////////////////////////////////////////////////
INLINE bool GeomVertexArrayData::
unclean_set_num_rows(int n) {
GeomVertexArrayDataPipelineWriter writer(this, true, Thread::get_current_thread());
return writer.unclean_set_num_rows(n);
return modify_handle()->unclean_set_num_rows(n);
}
////////////////////////////////////////////////////////////////////
@ -121,7 +118,7 @@ unclean_set_num_rows(int n) {
////////////////////////////////////////////////////////////////////
INLINE void GeomVertexArrayData::
clear_rows() {
set_data(PTA_uchar(GeomVertexArrayData::get_class_type()));
return modify_handle()->clear_rows();
}
////////////////////////////////////////////////////////////////////
@ -132,7 +129,7 @@ clear_rows() {
INLINE int GeomVertexArrayData::
get_data_size_bytes() const {
CDReader cdata(_cycler);
return cdata->_data.size();
return cdata->_data_full_size;
}
////////////////////////////////////////////////////////////////////
@ -149,49 +146,71 @@ get_modified() const {
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::get_data
// Function: GeomVertexArrayData::get_handle
// Access: Published
// Description: Returns a const pointer to the actual vertex data,
// for application code to directly examine (but not
// modify).
// Description: Returns an object that can be used to read the actual
// data bytes stored in the array. Calling this method
// locks the data, and will block any other threads
// attempting to read or write the data, until the
// returned object destructs.
////////////////////////////////////////////////////////////////////
INLINE CPTA_uchar GeomVertexArrayData::
get_data() const {
CDReader cdata(_cycler);
return cdata->_data;
INLINE CPT(GeomVertexArrayDataHandle) GeomVertexArrayData::
get_handle(Thread *current_thread) const {
return new GeomVertexArrayDataHandle(this, current_thread,
_cycler.read_unlocked(current_thread),
false);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::modify_data
// Function: GeomVertexArrayData::modify_handle
// Access: Published
// Description: Returns a modifiable pointer to the actual vertex
// array, so that application code may directly
// manipulate it. Use with caution.
//
// Don't call this in a downstream thread unless you
// don't mind it blowing away other changes you might
// have recently made in an upstream thread.
// Description: Returns an object that can be used to read or write
// the actual data bytes stored in the array. Calling
// this method locks the data, and will block any other
// threads attempting to read or write the data, until
// the returned object destructs.
////////////////////////////////////////////////////////////////////
INLINE PTA_uchar GeomVertexArrayData::
modify_data() {
GeomVertexArrayDataPipelineWriter writer(this, true, Thread::get_current_thread());
return writer.modify_data();
INLINE PT(GeomVertexArrayDataHandle) GeomVertexArrayData::
modify_handle(Thread *current_thread) {
return new GeomVertexArrayDataHandle(this, current_thread,
_cycler.write_upstream(true, current_thread),
true);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::set_data
// Function: GeomVertexArrayData::get_ram_class
// Access: Published
// Description: Replaces the vertex data array with a completely new
// array.
//
// Don't call this in a downstream thread unless you
// don't mind it blowing away other changes you might
// have recently made in an upstream thread.
// Description: Returns the current ram class of the array. If this
// is other than RC_resident, the array data is not
// resident in memory.
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayData::RamClass GeomVertexArrayData::
get_ram_class() const {
return _ram_class;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::get_global_lru
// Access: Published, Static
// Description: Returns a pointer to the global LRU object that
// manages the GeomVertexArrayData's with the indicated
// RamClass.
////////////////////////////////////////////////////////////////////
INLINE SimpleLru *GeomVertexArrayData::
get_global_lru(RamClass rclass) {
nassertr(rclass >= 0 && rclass < RC_end_of_list, NULL);
return &_global_lru[rclass];
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::set_ram_class
// Access: Private
// Description: Puts the data in a new ram class.
////////////////////////////////////////////////////////////////////
INLINE void GeomVertexArrayData::
set_data(CPTA_uchar array) {
GeomVertexArrayDataPipelineWriter writer(this, true, Thread::get_current_thread());
writer.set_data(array);
set_ram_class(RamClass rclass) {
_ram_class = rclass;
mark_used_lru(&_global_lru[rclass]);
}
////////////////////////////////////////////////////////////////////
@ -202,9 +221,9 @@ set_data(CPTA_uchar array) {
INLINE GeomVertexArrayData::CData::
CData() :
_usage_hint(UH_unspecified),
_data(GeomVertexArrayData::get_class_type())
_data(GeomVertexArrayData::get_class_type()),
_data_full_size(0)
{
_data.node_ref();
}
////////////////////////////////////////////////////////////////////
@ -215,24 +234,41 @@ CData() :
INLINE GeomVertexArrayData::CData::
CData(const GeomVertexArrayData::CData &copy) :
_usage_hint(copy._usage_hint),
_data(copy._data),
_data(GeomVertexArrayData::get_class_type()),
_data_full_size(copy._data_full_size),
_modified(copy._modified)
{
_data.node_ref();
_data.v() = copy._data.v();
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::Constructor
// Function: GeomVertexArrayData::CData::Copy Assignment
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineBase::
GeomVertexArrayDataPipelineBase(GeomVertexArrayData *object,
Thread *current_thread,
GeomVertexArrayData::CData *cdata) :
_object(object),
INLINE void GeomVertexArrayData::CData::
operator = (const GeomVertexArrayData::CData &copy) {
_usage_hint = copy._usage_hint;
_modified = copy._modified;
_data.v() = copy._data.v();
_data_full_size = copy._data_full_size;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataHandle::
GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
Thread *current_thread,
const GeomVertexArrayData::CData *cdata,
bool writable) :
_holder(((GeomVertexArrayData::CData *)cdata)->_rw_lock),
_object((GeomVertexArrayData *)object),
_current_thread(current_thread),
_cdata(cdata)
_cdata((GeomVertexArrayData::CData *)cdata),
_writable(writable)
{
#ifdef _DEBUG
nassertv(_object->test_ref_count_nonzero());
@ -243,16 +279,42 @@ GeomVertexArrayDataPipelineBase(GeomVertexArrayData *object,
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::Destructor
// Function: GeomVertexArrayDataHandle::Copy Constructor
// Access: Private
// Description: Don't attempt to copy these objects.
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataHandle::
GeomVertexArrayDataHandle(const GeomVertexArrayDataHandle &copy) :
_holder(copy._cdata->_rw_lock)
{
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::Copy Assignment Operator
// Access: Private
// Description: Don't attempt to copy these objects.
////////////////////////////////////////////////////////////////////
INLINE void GeomVertexArrayDataHandle::
operator = (const GeomVertexArrayDataHandle &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineBase::
~GeomVertexArrayDataPipelineBase() {
INLINE GeomVertexArrayDataHandle::
~GeomVertexArrayDataHandle() {
#ifdef _DEBUG
nassertv(_object->test_ref_count_nonzero());
#endif // _DEBUG
if (_writable) {
_object->_cycler.release_write(_cdata);
}
#ifdef DO_PIPELINING
unref_delete((CycleData *)_cdata);
#endif // DO_PIPELINING
@ -264,184 +326,134 @@ INLINE GeomVertexArrayDataPipelineBase::
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::get_current_thread
// Function: GeomVertexArrayDataHandle::get_current_thread
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Thread *GeomVertexArrayDataPipelineBase::
INLINE Thread *GeomVertexArrayDataHandle::
get_current_thread() const {
return _current_thread;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::get_array_format
// Function: GeomVertexArrayDataHandle::get_object
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const GeomVertexArrayData *GeomVertexArrayDataHandle::
get_object() const {
return _object;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::get_object
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayData *GeomVertexArrayDataHandle::
get_object() {
return _object;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::get_pointer
// Access: Public
// Description: Returns a pointer to the beginning of the actual data
// stream.
////////////////////////////////////////////////////////////////////
INLINE const unsigned char *GeomVertexArrayDataHandle::
get_pointer() const {
check_resident();
return _cdata->_data.p();
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::get_pointer
// Access: Public
// Description: Returns a pointer to the beginning of the actual data
// stream.
////////////////////////////////////////////////////////////////////
INLINE unsigned char *GeomVertexArrayDataHandle::
get_pointer() {
nassertr(_writable, NULL);
check_resident();
return _cdata->_data.p();
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::get_array_format
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const GeomVertexArrayFormat *GeomVertexArrayDataPipelineBase::
INLINE const GeomVertexArrayFormat *GeomVertexArrayDataHandle::
get_array_format() const {
return _object->_array_format;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::get_usage_hint
// Function: GeomVertexArrayDataHandle::get_usage_hint
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineBase::UsageHint GeomVertexArrayDataPipelineBase::
INLINE GeomVertexArrayDataHandle::UsageHint GeomVertexArrayDataHandle::
get_usage_hint() const {
return _cdata->_usage_hint;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::get_data
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CPTA_uchar GeomVertexArrayDataPipelineBase::
get_data() const {
return _cdata->_data;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::get_num_rows
// Function: GeomVertexArrayDataHandle::get_num_rows
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE int GeomVertexArrayDataPipelineBase::
INLINE int GeomVertexArrayDataHandle::
get_num_rows() const {
return get_data_size_bytes() / _object->_array_format->get_stride();
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::get_data_size_bytes
// Function: GeomVertexArrayDataHandle::clear_rows
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE int GeomVertexArrayDataPipelineBase::
get_data_size_bytes() const {
return _cdata->_data.size();
INLINE void GeomVertexArrayDataHandle::
clear_rows() {
set_num_rows(0);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineBase::get_modified
// Access: Public
// Function: GeomVertexArrayDataHandle::get_data_size_bytes
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq GeomVertexArrayDataPipelineBase::
INLINE int GeomVertexArrayDataHandle::
get_data_size_bytes() const {
return _cdata->_data_full_size;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataHandle::get_modified
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq GeomVertexArrayDataHandle::
get_modified() const {
return _cdata->_modified;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineReader::Constructor
// Access: Public
// Description:
// Function: GeomVertexArrayDataHandle::check_resident
// Access: Published
// Description: Forces the vertex data into system RAM, if it is not
// already there; also, marks it recently-used.
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineReader::
GeomVertexArrayDataPipelineReader(const GeomVertexArrayData *object,
Thread *current_thread) :
GeomVertexArrayDataPipelineBase((GeomVertexArrayData *)object,
current_thread,
(GeomVertexArrayData::CData *)object->_cycler.read_unlocked(current_thread))
{
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineReader::Copy Constructor
// Access: Private
// Description: Don't attempt to copy these objects.
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineReader::
GeomVertexArrayDataPipelineReader(const GeomVertexArrayDataPipelineReader &copy) :
GeomVertexArrayDataPipelineBase(copy)
{
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineReader::Copy Assignment Operator
// Access: Private
// Description: Don't attempt to copy these objects.
////////////////////////////////////////////////////////////////////
INLINE void GeomVertexArrayDataPipelineReader::
operator = (const GeomVertexArrayDataPipelineReader &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineReader::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineReader::
~GeomVertexArrayDataPipelineReader() {
// _object->_cycler.release_read(_cdata);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineReader::get_object
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const GeomVertexArrayData *GeomVertexArrayDataPipelineReader::
get_object() const {
return _object;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineWriter::
GeomVertexArrayDataPipelineWriter(GeomVertexArrayData *object, bool force_to_0,
Thread *current_thread) :
GeomVertexArrayDataPipelineBase(object, current_thread,
object->_cycler.write_upstream(force_to_0, current_thread))
{
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::Copy Constructor
// Access: Private
// Description: Don't attempt to copy these objects.
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineWriter::
GeomVertexArrayDataPipelineWriter(const GeomVertexArrayDataPipelineWriter &copy) :
GeomVertexArrayDataPipelineBase(copy)
{
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::Copy Assignment Operator
// Access: Private
// Description: Don't attempt to copy these objects.
////////////////////////////////////////////////////////////////////
INLINE void GeomVertexArrayDataPipelineWriter::
operator = (const GeomVertexArrayDataPipelineWriter &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineWriter::
~GeomVertexArrayDataPipelineWriter() {
_object->_cycler.release_write(_cdata);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::get_object
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayData *GeomVertexArrayDataPipelineWriter::
get_object() const {
return _object;
void GeomVertexArrayDataHandle::
check_resident() const {
if (_object->get_ram_class() != RC_resident) {
_object->make_resident();
} else {
_object->mark_used_lru();
}
nassertv(_cdata->_data.size() == _cdata->_data_full_size);
}
INLINE ostream &

View File

@ -23,11 +23,55 @@
#include "bamReader.h"
#include "bamWriter.h"
#include "pset.h"
#include "config_gobj.h"
#include "pStatTimer.h"
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
ConfigVariableInt max_ram_vertex_data
("max-ram-vertex-data", 0,
PRC_DESC("Specifies the maximum number of bytes of all vertex data "
"that is allowed to remain resident in system RAM at one time. "
"If more than this number of bytes of vertices are created, "
"the least-recently-used ones will be temporarily compressed in "
"system RAM until they are needed. Set it to 0 for no limit."));
ConfigVariableInt max_compressed_vertex_data
("max-compressed-vertex-data", 0,
PRC_DESC("Specifies the maximum number of bytes of all vertex data "
"that is allowed to remain compressed in system RAM at one time. "
"If more than this number of bytes of vertices are created, "
"the least-recently-used ones will be temporarily flushed to "
"disk until they are needed. Set it to 0 for no limit."));
// We make this a static constant rather than a dynamic variable,
// since we can't tolerate this value changing at runtime.
static const size_t min_vertex_data_compress_size =
ConfigVariableInt
("min-vertex-data-compress-size", 64,
PRC_DESC("This is the minimum number of bytes that we deem worthy of "
"passing through zlib to compress, when a vertex buffer is "
"evicted from resident state and compressed for long-term "
"storage. Buffers smaller than this are assumed to be likely to "
"have minimal compression gains (or even end up larger)."));
SimpleLru GeomVertexArrayData::_global_lru[RC_end_of_list] = {
SimpleLru(max_ram_vertex_data),
SimpleLru(max_compressed_vertex_data),
SimpleLru(0)
};
PStatCollector GeomVertexArrayData::_vdata_compress_pcollector("*:Vertex Data:Compress");
PStatCollector GeomVertexArrayData::_vdata_decompress_pcollector("*:Vertex Data:Decompress");
TypeHandle GeomVertexArrayData::_type_handle;
TypeHandle GeomVertexArrayData::CData::_type_handle;
TypeHandle GeomVertexArrayDataPipelineReader::_type_handle;
TypeHandle GeomVertexArrayDataPipelineWriter::_type_handle;
TypeHandle GeomVertexArrayDataHandle::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::Default Constructor
@ -36,8 +80,11 @@ TypeHandle GeomVertexArrayDataPipelineWriter::_type_handle;
// reading from the bam file.
////////////////////////////////////////////////////////////////////
GeomVertexArrayData::
GeomVertexArrayData() {
GeomVertexArrayData() : SimpleLruPage(0) {
_endian_reversed = false;
_ram_class = RC_resident;
// Can't put it in the LRU until it has been read in and made valid.
}
////////////////////////////////////////////////////////////////////
@ -47,6 +94,7 @@ GeomVertexArrayData() {
////////////////////////////////////////////////////////////////////
PT(CopyOnWriteObject) GeomVertexArrayData::
make_cow_copy() {
make_resident();
return new GeomVertexArrayData(*this);
}
@ -58,6 +106,7 @@ make_cow_copy() {
GeomVertexArrayData::
GeomVertexArrayData(const GeomVertexArrayFormat *array_format,
GeomVertexArrayData::UsageHint usage_hint) :
SimpleLruPage(0),
_array_format(array_format)
{
OPEN_ITERATE_ALL_STAGES(_cycler) {
@ -67,6 +116,10 @@ GeomVertexArrayData(const GeomVertexArrayFormat *array_format,
CLOSE_ITERATE_ALL_STAGES(_cycler);
_endian_reversed = false;
_ram_class = RC_resident;
mark_used_lru(&_global_lru[RC_resident]);
nassertv(_array_format->is_registered());
}
@ -78,10 +131,15 @@ GeomVertexArrayData(const GeomVertexArrayFormat *array_format,
GeomVertexArrayData::
GeomVertexArrayData(const GeomVertexArrayData &copy) :
CopyOnWriteObject(copy),
SimpleLruPage(copy),
_array_format(copy._array_format),
_cycler(copy._cycler)
{
_endian_reversed = false;
_ram_class = copy._ram_class;
mark_used_lru(&_global_lru[_ram_class]);
nassertv(_array_format->is_registered());
}
@ -96,6 +154,7 @@ GeomVertexArrayData(const GeomVertexArrayData &copy) :
void GeomVertexArrayData::
operator = (const GeomVertexArrayData &copy) {
CopyOnWriteObject::operator = (copy);
SimpleLruPage::operator = (copy);
_array_format = copy._array_format;
_cycler = copy._cycler;
@ -272,6 +331,155 @@ release_all() {
return num_freed;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::lru_epoch
// Access: Published, Static
// Description: Marks that an epoch has passed in each LRU. Asks the
// LRU's to consider whether they should perform
// evictions.
////////////////////////////////////////////////////////////////////
void GeomVertexArrayData::
lru_epoch() {
for (int i = 0; i < (int)RC_end_of_list; ++i) {
get_global_lru((RamClass)i)->consider_evict();
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::make_resident
// Access: Published
// Description: Moves the vertex data to fully resident status by
// expanding it or reading it from disk as necessary.
////////////////////////////////////////////////////////////////////
void GeomVertexArrayData::
make_resident() {
// TODO: make this work with pipelining properly.
if (_ram_class == RC_compressed) {
CDWriter cdata(_cycler, true);
#ifdef HAVE_ZLIB
if (cdata->_data_full_size > min_vertex_data_compress_size) {
PStatTimer timer(_vdata_decompress_pcollector);
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Expanding " << *this << " from " << cdata->_data.size()
<< " to " << cdata->_data_full_size << "\n";
}
PTA_uchar new_data = PTA_uchar::empty_array(cdata->_data_full_size, get_class_type());
uLongf dest_len = cdata->_data_full_size;
int result = uncompress(new_data.p(), &dest_len,
cdata->_data.p(), cdata->_data.size());
if (result != Z_OK) {
gobj_cat.error()
<< "Couldn't expand: zlib error " << result << "\n";
}
nassertv(dest_len == new_data.size());
cdata->_data = new_data;
}
#endif
set_lru_size(cdata->_data.size());
}
set_ram_class(RC_resident);
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::make_compressed
// Access: Published
// Description: Moves the vertex data to compressed status by
// compressing it or reading it from disk as necessary.
////////////////////////////////////////////////////////////////////
void GeomVertexArrayData::
make_compressed() {
// TODO: make this work with pipelining properly.
if (_ram_class == RC_resident) {
CDWriter cdata(_cycler, true);
#ifdef HAVE_ZLIB
if (cdata->_data_full_size > min_vertex_data_compress_size) {
PStatTimer timer(_vdata_compress_pcollector);
// According to the zlib manual, we need to provide this much
// buffer to the compress algorithm: 0.1% bigger plus twelve
// bytes.
uLongf buffer_size = cdata->_data_full_size + ((cdata->_data_full_size + 999) / 1000) + 12;
Bytef *buffer = new Bytef[buffer_size];
int result = compress(buffer, &buffer_size,
cdata->_data.p(), cdata->_data_full_size);
if (result != Z_OK) {
gobj_cat.error()
<< "Couldn't compress: zlib error " << result << "\n";
}
PTA_uchar new_data = PTA_uchar::empty_array(buffer_size, get_class_type());
memcpy(new_data.p(), buffer, buffer_size);
delete[] buffer;
cdata->_data = new_data;
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Compressed " << *this << " from " << cdata->_data_full_size
<< " to " << cdata->_data.size() << "\n";
}
}
#endif
set_ram_class(RC_compressed);
set_lru_size(cdata->_data.size());
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::make_disk
// Access: Published
// Description: Moves the vertex data to disk status by
// writing it to disk as necessary.
////////////////////////////////////////////////////////////////////
void GeomVertexArrayData::
make_disk() {
// TODO: make this work with pipelining properly.
if (_ram_class == RC_compressed) {
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::evict_lru
// Access: Public, Virtual
// Description: Evicts the page from the LRU. Called internally when
// the LRU determines that it is full. May also be
// called externally when necessary to explicitly evict
// the page.
//
// It is legal for this method to either evict the page
// as requested, do nothing (in which case the eviction
// will be requested again at the next epoch), or
// requeue itself on the tail of the queue (in which
// case the eviction will be requested again much
// later).
////////////////////////////////////////////////////////////////////
void GeomVertexArrayData::
evict_lru() {
nassertv(get_lru() == get_global_lru(_ram_class));
switch (_ram_class) {
case RC_resident:
make_compressed();
break;
case RC_compressed:
make_disk();
break;
case RC_disk:
gobj_cat.warning()
<< "Cannot evict array data from disk.\n";
break;
case RC_end_of_list:
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayData::clear_prepared
// Access: Private
@ -359,6 +567,7 @@ register_with_read_factory() {
////////////////////////////////////////////////////////////////////
void GeomVertexArrayData::
write_datagram(BamWriter *manager, Datagram &dg) {
make_resident();
CopyOnWriteObject::write_datagram(manager, dg);
manager->write_pointer(dg, _array_format);
@ -465,6 +674,8 @@ finalize(BamReader *manager) {
// Now is also the time to node_ref the data.
cdata->_data.node_ref();
set_ram_class(RC_resident);
}
////////////////////////////////////////////////////////////////////
@ -510,7 +721,6 @@ fillin(DatagramIterator &scan, BamReader *manager) {
////////////////////////////////////////////////////////////////////
GeomVertexArrayData::CData::
~CData() {
_data.node_unref();
}
////////////////////////////////////////////////////////////////////
@ -548,47 +758,41 @@ fillin(DatagramIterator &scan, BamReader *manager, void *extra_data) {
GeomVertexArrayData *array_data = (GeomVertexArrayData *)extra_data;
_usage_hint = (UsageHint)scan.get_uint8();
READ_PTA(manager, scan, array_data->read_raw_data, _data);
_data_full_size = _data.size();
array_data->set_lru_size(_data_full_size);
_modified = Geom::get_next_modified();
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::set_num_rows
// Function: GeomVertexArrayDataHandle::set_num_rows
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
bool GeomVertexArrayDataPipelineWriter::
bool GeomVertexArrayDataHandle::
set_num_rows(int n) {
nassertr(_writable, false);
check_resident();
int stride = _object->_array_format->get_stride();
int delta = n - (_cdata->_data.size() / stride);
if (delta != 0) {
if (_cdata->_data.get_node_ref_count() > 1) {
// Copy-on-write: the data is already reffed somewhere else,
// so we're just going to make a copy.
PTA_uchar new_data(GeomVertexArrayData::get_class_type());
new_data.reserve(n * stride);
new_data.insert(new_data.end(), n * stride, 0);
memcpy(new_data, _cdata->_data,
min((size_t)(n * stride), _cdata->_data.size()));
_cdata->_data.node_unref();
_cdata->_data = new_data;
_cdata->_data.node_ref();
if (delta > 0) {
_cdata->_data.insert(_cdata->_data.end(), delta * stride, 0);
} else {
// We've got the only reference to the data, so we can change
// it directly.
if (delta > 0) {
_cdata->_data.insert(_cdata->_data.end(), delta * stride, 0);
} else {
_cdata->_data.erase(_cdata->_data.begin() + n * stride,
_cdata->_data.end());
}
_cdata->_data.erase(_cdata->_data.begin() + n * stride,
_cdata->_data.end());
}
_cdata->_modified = Geom::get_next_modified();
_cdata->_data_full_size = _cdata->_data.size();
if (get_current_thread()->get_pipeline_stage() == 0) {
_object->set_ram_class(RC_resident);
_object->set_lru_size(_cdata->_data_full_size);
}
return true;
}
@ -596,24 +800,30 @@ set_num_rows(int n) {
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::unclean_set_num_rows
// Function: GeomVertexArrayDataHandle::unclean_set_num_rows
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
bool GeomVertexArrayDataPipelineWriter::
bool GeomVertexArrayDataHandle::
unclean_set_num_rows(int n) {
nassertr(_writable, false);
check_resident();
int stride = _object->_array_format->get_stride();
int delta = n - (_cdata->_data.size() / stride);
if (delta != 0) {
// Just make a new array. No reason to keep the old one around.
PTA_uchar new_data = PTA_uchar::empty_array(n * stride, GeomVertexArrayData::get_class_type());
//_cdata->_data = GeomVertexArrayData::Data('\0', n * stride, GeomVertexArrayData::get_class_type());
_cdata->_data = PTA_uchar::empty_array(n * stride, GeomVertexArrayData::get_class_type());
_cdata->_data.node_unref();
_cdata->_data = new_data;
_cdata->_data.node_ref();
_cdata->_modified = Geom::get_next_modified();
_cdata->_data_full_size = _cdata->_data.size();
if (get_current_thread()->get_pipeline_stage() == 0) {
_object->set_ram_class(RC_resident);
_object->set_lru_size(_cdata->_data_full_size);
}
return true;
}
@ -621,37 +831,66 @@ unclean_set_num_rows(int n) {
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::modify_data
// Access: Published
// Description:
// Function: GeomVertexArrayDataHandle::copy_data_from
// Access: Public
// Description: Copies the entire data array from the other object.
////////////////////////////////////////////////////////////////////
PTA_uchar GeomVertexArrayDataPipelineWriter::
modify_data() {
// Perform copy-on-write: if the *node* reference count on the
// vertex data is greater than 1, assume some other
// GeomVertexArrayData has the same pointer, so make a copy of it
// first.
if (_cdata->_data.get_node_ref_count() > 1) {
PTA_uchar orig_data = _cdata->_data;
_cdata->_data.node_unref();
_cdata->_data = PTA_uchar(GeomVertexArrayData::get_class_type());
_cdata->_data.v() = orig_data.v();
_cdata->_data.node_ref();
void GeomVertexArrayDataHandle::
copy_data_from(const GeomVertexArrayDataHandle *other) {
nassertv(_writable);
check_resident();
other->check_resident();
_cdata->_data.v() = other->_cdata->_data.v();
_cdata->_modified = Geom::get_next_modified();
_cdata->_data_full_size = _cdata->_data.size();
if (get_current_thread()->get_pipeline_stage() == 0) {
_object->set_ram_class(RC_resident);
_object->set_lru_size(_cdata->_data_full_size);
}
_cdata->_modified = Geom::get_next_modified();
return _cdata->_data;
}
////////////////////////////////////////////////////////////////////
// Function: GeomVertexArrayDataPipelineWriter::set_data
// Access: Published
// Description:
// Function: GeomVertexArrayDataHandle::copy_subdata_from
// Access: Public
// Description: Copies a portion of the data array from the other
// object into a portion of the data array of this
// object. If to_size != from_size, the size of this
// data array is adjusted accordingly.
////////////////////////////////////////////////////////////////////
void GeomVertexArrayDataPipelineWriter::
set_data(CPTA_uchar array) {
_cdata->_data.node_unref();
_cdata->_data = (PTA_uchar &)array;
_cdata->_data.node_ref();
void GeomVertexArrayDataHandle::
copy_subdata_from(size_t to_start, size_t to_size,
const GeomVertexArrayDataHandle *other,
size_t from_start, size_t from_size) {
nassertv(_writable);
check_resident();
other->check_resident();
pvector<unsigned char> &to_v = _cdata->_data.v();
to_start = min(to_start, to_v.size());
to_size = min(to_size, to_v.size() - to_start);
from_start = min(from_start, other->_cdata->_data.size());
from_size = min(from_size, other->_cdata->_data.size() - from_start);
if (from_size < to_size) {
// Reduce the array.
to_v.erase(to_v.begin() + to_start + from_size, to_v.begin() + to_start + to_size);
} else if (to_size < from_size) {
// Expand the array.
to_v.insert(to_v.begin() + to_start + to_size, from_size - to_size, char());
}
// Now copy the data.
memcpy(&to_v[0] + to_start, other->get_pointer() + from_start, from_size);
_cdata->_modified = Geom::get_next_modified();
_cdata->_data_full_size = _cdata->_data.size();
if (get_current_thread()->get_pipeline_stage() == 0) {
_object->set_ram_class(RC_resident);
_object->set_lru_size(_cdata->_data_full_size);
}
}

View File

@ -33,11 +33,15 @@
#include "pipelineCycler.h"
#include "pStatCollector.h"
#include "pmap.h"
#include "reMutex.h"
#include "simpleLru.h"
class PreparedGraphicsObjects;
class VertexBufferContext;
class GraphicsStateGuardianBase;
class GeomVertexArrayDataHandle;
////////////////////////////////////////////////////////////////////
// Class : GeomVertexArrayData
// Description : This is the data for one array of a GeomVertexData
@ -57,7 +61,7 @@ class GraphicsStateGuardianBase;
// GeomVertexReader/Writer/Rewriter for high-level tools
// to manipulate the actual vertex data.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA GeomVertexArrayData : public CopyOnWriteObject, public GeomEnums {
class EXPCL_PANDA GeomVertexArrayData : public CopyOnWriteObject, public SimpleLruPage, public GeomEnums {
private:
GeomVertexArrayData();
@ -90,9 +94,8 @@ PUBLISHED:
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
INLINE CPTA_uchar get_data() const;
INLINE PTA_uchar modify_data();
INLINE void set_data(CPTA_uchar data);
INLINE CPT(GeomVertexArrayDataHandle) get_handle(Thread *current_thread = Thread::get_current_thread()) const;
INLINE PT(GeomVertexArrayDataHandle) modify_handle(Thread *current_thread = Thread::get_current_thread());
void prepare(PreparedGraphicsObjects *prepared_objects);
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
@ -102,10 +105,25 @@ PUBLISHED:
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
INLINE RamClass get_ram_class() const;
INLINE static SimpleLru *get_global_lru(RamClass rclass);
static void lru_epoch();
void make_resident();
void make_compressed();
void make_disk();
public:
virtual void evict_lru();
private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
PTA_uchar reverse_data_endianness(const PTA_uchar &data);
INLINE void set_ram_class(RamClass rclass);
CPT(GeomVertexArrayFormat) _array_format;
// A GeomVertexArrayData keeps a list (actually, a map) of all the
@ -120,11 +138,17 @@ private:
// to indicate the data must be endian-reversed in finalize().
bool _endian_reversed;
RamClass _ram_class;
typedef pvector<unsigned char> Data;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
INLINE void operator = (const CData &copy);
virtual ~CData();
ALLOC_DELETED_CHAIN(CData);
virtual CycleData *make_copy() const;
@ -138,7 +162,12 @@ private:
UsageHint _usage_hint;
PTA_uchar _data;
size_t _data_full_size;
UpdateSeq _modified;
// This implements read-write locking. Anyone who gets the data for
// reading or writing will hold this mutex during the lock.
ReMutex _rw_lock;
public:
static TypeHandle get_class_type() {
@ -160,6 +189,11 @@ private:
typedef CycleDataStageReader<CData> CDStageReader;
typedef CycleDataStageWriter<CData> CDStageWriter;
static SimpleLru _global_lru[RC_end_of_list];
static PStatCollector _vdata_compress_pcollector;
static PStatCollector _vdata_decompress_pcollector;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
@ -194,104 +228,92 @@ private:
friend class GeomCacheManager;
friend class GeomVertexData;
friend class PreparedGraphicsObjects;
friend class GeomVertexArrayDataPipelineBase;
friend class GeomVertexArrayDataPipelineReader;
friend class GeomVertexArrayDataPipelineWriter;
friend class GeomVertexArrayDataHandle;
};
////////////////////////////////////////////////////////////////////
// Class : GeomVertexArrayDataPipelineBase
// Description : The common code from
// Class : GeomVertexArrayDataHandle
// Description : This data object is returned by
// GeomVertexArrayData::get_handle() or modify_handle().
// As long as it exists, the data is locked; when the
// last of these destructs, the data is unlocked.
//
// Only one thread at a time may lock the data; other
// threads attempting to lock the data will block. A
// given thread may simultaneously lock the data
// multiple times.
//
// This class serves in lieu of a pair of
// GeomVertexArrayDataPipelineReader and
// GeomVertexArrayDataPipelineWriter.
// GeomVertexArrayDataPipelineWriter classes
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA GeomVertexArrayDataPipelineBase : public GeomEnums {
protected:
INLINE GeomVertexArrayDataPipelineBase(GeomVertexArrayData *object,
Thread *current_thread,
GeomVertexArrayData::CData *cdata);
class EXPCL_PANDA GeomVertexArrayDataHandle : public ReferenceCount, public GeomEnums {
private:
INLINE GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
Thread *current_thread,
const GeomVertexArrayData::CData *_cdata,
bool writable);
INLINE GeomVertexArrayDataHandle(const GeomVertexArrayDataHandle &);
INLINE void operator = (const GeomVertexArrayDataHandle &);
PUBLISHED:
INLINE ~GeomVertexArrayDataHandle();
public:
INLINE ~GeomVertexArrayDataPipelineBase();
ALLOC_DELETED_CHAIN(GeomVertexArrayDataHandle);
INLINE Thread *get_current_thread() const;
INLINE const GeomVertexArrayData *get_object() const;
INLINE GeomVertexArrayData *get_object();
INLINE const unsigned char *get_pointer() const;
INLINE unsigned char *get_pointer();
PUBLISHED:
INLINE const GeomVertexArrayFormat *get_array_format() const;
INLINE UsageHint get_usage_hint() const;
INLINE CPTA_uchar get_data() const;
INLINE int get_num_rows() const;
bool set_num_rows(int n);
bool unclean_set_num_rows(int n);
INLINE void clear_rows();
INLINE int get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
protected:
void copy_data_from(const GeomVertexArrayDataHandle *other);
void copy_subdata_from(size_t to_start, size_t to_size,
const GeomVertexArrayDataHandle *other,
size_t from_start, size_t from_size);
/*
INLINE string get_data() const;
void set_data(const string &data);
INLINE string get_subdata(size_t start, size_t size) const;
void set_subdata(size_t start, size_t size, const string &data);
*/
INLINE void check_resident() const;
private:
ReMutexHolder _holder;
PT(GeomVertexArrayData) _object;
Thread *_current_thread;
GeomVertexArrayData::CData *_cdata;
};
////////////////////////////////////////////////////////////////////
// Class : GeomVertexArrayDataPipelineReader
// Description : Encapsulates the data from a GeomVertexArrayData,
// pre-fetched for one stage of the pipeline.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA GeomVertexArrayDataPipelineReader : public GeomVertexArrayDataPipelineBase {
public:
INLINE GeomVertexArrayDataPipelineReader(const GeomVertexArrayData *object, Thread *current_thread);
private:
INLINE GeomVertexArrayDataPipelineReader(const GeomVertexArrayDataPipelineReader &copy);
INLINE void operator = (const GeomVertexArrayDataPipelineReader &copy);
public:
INLINE ~GeomVertexArrayDataPipelineReader();
ALLOC_DELETED_CHAIN(GeomVertexArrayDataPipelineReader);
INLINE const GeomVertexArrayData *get_object() const;
bool _writable;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
register_type(_type_handle, "GeomVertexArrayDataPipelineReader");
register_type(_type_handle, "GeomVertexArrayDataHandle");
}
private:
static TypeHandle _type_handle;
};
////////////////////////////////////////////////////////////////////
// Class : GeomVertexArrayDataPipelineWriter
// Description : Encapsulates the data from a GeomVertexArrayData,
// pre-fetched for one stage of the pipeline.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA GeomVertexArrayDataPipelineWriter : public GeomVertexArrayDataPipelineBase {
public:
INLINE GeomVertexArrayDataPipelineWriter(GeomVertexArrayData *object, bool force_to_0, Thread *current_thread);
private:
INLINE GeomVertexArrayDataPipelineWriter(const GeomVertexArrayDataPipelineWriter &copy);
INLINE void operator = (const GeomVertexArrayDataPipelineWriter &copy);
public:
INLINE ~GeomVertexArrayDataPipelineWriter();
ALLOC_DELETED_CHAIN(GeomVertexArrayDataPipelineWriter);
bool set_num_rows(int n);
bool unclean_set_num_rows(int n);
INLINE GeomVertexArrayData *get_object() const;
PTA_uchar modify_data();
void set_data(CPTA_uchar data);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
register_type(_type_handle, "GeomVertexArrayDataPipelineWriter");
}
private:
static TypeHandle _type_handle;
friend class GeomVertexArrayData;
};
INLINE ostream &operator << (ostream &out, const GeomVertexArrayData &obj);

View File

@ -711,7 +711,7 @@ check_array_readers() const {
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const GeomVertexArrayDataPipelineReader *GeomVertexDataPipelineReader::
INLINE const GeomVertexArrayDataHandle *GeomVertexDataPipelineReader::
get_array_reader(int i) const {
nassertr(_got_array_readers, NULL);
nassertr(i >= 0 && i < (int)_array_readers.size(), NULL);
@ -846,7 +846,7 @@ check_array_writers() const {
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GeomVertexArrayDataPipelineWriter *GeomVertexDataPipelineWriter::
INLINE GeomVertexArrayDataHandle *GeomVertexDataPipelineWriter::
get_array_writer(int i) const {
nassertr(_got_array_writers, NULL);
nassertr(i >= 0 && i < (int)_array_writers.size(), NULL);

View File

@ -426,10 +426,10 @@ set_slider_table(const SliderTable *table) {
// more of the arrays can be copied without the need to
// apply any conversion operation. If it is true, the
// original GeomVertexArrayData objects in this object
// are retained, but their data arrays are copied
// pointerwise from the source; if it is false, then the
// GeomVertexArrayData objects themselves are copied
// pointerwise from the source.
// are retained, and their data arrays are copied
// byte-by-byte from the source; if it is false, then the
// GeomVertexArrayData objects are copied pointerwise
// from the source.
//
// Don't call this in a downstream thread unless you
// don't mind it blowing away other changes you might
@ -465,13 +465,10 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
// Great! Just use the same data for this one.
if (keep_data_objects) {
// Copy the data, but keep the same GeomVertexArrayData object.
// Maybe it even has the same data pointer already. If so,
// avoid flipping the modified flag.
CPTA_uchar source_data = source->get_array(source_i)->get_data();
if (get_array(dest_i)->get_data() != source_data) {
modify_array(dest_i)->set_data(source_data);
}
PT(GeomVertexArrayData) dest_data = modify_array(dest_i);
CPT(GeomVertexArrayData) source_data = source->get_array(source_i);
dest_data->modify_handle()->copy_data_from(source_data->get_handle());
} else {
// Copy the GeomVertexArrayData object.
if (get_array(dest_i) != source->get_array(source_i)) {
@ -491,7 +488,8 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
// Now go back through and copy any data that's left over.
for (source_i = 0; source_i < num_arrays; ++source_i) {
CPT(GeomVertexArrayData) array_obj = source->get_array(source_i);
CPTA_uchar array_data = array_obj->get_data();
CPT(GeomVertexArrayDataHandle) array_handle = array_obj->get_handle();
const unsigned char *array_data = array_handle->get_pointer();
const GeomVertexArrayFormat *source_array_format = source_format->get_array(source_i);
int num_columns = source_array_format->get_num_columns();
for (int di = 0; di < num_columns; ++di) {
@ -509,7 +507,8 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
if (dest_column->is_bytewise_equivalent(*source_column)) {
// We can do a quick bytewise copy.
PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
PTA_uchar dest_array_data = dest_array_obj->modify_data();
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
unsigned char *dest_array_data = dest_handle->get_pointer();
bytewise_copy(dest_array_data + dest_column->get_start(),
dest_array_format->get_stride(),
@ -520,7 +519,8 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
source_column->is_uint8_rgba()) {
// A common special case: OpenGL color to DirectX color.
PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
PTA_uchar dest_array_data = dest_array_obj->modify_data();
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
unsigned char *dest_array_data = dest_handle->get_pointer();
uint8_rgba_to_packed_argb
(dest_array_data + dest_column->get_start(),
@ -533,7 +533,8 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
// Another common special case: DirectX color to OpenGL
// color.
PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
PTA_uchar dest_array_data = dest_array_obj->modify_data();
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
unsigned char *dest_array_data = dest_handle->get_pointer();
packed_argb_to_uint8_rgba
(dest_array_data + dest_column->get_start(),
@ -654,10 +655,12 @@ copy_row_from(int dest_row, const GeomVertexData *source,
for (int i = 0; i < num_arrays; ++i) {
PT(GeomVertexArrayData) dest_array_obj = modify_array(i);
PTA_uchar dest_array_data = dest_array_obj->modify_data();
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
unsigned char *dest_array_data = dest_handle->get_pointer();
CPT(GeomVertexArrayData) source_array_obj = source->get_array(i);
CPTA_uchar source_array_data = source_array_obj->get_data();
CPT(GeomVertexArrayDataHandle) source_array_handle = source_array_obj->get_handle();
const unsigned char *source_array_data = source_array_handle->get_pointer();
const GeomVertexArrayFormat *array_format = source_format->get_array(i);
int stride = array_format->get_stride();
@ -948,6 +951,7 @@ animate_vertices(Thread *current_thread) const {
CDWriter cdataw(((GeomVertexData *)this)->_cycler, cdata, false);
cdataw->_animated_vertices_modified = modified;
((GeomVertexData *)this)->update_animated_vertices(cdataw, current_thread);
return cdataw->_animated_vertices;
}
@ -1270,7 +1274,7 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
if (slider_value != 0.0f) {
CPT(InternalName) base_name = orig_format->get_morph_base(mi);
CPT(InternalName) delta_name = orig_format->get_morph_delta(mi);
GeomVertexRewriter data(new_data, base_name);
GeomVertexReader delta(this, delta_name);
int num_subranges = rows.get_num_subranges();
@ -1714,7 +1718,7 @@ get_num_rows() const {
////////////////////////////////////////////////////////////////////
bool GeomVertexDataPipelineReader::
get_array_info(const InternalName *name,
const GeomVertexArrayDataPipelineReader *&array_reader,
const GeomVertexArrayDataHandle *&array_reader,
int &num_values,
GeomVertexDataPipelineReader::NumericType &numeric_type,
int &start, int &stride) const {
@ -1738,7 +1742,7 @@ get_array_info(const InternalName *name,
// Description:
////////////////////////////////////////////////////////////////////
bool GeomVertexDataPipelineReader::
get_vertex_info(const GeomVertexArrayDataPipelineReader *&array_reader,
get_vertex_info(const GeomVertexArrayDataHandle *&array_reader,
int &num_values,
GeomVertexDataPipelineReader::NumericType &numeric_type,
int &start, int &stride) const {
@ -1763,7 +1767,7 @@ get_vertex_info(const GeomVertexArrayDataPipelineReader *&array_reader,
// Description:
////////////////////////////////////////////////////////////////////
bool GeomVertexDataPipelineReader::
get_normal_info(const GeomVertexArrayDataPipelineReader *&array_reader,
get_normal_info(const GeomVertexArrayDataHandle *&array_reader,
GeomVertexDataPipelineReader::NumericType &numeric_type,
int &start, int &stride) const {
nassertr(_got_array_readers, false);
@ -1787,7 +1791,7 @@ get_normal_info(const GeomVertexArrayDataPipelineReader *&array_reader,
// Description:
////////////////////////////////////////////////////////////////////
bool GeomVertexDataPipelineReader::
get_color_info(const GeomVertexArrayDataPipelineReader *&array_reader,
get_color_info(const GeomVertexArrayDataHandle *&array_reader,
int &num_values,
GeomVertexDataPipelineReader::NumericType &numeric_type,
int &start, int &stride) const {
@ -1818,7 +1822,8 @@ make_array_readers() {
_array_readers.reserve(_cdata->_arrays.size());
GeomVertexData::Arrays::const_iterator ai;
for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
_array_readers.push_back(new GeomVertexArrayDataPipelineReader((*ai).get_read_pointer(), _current_thread));
CPT(GeomVertexArrayData) array_obj = (*ai).get_read_pointer();
_array_readers.push_back(array_obj->get_handle(_current_thread));
}
_got_array_readers = true;
@ -1833,10 +1838,6 @@ void GeomVertexDataPipelineReader::
delete_array_readers() {
nassertv(_got_array_readers);
ArrayReaders::iterator ri;
for (ri = _array_readers.begin(); ri != _array_readers.end(); ++ri) {
delete (*ri);
}
_array_readers.clear();
_got_array_readers = false;
}
@ -1888,15 +1889,15 @@ set_num_rows(int n) {
}
if (color_array >= 0 && orig_color_rows < n) {
// We have just added some rows, fill the "color" column with
// We have just added some rows; fill the "color" column with
// (1, 1, 1, 1), for the programmer's convenience.
GeomVertexArrayDataPipelineWriter *array_writer = _array_writers[color_array];
GeomVertexArrayDataHandle *array_writer = _array_writers[color_array];
const GeomVertexArrayFormat *array_format = array_writer->get_array_format();
const GeomVertexColumn *column =
array_format->get_column(InternalName::get_color());
int stride = array_format->get_stride();
unsigned char *start =
array_writer->modify_data() + column->get_start();
array_writer->get_pointer() + column->get_start();
unsigned char *stop = start + array_writer->get_data_size_bytes();
unsigned char *pointer = start + stride * orig_color_rows;
int num_values = column->get_num_values();
@ -1999,8 +2000,7 @@ set_array(int i, const GeomVertexArrayData *array) {
_cdata->_animated_vertices_modified = UpdateSeq();
if (_got_array_writers) {
delete _array_writers[i];
_array_writers[i] = new GeomVertexArrayDataPipelineWriter(_cdata->_arrays[i].get_write_pointer(), _force_to_0, _current_thread);
_array_writers[i] = _cdata->_arrays[i].get_write_pointer()->modify_handle(_current_thread);
}
}
@ -2017,7 +2017,7 @@ make_array_writers() {
GeomVertexData::Arrays::iterator ai;
for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
PT(GeomVertexArrayData) array_obj = (*ai).get_write_pointer();
_array_writers.push_back(new GeomVertexArrayDataPipelineWriter(array_obj, _force_to_0, _current_thread));
_array_writers.push_back(array_obj->modify_handle(_current_thread));
}
_object->clear_cache_stage();
@ -2036,10 +2036,6 @@ void GeomVertexDataPipelineWriter::
delete_array_writers() {
nassertv(_got_array_writers);
ArrayWriters::iterator ri;
for (ri = _array_writers.begin(); ri != _array_writers.end(); ++ri) {
delete (*ri);
}
_array_writers.clear();
_got_array_writers = false;
}

View File

@ -409,27 +409,27 @@ public:
INLINE const GeomVertexData *get_object() const;
INLINE void check_array_readers() const;
INLINE const GeomVertexArrayDataPipelineReader *get_array_reader(int i) const;
INLINE const GeomVertexArrayDataHandle *get_array_reader(int i) const;
int get_num_rows() const;
bool get_array_info(const InternalName *name,
const GeomVertexArrayDataPipelineReader *&array_reader,
const GeomVertexArrayDataHandle *&array_reader,
int &num_values, NumericType &numeric_type,
int &start, int &stride) const;
INLINE bool has_vertex() const;
INLINE bool is_vertex_transformed() const;
bool get_vertex_info(const GeomVertexArrayDataPipelineReader *&array_reader,
bool get_vertex_info(const GeomVertexArrayDataHandle *&array_reader,
int &num_values, NumericType &numeric_type,
int &start, int &stride) const;
INLINE bool has_normal() const;
bool get_normal_info(const GeomVertexArrayDataPipelineReader *&array_reader,
bool get_normal_info(const GeomVertexArrayDataHandle *&array_reader,
NumericType &numeric_type,
int &start, int &stride) const;
INLINE bool has_color() const;
bool get_color_info(const GeomVertexArrayDataPipelineReader *&array_reader,
bool get_color_info(const GeomVertexArrayDataHandle *&array_reader,
int &num_values, NumericType &numeric_type,
int &start, int &stride) const;
@ -438,7 +438,7 @@ private:
void delete_array_readers();
bool _got_array_readers;
typedef pvector<GeomVertexArrayDataPipelineReader *> ArrayReaders;
typedef pvector<CPT(GeomVertexArrayDataHandle) > ArrayReaders;
ArrayReaders _array_readers;
public:
@ -473,7 +473,7 @@ public:
INLINE GeomVertexData *get_object() const;
INLINE void check_array_writers() const;
INLINE GeomVertexArrayDataPipelineWriter *get_array_writer(int i) const;
INLINE GeomVertexArrayDataHandle *get_array_writer(int i) const;
PT(GeomVertexArrayData) modify_array(int i);
void set_array(int i, const GeomVertexArrayData *array);
@ -488,7 +488,7 @@ private:
bool _force_to_0;
bool _got_array_writers;
typedef pvector<GeomVertexArrayDataPipelineWriter *> ArrayWriters;
typedef pvector<PT(GeomVertexArrayDataHandle) > ArrayWriters;
ArrayWriters _array_writers;
public:

View File

@ -575,9 +575,10 @@ write_with_data(ostream &out, int indent_level,
indent(out, indent_level)
<< data->get_num_rows() << " rows.\n";
for (size_t i = 0; i < _arrays.size(); i++) {
CPTA_uchar array_data = data->get_array(i)->get_data();
CPT(GeomVertexArrayDataHandle) handle = data->get_array(i)->get_handle();
const unsigned char *array_data = handle->get_pointer();
indent(out, indent_level)
<< "Array " << i << " (" << (void *)array_data.p() << ", "
<< "Array " << i << " (" << (void *)array_data << ", "
<< *_arrays[i] << "):\n";
_arrays[i]->write_with_data(out, indent_level + 2, data->get_array(i));
}

View File

@ -147,7 +147,7 @@ GeomVertexReader(const GeomVertexReader &copy) :
_current_thread(copy._current_thread),
_packer(copy._packer),
_stride(copy._stride),
_data(copy._data),
_handle(copy._handle),
_pointer_begin(copy._pointer_begin),
_pointer_end(copy._pointer_end),
_pointer(copy._pointer),
@ -168,7 +168,7 @@ operator = (const GeomVertexReader &copy) {
_current_thread = copy._current_thread;
_packer = copy._packer;
_stride = copy._stride;
_data = copy._data;
_handle = copy._handle;
_pointer_begin = copy._pointer_begin;
_pointer_end = copy._pointer_end;
_pointer = copy._pointer;
@ -242,9 +242,7 @@ set_column(int column) {
&reader);
}
if (_array_data != (const GeomVertexArrayData *)NULL) {
GeomVertexArrayDataPipelineReader reader(_array_data, _current_thread);
return set_array_column(reader.get_array_format()->get_column(column),
&reader);
return set_array_column(_array_data->get_array_format()->get_column(column));
}
return false;
}
@ -291,9 +289,7 @@ set_column(const InternalName *name) {
&reader);
}
if (_array_data != (const GeomVertexArrayData *)NULL) {
GeomVertexArrayDataPipelineReader reader(_array_data, _current_thread);
return set_array_column(reader.get_array_format()->get_column(name),
&reader);
return set_array_column(_array_data->get_array_format()->get_column(name));
}
return false;
@ -511,10 +507,9 @@ get_packer() const {
// and sets the internal pointer to the indicated row.
////////////////////////////////////////////////////////////////////
INLINE void GeomVertexReader::
set_pointer(int row, const GeomVertexArrayDataPipelineReader *array_reader) {
_data = array_reader->get_data();
_pointer_begin = _data;
_pointer_end = _pointer_begin + array_reader->get_data_size_bytes();
set_pointer(int row) {
_pointer_begin = _handle->get_pointer();
_pointer_end = _pointer_begin + _handle->get_data_size_bytes();
quick_set_pointer(row);
}
@ -529,21 +524,16 @@ INLINE void GeomVertexReader::
quick_set_pointer(int row) {
nassertv(has_column());
#if defined(_DEBUG) && !defined(HAVE_THREADS)
// Make sure we still have the same pointer as stored the array. We
// only perform this test in debug mode, because it is expensive,
// and only in single-threaded mode, because in threaded mode
// another thread might have reallocated the other pointer outside
// of our control anyway.
if (_vertex_data != (const GeomVertexData *)NULL) {
const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
nassertv(_pointer_begin == array_data->get_data());
} else {
nassertv(_pointer_begin == _array_data->get_data());
}
#if defined(_DEBUG)
// Make sure we still have the same pointer as stored in the array.
nassertv(_pointer_begin == _handle->get_pointer());
#endif
_pointer = _pointer_begin + _packer->_column->get_start() + _stride * row;
#if defined(_DEBUG)
nassertv(_pointer_begin == _pointer_end || _pointer < _pointer_end);
#endif
}
////////////////////////////////////////////////////////////////////
@ -554,14 +544,11 @@ quick_set_pointer(int row) {
////////////////////////////////////////////////////////////////////
INLINE const unsigned char *GeomVertexReader::
inc_pointer() {
#ifdef _DEBUG
#if defined(_DEBUG)
nassertr(_pointer < _pointer_end, empty_buffer);
if (_vertex_data != (const GeomVertexData *)NULL){
const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
nassertr(_pointer >= array_data->get_data().p() && _pointer < array_data->get_data().p() + array_data->get_data_size_bytes(), empty_buffer);
} else {
nassertr(_pointer >= _array_data->get_data().p() && _pointer < _array_data->get_data().p() + _array_data->get_data_size_bytes(), empty_buffer);
}
// Make sure we still have the same pointer as stored in the array.
nassertr(_pointer_begin == _handle->get_pointer(), empty_buffer);
nassertr(_pointer < _pointer_begin + _handle->get_data_size_bytes(), empty_buffer);
#endif
const unsigned char *orig_pointer = _pointer;

View File

@ -57,8 +57,7 @@ set_column(int array, const GeomVertexColumn *column) {
return set_vertex_column(array, column, &reader);
}
if (_array_data != (const GeomVertexArrayData *)NULL) {
GeomVertexArrayDataPipelineReader reader(_array_data, _current_thread);
return set_array_column(column, &reader);
return set_array_column(column);
}
// No data is associated with the Reader.
@ -121,12 +120,11 @@ set_vertex_column(int array, const GeomVertexColumn *column,
#endif
_array = array;
const GeomVertexArrayDataPipelineReader *array_reader =
data_reader->get_array_reader(_array);
_stride = array_reader->get_array_format()->get_stride();
_handle = data_reader->get_array_reader(_array);
_stride = _handle->get_array_format()->get_stride();
_packer = column->_packer;
set_pointer(_start_row, array_reader);
set_pointer(_start_row);
return true;
}
@ -139,18 +137,18 @@ set_vertex_column(int array, const GeomVertexColumn *column,
// GeomVertexArrayData.
////////////////////////////////////////////////////////////////////
bool GeomVertexReader::
set_array_column(const GeomVertexColumn *column,
const GeomVertexArrayDataPipelineReader *array_reader) {
set_array_column(const GeomVertexColumn *column) {
if (column == (const GeomVertexColumn *)NULL) {
return set_column(0, NULL);
}
nassertr(_array_data != (const GeomVertexArrayData *)NULL, false);
_stride = array_reader->get_array_format()->get_stride();
_handle = _array_data->get_handle();
_stride = _handle->get_array_format()->get_stride();
_packer = column->_packer;
set_pointer(_start_row, array_reader);
set_pointer(_start_row);
return true;
}

View File

@ -120,15 +120,13 @@ protected:
private:
void initialize();
INLINE void set_pointer(int row,
const GeomVertexArrayDataPipelineReader *array_reader);
INLINE void set_pointer(int row);
INLINE void quick_set_pointer(int row);
INLINE const unsigned char *inc_pointer();
bool set_vertex_column(int array, const GeomVertexColumn *column,
const GeomVertexDataPipelineReader *data_reader);
bool set_array_column(const GeomVertexColumn *column,
const GeomVertexArrayDataPipelineReader *array_reader);
bool set_array_column(const GeomVertexColumn *column);
// It is important that we only store *one* of the following two
// pointers. If we are storing a GeomVertexData/array index, we
@ -143,7 +141,7 @@ private:
GeomVertexColumn::Packer *_packer;
int _stride;
CPTA_uchar _data;
CPT(GeomVertexArrayDataHandle) _handle;
const unsigned char *_pointer_begin;
const unsigned char *_pointer_end;
const unsigned char *_pointer;

View File

@ -145,7 +145,7 @@ GeomVertexWriter(const GeomVertexWriter &copy) :
_current_thread(copy._current_thread),
_packer(copy._packer),
_stride(copy._stride),
_data(copy._data),
_handle(copy._handle),
_pointer_begin(copy._pointer_begin),
_pointer_end(copy._pointer_end),
_pointer(copy._pointer),
@ -166,7 +166,7 @@ operator = (const GeomVertexWriter &copy) {
_current_thread = copy._current_thread;
_packer = copy._packer;
_stride = copy._stride;
_data = copy._data;
_handle = copy._handle;
_pointer_begin = copy._pointer_begin;
_pointer_end = copy._pointer_end;
_pointer = copy._pointer;
@ -240,9 +240,7 @@ set_column(int column) {
&writer);
}
if (_array_data != (GeomVertexArrayData *)NULL) {
GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
return set_array_column(writer.get_array_format()->get_column(column),
&writer);
return set_array_column(_array_data->get_array_format()->get_column(column));
}
return false;
}
@ -289,9 +287,7 @@ set_column(const InternalName *name) {
&writer);
}
if (_array_data != (GeomVertexArrayData *)NULL) {
GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
return set_array_column(writer.get_array_format()->get_column(name),
&writer);
return set_array_column(_array_data->get_array_format()->get_column(name));
}
return false;
}
@ -814,10 +810,9 @@ get_packer() const {
// and sets the internal pointer to the indicated row.
////////////////////////////////////////////////////////////////////
INLINE void GeomVertexWriter::
set_pointer(int row, GeomVertexArrayDataPipelineWriter *array_writer) {
_data = array_writer->modify_data();
_pointer_begin = _data;
_pointer_end = _pointer_begin + array_writer->get_data_size_bytes();
set_pointer(int row) {
_pointer_begin = _handle->get_pointer();
_pointer_end = _pointer_begin + _handle->get_data_size_bytes();
quick_set_pointer(row);
}
@ -832,21 +827,16 @@ INLINE void GeomVertexWriter::
quick_set_pointer(int row) {
nassertv(has_column());
#if defined(_DEBUG) && !defined(HAVE_THREADS)
// Make sure we still have the same pointer as stored the array. We
// only perform this test in debug mode, because it is expensive,
// and only in single-threaded mode, because in threaded mode
// another thread might have reallocated the other pointer outside
// of our control anyway.
if (_vertex_data != (const GeomVertexData *)NULL) {
const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
nassertv(_pointer_begin == array_data->get_data());
} else {
nassertv(_pointer_begin == _array_data->get_data());
}
#if defined(_DEBUG)
// Make sure we still have the same pointer as stored in the array.
nassertv(_pointer_begin == _handle->get_pointer());
#endif
_pointer = _pointer_begin + _packer->_column->get_start() + _stride * row;
#if defined(_DEBUG)
nassertv(_pointer_begin == _pointer_end || _pointer <= _pointer_end);
#endif
}
////////////////////////////////////////////////////////////////////
@ -857,14 +847,11 @@ quick_set_pointer(int row) {
////////////////////////////////////////////////////////////////////
INLINE unsigned char *GeomVertexWriter::
inc_pointer() {
#ifdef _DEBUG
#if defined(_DEBUG)
nassertr(_pointer < _pointer_end, empty_buffer);
if (_vertex_data != (GeomVertexData *)NULL){
const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
nassertr(_pointer >= array_data->get_data().p() && _pointer < array_data->get_data().p() + array_data->get_data_size_bytes(), empty_buffer);
} else {
nassertr(_pointer >= _array_data->get_data().p() && _pointer < _array_data->get_data().p() + _array_data->get_data_size_bytes(), empty_buffer);
}
// Make sure we still have the same pointer as stored in the array.
nassertr(_pointer_begin == _handle->get_pointer(), empty_buffer);
nassertr(_pointer < _pointer_begin + _handle->get_data_size_bytes(), empty_buffer);
#endif
unsigned char *orig_pointer = _pointer;
@ -885,16 +872,23 @@ inc_add_pointer() {
if (_pointer >= _pointer_end) {
// Reset the data pointer.
int write_row = get_write_row();
if (_vertex_data != (GeomVertexData *)NULL) {
// If we have a whole GeomVertexData, we must set the length of
// all its arrays at once.
GeomVertexDataPipelineWriter writer(_vertex_data, true, _current_thread);
writer.check_array_writers();
writer.set_num_rows(max(write_row + 1, writer.get_num_rows()));
set_pointer(write_row, writer.get_array_writer(_array));
_handle = writer.get_array_writer(_array);
} else {
GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
writer.set_num_rows(max(write_row + 1, writer.get_num_rows()));
set_pointer(write_row, &writer);
// Otherwise, we can get away with modifying only the one array
// we're using.
_handle->set_num_rows(max(write_row + 1, _handle->get_num_rows()));
}
set_pointer(write_row);
}
return inc_pointer();
}

View File

@ -62,8 +62,7 @@ set_column(int array, const GeomVertexColumn *column) {
return set_vertex_column(array, column, &writer);
}
if (_array_data != (GeomVertexArrayData *)NULL) {
GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
return set_array_column(column, &writer);
return set_array_column(column);
}
// No data is associated with the Writer.
@ -126,12 +125,11 @@ set_vertex_column(int array, const GeomVertexColumn *column,
#endif
_array = array;
GeomVertexArrayDataPipelineWriter *array_writer =
data_writer->get_array_writer(_array);
_stride = array_writer->get_array_format()->get_stride();
_handle = data_writer->get_array_writer(_array);
_stride = _handle->get_array_format()->get_stride();
_packer = column->_packer;
set_pointer(_start_row, array_writer);
set_pointer(_start_row);
return true;
}
@ -144,18 +142,18 @@ set_vertex_column(int array, const GeomVertexColumn *column,
// GeomVertexArrayData.
////////////////////////////////////////////////////////////////////
bool GeomVertexWriter::
set_array_column(const GeomVertexColumn *column,
GeomVertexArrayDataPipelineWriter *array_writer) {
set_array_column(const GeomVertexColumn *column) {
if (column == (const GeomVertexColumn *)NULL) {
return set_column(0, NULL);
}
nassertr(_array_data != (GeomVertexArrayData *)NULL, false);
_stride = array_writer->get_array_format()->get_stride();
_handle = _array_data->modify_handle();
_stride = _handle->get_array_format()->get_stride();
_packer = column->_packer;
set_pointer(_start_row, array_writer);
set_pointer(_start_row);
return true;
}

View File

@ -157,16 +157,14 @@ private:
void initialize();
INLINE void set_pointer(int row,
GeomVertexArrayDataPipelineWriter *array_writer);
INLINE void set_pointer(int row);
INLINE void quick_set_pointer(int row);
INLINE unsigned char *inc_pointer();
INLINE unsigned char *inc_add_pointer();
bool set_vertex_column(int array, const GeomVertexColumn *column,
GeomVertexDataPipelineWriter *data_writer);
bool set_array_column(const GeomVertexColumn *column,
GeomVertexArrayDataPipelineWriter *array_writer);
bool set_array_column(const GeomVertexColumn *column);
// It is important that we only store *one* of the following two
// pointers. If we are storing a GeomVertexData/array index, we
@ -181,7 +179,7 @@ private:
GeomVertexColumn::Packer *_packer;
int _stride;
PTA_uchar _data;
PT(GeomVertexArrayDataHandle) _handle;
unsigned char *_pointer_begin;
unsigned char *_pointer_end;
unsigned char *_pointer;

View File

@ -1,25 +1,28 @@
#include "bufferContext.cxx"
#include "bufferContextChain.cxx"
#include "bufferResidencyTracker.cxx"
#include "config_gobj.cxx"
#include "geom.cxx"
#include "geomContext.cxx"
#include "geomEnums.cxx"
#include "geomMunger.cxx"
#include "geomPrimitive.cxx"
#include "geomTriangles.cxx"
#include "geomTristrips.cxx"
#include "geomTrifans.cxx"
#include "geomLines.cxx"
#include "geomLinestrips.cxx"
#include "geomPoints.cxx"
#include "geomVertexArrayData.cxx"
#include "geomVertexArrayFormat.cxx"
#include "geomCacheEntry.cxx"
#include "geomCacheManager.cxx"
#include "geomContext.cxx"
#include "geomEnums.cxx"
#include "geomLines.cxx"
#include "geomLinestrips.cxx"
#include "geomMunger.cxx"
#include "geomPoints.cxx"
#include "geomPrimitive.cxx"
#include "geomTriangles.cxx"
#include "geomTrifans.cxx"
#include "geomTristrips.cxx"
#include "geomVertexAnimationSpec.cxx"
#include "geomVertexData.cxx"
#include "geomVertexArrayData.cxx"
#include "geomVertexArrayFormat.cxx"
#include "geomVertexColumn.cxx"
#include "geomVertexData.cxx"
#include "geomVertexFormat.cxx"
#include "geomVertexReader.cxx"
#include "geomVertexRewriter.cxx"
#include "geomVertexWriter.cxx"
#include "indexBufferContext.cxx"
#include "internalName.cxx"

View File

@ -1,6 +1,3 @@
#include "config_gobj.cxx"
#include "indexBufferContext.cxx"
#include "internalName.cxx"
#include "lens.cxx"
#include "material.cxx"
#include "materialPool.cxx"
@ -11,14 +8,15 @@
#include "preparedGraphicsObjects.cxx"
#include "queryContext.cxx"
#include "savedContext.cxx"
#include "shaderContext.cxx"
#include "shaderExpansion.cxx"
#include "simpleLru.cxx"
#include "sliderTable.cxx"
#include "texture.cxx"
#include "textureContext.cxx"
#include "texturePool.cxx"
#include "texturePoolFilter.cxx"
#include "textureStage.cxx"
#include "shaderExpansion.cxx"
#include "shaderContext.cxx"
#include "transformBlend.cxx"
#include "transformBlendTable.cxx"
#include "transformTable.cxx"

203
panda/src/gobj/simpleLru.I Normal file
View File

@ -0,0 +1,203 @@
// Filename: simpleLru.I
// Created by: drose (11May07)
//
////////////////////////////////////////////////////////////////////
//
// 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: SimpleLru::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
SimpleLru::
SimpleLru(size_t max_size) : LinkedListNode(true) {
_total_size = 0;
_max_size = max_size;
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLru::get_total_size
// Access: Published
// Description: Returns the total size of all objects currently
// active on the LRU.
////////////////////////////////////////////////////////////////////
INLINE size_t SimpleLru::
get_total_size() const {
return _total_size;
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLru::get_max_size
// Access: Published
// Description: Returns the max size of all objects that are allowed
// to be active on the LRU.
////////////////////////////////////////////////////////////////////
INLINE size_t SimpleLru::
get_max_size() const {
return _max_size;
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLru::set_max_size
// Access: Published
// Description: Changes the max size of all objects that are allowed
// to be active on the LRU.
////////////////////////////////////////////////////////////////////
INLINE void SimpleLru::
set_max_size(size_t max_size) {
_max_size = max_size;
consider_evict();
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLru::consider_evict
// Access: Published
// Description: Evicts a sequence of objects if the queue is full.
////////////////////////////////////////////////////////////////////
INLINE void SimpleLru::
consider_evict() {
if (_max_size != 0 && _total_size > _max_size) {
do_evict();
}
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE SimpleLruPage::
SimpleLruPage(size_t lru_size) :
_lru(NULL),
_lru_size(lru_size)
{
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::Copy Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE SimpleLruPage::
SimpleLruPage(const SimpleLruPage &copy) :
_lru(NULL),
_lru_size(copy._lru_size)
{
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::Copy Assignment Operator
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE void SimpleLruPage::
operator = (const SimpleLruPage &copy) {
set_lru_size(copy.get_lru_size());
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::enqueue_lru
// Access: Published
// Description: Returns the LRU that manages this page, or NULL if it
// is not currently managed by any LRU.
////////////////////////////////////////////////////////////////////
INLINE SimpleLru *SimpleLruPage::
get_lru() const {
return _lru;
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::enqueue_lru
// Access: Published
// Description: Adds the page to the tail of the SimpleLru. When it
// reaches the head, it will be the next to be evicted.
////////////////////////////////////////////////////////////////////
INLINE void SimpleLruPage::
enqueue_lru(SimpleLru *lru) {
dequeue_lru();
_lru = lru;
_lru->_total_size += _lru_size;
insert_before(_lru);
// Let's not automatically evict pages; instead, we'll evict only on
// an explicit epoch test.
// _lru->consider_evict();
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::dequeue_lru
// Access: Published
// Description: Removes the page from its SimpleLru.
////////////////////////////////////////////////////////////////////
INLINE void SimpleLruPage::
dequeue_lru() {
if (_lru != (SimpleLru *)NULL) {
remove_from_list();
_lru->_total_size -= _lru_size;
_lru = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::mark_used_lru
// Access: Published
// Description: To be called when the page is used; this will move it
// to the tail of the SimpleLru queue it is already on.
////////////////////////////////////////////////////////////////////
INLINE void SimpleLruPage::
mark_used_lru() {
if (_lru != (SimpleLru *)NULL) {
mark_used_lru(_lru);
}
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::mark_used_lru
// Access: Published
// Description: To be called when the page is used; this will move it
// to the tail of the specified SimpleLru queue.
////////////////////////////////////////////////////////////////////
INLINE void SimpleLruPage::
mark_used_lru(SimpleLru *lru) {
dequeue_lru();
enqueue_lru(lru);
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::get_lru_size
// Access: Published
// Description: Returns the size of this page as reported to the LRU,
// presumably in bytes.
////////////////////////////////////////////////////////////////////
INLINE size_t SimpleLruPage::
get_lru_size() const {
return _lru_size;
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::set_lru_size
// Access: Published
// Description: Specifies the size of this page, presumably in bytes,
// although any units is possible.
////////////////////////////////////////////////////////////////////
INLINE void SimpleLruPage::
set_lru_size(size_t lru_size) {
if (_lru != (SimpleLru *)NULL) {
_lru->_total_size -= _lru_size;
_lru->_total_size += lru_size;
}
_lru_size = lru_size;
}

View File

@ -0,0 +1,96 @@
// Filename: simpleLru.cxx
// Created by: drose (11May07)
//
////////////////////////////////////////////////////////////////////
//
// 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 "simpleLru.h"
////////////////////////////////////////////////////////////////////
// Function: SimpleLru::Destructor
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
SimpleLru::
~SimpleLru() {
#ifndef NDEBUG
// We're shutting down. Force-remove everything remaining, but
// don't explicitly evict it (that would force vertex buffers to
// write themselves to disk unnecessarily).
while (_next != (LinkedListNode *)NULL) {
((SimpleLruPage *)_next)->_lru = NULL;
((SimpleLruPage *)_next)->remove_from_list();
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLru::do_evict
// Access: Private
// Description: Evicts pages until the LRU is within tolerance.
////////////////////////////////////////////////////////////////////
void SimpleLru::
do_evict() {
// Store the current end of the list. If pages re-enqueue
// themselves during this traversal, we don't want to visit them
// twice.
SimpleLruPage *end = (SimpleLruPage *)_prev;
// Now walk through the list.
SimpleLruPage *node = (SimpleLruPage *)_next;
while (_total_size > _max_size) {
SimpleLruPage *next = (SimpleLruPage *)node->_next;
node->evict_lru();
if (node == end) {
// If we reach the original tail of the list, stop.
return;
}
node = next;
}
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
SimpleLruPage::
~SimpleLruPage() {
if (_lru != NULL) {
dequeue_lru();
}
}
////////////////////////////////////////////////////////////////////
// Function: SimpleLruPage::evict_lru
// Access: Published, Virtual
// Description: Evicts the page from the LRU. Called internally when
// the LRU determines that it is full. May also be
// called externally when necessary to explicitly evict
// the page.
//
// It is legal for this method to either evict the page
// as requested, do nothing (in which case the eviction
// will be requested again at the next epoch), or
// requeue itself on the tail of the queue (in which
// case the eviction will be requested again much
// later).
////////////////////////////////////////////////////////////////////
void SimpleLruPage::
evict_lru() {
dequeue_lru();
}

View File

@ -0,0 +1,88 @@
// Filename: simpleLru.h
// Created by: drose (11May07)
//
////////////////////////////////////////////////////////////////////
//
// 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 SIMPLELRU_H
#define SIMPLELRU_H
#include "pandabase.h"
#include "linkedListNode.h"
class SimpleLruPage;
////////////////////////////////////////////////////////////////////
// Class : SimpleLru
// Description : An implementation of a very simple LRU algorithm.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA SimpleLru : public LinkedListNode {
PUBLISHED:
INLINE SimpleLru(size_t max_size);
~SimpleLru();
INLINE size_t get_total_size() const;
INLINE size_t get_max_size() const;
INLINE void set_max_size(size_t max_size);
INLINE void consider_evict();
private:
void do_evict();
size_t _total_size;
size_t _max_size;
friend class SimpleLruPage;
};
////////////////////////////////////////////////////////////////////
// Class : SimpleLruPage
// Description : One atomic piece that may be managed by a SimpleLru
// chain. To use this class, inherit from it and
// override evict_lru().
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA SimpleLruPage : public LinkedListNode {
PUBLISHED:
INLINE SimpleLruPage(size_t lru_size);
INLINE SimpleLruPage(const SimpleLruPage &copy);
INLINE void operator = (const SimpleLruPage &copy);
virtual ~SimpleLruPage();
INLINE SimpleLru *get_lru() const;
INLINE void enqueue_lru(SimpleLru *lru);
INLINE void dequeue_lru();
INLINE void mark_used_lru();
INLINE void mark_used_lru(SimpleLru *lru);
INLINE size_t get_lru_size() const;
INLINE void set_lru_size(size_t lru_size);
virtual void evict_lru();
private:
SimpleLru *_lru;
size_t _lru_size;
friend class SimpleLru;
};
#include "simpleLru.I"
#endif

View File

@ -47,7 +47,7 @@ get_data() const {
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool VertexBufferContext::
changed_size(const GeomVertexArrayDataPipelineReader *reader) const {
changed_size(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
return get_data_size_bytes() != (size_t)reader->get_data_size_bytes();
}
@ -59,7 +59,7 @@ changed_size(const GeomVertexArrayDataPipelineReader *reader) const {
// since the last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool VertexBufferContext::
changed_usage_hint(const GeomVertexArrayDataPipelineReader *reader) const {
changed_usage_hint(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
return _usage_hint != reader->get_usage_hint();
}
@ -71,7 +71,7 @@ changed_usage_hint(const GeomVertexArrayDataPipelineReader *reader) const {
// last time mark_loaded() was called.
////////////////////////////////////////////////////////////////////
INLINE bool VertexBufferContext::
was_modified(const GeomVertexArrayDataPipelineReader *reader) const {
was_modified(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
return get_modified() != reader->get_modified();
}
@ -84,7 +84,7 @@ was_modified(const GeomVertexArrayDataPipelineReader *reader) const {
// internal flags for changed_size() and modified().
////////////////////////////////////////////////////////////////////
INLINE void VertexBufferContext::
mark_loaded(const GeomVertexArrayDataPipelineReader *reader) {
mark_loaded(const GeomVertexArrayDataHandle *reader) {
nassertv(reader->get_object() == _data);
update_data_size_bytes(reader->get_data_size_bytes());
update_modified(reader->get_modified());

View File

@ -44,12 +44,12 @@ public:
PUBLISHED:
INLINE GeomVertexArrayData *get_data() const;
INLINE bool changed_size(const GeomVertexArrayDataPipelineReader *reader) const;
INLINE bool changed_usage_hint(const GeomVertexArrayDataPipelineReader *reader) const;
INLINE bool was_modified(const GeomVertexArrayDataPipelineReader *reader) const;
INLINE bool changed_size(const GeomVertexArrayDataHandle *reader) const;
INLINE bool changed_usage_hint(const GeomVertexArrayDataHandle *reader) const;
INLINE bool was_modified(const GeomVertexArrayDataHandle *reader) const;
public:
INLINE void mark_loaded(const GeomVertexArrayDataPipelineReader *reader);
INLINE void mark_loaded(const GeomVertexArrayDataHandle *reader);
private:
// This cannot be a PT(GeomVertexArrayData), because the data and

View File

@ -484,15 +484,16 @@ collect_vertex_data(Geom *geom, int collect_bits) {
new_data->set_num_rows(new_num_vertices);
for (int i = 0; i < vdata->get_num_arrays(); ++i) {
GeomVertexArrayData *new_array = new_data->modify_array(i);
const GeomVertexArrayData *old_array = vdata->get_array(i);
PT(GeomVertexArrayData) new_array = new_data->modify_array(i);
CPT(GeomVertexArrayData) old_array = vdata->get_array(i);
int stride = format->get_array(i)->get_stride();
int start_byte = offset * stride;
int copy_bytes = old_array->get_data_size_bytes();
nassertr(start_byte + copy_bytes == new_array->get_data_size_bytes(), 0);
memcpy(new_array->modify_data() + start_byte,
old_array->get_data(), copy_bytes);
new_array->modify_handle()->copy_subdata_from
(start_byte, copy_bytes,
old_array->get_handle(), 0, copy_bytes);
}
// Also, copy the animation data (if any). This means combining

View File

@ -67,7 +67,7 @@ flatten(PandaNode *root, int combine_siblings_bits) {
// Now visit each of the children in turn.
int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) {
PandaNode *child_node = cr.get_child(i);
PT(PandaNode) child_node = cr.get_child(i);
num_pass_nodes += r_flatten(root, child_node, combine_siblings_bits);
}
@ -271,7 +271,7 @@ r_flatten(PandaNode *grandparent_node, PandaNode *parent_node,
PandaNode::Children cr = parent_node->get_children();
int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) {
PandaNode *child_node = cr.get_child(i);
PT(PandaNode) child_node = cr.get_child(i);
num_nodes += r_flatten(parent_node, child_node, combine_siblings_bits);
}
}

View File

@ -231,7 +231,7 @@ main_tick() {
size_t total_usage = 0;
int i;
for (int i = 0; i < num_typehandles; ++i) {
for (i = 0; i < num_typehandles; ++i) {
TypeHandle type = type_reg->get_typehandle(i);
for (int mi = 0; mi < (int)TypeHandle::MC_limit; ++mi) {
TypeHandle::MemoryClass mc = (TypeHandle::MemoryClass)mi;
@ -245,7 +245,7 @@ main_tick() {
}
size_t other_usage = total_usage;
for (int i = 0; i < num_typehandles; ++i) {
for (i = 0; i < num_typehandles; ++i) {
TypeHandle type = type_reg->get_typehandle(i);
for (int mi = 0; mi < (int)TypeHandle::MC_limit; ++mi) {
TypeHandle::MemoryClass mc = (TypeHandle::MemoryClass)mi;

View File

@ -199,6 +199,10 @@ static LevelCollectorProperties level_properties[] = {
{ 1, "Main memory", { 0.5, 1.0, 0.5 }, "MB", 64, 1048576 },
{ 1, "Main memory:C++", { 0.2, 0.2, 1.0 } },
{ 1, "Main memory:Interpreter", { 0.8, 0.2, 0.5 } },
{ 1, "Vertex Data", { 1.0, 0.4, 0.0 }, "MB", 64, 1048576 },
{ 1, "Vertex Data:Disk", { 0.6, 0.9, 0.1 } },
{ 1, "Vertex Data:Compressed", { 0.5, 0.1, 0.4 } },
{ 1, "Vertex Data:Resident", { 0.9, 0.1, 0.7 } },
{ 1, "TransformStates", { 1.0, 0.5, 0.5 }, "", 5000 },
{ 1, "TransformStates:On nodes", { 0.2, 0.8, 1.0 } },
{ 1, "TransformStates:Cached", { 1.0, 0.0, 0.2 } },

View File

@ -121,7 +121,7 @@ get_write_pointer() {
if (_object == (CopyOnWriteObject *)NULL) {
return NULL;
}
if (_object->get_ref_count() > 1) {
if (_object->get_cache_ref_count() > 1) {
PT(CopyOnWriteObject) new_object = _object->make_cow_copy();
cache_unref_delete(_object);
_object = new_object;