Prevent redundant glBindBuffer calls.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2016-10-20 21:50:48 -03:00
parent 4c122e6581
commit d1c5edd792
14 changed files with 128 additions and 160 deletions
+1
View File
@@ -315,6 +315,7 @@ void Canvas::drawv(const Matrix4 &t, const Vertex *v)
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD);
gl.bindBuffer(BUFFER_VERTEX, 0);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].x);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].s);
+3 -3
View File
@@ -663,6 +663,8 @@ void Font::drawVertices(const std::vector<DrawCommand> &drawcommands, bool buffe
// with client-side vertex arrays.
if (bufferedvertices)
quadIndices.getBuffer()->bind();
else
gl.bindBuffer(BUFFER_INDEX, 0);
// We need a separate draw call for every section of the text which uses a
// different texture than the previous section.
@@ -679,9 +681,6 @@ void Font::drawVertices(const std::vector<DrawCommand> &drawcommands, bool buffe
else
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getIndices(offset));
}
if (bufferedvertices)
quadIndices.getBuffer()->unbind();
}
void Font::printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices)
@@ -694,6 +693,7 @@ void Font::printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands
OpenGL::TempTransform transform(gl);
transform.get() *= t;
gl.bindBuffer(BUFFER_VERTEX, 0);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(GlyphVertex), &vertices[0].x);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(GlyphVertex), &vertices[0].s);
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlyphVertex), &vertices[0].color.r);
+19 -35
View File
@@ -34,11 +34,10 @@ namespace graphics
namespace opengl
{
GLBuffer::GLBuffer(size_t size, const void *data, GLenum target, GLenum usage, uint32 mapflags)
: is_bound(false)
, is_mapped(false)
GLBuffer::GLBuffer(size_t size, const void *data, BufferType type, GLenum usage, uint32 mapflags)
: is_mapped(false)
, size(size)
, target(target)
, type(type)
, usage(usage)
, vbo(0)
, memory_map(nullptr)
@@ -46,6 +45,8 @@ GLBuffer::GLBuffer(size_t size, const void *data, GLenum target, GLenum usage, u
, modified_size(0)
, map_flags(mapflags)
{
target = OpenGL::getGLBufferType(type);
try
{
memory_map = new char[size];
@@ -92,15 +93,17 @@ void GLBuffer::unmapStatic(size_t offset, size_t size)
return;
// Upload the mapped data to the buffer.
glBufferSubData(getTarget(), (GLintptr) offset, (GLsizeiptr) size, memory_map + offset);
gl.bindBuffer(type, vbo);
glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, memory_map + offset);
}
void GLBuffer::unmapStream()
{
// "orphan" current buffer to avoid implicit synchronisation on the GPU:
// http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf
glBufferData(getTarget(), (GLsizeiptr) getSize(), nullptr, getUsage());
glBufferData(getTarget(), (GLsizeiptr) getSize(), memory_map, getUsage());
gl.bindBuffer(type, vbo);
glBufferData(target, (GLsizeiptr) getSize(), nullptr, getUsage());
glBufferData(target, (GLsizeiptr) getSize(), memory_map, getUsage());
}
void GLBuffer::unmap()
@@ -119,14 +122,6 @@ void GLBuffer::unmap()
modified_size = getSize();
}
// VBO::bind is a no-op when the VBO is mapped, so we have to make sure it's
// bound here.
if (!is_bound)
{
glBindBuffer(getTarget(), vbo);
is_bound = true;
}
if (modified_size > 0)
{
switch (getUsage())
@@ -173,19 +168,7 @@ void GLBuffer::setMappedRangeModified(size_t offset, size_t modifiedsize)
void GLBuffer::bind()
{
if (!is_mapped)
{
glBindBuffer(getTarget(), vbo);
is_bound = true;
}
}
void GLBuffer::unbind()
{
if (is_bound)
glBindBuffer(getTarget(), 0);
is_bound = false;
gl.bindBuffer(getType(), vbo);
}
void GLBuffer::fill(size_t offset, size_t size, const void *data)
@@ -195,7 +178,10 @@ void GLBuffer::fill(size_t offset, size_t size, const void *data)
if (is_mapped)
setMappedRangeModified(offset, size);
else
glBufferSubData(getTarget(), (GLintptr) offset, (GLsizeiptr) size, data);
{
gl.bindBuffer(type, vbo);
glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, data);
}
}
const void *GLBuffer::getPointer(size_t offset) const
@@ -217,7 +203,7 @@ bool GLBuffer::load(bool restore)
{
glGenBuffers(1, &vbo);
GLBuffer::Bind bind(*this);
bind();
while (glGetError() != GL_NO_ERROR)
/* Clear the error buffer. */;
@@ -226,7 +212,7 @@ bool GLBuffer::load(bool restore)
const GLvoid *src = restore ? memory_map : nullptr;
// Note that if 'src' is '0', no data will be copied.
glBufferData(getTarget(), (GLsizeiptr) getSize(), src, getUsage());
glBufferData(target, (GLsizeiptr) getSize(), src, getUsage());
return (glGetError() == GL_NO_ERROR);
}
@@ -234,8 +220,7 @@ bool GLBuffer::load(bool restore)
void GLBuffer::unload()
{
is_mapped = false;
glDeleteBuffers(1, &vbo);
gl.deleteBuffer(vbo);
vbo = 0;
}
@@ -274,7 +259,7 @@ QuadIndices::QuadIndices(size_t size)
// QuadIndices will propagate the exception and keep the old GLBuffer.
try
{
newbuffer = new GLBuffer(buffersize, nullptr, GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
newbuffer = new GLBuffer(buffersize, nullptr, BUFFER_INDEX, GL_STATIC_DRAW);
newindices = new char[buffersize];
}
catch (std::bad_alloc &)
@@ -394,7 +379,6 @@ void QuadIndices::fill()
inds[i*6+5] = T(i * 4 + 3);
}
GLBuffer::Bind bind(*indexBuffer);
indexBuffer->fill(0, indexBuffer->getSize(), indices);
}
+7 -59
View File
@@ -56,10 +56,10 @@ public:
* Constructor.
*
* @param size The size of the GLBuffer in bytes.
* @param target The target GLBuffer object, e.g. GL_ARRAY_BUFFER.
* @param type The type of the buffer object.
* @param usage Usage hint, e.g. GL_DYNAMIC_DRAW.
*/
GLBuffer(size_t size, const void *data, GLenum target, GLenum usage, uint32 mapflags = 0);
GLBuffer(size_t size, const void *data, BufferType type, GLenum usage, uint32 mapflags = 0);
/**
* Destructor.
@@ -77,13 +77,11 @@ public:
}
/**
* Get the target buffer object.
*
* @return The target buffer object, e.g. GL_ARRAY_BUFFER.
* Get the type of the buffer object.
*/
GLenum getTarget() const
BufferType getType() const
{
return target;
return type;
}
/**
@@ -96,11 +94,6 @@ public:
return usage;
}
bool isBound() const
{
return is_bound;
}
bool isMapped() const
{
return is_mapped;
@@ -112,8 +105,6 @@ public:
* This can be faster for large changes to the buffer. For smaller
* changes, see fill().
*
* The GLBuffer must be bound to use this function.
*
* @return A pointer to memory which represents the buffer.
*/
void *map();
@@ -121,8 +112,6 @@ public:
/**
* Unmap a previously mapped GLBuffer. The buffer must be unmapped
* when used to draw elements.
*
* The GLBuffer must be bound to use this function.
*/
void unmap();
@@ -138,16 +127,9 @@ public:
*/
void bind();
/**
* Unbind a prevously bound GLBuffer.
*/
void unbind();
/**
* Fill a portion of the buffer with data and marks the range as modified.
*
* The GLBuffer must be bound to use this function.
*
* @param offset The offset in the GLBuffer to store the data.
* @param size The size of the incoming data.
* @param data Pointer to memory to copy data from.
@@ -171,38 +153,6 @@ public:
bool loadVolatile() override;
void unloadVolatile() override;
/**
* This helper class can bind a GLBuffer temporarily, and
* automatically un-bind when it's destroyed.
*/
class Bind
{
public:
/**
* Bind a GLBuffer.
*/
Bind(GLBuffer &buf)
: buf(buf)
{
buf.bind();
}
/**
* Unbinds a GLBuffer.
*/
~Bind()
{
buf.unbind();
}
private:
// GLBuffer to work on.
GLBuffer &buf;
}; // Bind
class Mapper
{
public:
@@ -253,16 +203,14 @@ private:
void unmapStatic(size_t offset, size_t size);
void unmapStream();
// Whether the buffer is currently bound.
bool is_bound;
// Whether the buffer is currently mapped to main memory.
bool is_mapped;
// The size of the buffer, in bytes.
size_t size;
// The target buffer object. (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER).
// The type of the buffer object.
BufferType type;
GLenum target;
// Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW.
+2
View File
@@ -1288,6 +1288,7 @@ void Graphics::points(const float *coords, const uint8 *colors, size_t numpoints
gl.prepareDraw();
gl.bindTexture(gl.getDefaultTexture());
gl.bindBuffer(BUFFER_VERTEX, 0);
uint32 attribflags = ATTRIBFLAG_POS;
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coords);
@@ -1550,6 +1551,7 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
gl.prepareDraw();
gl.bindTexture(gl.getDefaultTexture());
gl.bindBuffer(BUFFER_VERTEX, 0);
gl.useVertexAttribArrays(ATTRIBFLAG_POS);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coords);
gl.drawArrays(GL_TRIANGLE_FAN, 0, (int)count/2-1); // opengl will close the polygon for us
+1
View File
@@ -453,6 +453,7 @@ void Image::drawv(const Matrix4 &t, const Vertex *v)
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD);
gl.bindBuffer(BUFFER_VERTEX, 0);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].x);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].s);
+7 -27
View File
@@ -80,7 +80,7 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, const void *data, size
if (vertexCount == 0)
throw love::Exception("Data size is too small for specified vertex attribute formats.");
vbo = new GLBuffer(datasize, data, GL_ARRAY_BUFFER, getGLBufferUsage(usage), GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
vbo = new GLBuffer(datasize, data, BUFFER_VERTEX, getGLBufferUsage(usage), GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
vertexScratchBuffer = new char[vertexStride];
}
@@ -106,10 +106,9 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawM
size_t buffersize = vertexCount * vertexStride;
vbo = new GLBuffer(buffersize, nullptr, GL_ARRAY_BUFFER, getGLBufferUsage(usage), GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
vbo = new GLBuffer(buffersize, nullptr, BUFFER_VERTEX, getGLBufferUsage(usage), GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
// Initialize the buffer's contents to 0.
GLBuffer::Bind bind(*vbo);
memset(vbo->map(), 0, buffersize);
vbo->setMappedRangeModified(0, vbo->getSize());
vbo->unmap();
@@ -192,9 +191,7 @@ void Mesh::setVertex(size_t vertindex, const void *data, size_t datasize)
size_t offset = vertindex * vertexStride;
size_t size = std::min(datasize, vertexStride);
GLBuffer::Bind bind(*vbo);
uint8 *bufferdata = (uint8 *) vbo->map();
memcpy(bufferdata + offset, data, size);
vbo->setMappedRangeModified(offset, size);
@@ -209,9 +206,7 @@ size_t Mesh::getVertex(size_t vertindex, void *data, size_t datasize)
size_t size = std::min(datasize, vertexStride);
// We're relying on vbo->map() returning read/write data... ew.
GLBuffer::Bind bind(*vbo);
const uint8 *bufferdata = (const uint8 *) vbo->map();
memcpy(data, bufferdata + offset, size);
return size;
@@ -233,9 +228,7 @@ void Mesh::setVertexAttribute(size_t vertindex, int attribindex, const void *dat
size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex);
size_t size = std::min(datasize, attributeSizes[attribindex]);
GLBuffer::Bind bind(*vbo);
uint8 *bufferdata = (uint8 *) vbo->map();
memcpy(bufferdata + offset, data, size);
vbo->setMappedRangeModified(offset, size);
@@ -253,9 +246,7 @@ size_t Mesh::getVertexAttribute(size_t vertindex, int attribindex, void *data, s
size_t size = std::min(datasize, attributeSizes[attribindex]);
// We're relying on vbo->map() returning read/write data... ew.
GLBuffer::Bind bind(*vbo);
const uint8 *bufferdata = (const uint8 *) vbo->map();
memcpy(data, bufferdata + offset, size);
return size;
@@ -356,29 +347,21 @@ void Mesh::attachAttribute(const std::string &name, Mesh *mesh)
void *Mesh::mapVertexData()
{
GLBuffer::Bind bind(*vbo);
return vbo->map();
}
void Mesh::unmapVertexData(size_t modifiedoffset, size_t modifiedsize)
{
GLBuffer::Bind bind(*vbo);
vbo->setMappedRangeModified(modifiedoffset, modifiedsize);
vbo->unmap();
}
void Mesh::flush()
{
{
GLBuffer::Bind vbobind(*vbo);
vbo->unmap();
}
vbo->unmap();
if (ibo != nullptr)
{
GLBuffer::Bind ibobind(*ibo);
ibo->unmap();
}
}
/**
@@ -414,7 +397,7 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
}
if (!ibo && size > 0)
ibo = new GLBuffer(size, nullptr, GL_ELEMENT_ARRAY_BUFFER, vbo->getUsage());
ibo = new GLBuffer(size, nullptr, BUFFER_INDEX, vbo->getUsage());
useIndexBuffer = true;
elementCount = map.size();
@@ -422,7 +405,6 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
if (!ibo || elementCount == 0)
return;
GLBuffer::Bind ibobind(*ibo);
GLBuffer::Mapper ibomap(*ibo);
// Fill the buffer with the index values from the vector.
@@ -467,8 +449,6 @@ bool Mesh::getVertexMap(std::vector<uint32> &map) const
if (!ibo || elementCount == 0)
return true;
GLBuffer::Bind ibobind(*ibo);
// We unmap the buffer in Mesh::draw, Mesh::setVertexMap, and Mesh::flush.
void *buffer = ibo->map();
@@ -559,8 +539,8 @@ int Mesh::bindAttributeToShaderInput(int attributeindex, const std::string &inpu
if (attriblocation < 0)
return attriblocation;
// Needed for unmap and glVertexAttribPointer.
GLBuffer::Bind vbobind(*vbo);
// Needed for glVertexAttribPointer.
vbo->bind();
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
vbo->unmap();
@@ -614,7 +594,7 @@ void Mesh::draw(const Matrix4 &m)
if (useIndexBuffer && ibo && elementCount > 0)
{
// Use the custom vertex map (index buffer) to draw the vertices.
GLBuffer::Bind ibo_bind(*ibo);
ibo->bind();
// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
ibo->unmap();
+39
View File
@@ -143,6 +143,12 @@ void OpenGL::setupContext()
else
state.framebufferSRGBEnabled = false;
for (int i = 0; i < (int) BUFFER_MAX_ENUM; i++)
{
state.boundBuffers[i] = 0;
glBindBuffer(getGLBufferType((BufferType) i), 0);
}
// Initialize multiple texture unit support for shaders.
state.boundTextures.clear();
state.boundTextures.resize(maxTextureUnits, 0);
@@ -380,6 +386,39 @@ void OpenGL::prepareDraw()
}
}
GLenum OpenGL::getGLBufferType(BufferType type)
{
switch (type)
{
case BUFFER_VERTEX:
return GL_ARRAY_BUFFER;
case BUFFER_INDEX:
return GL_ELEMENT_ARRAY_BUFFER;
case BUFFER_MAX_ENUM:
return GL_ZERO;
}
}
void OpenGL::bindBuffer(BufferType type, GLuint buffer)
{
if (state.boundBuffers[type] != buffer)
{
glBindBuffer(getGLBufferType(type), buffer);
state.boundBuffers[type] = buffer;
}
}
void OpenGL::deleteBuffer(GLuint buffer)
{
glDeleteBuffers(1, &buffer);
for (int i = 0; i < (int) BUFFER_MAX_ENUM; i++)
{
if (state.boundBuffers[i] == buffer)
state.boundBuffers[i] = 0;
}
}
void OpenGL::drawArrays(GLenum mode, GLint first, GLsizei count)
{
glDrawArrays(mode, first, count);
+24 -2
View File
@@ -69,6 +69,13 @@ enum VertexAttribFlags
ATTRIBFLAG_CONSTANTCOLOR = 1 << ATTRIB_CONSTANTCOLOR
};
enum BufferType
{
BUFFER_VERTEX = 0,
BUFFER_INDEX,
BUFFER_MAX_ENUM
};
/**
* Thin layer between OpenGL and the rest of the program.
* Internally shadows some OpenGL context state for improved efficiency and
@@ -243,6 +250,18 @@ public:
**/
void prepareDraw();
/**
* State-tracked glBindBuffer.
* NOTE: This does not account for multiple VAOs being used! Index buffer
* bindings are per-VAO in OpenGL, but this doesn't know about that.
**/
void bindBuffer(BufferType type, GLuint buffer);
/**
* glDeleteBuffers which updates our shadowed state.
**/
void deleteBuffer(GLuint buffer);
/**
* glDrawArrays and glDrawElements which increment the draw-call counter by
* themselves.
@@ -396,6 +415,9 @@ public:
**/
Vendor getVendor() const;
static GLenum getGLBufferType(BufferType type);
static GLint getGLWrapMode(Texture::WrapMode wmode);
static const char *errorString(GLenum errorcode);
// Get human-readable strings for debug info.
@@ -411,8 +433,6 @@ private:
void initMatrices();
void createDefaultTexture();
GLint getGLWrapMode(Texture::WrapMode wmode);
bool contextInitialized;
float maxAnisotropy;
@@ -427,6 +447,8 @@ private:
// Tracked OpenGL state.
struct
{
GLuint boundBuffers[BUFFER_MAX_ENUM];
// Texture unit state (currently bound texture for each texture unit.)
std::vector<GLuint> boundTextures;
@@ -137,6 +137,7 @@ void ParticleSystem::draw(const Matrix4 &m)
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
gl.bindBuffer(BUFFER_VERTEX, 0);
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &particleVerts[0].r);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].x);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].s);
@@ -148,6 +149,7 @@ void ParticleSystem::draw(const Matrix4 &m)
// at least one graphics driver (the one for Kepler nvidia GPUs in OS X
// 10.11) fails to render geometry if an index buffer is used with
// client-side vertex arrays.
gl.bindBuffer(BUFFER_INDEX, 0);
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getIndices(0));
}
+4
View File
@@ -402,6 +402,7 @@ void Polyline::draw()
gl.prepareDraw();
gl.bindTexture(gl.getDefaultTexture());
gl.bindBuffer(BUFFER_VERTEX, 0);
uint32 enabledattribs = ATTRIBFLAG_POS;
@@ -426,7 +427,10 @@ void Polyline::draw()
// because the vertex array contains both the core line and the overdraw
// vertices.
if (use_quad_indices)
{
gl.bindBuffer(BUFFER_INDEX, 0);
gl.drawElements(draw_mode, (int) (total_vertex_count / 4) * 6, GL_UNSIGNED_SHORT, indices);
}
else
gl.drawArrays(draw_mode, 0, (int) total_vertex_count);
+16 -29
View File
@@ -57,7 +57,7 @@ SpriteBatch::SpriteBatch(Texture *texture, int size, Mesh::Usage usage)
GLenum gl_usage = Mesh::getGLBufferUsage(usage);
size_t vertex_size = sizeof(Vertex) * 4 * size;
array_buf = new GLBuffer(vertex_size, nullptr, GL_ARRAY_BUFFER, gl_usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
array_buf = new GLBuffer(vertex_size, nullptr, BUFFER_VERTEX, gl_usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY);
}
SpriteBatch::~SpriteBatch()
@@ -108,7 +108,6 @@ void SpriteBatch::clear()
void SpriteBatch::flush()
{
GLBuffer::Bind bind(*array_buf);
array_buf->unmap();
}
@@ -155,11 +154,7 @@ void SpriteBatch::setBufferSize(int newsize)
return;
// Map the old GLBuffer to get a pointer to its data.
void *old_data = nullptr;
{
GLBuffer::Bind bind(*array_buf);
old_data = array_buf->map();
}
void *old_data = array_buf->map();
size_t vertex_size = sizeof(Vertex) * 4 * newsize;
GLBuffer *new_array_buf = nullptr;
@@ -168,9 +163,7 @@ void SpriteBatch::setBufferSize(int newsize)
try
{
new_array_buf = new GLBuffer(vertex_size, nullptr, array_buf->getTarget(), array_buf->getUsage(), array_buf->getMapFlags());
GLBuffer::Bind bind(*new_array_buf);
new_array_buf = new GLBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
// Copy as much of the old data into the new GLBuffer as can fit.
size_t copy_size = sizeof(Vertex) * 4 * new_next;
@@ -263,25 +256,21 @@ void SpriteBatch::draw(const Matrix4 &m)
uint32 enabledattribs = ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD;
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
array_buf->bind();
// Apply per-sprite color, if a color is set.
if (color)
{
// Scope this bind so it doesn't interfere with the
// Mesh::bindAttributeToShaderInput calls below.
GLBuffer::Bind array_bind(*array_buf);
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
// Apply per-sprite color, if a color is set.
if (color)
{
enabledattribs |= ATTRIBFLAG_COLOR;
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), array_buf->getPointer(color_offset));
}
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(pos_offset));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(texel_offset));
enabledattribs |= ATTRIBFLAG_COLOR;
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), array_buf->getPointer(color_offset));
}
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(pos_offset));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(texel_offset));
for (const auto &it : attached_attributes)
{
Mesh *mesh = it.second.mesh.get();
@@ -309,7 +298,7 @@ void SpriteBatch::draw(const Matrix4 &m)
count = std::min(count, next - start);
GLBuffer::Bind element_bind(*quad_indices.getBuffer());
quad_indices.getBuffer()->bind();
const void *indices = quad_indices.getPointer(start * quad_indices.getElementSize());
if (count > 0)
@@ -327,8 +316,6 @@ void SpriteBatch::addv(const Vertex *v, const Matrix4 &m, int index)
if (color)
setColorv(sprite, *color);
GLBuffer::Bind bind(*array_buf);
// Always keep the VBO mapped when adding data for now (it'll be unmapped
// on draw.)
array_buf->map();
+2 -5
View File
@@ -58,13 +58,12 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
if (vbo != nullptr)
newsize = std::max(size_t(vbo->getSize() * 1.5), newsize);
GLBuffer *new_vbo = new GLBuffer(newsize, nullptr, GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
GLBuffer *new_vbo = new GLBuffer(newsize, nullptr, BUFFER_VERTEX, GL_DYNAMIC_DRAW);
if (vbo != nullptr)
{
try
{
GLBuffer::Bind bind(*vbo);
vbodata = (uint8 *) vbo->map();
}
catch (love::Exception &)
@@ -73,7 +72,6 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
throw;
}
GLBuffer::Bind bind(*new_vbo);
new_vbo->fill(0, vbo->getSize(), vbodata);
}
@@ -83,7 +81,6 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
if (vbo != nullptr && datasize > 0)
{
GLBuffer::Bind bind(*vbo);
vbodata = (uint8 *) vbo->map();
memcpy(vbodata + offset, &vertices[0], datasize);
// We unmap when we draw, to avoid unnecessary full map()/unmap() calls.
@@ -228,7 +225,7 @@ void Text::draw(const Matrix4 &m)
transform.get() *= m;
{
GLBuffer::Bind bind(*vbo);
vbo->bind();
vbo->unmap(); // Make sure all pending data is flushed to the GPU.
// Font::drawVertices expects AttribPointer calls to be done already.
+1
View File
@@ -134,6 +134,7 @@ void Video::draw(const Matrix4 &m)
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD);
gl.bindBuffer(BUFFER_VERTEX, 0);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertices[0].x);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertices[0].s);