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
+1
View File
@@ -527,6 +527,7 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
src/modules/graphics/Polyline.h
src/modules/graphics/Quad.cpp
src/modules/graphics/Quad.h
src/modules/graphics/Resource.h
src/modules/graphics/Shader.cpp
src/modules/graphics/Shader.h
src/modules/graphics/ShaderStage.cpp
@@ -1730,6 +1730,7 @@
FA0B7CCC1A95902C000E1D17 /* wrap_Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Window.h; sourceTree = "<group>"; };
FA0B7EF01A959D2C000E1D17 /* ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios.h; sourceTree = "<group>"; };
FA0B7EF11A959D2C000E1D17 /* ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ios.mm; sourceTree = "<group>"; };
FA10DD7B1F9EC24E00E1FE3D /* Resource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Resource.h; sourceTree = "<group>"; };
FA1557BF1CE90A2C00AFF582 /* tinyexr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinyexr.h; sourceTree = "<group>"; };
FA1557C11CE90BD200AFF582 /* EXRHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXRHandler.cpp; sourceTree = "<group>"; };
FA1557C21CE90BD200AFF582 /* EXRHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXRHandler.h; sourceTree = "<group>"; };
@@ -2725,6 +2726,7 @@
FA0B7B9C1A95902C000E1D17 /* Polyline.h */,
FA0B7BBC1A95902C000E1D17 /* Quad.cpp */,
FA0B7BBD1A95902C000E1D17 /* Quad.h */,
FA10DD7B1F9EC24E00E1FE3D /* Resource.h */,
FA1BA0AF1E16FD0800AA2803 /* Shader.cpp */,
FA1BA0B01E16FD0800AA2803 /* Shader.h */,
FA3C5E401F8C368C0003C579 /* ShaderStage.cpp */,
+2 -6
View File
@@ -24,6 +24,7 @@
#include "common/config.h"
#include "common/int.h"
#include "vertex.h"
#include "Resource.h"
// C
#include <stddef.h>
@@ -38,7 +39,7 @@ class Graphics;
/**
* A block of GPU-owned memory. Currently meant for internal use.
**/
class Buffer
class Buffer : public Resource
{
public:
@@ -91,11 +92,6 @@ public:
**/
virtual void setMappedRangeModified(size_t offset, size_t size) = 0;
/**
* Gets the backend-specific handle for this Buffer.
**/
virtual ptrdiff_t getHandle() const = 0;
/**
* Fill a portion of the buffer with data and marks the range as modified.
*
+31 -11
View File
@@ -323,6 +323,8 @@ void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::strin
auto it = attachedAttributes.find(name);
if (it != attachedAttributes.end())
oldattrib = it->second;
else if (attachedAttributes.size() + 1 > vertex::Attributes::MAX)
throw love::Exception("A maximum of %d attributes can be attached at once.", vertex::Attributes::MAX);
newattrib.mesh = mesh;
newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true;
@@ -585,30 +587,48 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount)
if (Shader::current && texture.get())
Shader::current->checkMainTexture(texture);
uint32 enabledattribs = 0;
uint32 instancedattribs = 0;
vertex::Attributes attributes;
vertex::Buffers buffers;
int activebuffers = 0;
for (const auto &attrib : attachedAttributes)
{
if (!attrib.second.enabled)
continue;
love::graphics::Mesh *mesh = attrib.second.mesh;
int location = mesh->bindAttributeToShaderInput(attrib.second.index, attrib.first);
Mesh *mesh = attrib.second.mesh;
int attributeindex = -1;
if (location >= 0)
// 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(attrib.first.c_str(), builtinattrib))
attributeindex = (int) builtinattrib;
else if (Shader::current)
attributeindex = Shader::current->getVertexAttributeIndex(attrib.first);
if (attributeindex >= 0)
{
uint32 bit = 1u << (uint32) location;
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
mesh->vbo->unmap();
enabledattribs |= bit;
const auto &formats = mesh->getVertexFormat();
const auto &format = formats[attrib.second.index];
if (attrib.second.step == STEP_PER_INSTANCE)
instancedattribs |= bit;
uint16 offset = (uint16) mesh->getAttributeOffset(attrib.second.index);
uint16 stride = (uint16) mesh->getVertexStride();
attributes.set(attributeindex, format.type, format.components, offset, stride, activebuffers, attrib.second.step);
// TODO: Ideally we want to reuse buffers with the same stride+step.
buffers.set(activebuffers, mesh->vbo, 0);
activebuffers++;
}
}
// Not supported on all platforms or GL versions, I believe.
if (!(enabledattribs & ATTRIBFLAG_POS))
if (!attributes.isEnabled(ATTRIB_POS))
throw love::Exception("Mesh must have an enabled VertexPosition attribute to be drawn.");
bool useindexbuffer = useIndexBuffer && ibo != nullptr && indexCount > 0;
@@ -643,7 +663,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount)
Graphics::TempTransform transform(gfx, m);
if (count > 0)
drawInternal(start, count, instancecount, useindexbuffer, enabledattribs, instancedattribs);
drawInternal(start, count, instancecount, useindexbuffer, attributes, buffers);
}
} // graphics
+3 -3
View File
@@ -167,8 +167,6 @@ public:
void setDrawRange();
bool getDrawRange(int &start, int &count) const;
virtual int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) = 0;
// Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override;
@@ -178,6 +176,8 @@ public:
protected:
friend class SpriteBatch;
struct AttachedAttribute
{
Mesh *mesh;
@@ -190,7 +190,7 @@ protected:
void calculateAttributeSizes();
size_t getAttributeOffset(size_t attribindex) const;
virtual void drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const = 0;
virtual void drawInternal(int start, int count, int instancecount, bool useindexbuffer, const vertex::Attributes &attributes, const vertex::Buffers &buffers) const = 0;
std::vector<AttribFormat> vertexFormat;
std::vector<size_t> attributeSizes;
+6 -1
View File
@@ -93,6 +93,7 @@ ParticleSystem::ParticleSystem(Graphics *gfx, Texture *texture, uint32 size)
, offset(float(texture->getWidth())*0.5f, float(texture->getHeight())*0.5f)
, defaultOffset(true)
, relativeRotation(false)
, vertexAttributes(vertex::CommonFormat::XYf_STf_RGBAub, 0)
, buffer(nullptr)
, quadIndices(gfx, size)
{
@@ -154,6 +155,7 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
, colors(p.colors)
, quads(p.quads)
, relativeRotation(p.relativeRotation)
, vertexAttributes(p.vertexAttributes)
, buffer(nullptr)
, quadIndices(p.quadIndices)
{
@@ -1089,8 +1091,11 @@ void ParticleSystem::draw(Graphics *gfx, const Matrix4 &m)
buffer->unmap();
vertex::Buffers vertexbuffers;
vertexbuffers.set(0, buffer, 0);
Graphics::TempTransform transform(gfx, m);
drawInternal();
drawInternal(vertexAttributes, vertexbuffers);
}
bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out)
+2 -1
View File
@@ -584,7 +584,7 @@ protected:
int quadIndex;
};
virtual void drawInternal() const = 0;
virtual void drawInternal(const vertex::Attributes &attributes, const vertex::Buffers &buffers) const = 0;
// Pointer to the beginning of the allocated memory.
Particle *pMem;
@@ -687,6 +687,7 @@ protected:
bool relativeRotation;
const vertex::Attributes vertexAttributes;
Buffer *buffer;
// Vertex index buffer.
+40
View File
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2006-2017 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#pragma once
#include <stddef.h>
namespace love
{
namespace graphics
{
class Resource
{
public:
virtual ~Resource() {}
virtual ptrdiff_t getHandle() const = 0;
}; // Resource
} // graphics
} // love
+2 -3
View File
@@ -25,6 +25,7 @@
#include "common/StringMap.h"
#include "Texture.h"
#include "ShaderStage.h"
#include "Resource.h"
// STL
#include <string>
@@ -45,7 +46,7 @@ namespace graphics
class Graphics;
// A GLSL shader
class Shader : public Object
class Shader : public Object, public Resource
{
public:
@@ -185,8 +186,6 @@ public:
void checkMainTextureType(TextureType textype, bool isDepthSampler) const;
void checkMainTexture(Texture *texture) const;
virtual ptrdiff_t getHandle() const = 0;
static bool validate(ShaderStage *vertex, ShaderStage *pixel, std::string &err);
static bool initialize();
+2 -3
View File
@@ -23,6 +23,7 @@
#include "common/Object.h"
#include "common/StringMap.h"
#include "Volatile.h"
#include "Resource.h"
#include <stddef.h>
#include <string>
@@ -39,7 +40,7 @@ namespace graphics
class Graphics;
class ShaderStage : public love::Object, public Volatile
class ShaderStage : public love::Object, public Volatile, public Resource
{
public:
@@ -57,8 +58,6 @@ public:
const std::string &getSource() const { return source; }
const std::string &getWarnings() const { return warnings; }
glslang::TShader *getGLSLangShader() const { return glslangShader; }
virtual ptrdiff_t getHandle() const = 0;
static bool getConstant(const char *in, StageType &out);
static bool getConstant(StageType in, const char *&out);
+48 -7
View File
@@ -334,14 +334,55 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
CommonFormat format = vertex_format;
Attributes attributes;
Buffers buffers;
if (!color_active)
{
if (format == CommonFormat::XYf_STPf_RGBAub)
format = CommonFormat::XYf_STPf;
else
format = CommonFormat::XYf_STf;
buffers.set(0, array_buf, 0);
attributes.setCommonFormat(vertex_format, 0);
if (!color_active)
attributes.disable(ATTRIB_COLOR);
}
int activebuffers = 1;
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 attributeindex = -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(it.first.c_str(), builtinattrib))
attributeindex = (int) builtinattrib;
else if (Shader::current)
attributeindex = Shader::current->getVertexAttributeIndex(it.first);
if (attributeindex >= 0)
{
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
mesh->vbo->unmap();
const auto &formats = mesh->getVertexFormat();
const auto &format = formats[it.second.index];
uint16 offset = (uint16) mesh->getAttributeOffset(it.second.index);
uint16 stride = (uint16) mesh->getVertexStride();
attributes.set(attributeindex, format.type, format.components, offset, stride, activebuffers);
// TODO: Ideally we want to reuse buffers with the same stride+step.
buffers.set(activebuffers, mesh->vbo, 0);
activebuffers++;
}
}
int start = std::min(std::max(0, range_start), next - 1);
@@ -358,7 +399,7 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
Graphics::TempTransform transform(gfx, m);
if (count > 0)
drawInternal(format, indexbytestart, indexcount);
drawInternal(indexbytestart, indexcount, attributes, buffers);
}
} // graphics
+1 -1
View File
@@ -123,7 +123,7 @@ protected:
**/
void setBufferSize(int newsize);
virtual void drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount) = 0;
virtual void drawInternal(size_t indexbytestart, size_t indexcount, const vertex::Attributes &attributes, const vertex::Buffers &buffers) = 0;
StrongRef<Texture> texture;
+2 -3
View File
@@ -23,6 +23,7 @@
// LOVE
#include "common/int.h"
#include "vertex.h"
#include "Resource.h"
// C
#include <cstddef>
@@ -32,7 +33,7 @@ namespace love
namespace graphics
{
class StreamBuffer
class StreamBuffer : public Resource
{
public:
@@ -61,8 +62,6 @@ public:
virtual void nextFrame() {}
virtual ptrdiff_t getHandle() const = 0;
protected:
StreamBuffer(BufferType mode, size_t size);
+3
View File
@@ -32,6 +32,7 @@ love::Type Text::type("Text", &Drawable::type);
Text::Text(Graphics *gfx, Font *font, const std::vector<Font::ColoredString> &text)
: font(font)
, vertexAttributes(Font::vertexFormat, 0)
, vbo(nullptr)
, quadIndices(gfx, 20)
, vert_offset(0)
@@ -68,6 +69,8 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
delete vbo;
vbo = new_vbo;
vertexBuffers.set(0, vbo, 0);
}
if (vbo != nullptr && datasize > 0)
+4
View File
@@ -86,6 +86,10 @@ protected:
virtual void drawInternal(const std::vector<Font::DrawCommand> &commands) const = 0;
StrongRef<Font> font;
vertex::Attributes vertexAttributes;
vertex::Buffers vertexBuffers;
Buffer *vbo;
QuadIndices quadIndices;
+2 -3
View File
@@ -32,6 +32,7 @@
#include "Quad.h"
#include "vertex.h"
#include "depthstencil.h"
#include "Resource.h"
// C
#include <stddef.h>
@@ -56,7 +57,7 @@ enum TextureType
* Base class for 2D textures. All textures can be drawn with Quads, have a
* width and height, and have filter and wrap modes.
**/
class Texture : public Drawable
class Texture : public Drawable, public Resource
{
public:
@@ -145,8 +146,6 @@ public:
Quad *getQuad() const;
virtual ptrdiff_t getHandle() const = 0;
static bool validateFilter(const Filter &f, bool mipmapsAllowed);
static int getMipmapCount(int w, int h);
+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();
+53
View File
@@ -37,6 +37,8 @@ static_assert(sizeof(XYf_STf_RGBAub) == sizeof(float)*2 + sizeof(float)*2 + size
static_assert(sizeof(XYf_STus_RGBAub) == sizeof(float)*2 + sizeof(uint16)*2 + sizeof(Color), "sizeof(XYf_STus_RGBAub) incorrect!");
static_assert(sizeof(XYf_STPf_RGBAub) == sizeof(float)*2 + sizeof(float)*3 + sizeof(Color), "sizeof(XYf_STPf_RGBAub) incorrect!");
static_assert(sizeof(AttributeInfo) == sizeof(uint64), "sizeof(AttributeInfo) incorrect!");
size_t getFormatStride(CommonFormat format)
{
switch (format)
@@ -222,6 +224,57 @@ void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount,
fillIndicesT(mode, vertexStart, vertexCount, indices);
}
void Attributes::setCommonFormat(CommonFormat format, uint8 bufferindex)
{
uint16 stride = (uint16) getFormatStride(format);
switch (format)
{
case CommonFormat::NONE:
break;
case CommonFormat::XYf:
set(ATTRIB_POS, DATA_FLOAT, 2, 0, stride, bufferindex);
break;
case CommonFormat::XYZf:
set(ATTRIB_POS, DATA_FLOAT, 3, 0, stride, bufferindex);
break;
case CommonFormat::RGBAub:
set(ATTRIB_COLOR, DATA_UNORM8, 4, 0, stride, bufferindex);
break;
case CommonFormat::STf_RGBAub:
set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, 0, stride, bufferindex);
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 2), stride, bufferindex);
break;
case CommonFormat::STPf_RGBAub:
set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, 0, stride, bufferindex);
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 3), stride, bufferindex);
break;
case CommonFormat::XYf_STf:
set(ATTRIB_POS, DATA_FLOAT, 2, 0, stride, bufferindex);
set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, uint16(sizeof(float) * 2), stride, bufferindex);
break;
case CommonFormat::XYf_STPf:
set(ATTRIB_POS, DATA_FLOAT, 2, 0, stride, bufferindex);
set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, uint16(sizeof(float) * 2), stride, bufferindex);
break;
case CommonFormat::XYf_STf_RGBAub:
set(ATTRIB_POS, DATA_FLOAT, 2, 0, stride, bufferindex);
set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, uint16(sizeof(float) * 2), stride, bufferindex);
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 4), stride, bufferindex);
break;
case CommonFormat::XYf_STus_RGBAub:
set(ATTRIB_POS, DATA_FLOAT, 2, 0, stride, bufferindex);
set(ATTRIB_TEXCOORD, DATA_UNORM16, 2, uint16(sizeof(float) * 2), stride, bufferindex);
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 2 + sizeof(uint16) * 2), stride, bufferindex);
break;
case CommonFormat::XYf_STPf_RGBAub:
set(ATTRIB_POS, DATA_FLOAT, 2, 0, stride, bufferindex);
set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, uint16(sizeof(float) * 2), stride, bufferindex);
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 5), stride, bufferindex);
break;
}
}
static StringMap<VertexAttribID, ATTRIB_MAX_ENUM>::Entry attribNameEntries[] =
{
{ "VertexPosition", ATTRIB_POS },
+115
View File
@@ -34,6 +34,8 @@ namespace love
namespace graphics
{
class Resource;
// Vertex attribute indices used in shaders by LOVE. The values map to OpenGL
// generic vertex attribute indices.
enum VertexAttribID
@@ -172,6 +174,119 @@ struct XYf_STPf_RGBAub
Color color;
};
struct Buffers
{
static const unsigned int MAX = 32;
uint32 usebits = 0;
struct
{
Resource *buffer;
size_t offset;
} info[MAX];
void set(unsigned int index, Resource *r, size_t offset)
{
usebits |= (1u << index);
info[index] = {r, offset};
}
void disable(unsigned int index) { usebits &= (1u << index); }
void clear() { usebits = 0; }
};
struct AttributeInfo
{
uint8 bufferindex;
DataType type : 8;
uint16 components;
uint16 offsetfromvertex;
uint16 stride;
};
struct Attributes
{
static const unsigned int MAX = 32;
uint32 enablebits = 0;
uint32 instancebits = 0;
union
{
AttributeInfo attribs[MAX];
uint64 data[MAX];
};
Attributes() {}
Attributes(CommonFormat format, uint8 bufferindex)
{
setCommonFormat(format, bufferindex);
}
void set(unsigned int index, DataType type, uint16 components, uint16 offsetfromvertex, uint16 stride, uint8 bufferindex, AttributeStep step = STEP_PER_VERTEX)
{
uint32 bit = (1u << index);
enablebits |= bit;
if (step == STEP_PER_INSTANCE)
instancebits |= bit;
else
instancebits &= ~bit;
attribs[index].bufferindex = bufferindex;
attribs[index].type = type;
attribs[index].components = components;
attribs[index].offsetfromvertex = offsetfromvertex;
attribs[index].stride = stride;
}
void disable(unsigned int index)
{
enablebits &= ~(1u << index);
}
void clear()
{
enablebits = 0;
}
bool isEnabled(unsigned int index) const
{
return (enablebits & (1u << index)) != 0;
}
AttributeStep getStep(unsigned int index) const
{
return (instancebits & (1u << index)) != 0 ? STEP_PER_INSTANCE : STEP_PER_VERTEX;
}
void setCommonFormat(CommonFormat format, uint8 bufferindex);
bool operator == (const Attributes &other) const
{
if (enablebits != other.enablebits)
return false;
uint32 instancediff = instancebits ^ other.instancebits;
for (unsigned int i = 0; i < MAX; i++)
{
if (isEnabled(i))
{
if (instancediff & (1u << i))
return false;
if (data[i] != other.data[i])
return false;
}
}
return true;
}
};
size_t getFormatStride(CommonFormat format);
uint32 getFormatFlags(CommonFormat format);