Browse Source

GL: accept Mesh index offset as a pointer-sized value.

Vertex buffer offsets are like this already (and I already had a use
case with a mesh of size larger than 4 GB), with index buffers so far I
thought it's not needed, but it makes sense to do that as well -- there
can be a giant index buffer for many meshes and even though the total
drawn element count won't reach 1 billion (or 1 million, even), it can
still go over. Since it was internally already stored as a pointer-sized
value and some (but not all) code was treating it as pointer-sized, this
change just makes sense.

This also fixes "warning C4244: 'return': conversion from 'const
GLintptr' to 'Magnum::Int', possible loss of data" on MSVC, although in
a very different way.
pull/638/head
Vladimír Vondruš 2 years ago
parent
commit
b141901765
  1. 20
      src/Magnum/GL/Mesh.cpp
  2. 16
      src/Magnum/GL/Mesh.h

20
src/Magnum/GL/Mesh.cpp

@ -438,7 +438,7 @@ UnsignedInt Mesh::indexTypeSize() const {
} }
#endif #endif
Mesh& Mesh::setIndexOffset(Int offset) { Mesh& Mesh::setIndexOffset(GLintptr offset) {
CORRADE_ASSERT(_indexBuffer.id(), CORRADE_ASSERT(_indexBuffer.id(),
"GL::Mesh::setIndexOffset(): mesh is not indexed", *this); "GL::Mesh::setIndexOffset(): mesh is not indexed", *this);
_indexOffset = offset; _indexOffset = offset;
@ -871,7 +871,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
{ {
const Implementation::MeshState& state = Context::current().state().mesh; const Implementation::MeshState& state = Context::current().state().mesh;
const UnsignedInt indexByteOffset = _indexBuffer.id() ? const GLintptr indexByteOffset = _indexBuffer.id() ?
_indexBufferOffset + indexOffset*meshIndexTypeSize(_indexType) : _indexBufferOffset + indexOffset*meshIndexTypeSize(_indexType) :
0; 0;
@ -900,7 +900,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
#else #else
state.drawRangeElementsBaseVertexImplementation state.drawRangeElementsBaseVertexImplementation
#endif #endif
(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset)), baseVertex); (GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset), baseVertex);
/* Indexed mesh */ /* Indexed mesh */
} else } else
@ -911,7 +911,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
#else #else
state.drawElementsBaseVertexImplementation state.drawElementsBaseVertexImplementation
#endif #endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset)), baseVertex); (GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset), baseVertex);
} }
#else #else
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): indexed mesh draw with base vertex specification possible only since WebGL 2.0", ); CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): indexed mesh draw with base vertex specification possible only since WebGL 2.0", );
@ -922,7 +922,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/* Indexed mesh with specified range */ /* Indexed mesh with specified range */
if(indexEnd) { if(indexEnd) {
glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset))); glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset));
/* Indexed mesh */ /* Indexed mesh */
} else } else
@ -931,7 +931,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
static_cast<void>(indexEnd); static_cast<void>(indexEnd);
#endif #endif
{ {
glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset))); glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset));
} }
} }
@ -971,7 +971,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
#else #else
state.drawElementsInstancedBaseVertexBaseInstanceImplementation state.drawElementsInstancedBaseVertexBaseInstanceImplementation
#endif #endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset)), instanceCount, baseVertex, baseInstance); (GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset), instanceCount, baseVertex, baseInstance);
/* Indexed mesh with base vertex */ /* Indexed mesh with base vertex */
} else { } else {
@ -980,7 +980,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
#else #else
state.drawElementsInstancedBaseVertexImplementation state.drawElementsInstancedBaseVertexImplementation
#endif #endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset)), instanceCount, baseVertex); (GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset), instanceCount, baseVertex);
} }
#else #else
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): instanced indexed mesh draw with base vertex specification possible only since OpenGL ES 3.0", ); CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): instanced indexed mesh draw with base vertex specification possible only since OpenGL ES 3.0", );
@ -996,7 +996,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
#else #else
state.drawElementsInstancedBaseInstanceImplementation state.drawElementsInstancedBaseInstanceImplementation
#endif #endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset)), instanceCount, baseInstance); (GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset), instanceCount, baseInstance);
/* Instanced mesh */ /* Instanced mesh */
} else } else
@ -1007,7 +1007,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
#else #else
state.drawElementsInstancedImplementation state.drawElementsInstancedImplementation
#endif #endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(std::size_t(indexByteOffset)), instanceCount); (GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexByteOffset), instanceCount);
} }
} }
} }

