Browse Source

Implemented indexed buffer binding.

The indexed binding is allowed for only some types (atomic counters,
uniforms, shader storage and transform feedback), thus we need separate
enum for that. Because the bind() function will be used far more often
than setTargetHint(), the original Target enum is now renamed to
TargetHint and the new Target enum contains (in non-deprecated build)
only three values.

For backwards compatibility, though, we need to have all original Target
values, thus the new Target enum contains also all other values from
TargetHint, but they are marked as deprecated and (at least) run-time
checked in bind() so they aren't accidentaly used for indexed binding.
Similarly there are also deprecated Target overloads of Buffer() and
setTargetHint(). It's ugly, but hopefully will suffice for now. This mess
will be removed as soon as possible in some upcoming version.
pull/68/head
Vladimír Vondruš 12 years ago
parent
commit
dc312cda0d
  1. 2
      doc/opengl-mapping.dox
  2. 6
      doc/opengl-support.dox
  3. 2
      src/Magnum/AbstractFramebuffer.cpp
  4. 26
      src/Magnum/AbstractTexture.cpp
  5. 151
      src/Magnum/Buffer.cpp
  6. 341
      src/Magnum/Buffer.h
  7. 4
      src/Magnum/BufferImage.cpp
  8. 4
      src/Magnum/DebugTools/ForceRenderer.cpp
  9. 8
      src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp
  10. 4
      src/Magnum/DebugTools/ObjectRenderer.cpp
  11. 71
      src/Magnum/Implementation/BufferState.cpp
  12. 6
      src/Magnum/Implementation/BufferState.h
  13. 12
      src/Magnum/Mesh.cpp
  14. 8
      src/Magnum/MeshTools/Compile.cpp
  15. 64
      src/Magnum/Test/BufferGLTest.cpp
  16. 20
      src/Magnum/Test/MeshGLTest.cpp
  17. 2
      src/Magnum/Text/Renderer.cpp

2
doc/opengl-mapping.dox

@ -49,7 +49,7 @@ OpenGL function | Matching API
@fn_gl{BeginTransformFeedback}, `glEndTransformFeedback()` | |
@fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation()
@fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere
@fn_gl{BindBufferBase}, \n @fn_gl{BindBuffersBase}, \n @fn_gl{BindBufferRange}, \n @fn_gl{BindBuffersRange} | |
@fn_gl{BindBufferBase}, \n @fn_gl{BindBuffersBase}, \n @fn_gl{BindBufferRange}, \n @fn_gl{BindBuffersRange} | @ref Buffer::bind(), \n @ref Buffer::unbind()
@fn_gl{BindFragDataLocation} | @ref AbstractShaderProgram::bindFragmentDataLocation()
@fn_gl{BindFragDataLocationIndexed} | @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
@fn_gl{BindFramebuffer} | @ref Framebuffer::bind()

6
doc/opengl-support.dox

@ -81,7 +81,7 @@ following:
@extension{ARB,texture_rectangle} | done
@extension{ARB,draw_instanced} | done
@extension{ARB,texture_buffer_object} | done
@extension{ARB,uniform_buffer_object} | |
@extension{ARB,uniform_buffer_object} | missing uniform block binding
@extension{ARB,copy_buffer} | done
@extension{EXT,texture_snorm} | done
@extension{NV,primitive_restart} | |
@ -156,7 +156,7 @@ following:
@extension{ARB,conservative_depth} | done (shading language only)
@extension{ARB,internalformat_query} | |
@extension{ARB,map_buffer_alignment} | done
@extension{ARB,shader_atomic_counters} | |
@extension{ARB,shader_atomic_counters} | done
@extension{ARB,shader_image_load_store} | |
@extension{ARB,shading_language_packing} | done (shading language only)
@extension{ARB,texture_storage} | done
@ -198,7 +198,7 @@ following:
@extension{ARB,buffer_storage} | |
@extension{ARB,clear_texture} | |
@extension{ARB,enhanced_layouts} | done (shading language only)
@extension{ARB,multi_bind} | only texture binding
@extension{ARB,multi_bind} | only texture and buffer binding
@extension{ARB,query_buffer_object} | |
@extension{ARB,texture_mirror_clamp_to_edge} | done
@extension{ARB,texture_stencil8} | done

2
src/Magnum/AbstractFramebuffer.cpp

@ -237,7 +237,7 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Buf
if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::Target::PixelPack);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(Context::current()->state().framebuffer->readImplementation)(offset, size, image.format(), image.type(), image.dataSize(size), nullptr);
}
#endif

26
src/Magnum/AbstractTexture.cpp

