]> git.tdb.fi Git - libs/gl.git/commitdiff
Remove the separate allocation step from textures and buffers
authorMikko Rasa <tdb@tdb.fi>
Sat, 18 Sep 2021 09:56:18 +0000 (12:56 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 18 Sep 2021 13:20:18 +0000 (16:20 +0300)
It was conceived as a way to avoid unnecessary OpenGL calls if the object
is initialized by uploading full contents.  However the storage extensions
are almost universally supported now and data uploads are not something
that usually happens every frame, so this optimization is no longer
relevant.

source/core/buffer.cpp
source/core/buffer.h
source/core/framebuffer.cpp
source/core/texture1d.cpp
source/core/texture1d.h
source/core/texture2d.cpp
source/core/texture2d.h
source/core/texture3d.cpp
source/core/texture3d.h
source/core/texturecube.cpp
source/core/texturecube.h

index 71ab6e2387a4d451e3a70c8d76a828cd6a598176..dcb83a7a5960f1cb48436cb9cff5063327c4d5f2 100644 (file)
@@ -17,8 +17,7 @@ namespace GL {
 Buffer *Buffer::scratch_binding = 0;
 
 Buffer::Buffer():
-       size(0),
-       allocated(false)
+       size(0)
 {
        static Require _req(ARB_vertex_buffer_object);
 
@@ -47,14 +46,6 @@ void Buffer::storage(unsigned sz)
                throw invalid_argument("Buffer::storage");
 
        size = sz;
-}
-
-void Buffer::allocate()
-{
-       if(size==0)
-               throw invalid_operation("Buffer::allocate");
-       if(allocated)
-               return;
 
        if(ARB_buffer_storage)
        {
@@ -66,30 +57,19 @@ void Buffer::allocate()
                        bind_scratch();
                        glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
                }
-
-               allocated = true;
        }
-       else
-               data(0);
-}
-
-void Buffer::data(const void *d)
-{
-       if(size==0)
-               throw invalid_operation("Buffer::data");
-
-       if(ARB_buffer_storage)
-               return sub_data(0, size, d);
-
-       if(ARB_direct_state_access)
-               glNamedBufferData(id, size, d, GL_STATIC_DRAW);
+       else if(ARB_direct_state_access)
+               glNamedBufferData(id, size, 0, GL_STATIC_DRAW);
        else
        {
                bind_scratch();
-               glBufferData(GL_ARRAY_BUFFER, size, d, GL_STATIC_DRAW);
+               glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
        }
+}
 
-       allocated = true;
+void Buffer::data(const void *d)
+{
+       return sub_data(0, size, d);
 }
 
 void Buffer::sub_data(unsigned off, unsigned sz, const void *d)
@@ -97,8 +77,6 @@ void Buffer::sub_data(unsigned off, unsigned sz, const void *d)
        if(size==0)
                throw invalid_operation("Buffer::sub_data");
 
-       allocate();
-
        if(ARB_direct_state_access)
                glNamedBufferSubData(id, off, sz, d);
        else
@@ -118,7 +96,6 @@ void *Buffer::map()
 {
        static Require _req(ARB_map_buffer_range);
 
-       allocate();
        if(ARB_direct_state_access)
                return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
        else
index 0d656131dd331b75ec3af57ff81581c9e2b2a3a5..9144afaed3d1682f28efd8076988c8e815a977db 100644 (file)
@@ -28,7 +28,6 @@ class Buffer
 private:
        unsigned id;
        unsigned size;
-       bool allocated;
 
        static Buffer *scratch_binding;
 
@@ -43,10 +42,6 @@ public:
        be uploaded.  Storage cannot be changed once set. */
        void storage(unsigned);
 
-       /** Allocates storage for the buffer.  The contents are initially undefined.
-       If storage has already been allocated, does nothing. */
-       void allocate();
-
        /** Uploads data into the buffer, completely replacing any previous
        contents.  Storage must be defined beforehand.  The data must have size
        matching the defined storage. */
index 851b6431b2fb134d470b1116262411af471532be..d6fa973960fbe169f0aa31e482fbb2029b084166 100644 (file)
@@ -273,7 +273,6 @@ void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, unsigned l
 
 void Framebuffer::attach(FrameAttachment attch, Texture2D &tex, unsigned level)
 {
-       tex.allocate(level);
        set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, 0, 0);
 }
 
@@ -284,27 +283,23 @@ void Framebuffer::attach(FrameAttachment attch, Texture2DMultisample &tex)
 
 void Framebuffer::attach(FrameAttachment attch, Texture3D &tex, unsigned layer, unsigned level)
 {
-       tex.allocate(level);
        set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, layer, 0);
 }
 
 void Framebuffer::attach(FrameAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level)
 {
-       tex.allocate(level);
        set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, TextureCube::get_face_index(face), 0);
 }
 
 void Framebuffer::attach_layered(FrameAttachment attch, Texture3D &tex, unsigned level)
 {
        static Require _req(ARB_geometry_shader4);
-       tex.allocate(level);
        set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0);
 }
 
 void Framebuffer::attach_layered(FrameAttachment attch, TextureCube &tex, unsigned level)
 {
        static Require _req(ARB_geometry_shader4);
-       tex.allocate(level);
        set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0);
 }
 
