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."));
45SimpleLru GeomVertexArrayData::_independent_lru(
"independent", max_independent_vertex_data);
46SimpleLru GeomVertexArrayData::_small_lru(
"small", max_independent_vertex_data);
52TypeHandle GeomVertexArrayData::CData::_type_handle;
53TypeHandle GeomVertexArrayDataHandle::_type_handle;
62GeomVertexArrayData() :
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());
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;
183void GeomVertexArrayData::
184output(std::ostream &out)
const {
185 nassertv(_array_format !=
nullptr);
192void GeomVertexArrayData::
193write(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) {
243 Contexts::const_iterator ci;
244 ci = _contexts->find(prepared_objects);
245 if (ci != _contexts->end()) {
253 if (vbc !=
nullptr) {
254 (*_contexts)[prepared_objects] = vbc;
256 else if (_contexts->empty()) {
269 if (_contexts !=
nullptr) {
270 Contexts::iterator ci;
271 ci = _contexts->find(prepared_objects);
272 if (ci != _contexts->end()) {
291 if (_contexts !=
nullptr) {
297 num_freed = (int)_contexts->size();
299 Contexts::const_iterator ci;
300 for (ci = temp.begin(); ci != temp.end(); ++ci) {
308 nassertr(_contexts ==
nullptr, num_freed);
339 cdata->_buffer.page_out(_book);
348void GeomVertexArrayData::
350 nassertv(_contexts !=
nullptr);
352 Contexts::iterator ci;
353 ci = _contexts->find(prepared_objects);
354 if (ci != _contexts->end()) {
355 _contexts->erase(ci);
356 if (_contexts->empty()) {
363 nassert_raise(
"unknown PreparedGraphicsObjects");
372void GeomVertexArrayData::
373reverse_data_endianness(
unsigned char *dest,
const unsigned char *source,
375 int num_columns = _array_format->get_num_columns();
378 for (
size_t pi = 0; pi < size; pi += _array_format->get_stride()) {
381 for (
int ci = 0; ci < num_columns; ++ci) {
384 if (component_bytes > 1) {
389 for (
int cj = 0; cj < num_components; ++cj) {
392 nd.store_value(dest + ci, component_bytes);
393 ci += component_bytes;
427 PTA_uchar data = PTA_uchar::empty_array(size, get_class_type());
428 const unsigned char *source_data =
466 GeomVertexArrayFormat::register_format(_array_format);
469 _array_format = new_array_format;
471 PT(BamAuxData) aux_data = (BamAuxData *)manager->
get_aux_data(
this,
"");
472 if (aux_data !=
nullptr) {
473 if (aux_data->_endian_reversed) {
476 reverse_data_endianness(new_buffer.
get_write_pointer(), cdata->_buffer.get_read_pointer(
true), cdata->_buffer.get_size());
477 cdata->_buffer.swap(new_buffer);
481 set_lru_size(cdata->_buffer.get_size());
496 object->fillin(scan, manager);
506void GeomVertexArrayData::
517GeomVertexArrayData::CData::
526 return new CData(*
this);
533void GeomVertexArrayData::CData::
542 dg.
append_data(_buffer.get_read_pointer(
true), _buffer.get_size());
546 unsigned char *new_data = (
unsigned char *)alloca(_buffer.get_size());
547 array_data->reverse_data_endianness(new_data, _buffer.get_read_pointer(
true), _buffer.get_size());
556void GeomVertexArrayData::CData::
559 _usage_hint = (UsageHint)scan.
get_uint8();
564 READ_PTA(manager, scan, array_data->
read_raw_data, new_data);
565 _buffer.unclean_realloc(new_data.size());
566 _buffer.set_size(new_data.size());
567 memcpy(_buffer.get_write_pointer(), &new_data[0], new_data.size());
572 _buffer.unclean_realloc(size);
573 _buffer.set_size(size);
575 const unsigned char *source_data =
577 memcpy(_buffer.get_write_pointer(), source_data + scan.
get_current_index(), size);
581 bool endian_reversed =
false;
586 if (array_data->_array_format ==
nullptr) {
589 endian_reversed =
true;
594 array_data->reverse_data_endianness(new_buffer.get_write_pointer(), _buffer.get_read_pointer(
true), _buffer.get_size());
595 _buffer.swap(new_buffer);
599 if (endian_reversed) {
600 PT(BamAuxData) aux_data =
new BamAuxData;
601 aux_data->_endian_reversed = endian_reversed;
605 array_data->set_lru_size(_buffer.get_size());
615 nassertr(_writable,
nullptr);
618 return _cdata->_buffer.get_write_pointer();
624bool GeomVertexArrayDataHandle::
626 nassertr(_writable,
false);
629 int stride = _object->_array_format->get_stride();
630 size_t new_size = n * stride;
631 size_t orig_size = _cdata->_buffer.get_size();
633 if (gobj_cat.is_spam()) {
635 << _object <<
".set_num_rows(" << n <<
"), size = " << new_size <<
"\n";
638 if (new_size != orig_size) {
639 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
640 if (new_size > orig_reserved_size) {
644 nassertr(new_reserved_size >= new_size,
false);
646 _cdata->_buffer.clean_realloc(new_reserved_size);
648 }
else if (new_size == 0) {
652 _cdata->_buffer.clear();
655 _cdata->_buffer.set_size(new_size);
658 if (new_size > orig_size) {
659 memset(_cdata->_buffer.get_write_pointer() + orig_size, 0,
660 new_size - orig_size);
665 if (get_current_thread()->get_pipeline_stage() == 0) {
666 _object->set_lru_size(_cdata->_buffer.get_size());
680bool GeomVertexArrayDataHandle::
681unclean_set_num_rows(
int n) {
682 nassertr(_writable,
false);
685 int stride = _object->_array_format->get_stride();
686 size_t new_size = n * stride;
687 size_t orig_size = _cdata->_buffer.get_size();
688 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
690 if (new_size != orig_size || new_size != orig_reserved_size) {
696 _cdata->_buffer.unclean_realloc(new_size);
697 _cdata->_buffer.set_size(new_size);
702 if (new_size != orig_size) {
705 if (get_current_thread()->get_pipeline_stage() == 0) {
706 _object->set_lru_size(_cdata->_buffer.get_size());
718bool GeomVertexArrayDataHandle::
719reserve_num_rows(
int n) {
720 nassertr(_writable,
false);
723 int stride = _object->_array_format->get_stride();
724 size_t new_reserved_size = n * stride;
725 new_reserved_size = max(_cdata->_buffer.get_size(), new_reserved_size);
726 size_t orig_reserved_size = _cdata->_buffer.get_reserved_size();
728 if (gobj_cat.is_debug()) {
730 << _object <<
".reserve_num_rows(" << n <<
"), size = " << new_reserved_size <<
"\n";
733 if (new_reserved_size != orig_reserved_size) {
737 _cdata->_buffer.clean_realloc(new_reserved_size);
752 size_t size = other->_cdata->_buffer.
get_size();
753 const unsigned char *source = other->_cdata->_buffer.
get_read_pointer(
true);
755 copy_data_from(source, size);
766 size_t from_start,
size_t from_size) {
770 size_t from_buffer_orig_size = from_buffer.
get_size();
771 from_start = min(from_start, from_buffer_orig_size);
772 from_size = min(from_size, from_buffer_orig_size - from_start);
774 copy_subdata_from(to_start, to_size,
776 from_start, from_size);
787 _cdata->_buffer.unclean_realloc(size);
788 _cdata->_buffer.set_size(size);
790 unsigned char *dest = _cdata->_buffer.get_write_pointer();
791 memcpy(dest, source, size);
795 if (get_current_thread()->get_pipeline_stage() == 0) {
796 _object->set_lru_size(_cdata->_buffer.get_size());
807 const unsigned char *source,
808 size_t from_start,
size_t from_size) {
813 size_t to_buffer_orig_size = to_buffer.
get_size();
814 to_start = min(to_start, to_buffer_orig_size);
815 to_size = min(to_size, to_buffer_orig_size - to_start);
817 if (from_size < to_size) {
820 memmove(pointer + to_start + to_size,
821 pointer + to_start + from_size,
822 to_buffer_orig_size - (to_start + to_size));
823 to_buffer.
set_size(to_buffer_orig_size + from_size - to_size);
825 }
else if (to_size < from_size) {
827 size_t needed_size = to_buffer_orig_size + from_size - to_size;
829 if (needed_size > to_buffer_orig_reserved_size) {
836 memmove(pointer + to_start + to_size,
837 pointer + to_start + from_size,
838 to_buffer_orig_size - (to_start + to_size));
843 source + from_start, from_size);
846 if (get_current_thread()->get_pipeline_stage() == 0) {
847 _object->set_lru_size(_cdata->_buffer.get_size());
861 _cdata->_buffer.unclean_realloc(data.size());
862 _cdata->_buffer.set_size(data.size());
863 memcpy(_cdata->_buffer.get_write_pointer(), data.data(), data.size());
867 if (get_current_thread()->get_pipeline_stage() == 0) {
868 _object->set_lru_size(_cdata->_buffer.get_size());
879set_subdata(
size_t start,
size_t size,
const vector_uchar &data) {
884 size_t to_buffer_orig_size = to_buffer.
get_size();
885 start = min(start, to_buffer_orig_size);
886 size = min(size, to_buffer_orig_size - start);
888 size_t from_size = data.size();
890 if (from_size < size) {
893 memmove(pointer + start + from_size,
894 pointer + start + size,
895 to_buffer_orig_size - (start + size));
896 to_buffer.
set_size(to_buffer_orig_size + from_size - size);
898 }
else if (size < from_size) {
900 size_t needed_size = to_buffer_orig_size + from_size - size;
902 if (needed_size > to_buffer_orig_reserved_size) {
909 memmove(pointer + start + from_size,
910 pointer + start + size,
911 to_buffer_orig_size - (start + size));
918 if (get_current_thread()->get_pipeline_stage() == 0) {
919 _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.
const unsigned char * get_read_pointer(bool force) const
Returns a read-only pointer to the raw data, or NULL if the data is not currently resident.
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.
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.