Restructure some internal vertex buffer binding code to be closer to how graphics APIs actually behave.

This commit is contained in:
Alex Szpakowski
2019-08-25 16:50:15 -03:00
parent 932068e777
commit 55d4dc0f9e
12 changed files with 117 additions and 92 deletions
+6 -5
View File
@@ -343,7 +343,7 @@ void Graphics::draw(const DrawIndexedCommand &cmd)
++drawCalls;
}
static inline void advanceVertexOffsets(const vertex::Attributes &attributes, vertex::Buffers &buffers, int vertexcount)
static inline void advanceVertexOffsets(const vertex::Attributes &attributes, vertex::BufferBindings &buffers, int vertexcount)
{
// TODO: Figure out a better way to avoid touching the same buffer multiple
// times, if multiple attributes share the buffer.
@@ -356,16 +356,17 @@ static inline void advanceVertexOffsets(const vertex::Attributes &attributes, ve
auto &attrib = attributes.attribs[i];
uint32 bufferbit = 1u << attrib.bufferindex;
uint32 bufferbit = 1u << attrib.bufferIndex;
if ((touchedbuffers & bufferbit) == 0)
{
touchedbuffers |= bufferbit;
buffers.info[attrib.bufferindex].offset += attrib.stride * vertexcount;
const auto &layout = attributes.bufferLayouts[attrib.bufferIndex];
buffers.info[attrib.bufferIndex].offset += layout.stride * vertexcount;
}
}
}
void Graphics::drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::Buffers &buffers, love::graphics::Texture *texture)
void Graphics::drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, love::graphics::Texture *texture)
{
const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
@@ -394,7 +395,7 @@ void Graphics::drawQuads(int start, int count, const vertex::Attributes &attribu
}
else
{
vertex::Buffers bufferscopy = buffers;
vertex::BufferBindings bufferscopy = buffers;
if (start > 0)
advanceVertexOffsets(attributes, bufferscopy, start * 4);
+1 -1
View File
@@ -73,7 +73,7 @@ public:
void draw(const DrawCommand &cmd) override;
void draw(const DrawIndexedCommand &cmd) override;
void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::Buffers &buffers, Texture *texture) override;
void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture) override;
void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) override;
void clear(const std::vector<OptionalColorf> &colors, OptionalInt stencil, OptionalDouble depth) override;
+27 -16
View File
@@ -195,7 +195,7 @@ void OpenGL::setupContext()
else
state.instancedAttribArrays = 0;
setVertexAttributes(vertex::Attributes(), vertex::Buffers());
setVertexAttributes(vertex::Attributes(), vertex::BufferBindings());
// Get the current viewport.
glGetIntegerv(GL_VIEWPORT, (GLint *) &state.viewport.x);
@@ -697,49 +697,60 @@ void OpenGL::deleteBuffer(GLuint buffer)
}
}
void OpenGL::setVertexAttributes(const vertex::Attributes &attributes, const vertex::Buffers &buffers)
void OpenGL::setVertexAttributes(const vertex::Attributes &attributes, const vertex::BufferBindings &buffers)
{
uint32 enablediff = attributes.enablebits ^ state.enabledAttribArrays;
uint32 instancediff = attributes.instancebits ^ state.instancedAttribArrays;
uint32 enablediff = attributes.enableBits ^ state.enabledAttribArrays;
uint32 instanceattribbits = 0;
uint32 allbits = attributes.enableBits | state.enabledAttribArrays;
for (uint32 i = 0; i < vertex::Attributes::MAX; i++)
uint32 i = 0;
while (allbits)
{
uint32 bit = 1u << i;
if (enablediff & bit)
{
if (attributes.enablebits & bit)
if (attributes.enableBits & bit)
glEnableVertexAttribArray(i);
else
glDisableVertexAttribArray(i);
}
if (instancediff & bit)
glVertexAttribDivisor(i, (attributes.instancebits & bit) != 0 ? 1 : 0);
if (attributes.enablebits & bit)
if (attributes.enableBits & bit)
{
const auto &attrib = attributes.attribs[i];
const auto &bufferinfo = buffers.info[attrib.bufferindex];
const auto &layout = attributes.bufferLayouts[attrib.bufferIndex];
const auto &bufferinfo = buffers.info[attrib.bufferIndex];
uint32 bufferbit = 1u << attrib.bufferIndex;
uint32 divisor = (attributes.instanceBits & bufferbit) != 0 ? 1 : 0;
uint32 divisorbit = divisor << i;
instanceattribbits |= divisorbit;
if ((state.enabledAttribArrays & bit) ^ divisorbit)
glVertexAttribDivisor(i, divisor);
GLboolean normalized = GL_FALSE;
GLenum gltype = getGLVertexDataType(attrib.type, normalized);
const void *offsetpointer = reinterpret_cast<void*>(bufferinfo.offset + attrib.offsetfromvertex);
const void *offsetpointer = reinterpret_cast<void*>(bufferinfo.offset + attrib.offsetFromVertex);
bindBuffer(BUFFER_VERTEX, (GLuint) bufferinfo.buffer->getHandle());
glVertexAttribPointer(i, attrib.components, gltype, normalized, attrib.stride, offsetpointer);
glVertexAttribPointer(i, attrib.components, gltype, normalized, layout.stride, offsetpointer);
}
i++;
allbits >>= 1;
}
state.enabledAttribArrays = attributes.enablebits;
state.instancedAttribArrays = attributes.instancebits;
state.enabledAttribArrays = attributes.enableBits;
state.instancedAttribArrays = instanceattribbits | (state.instancedAttribArrays & (~attributes.enableBits));
// 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 ((enablediff & ATTRIBFLAG_COLOR) && !(attributes.enablebits & ATTRIBFLAG_COLOR))
if ((enablediff & ATTRIBFLAG_COLOR) && !(attributes.enableBits & ATTRIBFLAG_COLOR))
glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
}
+1 -1
View File
@@ -237,7 +237,7 @@ public:
/**
* Set all vertex attribute state.
**/
void setVertexAttributes(const vertex::Attributes &attributes, const vertex::Buffers &buffers);
void setVertexAttributes(const vertex::Attributes &attributes, const vertex::BufferBindings &buffers);
/**
* Wrapper for glCullFace which eliminates redundant state setting.