index 7c3f02ab5f97988af099937eb6ed52254542b332..3fd1ae0955e88c1d432219506fe960db9e4ecdd2 100644 (file)
@@ -11,8 +11,7 @@ namespace GL {
 
 Texture1D::Texture1D():
        Texture(GL_TEXTURE_1D),
-       width(0),
-       allocated(0)
+       width(0)
 {
        static Require _req(MSP_texture1D);
 }
@@ -33,58 +32,34 @@ void Texture1D::storage(PixelFormat fmt, unsigned wd, unsigned lv)
        levels = get_n_levels();
        if(lv)
                levels = min(levels, lv);
-}
-
-void Texture1D::allocate(unsigned level)
-{
-       if(width==0)
-               throw invalid_operation("Texture1D::allocate");
-       if(level>=levels)
-               throw invalid_argument("Texture1D::allocate");
-       if(allocated&(1<<level))
-               return;
 
+       GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
        if(ARB_texture_storage)
        {
-               GLenum fmt = get_gl_pixelformat(storage_fmt);
                if(ARB_direct_state_access)
-                       glTextureStorage1D(id, levels, fmt, width);
+                       glTextureStorage1D(id, levels, gl_fmt, width);
                else
                {
                        bind_scratch();
-                       glTexStorage1D(target, levels, fmt, width);
+                       glTexStorage1D(target, levels, gl_fmt, width);
                }
-               apply_swizzle();
-               allocated |= (1<<levels)-1;
        }
        else
-               image(level, 0);
-}
-
-void Texture1D::image(unsigned level, const void *data)
-{
-       if(width==0)
-               throw invalid_operation("Texture1D::image");
-       if(level>=levels)
-               throw out_of_range("Texture1D::image");
-
-       if(ARB_texture_storage)
-               return sub_image(level, 0, get_level_size(level), data);
-
-       bind_scratch();
-
-       if(!allocated)
        {
+               bind_scratch();
                glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
-               apply_swizzle();
+               GLenum comp = get_gl_components(get_components(storage_fmt));
+               GLenum type = get_gl_type(get_component_type(storage_fmt));
+               for(unsigned i=0; i<levels; ++i)
+                       glTexImage1D(target, i, gl_fmt, get_level_size(i), 0, comp, type, 0);
        }
 
-       GLenum fmt = get_gl_pixelformat(storage_fmt);
-       GLenum comp = get_gl_components(get_components(storage_fmt));
-       GLenum type = get_gl_type(get_component_type(storage_fmt));
-       glTexImage1D(target, level, fmt, get_level_size(level), 0, comp, type, data);
+       apply_swizzle();
+}
 
-       allocated |= 1<<level;
+void Texture1D::image(unsigned level, const void *data)
+{
+       return sub_image(level, 0, get_level_size(level), data);
 }
 
 void Texture1D::sub_image(unsigned level, int x, unsigned wd, const void *data)
@@ -94,8 +69,6 @@ void Texture1D::sub_image(unsigned level, int x, unsigned wd, const void *data)
        if(level>=levels)
                throw out_of_range("Texture1D::sub_image");
 
-       allocate(level);
-
        GLenum comp = get_gl_components(get_components(storage_fmt));
        GLenum type = get_gl_type(get_component_type(storage_fmt));
        if(ARB_direct_state_access)
index d8dbb017bd6882c0a941e770e660b1dd9394be1a..241808c1656aa034a4383a61e07897a658453728 100644 (file)
@@ -25,14 +25,12 @@ public:
 private:
        unsigned width;
        unsigned levels;
-       unsigned allocated;
 
 public:
        Texture1D();
 
        void storage(PixelFormat, unsigned, unsigned = 0);
 
-       void allocate(unsigned);
        void image(unsigned, const void *);
        void sub_image(unsigned, int, unsigned, const void *);
        virtual void image(const Graphics::Image &, unsigned = 0);