@ -1211,7 +1211,7 @@ template<UnsignedInt dimensions> void AbstractTexture::image(GLenum target, GLin
if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::Target::PixelPack);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, nullptr);
}
@ -1279,78 +1279,78 @@ void AbstractTexture::DataHelper<3>::setStorageMultisample(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) {
Buffer::unbindInternal(Buffer::Target::PixelUnpack);
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
}
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) {
image.buffer().bindInternal(Buffer::Target::PixelUnpack);
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
}
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image) {
Buffer::unbindInternal(Buffer::Target::PixelUnpack);
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
}
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) {
image.buffer().bindInternal(Buffer::Target::PixelUnpack);
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference2D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::Target::PixelUnpack);
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
(texture.*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::Target::PixelUnpack);
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector2i& offset, const ImageReference2D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::Target::PixelUnpack);
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
(texture.*Context::current()->state().texture->subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector2i& offset, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::Target::PixelUnpack);
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference3D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::Target::PixelUnpack);
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
(texture.*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) {
image.buffer().bindInternal(Buffer::Target::PixelUnpack);
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector3i& offset, const ImageReference3D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::Target::PixelUnpack);
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
(texture.*Context::current()->state().texture->subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector3i& offset, BufferImage3D& image) {
image.buffer().bindInternal(Buffer::Target::PixelUnpack);
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().texture->subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
}
#endif

151
src/Magnum/Buffer.cpp

