From e921a111b59f0e4ed4d03d9dd5db091a960b625a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Jan 2014 18:18:35 +0100 Subject: [PATCH] Moved global data from Buffer class to per-context state. --- src/Magnum/Buffer.cpp | 96 ++++++++++++----------- src/Magnum/Buffer.h | 75 ++++-------------- src/Magnum/Context.cpp | 1 - src/Magnum/Implementation/BufferState.cpp | 61 ++++++++++++++ src/Magnum/Implementation/BufferState.h | 25 ++++-- src/Magnum/Implementation/State.cpp | 2 +- 6 files changed, 148 insertions(+), 112 deletions(-) diff --git a/src/Magnum/Buffer.cpp b/src/Magnum/Buffer.cpp index ff66c4209..9dd2a23b9 100644 --- a/src/Magnum/Buffer.cpp +++ b/src/Magnum/Buffer.cpp @@ -36,49 +36,6 @@ namespace Magnum { -#ifndef MAGNUM_TARGET_GLES2 -Buffer::CopyImplementation Buffer::copyImplementation = &Buffer::copyImplementationDefault; -#endif -Buffer::GetParameterImplementation Buffer::getParameterImplementation = &Buffer::getParameterImplementationDefault; -#ifndef MAGNUM_TARGET_GLES -Buffer::GetSubDataImplementation Buffer::getSubDataImplementation = &Buffer::getSubDataImplementationDefault; -#endif -Buffer::DataImplementation Buffer::dataImplementation = &Buffer::dataImplementationDefault; -Buffer::SubDataImplementation Buffer::subDataImplementation = &Buffer::subDataImplementationDefault; -Buffer::InvalidateImplementation Buffer::invalidateImplementation = &Buffer::invalidateImplementationNoOp; -Buffer::InvalidateSubImplementation Buffer::invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp; -Buffer::MapImplementation Buffer::mapImplementation = &Buffer::mapImplementationDefault; -Buffer::MapRangeImplementation Buffer::mapRangeImplementation = &Buffer::mapRangeImplementationDefault; -Buffer::FlushMappedRangeImplementation Buffer::flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDefault; -Buffer::UnmapImplementation Buffer::unmapImplementation = &Buffer::unmapImplementationDefault; - -void Buffer::initializeContextBasedFunctionality(Context& context) { - #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { - Debug() << "Buffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; - - copyImplementation = &Buffer::copyImplementationDSA; - getParameterImplementation = &Buffer::getParameterImplementationDSA; - getSubDataImplementation = &Buffer::getSubDataImplementationDSA; - dataImplementation = &Buffer::dataImplementationDSA; - subDataImplementation = &Buffer::subDataImplementationDSA; - mapImplementation = &Buffer::mapImplementationDSA; - mapRangeImplementation = &Buffer::mapRangeImplementationDSA; - flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSA; - unmapImplementation = &Buffer::unmapImplementationDSA; - } - - if(context.isExtensionSupported()) { - Debug() << "Buffer: using" << Extensions::GL::ARB::invalidate_subdata::string() << "features"; - - invalidateImplementation = &Buffer::invalidateImplementationARB; - invalidateSubImplementation = &Buffer::invalidateSubImplementationARB; - } - #else - static_cast(context); - #endif -} - #ifndef MAGNUM_TARGET_GLES Int Buffer::minMapAlignment() { if(!Context::current()->isExtensionSupported()) @@ -145,6 +102,12 @@ Int Buffer::maxUniformBindings() { } #endif +#ifndef MAGNUM_TARGET_GLES2 +void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) { + Context::current()->state().buffer->copyImplementation(read, write, readOffset, writeOffset, size); +} +#endif + Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint) #ifdef CORRADE_TARGET_NACL , _mappedBuffer(nullptr) @@ -218,10 +181,36 @@ Int Buffer::size() { * couldn't find any matching extension, though) */ GLint size; - (this->*getParameterImplementation)(GL_BUFFER_SIZE, &size); + (this->*Context::current()->state().buffer->getParameterImplementation)(GL_BUFFER_SIZE, &size); return size; } +Buffer& Buffer::setData(const Containers::ArrayReference data, const BufferUsage usage) { + (this->*Context::current()->state().buffer->dataImplementation)(data.size(), data, usage); + return *this; +} + +Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayReference data) { + (this->*Context::current()->state().buffer->subDataImplementation)(offset, data.size(), data); + return *this; +} + +#ifndef MAGNUM_TARGET_GLES +Buffer& Buffer::invalidateData() { + (this->*Context::current()->state().buffer->invalidateImplementation)(); + return *this; +} + +Buffer& Buffer::invalidateSubData(const GLintptr offset, const GLsizeiptr length) { + (this->*Context::current()->state().buffer->invalidateSubImplementation)(offset, length); + return *this; +} +#endif + +void* Buffer::map(const MapAccess access) { + return (this->*Context::current()->state().buffer->mapImplementation)(access); +} + #ifdef MAGNUM_TARGET_GLES2 void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAccess access) { /** @todo Enable also in Emscripten (?) when extension loader is available */ @@ -235,7 +224,20 @@ void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAc static_cast(access); #endif } +#endif + +void* Buffer::map(const GLintptr offset, const GLsizeiptr length, const MapFlags flags) { + return (this->*Context::current()->state().buffer->mapRangeImplementation)(offset, length, flags); +} + +Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length) { + (this->*Context::current()->state().buffer->flushMappedRangeImplementation)(offset, length); + return *this; +} + +bool Buffer::unmap() { return (this->*Context::current()->state().buffer->unmapImplementation)(); } +#ifdef MAGNUM_TARGET_GLES2 void Buffer::unmapSub() { /** @todo Enable also in Emscripten (?) when extension loader is available */ #ifdef CORRADE_TARGET_NACL @@ -248,6 +250,12 @@ void Buffer::unmapSub() { } #endif +#ifndef MAGNUM_TARGET_GLES +void Buffer::subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data) { + (this->*Context::current()->state().buffer->getSubDataImplementation)(offset, size, data); +} +#endif + #ifndef MAGNUM_TARGET_GLES2 void Buffer::copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { glCopyBufferSubData(GLenum(read.bindInternal(Target::CopyRead)), GLenum(write.bindInternal(Target::CopyWrite)), readOffset, writeOffset, size); diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index cd15ca04b..c64f03ad3 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -114,6 +114,8 @@ enum class BufferUsage: GLenum { #endif }; +namespace Implementation { class BufferState; } + /** @brief %Buffer @@ -190,7 +192,7 @@ nothing. @todo BindBufferRange/BindBufferOffset/BindBufferBase for transform feedback (3.0, @extension{EXT,transform_feedback}) */ class MAGNUM_EXPORT Buffer: public AbstractObject { - friend class Context; + friend class Implementation::BufferState; public: /** @@ -512,9 +514,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @requires_gl31 %Extension @extension{ARB,copy_buffer} * @requires_gles30 %Buffer copying is not available in OpenGL ES 2.0. */ - static void copy(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { - copyImplementation(read, write, readOffset, writeOffset, size); - } + static void copy(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); #endif /** @@ -669,10 +669,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferData} * or @fn_gl_extension{NamedBufferData,EXT,direct_state_access} */ - Buffer& setData(Containers::ArrayReference data, BufferUsage usage) { - (this->*dataImplementation)(data.size(), data, usage); - return *this; - } + Buffer& setData(Containers::ArrayReference data, BufferUsage usage); #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -709,10 +706,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferSubData} * or @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access} */ - Buffer& setSubData(GLintptr offset, Containers::ArrayReference data) { - (this->*subDataImplementation)(offset, data.size(), data); - return *this; - } + Buffer& setSubData(GLintptr offset, Containers::ArrayReference data); #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -746,10 +740,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * (part of OpenGL 4.3) is not available, this function does nothing. * @see @ref MapFlag::InvalidateBuffer, @fn_gl{InvalidateBufferData} */ - Buffer& invalidateData() { - (this->*invalidateImplementation)(); - return *this; - } + Buffer& invalidateData(); /** * @brief Invalidate buffer subdata @@ -761,10 +752,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * (part of OpenGL 4.3) is not available, this function does nothing. * @see @ref MapFlag::InvalidateRange, @fn_gl{InvalidateBufferData} */ - Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length) { - (this->*invalidateSubImplementation)(offset, length); - return *this; - } + Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length); #endif /** @@ -784,9 +772,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * in OpenGL ES 3.0 instead. */ - void* map(MapAccess access) { - return (this->*mapImplementation)(access); - } + void* map(MapAccess access); #if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT) /** @@ -827,9 +813,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @requires_gl30 %Extension @extension{ARB,map_buffer_range} * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} */ - void* map(GLintptr offset, GLsizeiptr length, MapFlags flags) { - return (this->*mapRangeImplementation)(offset, length, flags); - } + void* map(GLintptr offset, GLsizeiptr length, MapFlags flags); /** * @brief Flush mapped range @@ -849,10 +833,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @requires_gl30 %Extension @extension{ARB,map_buffer_range} * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} */ - Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length) { - (this->*flushMappedRangeImplementation)(offset, length); - return *this; - } + Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length); /** * @brief Unmap buffer @@ -868,9 +849,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @fn_gl_extension{UnmapNamedBuffer,EXT,direct_state_access} * @requires_gles30 %Extension @es_extension{OES,mapbuffer} */ - bool unmap() { - return (this->*unmapImplementation)(); - } + bool unmap(); #if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT) /** @@ -888,89 +867,69 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { #endif private: - static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context); - static void bind(Target hint, GLuint id); Target MAGNUM_LOCAL bindInternal(Target hint); #ifndef MAGNUM_TARGET_GLES2 - typedef void(*CopyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr); static void MAGNUM_LOCAL copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); #ifndef MAGNUM_TARGET_GLES static void MAGNUM_LOCAL copyImplementationDSA(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); #endif - static CopyImplementation copyImplementation; #endif - typedef void(Buffer::*GetParameterImplementation)(GLenum, GLint*); + #ifndef MAGNUM_TARGET_GLES + void subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data); + #endif + void MAGNUM_LOCAL getParameterImplementationDefault(GLenum value, GLint* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL getParameterImplementationDSA(GLenum value, GLint* data); #endif - static MAGNUM_LOCAL GetParameterImplementation getParameterImplementation; #ifndef MAGNUM_TARGET_GLES - typedef void(Buffer::*GetSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*); void MAGNUM_LOCAL getSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, GLvoid* data); void MAGNUM_LOCAL getSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, GLvoid* data); - static GetSubDataImplementation getSubDataImplementation; #endif - typedef void(Buffer::*DataImplementation)(GLsizeiptr, const GLvoid*, BufferUsage); void MAGNUM_LOCAL dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL dataImplementationDSA(GLsizeiptr size, const GLvoid* data, BufferUsage usage); #endif - static DataImplementation dataImplementation; - typedef void(Buffer::*SubDataImplementation)(GLintptr, GLsizeiptr, const GLvoid*); void MAGNUM_LOCAL subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL subDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data); #endif - static SubDataImplementation subDataImplementation; - typedef void(Buffer::*InvalidateImplementation)(); void MAGNUM_LOCAL invalidateImplementationNoOp(); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL invalidateImplementationARB(); #endif - static InvalidateImplementation invalidateImplementation; - typedef void(Buffer::*InvalidateSubImplementation)(GLintptr, GLsizeiptr); void MAGNUM_LOCAL invalidateSubImplementationNoOp(GLintptr offset, GLsizeiptr length); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length); #endif - static InvalidateSubImplementation invalidateSubImplementation; - typedef void*(Buffer::*MapImplementation)(MapAccess); void MAGNUM_LOCAL * mapImplementationDefault(MapAccess access); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL * mapImplementationDSA(MapAccess access); #endif - static MapImplementation mapImplementation; - typedef void*(Buffer::*MapRangeImplementation)(GLintptr, GLsizeiptr, MapFlags); void MAGNUM_LOCAL * mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL * mapRangeImplementationDSA(GLintptr offset, GLsizeiptr length, MapFlags access); #endif - static MapRangeImplementation mapRangeImplementation; - typedef void(Buffer::*FlushMappedRangeImplementation)(GLintptr, GLsizeiptr); void MAGNUM_LOCAL flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL flushMappedRangeImplementationDSA(GLintptr offset, GLsizeiptr length); #endif - static FlushMappedRangeImplementation flushMappedRangeImplementation; - typedef bool(Buffer::*UnmapImplementation)(); bool MAGNUM_LOCAL unmapImplementationDefault(); #ifndef MAGNUM_TARGET_GLES bool MAGNUM_LOCAL unmapImplementationDSA(); #endif - static UnmapImplementation unmapImplementation; GLuint _id; Target _targetHint; @@ -1003,7 +962,7 @@ template Containers::Array inline Buffer::data() { template Containers::Array inline Buffer::subData(const GLintptr offset, const GLsizeiptr size) { Containers::Array data(size); - if(size) (this->*getSubDataImplementation)(offset, size*sizeof(T), data); + if(size) subDataInternal(offset, size*sizeof(T), data); return std::move(data); } #endif diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 35df57aad..6297babc2 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -448,7 +448,6 @@ Context::Context() { _state = new Implementation::State(*this); /* Initialize functionality based on current OpenGL version and extensions */ - Buffer::initializeContextBasedFunctionality(*this); DefaultFramebuffer::initializeContextBasedFunctionality(*this); Mesh::initializeContextBasedFunctionality(*this); Renderer::initializeContextBasedFunctionality(*this); diff --git a/src/Magnum/Implementation/BufferState.cpp b/src/Magnum/Implementation/BufferState.cpp index 2c6fda44b..6be8f2945 100644 --- a/src/Magnum/Implementation/BufferState.cpp +++ b/src/Magnum/Implementation/BufferState.cpp @@ -27,6 +27,9 @@ #include +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + namespace Magnum { namespace Implementation { const Buffer::Target BufferState::targetForIndex[] = { @@ -75,4 +78,62 @@ std::size_t BufferState::indexForTarget(Buffer::Target target) { CORRADE_ASSERT_UNREACHABLE(); } +BufferState::BufferState(Context& context, std::vector& extensions): bindings() + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + , minMapAlignment(0), maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0) + #endif + , maxUniformBindings(0) + #endif +{ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); + + copyImplementation = &Buffer::copyImplementationDSA; + getParameterImplementation = &Buffer::getParameterImplementationDSA; + getSubDataImplementation = &Buffer::getSubDataImplementationDSA; + dataImplementation = &Buffer::dataImplementationDSA; + subDataImplementation = &Buffer::subDataImplementationDSA; + mapImplementation = &Buffer::mapImplementationDSA; + mapRangeImplementation = &Buffer::mapRangeImplementationDSA; + flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSA; + unmapImplementation = &Buffer::unmapImplementationDSA; + } else + #endif + { + #ifndef MAGNUM_TARGET_GLES2 + copyImplementation = &Buffer::copyImplementationDefault; + #endif + getParameterImplementation = &Buffer::getParameterImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + getSubDataImplementation = &Buffer::getSubDataImplementationDefault; + #endif + dataImplementation = &Buffer::dataImplementationDefault; + subDataImplementation = &Buffer::subDataImplementationDefault; + mapImplementation = &Buffer::mapImplementationDefault; + mapRangeImplementation = &Buffer::mapRangeImplementationDefault; + flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDefault; + unmapImplementation = &Buffer::unmapImplementationDefault; + } + + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string()); + + invalidateImplementation = &Buffer::invalidateImplementationARB; + invalidateSubImplementation = &Buffer::invalidateSubImplementationARB; + } else + #endif + { + invalidateImplementation = &Buffer::invalidateImplementationNoOp; + invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp; + } + + #ifdef MAGNUM_TARGET_GLES + static_cast(context); + static_cast(extensions); + #endif +} + }} diff --git a/src/Magnum/Implementation/BufferState.h b/src/Magnum/Implementation/BufferState.h index e45b5998e..4e16abb18 100644 --- a/src/Magnum/Implementation/BufferState.h +++ b/src/Magnum/Implementation/BufferState.h @@ -44,14 +44,23 @@ struct BufferState { static std::size_t indexForTarget(Buffer::Target target); static const Buffer::Target targetForIndex[TargetCount-1]; - constexpr BufferState(): bindings() - #ifndef MAGNUM_TARGET_GLES2 - #ifndef MAGNUM_TARGET_GLES - , minMapAlignment(0), maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0) - #endif - , maxUniformBindings(0) - #endif - {} + explicit BufferState(Context& context, std::vector& extensions); + + #ifndef MAGNUM_TARGET_GLES2 + void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr); + #endif + void(Buffer::*getParameterImplementation)(GLenum, GLint*); + #ifndef MAGNUM_TARGET_GLES2 + void(Buffer::*getSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*); + #endif + void(Buffer::*dataImplementation)(GLsizeiptr, const GLvoid*, BufferUsage); + void(Buffer::*subDataImplementation)(GLintptr, GLsizeiptr, const GLvoid*); + void(Buffer::*invalidateImplementation)(); + void(Buffer::*invalidateSubImplementation)(GLintptr, GLsizeiptr); + void*(Buffer::*mapImplementation)(Buffer::MapAccess); + void*(Buffer::*mapRangeImplementation)(GLintptr, GLsizeiptr, Buffer::MapFlags); + void(Buffer::*flushMappedRangeImplementation)(GLintptr, GLsizeiptr); + bool(Buffer::*unmapImplementation)(); /* Currently bound buffer for all targets */ GLuint bindings[TargetCount]; diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index f35b860a8..5daebb85e 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -51,7 +51,7 @@ State::State(Context& context) { extensions.reserve(8); #endif - buffer = new BufferState; + buffer = new BufferState(context, extensions); debug = new DebugState(context, extensions); framebuffer = new FramebufferState(context, extensions); mesh = new MeshState;