index b5b989a81c88a631abdfc2dbe2993196ac5e39c0..31d7016574b17ecdf3200d587f781d940914d21e 100644 (file)
@@ -36,8 +36,7 @@ public:
 Texture2D::Texture2D(ResourceManager *m):
        Texture(GL_TEXTURE_2D, m),
        width(0),
-       height(0),
-       allocated(0)
+       height(0)
 { }
 
 Texture2D::~Texture2D()
@@ -62,60 +61,38 @@ void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv)
        levels = get_n_levels();
        if(lv>0)
                levels = min(levels, lv);
-}
-
-void Texture2D::allocate(unsigned level)
-{
-       if(width==0 || height==0)
-               throw invalid_operation("Texture2D::allocate");
-       if(level>=levels)
-               throw invalid_argument("Texture2D::allocate");
-       if(allocated&(1<<level))
-               return;
 
+       GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
        if(ARB_texture_storage)
        {
-               GLenum fmt = get_gl_pixelformat(storage_fmt);
                if(ARB_direct_state_access)
-                       glTextureStorage2D(id, levels, fmt, width, height);
+                       glTextureStorage2D(id, levels, gl_fmt, width, height);
                else
                {
                        bind_scratch();
-                       glTexStorage2D(target, levels, fmt, width, height);
+                       glTexStorage2D(target, levels, gl_fmt, width, height);
                }
-               apply_swizzle();
-               allocated |= (1<<levels)-1;
        }
        else
-               image(level, 0);
-}
-
-void Texture2D::image(unsigned level, const void *data)
-{
-       if(width==0 || height==0)
-               throw invalid_operation("Texture2D::image");
-       if(level>=levels)
-               throw out_of_range("Texture2D::image");
-
-       LinAl::Vector<unsigned, 2> size = get_level_size(level);
-
-       if(ARB_texture_storage)
-               return sub_image(level, 0, 0, size.x, size.y, data);
-
-       bind_scratch();
-
-       if(!allocated)
        {
+               bind_scratch();
                glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
-               apply_swizzle();
+               GLenum comp = get_gl_components(get_components(storage_fmt));
+               GLenum type = get_gl_type(get_component_type(storage_fmt));
+               for(unsigned i=0; i<levels; ++i)
+               {
+                       LinAl::Vector<unsigned, 2> lv_size = get_level_size(i);
+                       glTexImage2D(target, i, gl_fmt, lv_size.x, lv_size.y, 0, comp, type, 0);
+               }
        }
 
-       GLenum fmt = get_gl_pixelformat(storage_fmt);
-       GLenum comp = get_gl_components(get_components(storage_fmt));
-       GLenum type = get_gl_type(get_component_type(storage_fmt));
-       glTexImage2D(target, level, fmt, size.x, size.y, 0, comp, type, data);
+       apply_swizzle();
+}
 
-       allocated |= 1<<level;
+void Texture2D::image(unsigned level, const void *data)
+{
+       LinAl::Vector<unsigned, 2> size = get_level_size(level);
+       return sub_image(level, 0, 0, size.x, size.y, data);
 }
 
 void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
@@ -125,8 +102,6 @@ void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht
        if(level>=levels)
                throw out_of_range("Texture2D::sub_image");
 
-       allocate(level);
-
        GLenum comp = get_gl_components(get_components(storage_fmt));
        GLenum type = get_gl_type(get_component_type(storage_fmt));
        if(ARB_direct_state_access)
@@ -188,7 +163,6 @@ void Texture2D::unload()
 {
        glDeleteTextures(1, &id);
        id = 0;
-       allocated = 0;
 }
 
 
index b3a5a749bd8fe987b0078b8e5b6cdf47c4d9712b..eba553b00c27089e44300424166afee3f8a6b54b 100644 (file)
@@ -36,7 +36,6 @@ private:
        unsigned width;
        unsigned height;
        unsigned levels;
-       unsigned allocated;
 
 public:
        Texture2D(ResourceManager * = 0);
@@ -49,10 +48,6 @@ public:
        it can't be changed. */
        void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv = 0);
 
-       /** Allocates storage for the texture.  The contents are initially
-       undefined.  If storage has already been allocated, does nothing. */
-       void allocate(unsigned level);
-
        /** Updates the contents of the entire texture.  Storage must be defined
        beforehand.  The image data must have dimensions and format matching the
        defined storage. */
index 984ffac7d4ef1a07985b3bf033915bbac3cf5b57..03a64f1cf83abdf8b4de758f8f1c2a44075b74a8 100644 (file)
@@ -16,16 +16,14 @@ Texture3D::Texture3D(GLenum t):
        Texture(t),
        width(0),
        height(0),
