diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index d57416564..dfe6fedf5 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -28,56 +28,62 @@ namespace graphics love::Type Buffer::type("GraphicsBuffer", &Object::type); -Buffer::Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) +Buffer::Buffer(const Settings &settings, const void */*data*/, size_t size) : arrayLength(0) , arrayStride(0) , size(size) - , typeFlags(typeflags) - , usage(usage) - , mapFlags(mapflags) + , typeFlags(settings.typeFlags) + , usage(settings.usage) + , mapFlags(settings.mapFlags) , mapped(false) { } -Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &dataMembers, size_t arraylength) - : Buffer(0, settings.typeFlags, settings.usage, settings.mapFlags) +Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &bufferformat, const void *data, size_t size, size_t arraylength) + : Buffer(settings, data, size) { - if (dataMembers.size() == 0) - throw love::Exception("Data format must contain values."); + if (size == 0 && arraylength == 0) + throw love::Exception("Size or array length must be specified."); - this->dataMembers = dataMembers; + if (bufferformat.size() == 0) + throw love::Exception("Data format must contain values."); bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3]; - bool uniformbuffer = settings.typeFlags & BUFFERFLAG_UNIFORM; - bool indexbuffer = settings.typeFlags & BUFFERFLAG_INDEX; - bool vertexbuffer = settings.typeFlags & BUFFERFLAG_VERTEX; - bool ssbuffer = settings.typeFlags & BUFFERFLAG_SHADER_STORAGE; - - if (indexbuffer && dataMembers.size() > 1) - throw love::Exception("test"); + bool uniformbuffer = settings.typeFlags & TYPEFLAG_UNIFORM; + bool indexbuffer = settings.typeFlags & TYPEFLAG_INDEX; + bool vertexbuffer = settings.typeFlags & TYPEFLAG_VERTEX; + bool ssbuffer = settings.typeFlags & TYPEFLAG_SHADER_STORAGE; size_t offset = 0; size_t stride = 0; - for (const auto &member : dataMembers) + for (const auto &decl : bufferformat) { - DataFormat format = member.format; - const DataFormatInfo &info = getDataFormatInfo(format); + DataMember member(decl); + + DataFormat format = member.decl.format; + const DataFormatInfo &info = member.info; if (indexbuffer) { if (format != DATAFORMAT_UINT16 && format != DATAFORMAT_UINT32) throw love::Exception("Index buffers only support uint16 and uint32 data types."); + + if (bufferformat.size() > 1) + throw love::Exception("Index buffers only support a single value per element."); } if (vertexbuffer) { + if (decl.arraySize > 0) + throw love::Exception("Arrays are not supported in vertex buffers."); + if (info.isMatrix) - throw love::Exception("matrix types are not supported in vertex buffers."); + throw love::Exception("Matrix types are not supported in vertex buffers."); if (info.baseType == DATA_BASETYPE_BOOL) - throw love::Exception("bool types are not supported in vertex buffers."); + throw love::Exception("Bool types are not supported in vertex buffers."); if ((info.baseType == DATA_BASETYPE_INT || info.baseType == DATA_BASETYPE_UINT) && !supportsGLSL3) throw love::Exception("Integer vertex attribute data types require GLSL 3 support."); @@ -88,11 +94,30 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector 0) + size += stride - remainder; + arraylength = size / stride; + } + else + { + size = arraylength * stride; } - this->arrayLength = arraylength; this->arrayStride = stride; - this->size = stride * arraylength; + this->arrayLength = arraylength; + this->size = size; } Buffer::~Buffer() @@ -103,7 +128,7 @@ int Buffer::getDataMemberIndex(const std::string &name) const { for (size_t i = 0; i < dataMembers.size(); i++) { - if (dataMembers[i].name == name) + if (dataMembers[i].decl.name == name) return (int) i; } diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 857444fe0..12fc2659a 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -40,7 +40,7 @@ namespace graphics class Graphics; /** - * A block of GPU-owned memory. Currently meant for internal use. + * A block of GPU-owned memory. **/ class Buffer : public love::Object, public Resource { @@ -50,30 +50,65 @@ public: enum MapFlags { + MAP_NONE = 0, MAP_EXPLICIT_RANGE_MODIFY = (1 << 0), // see setMappedRangeModified. MAP_READ = (1 << 1), }; - struct DataMember + enum TypeFlags + { + TYPEFLAG_NONE = 0, + TYPEFLAG_VERTEX = 1 << BUFFERTYPE_VERTEX, + TYPEFLAG_INDEX = 1 << BUFFERTYPE_INDEX, + TYPEFLAG_UNIFORM = 1 << BUFFERTYPE_UNIFORM, + TYPEFLAG_SHADER_STORAGE = 1 << BUFFERTYPE_SHADER_STORAGE, + }; + + struct DataDeclaration { std::string name; DataFormat format; int arraySize; + + DataDeclaration(const std::string &name, DataFormat format, int arraySize = 0) + : name(name) + , format(format) + , arraySize(arraySize) + {} + }; + + struct DataMember + { + DataDeclaration decl; + DataFormatInfo info; + size_t offset; + + DataMember(const DataDeclaration &decl) + : decl(decl) + , info(getDataFormatInfo(decl.format)) + , offset(0) + {} }; struct Settings { - BufferTypeFlags typeFlags; + TypeFlags typeFlags; MapFlags mapFlags; BufferUsage usage; + + Settings(uint32 typeflags, uint32 mapflags, BufferUsage usage) + : typeFlags((TypeFlags)typeflags) + , mapFlags((MapFlags)mapflags) + , usage(usage) + {} }; - Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags); - Buffer(Graphics *gfx, const Settings &settings, const std::vector &members, size_t arraylength); + Buffer(const Settings &settings, const void *data, size_t size); + Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength); virtual ~Buffer(); size_t getSize() const { return size; } - BufferTypeFlags getTypeFlags() const { return typeFlags; } + TypeFlags getTypeFlags() const { return typeFlags; } BufferUsage getUsage() const { return usage; } bool isMapped() const { return mapped; } uint32 getMapFlags() const { return mapFlags; } @@ -82,7 +117,7 @@ public: size_t getArrayStride() const { return arrayStride; } const std::vector &getDataMembers() const { return dataMembers; } const DataMember &getDataMember(int index) const { return dataMembers[index]; } - size_t getMemberOffset(int index) const { return memberOffsets[index]; } + size_t getMemberOffset(int index) const { return dataMembers[index].offset; } int getDataMemberIndex(const std::string &name) const; /** @@ -146,7 +181,6 @@ public: protected: std::vector dataMembers; - std::vector memberOffsets; size_t arrayLength; size_t arrayStride; @@ -154,7 +188,7 @@ protected: size_t size; // The type of the buffer object. - BufferTypeFlags typeFlags; + TypeFlags typeFlags; // Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW. BufferUsage usage; diff --git a/src/modules/graphics/Font.cpp b/src/modules/graphics/Font.cpp index 25b32a60d..7114d6853 100644 --- a/src/modules/graphics/Font.cpp +++ b/src/modules/graphics/Font.cpp @@ -642,7 +642,7 @@ void Font::printv(graphics::Graphics *gfx, const Matrix4 &t, const std::vector format = { + { "index", getIndexDataFormat(dataType), 0 } + }; + + return newBuffer(settings, format, indices, size, 0); +} + Mesh *Graphics::newMesh(const std::vector &vertices, PrimitiveType drawmode, BufferUsage usage) { return newMesh(Mesh::getDefaultVertexFormat(), &vertices[0], vertices.size() * sizeof(Vertex), drawmode, usage); @@ -270,12 +281,12 @@ Mesh *Graphics::newMesh(int vertexcount, PrimitiveType drawmode, BufferUsage usa return newMesh(Mesh::getDefaultVertexFormat(), vertexcount, drawmode, usage); } -love::graphics::Mesh *Graphics::newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) +love::graphics::Mesh *Graphics::newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) { return new Mesh(this, vertexformat, vertexcount, drawmode, usage); } -love::graphics::Mesh *Graphics::newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage) +love::graphics::Mesh *Graphics::newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage) { return new Mesh(this, vertexformat, data, datasize, drawmode, usage); } @@ -1003,7 +1014,7 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & if (cmd.primitiveMode != state.primitiveMode || cmd.formats[0] != state.formats[0] || cmd.formats[1] != state.formats[1] - || ((cmd.indexMode != TriangleIndexMode::NONE) != (state.indexCount > 0)) + || ((cmd.indexMode != TRIANGLEINDEX_NONE) != (state.indexCount > 0)) || cmd.texture != state.texture || cmd.standardShaderType != state.standardShaderType) { @@ -1013,7 +1024,7 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & int totalvertices = state.vertexCount + cmd.vertexCount; // We only support uint16 index buffers for now. - if (totalvertices > LOVE_UINT16_MAX && cmd.indexMode != TriangleIndexMode::NONE) + if (totalvertices > LOVE_UINT16_MAX && cmd.indexMode != TRIANGLEINDEX_NONE) shouldflush = true; int reqIndexCount = getIndexCount(cmd.indexMode, cmd.vertexCount); @@ -1042,7 +1053,7 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & newdatasizes[i] = stride * cmd.vertexCount; } - if (cmd.indexMode != TriangleIndexMode::NONE) + if (cmd.indexMode != TRIANGLEINDEX_NONE) { size_t datasize = (state.indexCount + reqIndexCount) * sizeof(uint16); @@ -1080,18 +1091,18 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & if (state.vb[i]->getSize() < buffersizes[i]) { delete state.vb[i]; - state.vb[i] = newStreamBuffer(BUFFER_VERTEX, buffersizes[i]); + state.vb[i] = newStreamBuffer(BUFFERTYPE_VERTEX, buffersizes[i]); } } if (state.indexBuffer->getSize() < buffersizes[2]) { delete state.indexBuffer; - state.indexBuffer = newStreamBuffer(BUFFER_INDEX, buffersizes[2]); + state.indexBuffer = newStreamBuffer(BUFFERTYPE_INDEX, buffersizes[2]); } } - if (cmd.indexMode != TriangleIndexMode::NONE) + if (cmd.indexMode != TRIANGLEINDEX_NONE) { if (state.indexBufferMap.data == nullptr) state.indexBufferMap = state.indexBuffer->map(reqIndexSize); @@ -1573,7 +1584,7 @@ void Graphics::polygon(DrawMode mode, const Vector2 *coords, size_t count, bool StreamDrawCommand cmd; cmd.formats[0] = getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::RGBAub; - cmd.indexMode = TriangleIndexMode::FAN; + cmd.indexMode = TRIANGLEINDEX_FAN; cmd.vertexCount = (int)count - (skipLastFilledVertex ? 1 : 0); StreamVertexData data = requestStreamDraw(cmd); diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 1ea9607c7..aba60539e 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -260,7 +260,7 @@ public: { PrimitiveType primitiveMode = PRIMITIVE_TRIANGLES; CommonFormat formats[2]; - TriangleIndexMode indexMode = TriangleIndexMode::NONE; + TriangleIndexMode indexMode = TRIANGLEINDEX_NONE; int vertexCount = 0; Texture *texture = nullptr; Shader::StandardShader standardShaderType = Shader::STANDARD_DEFAULT; @@ -445,15 +445,15 @@ public: ShaderStage *newShaderStage(ShaderStage::StageType stage, const std::string &source); Shader *newShader(const std::string &vertex, const std::string &pixel); - virtual Buffer *newBuffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) = 0; - virtual Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, size_t arraylength) = 0; + virtual Buffer *newBuffer(const Buffer::Settings &settings, const void *data, size_t size) = 0; + virtual Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) = 0; -// Buffer *newIndexBuffer(IndexDataType dataType, const void *indices, size_t bytesize, vertex::Usage usage, uint32 mapflags) = 0; + Buffer *newIndexBuffer(IndexDataType dataType, const void *indices, size_t size, BufferUsage usage, uint32 mapflags); Mesh *newMesh(const std::vector &vertices, PrimitiveType drawmode, BufferUsage usage); Mesh *newMesh(int vertexcount, PrimitiveType drawmode, BufferUsage usage); - Mesh *newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage); - Mesh *newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage); + Mesh *newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage); + Mesh *newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage); Text *newText(Font *font, const std::vector &text = {}); diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 13c7477a4..ef186137e 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -45,13 +45,13 @@ static_assert(offsetof(Vertex, x) == sizeof(float) * 0, "Incorrect position offs static_assert(offsetof(Vertex, s) == sizeof(float) * 2, "Incorrect texture coordinate offset in Vertex struct"); static_assert(offsetof(Vertex, color.r) == sizeof(float) * 4, "Incorrect color offset in Vertex struct"); -std::vector Mesh::getDefaultVertexFormat() +std::vector Mesh::getDefaultVertexFormat() { // Corresponds to the love::Vertex struct. - std::vector vertexformat = { - { getBuiltinAttribName(ATTRIB_POS), DATA_FLOAT, 2 }, - { getBuiltinAttribName(ATTRIB_TEXCOORD), DATA_FLOAT, 2 }, - { getBuiltinAttribName(ATTRIB_COLOR), DATA_UNORM8, 4 }, + std::vector vertexformat = { + { getBuiltinAttribName(ATTRIB_POS), DATAFORMAT_FLOAT_VEC2, 0 }, + { getBuiltinAttribName(ATTRIB_TEXCOORD), DATAFORMAT_FLOAT_VEC2, 0 }, + { getBuiltinAttribName(ATTRIB_COLOR), DATAFORMAT_UNORM8_VEC4, 0 }, }; return vertexformat; @@ -59,9 +59,8 @@ std::vector Mesh::getDefaultVertexFormat() love::Type Mesh::type("Mesh", &Drawable::type); -Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage) - : vertexFormat(vertexformat) - , vertexBuffer(nullptr) +Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage) + : vertexBuffer(nullptr) , vertexCount(0) , vertexStride(0) , indexBuffer(nullptr) @@ -72,24 +71,22 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma , rangeStart(-1) , rangeCount(-1) { + Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ, usage); + vertexBuffer.set(gfx->newBuffer(settings, vertexformat, data, datasize, 0), Acquire::NORETAIN); + + vertexCount = vertexBuffer->getArrayLength(); + vertexStride = vertexBuffer->getArrayStride(); + vertexFormat = vertexBuffer->getDataMembers(); + setupAttachedAttributes(); - calculateAttributeSizes(gfx); - vertexCount = datasize / vertexStride; indexDataType = getIndexDataTypeFromMax(vertexCount); - if (vertexCount == 0) - throw love::Exception("Data size is too small for specified vertex attribute formats."); - - auto buffer = gfx->newBuffer(datasize, data, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); - vertexBuffer.set(buffer, Acquire::NORETAIN); - vertexScratchBuffer = new char[vertexStride]; } -Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) - : vertexFormat(vertexformat) - , vertexBuffer(nullptr) +Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) + : vertexBuffer(nullptr) , vertexCount((size_t) vertexcount) , vertexStride(0) , indexBuffer(nullptr) @@ -103,16 +100,15 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma if (vertexcount <= 0) throw love::Exception("Invalid number of vertices (%d).", vertexcount); + Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ, usage); + vertexBuffer.set(gfx->newBuffer(settings, vertexformat, nullptr, 0, vertexcount), Acquire::NORETAIN); + + vertexStride = vertexBuffer->getArrayStride(); + vertexFormat = vertexBuffer->getDataMembers(); + setupAttachedAttributes(); - calculateAttributeSizes(gfx); - size_t buffersize = vertexCount * vertexStride; - - auto buffer = gfx->newBuffer(buffersize, nullptr, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); - vertexBuffer.set(buffer, Acquire::NORETAIN); - - // Initialize the buffer's contents to 0. - memset(vertexBuffer->map(), 0, buffersize); + memset(vertexBuffer->map(), 0, vertexBuffer->getSize()); vertexBuffer->setMappedRangeModified(0, vertexBuffer->getSize()); vertexBuffer->unmap(); @@ -134,53 +130,15 @@ void Mesh::setupAttachedAttributes() { for (size_t i = 0; i < vertexFormat.size(); i++) { - const std::string &name = vertexFormat[i].name; + const std::string &name = vertexFormat[i].decl.name; if (attachedAttributes.find(name) != attachedAttributes.end()) throw love::Exception("Duplicate vertex attribute name: %s", name.c_str()); - attachedAttributes[name] = {nullptr, (int) i, STEP_PER_VERTEX, true}; + attachedAttributes[name] = {vertexBuffer, (int) i, STEP_PER_VERTEX, true}; } } -void Mesh::calculateAttributeSizes(Graphics *gfx) -{ - bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3]; - - size_t stride = 0; - - for (const AttribFormat &format : vertexFormat) - { - size_t size = getDataTypeSize(format.type) * format.components; - - if (format.components <= 0 || format.components > 4) - throw love::Exception("Vertex attributes must have between 1 and 4 components."); - - // Hardware really doesn't like attributes that aren't 32 bit-aligned. - if (size % 4 != 0) - throw love::Exception("Vertex attributes must have enough components to be a multiple of 32 bits."); - - if (isDataTypeInteger(format.type) && !supportsGLSL3) - throw love::Exception("Integer vertex attribute data types require GLSL 3 support."); - - // Total size in bytes of each attribute in a single vertex. - attributeSizes.push_back(size); - stride += size; - } - - vertexStride = stride; -} - -size_t Mesh::getAttributeOffset(size_t attribindex) const -{ - size_t offset = 0; - - for (size_t i = 0; i < attribindex; i++) - offset += attributeSizes[i]; - - return offset; -} - void Mesh::setVertex(size_t vertindex, const void *data, size_t datasize) { if (vertindex >= vertexCount) @@ -223,8 +181,10 @@ void Mesh::setVertexAttribute(size_t vertindex, int attribindex, const void *dat if (attribindex >= (int) vertexFormat.size()) throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1); - size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex); - size_t size = std::min(datasize, attributeSizes[attribindex]); + const auto &member = vertexFormat[attribindex]; + + size_t offset = vertindex * vertexStride + member.offset; + size_t size = std::min(datasize, member.info.size); uint8 *bufferdata = (uint8 *) vertexBuffer->map(); memcpy(bufferdata + offset, data, size); @@ -240,8 +200,10 @@ size_t Mesh::getVertexAttribute(size_t vertindex, int attribindex, void *data, s if (attribindex >= (int) vertexFormat.size()) throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1); - size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex); - size_t size = std::min(datasize, attributeSizes[attribindex]); + const auto &member = vertexFormat[attribindex]; + + size_t offset = vertindex * vertexStride + member.offset; + size_t size = std::min(datasize, member.info.size); // We're relying on map() returning read/write data... ew. const uint8 *bufferdata = (const uint8 *) vertexBuffer->map(); @@ -265,25 +227,16 @@ Buffer *Mesh::getVertexBuffer() const return vertexBuffer; } -const std::vector &Mesh::getVertexFormat() const +const std::vector &Mesh::getVertexFormat() const { return vertexFormat; } -DataType Mesh::getAttributeInfo(int attribindex, int &components) const -{ - if (attribindex < 0 || attribindex >= (int) vertexFormat.size()) - throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1); - - components = vertexFormat[attribindex].components; - return vertexFormat[attribindex].type; -} - int Mesh::getAttributeIndex(const std::string &name) const { for (int i = 0; i < (int) vertexFormat.size(); i++) { - if (vertexFormat[i].name == name) + if (vertexFormat[i].decl.name == name) return i; } @@ -312,7 +265,7 @@ bool Mesh::isAttributeEnabled(const std::string &name) const void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step) { - if ((buffer->getTypeFlags() & BUFFER_VERTEX) == 0) + if ((buffer->getTypeFlags() & Buffer::TYPEFLAG_VERTEX) == 0) throw love::Exception("GraphicsBuffer must be created with vertex buffer support to be used as a Mesh vertex attribute."); auto gfx = Module::getInstance(Module::M_GRAPHICS); @@ -410,7 +363,8 @@ void Mesh::setVertexMap(const std::vector &map) if (indexBuffer.get() == nullptr || size > indexBuffer->getSize()) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - indexBuffer.set(gfx->newBuffer(size, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ), Acquire::NORETAIN); + Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, vertexBuffer->getUsage()); + indexBuffer.set(gfx->newBuffer(settings, nullptr, size), Acquire::NORETAIN); } useIndexBuffer = true; @@ -441,7 +395,8 @@ void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasiz if (indexBuffer.get() == nullptr || datasize > indexBuffer->getSize()) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - indexBuffer.set(gfx->newBuffer(datasize, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ), Acquire::NORETAIN); + Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, vertexBuffer->getUsage()); + indexBuffer.set(gfx->newBuffer(settings, nullptr, datasize), Acquire::NORETAIN); } indexCount = datasize / getIndexDataSize(datatype); @@ -607,7 +562,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) uint16 offset = (uint16) buffer->getMemberOffset(attrib.second.index); uint16 stride = (uint16) buffer->getArrayStride(); - attributes.set(attributeindex, member.format, offset, activebuffers); + attributes.set(attributeindex, member.decl.format, offset, activebuffers); attributes.setBufferLayout(activebuffers, stride, attrib.second.step); // TODO: Ideally we want to reuse buffers with the same stride+step. diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index a0a16bb06..160dcf66e 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -52,15 +52,8 @@ public: static love::Type type; - struct AttribFormat - { - std::string name; - DataType type; - int components; // max 4 - }; - - Mesh(Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage); - Mesh(Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage); + Mesh(Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage); + Mesh(Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage); virtual ~Mesh(); @@ -97,8 +90,7 @@ public: /** * Gets the format of each vertex attribute stored in the Mesh. **/ - const std::vector &getVertexFormat() const; - DataType getAttributeInfo(int attribindex, int &components) const; + const std::vector &getVertexFormat() const; int getAttributeIndex(const std::string &name) const; /** @@ -174,7 +166,7 @@ public: void drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount); - static std::vector getDefaultVertexFormat(); + static std::vector getDefaultVertexFormat(); private: @@ -189,11 +181,8 @@ private: }; void setupAttachedAttributes(); - void calculateAttributeSizes(Graphics *gfx); - size_t getAttributeOffset(size_t attribindex) const; - std::vector vertexFormat; - std::vector attributeSizes; + std::vector vertexFormat; std::unordered_map attachedAttributes; diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index 6e1123870..0f8a5aa50 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -191,7 +191,8 @@ void ParticleSystem::createBuffers(size_t size) auto gfx = Module::getInstance(Module::M_GRAPHICS); size_t bytes = sizeof(Vertex) * size * 4; - buffer = gfx->newBuffer(bytes, nullptr, BUFFERFLAG_VERTEX, BUFFERUSAGE_STREAM, 0); + Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, 0, BUFFERUSAGE_STREAM); + buffer = gfx->newBuffer(settings, nullptr, bytes); } catch (std::bad_alloc &) { @@ -203,7 +204,8 @@ void ParticleSystem::createBuffers(size_t size) void ParticleSystem::deleteBuffers() { delete[] pMem; - buffer->release(); + if (buffer) + buffer->release(); pMem = nullptr; buffer = nullptr; diff --git a/src/modules/graphics/Polyline.cpp b/src/modules/graphics/Polyline.cpp index 27035e48b..4b9a8491b 100644 --- a/src/modules/graphics/Polyline.cpp +++ b/src/modules/graphics/Polyline.cpp @@ -82,7 +82,7 @@ void Polyline::render(const Vector2 *coords, size_t count, size_t size_hint, flo // extra degenerate triangle in between the core line and the overdraw // line in order to break up the strip into two. This will let us draw // everything in one draw call. - if (triangle_mode == TriangleIndexMode::STRIP) + if (triangle_mode == TRIANGLEINDEX_STRIP) extra_vertices = 2; } @@ -383,7 +383,7 @@ void Polyline::draw(love::graphics::Graphics *gfx) int maxvertices = LOVE_UINT16_MAX - 3; int advance = maxvertices; - if (triangle_mode == TriangleIndexMode::STRIP) + if (triangle_mode == TRIANGLEINDEX_STRIP) advance -= 2; for (int vertex_start = 0; vertex_start < total_vertex_count; vertex_start += advance) diff --git a/src/modules/graphics/Polyline.h b/src/modules/graphics/Polyline.h index efb42e9e8..32bd4c621 100644 --- a/src/modules/graphics/Polyline.h +++ b/src/modules/graphics/Polyline.h @@ -44,7 +44,7 @@ class Polyline { public: - Polyline(TriangleIndexMode mode = TriangleIndexMode::STRIP) + Polyline(TriangleIndexMode mode = TRIANGLEINDEX_STRIP) : vertices(nullptr) , overdraw(nullptr) , vertex_count(0) @@ -109,7 +109,7 @@ class NoneJoinPolyline : public Polyline public: NoneJoinPolyline() - : Polyline(TriangleIndexMode::QUADS) + : Polyline(TRIANGLEINDEX_QUADS) {} void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index 50ee28123..9197b39cd 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -64,7 +64,8 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage vertex_stride = getFormatStride(vertex_format); size_t vertex_size = vertex_stride * 4 * size; - array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY); + Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY, usage); + array_buf = gfx->newBuffer(settings, nullptr, vertex_size); } SpriteBatch::~SpriteBatch() @@ -218,7 +219,8 @@ void SpriteBatch::setBufferSize(int newsize) try { auto gfx = Module::getInstance(Module::M_GRAPHICS); - new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getTypeFlags(), array_buf->getUsage(), array_buf->getMapFlags()); + Buffer::Settings settings(array_buf->getTypeFlags(), array_buf->getMapFlags(), array_buf->getUsage()); + new_array_buf = gfx->newBuffer(settings, nullptr, vertex_size); // Copy as much of the old data into the new GLBuffer as can fit. size_t copy_size = vertex_stride * 4 * new_next; @@ -246,7 +248,7 @@ int SpriteBatch::getBufferSize() const void SpriteBatch::attachAttribute(const std::string &name, Buffer *buffer) { - if ((buffer->getTypeFlags() & BUFFER_VERTEX) == 0) + if ((buffer->getTypeFlags() & Buffer::TYPEFLAG_VERTEX) == 0) throw love::Exception("GraphicsBuffer must be created with vertex buffer support to be used as a SpriteBatch vertex attribute."); AttachedAttribute oldattrib = {}; @@ -357,7 +359,7 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) uint16 offset = (uint16) buffer->getMemberOffset(it.second.index); uint16 stride = (uint16) buffer->getArrayStride(); - attributes.set(attributeindex, member.format, offset, activebuffers); + attributes.set(attributeindex, member.decl.format, offset, activebuffers); attributes.setBufferLayout(activebuffers, stride); // TODO: We should reuse buffer bindings with the same buffer+stride+step. diff --git a/src/modules/graphics/Text.cpp b/src/modules/graphics/Text.cpp index 1909a35cf..f9db16d5e 100644 --- a/src/modules/graphics/Text.cpp +++ b/src/modules/graphics/Text.cpp @@ -42,7 +42,8 @@ Text::Text(Font *font, const std::vector &text) Text::~Text() { - delete vertex_buffer; + if (vertex_buffer) + vertex_buffer->release(); } void Text::uploadVertices(const std::vector &vertices, size_t vertoffset) @@ -60,12 +61,13 @@ void Text::uploadVertices(const std::vector &vertices, size_t newsize = std::max(size_t(vertex_buffer->getSize() * 1.5), newsize); auto gfx = Module::getInstance(Module::M_GRAPHICS); - Buffer *new_buffer = gfx->newBuffer(newsize, nullptr, BUFFERFLAG_VERTEX, BUFFERUSAGE_DYNAMIC, 0); + Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, 0, BUFFERUSAGE_DYNAMIC); + Buffer *new_buffer = gfx->newBuffer(settings, nullptr, newsize); if (vertex_buffer != nullptr) vertex_buffer->copyTo(0, vertex_buffer->getSize(), new_buffer, 0); - delete vertex_buffer; + vertex_buffer->release(); vertex_buffer = new_buffer; vertexBuffers.set(0, vertex_buffer, 0); diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index f37ef41b6..9eebbf659 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -132,7 +132,7 @@ void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform) Graphics::StreamDrawCommand cmd; cmd.formats[0] = getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::STf_RGBAub; - cmd.indexMode = TriangleIndexMode::QUADS; + cmd.indexMode = TRIANGLEINDEX_QUADS; cmd.vertexCount = 4; cmd.texture = this; @@ -184,7 +184,7 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) Graphics::StreamDrawCommand cmd; cmd.formats[0] = getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::STPf_RGBAub; - cmd.indexMode = TriangleIndexMode::QUADS; + cmd.indexMode = TRIANGLEINDEX_QUADS; cmd.vertexCount = 4; cmd.texture = this; cmd.standardShaderType = Shader::STANDARD_ARRAY; diff --git a/src/modules/graphics/Video.cpp b/src/modules/graphics/Video.cpp index e3c71c1ef..0733e6d84 100644 --- a/src/modules/graphics/Video.cpp +++ b/src/modules/graphics/Video.cpp @@ -117,7 +117,7 @@ void Video::draw(Graphics *gfx, const Matrix4 &m) Graphics::StreamDrawCommand cmd; cmd.formats[0] = getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::STf_RGBAub; - cmd.indexMode = TriangleIndexMode::QUADS; + cmd.indexMode = TRIANGLEINDEX_QUADS; cmd.vertexCount = 4; cmd.standardShaderType = Shader::STANDARD_VIDEO; diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 3559a2221..2c94deaee 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -35,21 +35,34 @@ namespace graphics namespace opengl { -Buffer::Buffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) - : love::graphics::Buffer(size, typeflags, usage, mapflags) - , vbo(0) - , memoryMap(nullptr) - , modifiedOffset(0) - , modifiedSize(0) +Buffer::Buffer(const Settings &settings, const void *data, size_t size) + : love::graphics::Buffer(settings, data, size) { - if (typeflags & BUFFERFLAG_VERTEX) - mapType = BUFFER_VERTEX; - else if (typeflags & BUFFERFLAG_INDEX) - mapType = BUFFER_INDEX; - else if (mapflags & BUFFERFLAG_UNIFORM) - mapType = BUFFER_UNIFORM; - else if (mapflags & BUFFERFLAG_SHADER_STORAGE) - mapType = BUFFER_SHADER_STORAGE; + initialize(data); +} + +Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) + : love::graphics::Buffer(gfx, settings, format, data, size, arraylength) +{ + initialize(data); +} + +Buffer::~Buffer() +{ + unloadVolatile(); + delete[] memoryMap; +} + +void Buffer::initialize(const void *data) +{ + if (typeFlags & TYPEFLAG_VERTEX) + mapType = BUFFERTYPE_VERTEX; + else if (typeFlags & TYPEFLAG_INDEX) + mapType = BUFFERTYPE_INDEX; + else if (typeFlags & TYPEFLAG_UNIFORM) + mapType = BUFFERTYPE_UNIFORM; + else if (typeFlags & TYPEFLAG_SHADER_STORAGE) + mapType = BUFFERTYPE_SHADER_STORAGE; target = OpenGL::getGLBufferType(mapType); @@ -72,12 +85,34 @@ Buffer::Buffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferU } } -Buffer::~Buffer() +bool Buffer::loadVolatile() { - if (vbo != 0) - unload(); + return load(true); +} - delete[] memoryMap; +void Buffer::unloadVolatile() +{ + mapped = false; + if (vbo != 0) + gl.deleteBuffer(vbo); + vbo = 0; +} + +bool Buffer::load(bool restore) +{ + glGenBuffers(1, &vbo); + gl.bindBuffer(mapType, vbo); + + while (glGetError() != GL_NO_ERROR) + /* Clear the error buffer. */; + + // Copy the old buffer only if 'restore' was requested. + const GLvoid *src = restore ? memoryMap : nullptr; + + // Note that if 'src' is '0', no data will be copied. + glBufferData(target, (GLsizeiptr) getSize(), src, OpenGL::getGLBufferUsage(getUsage())); + + return (glGetError() == GL_NO_ERROR); } void *Buffer::map() @@ -204,40 +239,6 @@ void Buffer::copyTo(size_t offset, size_t size, love::graphics::Buffer *other, s other->fill(otheroffset, size, memoryMap + offset); } -bool Buffer::loadVolatile() -{ - return load(true); -} - -void Buffer::unloadVolatile() -{ - unload(); -} - -bool Buffer::load(bool restore) -{ - glGenBuffers(1, &vbo); - gl.bindBuffer(mapType, vbo); - - while (glGetError() != GL_NO_ERROR) - /* Clear the error buffer. */; - - // Copy the old buffer only if 'restore' was requested. - const GLvoid *src = restore ? memoryMap : nullptr; - - // Note that if 'src' is '0', no data will be copied. - glBufferData(target, (GLsizeiptr) getSize(), src, OpenGL::getGLBufferUsage(getUsage())); - - return (glGetError() == GL_NO_ERROR); -} - -void Buffer::unload() -{ - mapped = false; - gl.deleteBuffer(vbo); - vbo = 0; -} - } // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index 60946ddfb..df74fd982 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -32,6 +32,9 @@ namespace love { namespace graphics { + +class Graphics; + namespace opengl { @@ -39,9 +42,14 @@ class Buffer final : public love::graphics::Buffer, public Volatile { public: - Buffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags); + Buffer(const Settings &settings, const void *data, size_t size); + Buffer(love::graphics::Graphics *gfx, const Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength); virtual ~Buffer(); + // Implements Volatile. + bool loadVolatile() override; + void unloadVolatile() override; + void *map() override; void unmap() override; void setMappedRangeModified(size_t offset, size_t size) override; @@ -50,29 +58,26 @@ public: void copyTo(size_t offset, size_t size, love::graphics::Buffer *other, size_t otheroffset) override; - // Implements Volatile. - bool loadVolatile() override; - void unloadVolatile() override; - private: + void initialize(const void *data); + bool load(bool restore); - void unload(); void unmapStatic(size_t offset, size_t size); void unmapStream(); - BufferType mapType; - GLenum target; + BufferType mapType = BUFFERTYPE_VERTEX; + GLenum target = 0; // The VBO identifier. Assigned by OpenGL. - GLuint vbo; + GLuint vbo = 0; // A pointer to mapped memory. - char *memoryMap; + char *memoryMap = nullptr; - size_t modifiedOffset; - size_t modifiedSize; + size_t modifiedOffset = 0; + size_t modifiedSize = 0; }; // Buffer diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index e17028d46..b1f7858d5 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -155,15 +155,14 @@ love::graphics::Shader *Graphics::newShaderInternal(love::graphics::ShaderStage return new Shader(vertex, pixel); } -love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) +love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const void *data, size_t size) { - return new Buffer(size, data, typeflags, usage, mapflags); + return new Buffer(settings, data, size); } -love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const std::vector &format, size_t arraylength) +love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) { - // TODO - return nullptr; + return new Buffer(this, settings, format, data, size, arraylength); } void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) @@ -254,9 +253,9 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b { // Initial sizes that should be good enough for most cases. It will // resize to fit if needed, later. - streamBufferState.vb[0] = CreateStreamBuffer(BUFFER_VERTEX, 1024 * 1024 * 1); - streamBufferState.vb[1] = CreateStreamBuffer(BUFFER_VERTEX, 256 * 1024 * 1); - streamBufferState.indexBuffer = CreateStreamBuffer(BUFFER_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); + streamBufferState.vb[0] = CreateStreamBuffer(BUFFERTYPE_VERTEX, 1024 * 1024 * 1); + streamBufferState.vb[1] = CreateStreamBuffer(BUFFERTYPE_VERTEX, 256 * 1024 * 1); + streamBufferState.indexBuffer = CreateStreamBuffer(BUFFERTYPE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); } // Reload all volatile objects. @@ -375,7 +374,7 @@ void Graphics::draw(const DrawIndexedCommand &cmd) GLenum glprimitivetype = OpenGL::getGLPrimitiveType(cmd.primitiveType); GLenum gldatatype = OpenGL::getGLIndexDataType(cmd.indexType); - gl.bindBuffer(BUFFER_INDEX, cmd.indexBuffer->getHandle()); + gl.bindBuffer(BUFFERTYPE_INDEX, cmd.indexBuffer->getHandle()); if (cmd.instanceCount > 1) glDrawElementsInstanced(glprimitivetype, cmd.indexCount, gldatatype, gloffset, cmd.instanceCount); @@ -417,7 +416,7 @@ void Graphics::drawQuads(int start, int count, const VertexAttributes &attribute gl.bindTextureToUnit(texture, 0, false); gl.setCullMode(CULL_NONE); - gl.bindBuffer(BUFFER_INDEX, quadIndexBuffer->getHandle()); + gl.bindBuffer(BUFFERTYPE_INDEX, quadIndexBuffer->getHandle()); if (gl.isBaseVertexSupported()) { diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 36c63d64c..c47eb0ba8 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -63,8 +63,8 @@ public: love::graphics::Image *newImage(const Image::Slices &data, const Image::Settings &settings) override; love::graphics::Image *newImage(TextureType textype, PixelFormat format, int width, int height, int slices, const Image::Settings &settings) override; love::graphics::Canvas *newCanvas(const Canvas::Settings &settings) override; - love::graphics::Buffer *newBuffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) override; - love::graphics::Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, size_t arraylength) override; + love::graphics::Buffer *newBuffer(const Buffer::Settings &settings, const void *data, size_t size) override; + love::graphics::Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) override; void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; bool setMode(int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil) override; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 620372012..1e821ff3d 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -223,7 +223,7 @@ void OpenGL::setupContext() glGetIntegerv(GL_CULL_FACE_MODE, &faceCull); state.faceCullMode = faceCull; - for (int i = 0; i < (int) BUFFER_MAX_ENUM; i++) + for (int i = 0; i < (int) BUFFERTYPE_MAX_ENUM; i++) { state.boundBuffers[i] = 0; glBindBuffer(getGLBufferType((BufferType) i), 0); @@ -584,15 +584,15 @@ GLenum OpenGL::getGLBufferType(BufferType type) { switch (type) { - case BUFFER_VERTEX: + case BUFFERTYPE_VERTEX: return GL_ARRAY_BUFFER; - case BUFFER_INDEX: + case BUFFERTYPE_INDEX: return GL_ELEMENT_ARRAY_BUFFER; - case BUFFER_UNIFORM: + case BUFFERTYPE_UNIFORM: return GL_UNIFORM_BUFFER; - case BUFFER_SHADER_STORAGE: + case BUFFERTYPE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER; - case BUFFER_MAX_ENUM: + case BUFFERTYPE_MAX_ENUM: return GL_ZERO; } @@ -717,10 +717,6 @@ GLenum OpenGL::getGLVertexDataType(DataFormat format, int &components, GLboolean intformat = true; return GL_UNSIGNED_BYTE; - case DATAFORMAT_SNORM16: - components = 1; - normalized = GL_TRUE; - return GL_SHORT; case DATAFORMAT_SNORM16_VEC2: components = 2; normalized = GL_TRUE; @@ -730,10 +726,6 @@ GLenum OpenGL::getGLVertexDataType(DataFormat format, int &components, GLboolean normalized = GL_TRUE; return GL_BYTE; - case DATAFORMAT_UNORM16: - components = 1; - normalized = GL_TRUE; - return GL_UNSIGNED_SHORT; case DATAFORMAT_UNORM16_VEC2: components = 2; normalized = GL_TRUE; @@ -743,10 +735,6 @@ GLenum OpenGL::getGLVertexDataType(DataFormat format, int &components, GLboolean normalized = GL_TRUE; return GL_UNSIGNED_SHORT; - case DATAFORMAT_INT16: - components = 1; - intformat = true; - return GL_SHORT; case DATAFORMAT_INT16_VEC2: components = 2; intformat = true; @@ -810,7 +798,7 @@ void OpenGL::deleteBuffer(GLuint buffer) { glDeleteBuffers(1, &buffer); - for (int i = 0; i < (int) BUFFER_MAX_ENUM; i++) + for (int i = 0; i < (int) BUFFERTYPE_MAX_ENUM; i++) { if (state.boundBuffers[i] == buffer) state.boundBuffers[i] = 0; @@ -857,7 +845,7 @@ void OpenGL::setVertexAttributes(const VertexAttributes &attributes, const Buffe const void *offsetpointer = reinterpret_cast(bufferinfo.offset + attrib.offsetFromVertex); - bindBuffer(BUFFER_VERTEX, (GLuint) bufferinfo.buffer->getHandle()); + bindBuffer(BUFFERTYPE_VERTEX, (GLuint) bufferinfo.buffer->getHandle()); if (intformat) glVertexAttribIPointer(i, components, gltype, layout.stride, offsetpointer); diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 01faf8a37..c61fc0ac6 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -453,7 +453,7 @@ private: // Tracked OpenGL state. struct { - GLuint boundBuffers[BUFFER_MAX_ENUM]; + GLuint boundBuffers[BUFFERTYPE_MAX_ENUM]; // Texture unit state (currently bound texture for each texture unit.) std::vector boundTextures[TEXTURE_MAX_ENUM]; diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 42ab2f153..0b6c92e46 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -137,21 +137,18 @@ static const DataFormatInfo dataFormatInfo[] { DATA_BASETYPE_INT, false, 4, 0, 0, 1, 1, 4 }, // DATAFORMAT_INT8_VEC4 { DATA_BASETYPE_UINT, false, 4, 0, 0, 1, 1, 4 }, // DATAFORMAT_UINT8_VEC4 - { DATA_BASETYPE_SNORM, false, 1, 0, 0, 2, 2, 2 }, // DATAFORMAT_SNORM16 { DATA_BASETYPE_SNORM, false, 2, 0, 0, 2, 2, 4 }, // DATAFORMAT_SNORM16_VEC2 { DATA_BASETYPE_SNORM, false, 4, 0, 0, 2, 2, 8 }, // DATAFORMAT_SNORM16_VEC4 - { DATA_BASETYPE_UNORM, false, 1, 0, 0, 2, 2, 2 }, // DATAFORMAT_SNORM16 - { DATA_BASETYPE_UNORM, false, 2, 0, 0, 2, 2, 4 }, // DATAFORMAT_SNORM16_VEC2 - { DATA_BASETYPE_UNORM, false, 4, 0, 0, 2, 2, 8 }, // DATAFORMAT_SNORM16_VEC4 + { DATA_BASETYPE_UNORM, false, 2, 0, 0, 2, 2, 4 }, // DATAFORMAT_UNORM16_VEC2 + { DATA_BASETYPE_UNORM, false, 4, 0, 0, 2, 2, 8 }, // DATAFORMAT_UNORM16_VEC4 - { DATA_BASETYPE_INT, false, 1, 0, 0, 2, 2, 2 }, // DATAFORMAT_SNORM16 - { DATA_BASETYPE_INT, false, 2, 0, 0, 2, 2, 4 }, // DATAFORMAT_SNORM16_VEC2 - { DATA_BASETYPE_INT, false, 4, 0, 0, 2, 2, 8 }, // DATAFORMAT_SNORM16_VEC4 + { DATA_BASETYPE_INT, false, 2, 0, 0, 2, 2, 4 }, // DATAFORMAT_INT16_VEC2 + { DATA_BASETYPE_INT, false, 4, 0, 0, 2, 2, 8 }, // DATAFORMAT_INT16_VEC4 - { DATA_BASETYPE_UINT, false, 1, 0, 0, 2, 2, 2 }, // DATAFORMAT_SNORM16 - { DATA_BASETYPE_UINT, false, 2, 0, 0, 2, 2, 4 }, // DATAFORMAT_SNORM16_VEC2 - { DATA_BASETYPE_UINT, false, 4, 0, 0, 2, 2, 8 }, // DATAFORMAT_SNORM16_VEC4 + { DATA_BASETYPE_UINT, false, 1, 0, 0, 2, 2, 2 }, // DATAFORMAT_UINT16 + { DATA_BASETYPE_UINT, false, 2, 0, 0, 2, 2, 4 }, // DATAFORMAT_UINT16_VEC2 + { DATA_BASETYPE_UINT, false, 4, 0, 0, 2, 2, 8 }, // DATAFORMAT_UINT16_VEC4 { DATA_BASETYPE_BOOL, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_BOOL { DATA_BASETYPE_BOOL, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_BOOL_VEC2 @@ -176,62 +173,26 @@ size_t getIndexDataSize(IndexDataType type) } } -size_t getDataTypeSize(DataType datatype) -{ - switch (datatype) - { - case DATA_SNORM8: - case DATA_UNORM8: - case DATA_INT8: - case DATA_UINT8: - return sizeof(uint8); - case DATA_SNORM16: - case DATA_UNORM16: - case DATA_INT16: - case DATA_UINT16: - return sizeof(uint16); - case DATA_INT32: - case DATA_UINT32: - return sizeof(uint32); - case DATA_FLOAT: - return sizeof(float); - case DATA_MAX_ENUM: - return 0; - } - return 0; -} - -bool isDataTypeInteger(DataType datatype) -{ - switch (datatype) - { - case DATA_INT8: - case DATA_UINT8: - case DATA_INT16: - case DATA_UINT16: - case DATA_INT32: - case DATA_UINT32: - return true; - default: - return false; - } -} - IndexDataType getIndexDataTypeFromMax(size_t maxvalue) { return maxvalue > LOVE_UINT16_MAX ? INDEX_UINT32 : INDEX_UINT16; } +DataFormat getIndexDataFormat(IndexDataType type) +{ + return type == INDEX_UINT32 ? DATAFORMAT_UINT32 : DATAFORMAT_UINT16; +} + int getIndexCount(TriangleIndexMode mode, int vertexCount) { switch (mode) { - case TriangleIndexMode::NONE: + case TRIANGLEINDEX_NONE: return 0; - case TriangleIndexMode::STRIP: - case TriangleIndexMode::FAN: + case TRIANGLEINDEX_STRIP: + case TRIANGLEINDEX_FAN: return 3 * (vertexCount - 2); - case TriangleIndexMode::QUADS: + case TRIANGLEINDEX_QUADS: return vertexCount * 6 / 4; } return 0; @@ -242,9 +203,9 @@ static void fillIndicesT(TriangleIndexMode mode, T vertexStart, T vertexCount, T { switch (mode) { - case TriangleIndexMode::NONE: + case TRIANGLEINDEX_NONE: break; - case TriangleIndexMode::STRIP: + case TRIANGLEINDEX_STRIP: { int i = 0; for (T index = 0; index < vertexCount - 2; index++) @@ -255,7 +216,7 @@ static void fillIndicesT(TriangleIndexMode mode, T vertexStart, T vertexCount, T } } break; - case TriangleIndexMode::FAN: + case TRIANGLEINDEX_FAN: { int i = 0; for (T index = 2; index < vertexCount; index++) @@ -266,7 +227,7 @@ static void fillIndicesT(TriangleIndexMode mode, T vertexStart, T vertexCount, T } } break; - case TriangleIndexMode::QUADS: + case TRIANGLEINDEX_QUADS: { // 0---2 // | / | @@ -390,21 +351,13 @@ DEFINE_STRINGMAP_BEGIN(AttributeStep, STEP_MAX_ENUM, attributeStep) } DEFINE_STRINGMAP_END(AttributeStep, STEP_MAX_ENUM, attributeStep) -DEFINE_STRINGMAP_BEGIN(DataType, DATA_MAX_ENUM, dataType) +DEFINE_STRINGMAP_BEGIN(DataTypeDeprecated, DATADEPRECATED_MAX_ENUM, dataType) { - { "snorm8", DATA_SNORM8 }, - { "unorm8", DATA_UNORM8 }, - { "int8", DATA_INT8 }, - { "uint8", DATA_UINT8 }, - { "snorm16", DATA_SNORM16 }, - { "unorm16", DATA_UNORM16 }, - { "int16", DATA_INT16 }, - { "uint16", DATA_UINT16 }, - { "int32", DATA_INT32 }, - { "uint32", DATA_UINT32 }, - { "float", DATA_FLOAT }, + { "unorm8", DATADEPRECATED_UNORM8 }, + { "unorm16", DATADEPRECATED_UNORM16 }, + { "float", DATADEPRECATED_FLOAT }, } -DEFINE_STRINGMAP_END(DataType, DATA_MAX_ENUM, dataType) +DEFINE_STRINGMAP_END(DataTypeDeprecated, DATADEPRECATED_MAX_ENUM, dataType) DEFINE_STRINGMAP_BEGIN(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) { @@ -440,15 +393,12 @@ DEFINE_STRINGMAP_BEGIN(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) { "int8vec4", DATAFORMAT_INT8_VEC4 }, { "uint8vec4", DATAFORMAT_UINT8_VEC4 }, - { "snorm16", DATAFORMAT_SNORM16 }, { "snorm16vec2", DATAFORMAT_SNORM16_VEC2 }, { "snorm16vec4", DATAFORMAT_SNORM16_VEC4 }, - { "unorm16", DATAFORMAT_UNORM16 }, { "unorm16vec2", DATAFORMAT_UNORM16_VEC2 }, { "unorm16vec4", DATAFORMAT_UNORM16_VEC4 }, - { "int16", DATAFORMAT_INT16 }, { "int16vec2", DATAFORMAT_INT16_VEC2 }, { "int16vec4", DATAFORMAT_INT16_VEC4 }, diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index aacd0f53f..cac61989f 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -56,19 +56,11 @@ enum BuiltinVertexAttributeFlags enum BufferType { - BUFFER_VERTEX = 0, - BUFFER_INDEX, - BUFFER_UNIFORM, - BUFFER_SHADER_STORAGE, - BUFFER_MAX_ENUM -}; - -enum BufferTypeFlags -{ - BUFFERFLAG_VERTEX = 1 << BUFFER_VERTEX, - BUFFERFLAG_INDEX = 1 << BUFFER_INDEX, - BUFFERFLAG_UNIFORM = 1 << BUFFER_UNIFORM, - BUFFERFLAG_SHADER_STORAGE = 1 << BUFFER_SHADER_STORAGE, + BUFFERTYPE_VERTEX = 0, + BUFFERTYPE_INDEX, + BUFFERTYPE_UNIFORM, + BUFFERTYPE_SHADER_STORAGE, + BUFFERTYPE_MAX_ENUM }; enum IndexDataType @@ -112,24 +104,12 @@ enum BufferUsage BUFFERUSAGE_MAX_ENUM }; -enum DataType +enum DataTypeDeprecated { - DATA_SNORM8, - DATA_UNORM8, - DATA_INT8, - DATA_UINT8, - - DATA_SNORM16, - DATA_UNORM16, - DATA_INT16, - DATA_UINT16, - - DATA_INT32, - DATA_UINT32, - - DATA_FLOAT, - - DATA_MAX_ENUM + DATADEPRECATED_UNORM8, + DATADEPRECATED_UNORM16, + DATADEPRECATED_FLOAT, + DATADEPRECATED_MAX_ENUM }; // Value types used when interfacing with the GPU (vertex and shader data). @@ -164,22 +144,16 @@ enum DataFormat DATAFORMAT_UINT32_VEC4, DATAFORMAT_SNORM8_VEC4, - DATAFORMAT_UNORM8_VEC4, - DATAFORMAT_INT8_VEC4, - DATAFORMAT_UINT8_VEC4, - DATAFORMAT_SNORM16, DATAFORMAT_SNORM16_VEC2, DATAFORMAT_SNORM16_VEC4, - DATAFORMAT_UNORM16, DATAFORMAT_UNORM16_VEC2, DATAFORMAT_UNORM16_VEC4, - DATAFORMAT_INT16, DATAFORMAT_INT16_VEC2, DATAFORMAT_INT16_VEC4, @@ -213,12 +187,12 @@ enum Winding WINDING_MAX_ENUM }; -enum class TriangleIndexMode +enum TriangleIndexMode { - NONE, - STRIP, - FAN, - QUADS, + TRIANGLEINDEX_NONE, + TRIANGLEINDEX_STRIP, + TRIANGLEINDEX_FAN, + TRIANGLEINDEX_QUADS, }; enum class CommonFormat @@ -403,10 +377,8 @@ inline CommonFormat getSinglePositionFormat(bool is2D) const DataFormatInfo &getDataFormatInfo(DataFormat format); size_t getIndexDataSize(IndexDataType type); -size_t getDataTypeSize(DataType datatype); -bool isDataTypeInteger(DataType datatype); - IndexDataType getIndexDataTypeFromMax(size_t maxvalue); +DataFormat getIndexDataFormat(IndexDataType type); int getIndexCount(TriangleIndexMode mode, int vertexCount); @@ -418,7 +390,7 @@ DECLARE_STRINGMAP(IndexDataType); DECLARE_STRINGMAP(BufferUsage); DECLARE_STRINGMAP(PrimitiveType); DECLARE_STRINGMAP(AttributeStep); -DECLARE_STRINGMAP(DataType); +DECLARE_STRINGMAP(DataTypeDeprecated); DECLARE_STRINGMAP(DataFormat); DECLARE_STRINGMAP(DataBaseType); DECLARE_STRINGMAP(CullMode); diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 0ea9e52c0..ef45b95be 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1503,7 +1503,7 @@ static Mesh *newCustomMesh(lua_State *L) // First argument is the vertex format, second is a table of vertices or // the number of vertices. - std::vector vertexformat; + std::vector vertexformat; PrimitiveType drawmode = luax_optmeshdrawmode(L, 3, PRIMITIVE_TRIANGLE_FAN); BufferUsage usage = luax_optmeshusage(L, 4, BUFFERUSAGE_DYNAMIC); @@ -1525,27 +1525,35 @@ static Mesh *newCustomMesh(lua_State *L) for (int j = 1; j <= 3; j++) lua_rawgeti(L, -j, j); - Mesh::AttribFormat format; - format.name = luaL_checkstring(L, -3); + const char *name = luaL_checkstring(L, -3); + DataFormat format = DATAFORMAT_FLOAT; const char *tname = luaL_checkstring(L, -2); - if (strcmp(tname, "byte") == 0) // Legacy name. - format.type = DATA_UNORM8; - else if (!getConstant(tname, format.type)) - { - luax_enumerror(L, "Mesh vertex data type name", getConstants(format.type), tname); - return nullptr; - } - format.components = (int) luaL_checkinteger(L, -1); - if (format.components <= 0 || format.components > 4) + if (!getConstant(tname, format)) { - luaL_error(L, "Number of vertex attribute components must be between 1 and 4 (got %d)", format.components); - return nullptr; + DataTypeDeprecated legacyType = DATADEPRECATED_FLOAT; + + if (strcmp(tname, "byte") == 0) // Legacy name. + legacyType = DATADEPRECATED_UNORM8; + else if (!getConstant(tname, legacyType)) + { + luax_enumerror(L, "Mesh vertex data format name", getConstants(format), tname); + return nullptr; + } + + int components = (int) luaL_checkinteger(L, -1); + if (components <= 0 || components > 4) + { + luaL_error(L, "Number of vertex attribute components must be between 1 and 4 (got %d)", components); + return nullptr; + } + + // TODO: convert legacy type+components to new format enum. } lua_pop(L, 4); - vertexformat.push_back(format); + vertexformat.emplace_back(name, format); } if (lua_isnumber(L, 2)) @@ -1570,10 +1578,6 @@ static Mesh *newCustomMesh(lua_State *L) } lua_pop(L, 1); - int vertexcomponents = 0; - for (const Mesh::AttribFormat &format : vertexformat) - vertexcomponents += format.components; - size_t numvertices = luax_objlen(L, 2); luax_catchexcept(L, [&](){ t = instance()->newMesh(vertexformat, numvertices, drawmode, usage); }); @@ -1590,7 +1594,8 @@ static Mesh *newCustomMesh(lua_State *L) int n = 0; for (size_t i = 0; i < vertexformat.size(); i++) { - int components = vertexformat[i].components; + const auto &info = getDataFormatInfo(vertexformat[i].format); + int components = info.components; // get vertices[vertindex][n] for (int c = 0; c < components; c++) @@ -1600,7 +1605,7 @@ static Mesh *newCustomMesh(lua_State *L) } // Fetch the values from Lua and store them in data buffer. - luax_writeAttributeData(L, -components, vertexformat[i].type, components, data); + luax_writeAttributeData(L, -components, vertexformat[i].format, components, data); lua_pop(L, components); diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index 8bad4cbfa..4f6d5c617 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -54,7 +54,7 @@ template static inline size_t writeSNormData(lua_State *L, int startidx, int components, char *data) { auto componentdata = (T *) data; - auto maxval = std::numeric_limits::max(); + const auto maxval = std::numeric_limits::max(); for (int i = 0; i < components; i++) componentdata[i] = (T) (luax_optnumberclamped(L, startidx + i, -1.0, 1.0, defaultComponents[i]) * maxval); @@ -66,7 +66,7 @@ template static inline size_t writeUNormData(lua_State *L, int startidx, int components, char *data) { auto componentdata = (T *) data; - auto maxval = std::numeric_limits::max(); + const auto maxval = std::numeric_limits::max(); for (int i = 0; i < components; i++) componentdata[i] = (T) (luax_optnumberclamped01(L, startidx + i, 1.0) * maxval); @@ -74,32 +74,54 @@ static inline size_t writeUNormData(lua_State *L, int startidx, int components, return sizeof(T) * components; } -char *luax_writeAttributeData(lua_State *L, int startidx, DataType type, int components, char *data) +char *luax_writeAttributeData(lua_State *L, int startidx, DataFormat format, int components, char *data) { - switch (type) + switch (format) { - case DATA_SNORM8: - return data + writeSNormData(L, startidx, components, data); - case DATA_UNORM8: - return data + writeUNormData(L, startidx, components, data); - case DATA_INT8: - return data + writeData(L, startidx, components, data); - case DATA_UINT8: - return data + writeData(L, startidx, components, data); - case DATA_SNORM16: - return data + writeSNormData(L, startidx, components, data); - case DATA_UNORM16: - return data + writeUNormData(L, startidx, components, data); - case DATA_INT16: - return data + writeData(L, startidx, components, data); - case DATA_UINT16: - return data + writeData(L, startidx, components, data); - case DATA_INT32: - return data + writeData(L, startidx, components, data); - case DATA_UINT32: - return data + writeData(L, startidx, components, data); - case DATA_FLOAT: + case DATAFORMAT_FLOAT: + case DATAFORMAT_FLOAT_VEC2: + case DATAFORMAT_FLOAT_VEC3: + case DATAFORMAT_FLOAT_VEC4: return data + writeData(L, startidx, components, data); + + case DATAFORMAT_INT32: + case DATAFORMAT_INT32_VEC2: + case DATAFORMAT_INT32_VEC3: + case DATAFORMAT_INT32_VEC4: + return data + writeData(L, startidx, components, data); + + case DATAFORMAT_UINT32: + case DATAFORMAT_UINT32_VEC2: + case DATAFORMAT_UINT32_VEC3: + case DATAFORMAT_UINT32_VEC4: + return data + writeData(L, startidx, components, data); + + case DATAFORMAT_SNORM8_VEC4: + return data + writeSNormData(L, startidx, 4, data); + case DATAFORMAT_UNORM8_VEC4: + return data + writeUNormData(L, startidx, 4, data); + case DATAFORMAT_INT8_VEC4: + return data + writeData(L, startidx, 4, data); + case DATAFORMAT_UINT8_VEC4: + return data + writeData(L, startidx, 4, data); + + case DATAFORMAT_SNORM16_VEC2: + case DATAFORMAT_SNORM16_VEC4: + return data + writeSNormData(L, startidx, components, data); + + case DATAFORMAT_UNORM16_VEC2: + case DATAFORMAT_UNORM16_VEC4: + return data + writeUNormData(L, startidx, components, data); + + case DATAFORMAT_INT16_VEC2: + case DATAFORMAT_INT16_VEC4: + return data + writeData(L, startidx, components, data); + + case DATAFORMAT_UINT16: + case DATAFORMAT_UINT16_VEC2: + case DATAFORMAT_UINT16_VEC4: + return data + writeData(L, startidx, components, data); + default: return data; } @@ -108,7 +130,7 @@ char *luax_writeAttributeData(lua_State *L, int startidx, DataType type, int com template static inline size_t readData(lua_State *L, int components, const char *data) { - auto componentdata = (const T *) data; + const auto componentdata = (const T *) data; for (int i = 0; i < components; i++) lua_pushnumber(L, (lua_Number) componentdata[i]); @@ -119,8 +141,8 @@ static inline size_t readData(lua_State *L, int components, const char *data) template static inline size_t readSNormData(lua_State *L, int components, const char *data) { - auto componentdata = (const T *) data; - auto maxval = std::numeric_limits::max(); + const auto componentdata = (const T *) data; + const auto maxval = std::numeric_limits::max(); for (int i = 0; i < components; i++) lua_pushnumber(L, std::max(-1.0, (lua_Number) componentdata[i] / (lua_Number)maxval)); @@ -131,8 +153,8 @@ static inline size_t readSNormData(lua_State *L, int components, const char *dat template static inline size_t readUNormData(lua_State *L, int components, const char *data) { - auto componentdata = (const T *) data; - auto maxval = std::numeric_limits::max(); + const auto componentdata = (const T *) data; + const auto maxval = std::numeric_limits::max(); for (int i = 0; i < components; i++) lua_pushnumber(L, (lua_Number) componentdata[i] / (lua_Number)maxval); @@ -140,32 +162,54 @@ static inline size_t readUNormData(lua_State *L, int components, const char *dat return sizeof(T) * components; } -const char *luax_readAttributeData(lua_State *L, DataType type, int components, const char *data) +const char *luax_readAttributeData(lua_State *L, DataFormat format, int components, const char *data) { - switch (type) + switch (format) { - case DATA_SNORM8: - return data + readSNormData(L, components, data); - case DATA_UNORM8: - return data + readUNormData(L, components, data); - case DATA_INT8: - return data + readData(L, components, data); - case DATA_UINT8: - return data + readData(L, components, data); - case DATA_SNORM16: - return data + readSNormData(L, components, data); - case DATA_UNORM16: - return data + readUNormData(L, components, data); - case DATA_INT16: - return data + readData(L, components, data); - case DATA_UINT16: - return data + readData(L, components, data); - case DATA_INT32: - return data + readData(L, components, data); - case DATA_UINT32: - return data + readData(L, components, data); - case DATA_FLOAT: + case DATAFORMAT_FLOAT: + case DATAFORMAT_FLOAT_VEC2: + case DATAFORMAT_FLOAT_VEC3: + case DATAFORMAT_FLOAT_VEC4: return data + readData(L, components, data); + + case DATAFORMAT_INT32: + case DATAFORMAT_INT32_VEC2: + case DATAFORMAT_INT32_VEC3: + case DATAFORMAT_INT32_VEC4: + return data + readData(L, components, data); + + case DATAFORMAT_UINT32: + case DATAFORMAT_UINT32_VEC2: + case DATAFORMAT_UINT32_VEC3: + case DATAFORMAT_UINT32_VEC4: + return data + readData(L, components, data); + + case DATAFORMAT_SNORM8_VEC4: + return data + readSNormData(L, 4, data); + case DATAFORMAT_UNORM8_VEC4: + return data + readUNormData(L, 4, data); + case DATAFORMAT_INT8_VEC4: + return data + readData(L, 4, data); + case DATAFORMAT_UINT8_VEC4: + return data + readData(L, 4, data); + + case DATAFORMAT_SNORM16_VEC2: + case DATAFORMAT_SNORM16_VEC4: + return data + readSNormData(L, components, data); + + case DATAFORMAT_UNORM16_VEC2: + case DATAFORMAT_UNORM16_VEC4: + return data + readUNormData(L, components, data); + + case DATAFORMAT_INT16_VEC2: + case DATAFORMAT_INT16_VEC4: + return data + readData(L, components, data); + + case DATAFORMAT_UINT16: + case DATAFORMAT_UINT16_VEC2: + case DATAFORMAT_UINT16_VEC4: + return data + readData(L, components, data); + default: return data; } @@ -216,11 +260,11 @@ int w_Mesh_setVertices(lua_State *L) if (vertstart + vertcount > totalverts) return luaL_error(L, "Too many vertices (expected at most %d, got %d)", totalverts - vertstart, vertcount); - const std::vector &vertexformat = t->getVertexFormat(); + const std::vector &vertexformat = t->getVertexFormat(); int ncomponents = 0; - for (const Mesh::AttribFormat &format : vertexformat) - ncomponents += format.components; + for (const Buffer::DataMember &member : vertexformat) + ncomponents += member.info.components; char *data = (char *) t->mapVertexData() + byteoffset; @@ -236,11 +280,11 @@ int w_Mesh_setVertices(lua_State *L) int idx = -ncomponents; - for (const Mesh::AttribFormat &format : vertexformat) + for (const Buffer::DataMember &member : vertexformat) { // Fetch the values from Lua and store them in data buffer. - data = luax_writeAttributeData(L, idx, format.type, format.components, data); - idx += format.components; + data = luax_writeAttributeData(L, idx, member.decl.format, member.info.components, data); + idx += member.info.components; } lua_pop(L, ncomponents + 1); @@ -257,7 +301,7 @@ int w_Mesh_setVertex(lua_State *L) bool istable = lua_istable(L, 3); - const std::vector &vertexformat = t->getVertexFormat(); + const std::vector &vertexformat = t->getVertexFormat(); char *data = (char *) t->getVertexScratchBuffer(); char *writtendata = data; @@ -266,25 +310,28 @@ int w_Mesh_setVertex(lua_State *L) if (istable) { - for (const Mesh::AttribFormat &format : vertexformat) + for (const Buffer::DataMember &member : vertexformat) { - for (int i = idx; i < idx + format.components; i++) + int components = member.info.components; + + for (int i = idx; i < idx + components; i++) lua_rawgeti(L, 3, i); // Fetch the values from Lua and store them in data buffer. - writtendata = luax_writeAttributeData(L, -format.components, format.type, format.components, writtendata); + writtendata = luax_writeAttributeData(L, -components, member.decl.format, components, writtendata); - idx += format.components; - lua_pop(L, format.components); + idx += components; + lua_pop(L, components); } } else { - for (const Mesh::AttribFormat &format : vertexformat) + for (const Buffer::DataMember &member : vertexformat) { // Fetch the values from Lua and store them in data buffer. - writtendata = luax_writeAttributeData(L, idx, format.type, format.components, writtendata); - idx += format.components; + int components = member.info.components; + writtendata = luax_writeAttributeData(L, idx, member.decl.format, components, writtendata); + idx += components; } } @@ -297,7 +344,7 @@ int w_Mesh_getVertex(lua_State *L) Mesh *t = luax_checkmesh(L, 1); size_t index = (size_t) luaL_checkinteger(L, 2) - 1; - const std::vector &vertexformat = t->getVertexFormat(); + const std::vector &vertexformat = t->getVertexFormat(); char *data = (char *) t->getVertexScratchBuffer(); const char *readdata = data; @@ -306,10 +353,11 @@ int w_Mesh_getVertex(lua_State *L) int n = 0; - for (const Mesh::AttribFormat &format : vertexformat) + for (const Buffer::DataMember &member : vertexformat) { - readdata = luax_readAttributeData(L, format.type, format.components, readdata); - n += format.components; + int components = member.info.components; + readdata = luax_readAttributeData(L, member.decl.format, components, readdata); + n += components; } return n; @@ -321,15 +369,18 @@ int w_Mesh_setVertexAttribute(lua_State *L) size_t vertindex = (size_t) luaL_checkinteger(L, 2) - 1; int attribindex = (int) luaL_checkinteger(L, 3) - 1; - DataType type; - int components; - luax_catchexcept(L, [&](){ type = t->getAttributeInfo(attribindex, components); }); + const auto &vertexformat = t->getVertexFormat(); + + if (attribindex < 0 || attribindex >= (int) vertexformat.size()) + return luaL_error(L, "Invalid vertex attribute index: %d", attribindex + 1); + + const Buffer::DataMember &member = vertexformat[attribindex]; // Maximum possible size for a single vertex attribute. char data[sizeof(float) * 4]; // Fetch the values from Lua and store them in the data buffer. - luax_writeAttributeData(L, 4, type, components, data); + luax_writeAttributeData(L, 4, member.decl.format, member.info.components, data); luax_catchexcept(L, [&](){ t->setVertexAttribute(vertindex, attribindex, data, sizeof(float) * 4); }); return 0; @@ -341,17 +392,20 @@ int w_Mesh_getVertexAttribute(lua_State *L) size_t vertindex = (size_t) luaL_checkinteger(L, 2) - 1; int attribindex = (int) luaL_checkinteger(L, 3) - 1; - DataType type; - int components; - luax_catchexcept(L, [&](){ type = t->getAttributeInfo(attribindex, components); }); + const auto &vertexformat = t->getVertexFormat(); + + if (attribindex < 0 || attribindex >= (int) vertexformat.size()) + return luaL_error(L, "Invalid vertex attribute index: %d", attribindex + 1); + + const Buffer::DataMember &member = vertexformat[attribindex]; // Maximum possible size for a single vertex attribute. char data[sizeof(float) * 4]; luax_catchexcept(L, [&](){ t->getVertexAttribute(vertindex, attribindex, data, sizeof(float) * 4); }); - luax_readAttributeData(L, type, components, data); - return components; + luax_readAttributeData(L, member.decl.format, member.info.components, data); + return member.info.components; } int w_Mesh_getVertexCount(lua_State *L) @@ -365,28 +419,27 @@ int w_Mesh_getVertexFormat(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); - const std::vector &vertexformat = t->getVertexFormat(); + const std::vector &vertexformat = t->getVertexFormat(); lua_createtable(L, (int) vertexformat.size(), 0); const char *tname = nullptr; for (size_t i = 0; i < vertexformat.size(); i++) { - if (!getConstant(vertexformat[i].type, tname)) - return luax_enumerror(L, "vertex attribute data type", getConstants(vertexformat[i].type), tname); + const auto &decl = vertexformat[i].decl; + + if (!getConstant(decl.format, tname)) + return luax_enumerror(L, "vertex attribute data type", getConstants(decl.format), tname); lua_createtable(L, 3, 0); - lua_pushstring(L, vertexformat[i].name.c_str()); + lua_pushstring(L, decl.name.c_str()); lua_rawseti(L, -2, 1); lua_pushstring(L, tname); lua_rawseti(L, -2, 2); - lua_pushinteger(L, vertexformat[i].components); - lua_rawseti(L, -2, 3); - - // format[i] = {name, type, components} + // format[i] = {name, type} lua_rawseti(L, -2, (int) i + 1); } diff --git a/src/modules/graphics/wrap_Mesh.h b/src/modules/graphics/wrap_Mesh.h index b9477c624..29bc319bf 100644 --- a/src/modules/graphics/wrap_Mesh.h +++ b/src/modules/graphics/wrap_Mesh.h @@ -30,8 +30,8 @@ namespace love namespace graphics { -char *luax_writeAttributeData(lua_State *L, int startidx, DataType type, int components, char *data); -const char *luax_readAttributeData(lua_State *L, DataType type, int components, const char *data); +char *luax_writeAttributeData(lua_State *L, int startidx, DataFormat format, int components, char *data); +const char *luax_readAttributeData(lua_State *L, DataFormat format, int components, const char *data); Mesh *luax_checkmesh(lua_State *L, int idx); extern "C" int luaopen_mesh(lua_State *L);