From 53d82bda19d7e0d8eec5b53886da05d096533d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 21 Oct 2012 16:34:02 +0200 Subject: [PATCH] Got rid of default Buffer target. For non-DSA access user can now specify target hint, which will be used when binding the buffer internally. --- src/Buffer.cpp | 4 ++-- src/Buffer.h | 50 ++++++++++++++++++++++++++------------------- src/BufferedImage.h | 4 +++- src/IndexedMesh.cpp | 4 ++-- src/IndexedMesh.h | 8 ++++++-- 5 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 5ecefd2e8..45647eeed 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -85,7 +85,7 @@ void Buffer::copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOff } void Buffer::setDataImplementationDefault(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) { - glBufferData(static_cast(bindInternal(_defaultTarget)), size, data, static_cast(usage)); + glBufferData(static_cast(bindInternal(_targetHint)), size, data, static_cast(usage)); } void Buffer::setDataImplementationDSA(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) { @@ -93,7 +93,7 @@ void Buffer::setDataImplementationDSA(GLsizeiptr size, const GLvoid* data, Buffe } void Buffer::setSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data) { - glBufferSubData(static_cast(bindInternal(_defaultTarget)), offset, size, data); + glBufferSubData(static_cast(bindInternal(_targetHint)), offset, size, data); } void Buffer::setSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data) { diff --git a/src/Buffer.h b/src/Buffer.h index 04a127405..17f69a52d 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -65,7 +65,8 @@ The engine tracks currently bound buffers to avoid unnecessary calls to @fn_gl{BindBuffer}. If the buffer is already bound to some target, functions copy(), setData() and setSubData() use that target in @fn_gl{CopyBufferSubData}, @fn_gl{BufferData} and @fn_gl{BufferSubData} -functions instead of binding the buffer to some specific target. +functions instead of binding the buffer to some specific target. You can also +use setTargetHint() to possibly reduce unnecessary rebinding. If extension @extension{EXT,direct_state_access} is available, functions copy(), setData() and setSubData() use DSA functions to avoid unnecessary @@ -259,8 +260,10 @@ class MAGNUM_EXPORT Buffer { * @param writeOffset Offset in the write buffer * @param size Data size * - * If @extension{EXT,direct_state_access} is not available, both - * buffers are bound to some target before the copy is performed. + * If @extension{EXT,direct_state_access} is not available and the + * buffers aren't already bound somewhere, they are bound to + * `Target::CopyRead` and `Target::CopyWrite` before the copy is + * performed. * @requires_gl31 Extension @extension{ARB,copy_buffer} * @requires_gles30 (no extension providing this functionality) * @see @fn_gl{BindBuffer} and @fn_gl{CopyBufferSubData} or @@ -272,13 +275,11 @@ class MAGNUM_EXPORT Buffer { /** * @brief Constructor - * @param defaultTarget Default target (used when calling bind() - * without parameter) * * Generates new OpenGL buffer. * @see @fn_gl{GenBuffers} */ - inline Buffer(Target defaultTarget): _defaultTarget(defaultTarget) { + inline Buffer(): _targetHint(Target::Array) { glGenBuffers(1, &_id); } @@ -290,19 +291,24 @@ class MAGNUM_EXPORT Buffer { */ virtual ~Buffer(); - /** @brief Default bind type */ - inline Target defaultTarget() const { return _defaultTarget; } - /** @brief OpenGL buffer ID */ inline GLuint id() const { return _id; } + /** @brief Target hint */ + inline Target targetHint() const { return _targetHint; } + /** - * @brief Bind buffer + * @brief Set target hint * - * Binds buffer to default target. - * @see bind(Target) + * If @extension{EXT,direct_state_access} is not available, the buffer + * must be internally bound to some target before any operation. You + * can specify target which will always be used when binding the + * buffer internally, possibly saving some calls to @fn_gl{BindBuffer}. + * + * Default target hint is `Target::Array`. + * @see setData(), setSubData() */ - inline void bind() { bind(_defaultTarget); } + inline void setTargetHint(Target hint) { _targetHint = hint; } /** * @brief Bind buffer @@ -318,9 +324,10 @@ class MAGNUM_EXPORT Buffer { * @param data Pointer to data * @param usage %Buffer usage * - * If @extension{EXT,direct_state_access} is not available, the buffer - * is bound to some target before the operation. - * @see @fn_gl{BindBuffer} and @fn_gl{BufferData} or + * If @extension{EXT,direct_state_access} is not available and the + * buffer is not already bound somewhere, it is bound to hinted target + * before the operation. + * @see setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferData} or * @fn_gl_extension{NamedBufferData,EXT,direct_state_access} */ inline void setData(GLsizeiptr size, const GLvoid* data, Usage usage) { @@ -360,10 +367,11 @@ class MAGNUM_EXPORT Buffer { * @param size Data size * @param data Pointer to data * - * If @extension{EXT,direct_state_access} is not available, the buffer - * is bound to some target before the operation. - * @see @fn_gl{BindBuffer} and @fn_gl{BufferSubData} or - * @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access} + * If @extension{EXT,direct_state_access} is not available and the + * buffer is not already bound somewhere, it is bound to hinted target + * before the operation. + * @see setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferSubData} + * or @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access} */ inline void setSubData(GLintptr offset, GLsizeiptr size, const GLvoid* data) { (this->*setSubDataImplementation)(offset, size, data); @@ -418,7 +426,7 @@ class MAGNUM_EXPORT Buffer { static SetSubDataImplementation setSubDataImplementation; GLuint _id; - Target _defaultTarget; + Target _targetHint; }; } diff --git a/src/BufferedImage.h b/src/BufferedImage.h index 4ec955e47..a09f01964 100644 --- a/src/BufferedImage.h +++ b/src/BufferedImage.h @@ -48,7 +48,9 @@ template class BufferedImage: public AbstractImage { * Dimensions and buffer are empty, call setData() to fill the image * with data. */ - inline BufferedImage(Components components, ComponentType type): AbstractImage(components, type), _buffer(Buffer::Target::PixelPack) {} + inline BufferedImage(Components components, ComponentType type): AbstractImage(components, type) { + _buffer.setTargetHint(Buffer::Target::PixelPack); + } /** @brief %Image size */ inline constexpr typename DimensionTraits::VectorType size() const { return _size; } diff --git a/src/IndexedMesh.cpp b/src/IndexedMesh.cpp index 6e9e96549..b6473c677 100644 --- a/src/IndexedMesh.cpp +++ b/src/IndexedMesh.cpp @@ -30,7 +30,7 @@ void IndexedMesh::draw() { /* Buffers must be bound after initialization */ #ifdef MAGNUM_TARGET_GLES bind(); - _indexBuffer.bind(); + _indexBuffer.bind(Buffer::Target::ElementArray); #endif /** @todo Start at given index */ @@ -50,7 +50,7 @@ void IndexedMesh::finalize() { /* Bind index buffer to VAO too */ #ifndef MAGNUM_TARGET_GLES - _indexBuffer.bind(); + _indexBuffer.bind(Buffer::Target::ElementArray); #endif } #endif diff --git a/src/IndexedMesh.h b/src/IndexedMesh.h index 5b9deec23..541c81a7b 100644 --- a/src/IndexedMesh.h +++ b/src/IndexedMesh.h @@ -37,7 +37,9 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { * Note that you have to call setVertexCount(), setIndexCount() and * setIndexType() manually for mesh to draw properly. */ - inline IndexedMesh(Primitive primitive = Primitive::Triangles): Mesh(primitive), _indexBuffer(Buffer::Target::ElementArray), _indexCount(0), _indexType(Type::UnsignedShort) {} + inline IndexedMesh(Primitive primitive = Primitive::Triangles): Mesh(primitive), _indexCount(0), _indexType(Type::UnsignedShort) { + _indexBuffer.setTargetHint(Buffer::Target::ElementArray); + } /** * @brief Constructor @@ -46,7 +48,9 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { * @param indexCount Count of indices * @param indexType Type of indices (indexable, see TypeTraits) */ - inline IndexedMesh(Primitive primitive, GLsizei vertexCount, GLsizei indexCount, Type indexType = Type::UnsignedShort): Mesh(primitive, vertexCount), _indexBuffer(Buffer::Target::ElementArray), _indexCount(indexCount), _indexType(indexType) {} + inline IndexedMesh(Primitive primitive, GLsizei vertexCount, GLsizei indexCount, Type indexType = Type::UnsignedShort): Mesh(primitive, vertexCount), _indexCount(indexCount), _indexType(indexType) { + _indexBuffer.setTargetHint(Buffer::Target::ElementArray); + } /** @brief Index count */ inline GLsizei indexCount() const { return _indexCount; }