-       depth(0),
-       allocated(0)
+       depth(0)
 { }
 
 Texture3D::Texture3D():
        Texture(GL_TEXTURE_3D),
        width(0),
        height(0),
-       depth(0),
-       allocated(0)
+       depth(0)
 {
        static Require _req(EXT_texture3D);
 }
@@ -48,60 +46,38 @@ void Texture3D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned dp,
        levels = get_n_levels();
        if(lv>0)
                levels = min(levels, lv);
-}
-
-void Texture3D::allocate(unsigned level)
-{
-       if(width==0 || height==0 || depth==0)
-               throw invalid_operation("Texture3D::allocate");
-       if(level>=levels)
-               throw invalid_argument("Texture3D::allocate");
-       if(allocated&(1<<level))
-               return;
 
+       GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
        if(ARB_texture_storage)
        {
-               GLenum fmt = get_gl_pixelformat(storage_fmt);
                if(ARB_direct_state_access)
-                       glTextureStorage3D(id, levels, fmt, width, height, depth);
+                       glTextureStorage3D(id, levels, gl_fmt, width, height, depth);
                else
                {
                        bind_scratch();
-                       glTexStorage3D(target, levels, fmt, width, height, depth);
+                       glTexStorage3D(target, levels, gl_fmt, width, height, depth);
                }
-               apply_swizzle();
-               allocated |= (1<<levels)-1;
        }
        else
-               image(level, 0);
-}
-
-void Texture3D::image(unsigned level, const void *data)
-{
-       if(width==0 || height==0 || depth==0)
-               throw invalid_operation("Texture3D::image");
-       if(level>=levels)
-               throw out_of_range("Texture3D::image");
-
-       LinAl::Vector<unsigned, 3> size = get_level_size(level);
-
-       if(ARB_texture_storage)
-               return sub_image(level, 0, 0, 0, size.x, size.y, size.z, data);
-
-       bind_scratch();
-
-       if(!allocated)
        {
+               bind_scratch();
+               GLenum comp = get_gl_components(get_components(storage_fmt));
+               GLenum type = get_gl_type(get_component_type(storage_fmt));
+               for(unsigned i=0; i<levels; ++i)
+               {
+                       LinAl::Vector<unsigned, 3> lv_size = get_level_size(i);
+                       glTexImage3D(target, i, gl_fmt, lv_size.x, lv_size.y, lv_size.z, 0, comp, type, 0);
+               }
                glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
-               apply_swizzle();
        }
 
-       GLenum fmt = get_gl_pixelformat(storage_fmt);
-       GLenum comp = get_gl_components(get_components(storage_fmt));
-       GLenum type = get_gl_type(get_component_type(storage_fmt));
-       glTexImage3D(target, level, fmt, size.x, size.y, size.z, 0, comp, type, data);
+       apply_swizzle();
+}
 
-       allocated |= 1<<level;
+void Texture3D::image(unsigned level, const void *data)
+{
+       LinAl::Vector<unsigned, 3> size = get_level_size(level);
+       return sub_image(level, 0, 0, 0, size.x, size.y, size.z, data);
 }
 
 void Texture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, const void *data)
@@ -111,8 +87,6 @@ void Texture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsi
        if(level>=levels)
                throw out_of_range("Texture3D::sub_image");
 
-       allocate(level);
-
        GLenum comp = get_gl_components(get_components(storage_fmt));
        GLenum type = get_gl_type(get_component_type(storage_fmt));
        if(ARB_direct_state_access)
index 3538f6bba82018b85edd68a69f6686c52e991460..7b88db50d36f6afed388d2cae9dd61685a5204ac 100644 (file)
@@ -33,7 +33,6 @@ protected:
        unsigned height;
        unsigned depth;
        unsigned levels;
-       unsigned allocated;
 
        Texture3D(GLenum);
 public:
@@ -46,10 +45,6 @@ public:
        it can't be changed. */
        void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned dp, unsigned lv = 0);
 
-       /** Allocates storage for the texture.  The contents are initially
-       undefined.  If storage has already been allocated, does nothing. */
-       void allocate(unsigned level);
-
        /** Updates the contents of the entire texture.  Storage must be defined
        beforehand.  The image data must have dimensions and format matching the
        defined storage. */
index 4bbf7e6f5d07da4e1f322775124e1b3eefe9de79..5ee772cab94d742b7939c5373cb36614bca8b4e1 100644 (file)
@@ -45,8 +45,7 @@ unsigned TextureCube::orientations[12] =
 
 TextureCube::TextureCube():
        Texture(GL_TEXTURE_CUBE_MAP),