@ -127,12 +127,42 @@ Int Buffer::maxUniformBindings() {
return value;
}
void Buffer::unbind(const Target target, const UnsignedInt index) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
glBindBufferBase(GLenum(target), index, 0);
}
void Buffer::unbind(const Target target, const UnsignedInt firstIndex, const std::size_t count) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
Context::current()->state().buffer->bindBasesImplementation(target, firstIndex, {nullptr, count});
}
/** @todoc const std::initializer_list makes Doxygen grumpy */
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
Context::current()->state().buffer->bindRangesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
}
/** @todoc const std::initializer_list makes Doxygen grumpy */
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
Context::current()->state().buffer->bindBasesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
}
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(const Target targetHint): _targetHint{targetHint},
Buffer::Buffer(const TargetHint targetHint): _targetHint{targetHint},
#ifdef CORRADE_TARGET_NACL
_mappedBuffer{nullptr},
#endif
@ -186,7 +216,7 @@ Buffer& Buffer::setLabelInternal(const Containers::ArrayReference<const char> la
return *this;
}
void Buffer::bindInternal(const Target target, Buffer* const buffer) {
void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
const GLuint id = buffer ? buffer->_id : 0;
GLuint& bound = Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(target)];
@ -199,7 +229,7 @@ void Buffer::bindInternal(const Target target, Buffer* const buffer) {
glBindBuffer(GLenum(target), id);
}
Buffer::Target Buffer::bindSomewhereInternal(Target hint) {
auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint {
GLuint* bindings = Context::current()->state().buffer->bindings;
GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)];
@ -218,6 +248,24 @@ Buffer::Target Buffer::bindSomewhereInternal(Target hint) {
return hint;
}
#ifndef MAGNUM_TARGET_GLES2
Buffer& Buffer::bind(const Target target, const UnsignedInt index, const GLintptr offset, const GLsizeiptr size) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
glBindBufferRange(GLenum(target), index, _id, offset, size);
return *this;
}
Buffer& Buffer::bind(const Target target, const UnsignedInt index) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
glBindBufferBase(GLenum(target), index, _id);
return *this;
}
#endif
Int Buffer::size() {
/**
* @todo there is something like glGetBufferParameteri64v in 3.2 (I
@ -296,8 +344,59 @@ void Buffer::subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data) {
#endif
#ifndef MAGNUM_TARGET_GLES2
void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, Containers::ArrayReference<Buffer* const> buffers) {
for(std::size_t i = 0; i != buffers.size(); ++i) {
if(buffers && buffers[i]) buffers[i]->bind(target, firstIndex + i);
else unbind(target, firstIndex + i);
}
}
#ifndef MAGNUM_TARGET_GLES
void Buffer::bindImplementationMulti(const Target target, const GLuint firstIndex, Containers::ArrayReference<Buffer* const> buffers) {
Containers::Array<GLuint> ids{buffers ? buffers.size() : 0};
if(buffers) for(std::size_t i = 0; i != buffers.size(); ++i) {
if(buffers[i]) {
buffers[i]->createIfNotAlready();
ids[i] = buffers[i]->_id;
} else {
ids[i] = 0;
}
}
glBindBuffersBase(GLenum(target), firstIndex, buffers.size(), ids);
}
#endif
void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, const Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
for(std::size_t i = 0; i != buffers.size(); ++i) {
if(buffers && std::get<0>(buffers[i]))
std::get<0>(buffers[i])->bind(target, firstIndex + i, std::get<1>(buffers[i]), std::get<2>(buffers[i]));
else unbind(target, firstIndex + i);
}
}
#ifndef MAGNUM_TARGET_GLES
void Buffer::bindImplementationMulti(const Target target, const GLuint firstIndex, const Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
/** @todo use ArrayTuple */
Containers::Array<GLuint> ids{buffers ? buffers.size() : 0};
Containers::Array<GLintptr> offsetsSizes{buffers ? buffers.size()*2 : 0};
if(buffers) for(std::size_t i = 0; i != buffers.size(); ++i) {
if(std::get<0>(buffers[i])) {
std::get<0>(buffers[i])->createIfNotAlready();
ids[i] = std::get<0>(buffers[i])->_id;
std::tie(std::ignore, offsetsSizes[i], offsetsSizes[buffers.size() + i]) = buffers[i];
} else {
ids[i] = 0;
offsetsSizes[i] = offsetsSizes[buffers.size() + i] = 0;
}
}
glBindBuffersRange(GLenum(target), firstIndex, buffers.size(), ids, offsetsSizes, offsetsSizes + buffers.size());
}
#endif
void Buffer::copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
glCopyBufferSubData(GLenum(read.bindSomewhereInternal(Target::CopyRead)), GLenum(write.bindSomewhereInternal(Target::CopyWrite)), readOffset, writeOffset, size);
glCopyBufferSubData(GLenum(read.bindSomewhereInternal(TargetHint::CopyRead)), GLenum(write.bindSomewhereInternal(TargetHint::CopyWrite)), readOffset, writeOffset, size);
}
#ifndef MAGNUM_TARGET_GLES
@ -445,9 +544,9 @@ bool Buffer::unmapImplementationDSA() {
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, Buffer::Target value) {
Debug operator<<(Debug debug, Buffer::TargetHint value) {
switch(value) {
#define _c(value) case Buffer::Target::value: return debug << "Buffer::Target::" #value;
#define _c(value) case Buffer::TargetHint::value: return debug << "Buffer::TargetHint::" #value;
_c(Array)
#ifndef MAGNUM_TARGET_GLES2
_c(AtomicCounter)
@ -472,8 +571,48 @@ Debug operator<<(Debug debug, Buffer::Target value) {
#undef _c
}
return debug << "Buffer::TargetHint::(invalid)";
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, Buffer::Target value) {
switch(value) {
#ifndef MAGNUM_TARGET_GLES2
#define _c(value) case Buffer::Target::value: return debug << "Buffer::Target::" #value;
_c(AtomicCounter)
_c(ShaderStorage)
_c(Uniform)
#undef _c
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
case Buffer::Target::Array:
#ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::CopyRead:
case Buffer::Target::CopyWrite:
case Buffer::Target::DispatchIndirect:
case Buffer::Target::DrawIndirect:
#endif
case Buffer::Target::ElementArray:
#ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::PixelPack:
case Buffer::Target::PixelUnpack:
#endif
#ifndef MAGNUM_TARGET_GLES
case Buffer::Target::Texture:
#endif
#ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::TransformFeedback:
#endif
return debug << static_cast<Buffer::TargetHint>(value);
#endif
}
return debug << "Buffer::Target::(invalid)";
}
#endif
#endif
}

341
src/Magnum/Buffer.h

@ -215,7 +215,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
*
* @see @ref Buffer(), @ref setTargetHint()
*/
enum class Target: GLenum {
enum class TargetHint: GLenum {
/** Used for storing vertex attributes. */
Array = GL_ARRAY_BUFFER,
@ -316,6 +316,139 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#endif
};
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
/**
* @brief %Buffer binding target
*
* @see @ref bind(), @ref unbind()
*/
enum class Target: GLenum {
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copydoc TargetHint::Array
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::Array "TargetHint::Array"
* instead.
*/
Array = GL_ARRAY_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Atomic counter binding
* @requires_gl42 %Extension @extension{ARB,shader_atomic_counters}
* @requires_gles31 Atomic counters are not available in OpenGL ES
* 3.0 and older
*/
AtomicCounter = GL_ATOMIC_COUNTER_BUFFER,
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::CopyRead
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::CopyRead "TargetHint::CopyRead"
* instead.
*/
CopyRead = GL_COPY_READ_BUFFER,
/**
* @copydoc TargetHint::CopyWrite
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::CopyWrite "TargetHint::CopyWrite"
* instead.
*/
CopyWrite = GL_COPY_WRITE_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::DispatchIndirect
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::DispatchIndirect "TargetHint::DispatchIndirect"
* instead.
*/
DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER,
/**
* @copydoc TargetHint::DrawIndirect
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::DrawIndirect "TargetHint::DrawIndirect"
* instead.
*/
DrawIndirect = GL_DRAW_INDIRECT_BUFFER,
#endif
/**
* @copydoc TargetHint::ElementArray
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::ElementArray "TargetHint::ElementArray"
* instead.
*/
ElementArray = GL_ELEMENT_ARRAY_BUFFER,
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::PixelPack
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::PixelPack "TargetHint::PixelPack"
* instead.
*/
PixelPack = GL_PIXEL_PACK_BUFFER,
/**
* @copydoc TargetHint::PixelUnpack
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::PixelUnpack "TargetHint::PixelUnpack"
* instead.
*/
PixelUnpack = GL_PIXEL_UNPACK_BUFFER,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Shader storage binding
* @requires_gl43 %Extension @extension{ARB,shader_storage_buffer_object}
* @requires_gles31 Shader storage is not available in OpenGL ES
* 3.0 and older
*/
ShaderStorage = GL_SHADER_STORAGE_BUFFER,
#endif
#if defined(MAGNUM_BUILD_DEPRECATED) && !defined(MAGNUM_TARGET_GLES)
/**
* @copydoc TargetHint::Texture
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::Texture "TargetHint::Texture"
* instead.
*/
Texture = GL_TEXTURE_BUFFER,
#endif
#if defined(MAGNUM_BUILD_DEPRECATED) && !defined(MAGNUM_TARGET_GLES2)
/**
* @copydoc TargetHint::TransformFeedback
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::TransformFeedback "TargetHint::TransformFeedback"
* instead.
*/
TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Uniform binding
* @requires_gl31 %Extension @extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES
* 2.0
*/
Uniform = GL_UNIFORM_BUFFER
#endif
};
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief BufferUsage
@ -455,7 +588,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_atomic_counters}
* (part of OpenGL 4.2) nor OpenGL ES 3.1 is available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS}
* @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS}
* @requires_gles30 Not defined in OpenGL ES 2.0
*/
static Int maxAtomicCounterBindings();
@ -466,7 +600,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object}
* (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS}
* @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS}
* @requires_gles30 Not defined in OpenGL ES 2.0
*/
static Int maxShaderStorageBindings();
@ -477,7 +612,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* (part of OpenGL 3.1) is not available, returns `1`.
* @see @fn_gl{Get} with @def_gl{UNIFORM_BUFFER_OFFSET_ALIGNMENT}
* @see @ref bind(), @fn_gl{Get} with @def_gl{UNIFORM_BUFFER_OFFSET_ALIGNMENT}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0
*/
static Int uniformOffsetAlignment();
@ -488,7 +623,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object}
* (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `1`.
* @see @fn_gl{Get} with @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT}
* @see @ref bind(), @fn_gl{Get} with @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT}
* @requires_gles30 Not defined in OpenGL ES 2.0
*/
static Int shaderStorageOffsetAlignment();
@ -499,11 +634,108 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* (part of OpenGL 3.1) is not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_BUFFER_BINDINGS}
* @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_UNIFORM_BUFFER_BINDINGS}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0
*/
static Int maxUniformBindings();
/**
* @brief Unbind any buffer from given indexed target
*
* The @p index parameter must respect limits for given @p target.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void unbind(Target target, UnsignedInt index);
/**
* @brief Unbind given range of indexed targets
*
* Unbinds all buffers in given target in range @f$ [ firstIndex ; firstIndex + count ] @f$.
* The range of indices must respect limits for given @p target. If
* @extension{ARB,multi_bind} (part of OpenGL 4.4) is not available,
* the feature is emulated with sequence of @ref unbind(Target, UnsignedInt)
* calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref unbind(Target, UnsignedInt), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBuffersBase} or @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void unbind(Target target, UnsignedInt firstIndex, std::size_t count);
/**
* @brief Bind ranges of buffers to given range of indexed targets
*
* Binds first buffer in the list to @p firstIndex, second to
* `firstIndex + 1` etc. Second parameter is offset, third is size. If
* any buffer is `nullptr`, given indexed target is unbound. The range
* of indices must respect limits for given @p target. The offsets must
* respect alignment, which is 4 bytes for @ref Target::AtomicCounter
* and implementation-defined for other targets. If @extension{ARB,multi_bind}
* (part of OpenGL 4.4) is not available, the feature is emulated with
* sequence of @ref bind(Target, UnsignedInt, GLintptr, GLsizeiptr) /
* @ref unbind(Target, UnsignedInt) calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, GLintptr, GLsizeiptr),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @ref shaderStorageOffsetAlignment(),
* @ref uniformOffsetAlignment(), @fn_gl{BindBuffersRange} or
* @fn_gl{BindBufferRange}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void bind(Target target, UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
/**
* @brief Bind buffers to given range of indexed targets
*
* Binds first buffer in the list to @p firstIndex, second to
* `firstIndex + 1` etc. If any buffer is `nullptr`, given indexed
* target is unbound. The range of indices must respect limits for
* given @p target. If @extension{ARB,multi_bind} (part of OpenGL 4.4)
* is not available, the feature is emulated with sequence of
* @ref bind(Target, UnsignedInt) / @ref unbind(Target, UnsignedInt)
* calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBuffersBase} or @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void bind(Target target, UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers);
/**
* @brief Copy one buffer to another
* @param read %Buffer from which to read
@ -532,7 +764,14 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* Creates new OpenGL buffer.
* @see @fn_gl{GenBuffers}
*/
explicit Buffer(Target targetHint = Target::Array);
explicit Buffer(TargetHint targetHint = TargetHint::Array);
/**
* @copybrief Buffer(TargetHint)
* @deprecated Use @ref Magnum::Buffer::Buffer(Magnum::Buffer::TargetHint) "Buffer(TargetHint)"
* instead.
*/
CORRADE_DEPRECATED("use Buffer(TargetHint) instead") explicit Buffer(Target targetHint): Buffer{static_cast<TargetHint>(targetHint)} {}
/** @brief Copying is not allowed */
Buffer(const Buffer&) = delete;
@ -591,7 +830,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
}
/** @brief Target hint */
Target targetHint() const { return _targetHint; }
TargetHint targetHint() const { return _targetHint; }
/**
* @brief Set target hint
@ -608,11 +847,65 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* http://www.opengl.org/wiki/Vertex_Specification#Index_buffers
* ... damned GL state
*/
Buffer& setTargetHint(Target hint) {
Buffer& setTargetHint(TargetHint hint) {
_targetHint = hint;
return *this;
}
/**
* @copybrief setTargetHint(TargetHint)
* @deprecated Use @ref Magnum::Buffer::setTargetHint(Magnum::Buffer::TargetHint) "setTargetHint(TargetHint)"
* instead.
*/
CORRADE_DEPRECATED("use setTargetHint(TargetHint) instead") Buffer& setTargetHint(Target hint) {
return setTargetHint(static_cast<TargetHint>(hint));
}
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind buffer range to given binding index
*
* The @p index parameter must respect limits for given @p target. The
* @p offset parameter must respect alignment, which is 4 bytes for
* @ref Target::AtomicCounter and implementation-defined for other
* targets.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>>),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @ref shaderStorageOffsetAlignment(),
* @ref uniformOffsetAlignment(), @fn_gl{BindBufferRange}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @todo State tracking for indexed binding
*/
Buffer& bind(Target target, UnsignedInt index, GLintptr offset, GLsizeiptr size);
/**
* @brief Bind buffer to given binding index
*
* The @p index parameter must respect limits for given @p target.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, std::initializer_list<Buffer*>),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
Buffer& bind(Target target, UnsignedInt index);
#endif
/**
* @brief %Buffer size
*
@ -850,13 +1143,26 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
/* There should be no need to use these from user code */
static void unbindInternal(Target target) { bindInternal(target, nullptr); }
void bindInternal(Target target) { bindInternal(target, this); }
/* There should be no need to use these from user code. Also it's a bit
unfortunate to have the parameter typed as TargetHint while in this
case it is no hint at all, but it allows to have cleaner public
binding API (just with short Target name) */
static void unbindInternal(TargetHint target) { bindInternal(target, nullptr); }
void bindInternal(TargetHint target) { bindInternal(target, this); }
private:
static void bindInternal(Target hint, Buffer* buffer);
Target MAGNUM_LOCAL bindSomewhereInternal(Target hint);
static void bindInternal(TargetHint hint, Buffer* buffer);
TargetHint MAGNUM_LOCAL bindSomewhereInternal(TargetHint hint);
static void MAGNUM_LOCAL bindImplementationFallback(Target target, GLuint first, Containers::ArrayReference<Buffer* const> buffers);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(Target target, GLuint first, Containers::ArrayReference<Buffer* const> buffers);
#endif
static void MAGNUM_LOCAL bindImplementationFallback(Target target, GLuint first, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(Target target, GLuint first, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
#endif
#ifndef MAGNUM_TARGET_GLES2
static void MAGNUM_LOCAL copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
@ -924,7 +1230,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#endif
GLuint _id;
Target _targetHint;
TargetHint _targetHint;
#ifdef CORRADE_TARGET_NACL
void* _mappedBuffer;
#endif
@ -933,8 +1239,13 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags)
/** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::TargetHint} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::TargetHint value);
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
/** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::Target} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::Target value);
#endif
inline Buffer::Buffer(Buffer&& other) noexcept: _id{other._id}, _targetHint{other._targetHint},
#ifdef CORRADE_TARGET_NACL

4
src/Magnum/BufferImage.cpp

@ -28,11 +28,11 @@
namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage): AbstractImage(format, type), _size(size), _buffer(Buffer::Target::PixelPack) {
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage): AbstractImage(format, type), _size(size), _buffer(Buffer::TargetHint::PixelPack) {
_buffer.setData({data, dataSize(size)}, usage);
}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type), _buffer(Buffer::Target::PixelPack) {}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type), _buffer(Buffer::TargetHint::PixelPack) {}
template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(ColorFormat format, ColorType type, const VectorTypeFor<dimensions, Int>& size, const void* data, BufferUsage usage) {
_format = format;

4
src/Magnum/DebugTools/ForceRenderer.cpp

@ -68,8 +68,8 @@ template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(SceneG
if(mesh) return;
/* Create the mesh */
Buffer* vertexBuffer = new Buffer(Buffer::Target::Array);
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
Buffer* vertexBuffer = new Buffer{Buffer::TargetHint::Array};
Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
vertexBuffer->setData(positions, BufferUsage::StaticDraw);
ResourceManager::instance().set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);

