From 5dfa5043703673e67fbeb3fb04173b5b011cb78c Mon Sep 17 00:00:00 2001 From: Mike Christel Date: Thu, 29 Apr 2010 14:48:44 +0000 Subject: [PATCH] Texture arrays added to Texture class, passed to shader through setShaderInput(name, texture). A new Cg type sampler2DArray has been added to the panda3d Shader Class. --- panda/src/display/graphicsStateGuardian.I | 29 +++++ panda/src/display/graphicsStateGuardian.cxx | 4 + panda/src/display/graphicsStateGuardian.h | 6 + .../glstuff/glGraphicsStateGuardian_src.cxx | 121 +++++++++++++++--- panda/src/glstuff/glShaderContext_src.cxx | 29 ++--- panda/src/gobj/shader.cxx | 91 +++++++------ panda/src/gobj/shader.h | 5 +- panda/src/gobj/texture.I | 29 +++++ panda/src/gobj/texture.cxx | 41 ++++-- panda/src/gobj/texture.h | 6 +- panda/src/gobj/texturePool.I | 22 ++++ panda/src/gobj/texturePool.cxx | 119 ++++++++++++++++- panda/src/gobj/texturePool.h | 7 + panda/src/pgraph/nodePath.cxx | 6 +- 14 files changed, 426 insertions(+), 89 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index d9cd494a5d..a50ac0e9a6 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -1,5 +1,7 @@ // Filename: graphicsStateGuardian.I // Created by: drose (24Sep99) +// Updated by: fperazzi, PandaSE (29Apr10) (added +// get_max_2d_texture_array_layers and related) // //////////////////////////////////////////////////////////////////// // @@ -329,6 +331,22 @@ get_max_3d_texture_dimension() const { return _max_3d_texture_dimension; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_max_2d_texture_array_layers +// Access: Published +// Description: Returns the largest possible number of pages, or -1 +// if there is no particular limit. Returns 0 if 2-d +// texture arrays not supported. +// +// The value returned may not be meaningful until after +// the graphics context has been fully created (e.g. the +// window has been opened). +//////////////////////////////////////////////////////////////////// +INLINE int GraphicsStateGuardian:: +get_max_2d_texture_array_layers() const { + return _max_2d_texture_array_layers; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_max_cube_map_dimension // Access: Published @@ -397,6 +415,17 @@ get_supports_3d_texture() const { return _supports_3d_texture; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_supports_2d_texture_array +// Access: Published +// Description: Returns true if this GSG can render 2-d textures +// array. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +get_supports_2d_texture_array() const { + return _supports_2d_texture_array; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_supports_cube_map // Access: Published diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 8a488bde2e..191072ed58 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1,6 +1,8 @@ // Filename: graphicsStateGuardian.cxx // Created by: drose (02Feb99) // Updated by: fperazzi, PandaSE (06Apr10) (added fetch_ptr_parameter) +// Updated by: fperazzi, PandaSE (29Apr10) (added +// _max_2d_texture_array_layers, _supports_2d_texture_array) // //////////////////////////////////////////////////////////////////// // @@ -169,6 +171,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, // and that 3-d and cube-map textures are not supported. _max_texture_dimension = -1; _max_3d_texture_dimension = 0; + _max_2d_texture_array_layers = 0; _max_cube_map_dimension = 0; // Assume we don't support these fairly advanced texture combiner @@ -178,6 +181,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _supports_texture_dot3 = false; _supports_3d_texture = false; + _supports_2d_texture_array = false; _supports_cube_map = false; _supports_tex_non_pow2 = false; _supports_compressed_texture = false; diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index ee41f053bc..1b78e56a91 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -1,6 +1,8 @@ // Filename: graphicsStateGuardian.h // Created by: drose (02Feb99) // Updated by: fperazzi, PandaSE (06Apr10) (added fetch_ptr_parameter) +// Updated by: fperazzi, PandaSE (29Apr10) (added +// _max_2d_texture_array_layers on z axis) // //////////////////////////////////////////////////////////////////// // @@ -114,6 +116,7 @@ PUBLISHED: INLINE int get_max_texture_stages() const; virtual INLINE int get_max_texture_dimension() const; INLINE int get_max_3d_texture_dimension() const; + INLINE int get_max_2d_texture_array_layers() const; //z axis INLINE int get_max_cube_map_dimension() const; INLINE bool get_supports_texture_combine() const; @@ -121,6 +124,7 @@ PUBLISHED: INLINE bool get_supports_texture_dot3() const; INLINE bool get_supports_3d_texture() const; + INLINE bool get_supports_2d_texture_array() const; INLINE bool get_supports_cube_map() const; INLINE bool get_supports_tex_non_pow2() const; @@ -433,6 +437,7 @@ protected: int _max_texture_stages; int _max_texture_dimension; int _max_3d_texture_dimension; + int _max_2d_texture_array_layers; //on the z axis int _max_cube_map_dimension; bool _supports_texture_combine; @@ -440,6 +445,7 @@ protected: bool _supports_texture_dot3; bool _supports_3d_texture; + bool _supports_2d_texture_array; bool _supports_cube_map; bool _supports_tex_non_pow2; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 72cb8f5699..7d08495eae 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -584,6 +584,9 @@ reset() { } } +#ifndef OPENGLES + _supports_2d_texture_array = has_extension("GL_EXT_texture_array"); +#endif #ifdef OPENGLES_2 _supports_cube_map = true; #else @@ -1306,6 +1309,7 @@ reset() { GLint max_texture_size = 0; GLint max_3d_texture_size = 0; + GLint max_2d_texture_array_layers = 0; GLint max_cube_map_size = 0; GLP(GetIntegerv)(GL_MAX_TEXTURE_SIZE, &max_texture_size); @@ -1319,7 +1323,12 @@ reset() { } else { _max_3d_texture_dimension = 0; } - +#ifndef OPENGLES + if(_supports_2d_texture_array) { + GLP(GetIntegerv)(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &max_2d_texture_array_layers); + _max_2d_texture_array_layers = max_2d_texture_array_layers; + } +#endif if (_supports_cube_map) { GLP(GetIntegerv)(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_size); _max_cube_map_dimension = max_cube_map_size; @@ -1343,6 +1352,7 @@ reset() { GLCAT.debug() << "max texture dimension = " << _max_texture_dimension << ", max 3d texture = " << _max_3d_texture_dimension + << ", max 2d texture array = " << max_2d_texture_array_layers << ", max cube map = " << _max_cube_map_dimension << "\n"; GLCAT.debug() << "max_elements_vertices = " << max_elements_vertices @@ -3203,6 +3213,14 @@ prepare_texture(Texture *tex) { return NULL; } break; + + case Texture::TT_2d_texture_array: + if (!_supports_2d_texture_array) { + GLCAT.warning() + << "2-D texture arrays are not supported by this OpenGL driver.\n"; + return NULL; + } + break; case Texture::TT_cube_map: if (!_supports_cube_map) { @@ -5638,7 +5656,14 @@ get_texture_target(Texture::TextureType texture_type) const { } else { return GL_NONE; } - + case Texture::TT_2d_texture_array: + if (_supports_2d_texture_array) { +#ifndef OPENGLES + return GL_TEXTURE_2D_ARRAY_EXT; +#endif + } else { + return GL_NONE; + } case Texture::TT_cube_map: if (_supports_cube_map) { return GL_TEXTURE_CUBE_MAP; @@ -5992,7 +6017,8 @@ get_internal_image_format(Texture *tex) const { // no compression for render targets compression = Texture::CM_off; } - bool is_3d = (tex->get_texture_type() == Texture::TT_3d_texture); + bool is_3d = (tex->get_texture_type() == Texture::TT_3d_texture || + tex->get_texture_type() == Texture::TT_2d_texture_array); #ifndef OPENGLES if (get_supports_compressed_texture_format(compression)) { @@ -8249,22 +8275,38 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { GLenum component_type = get_component_type(tex->get_component_type()); // Ensure that the texture fits within the GL's specified limits. - int max_dimension; + // Need to split dimensions because of texture arrays + int max_dimension_x; + int max_dimension_y; + int max_dimension_z; + switch (tex->get_texture_type()) { case Texture::TT_3d_texture: - max_dimension = _max_3d_texture_dimension; + max_dimension_x = _max_3d_texture_dimension; + max_dimension_y = _max_3d_texture_dimension; + max_dimension_z = _max_3d_texture_dimension; break; case Texture::TT_cube_map: - max_dimension = _max_cube_map_dimension; + max_dimension_x = _max_cube_map_dimension; + max_dimension_y = _max_cube_map_dimension; + max_dimension_z = 6; + break; + + case Texture::TT_2d_texture_array: + max_dimension_x = _max_texture_dimension; + max_dimension_y = _max_texture_dimension; + max_dimension_z = _max_2d_texture_array_layers; break; default: - max_dimension = _max_texture_dimension; + max_dimension_x = _max_texture_dimension; + max_dimension_y = _max_texture_dimension; + max_dimension_z = 1; } - if (max_dimension == 0) { - // Guess this GL doesn't support cube mapping/3d textures. + if (max_dimension_x == 0 || max_dimension_y == 0 || max_dimension_z == 0) { + // Guess this GL doesn't support cube mapping/3d textures/2d texture arrays. report_my_gl_errors(); return false; } @@ -8277,10 +8319,11 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { // reduce the texture at load time instead; of course, the user // doesn't always know ahead of time what the hardware limits are. - if (max_dimension > 0 && image_compression == Texture::CM_off) { - while (tex->get_expected_mipmap_x_size(mipmap_bias) > max_dimension || - tex->get_expected_mipmap_y_size(mipmap_bias) > max_dimension || - tex->get_expected_mipmap_z_size(mipmap_bias) > max_dimension) { + if ((max_dimension_x > 0 && max_dimension_y > 0 && max_dimension_z > 0) && + image_compression == Texture::CM_off) { + while (tex->get_expected_mipmap_x_size(mipmap_bias) > max_dimension_x || + tex->get_expected_mipmap_y_size(mipmap_bias) > max_dimension_y || + tex->get_expected_mipmap_z_size(mipmap_bias) > max_dimension_z) { ++mipmap_bias; } @@ -8652,6 +8695,22 @@ upload_texture_image(CLP(TextureContext) *gtc, return false; } break; +#endif +#ifndef OPENGLES + case GL_TEXTURE_2D_ARRAY_EXT: + if (_supports_2d_texture_array) { + if (image_compression == Texture::CM_off) { + _glTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth, + external_format, component_type, image_ptr); + } else { + _glCompressedTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth, + external_format, image_size, image_ptr); + } + } else { + report_my_gl_errors(); + return false; + } + break; #endif default: if (image_compression == Texture::CM_off) { @@ -8791,6 +8850,22 @@ upload_texture_image(CLP(TextureContext) *gtc, } break; #endif + case GL_TEXTURE_2D_ARRAY_EXT: + if (_supports_2d_texture_array) { + if (image_compression == Texture::CM_off) { + _glTexImage3D(page_target, n - mipmap_bias, internal_format, + width, height, depth, 0, + external_format, component_type, image_ptr); + } else { + _glCompressedTexImage3D(page_target, n - mipmap_bias, external_format, width, + height, depth, + 0, image_size, image_ptr); + } + } else { + report_my_gl_errors(); + return false; + } + break; #endif // OPENGLES // OpenGL ES will fall through. default: @@ -8998,11 +9073,11 @@ get_texture_memory_size(Texture *tex) { GLint width = 1, height = 1, depth = 1; GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_WIDTH, &width); GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_HEIGHT, &height); - if (_supports_3d_texture) { + if (_supports_3d_texture || _supports_2d_texture_array) { GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_DEPTH, &depth); } - - report_my_gl_errors(); + + report_my_gl_errors(); size_t num_bits = (red_size + green_size + blue_size + alpha_size + luminance_size + intensity_size + depth_size); size_t num_bytes = (num_bits + 7) / 8; @@ -9084,6 +9159,11 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { #ifdef OPENGLES_2 GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_R_OES, &wrap_w); #endif +#ifndef OPENGLES + GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_R, &wrap_w); +#endif + } + if (_supports_2d_texture_array) { #ifndef OPENGLES GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_R, &wrap_w); #endif @@ -9113,12 +9193,17 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { if (_supports_3d_texture && target == GL_TEXTURE_3D) { GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_DEPTH, &depth); - } else if (target == GL_TEXTURE_CUBE_MAP) { + } +#ifndef OPENGLES + else if (_supports_2d_texture_array && target == GL_TEXTURE_2D_ARRAY_EXT) { + GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_DEPTH, &depth); + } +#endif + else if (target == GL_TEXTURE_CUBE_MAP) { depth = 6; } #endif clear_my_gl_errors(); - if (width <= 0 || height <= 0 || depth <= 0) { GLCAT.error() << "No texture data for " << tex->get_name() << "\n"; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index fe5b80fb11..5a5437b764 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -1,6 +1,6 @@ // Filename: glShaderContext_src.cxx // Created by: jyelon (01Sep05) -// Updated by: fperazzi, PandaSE (06Apr10) (updated CLP with note that some +// Updated by: fperazzi, PandaSE (29Apr10) (updated CLP with note that some // parameter types only supported under Cg) // //////////////////////////////////////////////////////////////////// @@ -567,7 +567,7 @@ issue_parameters(GSG *gsg, int altered) { case Shader::SAT_vec3: cgSetParameter3fv(p,(float*)_ptr_data->_ptr); continue; case Shader::SAT_vec4: cgSetParameter4fv(p,(float*)_ptr_data->_ptr); continue; } - case Shader::SAC_matrix: cgGLSetMatrixParameterfr(p,(float*)_ptr_data->_ptr); continue; + case Shader::SAC_matrix: cgGLSetMatrixParameterfc(p,(float*)_ptr_data->_ptr); continue; case Shader::SAC_array: { switch(_ptr._info._subclass) { case Shader::SAC_scalar: @@ -580,7 +580,7 @@ issue_parameters(GSG *gsg, int altered) { case 4: cgGLSetParameterArray4f(p,0,_ptr._dim[0],(float*)_ptr_data->_ptr); continue; } case Shader::SAC_matrix: - cgGLSetMatrixParameterArrayfr(p,0,_ptr._dim[0],(float*)_ptr_data->_ptr); continue; + cgGLSetMatrixParameterArrayfc(p,0,_ptr._dim[0],(float*)_ptr_data->_ptr); continue; } } } @@ -594,7 +594,7 @@ issue_parameters(GSG *gsg, int altered) { case Shader::SAT_vec3: cgSetParameter3dv(p,(double*)_ptr_data->_ptr); continue; case Shader::SAT_vec4: cgSetParameter4dv(p,(double*)_ptr_data->_ptr); continue; } - case Shader::SAC_matrix: cgGLSetMatrixParameterdr(p,(double*)_ptr_data->_ptr); continue; + case Shader::SAC_matrix: cgGLSetMatrixParameterdc(p,(double*)_ptr_data->_ptr); continue; case Shader::SAC_array: { switch(_ptr._info._subclass) { case Shader::SAC_scalar: @@ -607,7 +607,7 @@ issue_parameters(GSG *gsg, int altered) { case 4: cgGLSetParameterArray4d(p,0,_ptr._dim[0],(double*)_ptr_data->_ptr); continue; } case Shader::SAC_matrix: - cgGLSetMatrixParameterArraydr(p,0,_ptr._dim[0],(double*)_ptr_data->_ptr); continue; + cgGLSetMatrixParameterArraydc(p,0,_ptr._dim[0],(double*)_ptr_data->_ptr); continue; } } } @@ -833,16 +833,21 @@ disable_shader_texture_bindings(GSG *gsg) { return; } #ifndef OPENGLES - GLP(Disable)(GL_TEXTURE_1D); + GLP(BindTexture)(GL_TEXTURE_1D, 0); #endif // OPENGLES - GLP(Disable)(GL_TEXTURE_2D); + GLP(BindTexture)(GL_TEXTURE_2D, 0); #ifndef OPENGLES_1 if (gsg->_supports_3d_texture) { - GLP(Disable)(GL_TEXTURE_3D); + GLP(BindTexture)(GL_TEXTURE_3D, 0); } #endif // OPENGLES_1 +#ifndef OPENGLES + if (gsg->_supports_2d_texture_array) { + GLP(BindTexture)(GL_TEXTURE_2D_ARRAY_EXT, 0); + } +#endif if (gsg->_supports_cube_map) { - GLP(Disable)(GL_TEXTURE_CUBE_MAP); + GLP(BindTexture)(GL_TEXTURE_CUBE_MAP, 0); } // This is probably faster - but maybe not as safe? // cgGLDisableTextureParameter(p); @@ -938,9 +943,6 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { // Unsupported texture mode. continue; } -#ifndef OPENGLES_2 - GLP(Enable)(target); -#endif gsg->apply_texture(tc); if (_shader->get_language() == Shader::SL_GLSL) { @@ -949,9 +951,6 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { } if (!gsg->update_texture(tc, false)) { -#ifndef OPENGLES_2 - GLP(Disable)(target); -#endif continue; } } diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 137ca24582..e787f99702 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -1,6 +1,7 @@ // Filename: shader.cxx // Created by: jyelon (01Sep05) // Updated by: fperazzi, PandaSE(06Apr10) +// Updated by: fperazzi, PandaSE(29Apr10) (added SAT_sampler2dArray) //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE @@ -57,42 +58,43 @@ cp_report_error(ShaderArgInfo &p, const string &msg) { string tstr = "invalid "; switch (p._type) { - case SAT_scalar: tstr = "scalar "; break; - case SAT_vec1: tstr = "vec1 "; break; - case SAT_vec2: tstr = "vec2 "; break; - case SAT_vec3: tstr = "vec3 "; break; - case SAT_vec4: tstr = "vec4 "; break; - case SAT_mat1x1: tstr = "mat1x1 "; break; - case SAT_mat1x2: tstr = "mat1x2 "; break; - case SAT_mat1x3: tstr = "mat1x3 "; break; - case SAT_mat1x4: tstr = "mat1x4 "; break; - case SAT_mat2x1: tstr = "mat2x1 "; break; - case SAT_mat2x2: tstr = "mat2x2 "; break; - case SAT_mat2x3: tstr = "mat2x3 "; break; - case SAT_mat2x4: tstr = "mat2x4 "; break; - case SAT_mat3x1: tstr = "mat3x1 "; break; - case SAT_mat3x2: tstr = "mat3x2 "; break; - case SAT_mat3x3: tstr = "mat3x3 "; break; - case SAT_mat3x4: tstr = "mat3x4 "; break; - case SAT_mat4x1: tstr = "mat4x1 "; break; - case SAT_mat4x2: tstr = "mat4x2 "; break; - case SAT_mat4x3: tstr = "mat4x3 "; break; - case SAT_mat4x4: tstr = "mat4x4 "; break; - case SAT_sampler1d: tstr = "sampler1d "; break; - case SAT_sampler2d: tstr = "sampler2d "; break; - case SAT_sampler3d: tstr = "sampler3d "; break; - case SAT_samplercube: tstr = "samplercube "; break; - default: tstr = "unknown "; break; + case SAT_scalar: tstr = "scalar "; break; + case SAT_vec1: tstr = "vec1 "; break; + case SAT_vec2: tstr = "vec2 "; break; + case SAT_vec3: tstr = "vec3 "; break; + case SAT_vec4: tstr = "vec4 "; break; + case SAT_mat1x1: tstr = "mat1x1 "; break; + case SAT_mat1x2: tstr = "mat1x2 "; break; + case SAT_mat1x3: tstr = "mat1x3 "; break; + case SAT_mat1x4: tstr = "mat1x4 "; break; + case SAT_mat2x1: tstr = "mat2x1 "; break; + case SAT_mat2x2: tstr = "mat2x2 "; break; + case SAT_mat2x3: tstr = "mat2x3 "; break; + case SAT_mat2x4: tstr = "mat2x4 "; break; + case SAT_mat3x1: tstr = "mat3x1 "; break; + case SAT_mat3x2: tstr = "mat3x2 "; break; + case SAT_mat3x3: tstr = "mat3x3 "; break; + case SAT_mat3x4: tstr = "mat3x4 "; break; + case SAT_mat4x1: tstr = "mat4x1 "; break; + case SAT_mat4x2: tstr = "mat4x2 "; break; + case SAT_mat4x3: tstr = "mat4x3 "; break; + case SAT_mat4x4: tstr = "mat4x4 "; break; + case SAT_sampler1d: tstr = "sampler1d "; break; + case SAT_sampler2d: tstr = "sampler2d "; break; + case SAT_sampler3d: tstr = "sampler3d "; break; + case SAT_sampler2dArray: tstr = "sampler2dArray "; break; + case SAT_samplercube: tstr = "samplercube "; break; + default: tstr = "unknown "; break; } string cstr = "invalid"; switch (p._class) { - case SAC_scalar: cstr = "scalar "; break; - case SAC_vector: cstr = "vector "; break; - case SAC_matrix: cstr = "matrix "; break; + case SAC_scalar: cstr = "scalar "; break; + case SAC_vector: cstr = "vector "; break; + case SAC_matrix: cstr = "matrix "; break; case SAC_sampler: cstr = "sampler "; break; - case SAC_array: cstr = "array "; break; - default: cstr = "unknown ";break; + case SAC_array: cstr = "array "; break; + default: cstr = "unknown "; break; } Filename fn = get_filename(p._id._type); @@ -238,6 +240,7 @@ cp_errchk_parameter_sampler(ShaderArgInfo &p) if ((p._type!=SAT_sampler1d)&& (p._type!=SAT_sampler2d)&& (p._type!=SAT_sampler3d)&& + (p._type!=SAT_sampler2dArray)&& (p._type!=SAT_samplercube)) { cp_report_error(p, "parameter should have a 'sampler' type"); return false; @@ -1021,10 +1024,11 @@ compile_parameter(const ShaderArgId &arg_id, bind._name = 0; bind._stage = atoi(pieces[1].c_str()); switch (p._type) { - case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture; break; - case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break; - case SAT_sampler3d: bind._desired_type = Texture::TT_3d_texture; break; - case SAT_samplercube: bind._desired_type = Texture::TT_cube_map; break; + case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture; break; + case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break; + case SAT_sampler3d: bind._desired_type = Texture::TT_3d_texture; break; + case SAT_sampler2dArray: bind._desired_type = Texture::TT_2d_texture_array; break; + case SAT_samplercube: bind._desired_type = Texture::TT_cube_map; break; default: cp_report_error(p, "Invalid type for a tex-parameter"); return false; @@ -1153,6 +1157,14 @@ compile_parameter(const ShaderArgId &arg_id, _tex_spec.push_back(bind); return true; } + case SAT_sampler2dArray: { + ShaderTexSpec bind; + bind._id = arg_id; + bind._name = kinputname; + bind._desired_type = Texture::TT_2d_texture_array; + _tex_spec.push_back(bind); + return true; + } case SAT_samplercube: { ShaderTexSpec bind; bind._id = arg_id; @@ -1245,10 +1257,11 @@ cg_parameter_type(CGparameter p) { } case CG_PARAMETERCLASS_SAMPLER: switch (cgGetParameterType(p)){ - case CG_SAMPLER1D: return Shader::SAT_sampler1d; - case CG_SAMPLER2D: return Shader::SAT_sampler2d; - case CG_SAMPLER3D: return Shader::SAT_sampler3d; - case CG_SAMPLERCUBE: return Shader::SAT_samplercube; + case CG_SAMPLER1D: return Shader::SAT_sampler1d; + case CG_SAMPLER2D: return Shader::SAT_sampler2d; + case CG_SAMPLER3D: return Shader::SAT_sampler3d; + case CG_SAMPLER2DARRAY: return Shader::SAT_sampler2dArray; + case CG_SAMPLERCUBE: return Shader::SAT_samplercube; default: return SAT_unknown; } case CG_PARAMETERCLASS_ARRAY: return SAT_unknown; diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index bf478fc2a1..a267ffb8f0 100755 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -1,6 +1,6 @@ // Filename: shader.h // Created by: jyelon (01Sep05) -// Updated by: fperazzi, PandaSE(06Apr10) +// Updated by: fperazzi, PandaSE(29Apr10) (added SAT_sampler2dArray) //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE @@ -171,7 +171,8 @@ public: SAT_mat4x4, SAT_sampler1d, SAT_sampler2d, - SAT_sampler3d, + SAT_sampler3d, + SAT_sampler2dArray, SAT_samplercube, SAT_unknown }; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 4c3b674296..6ed0d1c323 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -1,5 +1,6 @@ // Filename: texture.I // Created by: drose (05Feb99) +// Updated by: fperazzi, PandaSE(29Apr10) (added setup_2d_texture_array) // //////////////////////////////////////////////////////////////////// // @@ -144,6 +145,34 @@ setup_3d_texture(int x_size, int y_size, int z_size, setup_texture(TT_3d_texture, x_size, y_size, z_size, component_type, format); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_2d_texture_array +// Access: Published +// Description: Sets the texture as an empty 2-d texture array with +// no dimensions (though if you know the depth ahead +// of time, it saves a bit of reallocation later). +// Follow up with read() or load() to fill the texture +// properties and image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_2d_texture_array(int z_size) { + setup_2d_texture_array(0, 1, z_size, T_unsigned_byte, F_rgb); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_2d_texture_array +// Access: Published +// Description: Sets the texture as an empty 2-d texture array with the +// specified dimensions and properties. Follow up with +// set_ram_image() or modify_ram_image() to fill the +// image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_2d_texture_array(int x_size, int y_size, int z_size, + ComponentType component_type, Format format) { + setup_texture(TT_2d_texture_array, x_size, y_size, z_size, component_type, format); +} + //////////////////////////////////////////////////////////////////// // Function: Texture::setup_cube_map // Access: Published diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 941257219e..c47cf8f8a5 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1,5 +1,6 @@ // Filename: texture.cxx // Created by: mike (09Jan97) +// Updated by: fperazzi, PandaSE(29Apr10) (added TT_2d_texture_array) // //////////////////////////////////////////////////////////////////// // @@ -1360,7 +1361,11 @@ write(ostream &out, int indent_level) const { case TT_3d_texture: out << "3-d, " << _x_size << " x " << _y_size << " x " << _z_size; break; - + + case TT_2d_texture_array: + out << "2-d array, " << _x_size << " x " << _y_size << " x " << _z_size; + break; + case TT_cube_map: out << "cube map, " << _x_size << " x " << _y_size; break; @@ -1490,6 +1495,10 @@ write(ostream &out, int indent_level) const { out << _wrap_u << " x " << _wrap_v << " x " << _wrap_w << ", "; break; + case TT_2d_texture_array: + out << _wrap_u << " x " << _wrap_v << " x " << _wrap_w << ", "; + break; + case TT_cube_map: break; } @@ -3553,7 +3562,9 @@ do_compress_ram_image(Texture::CompressionMode compression, } #ifdef HAVE_SQUISH - if (_texture_type != TT_3d_texture && _component_type == T_unsigned_byte) { + if (_texture_type != TT_3d_texture && + _texture_type != TT_2d_texture_array && + _component_type == T_unsigned_byte) { int squish_flags = 0; switch (compression) { case CM_dxt1: @@ -3612,7 +3623,9 @@ bool Texture:: do_uncompress_ram_image() { #ifdef HAVE_SQUISH - if (_texture_type != TT_3d_texture && _component_type == T_unsigned_byte) { + if (_texture_type != TT_3d_texture && + _texture_type != TT_2d_texture_array && + _component_type == T_unsigned_byte) { int squish_flags = 0; switch (_ram_image_compression) { case CM_dxt1: @@ -3689,9 +3702,10 @@ do_reconsider_z_size(int z) { if (z >= _z_size) { // If we're loading a page past _z_size, treat it as an implicit // request to enlarge _z_size. However, this is only legal if - // this is, in fact, a 3-d texture (cube maps always have z_size - // 6, and other types have z_size 1). - nassertr(_texture_type == Texture::TT_3d_texture, false); + // this is, in fact, a 3-d texture or a 2d texture array (cube maps + // always have z_size 6, and other types have z_size 1). + nassertr(_texture_type == Texture::TT_3d_texture || + _texture_type == Texture::TT_2d_texture_array, false); _z_size = z + 1; // Increase the size of the data buffer to make room for the new @@ -3882,6 +3896,9 @@ do_setup_texture(Texture::TextureType texture_type, int x_size, int y_size, case TT_3d_texture: break; + case TT_2d_texture_array: + break; + case TT_cube_map: // Cube maps must always consist of six square images. nassertv(x_size == y_size && z_size == 6); @@ -4039,9 +4056,9 @@ do_set_y_size(int y_size) { void Texture:: do_set_z_size(int z_size) { if (_z_size != z_size) { - nassertv(_texture_type == Texture::TT_3d_texture || + nassertv((_texture_type == Texture::TT_3d_texture) || (_texture_type == Texture::TT_cube_map && z_size == 6) || - (z_size == 1)); + (_texture_type == Texture::TT_2d_texture_array) || (z_size == 1)); _z_size = z_size; ++_image_modified; do_clear_ram_image(); @@ -6139,7 +6156,11 @@ make_from_bam(const FactoryParams ¶ms) { case TT_3d_texture: me = TexturePool::load_3d_texture(filename, false, options); break; - + + case TT_2d_texture_array: + me = TexturePool::load_2d_texture_array(filename, false, options); + break; + case TT_cube_map: me = TexturePool::load_cube_map(filename, false, options); break; @@ -6465,6 +6486,8 @@ operator << (ostream &out, Texture::TextureType tt) { return out << "2d_texture"; case Texture::TT_3d_texture: return out << "3d_texture"; + case Texture::TT_2d_texture_array: + return out << "2d_texture_array"; case Texture::TT_cube_map: return out << "cube_map"; } diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index f58a6e5d80..a4256e3419 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -1,5 +1,6 @@ // Filename: texture.h // Created by: mike (09Jan97) +// Updated by: fperazzi, PandaSE(29Apr10) (added TT_2d_texture_array) // //////////////////////////////////////////////////////////////////// // @@ -66,6 +67,7 @@ PUBLISHED: TT_1d_texture, TT_2d_texture, TT_3d_texture, + TT_2d_texture_array, TT_cube_map, }; @@ -217,7 +219,9 @@ PUBLISHED: INLINE void setup_cube_map(); INLINE void setup_cube_map(int size, ComponentType component_type, Format format); - + INLINE void setup_2d_texture_array(int z_size = 1); + INLINE void setup_2d_texture_array(int x_size, int y_size, int z_size, + ComponentType component_type, Format format); void generate_normalization_cube_map(int size); void generate_alpha_scale_map(); diff --git a/panda/src/gobj/texturePool.I b/panda/src/gobj/texturePool.I index 388559bf0f..c8aea71351 100644 --- a/panda/src/gobj/texturePool.I +++ b/panda/src/gobj/texturePool.I @@ -1,5 +1,6 @@ // Filename: texturePool.I // Created by: drose (26Apr00) +// Updated by: fperazzi, PandaSE(29Apr10) (added load_2d_texture_array) // //////////////////////////////////////////////////////////////////// // @@ -106,6 +107,27 @@ load_3d_texture(const Filename &filename_pattern, bool read_mipmaps, options); } +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::load_2d_texture_array +// Access: Published, Static +// Description: Loads a 2-D texture array that is specified with a series +// of n pages, all numbered in sequence, and beginning +// with index 0. The filename should include a sequence +// of one or more hash characters ("#") which will be +// filled in with the index number of each level. +// +// If read_mipmaps is true, the filename should contain +// an additional hash mark. The first hash mark will be +// filled in with the mipmap level number, and the +// second with the index number of each 2-d level. +//////////////////////////////////////////////////////////////////// +INLINE Texture *TexturePool:: +load_2d_texture_array(const Filename &filename_pattern, bool read_mipmaps, + const LoaderOptions &options) { + return get_global_ptr()->ns_load_2d_texture_array(filename_pattern, read_mipmaps, + options); +} + //////////////////////////////////////////////////////////////////// // Function: TexturePool::load_cube_map // Access: Published, Static diff --git a/panda/src/gobj/texturePool.cxx b/panda/src/gobj/texturePool.cxx index e6409ccc38..17afc961ec 100644 --- a/panda/src/gobj/texturePool.cxx +++ b/panda/src/gobj/texturePool.cxx @@ -1,5 +1,6 @@ // Filename: texturePool.cxx // Created by: drose (26Apr00) +// Updated by: fperazzi, PandaSE(29Apr10) (added ns_load_2d_texture_array) // //////////////////////////////////////////////////////////////////// // @@ -491,8 +492,10 @@ ns_load_3d_texture(const Filename &filename_pattern, Textures::const_iterator ti; ti = _textures.find(filename); if (ti != _textures.end()) { - // This texture was previously loaded. - return (*ti).second; + if ((*ti).second->get_texture_type() == Texture::TT_3d_texture) { + // This texture was previously loaded, as a 3d texture + return (*ti).second; + } } } @@ -554,8 +557,10 @@ ns_load_3d_texture(const Filename &filename_pattern, Textures::const_iterator ti; ti = _textures.find(filename); if (ti != _textures.end()) { - // This texture was previously loaded. - return (*ti).second; + if ((*ti).second->get_texture_type() == Texture::TT_3d_texture) { + // This texture was previously loaded, as a 3d texture + return (*ti).second; + } } _textures[filename] = tex; @@ -571,6 +576,112 @@ ns_load_3d_texture(const Filename &filename_pattern, return tex; } +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::ns_load_2d_texture_array +// Access: Private +// Description: The nonstatic implementation of load_2d_texture_array(). +//////////////////////////////////////////////////////////////////// +Texture *TexturePool:: +ns_load_2d_texture_array(const Filename &filename_pattern, + bool read_mipmaps, const LoaderOptions &options) { + Filename orig_filename(filename_pattern); + orig_filename.set_pattern(true); + + Filename filename; + Filename unique_filename; //differentiate 3d-textures from 2d-texture arrays + { + MutexHolder holder(_lock); + resolve_filename(filename, orig_filename); + // Differentiate from preloaded 3d textures + unique_filename = filename + ".2DARRAY"; + + Textures::const_iterator ti; + ti = _textures.find(unique_filename); + if (ti != _textures.end()) { + if ((*ti).second->get_texture_type() == Texture::TT_2d_texture_array) { + // This texture was previously loaded, as a 2d texture array + return (*ti).second; + } + } + } + + PT(Texture) tex; + PT(BamCacheRecord) record; + bool store_record = false; + + BamCache *cache = BamCache::get_global_ptr(); + bool compressed_cache_record = false; + try_load_cache(tex, cache, filename, record, compressed_cache_record, + options); + + if (tex == (Texture *)NULL || + tex->get_texture_type() != Texture::TT_2d_texture_array) { + // The texture was neither in the pool, nor found in the on-disk + // cache; it needs to be loaded from its source image(s). + gobj_cat.info() + << "Loading 2-d texture array " << filename << "\n"; + tex = make_texture(filename.get_extension()); + tex->setup_2d_texture_array(); + if (!tex->read(filename, 0, 0, true, read_mipmaps, options)) { + // This texture was not found or could not be read. + report_texture_unreadable(filename); + return NULL; + } + store_record = (record != (BamCacheRecord *)NULL); + } + + if (cache->get_cache_compressed_textures() && tex->has_compression()) { +#ifndef HAVE_SQUISH + bool needs_driver_compression = true; +#else + bool needs_driver_compression = driver_compress_textures; +#endif // HAVE_SQUISH + if (needs_driver_compression) { + // We don't want to save the uncompressed version; we'll save the + // compressed version when it becomes available. + store_record = false; + if (!compressed_cache_record) { + tex->set_post_load_store_cache(true); + } + } + + } else if (!cache->get_cache_textures()) { + // We don't want to save this texture. + store_record = false; + } + + // Set the original filename, before we searched along the path. + nassertr(tex != (Texture *)NULL, false); + tex->set_filename(filename_pattern); + tex->set_fullpath(filename); + tex->_texture_pool_key = filename; + + { + MutexHolder holder(_lock); + + // Now look again. + Textures::const_iterator ti; + ti = _textures.find(unique_filename); + if (ti != _textures.end()) { + if ((*ti).second->get_texture_type() == Texture::TT_2d_texture_array) { + // This texture was previously loaded, as a 2d texture array + return (*ti).second; + } + } + + _textures[unique_filename] = tex; + } + + if (store_record && tex->has_ram_image()) { + // Store the on-disk cache record for next time. + record->set_data(tex, tex); + cache->store(record); + } + + nassertr(!tex->get_fullpath().empty(), tex); + return tex; +} + //////////////////////////////////////////////////////////////////// // Function: TexturePool::ns_load_cube_map // Access: Private diff --git a/panda/src/gobj/texturePool.h b/panda/src/gobj/texturePool.h index 6f070154af..52a24d4592 100644 --- a/panda/src/gobj/texturePool.h +++ b/panda/src/gobj/texturePool.h @@ -1,5 +1,6 @@ // Filename: texturePool.h // Created by: drose (26Apr00) +// Updated by: fperazzi, PandaSE(29Apr10) (added load_2d_texture_array) // //////////////////////////////////////////////////////////////////// // @@ -53,6 +54,9 @@ PUBLISHED: INLINE static Texture *load_3d_texture(const Filename &filename_pattern, bool read_mipmaps = false, const LoaderOptions &options = LoaderOptions()); + INLINE static Texture *load_2d_texture_array(const Filename &filename_pattern, + bool read_mipmaps = false, + const LoaderOptions &options = LoaderOptions()); INLINE static Texture *load_cube_map(const Filename &filename_pattern, bool read_mipmaps = false, const LoaderOptions &options = LoaderOptions()); @@ -108,6 +112,9 @@ private: Texture *ns_load_3d_texture(const Filename &filename_pattern, bool read_mipmaps, const LoaderOptions &options); + Texture *ns_load_2d_texture_array(const Filename &filename_pattern, + bool read_mipmaps, + const LoaderOptions &options); Texture *ns_load_cube_map(const Filename &filename_pattern, bool read_mipmaps, const LoaderOptions &options); diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 5809ded96b..e647dcc480 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -3420,7 +3420,11 @@ set_texture(Texture *tex, int priority) { void NodePath:: set_texture(TextureStage *stage, Texture *tex, int priority) { nassertv_always(!is_empty()); - + if (tex->get_texture_type() == Texture::TT_2d_texture_array){ + pgraph_cat.error() << "Texture::TT_2d_texture_array is not supported by" << \ + " the fixed pipeline.\n"; + return; + } const RenderAttrib *attrib = node()->get_attrib(TextureAttrib::get_class_slot()); if (attrib != (const RenderAttrib *)NULL) {