From 7de805989f61870e22bdfd5f6106a08c209c0a5b Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 17 Dec 2011 01:55:52 +0000 Subject: [PATCH] add vertex-column-alignment --- panda/src/gobj/config_gobj.cxx | 6 ++++ panda/src/gobj/config_gobj.h | 1 + panda/src/gobj/geomPrimitive.I | 13 ------- panda/src/gobj/geomPrimitive.cxx | 16 +++++++++ panda/src/gobj/geomPrimitive.h | 2 +- panda/src/gobj/geomVertexArrayFormat.I | 46 +++++++++++++++++++++++- panda/src/gobj/geomVertexArrayFormat.cxx | 34 ++++++++++++++++-- panda/src/gobj/geomVertexArrayFormat.h | 4 +++ 8 files changed, 105 insertions(+), 17 deletions(-) diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 682f9d385f..aa6a5a73cc 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -272,6 +272,12 @@ ConfigVariableBool vertices_float64 "driver to downsample the vertices at load time, making everything " "slower.")); +ConfigVariableInt vertex_column_alignment +("vertex-column-alignment", 0, + PRC_DESC("This specifies the default byte alignment for each column of " + "data within a GeomVertexData when it is assembled using the default " + "interfaces. See GeomVertexFormat::set_column_alignment().")); + ConfigVariableEnum textures_power_2 ("textures-power-2", ATS_down, PRC_DESC("Specify whether textures should automatically be constrained to " diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index 674c46865e..4e2e08d8cd 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -64,6 +64,7 @@ extern EXPCL_PANDA_GOBJ ConfigVariableBool preserve_triangle_strips; extern EXPCL_PANDA_GOBJ ConfigVariableBool dump_generated_shaders; extern EXPCL_PANDA_GOBJ ConfigVariableBool enforce_attrib_lock; extern EXPCL_PANDA_GOBJ ConfigVariableBool vertices_float64; +extern EXPCL_PANDA_GOBJ ConfigVariableInt vertex_column_alignment; extern EXPCL_PANDA_GOBJ ConfigVariableEnum textures_power_2; extern EXPCL_PANDA_GOBJ ConfigVariableEnum textures_square; diff --git a/panda/src/gobj/geomPrimitive.I b/panda/src/gobj/geomPrimitive.I index a593e01734..da47eb154f 100644 --- a/panda/src/gobj/geomPrimitive.I +++ b/panda/src/gobj/geomPrimitive.I @@ -415,19 +415,6 @@ add_vertices(int v1, int v2, int v3, int v4) { add_vertex(v4); } -//////////////////////////////////////////////////////////////////// -// Function: GeomPrimitive::get_index_format -// Access: Public -// Description: Returns a registered format appropriate for using to -// store the index table. -//////////////////////////////////////////////////////////////////// -INLINE CPT(GeomVertexArrayFormat) GeomPrimitive:: -get_index_format() const { - return GeomVertexArrayFormat::register_format - (new GeomVertexArrayFormat(InternalName::get_index(), 1, - get_index_type(), C_index)); -} - //////////////////////////////////////////////////////////////////// // Function: GeomPrimitive::make_index_data // Access: Public diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index babdfb36d6..029842ab7e 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -1416,6 +1416,22 @@ release_all() { return num_freed; } +//////////////////////////////////////////////////////////////////// +// Function: GeomPrimitive::get_index_format +// Access: Public +// Description: Returns a registered format appropriate for using to +// store the index table. +//////////////////////////////////////////////////////////////////// +CPT(GeomVertexArrayFormat) GeomPrimitive:: +get_index_format() const { + PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat; + // It's important that the index format not attempt to have any kind + // of SSE2 alignment or whatever. It needs to be tightly packed. + format->set_column_alignment(1); + format->add_column(InternalName::get_index(), 1, get_index_type(), C_index); + return GeomVertexArrayFormat::register_format(format); +} + //////////////////////////////////////////////////////////////////// // Function: GeomPrimitive::clear_prepared // Access: Private diff --git a/panda/src/gobj/geomPrimitive.h b/panda/src/gobj/geomPrimitive.h index 0d96ec3109..f57d846bb7 100644 --- a/panda/src/gobj/geomPrimitive.h +++ b/panda/src/gobj/geomPrimitive.h @@ -186,7 +186,7 @@ public: bool release(PreparedGraphicsObjects *prepared_objects); int release_all(); - INLINE CPT(GeomVertexArrayFormat) get_index_format() const; + CPT(GeomVertexArrayFormat) get_index_format() const; INLINE PT(GeomVertexArrayData) make_index_data() const; private: diff --git a/panda/src/gobj/geomVertexArrayFormat.I b/panda/src/gobj/geomVertexArrayFormat.I index d8bb51ca14..0da7aa14ca 100644 --- a/panda/src/gobj/geomVertexArrayFormat.I +++ b/panda/src/gobj/geomVertexArrayFormat.I @@ -60,14 +60,58 @@ get_stride() const { // Function: GeomVertexArrayFormat::set_stride // Access: Published // Description: Changes the total number of bytes reserved in the -// array for each vertex. +// array for each vertex. You may not reduce this below +// get_total_bytes(), but you may increase it +// arbitrarily. //////////////////////////////////////////////////////////////////// INLINE void GeomVertexArrayFormat:: set_stride(int stride) { nassertv(!_is_registered); + nassertv(_stride >= _total_bytes); _stride = stride; } +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayFormat::get_column_alignment +// Access: Published +// Description: See set_column_alignment(). +//////////////////////////////////////////////////////////////////// +INLINE int GeomVertexArrayFormat:: +get_column_alignment() const { + return _column_alignment; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayFormat::set_column_alignment +// Access: Published +// Description: This specifies the byte alignment for each +// column of data within the format when add_column() is +// subsequently called with default parameters. +// Normally this is 0 or 1 to specify no particular +// alignment, but you may specify a higher number, for +// instace 4 to guarantee that all columns start at a +// word alignment, or 16 to align all columns for SSE2 +// processing. This will introduce unused bytes between +// columns as needed to guarantee the requested +// alignment. +// +// Note that this does not change existing columns, only +// subsequent columns; and if you specify the start byte +// explicitly in add_column(), it will override this +// setting. Note also that there is no point in +// exceeding the memory alignment of Panda3D itself, +// which is compiled into Panda and can be determined by +// MemoryHook::get_memory_alignment(). +// +// Also see the config variable vertex-column-alignment +// for a way to change the global default. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexArrayFormat:: +set_column_alignment(int column_alignment) { + nassertv(!_is_registered); + _column_alignment = column_alignment; +} + //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::get_total_bytes // Access: Published diff --git a/panda/src/gobj/geomVertexArrayFormat.cxx b/panda/src/gobj/geomVertexArrayFormat.cxx index 25b4aa80f1..edd1d6827c 100644 --- a/panda/src/gobj/geomVertexArrayFormat.cxx +++ b/panda/src/gobj/geomVertexArrayFormat.cxx @@ -34,6 +34,7 @@ GeomVertexArrayFormat:: GeomVertexArrayFormat() : _is_registered(false), _stride(0), + _column_alignment(vertex_column_alignment), _total_bytes(0), _pad_to(1), _columns_unsorted(false) @@ -51,6 +52,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, GeomVertexArrayFormat::Contents contents0) : _is_registered(false), _stride(0), + _column_alignment(vertex_column_alignment), _total_bytes(0), _pad_to(1), _columns_unsorted(false) @@ -72,6 +74,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, GeomVertexArrayFormat::Contents contents1) : _is_registered(false), _stride(0), + _column_alignment(vertex_column_alignment), _total_bytes(0), _pad_to(1), _columns_unsorted(false) @@ -97,6 +100,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, GeomVertexArrayFormat::Contents contents2) : _is_registered(false), _stride(0), + _column_alignment(vertex_column_alignment), _total_bytes(0), _pad_to(1), _columns_unsorted(false) @@ -126,6 +130,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, GeomVertexArrayFormat::Contents contents3) : _is_registered(false), _stride(0), + _column_alignment(vertex_column_alignment), _total_bytes(0), _pad_to(1), _columns_unsorted(false) @@ -145,6 +150,7 @@ GeomVertexArrayFormat:: GeomVertexArrayFormat(const GeomVertexArrayFormat ©) : _is_registered(false), _stride(copy._stride), + _column_alignment(copy._column_alignment), _total_bytes(copy._total_bytes), _pad_to(copy._pad_to), _columns_unsorted(copy._columns_unsorted) @@ -164,6 +170,7 @@ void GeomVertexArrayFormat:: operator = (const GeomVertexArrayFormat ©) { nassertv(!_is_registered); _stride = copy._stride; + _column_alignment = copy._column_alignment; _total_bytes = copy._total_bytes; _pad_to = copy._pad_to; @@ -233,6 +240,10 @@ add_column(InternalName *name, int num_components, GeomVertexArrayFormat::Contents contents, int start) { if (start < 0) { start = _total_bytes; + if (_column_alignment > 1) { + // Round up to the next multiple of _column_alignment. + start = ((start + (_column_alignment - 1)) / _column_alignment) * _column_alignment; + } GeomVertexColumn temp_column (name, num_components, numeric_type, contents, 0); @@ -275,9 +286,19 @@ add_column(const GeomVertexColumn &column) { orig_column = get_column(column.get_start(), column.get_total_bytes()); } - _total_bytes = max(_total_bytes, column.get_start() + column.get_total_bytes()); + int column_bytes = column.get_total_bytes(); + if (_column_alignment > 1 && (column.get_start() % _column_alignment == 0)) { + // Round up to the next multiple of _column_alignment. + column_bytes = ((column_bytes + _column_alignment - 1) / _column_alignment) * _column_alignment; + } + + _total_bytes = max(_total_bytes, column.get_start() + column_bytes); _pad_to = max(_pad_to, column.get_component_bytes()); - _stride = max(_stride, ((_total_bytes + _pad_to - 1) / _pad_to) * _pad_to); + _stride = max(_stride, _total_bytes); + _stride = ((_stride + _pad_to - 1) / _pad_to) * _pad_to; + if (_column_alignment > 1) { + _stride = ((_stride + _column_alignment - 1) / _column_alignment) * _column_alignment; + } GeomVertexColumn *new_column = new GeomVertexColumn(column); @@ -554,6 +575,14 @@ compare_to(const GeomVertexArrayFormat &other) const { if (_stride != other._stride) { return _stride - other._stride; } + /* + // We don't compare column_alignment. That's a setting used only + // when constructing the format, and no longer relevant after it's + // been constructed. + if (_column_alignment != other._column_alignment) { + return _column_alignment - other._column_alignment; + } + */ if (_total_bytes != other._total_bytes) { return _total_bytes - other._total_bytes; } @@ -731,6 +760,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { TypedWritableReferenceCount::fillin(scan, manager); nassertv(!_is_registered); + // Maybe we should record _column_alignment, but we don't. _stride = scan.get_uint16(); _total_bytes = scan.get_uint16(); _pad_to = scan.get_uint8(); diff --git a/panda/src/gobj/geomVertexArrayFormat.h b/panda/src/gobj/geomVertexArrayFormat.h index c339e3978a..d738c23eda 100644 --- a/panda/src/gobj/geomVertexArrayFormat.h +++ b/panda/src/gobj/geomVertexArrayFormat.h @@ -85,6 +85,9 @@ PUBLISHED: INLINE int get_stride() const; INLINE void set_stride(int stride); + INLINE int get_column_alignment() const; + INLINE void set_column_alignment(int column_alignment); + INLINE int get_total_bytes() const; INLINE int get_pad_to() const; @@ -128,6 +131,7 @@ private: bool _is_registered; int _stride; + int _column_alignment; int _total_bytes; int _pad_to;