16
src/Magnum/GL/Mesh.h

@ -753,7 +753,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
* @brief Index offset * @brief Index offset
* @m_since_latest * @m_since_latest
*/ */
Int indexOffset() const { return _indexOffset; } GLintptr indexOffset() const { return _indexOffset; }
/** /**
* @brief Set index offset * @brief Set index offset
@ -768,7 +768,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
* @p start and @p end parameters may help to improve memory access * @p start and @p end parameters may help to improve memory access
* performance, as only a portion of vertex buffer needs to be * performance, as only a portion of vertex buffer needs to be
* acccessed. On OpenGL ES 2.0 this function behaves the same as * acccessed. On OpenGL ES 2.0 this function behaves the same as
* @ref setIndexOffset(Int), as index range functionality is not * @ref setIndexOffset(GLintptr), as index range functionality is not
* available there. Ignored when calling * available there. Ignored when calling
* @ref AbstractShaderProgram::drawTransformFeedback(). * @ref AbstractShaderProgram::drawTransformFeedback().
* *
@ -776,7 +776,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
* @see @ref setCount(), @ref isIndexed() * @see @ref setCount(), @ref isIndexed()
*/ */
/* MinGW/MSVC needs inline also here to avoid linkage conflicts */ /* MinGW/MSVC needs inline also here to avoid linkage conflicts */
inline Mesh& setIndexOffset(Int offset, UnsignedInt start, UnsignedInt end); inline Mesh& setIndexOffset(GLintptr offset, UnsignedInt start, UnsignedInt end);
/** /**
* @brief Set index offset * @brief Set index offset
@ -785,14 +785,14 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
* *
* The offset gets multiplied by index type size and added to the base * The offset gets multiplied by index type size and added to the base
* offset that was specified in @ref Mesh::setIndexBuffer(). Prefer to * offset that was specified in @ref Mesh::setIndexBuffer(). Prefer to
* use @ref setIndexOffset(Int, UnsignedInt, UnsignedInt) for potential * use @ref setIndexOffset(GLintptr, UnsignedInt, UnsignedInt) for
* better performance on certain drivers. Ignored when calling * potential better performance on certain drivers. Ignored when
* @ref AbstractShaderProgram::drawTransformFeedback(). * calling @ref AbstractShaderProgram::drawTransformFeedback().
* *
* Expects that the mesh is indexed. * Expects that the mesh is indexed.
* @see @ref setCount(), @ref isIndexed() * @see @ref setCount(), @ref isIndexed()
*/ */
Mesh& setIndexOffset(Int offset); Mesh& setIndexOffset(GLintptr offset);
/** @brief Instance count */ /** @brief Instance count */
Int instanceCount() const { return _instanceCount; } Int instanceCount() const { return _instanceCount; }
@ -1443,7 +1443,7 @@ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, MeshPrimitive value);
/** @debugoperatorenum{MeshIndexType} */ /** @debugoperatorenum{MeshIndexType} */
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, MeshIndexType value); MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, MeshIndexType value);
inline Mesh& Mesh::setIndexOffset(Int first, UnsignedInt start, UnsignedInt end) { inline Mesh& Mesh::setIndexOffset(GLintptr first, UnsignedInt start, UnsignedInt end) {
setIndexOffset(first); setIndexOffset(first);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_indexStart = start; _indexStart = start;

Loading…
Cancel
Save