diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 0ccf6dd07c..ed0af995b8 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1359,6 +1359,22 @@ reset() { } #endif + _supports_vertex_attrib_divisor = false; +#ifndef OPENGLES + if (is_at_least_gl_version(3, 3)) { + _glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) + get_extension_func("glVertexAttribDivisor"); + + _supports_vertex_attrib_divisor = true; + + } else if (has_extension("GL_ARB_instanced_arrays")) { + _glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) + get_extension_func("glVertexAttribDivisorARB"); + + _supports_vertex_attrib_divisor = true; + } +#endif + #ifdef OPENGLES_2 // In OpenGL ES 2.x, FBO's are supported in the core. _supports_framebuffer_object = true; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index e91e9a4df7..5b331abbc1 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -182,6 +182,7 @@ typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); #endif // OPENGLES_1 #ifndef OPENGLES typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); @@ -572,6 +573,8 @@ protected: bool _use_sender; #endif // SUPPORT_IMMEDIATE_MODE + bool _supports_vertex_attrib_divisor; + // Cache the data necessary to bind each particular light each // frame, so if we bind a given light multiple times, we only have // to compute its data once. @@ -785,6 +788,7 @@ public: PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer; PFNGLVERTEXATTRIBIPOINTERPROC _glVertexAttribIPointer; PFNGLVERTEXATTRIBLPOINTERPROC _glVertexAttribLPointer; + PFNGLVERTEXATTRIBDIVISORPROC _glVertexAttribDivisor; #endif // OPENGLES_1 #ifndef OPENGLES PFNGLGENSAMPLERSPROC _glGenSamplers; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 1dcdf62a40..7166b7770e 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -998,6 +998,9 @@ disable_shader_vertex_arrays() { for (int i=0; i<(int)_shader->_var_spec.size(); i++) { const Shader::ShaderVarSpec &bind = _shader->_var_spec[i]; const GLint p = _glsl_parameter_map[bind._id._seqno]; + if (_glgsg->_supports_vertex_attrib_divisor) { + _glgsg->_glVertexAttribDivisor(p, 0); + } _glgsg->_glDisableVertexAttribArray(p); } @@ -1052,10 +1055,10 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { } GLint p = _glsl_parameter_map[bind._id._seqno]; - int num_elements, element_stride; + int num_elements, element_stride, divisor; if (_glgsg->_data_reader->get_array_info(name, array_reader, num_values, numeric_type, - start, stride, + start, stride, divisor, num_elements, element_stride)) { const unsigned char *client_pointer; if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) { @@ -1066,12 +1069,12 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { for (int i = 0; i < num_elements; ++i) { _glgsg->_glEnableVertexAttribArray(p); - #ifndef OPENGLES +#ifndef OPENGLES if (bind._integer) { _glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type), stride, client_pointer); } else - #endif +#endif if (numeric_type == GeomEnums::NT_packed_dabc) { _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, stride, client_pointer); @@ -1079,6 +1082,11 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { _glgsg->_glVertexAttribPointer(p, num_values, _glgsg->get_numeric_type(numeric_type), GL_TRUE, stride, client_pointer); } + + if (_glgsg->_supports_vertex_attrib_divisor) { + _glgsg->_glVertexAttribDivisor(p, divisor); + } + ++p; client_pointer += element_stride; } diff --git a/panda/src/gobj/geomVertexArrayFormat.I b/panda/src/gobj/geomVertexArrayFormat.I index 6a51a54b15..f813084c96 100644 --- a/panda/src/gobj/geomVertexArrayFormat.I +++ b/panda/src/gobj/geomVertexArrayFormat.I @@ -106,6 +106,33 @@ set_pad_to(int pad_to) { _stride = ((_stride + _pad_to - 1) / _pad_to) * _pad_to; } +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayFormat::get_divisor +// Access: Published +// Description: Returns the divisor attribute for the data in this +// array. If 0, it contains per-vertex data. If 1, +// it contains per-instance data. If higher than 1, +// the read row is advanced for each n instances. +//////////////////////////////////////////////////////////////////// +INLINE int GeomVertexArrayFormat:: +get_divisor() const { + return _divisor; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayFormat::set_divisor +// Access: Published +// Description: Set this to 0 to indicate that this array contains +// per-vertex data, or to 1 to indicate that it +// contains per-instance data. If higher than 1, +// the read row is advanced for each n instances. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexArrayFormat:: +set_divisor(int divisor) { + nassertv(divisor >= 0); + _divisor = divisor; +} + //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::get_total_bytes // Access: Published diff --git a/panda/src/gobj/geomVertexArrayFormat.cxx b/panda/src/gobj/geomVertexArrayFormat.cxx index 1c2877b1f3..4d53cc3ea0 100644 --- a/panda/src/gobj/geomVertexArrayFormat.cxx +++ b/panda/src/gobj/geomVertexArrayFormat.cxx @@ -28,7 +28,7 @@ TypeHandle GeomVertexArrayFormat::_type_handle; //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat:: GeomVertexArrayFormat() : @@ -36,6 +36,7 @@ GeomVertexArrayFormat() : _stride(0), _total_bytes(0), _pad_to(1), + _divisor(0), _columns_unsorted(false) { } @@ -43,7 +44,7 @@ GeomVertexArrayFormat() : //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat:: GeomVertexArrayFormat(InternalName *name0, int num_components0, @@ -53,6 +54,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, _stride(0), _total_bytes(0), _pad_to(1), + _divisor(0), _columns_unsorted(false) { add_column(name0, num_components0, numeric_type0, contents0); @@ -61,7 +63,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat:: GeomVertexArrayFormat(InternalName *name0, int num_components0, @@ -74,6 +76,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, _stride(0), _total_bytes(0), _pad_to(1), + _divisor(0), _columns_unsorted(false) { add_column(name0, num_components0, numeric_type0, contents0); @@ -83,7 +86,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat:: GeomVertexArrayFormat(InternalName *name0, int num_components0, @@ -99,6 +102,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, _stride(0), _total_bytes(0), _pad_to(1), + _divisor(0), _columns_unsorted(false) { add_column(name0, num_components0, numeric_type0, contents0); @@ -109,7 +113,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat:: GeomVertexArrayFormat(InternalName *name0, int num_components0, @@ -128,6 +132,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, _stride(0), _total_bytes(0), _pad_to(1), + _divisor(0), _columns_unsorted(false) { add_column(name0, num_components0, numeric_type0, contents0); @@ -139,7 +144,7 @@ GeomVertexArrayFormat(InternalName *name0, int num_components0, //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Copy Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat:: GeomVertexArrayFormat(const GeomVertexArrayFormat ©) : @@ -147,6 +152,7 @@ GeomVertexArrayFormat(const GeomVertexArrayFormat ©) : _stride(copy._stride), _total_bytes(copy._total_bytes), _pad_to(copy._pad_to), + _divisor(copy._divisor), _columns_unsorted(copy._columns_unsorted) { Columns::const_iterator dti; @@ -158,7 +164,7 @@ GeomVertexArrayFormat(const GeomVertexArrayFormat ©) : //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Copy Assignment Operator // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexArrayFormat:: operator = (const GeomVertexArrayFormat ©) { @@ -166,6 +172,7 @@ operator = (const GeomVertexArrayFormat ©) { _stride = copy._stride; _total_bytes = copy._total_bytes; _pad_to = copy._pad_to; + _divisor = copy._divisor; _columns.clear(); _columns_by_name.clear(); @@ -175,11 +182,11 @@ operator = (const GeomVertexArrayFormat ©) { add_column(*(*dti)); } } - + //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Destructor // Access: Published, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat:: ~GeomVertexArrayFormat() { @@ -228,15 +235,15 @@ unref() const { // type. //////////////////////////////////////////////////////////////////// int GeomVertexArrayFormat:: -add_column(InternalName *name, int num_components, - GeomVertexArrayFormat::NumericType numeric_type, +add_column(InternalName *name, int num_components, + GeomVertexArrayFormat::NumericType numeric_type, GeomVertexArrayFormat::Contents contents, int start, int column_alignment) { if (start < 0) { start = _total_bytes; } - return add_column(GeomVertexColumn(name, num_components, numeric_type, contents, + return add_column(GeomVertexColumn(name, num_components, numeric_type, contents, start, column_alignment)); } @@ -500,7 +507,7 @@ count_unused_space() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::output // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexArrayFormat:: output(ostream &out) const { @@ -526,7 +533,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::write // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexArrayFormat:: write(ostream &out, int indent_level) const { @@ -537,7 +544,7 @@ write(ostream &out, int indent_level) const { for (ci = _columns.begin(); ci != _columns.end(); ++ci) { const GeomVertexColumn *column = (*ci); indent(out, indent_level + 2) - << *column + << *column << " " << column->get_numeric_type() << " " << column->get_contents() << " start at " << column->get_start() << "\n"; @@ -547,7 +554,7 @@ write(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::write_with_data // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexArrayFormat:: write_with_data(ostream &out, int indent_level, @@ -568,7 +575,7 @@ write_with_data(ostream &out, int indent_level, reader.set_column(0, column); const LVecBase4f &d = reader.get_data4f(); - indent(out, indent_level + 2) + indent(out, indent_level + 2) << *column->get_name(); for (int v = 0; v < num_values; v++) { out << " " << d[v]; @@ -658,7 +665,7 @@ get_format_string(bool pad) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::compare_to // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// int GeomVertexArrayFormat:: compare_to(const GeomVertexArrayFormat &other) const { @@ -671,6 +678,9 @@ compare_to(const GeomVertexArrayFormat &other) const { if (_pad_to != other._pad_to) { return _pad_to - other._pad_to; } + if (_divisor != other._divisor) { + return _divisor - other._divisor; + } if (_columns.size() != other._columns.size()) { return (int)_columns.size() - (int)other._columns.size(); } @@ -720,7 +730,7 @@ do_register() { nassertv(!_is_registered); _is_registered = true; } - + //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::do_unregister // Access: Private @@ -756,6 +766,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_uint16(_stride); dg.add_uint16(_total_bytes); dg.add_uint8(_pad_to); + dg.add_uint16(_divisor); consider_sort_columns(); @@ -845,6 +856,11 @@ fillin(DatagramIterator &scan, BamReader *manager) { _stride = scan.get_uint16(); _total_bytes = scan.get_uint16(); _pad_to = scan.get_uint8(); + if (manager->get_file_minor_ver() > 36) { + _divisor = scan.get_uint16(); + } else { + _divisor = 0; + } int num_columns = scan.get_uint16(); _columns.reserve(num_columns); @@ -859,7 +875,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::Registry::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexArrayFormat::Registry:: Registry() { @@ -890,7 +906,7 @@ register_format(GeomVertexArrayFormat *format) { // a zero reference count and is not added into the map below, it // will be automatically deleted when this function returns. PT(GeomVertexArrayFormat) pt_format = format; - + GeomVertexArrayFormat *new_format; { LightMutexHolder holder(_lock); diff --git a/panda/src/gobj/geomVertexArrayFormat.h b/panda/src/gobj/geomVertexArrayFormat.h index 56a9d066ab..3bdb3e1596 100644 --- a/panda/src/gobj/geomVertexArrayFormat.h +++ b/panda/src/gobj/geomVertexArrayFormat.h @@ -88,6 +88,9 @@ PUBLISHED: INLINE int get_pad_to() const; INLINE void set_pad_to(int pad_to); + INLINE int get_divisor() const; + INLINE void set_divisor(int divisor); + INLINE int get_total_bytes() const; int add_column(InternalName *name, int num_components, @@ -135,6 +138,7 @@ private: int _stride; int _total_bytes; int _pad_to; + int _divisor; typedef pvector Columns; Columns _columns; diff --git a/panda/src/gobj/geomVertexData.I b/panda/src/gobj/geomVertexData.I index 3341b20e4a..9478e08fa7 100644 --- a/panda/src/gobj/geomVertexData.I +++ b/panda/src/gobj/geomVertexData.I @@ -98,12 +98,10 @@ get_num_rows() const { // was changed, false if the object already contained n // rows (or if there was some error). // -// Although this method is Published, application code -// only very rarely has any need to call it. Instead, -// you should use the GeomVertexWriter to build up the -// rows in a GeomVertexData object automatically, -// without need to explicitly set the number of -// rows. +// This can be used when you know exactly how many +// rows you will be needing. It is faster than +// reserve_num_rows(). Also see unclean_set_num_rows() +// if you are planning to fill in all the data yourself. // // Don't call this in a downstream thread unless you // don't mind it blowing away other changes you might @@ -129,12 +127,9 @@ set_num_rows(int n) { // anyway; it provides a tiny performance boost over // set_num_rows(). // -// Although this method is Published, application code -// only very rarely has any need to call it. Instead, -// you should use the GeomVertexWriter to build up the -// rows in a GeomVertexData object automatically, -// without need to explicitly set the number of -// rows. +// This can be used when you know exactly how many +// rows you will be needing. It is faster than +// reserve_num_rows(). //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexData:: unclean_set_num_rows(int n) { @@ -152,6 +147,10 @@ unclean_set_num_rows(int n) { // This is a performance optimization only; it is // especially useful when you know ahead of time that // you will be adding n rows to the data. +// +// If you know exactly how many rows you will be +// needing, it is significantly faster to use +// set_num_rows() or unclean_set_num_rows() instead. //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexData:: reserve_num_rows(int n) { diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 5d4029834d..2fb8783333 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -2368,7 +2368,7 @@ get_array_info(const InternalName *name, const GeomVertexArrayDataHandle *&array_reader, int &num_values, GeomVertexDataPipelineReader::NumericType &numeric_type, - int &start, int &stride, + int &start, int &stride, int &divisor, int &num_elements, int &element_stride) const { nassertr(_got_array_readers, false); int array_index; @@ -2379,6 +2379,7 @@ get_array_info(const InternalName *name, numeric_type = column->get_numeric_type(); start = column->get_start(); stride = _cdata->_format->get_array(array_index)->get_stride(); + divisor = _cdata->_format->get_array(array_index)->get_divisor(); num_elements = column->get_num_elements(); element_stride = column->get_element_stride(); return true; diff --git a/panda/src/gobj/geomVertexData.h b/panda/src/gobj/geomVertexData.h index cab0d62e1c..9bcdd7daec 100644 --- a/panda/src/gobj/geomVertexData.h +++ b/panda/src/gobj/geomVertexData.h @@ -453,7 +453,7 @@ public: bool get_array_info(const InternalName *name, const GeomVertexArrayDataHandle *&array_reader, int &num_values, NumericType &numeric_type, - int &start, int &stride, + int &start, int &stride, int &divisor, int &num_elements, int &element_stride) const; INLINE bool has_vertex() const; diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index aa07af2c2f..55916dd228 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -33,7 +33,7 @@ static const unsigned short _bam_major_ver = 6; // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData. static const unsigned short _bam_first_minor_ver = 14; -static const unsigned short _bam_minor_ver = 36; +static const unsigned short _bam_minor_ver = 37; // Bumped to minor version 14 on 12/19/07 to change default ColorAttrib. // Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort. // Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level. @@ -57,5 +57,6 @@ static const unsigned short _bam_minor_ver = 36; // Bumped to minor version 34 on 9/16/14 to add ScissorAttrib::_off. // Bumped to minor version 35 on 12/3/14 to change StencilAttrib. // Bumped to minor version 36 on 12/9/14 to add samplers and lod settings. +// Bumped to minor version 37 on 1/22/15 to add GeomVertexArrayFormat::_divisor. #endif