8
src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp

@ -46,7 +46,7 @@ template<UnsignedInt dimensions> void create(typename MeshData<dimensions>::Type
template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
/* Vertex buffer */
Buffer* buffer = new Buffer(Buffer::Target::Array);
Buffer* buffer = new Buffer{Buffer::TargetHint::Array};
buffer->setData(data.positions(0), BufferUsage::StaticDraw);
ResourceManager::instance().set(vertexBufferResource.key(), buffer, ResourceDataState::Final, ResourcePolicy::Manual);
@ -65,7 +65,7 @@ template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource,
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices());
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
indexBuffer->setData(indexData, BufferUsage::StaticDraw);
mesh->setCount(data.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
@ -78,7 +78,7 @@ template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource,
template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
/* Vertex buffer */
Buffer* vertexBuffer = new Buffer(Buffer::Target::Array);
Buffer* vertexBuffer = new Buffer{Buffer::TargetHint::Array};
vertexBuffer->setData(data.positions(0), BufferUsage::StaticDraw);
ResourceManager::instance().set(vertexBufferResource.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
@ -97,7 +97,7 @@ template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource,
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices());
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
indexBuffer->setData(indexData, BufferUsage::StaticDraw);
mesh->setCount(data.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);

4
src/Magnum/DebugTools/ObjectRenderer.cpp

@ -156,8 +156,8 @@ template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(Scen
if(mesh) return;
/* Create the mesh */
Buffer* vertexBuffer = new Buffer(Buffer::Target::Array);
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
Buffer* vertexBuffer = new Buffer{Buffer::TargetHint::Array};
Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
Mesh* mesh = new Mesh;
vertexBuffer->setData(MeshTools::interleave(Renderer<dimensions>::positions, Renderer<dimensions>::colors), BufferUsage::StaticDraw);

71
src/Magnum/Implementation/BufferState.cpp

@ -34,43 +34,43 @@
namespace Magnum { namespace Implementation {
const Buffer::Target BufferState::targetForIndex[] = {
Buffer::Target::Array,
Buffer::Target::ElementArray,
const Buffer::TargetHint BufferState::targetForIndex[] = {
Buffer::TargetHint::Array,
Buffer::TargetHint::ElementArray,
#ifndef MAGNUM_TARGET_GLES2
Buffer::Target::CopyRead,
Buffer::Target::CopyWrite,
Buffer::Target::PixelPack,
Buffer::Target::PixelUnpack,
Buffer::Target::TransformFeedback,
Buffer::Target::Uniform,
Buffer::Target::AtomicCounter,
Buffer::Target::DispatchIndirect,
Buffer::Target::DrawIndirect,
Buffer::Target::ShaderStorage,
Buffer::TargetHint::CopyRead,
Buffer::TargetHint::CopyWrite,
Buffer::TargetHint::PixelPack,
Buffer::TargetHint::PixelUnpack,
Buffer::TargetHint::TransformFeedback,
Buffer::TargetHint::Uniform,
Buffer::TargetHint::AtomicCounter,
Buffer::TargetHint::DispatchIndirect,
Buffer::TargetHint::DrawIndirect,
Buffer::TargetHint::ShaderStorage,
#ifndef MAGNUM_TARGET_GLES
Buffer::Target::Texture
Buffer::TargetHint::Texture
#endif
#endif
};
std::size_t BufferState::indexForTarget(Buffer::Target target) {
std::size_t BufferState::indexForTarget(Buffer::TargetHint target) {
switch(target) {
case Buffer::Target::Array: return 1;
case Buffer::Target::ElementArray: return 2;
case Buffer::TargetHint::Array: return 1;
case Buffer::TargetHint::ElementArray: return 2;
#ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::CopyRead: return 3;
case Buffer::Target::CopyWrite: return 4;
case Buffer::Target::PixelPack: return 5;
case Buffer::Target::PixelUnpack: return 6;
case Buffer::Target::TransformFeedback: return 7;
case Buffer::Target::Uniform: return 8;
case Buffer::Target::AtomicCounter: return 9;
case Buffer::Target::DispatchIndirect: return 10;
case Buffer::Target::DrawIndirect: return 11;
case Buffer::Target::ShaderStorage: return 12;
case Buffer::TargetHint::CopyRead: return 3;
case Buffer::TargetHint::CopyWrite: return 4;
case Buffer::TargetHint::PixelPack: return 5;
case Buffer::TargetHint::PixelUnpack: return 6;
case Buffer::TargetHint::TransformFeedback: return 7;
case Buffer::TargetHint::Uniform: return 8;
case Buffer::TargetHint::AtomicCounter: return 9;
case Buffer::TargetHint::DispatchIndirect: return 10;
case Buffer::TargetHint::DrawIndirect: return 11;
case Buffer::TargetHint::ShaderStorage: return 12;
#ifndef MAGNUM_TARGET_GLES
case Buffer::Target::Texture: return 13;
case Buffer::TargetHint::Texture: return 13;
#endif
#endif
}
@ -130,6 +130,21 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp;
}
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
extensions.push_back(Extensions::GL::ARB::multi_bind::string());
bindBasesImplementation = &Buffer::bindImplementationMulti;
bindRangesImplementation = &Buffer::bindImplementationMulti;
} else
#endif
{
bindBasesImplementation = &Buffer::bindImplementationFallback;
bindRangesImplementation = &Buffer::bindImplementationFallback;
}
#endif
#ifdef MAGNUM_TARGET_GLES
static_cast<void>(context);
static_cast<void>(extensions);

6
src/Magnum/Implementation/BufferState.h

@ -39,14 +39,16 @@ struct BufferState {
#endif
/* Target <-> index mapping */
static std::size_t indexForTarget(Buffer::Target target);
static const Buffer::Target targetForIndex[TargetCount-1];
static std::size_t indexForTarget(Buffer::TargetHint target);
static const Buffer::TargetHint targetForIndex[TargetCount-1];
explicit BufferState(Context& context, std::vector<std::string>& extensions);
void reset();
#ifndef MAGNUM_TARGET_GLES2
void(*bindBasesImplementation)(Buffer::Target, UnsignedInt, Containers::ArrayReference<Buffer* const>);
void(*bindRangesImplementation)(Buffer::Target, UnsignedInt, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>>);
void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr);
#endif
void(Buffer::*getParameterImplementation)(GLenum, GLint*);

12
src/Magnum/Mesh.cpp

@ -392,7 +392,7 @@ void Mesh::attributePointerImplementationDSA(const Attribute& attribute) {
void Mesh::vertexAttribPointer(const Attribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bindInternal(Buffer::Target::Array);
attribute.buffer->bindInternal(Buffer::TargetHint::Array);
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) {
#ifndef MAGNUM_TARGET_GLES2
@ -428,7 +428,7 @@ void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute)
void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bindInternal(Buffer::Target::Array);
attribute.buffer->bindInternal(Buffer::TargetHint::Array);
glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
}
@ -457,7 +457,7 @@ void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) {
void Mesh::vertexAttribPointer(const LongAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bindInternal(Buffer::Target::Array);
attribute.buffer->bindInternal(Buffer::TargetHint::Array);
glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
}
@ -502,9 +502,9 @@ void Mesh::bindIndexBufferImplementationVAO(Buffer& buffer) {
/* Reset ElementArray binding to force explicit glBindBuffer call later */
/** @todo Do this cleaner way */
Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(Buffer::Target::ElementArray)] = 0;
Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(Buffer::TargetHint::ElementArray)] = 0;
buffer.bindInternal(Buffer::Target::ElementArray);
buffer.bindInternal(Buffer::TargetHint::ElementArray);
}
void Mesh::bindImplementationDefault() {
@ -523,7 +523,7 @@ void Mesh::bindImplementationDefault() {
#endif
/* Bind index buffer, if the mesh is indexed */
if(_indexBuffer) _indexBuffer->bindInternal(Buffer::Target::ElementArray);
if(_indexBuffer) _indexBuffer->bindInternal(Buffer::TargetHint::ElementArray);
}
void Mesh::bindImplementationVAO() {

8
src/Magnum/MeshTools/Compile.cpp

@ -49,7 +49,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
stride += sizeof(Shaders::Generic2D::TextureCoordinates::Type);
/* Create vertex buffer */
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}};
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::TargetHint::Array}};
/* Interleave positions */
Containers::Array<char> data = MeshTools::interleave(
@ -82,7 +82,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices());
indexBuffer.reset(new Buffer{Buffer::Target::ElementArray});
indexBuffer.reset(new Buffer{Buffer::TargetHint::ElementArray});
indexBuffer->setData(indexData, usage);
mesh.setCount(meshData.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
@ -109,7 +109,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
stride += sizeof(Shaders::Generic3D::TextureCoordinates::Type);
/* Create vertex buffer */
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}};
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::TargetHint::Array}};
/* Interleave positions */
Containers::Array<char> data = MeshTools::interleave(
@ -154,7 +154,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices());
indexBuffer.reset(new Buffer{Buffer::Target::ElementArray});
indexBuffer.reset(new Buffer{Buffer::TargetHint::ElementArray});
indexBuffer->setData(indexData, usage);
mesh.setCount(meshData.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);

