Make internal vertex attribute code less OpenGL-specific.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-10-25 23:12:39 -03:00
parent b0c5bf2156
commit 15cc540e4c
28 changed files with 369 additions and 230 deletions
+13 -15
View File
@@ -353,7 +353,9 @@ void Graphics::flushStreamDraws()
OpenGL::TempDebugGroup debuggroup("Stream vertices flush and draw");
uint32 attribs = 0;
Attributes attributes;
Buffers buffers;
size_t usedsizes[3] = {0, 0, 0};
for (int i = 0; i < 2; i++)
@@ -361,26 +363,20 @@ void Graphics::flushStreamDraws()
if (sbstate.formats[i] == CommonFormat::NONE)
continue;
attributes.setCommonFormat(sbstate.formats[i], (uint8) i);
usedsizes[i] = getFormatStride(sbstate.formats[i]) * sbstate.vertexCount;
love::graphics::StreamBuffer *buffer = sbstate.vb[i];
gl.bindBuffer(BUFFER_VERTEX, (GLuint) buffer->getHandle());
size_t offset = buffer->unmap(usedsizes[i]);
size_t offset = sbstate.vb[i]->unmap(usedsizes[i]);
buffers.set(i, sbstate.vb[i], offset);
sbstate.vbMap[i] = StreamBuffer::MapInfo();
gl.setVertexPointers(sbstate.formats[i], offset);
attribs |= getFormatFlags(sbstate.formats[i]);
}
if (attribs == 0)
if (attributes.enablebits == 0)
return;
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(sbstate.primitiveMode);
Colorf nc = gl.getConstantColor();
if (attribs & ATTRIBFLAG_COLOR)
if (attributes.isEnabled(ATTRIB_COLOR))
gl.setConstantColor(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
pushIdentityTransform();
@@ -388,7 +384,9 @@ void Graphics::flushStreamDraws()
gl.prepareDraw();
gl.bindTextureToUnit(sbstate.texture, 0, false);
gl.useVertexAttribArrays(attribs);
gl.setVertexAttributes(attributes, buffers);
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(sbstate.primitiveMode);
if (sbstate.indexCount > 0)
{
@@ -415,7 +413,7 @@ void Graphics::flushStreamDraws()
popTransform();
if (attribs & ATTRIB_CONSTANTCOLOR)
if (attributes.isEnabled(ATTRIB_COLOR))
gl.setConstantColor(nc);
streamBufferState.vertexCount = 0;
+2 -35
View File
@@ -49,44 +49,11 @@ Mesh::~Mesh()
{
}
int Mesh::bindAttributeToShaderInput(int attributeindex, const std::string &inputname)
{
const AttribFormat &format = vertexFormat[attributeindex];
GLint attriblocation = -1;
// If the attribute is one of the LOVE-defined ones, use the constant
// attribute index for it, otherwise query the index from the shader.
VertexAttribID builtinattrib;
if (vertex::getConstant(inputname.c_str(), builtinattrib))
attriblocation = (GLint) builtinattrib;
else if (Shader::current)
attriblocation = Shader::current->getVertexAttributeIndex(inputname);
// The active shader might not use this vertex attribute name.
if (attriblocation < 0)
return attriblocation;
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
vbo->unmap();
gl.bindBuffer(BUFFER_VERTEX, (GLuint) vbo->getHandle());
GLboolean normalized = GL_FALSE;
GLenum datatype = OpenGL::getGLVertexDataType(format.type, normalized);
const void *gloffset = BUFFER_OFFSET(getAttributeOffset(attributeindex));
glVertexAttribPointer(attriblocation, format.components, datatype, normalized, (GLsizei) vertexStride, gloffset);
return attriblocation;
}
void Mesh::drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const
void Mesh::drawInternal(int start, int count, int instancecount, bool useindexbuffer, const vertex::Attributes &attributes, const vertex::Buffers &buffers) const
{
OpenGL::TempDebugGroup debuggroup("Mesh draw");
gl.useVertexAttribArrays(attribflags, instancedattribflags);
gl.setVertexAttributes(attributes, buffers);
gl.bindTextureToUnit(texture, 0, false);
gl.prepareDraw();
+1 -4
View File
@@ -37,14 +37,11 @@ public:
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, vertex::Usage usage);
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, PrimitiveType drawmode, vertex::Usage usage);
virtual ~Mesh();
int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) override;
protected:
void drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const override;
void drawInternal(int start, int count, int instancecount, bool useindexbuffer, const vertex::Attributes &attributes, const vertex::Buffers &buffers) const override;
}; // Mesh
+25 -84
View File
@@ -172,7 +172,7 @@ void OpenGL::setupContext()
else
state.instancedAttribArrays = 0;
useVertexAttribArrays(0, 0);
setVertexAttributes(vertex::Attributes(), vertex::Buffers());
// Get the current viewport.
glGetIntegerv(GL_VIEWPORT, (GLint *) &state.viewport.x);
@@ -647,111 +647,52 @@ void OpenGL::drawElements(GLenum mode, GLsizei count, GLenum type, const void *i
++stats.drawCalls;
}
void OpenGL::useVertexAttribArrays(uint32 arraybits, uint32 instancedbits)
void OpenGL::setVertexAttributes(const vertex::Attributes &attributes, const vertex::Buffers &buffers)
{
uint32 diff = arraybits ^ state.enabledAttribArrays;
uint32 instancediff = instancedbits ^ state.instancedAttribArrays;
uint32 enablediff = attributes.enablebits ^ state.enabledAttribArrays;
uint32 instancediff = attributes.instancebits ^ state.instancedAttribArrays;
if (diff == 0 && instancediff == 0)
return;
// Max 32 attributes. As of when this was written, no GL driver exposes more
// than 32. Lets hope that doesn't change...
for (uint32 i = 0; i < 32; i++)
for (uint32 i = 0; i < vertex::Attributes::MAX; i++)
{
uint32 bit = 1u << i;
if (diff & bit)
if (enablediff & bit)
{
if (arraybits & bit)
if (attributes.enablebits & bit)
glEnableVertexAttribArray(i);
else
glDisableVertexAttribArray(i);
}
if (instancediff & bit)
glVertexAttribDivisor(i, (instancedbits & bit) != 0 ? 1 : 0);
glVertexAttribDivisor(i, (attributes.instancebits & bit) != 0 ? 1 : 0);
if (attributes.enablebits & bit)
{
const auto &attrib = attributes.attribs[i];
const auto &bufferinfo = buffers.info[attrib.bufferindex];
GLboolean normalized = GL_FALSE;
GLenum gltype = getGLVertexDataType(attrib.type, normalized);
const void *offsetpointer = BUFFER_OFFSET(bufferinfo.offset + attrib.offsetfromvertex);
bindBuffer(BUFFER_VERTEX, (GLuint) bufferinfo.buffer->getHandle());
glVertexAttribPointer(i, attrib.components, gltype, normalized, attrib.stride, offsetpointer);
}
}
state.enabledAttribArrays = arraybits;
state.instancedAttribArrays = instancedbits;
state.enabledAttribArrays = attributes.enablebits;
state.instancedAttribArrays = attributes.instancebits;
// glDisableVertexAttribArray will make the constant value for a vertex
// attribute undefined. We rely on the per-vertex color attribute being
// white when no per-vertex color is used, so we set it here.
// FIXME: Is there a better place to do this?
if ((diff & ATTRIBFLAG_COLOR) && !(arraybits & ATTRIBFLAG_COLOR))
if ((enablediff & ATTRIBFLAG_COLOR) && !(attributes.enablebits & ATTRIBFLAG_COLOR))
glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
}
void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_t offset)
{
using namespace vertex;
switch (format)
{
case CommonFormat::NONE:
break;
case CommonFormat::XYf:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
break;
case CommonFormat::XYZf:
glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
break;
case CommonFormat::RGBAub:
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset));
break;
case CommonFormat::STf_RGBAub:
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(STf_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(STf_RGBAub, color.r)));
break;
case CommonFormat::STPf_RGBAub:
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(STPf_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(STPf_RGBAub, color.r)));
break;
case CommonFormat::XYf_STf:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, s)));
break;
case CommonFormat::XYf_STPf:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, s)));
break;
case CommonFormat::XYf_STf_RGBAub:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, color.r)));
break;
case CommonFormat::XYf_STus_RGBAub:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, color.r)));
break;
case CommonFormat::XYf_STPf_RGBAub:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, color.r)));
break;
}
}
void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t offset)
{
setVertexPointers(format, getFormatStride(format), offset);
}
void OpenGL::setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t offset)
{
bindBuffer(BUFFER_VERTEX, (GLuint) buffer->getHandle());
setVertexPointers(format, offset);
}
void OpenGL::setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t stride, size_t offset)
{
bindBuffer(BUFFER_VERTEX, (GLuint) buffer->getHandle());
setVertexPointers(format, stride, offset);
}
void OpenGL::clearDepth(double value)
{
if (GLAD_ES_VERSION_2_0)
+2 -17
View File
@@ -46,6 +46,7 @@ namespace love
namespace graphics
{
class Resource;
class Buffer;
namespace opengl
@@ -206,23 +207,7 @@ public:
void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instancecount = 1);
void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount = 1);
/**
* Sets the enabled vertex attribute arrays based on the specified attribute
* bits. Each bit in the uint32 represents an enabled attribute array index.
* For example, useVertexAttribArrays(1 << 0) will enable attribute index 0.
* See the VertexAttribFlags enum for the standard vertex attributes.
* This function *must* be used instead of glEnable/DisableVertexAttribArray.
**/
void useVertexAttribArrays(uint32 arraybits, uint32 instancedbits = 0);
/**
* Calls glVertexAttribPointer appropriately for each attribute used in the
* specified format.
**/
void setVertexPointers(vertex::CommonFormat format, size_t offset);
void setVertexPointers(vertex::CommonFormat format, size_t stride, size_t offset);
void setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t offset);
void setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t stride, size_t offset);
void setVertexAttributes(const vertex::Attributes &attributes, const vertex::Buffers &buffers);
/**
* Wrapper for glClearDepth and glClearDepthf.
@@ -50,17 +50,14 @@ ParticleSystem *ParticleSystem::clone()
return new ParticleSystem(*this);
}
void ParticleSystem::drawInternal() const
void ParticleSystem::drawInternal(const vertex::Attributes &attributes, const vertex::Buffers &buffers) const
{
using namespace vertex;
OpenGL::TempDebugGroup debuggroup("ParticleSystem draw");
gl.bindTextureToUnit(texture, 0, false);
gl.prepareDraw();
gl.useVertexAttribArrays(getFormatFlags(CommonFormat::XYf_STf_RGBAub));
gl.setVertexPointers(CommonFormat::XYf_STf_RGBAub, buffer, 0);
gl.setVertexAttributes(attributes, buffers);
GLsizei count = (GLsizei) quadIndices.getIndexCount(getCount());
GLenum gltype = OpenGL::getGLIndexDataType(quadIndices.getType());
+1 -1
View File
@@ -47,7 +47,7 @@ public:
private:
void drawInternal() const override;
void drawInternal(const vertex::Attributes &attributes, const vertex::Buffers &buffers) const override;
}; // ParticleSystem
+2 -23
View File
@@ -51,32 +51,11 @@ SpriteBatch::~SpriteBatch()
{
}
void SpriteBatch::drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount)
void SpriteBatch::drawInternal(size_t indexbytestart, size_t indexcount, const vertex::Attributes &attributes, const vertex::Buffers &buffers)
{
OpenGL::TempDebugGroup debuggroup("SpriteBatch draw");
uint32 enabledattribs = getFormatFlags(format);
// We want attached attributes to override local attributes, so we should
// call this before binding attached attributes.
gl.setVertexPointers(format, array_buf, vertex_stride, 0);
for (const auto &it : attached_attributes)
{
Mesh *mesh = it.second.mesh.get();
// We have to do this check here as wll because setBufferSize can be
// called after attachAttribute.
if (mesh->getVertexCount() < (size_t) next * 4)
throw love::Exception("Mesh with attribute '%s' attached to this SpriteBatch has too few vertices", it.first.c_str());
int location = mesh->bindAttributeToShaderInput(it.second.index, it.first);
if (location >= 0)
enabledattribs |= 1u << (uint32) location;
}
gl.useVertexAttribArrays(enabledattribs);
gl.setVertexAttributes(attributes, buffers);
gl.bindTextureToUnit(texture, 0, false);
gl.prepareDraw();
+1 -1
View File
@@ -39,7 +39,7 @@ public:
protected:
void drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount) override;
void drawInternal(size_t indexbytestart, size_t indexcount, const vertex::Attributes &attributes, const vertex::Buffers &buffers) override;
}; // SpriteBatch
+1 -3
View File
@@ -45,9 +45,7 @@ void Text::drawInternal(const std::vector<Font::DrawCommand> &commands) const
OpenGL::TempDebugGroup debuggroup("Text object draw");
gl.prepareDraw();
gl.setVertexPointers(Font::vertexFormat, vbo, 0);
gl.useVertexAttribArrays(vertex::getFormatFlags(Font::vertexFormat));
gl.setVertexAttributes(vertexAttributes, vertexBuffers);
const GLenum gltype = OpenGL::getGLIndexDataType(quadIndices.getType());
const size_t elemsize = quadIndices.getElementSize();