From 2ff9083812aa20f667a03b1917670fc7ceda9533 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 16 Apr 2015 16:55:29 +0200 Subject: [PATCH] Add support for buffer textures --- panda/src/display/graphicsStateGuardian.I | 26 +++ panda/src/display/graphicsStateGuardian.cxx | 2 + panda/src/display/graphicsStateGuardian.h | 4 + .../glstuff/glGraphicsStateGuardian_src.cxx | 155 +++++++++++++++--- .../src/glstuff/glGraphicsStateGuardian_src.h | 4 + panda/src/glstuff/glShaderContext_src.cxx | 26 ++- panda/src/glstuff/glTextureContext_src.I | 1 + panda/src/glstuff/glTextureContext_src.cxx | 10 ++ panda/src/glstuff/glTextureContext_src.h | 3 + panda/src/gobj/texture.I | 32 ++++ panda/src/gobj/texture.cxx | 31 +++- panda/src/gobj/texture.h | 6 + 12 files changed, 274 insertions(+), 26 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index a4cea5ffc3..9cfa0e3fed 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -397,6 +397,22 @@ get_max_cube_map_dimension() const { return _max_cube_map_dimension; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_max_buffer_texture_size +// Access: Published +// Description: Returns the largest possible buffer texture size, +// or -1 if there is no particular limit. Returns 0 +// if cube map textures are 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_buffer_texture_size() const { + return _max_buffer_texture_size; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_supports_texture_combine // Access: Published @@ -469,6 +485,16 @@ get_supports_cube_map() const { return _supports_cube_map; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_supports_buffer_texture +// Access: Published +// Description: Returns true if this GSG can render buffer textures. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +get_supports_buffer_texture() const { + return _supports_buffer_texture; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_supports_tex_non_pow2 // Access: Published diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 1263339604..41cc8315ea 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -185,6 +185,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _max_3d_texture_dimension = 0; _max_2d_texture_array_layers = 0; _max_cube_map_dimension = 0; + _max_buffer_texture_size = 0; // Assume we don't support these fairly advanced texture combiner // modes. @@ -195,6 +196,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _supports_3d_texture = false; _supports_2d_texture_array = false; _supports_cube_map = false; + _supports_buffer_texture = false; _supports_tex_non_pow2 = false; _supports_texture_srgb = false; _supports_compressed_texture = false; diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index b546a61945..7e9d8b6f47 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -121,6 +121,7 @@ PUBLISHED: 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 int get_max_buffer_texture_size() const; INLINE bool get_supports_texture_combine() const; INLINE bool get_supports_texture_saved_result() const; @@ -129,6 +130,7 @@ PUBLISHED: 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_buffer_texture() const; INLINE bool get_supports_tex_non_pow2() const; INLINE bool get_supports_texture_srgb() const; @@ -476,6 +478,7 @@ protected: int _max_3d_texture_dimension; int _max_2d_texture_array_layers; //on the z axis int _max_cube_map_dimension; + int _max_buffer_texture_size; bool _supports_texture_combine; bool _supports_texture_saved_result; @@ -484,6 +487,7 @@ protected: bool _supports_3d_texture; bool _supports_2d_texture_array; bool _supports_cube_map; + bool _supports_buffer_texture; bool _supports_tex_non_pow2; bool _supports_texture_srgb; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 637bfb63e9..8efef7fd09 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -854,6 +854,17 @@ reset() { } #endif +#ifndef OPENGLES + if (is_at_least_gl_version(3, 0)) { + _glTexBuffer = (PFNGLTEXBUFFERPROC)get_extension_func("glTexBuffer"); + _supports_buffer_texture = true; + + } else if (has_extension("GL_ARB_texture_buffer_object")) { + _glTexBuffer = (PFNGLTEXBUFFERPROC)get_extension_func("glTexBufferARB"); + _supports_buffer_texture = true; + } +#endif + _supports_texture_srgb = false; if (is_at_least_gl_version(2, 1) || has_extension("GL_EXT_texture_sRGB")) { _supports_texture_srgb = true; @@ -1941,6 +1952,7 @@ reset() { GLint max_3d_texture_size = 0; GLint max_2d_texture_array_layers = 0; GLint max_cube_map_size = 0; + GLint max_buffer_texture_size = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); _max_texture_dimension = max_texture_size; @@ -1966,6 +1978,15 @@ reset() { _max_cube_map_dimension = 0; } +#ifndef OPENGLES + if (_supports_buffer_texture) { + glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max_buffer_texture_size); + _max_buffer_texture_size = max_buffer_texture_size; + } else { + _max_buffer_texture_size = 0; + } +#endif // !OPENGLES + GLint max_elements_vertices = 0, max_elements_indices = 0; #ifndef OPENGLES glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &max_elements_vertices); @@ -4510,6 +4531,15 @@ prepare_texture(Texture *tex, int view) { << "Cube map textures are not supported by this OpenGL driver.\n"; return NULL; } + break; + + case Texture::TT_buffer_texture: + if (!_supports_buffer_texture) { + GLCAT.warning() + << "Buffer textures are not supported by this OpenGL driver.\n"; + return NULL; + } + break; default: break; @@ -7362,27 +7392,35 @@ get_texture_target(Texture::TextureType texture_type) const { return GL_TEXTURE_2D; case Texture::TT_3d_texture: - if (_supports_3d_texture) { #ifndef OPENGLES_1 + if (_supports_3d_texture) { return GL_TEXTURE_3D; -#endif - } else { - return GL_NONE; } +#endif + return GL_NONE; + case Texture::TT_2d_texture_array: - if (_supports_2d_texture_array) { #ifndef OPENGLES + if (_supports_2d_texture_array) { return GL_TEXTURE_2D_ARRAY_EXT; -#endif - } else { - return GL_NONE; } +#endif + return GL_NONE; + case Texture::TT_cube_map: if (_supports_cube_map) { return GL_TEXTURE_CUBE_MAP; } else { return GL_NONE; } + + case Texture::TT_buffer_texture: +#ifndef OPENGLES + if (_supports_buffer_texture) { + return GL_TEXTURE_BUFFER; + } +#endif + return GL_NONE; } GLCAT.error() << "Invalid Texture::TextureType value!\n"; @@ -10252,6 +10290,12 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { // Unsupported target (e.g. 3-d texturing on GL 1.1). return false; } +#ifndef OPENGLES + if (target == GL_TEXTURE_BUFFER) { + // Buffer textures may not receive texture parameters. + return false; + } +#endif // OPENGLES // Record the active sampler settings. gtc->_active_sampler = sampler; @@ -10505,7 +10549,8 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { // If we'll use immutable texture storage, we have to pick a sized // image format. - bool force_sized = (gl_immutable_texture_storage && _supports_tex_storage); + bool force_sized = (gl_immutable_texture_storage && _supports_tex_storage) || + (tex->get_texture_type() == Texture::TT_buffer_texture); GLint internal_format = get_internal_image_format(tex, force_sized); GLint external_format = get_external_image_format(tex); @@ -10553,6 +10598,12 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { max_dimension_z = _max_2d_texture_array_layers; break; + case Texture::TT_buffer_texture: + max_dimension_x = _max_buffer_texture_size; + max_dimension_y = 1; + max_dimension_z = 1; + break; + default: max_dimension_x = _max_texture_dimension; max_dimension_y = _max_texture_dimension; @@ -10631,6 +10682,13 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { GLenum target = get_texture_target(tex->get_texture_type()); uses_mipmaps = (uses_mipmaps && !gl_ignore_mipmaps) || gl_force_mipmaps; +#ifndef OPENGLES + if (target == GL_TEXTURE_BUFFER) { + // Buffer textures may not have mipmaps. + uses_mipmaps = false; + } +#endif // OPENGLES + bool needs_reload = false; if (!gtc->_has_storage || gtc->_uses_mipmaps != uses_mipmaps || @@ -10640,6 +10698,12 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { gtc->_depth != depth) { // We need to reload a new GL Texture object. needs_reload = true; + + if (_use_object_labels) { + // This seems like a good time to assign a label for the debug messages. + const string &name = tex->get_name(); + _glObjectLabel(GL_TEXTURE, gtc->_index, name.size(), name.data()); + } } if (needs_reload && gtc->_immutable) { @@ -10648,13 +10712,26 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { glBindTexture(target, gtc->_index); } - if (needs_reload) { - if (_use_object_labels) { - // This seems like a good time to assign a label for the debug messages. - const string &name = tex->get_name(); - _glObjectLabel(GL_TEXTURE, gtc->_index, name.size(), name.data()); - } +#ifndef OPENGLES + if (target == GL_TEXTURE_BUFFER) { + // Buffer textures don't support mipmappping. + gtc->_generate_mipmaps = false; + if (gtc->_buffer == 0) { + // The buffer object wasn't created yet. + _glGenBuffers(1, >c->_buffer); + _glBindBuffer(GL_TEXTURE_BUFFER, gtc->_buffer); + _glTexBuffer(GL_TEXTURE_BUFFER, internal_format, gtc->_buffer); + needs_reload = true; + } else { + _glBindBuffer(GL_TEXTURE_BUFFER, gtc->_buffer); + if (gtc->_internal_format != internal_format) { + _glTexBuffer(GL_TEXTURE_BUFFER, internal_format, gtc->_buffer); + } + } + } else +#endif // !OPENGLES + if (needs_reload) { // Figure out whether mipmaps will be generated by the GPU or by // Panda (or not at all), and how many mipmap levels should be created. gtc->_generate_mipmaps = false; @@ -10736,6 +10813,8 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { } switch (tex->get_texture_type()) { + case Texture::TT_buffer_texture: + // Won't get here, but squelch compiler warning case Texture::TT_1d_texture: _glTexStorage1D(target, num_levels, internal_format, width); break; @@ -11095,6 +11174,17 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, break; #endif // OPENGLES +#ifndef OPENGLES + case GL_TEXTURE_BUFFER: + if (_supports_buffer_texture) { + _glBufferSubData(GL_TEXTURE_BUFFER, 0, width, image_ptr); + } else { + report_my_gl_errors(); + return false; + } + break; +#endif // OPENGLES + default: if (image_compression == Texture::CM_off) { if (n==0) { @@ -11248,6 +11338,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, } break; #endif + #ifndef OPENGLES case GL_TEXTURE_2D_ARRAY_EXT: if (_supports_2d_texture_array) { @@ -11265,7 +11356,19 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, return false; } break; -#endif +#endif // OPENGLES + +#ifndef OPENGLES + case GL_TEXTURE_BUFFER: + if (_supports_buffer_texture) { + _glBufferData(GL_TEXTURE_BUFFER, width, image_ptr, + get_usage(tex->get_usage_hint())); + } else { + report_my_gl_errors(); + return false; + } + break; +#endif // OPENGLES default: if (image_compression == Texture::CM_off) { @@ -11396,6 +11499,12 @@ get_texture_memory_size(Texture *tex) { // We need a particular page to get the level parameter from. page_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; scale = 6; + + } else if (target == GL_TEXTURE_BUFFER) { + // In the case of buffer textures, we provided the size to begin with, + // so no point in querying anything. Plus, glGetTexParameter is not even + // supported for buffer textures. + return tex->get_expected_ram_image_size(); } GLint minfilter; @@ -11431,20 +11540,20 @@ get_texture_memory_size(Texture *tex) { luminance_size, intensity_size; GLint depth_size = 0; glGetTexLevelParameteriv(page_target, 0, - GL_TEXTURE_RED_SIZE, &red_size); + GL_TEXTURE_RED_SIZE, &red_size); glGetTexLevelParameteriv(page_target, 0, - GL_TEXTURE_GREEN_SIZE, &green_size); + GL_TEXTURE_GREEN_SIZE, &green_size); glGetTexLevelParameteriv(page_target, 0, - GL_TEXTURE_BLUE_SIZE, &blue_size); + GL_TEXTURE_BLUE_SIZE, &blue_size); glGetTexLevelParameteriv(page_target, 0, - GL_TEXTURE_ALPHA_SIZE, &alpha_size); + GL_TEXTURE_ALPHA_SIZE, &alpha_size); glGetTexLevelParameteriv(page_target, 0, - GL_TEXTURE_LUMINANCE_SIZE, &luminance_size); + GL_TEXTURE_LUMINANCE_SIZE, &luminance_size); glGetTexLevelParameteriv(page_target, 0, - GL_TEXTURE_INTENSITY_SIZE, &intensity_size); + GL_TEXTURE_INTENSITY_SIZE, &intensity_size); if (_supports_depth_texture) { glGetTexLevelParameteriv(page_target, 0, - GL_TEXTURE_DEPTH_SIZE, &depth_size); + GL_TEXTURE_DEPTH_SIZE, &depth_size); } GLint width = 1, height = 1, depth = 1; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 3a7f5ddba7..cac7694f4e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -693,6 +693,10 @@ public: PFNGLTEXSTORAGE2DPROC _glTexStorage2D; PFNGLTEXSTORAGE3DPROC _glTexStorage3D; +#ifndef OPENGLES + PFNGLTEXBUFFERPROC _glTexBuffer; +#endif + bool _supports_clear_texture; #ifndef OPENGLES PFNGLCLEARTEXIMAGEPROC _glClearTexImage; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 3c031dc904..dc50428d00 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -602,16 +602,19 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext case GL_INT_SAMPLER_3D: case GL_INT_SAMPLER_2D_ARRAY: case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_BUFFER: case GL_UNSIGNED_INT_SAMPLER_1D: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_1D: case GL_SAMPLER_CUBE_SHADOW: case GL_SAMPLER_2D_ARRAY: case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_BUFFER: #endif // !OPENGLES case GL_SAMPLER_2D: case GL_SAMPLER_2D_SHADOW: @@ -620,7 +623,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext Shader::ShaderTexSpec bind; bind._id = arg_id; bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_2d_texture_array; + bind._desired_type = Texture::TT_2d_texture; bind._stage = texunitno++; if (get_sampler_texture_type(bind._desired_type, param_type)) { _glgsg->_glUniform1i(p, s->_tex_spec.size()); @@ -761,16 +764,19 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext case GL_IMAGE_3D_EXT: case GL_IMAGE_CUBE_EXT: case GL_IMAGE_2D_ARRAY_EXT: + case GL_IMAGE_BUFFER_EXT: case GL_INT_IMAGE_1D_EXT: case GL_INT_IMAGE_2D_EXT: case GL_INT_IMAGE_3D_EXT: case GL_INT_IMAGE_CUBE_EXT: case GL_INT_IMAGE_2D_ARRAY_EXT: + case GL_INT_IMAGE_BUFFER_EXT: case GL_UNSIGNED_INT_IMAGE_1D_EXT: case GL_UNSIGNED_INT_IMAGE_2D_EXT: case GL_UNSIGNED_INT_IMAGE_3D_EXT: case GL_UNSIGNED_INT_IMAGE_CUBE_EXT: case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT: + case GL_UNSIGNED_INT_IMAGE_BUFFER_EXT: // This won't really change at runtime, so we might as well // bind once and then forget about it. _glgsg->_glUniform1i(p, imgunitno++); @@ -1076,6 +1082,18 @@ get_sampler_texture_type(int &out, GLenum param_type) { << "GLSL shader uses 2D texture array, which is unsupported by the driver.\n"; return false; } + + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_BUFFER: + out = Texture::TT_buffer_texture; + if (_glgsg->_supports_buffer_texture) { + return true; + } else { + GLCAT.error() + << "GLSL shader uses buffer texture, which is unsupported by the driver.\n"; + return false; + } #endif default: @@ -1509,6 +1527,12 @@ disable_shader_texture_bindings() { case Texture::TT_cube_map: glBindTexture(GL_TEXTURE_CUBE_MAP, 0); break; + + case Texture::TT_buffer_texture: +#ifndef OPENGLES + glBindTexture(GL_TEXTURE_BUFFER, 0); +#endif + break; } } diff --git a/panda/src/glstuff/glTextureContext_src.I b/panda/src/glstuff/glTextureContext_src.I index 687a2e1f3b..37aa40d50c 100644 --- a/panda/src/glstuff/glTextureContext_src.I +++ b/panda/src/glstuff/glTextureContext_src.I @@ -26,6 +26,7 @@ CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg, _glgsg = glgsg; glGenTextures(1, &_index); + _buffer = 0; _handle = 0; _has_storage = false; diff --git a/panda/src/glstuff/glTextureContext_src.cxx b/panda/src/glstuff/glTextureContext_src.cxx index af6d8c7259..1383275832 100644 --- a/panda/src/glstuff/glTextureContext_src.cxx +++ b/panda/src/glstuff/glTextureContext_src.cxx @@ -34,6 +34,11 @@ CLP(TextureContext):: glDeleteTextures(1, &_index); _index = 0; + + if (_buffer != 0) { + _glgsg->_glDeleteBuffers(1, &_buffer); + _buffer = 0; + } } //////////////////////////////////////////////////////////////////// @@ -88,6 +93,11 @@ reset_data() { // Free the texture resources. glDeleteTextures(1, &_index); + if (_buffer != 0) { + _glgsg->_glDeleteBuffers(1, &_buffer); + _buffer = 0; + } + // We still need a valid index number, though, in case we want to // re-load the texture later. glGenTextures(1, &_index); diff --git a/panda/src/glstuff/glTextureContext_src.h b/panda/src/glstuff/glTextureContext_src.h index 14a0b68f6e..57fd2fc790 100644 --- a/panda/src/glstuff/glTextureContext_src.h +++ b/panda/src/glstuff/glTextureContext_src.h @@ -48,6 +48,9 @@ public: // This is the GL "name" of the texture object. GLuint _index; + // This is only used for buffer textures. + GLuint _buffer; + // This is the bindless "handle" to the texture object. GLuint64 _handle; bool _handle_resident; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index e7db1364ce..4aeaf4b259 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -215,6 +215,26 @@ setup_cube_map(int size, ComponentType component_type, Format format) { setup_texture(TT_cube_map, size, size, 6, component_type, format); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_buffer_texture +// Access: Published +// Description: Sets the texture as an empty buffer texture with +// the specified size and properties. Follow up +// with set_ram_image() or modify_ram_image() to fill +// the image data, or use set_clear_color to let the +// texture be cleared to a solid color. +// +// Note that a buffer texture's format needs to match +// the component type. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_buffer_texture(int size, ComponentType component_type, Format format, + GeomEnums::UsageHint usage) { + setup_texture(TT_buffer_texture, size, 1, 1, component_type, format); + CDWriter cdata(_cycler); + cdata->_usage_hint = usage; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::clear_image // Access: Published @@ -886,6 +906,18 @@ get_component_type() const { return cdata->_component_type; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_usage_hint +// Access: Published +// Description: Returns the usage hint specified for buffer textures, +// or UH_unspecified for all other texture types. +//////////////////////////////////////////////////////////////////// +INLINE GeomEnums::UsageHint Texture:: +get_usage_hint() const { + CDReader cdata(_cycler); + return cdata->_usage_hint; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::set_wrap_u // Access: Published diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index bf6b8f0422..13137221f0 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1524,6 +1524,10 @@ write(ostream &out, int indent_level) const { case TT_cube_map: out << "cube map, " << cdata->_x_size << " x " << cdata->_y_size; break; + + case TT_buffer_texture: + out << "buffer, " << cdata->_x_size; + break; } if (cdata->_num_views > 1) { @@ -1924,6 +1928,8 @@ format_texture_type(TextureType tt) { return "2d_texture_array"; case TT_cube_map: return "cube_map"; + case TT_buffer_texture: + return "buffer_texture"; } return "**invalid**"; } @@ -1946,6 +1952,8 @@ string_texture_type(const string &str) { return TT_2d_texture_array; } else if (cmp_nocase(str, "cube_map") == 0) { return TT_cube_map; + } else if (cmp_nocase(str, "buffer_texture") == 0) { + return TT_buffer_texture; } gobj_cat->error() @@ -2673,6 +2681,7 @@ do_read(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpath, switch (cdata->_texture_type) { case TT_1d_texture: case TT_2d_texture: + case TT_buffer_texture: z_size = 1; break; @@ -4854,7 +4863,8 @@ do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_com } #ifndef NDEBUG - if (cdata->_texture_type == TT_1d_texture) { + if (cdata->_texture_type == TT_1d_texture || + cdata->_texture_type == TT_buffer_texture) { nassertr(y_size == 1, false); } else if (cdata->_texture_type == TT_cube_map) { nassertr(x_size == y_size, false); @@ -5051,6 +5061,10 @@ do_setup_texture(CData *cdata, Texture::TextureType texture_type, cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp); cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp); break; + + case TT_buffer_texture: + nassertv(y_size == 1 && z_size == 1); + break; } if (texture_type != TT_2d_texture) { @@ -5199,7 +5213,8 @@ do_set_x_size(CData *cdata, int x_size) { void Texture:: do_set_y_size(CData *cdata, int y_size) { if (cdata->_y_size != y_size) { - nassertv(cdata->_texture_type != Texture::TT_1d_texture || y_size == 1); + nassertv((cdata->_texture_type != Texture::TT_buffer_texture && + cdata->_texture_type != Texture::TT_1d_texture) || y_size == 1); cdata->_y_size = y_size; cdata->inc_image_modified(); do_clear_ram_image(cdata); @@ -7897,6 +7912,10 @@ do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) { me.add_uint8(cdata->_format); me.add_uint8(cdata->_num_components); + if (cdata->_texture_type == TT_buffer_texture) { + me.add_uint8(cdata->_usage_hint); + } + me.add_uint8(cdata->_auto_texture_scale); me.add_uint32(cdata->_orig_file_x_size); me.add_uint32(cdata->_orig_file_y_size); @@ -8063,6 +8082,7 @@ make_this_from_bam(const FactoryParams ¶ms) { options.set_auto_texture_scale(auto_texture_scale); switch (texture_type) { + case TT_buffer_texture: case TT_1d_texture: case TT_2d_texture: if (alpha_filename.empty()) { @@ -8124,6 +8144,10 @@ do_fillin_body(CData *cdata, DatagramIterator &scan, BamReader *manager) { cdata->_format = (Format)scan.get_uint8(); cdata->_num_components = scan.get_uint8(); + if (cdata->_texture_type == TT_buffer_texture) { + cdata->_usage_hint = (GeomEnums::UsageHint)scan.get_uint8(); + } + cdata->inc_properties_modified(); cdata->_auto_texture_scale = ATS_unspecified; @@ -8304,6 +8328,9 @@ CData() { // check in do_set_format depending on an uninitialized value. _format = F_rgba; + // Only used for buffer textures. + _usage_hint = GeomEnums::UH_unspecified; + _pad_x_size = 0; _pad_y_size = 0; _pad_z_size = 0; diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 1320935860..f19b1ef8fa 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -42,6 +42,7 @@ #include "samplerState.h" #include "pnmImage.h" #include "colorSpace.h" +#include "geomEnums.h" class PNMImage; class PfmFile; @@ -82,6 +83,7 @@ PUBLISHED: TT_3d_texture, TT_2d_texture_array, TT_cube_map, + TT_buffer_texture, }; enum ComponentType { @@ -240,6 +242,8 @@ PUBLISHED: 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); + INLINE void setup_buffer_texture(int size, ComponentType component_type, + Format format, GeomEnums::UsageHint usage); void generate_normalization_cube_map(int size); void generate_alpha_scale_map(); @@ -304,6 +308,7 @@ PUBLISHED: INLINE TextureType get_texture_type() const; INLINE Format get_format() const; INLINE ComponentType get_component_type() const; + INLINE GeomEnums::UsageHint get_usage_hint() const; INLINE void set_wrap_u(WrapMode wrap); INLINE void set_wrap_v(WrapMode wrap); @@ -829,6 +834,7 @@ protected: TextureType _texture_type; Format _format; ComponentType _component_type; + GeomEnums::UsageHint _usage_hint; bool _loaded_from_image; bool _loaded_from_txo;