-       size(0),
-       allocated(0)
+       size(0)
 {
        static Require _req(ARB_texture_cube_map);
        if(ARB_seamless_cube_map)
@@ -69,74 +68,39 @@ void TextureCube::storage(PixelFormat fmt, unsigned sz, unsigned lv)
        levels = get_n_levels();
        if(lv>0)
                levels = min(levels, lv);
-}
-
-void TextureCube::allocate(unsigned level)
-{
-       if(size==0)
-               throw invalid_operation("TextureCube::allocate");
-       if(level>=levels)
-               throw invalid_argument("TextureCube::allocate");
-       if(allocated&(64<<level))
-               return;
 
+       GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
        if(ARB_texture_storage)
        {
-               GLenum fmt = get_gl_pixelformat(storage_fmt);
                if(ARB_direct_state_access)
-                       glTextureStorage2D(id, levels, fmt, size, size);
+                       glTextureStorage2D(id, levels, gl_fmt, size, size);
                else
                {
                        bind_scratch();
-                       glTexStorage2D(target, levels, fmt, size, size);
+                       glTexStorage2D(target, levels, gl_fmt, size, size);
                }
-               apply_swizzle();
-               allocated |= (64<<levels)-1;
        }
        else
        {
-               for(unsigned i=0; i<6; ++i)
-                       image(enumerate_faces(i), level, 0);
+               bind_scratch();
+               GLenum comp = get_gl_components(get_components(storage_fmt));
+               GLenum type = get_gl_type(get_component_type(storage_fmt));
+               for(unsigned i=0; i<levels; ++i)
+               {
+                       unsigned lv_size = get_level_size(i);
+                       for(unsigned j=0; j<6; ++j)
+                               glTexImage2D(enumerate_faces(j), i, gl_fmt, lv_size, lv_size, 0, comp, type, 0);
+               }
+               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
        }
+
+       apply_swizzle();
 }
 
 void TextureCube::image(TextureCubeFace face, unsigned level, const void *data)
 {
-       if(size==0)
-               throw invalid_operation("TextureCube::image");
-       if(level>=levels)
-               throw out_of_range("TextureCube::image");
-
        unsigned lsz = get_level_size(level);
-
-       if(ARB_texture_storage)
-               return sub_image(face, level, 0, 0, lsz, lsz, data);
-
-       if(!allocated)
-       {
-               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
-               apply_swizzle();
-       }
-
-       GLenum fmt = get_gl_pixelformat(storage_fmt);
-       GLenum comp = get_gl_components(get_components(storage_fmt));
-       GLenum type = get_gl_type(get_component_type(storage_fmt));
-       glTexImage2D(face, level, fmt, lsz, lsz, 0, comp, type, data);
-
-       if(level==0)
-       {
-               allocated |= 1<<get_face_index(face);
-               if((allocated&63)==63)
-                       allocated |= 64;
-       }
-       else if(!(allocated&(64<<level)))
-       {
-               for(unsigned i=0; i<6; ++i)
-                       if(enumerate_faces(i)!=face)
-                               glTexImage2D(enumerate_faces(i), level, fmt, lsz, lsz, 0, comp, type, 0);
-
-               allocated |= 64<<level;
-       }
+       return sub_image(face, level, 0, 0, lsz, lsz, data);
 }
 
 void TextureCube::sub_image(TextureCubeFace face, unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
@@ -146,8 +110,6 @@ void TextureCube::sub_image(TextureCubeFace face, unsigned level, int x, int y,
        if(level>=levels)
                throw out_of_range("TextureCube::sub_image");
 
-       allocate(level);
-
        GLenum comp = get_gl_components(get_components(storage_fmt));
        GLenum type = get_gl_type(get_component_type(storage_fmt));
        if(ARB_direct_state_access)
index 93c14336e31f91d67003b095cdb20b217a144c6f..b68210b05c98230d892e7dcb780a2331095b3124 100644 (file)
@@ -52,9 +52,6 @@ public:
 private:
        unsigned size;
        unsigned levels;
-       /* Lowest six bits track allocation status of faces on the base level.  Bit
-       seven is set if the entire base level is allocated. */
-       unsigned allocated;
 
        static TextureCubeFace face_order[6];
        static Vector3 directions[6];
@@ -70,10 +67,6 @@ public:
        it can't be changed. */
        void storage(PixelFormat fmt, unsigned size, unsigned lv = 0);
 
-       /** Allocates storage for the cube faces.  The contents are initially
-       undefined.  If storage has already been allocated, does nothing. */
-       void allocate(unsigned level);
-
        /** Updates the contents of a face.  Storage must be defined beforehand.
        The image data must have dimensions and format matching the defined
        storage. */