64
src/Magnum/Test/BufferGLTest.cpp

@ -43,6 +43,12 @@ class BufferGLTest: public AbstractOpenGLTester {
void constructMove();
void label();
#ifndef MAGNUM_TARGET_GLES2
void bindBase();
void bindRange();
#endif
void data();
void map();
#ifdef MAGNUM_TARGET_GLES2
@ -60,7 +66,14 @@ BufferGLTest::BufferGLTest() {
addTests({&BufferGLTest::construct,
&BufferGLTest::constructCopy,
&BufferGLTest::constructMove,
&BufferGLTest::label,
#ifndef MAGNUM_TARGET_GLES2
&BufferGLTest::bindBase,
&BufferGLTest::bindRange,
#endif
&BufferGLTest::data,
&BufferGLTest::map,
#ifdef MAGNUM_TARGET_GLES2
@ -80,7 +93,7 @@ void BufferGLTest::construct() {
MAGNUM_VERIFY_NO_ERROR();
CORRADE_VERIFY(buffer.id() > 0);
CORRADE_COMPARE(buffer.targetHint(), Buffer::Target::Array);
CORRADE_COMPARE(buffer.targetHint(), Buffer::TargetHint::Array);
CORRADE_COMPARE(buffer.size(), 0);
}
@ -131,6 +144,55 @@ void BufferGLTest::label() {
CORRADE_COMPARE(buffer.label(), "MyBuffer");
}
#ifndef MAGNUM_TARGET_GLES2
void BufferGLTest::bindBase() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::uniform_buffer_object::string() + std::string{" is not supported."});
#endif
Buffer buffer;
buffer.bind(Buffer::Target::Uniform, 15);
MAGNUM_VERIFY_NO_ERROR();
Buffer::unbind(Buffer::Target::Uniform, 15);
MAGNUM_VERIFY_NO_ERROR();
Buffer::bind(Buffer::Target::Uniform, 7, {&buffer, nullptr, &buffer});
MAGNUM_VERIFY_NO_ERROR();
Buffer::unbind(Buffer::Target::Uniform, 7, 3);
MAGNUM_VERIFY_NO_ERROR();
}
void BufferGLTest::bindRange() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::uniform_buffer_object::string() + std::string{" is not supported."});
#endif
/* Check that we have correct offset alignment */
CORRADE_INTERNAL_ASSERT(256 % Buffer::uniformOffsetAlignment() == 0);
Buffer buffer;
buffer.setData({nullptr, 1024}, BufferUsage::StaticDraw)
.bind(Buffer::Target::Uniform, 15, 256, 13);
MAGNUM_VERIFY_NO_ERROR();
/** @todo C++14: get rid of std::make_tuple */
Buffer::bind(Buffer::Target::Uniform, 7, {
std::make_tuple(&buffer, 256, 13), {},
std::make_tuple(&buffer, 768, 64)});
MAGNUM_VERIFY_NO_ERROR();
}
#endif
void BufferGLTest::data() {
Buffer buffer;

20
src/Magnum/Test/MeshGLTest.cpp

@ -1262,7 +1262,7 @@ void MeshGLTest::setIndexBuffer() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1289,7 +1289,7 @@ void MeshGLTest::setIndexBufferRange() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1321,7 +1321,7 @@ void MeshGLTest::setIndexBufferUnsignedInt() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedInt indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1352,7 +1352,7 @@ void MeshGLTest::setBaseVertex() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1428,7 +1428,7 @@ void MeshGLTest::setInstanceCountIndexed() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1500,7 +1500,7 @@ void MeshGLTest::setInstanceCountBaseInstanceIndexed() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1534,7 +1534,7 @@ void MeshGLTest::setInstanceCountBaseVertex() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1570,7 +1570,7 @@ void MeshGLTest::setInstanceCountBaseVertexBaseInstance() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1788,7 +1788,7 @@ void MeshGLTest::multiDrawIndexed() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
@ -1813,7 +1813,7 @@ void MeshGLTest::multiDrawBaseVertex() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;

2
src/Magnum/Text/Renderer.cpp

@ -301,7 +301,7 @@ void AbstractRenderer::bufferUnmapImplementationDefault(Buffer& buffer)
#endif
}
AbstractRenderer::AbstractRenderer(AbstractFont& font, const GlyphCache& cache, const Float size, const Alignment alignment): _vertexBuffer(Buffer::Target::Array), _indexBuffer(Buffer::Target::ElementArray), font(font), cache(cache), size(size), _alignment(alignment), _capacity(0) {
AbstractRenderer::AbstractRenderer(AbstractFont& font, const GlyphCache& cache, const Float size, const Alignment alignment): _vertexBuffer{Buffer::TargetHint::Array}, _indexBuffer{Buffer::TargetHint::ElementArray}, font(font), cache(cache), size(size), _alignment(alignment), _capacity(0) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::map_buffer_range);
#elif defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN)

Loading…
Cancel
Save