From: Mikko Rasa Date: Thu, 16 Sep 2021 18:52:22 +0000 (+0300) Subject: Use a scratch binding to modify textures and buffers X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=7b569bbfcfb65d8d88b47ac42ee1df6a7d27e784 Use a scratch binding to modify textures and buffers This simplifies the code quite a bit. It's assumed that textures are not modified during rendering, as that would potentially interfere with the rendering pipeline state. --- diff --git a/source/core/buffer.cpp b/source/core/buffer.cpp index ecf7b49a..78e85af0 100644 --- a/source/core/buffer.cpp +++ b/source/core/buffer.cpp @@ -15,6 +15,8 @@ using namespace std; namespace Msp { namespace GL { +Buffer *Buffer::scratch_binding = 0; + Buffer::Buffer(): size(0), allocated(false) @@ -29,6 +31,8 @@ Buffer::Buffer(): Buffer::~Buffer() { + if(this==scratch_binding) + unbind_scratch(); glDeleteBuffers(1, &id); } @@ -60,9 +64,8 @@ void Buffer::allocate() glNamedBufferStorage(id, size, 0, flags); else { - glBindBuffer(GL_ARRAY_BUFFER, id); + bind_scratch(); glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags); - glBindBuffer(GL_ARRAY_BUFFER, 0); } allocated = true; @@ -87,9 +90,8 @@ void Buffer::data(const void *d) glNamedBufferData(id, size, d, STATIC_DRAW); else { - glBindBuffer(GL_ARRAY_BUFFER, id); + bind_scratch(); glBufferData(GL_ARRAY_BUFFER, size, d, STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); } allocated = true; @@ -116,9 +118,8 @@ void Buffer::sub_data(unsigned off, unsigned sz, const void *d) glNamedBufferSubData(id, off, sz, d); else { - glBindBuffer(GL_ARRAY_BUFFER, id); + bind_scratch(); glBufferSubData(GL_ARRAY_BUFFER, off, sz, d); - glBindBuffer(GL_ARRAY_BUFFER, 0); } } @@ -137,9 +138,8 @@ void *Buffer::map() return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT); else { - glBindBuffer(GL_ARRAY_BUFFER, id); + bind_scratch(); void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT); - glBindBuffer(GL_ARRAY_BUFFER, 0); return result; } } @@ -151,9 +151,8 @@ bool Buffer::unmap() return glUnmapNamedBuffer(id); else if(OES_mapbuffer) { - glBindBuffer(GL_ARRAY_BUFFER, id); + bind_scratch(); bool result = glUnmapBuffer(GL_ARRAY_BUFFER); - glBindBuffer(GL_ARRAY_BUFFER, 0); return result; } else @@ -170,5 +169,23 @@ void Buffer::set_debug_name(const string &name) #endif } +void Buffer::bind_scratch() +{ + if(scratch_binding!=this) + { + glBindBuffer(GL_ARRAY_BUFFER, id); + scratch_binding = this; + } +} + +void Buffer::unbind_scratch() +{ + if(scratch_binding) + { + glBindBuffer(GL_ARRAY_BUFFER, 0); + scratch_binding = 0; + } +} + } // namespace GL } // namespace Msp diff --git a/source/core/buffer.h b/source/core/buffer.h index a80e52a6..ca9a5955 100644 --- a/source/core/buffer.h +++ b/source/core/buffer.h @@ -57,6 +57,8 @@ private: unsigned size; bool allocated; + static Buffer *scratch_binding; + public: Buffer(); ~Buffer(); @@ -96,6 +98,11 @@ public: bool unmap(); void set_debug_name(const std::string &); + +private: + void bind_scratch(); +public: + static void unbind_scratch(); }; } // namespace GL diff --git a/source/core/pipelinestate.cpp b/source/core/pipelinestate.cpp index 21cb64f9..318522d6 100644 --- a/source/core/pipelinestate.cpp +++ b/source/core/pipelinestate.cpp @@ -162,6 +162,9 @@ void PipelineState::set_blend(const Blend *b) void PipelineState::apply() const { + if(!last_applied) + Texture::unbind_scratch(); + apply(this==last_applied ? changes : ~0U); } diff --git a/source/core/texture.cpp b/source/core/texture.cpp index 347634d4..b4004670 100644 --- a/source/core/texture.cpp +++ b/source/core/texture.cpp @@ -21,6 +21,8 @@ int Texture::swizzle_orders[] = GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; +Texture *Texture::scratch_binding = 0; + Texture::Texture(GLenum t, ResourceManager *m): id(0), target(t), @@ -45,6 +47,8 @@ Texture::Texture(GLenum t, ResourceManager *m): Texture::~Texture() { + if(this==scratch_binding) + unbind_scratch(); if(id) glDeleteTextures(1, &id); } @@ -139,22 +143,13 @@ void Texture::generate_mipmap() // glGenerateMipmap is defined here static Require _req(EXT_framebuffer_object); - if(!ARB_direct_state_access) - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - } - generate_mipmap_(); - if(!ARB_direct_state_access) - glBindTexture(target, 0); -} - -void Texture::generate_mipmap_() -{ if(ARB_direct_state_access) glGenerateTextureMipmap(id); else + { + bind_scratch(); glGenerateMipmap(target); + } } void Texture::set_auto_generate_mipmap(bool gm) @@ -194,6 +189,28 @@ void Texture::set_debug_name(const string &name) #endif } +void Texture::bind_scratch() +{ + if(!scratch_binding) + glActiveTexture(GL_TEXTURE0); + if(scratch_binding!=this) + { + if(scratch_binding && scratch_binding->target!=target) + glBindTexture(scratch_binding->target, 0); + glBindTexture(target, id); + scratch_binding = this; + } +} + +void Texture::unbind_scratch() +{ + if(scratch_binding) + { + glBindTexture(scratch_binding->target, 0); + scratch_binding = 0; + } +} + Texture::Loader::Loader(Texture &t): DataFile::CollectionObjectLoader(t, 0) diff --git a/source/core/texture.h b/source/core/texture.h index 3057ef36..1631f69f 100644 --- a/source/core/texture.h +++ b/source/core/texture.h @@ -67,6 +67,7 @@ protected: std::string debug_name; static int swizzle_orders[]; + static Texture *scratch_binding; Texture(GLenum, ResourceManager * = 0); Texture(const Texture &); @@ -86,10 +87,7 @@ public: static bool can_generate_mipmap(); void generate_mipmap(); -protected: - void generate_mipmap_(); -public: /** Sets automatic mipmap generation. If enabled, mipmaps are generated when a texture image is uploaded. */ void set_auto_generate_mipmap(bool); @@ -115,6 +113,11 @@ public: virtual UInt64 get_data_size() const { return 0; } void set_debug_name(const std::string &); + +protected: + void bind_scratch(); +public: + static void unbind_scratch(); }; } // namespace GL diff --git a/source/core/texture1d.cpp b/source/core/texture1d.cpp index feff9f98..1dbe36eb 100644 --- a/source/core/texture1d.cpp +++ b/source/core/texture1d.cpp @@ -42,22 +42,6 @@ void Texture1D::allocate(unsigned level) throw invalid_operation("Texture1D::allocate"); if(level>=levels) throw invalid_argument("Texture1D::allocate"); - - bool direct = ARB_texture_storage && ARB_direct_state_access; - if(!direct) - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - } - - allocate_(level); - - if(!direct) - glBindTexture(target, 0); -} - -void Texture1D::allocate_(unsigned level) -{ if(allocated&(1<=levels) throw out_of_range("Texture1D::sub_image"); - bool direct = (ARB_direct_state_access && (ARB_texture_storage || (allocated&(1<=levels) throw invalid_argument("Texture2D::allocate"); - - bool direct = ARB_texture_storage && ARB_direct_state_access; - if(!direct) - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - } - - allocate_(level); - - if(!direct) - glBindTexture(target, 0); -} - -void Texture2D::allocate_(unsigned level) -{ if(allocated&(1<=levels) throw out_of_range("Texture2D::image"); + LinAl::Vector size = get_level_size(level); + if(ARB_texture_storage) - { - LinAl::Vector size = get_level_size(level); return sub_image(level, 0, 0, size.x, size.y, data); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - - image_(level, data); - - if(auto_gen_mipmap && level==0) - { - generate_mipmap_(); - allocated |= (1< size = get_level_size(level); 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); allocated |= 1<=levels) throw out_of_range("Texture2D::sub_image"); - bool direct = (ARB_direct_state_access && (ARB_texture_storage || (allocated&(1<=levels) throw invalid_argument("Texture3D::allocate"); - - bool direct = ARB_texture_storage && ARB_direct_state_access; - if(!direct) - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - } - - allocate_(level); - - if(!direct) - glBindTexture(target, 0); -} - -void Texture3D::allocate_(unsigned level) -{ if(allocated&(1<=levels) throw out_of_range("Texture3D::image"); + LinAl::Vector size = get_level_size(level); + if(ARB_texture_storage) - { - LinAl::Vector size = get_level_size(level); return sub_image(level, 0, 0, 0, size.x, size.y, size.z, data); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - - image_(level, data); - - if(auto_gen_mipmap && level==0) - { - generate_mipmap_(); - allocated |= (1< size = get_level_size(level); 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); allocated |= 1<=levels) throw out_of_range("Texture3D::sub_image"); - bool direct = (ARB_direct_state_access && (ARB_texture_storage || (allocated&(1<=levels) throw invalid_argument("TextureCube::allocate"); - - bool direct = ARB_texture_storage && ARB_direct_state_access; - if(!direct) - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - } - - allocate_(level); - - if(!direct) - glBindTexture(target, 0); -} - -void TextureCube::allocate_(unsigned level) -{ if(allocated&(64<=levels) throw out_of_range("TextureCube::image"); + unsigned lsz = get_level_size(level); + if(ARB_texture_storage) - { - unsigned lsz = get_level_size(level); return sub_image(face, level, 0, 0, lsz, lsz, data); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, id); - - image_(face, level, data); - if(auto_gen_mipmap && level==0 && (allocated&63)==63) - { - generate_mipmap_(); - allocated |= (64<=levels) throw out_of_range("TextureCube::sub_image"); - bool direct = (ARB_direct_state_access && (ARB_texture_storage || (allocated&(1<get_id()); + } const VertexFormat &fmt = array.get_format(); unsigned stride = fmt.stride();