mirror of
https://github.com/love2d/love.git
synced 2026-08-17 02:58:31 +02:00
Restructure some internal vertex buffer binding code to be closer to how graphics APIs actually behave.
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user