32 (
"max-independent-vertex-data", -1,
33 PRC_DESC(
"Specifies the maximum number of bytes of all vertex data " 34 "that is independent of the paging system. This is an " 35 "initial buffer before max-ram-vertex-data, specifically " 36 "designed for vertex datas that are dynamic in nature and " 37 "may change size or be created and destroyed frequently."));
40 (
"vertex-data-page-size", 262144,
41 PRC_DESC(
"The number of bytes to allocate at a time for vertex data. " 42 "This also controls the page size that is compressed or written " 43 "to disk when vertex data pages are evicted from memory."));
45 SimpleLru GeomVertexArrayData::_independent_lru(
"independent", max_independent_vertex_data);
46 SimpleLru GeomVertexArrayData::_small_lru(
"small", max_independent_vertex_data);
52 TypeHandle GeomVertexArrayData::CData::_type_handle;
53 TypeHandle GeomVertexArrayDataHandle::_type_handle;
81 GeomVertexArrayData::UsageHint usage_hint) :
83 _array_format(array_format),
84 _cycler(CData(usage_hint)),
88 nassertv(_array_format->is_registered());
98 _array_format(copy._array_format),
99 _cycler(copy._cycler),
104 set_lru_size(get_data_size_bytes());
105 nassertv(_array_format->is_registered());
115 CopyOnWriteObject::operator = (copy);
116 SimpleLruPage::operator = (copy);
120 _array_format = copy._array_format;
121 _cycler = copy._cycler;
123 OPEN_ITERATE_ALL_STAGES(_cycler) {
127 CLOSE_ITERATE_ALL_STAGES(_cycler);
129 nassertv(_array_format->is_registered());
135 GeomVertexArrayData::
136 ~GeomVertexArrayData() {
146 Thread *current_thread = Thread::get_current_thread();
151 if (handle->get_usage_hint() != other_handle->get_usage_hint()) {
152 return (
int)handle->
get_usage_hint() - (int)other_handle->get_usage_hint();
154 if (handle->get_array_format() != other_handle->get_array_format()) {
155 return handle->get_array_format() < other_handle->get_array_format() ? -1 : 1;
157 if (handle->get_data_size_bytes() != other_handle->get_data_size_bytes()) {
158 return (
int)handle->get_data_size_bytes() - (int)other_handle->get_data_size_bytes();
160 return memcmp(handle->get_read_pointer(
true),
161 other_handle->get_read_pointer(
true),
162 handle->get_data_size_bytes());
173 CDWriter cdata(_cycler,
true);
174 cdata->_usage_hint = usage_hint;
181 void GeomVertexArrayData::
182 output(std::ostream &out)
const {
189 void GeomVertexArrayData::
190 write(std::ostream &out,
int indent_level)
const {
191 _array_format->write_with_data(out, indent_level,
this);
213 if (_contexts ==
nullptr) {
216 Contexts::const_iterator ci;
217 ci = _contexts->find(prepared_objects);
218 if (ci != _contexts->end()) {
238 if (_contexts ==
nullptr) {
241 Contexts::const_iterator ci;
242 ci = _contexts->find(prepared_objects);
243 if (ci != _contexts->end()) {
248 if (vbc !=
nullptr) {
249 (*_contexts)[prepared_objects] = vbc;
260 if (_contexts !=
nullptr) {
261 Contexts::iterator ci;
262 ci = _contexts->find(prepared_objects);
263 if (ci != _contexts->end()) {
282 if (_contexts !=
nullptr) {
288 num_freed = (int)_contexts->size();
290 Contexts::const_iterator ci;
291 for (ci = temp.begin(); ci != temp.end(); ++ci) {
299 nassertr(_contexts ==
nullptr, num_freed);
330 cdata->_buffer.page_out(_book);
339 void GeomVertexArrayData::
341 nassertv(_contexts !=
nullptr);
343 Contexts::iterator ci;
344 ci = _contexts->find(prepared_objects);
345 if (ci != _contexts->end()) {
346 _contexts->erase(ci);
347 if (_contexts->empty()) {
354 nassert_raise(
"unknown PreparedGraphicsObjects");
363 void GeomVertexArrayData::
364 reverse_data_endianness(
unsigned char *dest,
const unsigned char *source,
366 int num_columns = _array_format->get_num_columns();
369 for (
size_t pi = 0; pi < size; pi += _array_format->get_stride()) {
372 for (
int ci = 0; ci < num_columns; ++ci) {
375 if (component_bytes > 1) {
380 for (
int cj = 0; cj < num_components; ++cj) {
383 nd.store_value(dest + ci, component_bytes);
384 ci += component_bytes;
418 PTA_uchar data = PTA_uchar::empty_array(size, get_class_type());
419 const unsigned char *source_data =
457 GeomVertexArrayFormat::register_format(_array_format);
460 _array_format = new_array_format;
462 PT(BamAuxData) aux_data = (BamAuxData *)manager->
get_aux_data(
this,
"");
463 if (aux_data !=
nullptr) {
464 if (aux_data->_endian_reversed) {
467 reverse_data_endianness(new_buffer.get_write_pointer(), cdata->_buffer.get_read_pointer(
true), cdata->_buffer.get_size());
468 cdata->_buffer.swap(new_buffer);
472 set_lru_size(cdata->_buffer.get_size());
487 object->fillin(scan, manager);
497 void GeomVertexArrayData::
508 GeomVertexArrayData::CData::
517 return new CData(*
this);
524 void GeomVertexArrayData::CData::
533 dg.
append_data(_buffer.get_read_pointer(
true), _buffer.get_size());
537 unsigned char *new_data = (
unsigned char *)alloca(_buffer.get_size());
538 array_data->reverse_data_endianness(new_data, _buffer.get_read_pointer(
true), _buffer.get_size());
547 void GeomVertexArrayData::CData::
550 _usage_hint = (UsageHint)scan.
get_uint8();
555 READ_PTA(manager, scan, array_data->
read_raw_data, new_data);
556 _buffer.unclean_realloc(new_data.size());
557 _buffer.set_size(new_data.size());
558 memcpy(_buffer.get_write_pointer(), &new_data[0], new_data.size());
563 _buffer.unclean_realloc(size);
564 _buffer.set_size(size);
566 const unsigned char *source_data =
568 memcpy(_buffer.get_write_pointer(), source_data + scan.
get_current_index(), size);
572 bool endian_reversed =
false;
577 if (array_data->_array_format ==
nullptr) {
580 endian_reversed =
true;
585 array_data->reverse_data_endianness(new_buffer.get_write_pointer(), _buffer.get_read_pointer(
true), _buffer.get_size());
586 _buffer.swap(new_buffer);
590 if (endian_reversed) {
591 PT(BamAuxData) aux_data =
new BamAuxData;
592 aux_data->_endian_reversed = endian_reversed;
596 array_data->set_lru_size(_buffer.get_size());
606 nassertr(_writable,
nullptr);
609 return _cdata->_buffer.get_write_pointer();
615 bool GeomVertexArrayDataHandle::
616 set_num_rows(
int n) {
617 nassertr(_writable,
false);
620 int stride = _object->_array_format->get_stride();
621 size_t new_size = n * stride;
622 size_t orig_size = _cdata->_buffer.get_size();
624 if (gobj_cat.is_spam()) {
626 << _object <<
".set_num_rows(" << n <<
"), size = " << new_size <<
"\n";
629 if (new_size != orig_size) {
630 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
631 if (new_size > orig_reserved_size) {
635 nassertr(new_reserved_size >= new_size,
false);
637 _cdata->_buffer.clean_realloc(new_reserved_size);
639 }
else if (new_size == 0) {
643 _cdata->_buffer.clear();
646 _cdata->_buffer.set_size(new_size);
649 if (new_size > orig_size) {
650 memset(_cdata->_buffer.get_write_pointer() + orig_size, 0,
651 new_size - orig_size);
656 if (get_current_thread()->get_pipeline_stage() == 0) {
657 _object->set_lru_size(_cdata->_buffer.get_size());
660 nassertr(get_num_rows() == n,
true);
664 nassertr(get_num_rows() == n,
false);
671 bool GeomVertexArrayDataHandle::
672 unclean_set_num_rows(
int n) {
673 nassertr(_writable,
false);
676 int stride = _object->_array_format->get_stride();
677 size_t new_size = n * stride;
678 size_t orig_size = _cdata->_buffer.get_size();
679 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
681 if (new_size != orig_size || new_size != orig_reserved_size) {
687 _cdata->_buffer.unclean_realloc(new_size);
688 _cdata->_buffer.set_size(new_size);
693 if (new_size != orig_size) {
696 if (get_current_thread()->get_pipeline_stage() == 0) {
697 _object->set_lru_size(_cdata->_buffer.get_size());
709 bool GeomVertexArrayDataHandle::
710 reserve_num_rows(
int n) {
711 nassertr(_writable,
false);
714 int stride = _object->_array_format->get_stride();
715 size_t new_reserved_size = n * stride;
716 new_reserved_size = max(_cdata->_buffer.get_size(), new_reserved_size);
717 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
719 if (gobj_cat.is_debug()) {
721 << _object <<
".reserve_num_rows(" << n <<
"), size = " << new_reserved_size <<
"\n";
724 if (new_reserved_size != orig_reserved_size) {
728 _cdata->_buffer.clean_realloc(new_reserved_size);
743 size_t size = other->_cdata->_buffer.get_size();
744 const unsigned char *source = other->_cdata->_buffer.get_read_pointer(
true);
757 size_t from_start,
size_t from_size) {
761 size_t from_buffer_orig_size = from_buffer.
get_size();
762 from_start = min(from_start, from_buffer_orig_size);
763 from_size = min(from_size, from_buffer_orig_size - from_start);
767 from_start, from_size);
778 _cdata->_buffer.unclean_realloc(size);
779 _cdata->_buffer.set_size(size);
781 unsigned char *dest = _cdata->_buffer.get_write_pointer();
782 memcpy(dest, source, size);
786 if (get_current_thread()->get_pipeline_stage() == 0) {
787 _object->set_lru_size(_cdata->_buffer.get_size());
798 const unsigned char *source,
799 size_t from_start,
size_t from_size) {
804 size_t to_buffer_orig_size = to_buffer.
get_size();
805 to_start = min(to_start, to_buffer_orig_size);
806 to_size = min(to_size, to_buffer_orig_size - to_start);
808 if (from_size < to_size) {
811 memmove(pointer + to_start + to_size,
812 pointer + to_start + from_size,
813 to_buffer_orig_size - (to_start + to_size));
814 to_buffer.
set_size(to_buffer_orig_size + from_size - to_size);
816 }
else if (to_size < from_size) {
818 size_t needed_size = to_buffer_orig_size + from_size - to_size;
820 if (needed_size > to_buffer_orig_reserved_size) {
827 memmove(pointer + to_start + to_size,
828 pointer + to_start + from_size,
829 to_buffer_orig_size - (to_start + to_size));
834 source + from_start, from_size);
837 if (get_current_thread()->get_pipeline_stage() == 0) {
838 _object->set_lru_size(_cdata->_buffer.get_size());
852 _cdata->_buffer.unclean_realloc(data.size());
853 _cdata->_buffer.set_size(data.size());
854 memcpy(_cdata->_buffer.get_write_pointer(), data.data(), data.size());
858 if (get_current_thread()->get_pipeline_stage() == 0) {
859 _object->set_lru_size(_cdata->_buffer.get_size());
870 set_subdata(
size_t start,
size_t size,
const vector_uchar &data) {
875 size_t to_buffer_orig_size = to_buffer.
get_size();
876 start = min(start, to_buffer_orig_size);
877 size = min(size, to_buffer_orig_size - start);
879 size_t from_size = data.size();
881 if (from_size < size) {
884 memmove(pointer + start + from_size,
885 pointer + start + size,
886 to_buffer_orig_size - (start + size));
887 to_buffer.
set_size(to_buffer_orig_size + from_size - size);
889 }
else if (size < from_size) {
891 size_t needed_size = to_buffer_orig_size + from_size - size;
893 if (needed_size > to_buffer_orig_reserved_size) {
900 memmove(pointer + start + from_size,
901 pointer + start + size,
902 to_buffer_orig_size - (start + size));
909 if (get_current_thread()->get_pipeline_stage() == 0) {
910 _object->set_lru_size(_cdata->_buffer.get_size());
VertexBufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the data on the particular GSG, if it does not already exist.
unsigned char * get_write_pointer()
Returns a writable pointer to the raw data.
size_t get_size() const
Returns the number of bytes in the buffer.
An implementation of a very simple LRU algorithm.
int compare_to(const GeomVertexArrayData &other) const
Returns 0 if the two arrays are equivalent, even if they are not the same pointer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL map.
PTA_uchar read_raw_data(BamReader *manager, DatagramIterator &source)
Called by CData::fillin to read the raw data of the array from the indicated datagram.
AuxData * get_aux_data(TypedWritable *obj, const std::string &name) const
Returns the pointer previously associated with the bam reader by a previous call to set_aux_data(),...
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void operator=(const GeomVertexArrayData ©)
The copy assignment operator is not pipeline-safe.
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
set_usage_hint
Changes the UsageHint hint for this array.
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
void mark_used_lru() const
To be called when the page is used; this will move it to the tail of the SimpleLru queue it is alread...
const Datagram & get_datagram() const
Return the datagram of this iterator.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
Base class for objects that can be written to and read from Bam files.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
bool is_vertex_buffer_queued(const GeomVertexArrayData *data) const
Returns true if the vertex buffer has been queued on this GSG, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int release_all()
Frees the context allocated on all objects for which the data has been declared.
void release_vertex_buffer(VertexBufferContext *vbc)
Indicates that a data context, created by a previous call to prepare_vertex_buffer(),...
void dequeue_lru()
Removes the page from its SimpleLru.
void begin_epoch()
Marks the end of the previous epoch and the beginning of the next one.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VertexBufferContext * prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new VertexBufferContext for the indicated data and returns it.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static SimpleLru * get_global_lru(RamClass rclass)
Returns a pointer to the global LRU object that manages the VertexDataPage's with the indicated RamCl...
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
A table of objects that are saved within the graphics context for reference by handle later.
static void lru_epoch()
Marks that an epoch has passed in each LRU.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
This defines how a single column is interleaved within a vertex array stored within a Geom.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the data should be enqueued to be prepared in the indicated prepared_objects at the be...
void clean_realloc(size_t reserved_size)
Changes the "reserved" size of the buffer, preserving its data (except for any data beyond the new en...
virtual void evict_lru()
Evicts the page from the LRU.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
size_t get_current_index() const
Returns the current position within the datagram of the next piece of data to extract.
get_array_format
Returns the format object that describes this array.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the datagram.
bool change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer)
Indicates that an object recently read from the bam stream should be replaced with a new object.
One atomic piece that may be managed by a SimpleLru chain.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
bool dequeue_vertex_buffer(GeomVertexArrayData *data)
Removes a buffer from the queued list of data arrays to be prepared.
A block of bytes that stores the actual raw vertex data referenced by a GeomVertexArrayData object.
void set_data(const vector_uchar &data)
Replaces the entire raw data array with the contents of the indicated string.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
size_t get_reserved_size() const
Returns the total number of bytes "reserved" in the buffer.
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the data context only on the indicated object, if it exists there.
void enqueue_vertex_buffer(GeomVertexArrayData *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
void set_size(size_t size)
Changes the size of the buffer.
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the data has already been prepared or enqueued for preparation on the indicated GSG,...
unsigned char * get_write_pointer()
Returns a writable pointer to the beginning of the actual data stream.
NativeNumericData and ReversedNumericData work together to provide a sneaky interface for automatical...
void copy_data_from(const GeomVertexArrayDataHandle *other)
Copies the entire data array from the other object.
A collection of VertexDataPages, which can be used to allocate new VertexDataBlock objects.
int get_start() const
Returns the byte within the array record at which this column starts.
void set_aux_data(TypedWritable *obj, const std::string &name, AuxData *data)
Associates an arbitrary block of data with the indicated object (or NULL), and the indicated name.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const unsigned char * get_read_pointer(bool force) const
Returns a readable pointer to the beginning of the actual data stream, or NULL if the data is not cur...
int get_component_bytes() const
Returns the number of bytes used by each component (that is, by one element of the numeric type).
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
get_file_endian
Returns the endian preference indicated by the Bam file currently being read.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
void mark_used() const
Marks the array data recently-used.
A thread; that is, a lightweight process.
void copy_subdata_from(size_t to_start, size_t to_size, const GeomVertexArrayDataHandle *other, size_t from_start, size_t from_size)
Copies a portion of the data array from the other object into a portion of the data array of this obj...
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
void set_subdata(size_t start, size_t size, const vector_uchar &data)
Replaces a portion of the data array from the indicated string.
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
This is a special class object that holds all the information returned by a particular GSG to indicat...
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
This is a convenience class to specialize ConfigVariable as an integer type.
get_usage_hint
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
get_file_endian
Returns the endian preference indicated by the Bam file currently being written.
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomVertexArrayData.
A class to retrieve the individual data elements previously stored in a Datagram.
TypeHandle is the identifier used to differentiate C++ class types.
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
PT(CopyOnWriteObject) GeomVertexArrayData
Required to implement CopyOnWriteObject.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the data for one array of a GeomVertexData structure.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.