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;
62 GeomVertexArrayData() :
64 _array_format(nullptr),
83 GeomVertexArrayData::UsageHint usage_hint) :
85 _array_format(array_format),
86 _cycler(CData(usage_hint)),
90 nassertv(_array_format->is_registered());
100 _array_format(copy._array_format),
101 _cycler(copy._cycler),
106 set_lru_size(get_data_size_bytes());
107 nassertv(_array_format->is_registered());
117 CopyOnWriteObject::operator = (copy);
118 SimpleLruPage::operator = (copy);
122 _array_format = copy._array_format;
123 _cycler = copy._cycler;
125 OPEN_ITERATE_ALL_STAGES(_cycler) {
129 CLOSE_ITERATE_ALL_STAGES(_cycler);
131 nassertv(_array_format->is_registered());
137 GeomVertexArrayData::
138 ~GeomVertexArrayData() {
153 if (handle->get_usage_hint() != other_handle->get_usage_hint()) {
154 return (
int)handle->
get_usage_hint() - (int)other_handle->get_usage_hint();
156 if (handle->get_array_format() != other_handle->get_array_format()) {
157 return handle->get_array_format() < other_handle->get_array_format() ? -1 : 1;
159 if (handle->get_data_size_bytes() != other_handle->get_data_size_bytes()) {
160 return (
int)handle->get_data_size_bytes() - (int)other_handle->get_data_size_bytes();
162 return memcmp(handle->get_read_pointer(
true),
163 other_handle->get_read_pointer(
true),
164 handle->get_data_size_bytes());
175 CDWriter cdata(_cycler,
true);
176 cdata->_usage_hint = usage_hint;
183 void GeomVertexArrayData::
184 output(std::ostream &out)
const {
185 nassertv(_array_format !=
nullptr);
192 void GeomVertexArrayData::
193 write(std::ostream &out,
int indent_level)
const {
194 nassertv(_array_format !=
nullptr);
195 _array_format->write_with_data(out, indent_level,
this);
217 if (_contexts ==
nullptr) {
220 Contexts::const_iterator ci;
221 ci = _contexts->find(prepared_objects);
222 if (ci != _contexts->end()) {
242 if (_contexts ==
nullptr) {
245 Contexts::const_iterator ci;
246 ci = _contexts->find(prepared_objects);
247 if (ci != _contexts->end()) {
252 if (vbc !=
nullptr) {
253 (*_contexts)[prepared_objects] = vbc;
264 if (_contexts !=
nullptr) {
265 Contexts::iterator ci;
266 ci = _contexts->find(prepared_objects);
267 if (ci != _contexts->end()) {
286 if (_contexts !=
nullptr) {
292 num_freed = (int)_contexts->size();
294 Contexts::const_iterator ci;
295 for (ci = temp.begin(); ci != temp.end(); ++ci) {
303 nassertr(_contexts ==
nullptr, num_freed);
334 cdata->_buffer.page_out(_book);
343 void GeomVertexArrayData::
345 nassertv(_contexts !=
nullptr);
347 Contexts::iterator ci;
348 ci = _contexts->find(prepared_objects);
349 if (ci != _contexts->end()) {
350 _contexts->erase(ci);
351 if (_contexts->empty()) {
358 nassert_raise(
"unknown PreparedGraphicsObjects");
367 void GeomVertexArrayData::
368 reverse_data_endianness(
unsigned char *dest,
const unsigned char *source,
370 int num_columns = _array_format->get_num_columns();
373 for (
size_t pi = 0; pi < size; pi += _array_format->get_stride()) {
376 for (
int ci = 0; ci < num_columns; ++ci) {
379 if (component_bytes > 1) {
384 for (
int cj = 0; cj < num_components; ++cj) {
387 nd.store_value(dest + ci, component_bytes);
388 ci += component_bytes;
422 PTA_uchar data = PTA_uchar::empty_array(size, get_class_type());
423 const unsigned char *source_data =
461 GeomVertexArrayFormat::register_format(_array_format);
464 _array_format = new_array_format;
466 PT(BamAuxData) aux_data = (BamAuxData *)manager->
get_aux_data(
this,
"");
467 if (aux_data !=
nullptr) {
468 if (aux_data->_endian_reversed) {
471 reverse_data_endianness(new_buffer.
get_write_pointer(), cdata->_buffer.get_read_pointer(
true), cdata->_buffer.get_size());
472 cdata->_buffer.swap(new_buffer);
476 set_lru_size(cdata->_buffer.get_size());
491 object->fillin(scan, manager);
501 void GeomVertexArrayData::
512 GeomVertexArrayData::CData::
521 return new CData(*
this);
528 void GeomVertexArrayData::CData::
537 dg.
append_data(_buffer.get_read_pointer(
true), _buffer.get_size());
541 unsigned char *new_data = (
unsigned char *)alloca(_buffer.get_size());
542 array_data->reverse_data_endianness(new_data, _buffer.get_read_pointer(
true), _buffer.get_size());
551 void GeomVertexArrayData::CData::
554 _usage_hint = (UsageHint)scan.
get_uint8();
559 READ_PTA(manager, scan, array_data->
read_raw_data, new_data);
560 _buffer.unclean_realloc(new_data.size());
561 _buffer.set_size(new_data.size());
562 memcpy(_buffer.get_write_pointer(), &new_data[0], new_data.size());
567 _buffer.unclean_realloc(size);
568 _buffer.set_size(size);
570 const unsigned char *source_data =
572 memcpy(_buffer.get_write_pointer(), source_data + scan.
get_current_index(), size);
576 bool endian_reversed =
false;
581 if (array_data->_array_format ==
nullptr) {
584 endian_reversed =
true;
589 array_data->reverse_data_endianness(new_buffer.get_write_pointer(), _buffer.get_read_pointer(
true), _buffer.get_size());
590 _buffer.swap(new_buffer);
594 if (endian_reversed) {
595 PT(BamAuxData) aux_data =
new BamAuxData;
596 aux_data->_endian_reversed = endian_reversed;
600 array_data->set_lru_size(_buffer.get_size());
610 nassertr(_writable,
nullptr);
613 return _cdata->_buffer.get_write_pointer();
619 bool GeomVertexArrayDataHandle::
620 set_num_rows(
int n) {
621 nassertr(_writable,
false);
624 int stride = _object->_array_format->get_stride();
625 size_t new_size = n * stride;
626 size_t orig_size = _cdata->_buffer.get_size();
628 if (gobj_cat.is_spam()) {
630 << _object <<
".set_num_rows(" << n <<
"), size = " << new_size <<
"\n";
633 if (new_size != orig_size) {
634 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
635 if (new_size > orig_reserved_size) {
639 nassertr(new_reserved_size >= new_size,
false);
641 _cdata->_buffer.clean_realloc(new_reserved_size);
643 }
else if (new_size == 0) {
647 _cdata->_buffer.clear();
650 _cdata->_buffer.set_size(new_size);
653 if (new_size > orig_size) {
654 memset(_cdata->_buffer.get_write_pointer() + orig_size, 0,
655 new_size - orig_size);
660 if (get_current_thread()->get_pipeline_stage() == 0) {
661 _object->set_lru_size(_cdata->_buffer.get_size());
664 nassertr(get_num_rows() == n,
true);
668 nassertr(get_num_rows() == n,
false);
675 bool GeomVertexArrayDataHandle::
676 unclean_set_num_rows(
int n) {
677 nassertr(_writable,
false);
680 int stride = _object->_array_format->get_stride();
681 size_t new_size = n * stride;
682 size_t orig_size = _cdata->_buffer.get_size();
683 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
685 if (new_size != orig_size || new_size != orig_reserved_size) {
691 _cdata->_buffer.unclean_realloc(new_size);
692 _cdata->_buffer.set_size(new_size);
697 if (new_size != orig_size) {
700 if (get_current_thread()->get_pipeline_stage() == 0) {
701 _object->set_lru_size(_cdata->_buffer.get_size());
713 bool GeomVertexArrayDataHandle::
714 reserve_num_rows(
int n) {
715 nassertr(_writable,
false);
718 int stride = _object->_array_format->get_stride();
719 size_t new_reserved_size = n * stride;
720 new_reserved_size = max(_cdata->_buffer.get_size(), new_reserved_size);
721 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
723 if (gobj_cat.is_debug()) {
725 << _object <<
".reserve_num_rows(" << n <<
"), size = " << new_reserved_size <<
"\n";
728 if (new_reserved_size != orig_reserved_size) {
732 _cdata->_buffer.clean_realloc(new_reserved_size);
747 size_t size = other->_cdata->_buffer.get_size();
748 const unsigned char *source = other->_cdata->_buffer.get_read_pointer(
true);
761 size_t from_start,
size_t from_size) {
765 size_t from_buffer_orig_size = from_buffer.
get_size();
766 from_start = min(from_start, from_buffer_orig_size);
767 from_size = min(from_size, from_buffer_orig_size - from_start);
771 from_start, from_size);
782 _cdata->_buffer.unclean_realloc(size);
783 _cdata->_buffer.set_size(size);
785 unsigned char *dest = _cdata->_buffer.get_write_pointer();
786 memcpy(dest, source, size);
790 if (get_current_thread()->get_pipeline_stage() == 0) {
791 _object->set_lru_size(_cdata->_buffer.get_size());
802 const unsigned char *source,
803 size_t from_start,
size_t from_size) {
808 size_t to_buffer_orig_size = to_buffer.
get_size();
809 to_start = min(to_start, to_buffer_orig_size);
810 to_size = min(to_size, to_buffer_orig_size - to_start);
812 if (from_size < to_size) {
815 memmove(pointer + to_start + to_size,
816 pointer + to_start + from_size,
817 to_buffer_orig_size - (to_start + to_size));
818 to_buffer.
set_size(to_buffer_orig_size + from_size - to_size);
820 }
else if (to_size < from_size) {
822 size_t needed_size = to_buffer_orig_size + from_size - to_size;
824 if (needed_size > to_buffer_orig_reserved_size) {
831 memmove(pointer + to_start + to_size,
832 pointer + to_start + from_size,
833 to_buffer_orig_size - (to_start + to_size));
838 source + from_start, from_size);
841 if (get_current_thread()->get_pipeline_stage() == 0) {
842 _object->set_lru_size(_cdata->_buffer.get_size());
852 set_data(
const vector_uchar &data) {
856 _cdata->_buffer.unclean_realloc(data.size());
857 _cdata->_buffer.set_size(data.size());
858 memcpy(_cdata->_buffer.get_write_pointer(), data.data(), data.size());
862 if (get_current_thread()->get_pipeline_stage() == 0) {
863 _object->set_lru_size(_cdata->_buffer.get_size());
874 set_subdata(
size_t start,
size_t size,
const vector_uchar &data) {
879 size_t to_buffer_orig_size = to_buffer.
get_size();
880 start = min(start, to_buffer_orig_size);
881 size = min(size, to_buffer_orig_size - start);
883 size_t from_size = data.size();
885 if (from_size < size) {
888 memmove(pointer + start + from_size,
889 pointer + start + size,
890 to_buffer_orig_size - (start + size));
891 to_buffer.
set_size(to_buffer_orig_size + from_size - size);
893 }
else if (size < from_size) {
895 size_t needed_size = to_buffer_orig_size + from_size - size;
897 if (needed_size > to_buffer_orig_reserved_size) {
904 memmove(pointer + start + from_size,
905 pointer + start + size,
906 to_buffer_orig_size - (start + size));
913 if (get_current_thread()->get_pipeline_stage() == 0) {
914 _object->set_lru_size(_cdata->_buffer.get_size());
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
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.
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.
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
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(),...
get_file_endian
Returns the endian preference indicated by the Bam file currently being read.
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
get_file_endian
Returns the endian preference indicated by the Bam file currently being written.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
This is a convenience class to specialize ConfigVariable as an integer type.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
A class to retrieve the individual data elements previously stored in a Datagram.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the datagram.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
const Datagram & get_datagram() const
Return the datagram of this iterator.
size_t get_current_index() const
Returns the current position within the datagram of the next piece of data to extract.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
void copy_data_from(const GeomVertexArrayDataHandle *other)
Copies the entire data array from the other object.
void set_subdata(size_t start, size_t size, const vector_uchar &data)
Replaces a portion of the data array from the indicated string.
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...
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...
unsigned char * get_write_pointer()
Returns a writable pointer to the beginning of the actual data stream.
void mark_used() const
Marks the array data recently-used.
void set_data(const vector_uchar &data)
Replaces the entire raw data array with the contents of the indicated string.
This is the data for one array of a GeomVertexData structure.
get_usage_hint
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
virtual void evict_lru()
Evicts the page from the LRU.
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the data context only on the indicated object, if it exists there.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the data has already been prepared or enqueued for preparation on the indicated GSG,...
int compare_to(const GeomVertexArrayData &other) const
Returns 0 if the two arrays are equivalent, even if they are not the same pointer.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomVertexArrayData.
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride.
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.
int release_all()
Frees the context allocated on all objects for which the data has been declared.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the data should be enqueued to be prepared in the indicated prepared_objects at the be...
void operator=(const GeomVertexArrayData ©)
The copy assignment operator is not pipeline-safe.
VertexBufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the data on the particular GSG, if it does not already exist.
static void lru_epoch()
Marks that an epoch has passed in each LRU.
set_usage_hint
Changes the UsageHint hint for this array.
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 defines how a single column is interleaved within a vertex array stored within a Geom.
int get_start() const
Returns the byte within the array record at which this column starts.
int get_component_bytes() const
Returns the number of bytes used by each component (that is, by one element of the numeric type).
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A table of objects that are saved within the graphics context for reference by handle later.
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...
bool dequeue_vertex_buffer(GeomVertexArrayData *data)
Removes a buffer from the queued list of data arrays to be prepared.
void release_vertex_buffer(VertexBufferContext *vbc)
Indicates that a data context, created by a previous call to prepare_vertex_buffer(),...
bool is_vertex_buffer_queued(const GeomVertexArrayData *data) const
Returns true if the vertex buffer has been queued on this GSG, false otherwise.
VertexBufferContext * prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new VertexBufferContext for the indicated data and returns it.
NativeNumericData and ReversedNumericData work together to provide a sneaky interface for automatical...
One atomic piece that may be managed by a SimpleLru chain.
void dequeue_lru()
Removes the page from its SimpleLru.
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...
An implementation of a very simple LRU algorithm.
void begin_epoch()
Marks the end of the previous epoch and the beginning of the next one.
A thread; that is, a lightweight process.
get_current_thread
Returns a pointer to the currently-executing Thread object.
TypeHandle is the identifier used to differentiate C++ class types.
Base class for objects that can be written to and read from Bam files.
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...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
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().
This is a special class object that holds all the information returned by a particular GSG to indicat...
A collection of VertexDataPages, which can be used to allocate new VertexDataBlock objects.
A block of bytes that stores the actual raw vertex data referenced by a GeomVertexArrayData object.
void set_size(size_t size)
Changes the size of the buffer.
unsigned char * get_write_pointer()
Returns a writable pointer to the raw data.
size_t get_reserved_size() const
Returns the total number of bytes "reserved" in the buffer.
size_t get_size() const
Returns the number of bytes in the buffer.
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...
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 is our own Panda specialization on the default STL map.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(CopyOnWriteObject) GeomVertexArrayData
Required to implement CopyOnWriteObject.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_next_higher_bit(unsigned short x)
Returns the smallest power of 2 greater than x.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.