From b0232a4a6bb0bdcfc2f995f4cd62fa15b9741ce9 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 12 Jan 2020 16:41:23 -0400 Subject: [PATCH 01/26] Initial work on unified graphics buffers representing different types of data. --- src/modules/graphics/Buffer.cpp | 35 ++++++- src/modules/graphics/Buffer.h | 114 ++++++++++++++++++----- src/modules/graphics/Graphics.cpp | 2 +- src/modules/graphics/Graphics.h | 5 +- src/modules/graphics/Mesh.cpp | 8 +- src/modules/graphics/ParticleSystem.cpp | 2 +- src/modules/graphics/SpriteBatch.cpp | 4 +- src/modules/graphics/Text.cpp | 2 +- src/modules/graphics/opengl/Buffer.cpp | 101 +++++++++++--------- src/modules/graphics/opengl/Buffer.h | 9 +- src/modules/graphics/opengl/Graphics.cpp | 10 +- src/modules/graphics/opengl/Graphics.h | 3 +- src/modules/graphics/opengl/OpenGL.cpp | 4 + src/modules/graphics/vertex.h | 12 ++- 14 files changed, 219 insertions(+), 92 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index f67e46d54..11df52b0e 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -19,21 +19,48 @@ **/ #include "Buffer.h" +#include "Graphics.h" namespace love { namespace graphics { -Buffer::Buffer(size_t size, BufferType type, vertex::Usage usage, uint32 mapflags) +Buffer::Buffer(size_t size, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags) : size(size) - , type(type) + , typeFlags(typeflags) , usage(usage) - , map_flags(mapflags) - , is_mapped(false) + , mapFlags(mapflags) + , mapped(false) { } +Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, size_t arraylength) + : Buffer(0, settings.typeFlags, settings.usage, settings.mapFlags) +{ + 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 && format.size() > 1) + throw love::Exception("test"); + + for (const auto &member : format) + { + if (indexbuffer) + { + if (member.type != DATA_UINT16 && member.type != DATA_UINT32) + throw love::Exception("test"); + } + + if (uniformbuffer) + { + + } + } +} + Buffer::~Buffer() { } diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 8d6df1932..8c26bb456 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -28,12 +28,16 @@ // C #include +#include +#include namespace love { namespace graphics { +class Graphics; + /** * A block of GPU-owned memory. Currently meant for internal use. **/ @@ -47,16 +51,90 @@ public: MAP_READ = (1 << 1), }; - Buffer(size_t size, BufferType type, vertex::Usage usage, uint32 mapflags); + enum DataType + { + DATA_FLOAT, + DATA_FLOAT_VEC2, + DATA_FLOAT_VEC3, + DATA_FLOAT_VEC4, + + DATA_FLOAT_MAT2X2, + DATA_FLOAT_MAT2X3, + DATA_FLOAT_MAT2X4, + + DATA_FLOAT_MAT3X2, + DATA_FLOAT_MAT3X3, + DATA_FLOAT_MAT3X4, + + DATA_FLOAT_MAT4X2, + DATA_FLOAT_MAT4X3, + DATA_FLOAT_MAT4X4, + + DATA_INT32, + DATA_INT32_VEC2, + DATA_INT32_VEC3, + DATA_INT32_VEC4, + + DATA_UINT32, + DATA_UINT32_VEC2, + DATA_UINT32_VEC3, + DATA_UINT32_VEC4, + + DATA_SNORM8_VEC4, + + DATA_UNORM8_VEC4, + + DATA_INT8_VEC4, + + DATA_UINT8_VEC4, + + DATA_SNORM16, + DATA_SNORM16_VEC2, + DATA_SNORM16_VEC4, + + DATA_UNORM16, + DATA_UNORM16_VEC2, + DATA_UNORM16_VEC4, + + DATA_INT16, + DATA_INT16_VEC2, + DATA_INT16_VEC4, + + DATA_UINT16, + DATA_UINT16_VEC2, + DATA_UINT16_VEC4, + + DATA_BOOL, + DATA_BOOL_VEC2, + DATA_BOOL_VEC3, + DATA_BOOL_VEC4, + + DATA_MAX_ENUM + }; + + struct DataMember + { + std::string name; + DataType type; + int arraySize; + }; + + struct Settings + { + BufferTypeFlags typeFlags; + MapFlags mapFlags; + vertex::Usage usage; + }; + + Buffer(size_t size, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags); + Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, size_t arraylength); virtual ~Buffer(); size_t getSize() const { return size; } - - BufferType getType() const { return type; } - + BufferTypeFlags getTypeFlags() const { return typeFlags; } vertex::Usage getUsage() const { return usage; } - - bool isMapped() const { return is_mapped; } + bool isMapped() const { return mapped; } + uint32 getMapFlags() const { return mapFlags; } /** * Map the Buffer to client memory. @@ -92,36 +170,22 @@ public: **/ virtual void copyTo(size_t offset, size_t size, Buffer *other, size_t otheroffset) = 0; - uint32 getMapFlags() const { return map_flags; } - class Mapper { public: - /** - * Memory-maps a Buffer. - */ Mapper(Buffer &buffer) : buf(buffer) { elems = buf.map(); } - /** - * unmaps the buffer - */ ~Mapper() { buf.unmap(); } - /** - * Get pointer to memory mapped region - */ - void *get() - { - return elems; - } + void *get() { return elems; } private: @@ -130,20 +194,22 @@ public: }; // Mapper +// static size_t getDataTypeSize(DataType type, bool uniform) + protected: // The size of the buffer, in bytes. size_t size; // The type of the buffer object. - BufferType type; + BufferTypeFlags typeFlags; // Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW. vertex::Usage usage; - uint32 map_flags; + uint32 mapFlags; - bool is_mapped; + bool mapped; }; // Buffer diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 835344e29..f0e580760 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -173,7 +173,7 @@ void Graphics::createQuadIndexBuffer() return; size_t size = sizeof(uint16) * (LOVE_UINT16_MAX / 4) * 6; - quadIndexBuffer = newBuffer(size, nullptr, BUFFER_INDEX, vertex::USAGE_STATIC, 0); + quadIndexBuffer = newBuffer(size, nullptr, BUFFERFLAG_INDEX, vertex::USAGE_STATIC, 0); Buffer::Mapper map(*quadIndexBuffer); vertex::fillIndices(vertex::TriangleIndexMode::QUADS, 0, LOVE_UINT16_MAX, (uint16 *) map.get()); diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index e8f146cf1..cc87d9431 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -445,7 +445,10 @@ 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, BufferType type, vertex::Usage usage, uint32 mapflags) = 0; + virtual Buffer *newBuffer(size_t size, const void *data, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags) = 0; + virtual Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, size_t arraylength) = 0; + +// Buffer *newIndexBuffer(IndexDataType dataType, const void *indices, size_t bytesize, vertex::Usage usage, uint32 mapflags) = 0; Mesh *newMesh(const std::vector &vertices, PrimitiveType drawmode, vertex::Usage usage); Mesh *newMesh(int vertexcount, PrimitiveType drawmode, vertex::Usage usage); diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 7c3a42c95..8695f852c 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -81,7 +81,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma if (vertexCount == 0) throw love::Exception("Data size is too small for specified vertex attribute formats."); - vertexBuffer = gfx->newBuffer(datasize, data, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); + vertexBuffer = gfx->newBuffer(datasize, data, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); vertexScratchBuffer = new char[vertexStride]; } @@ -107,7 +107,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma size_t buffersize = vertexCount * vertexStride; - vertexBuffer = gfx->newBuffer(buffersize, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); + vertexBuffer = gfx->newBuffer(buffersize, nullptr, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); // Initialize the buffer's contents to 0. memset(vertexBuffer->map(), 0, buffersize); @@ -420,7 +420,7 @@ void Mesh::setVertexMap(const std::vector &map) if (!indexBuffer && size > 0) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - indexBuffer = gfx->newBuffer(size, nullptr, BUFFER_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ); + indexBuffer = gfx->newBuffer(size, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ); } useIndexBuffer = true; @@ -457,7 +457,7 @@ void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasiz if (!indexBuffer && datasize > 0) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - indexBuffer = gfx->newBuffer(datasize, nullptr, BUFFER_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ); + indexBuffer = gfx->newBuffer(datasize, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ); } indexCount = datasize / vertex::getIndexDataSize(datatype); diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index 35cb48979..6e1d35051 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -191,7 +191,7 @@ 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, BUFFER_VERTEX, vertex::USAGE_STREAM, 0); + buffer = gfx->newBuffer(bytes, nullptr, BUFFERFLAG_VERTEX, vertex::USAGE_STREAM, 0); } catch (std::bad_alloc &) { diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index 2b7348aed..d3155d7a5 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -64,7 +64,7 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usag vertex_stride = vertex::getFormatStride(vertex_format); size_t vertex_size = vertex_stride * 4 * size; - array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY); + array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY); } SpriteBatch::~SpriteBatch() @@ -222,7 +222,7 @@ void SpriteBatch::setBufferSize(int newsize) try { auto gfx = Module::getInstance(Module::M_GRAPHICS); - new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags()); + new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getTypeFlags(), array_buf->getUsage(), array_buf->getMapFlags()); // Copy as much of the old data into the new GLBuffer as can fit. size_t copy_size = vertex_stride * 4 * new_next; diff --git a/src/modules/graphics/Text.cpp b/src/modules/graphics/Text.cpp index 180862ed3..319262446 100644 --- a/src/modules/graphics/Text.cpp +++ b/src/modules/graphics/Text.cpp @@ -60,7 +60,7 @@ 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, BUFFER_VERTEX, vertex::USAGE_DYNAMIC, 0); + Buffer *new_buffer = gfx->newBuffer(newsize, nullptr, BUFFERFLAG_VERTEX, vertex::USAGE_DYNAMIC, 0); if (vertex_buffer != nullptr) vertex_buffer->copyTo(0, vertex_buffer->getSize(), new_buffer, 0); diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index b50227552..79f5cc8b5 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -35,18 +35,27 @@ namespace graphics namespace opengl { -Buffer::Buffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) - : love::graphics::Buffer(size, type, usage, mapflags) +Buffer::Buffer(size_t size, const void *data, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags) + : love::graphics::Buffer(size, typeflags, usage, mapflags) , vbo(0) - , memory_map(nullptr) - , modified_offset(0) - , modified_size(0) + , memoryMap(nullptr) + , modifiedOffset(0) + , modifiedSize(0) { - target = OpenGL::getGLBufferType(type); + 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; + + target = OpenGL::getGLBufferType(mapType); try { - memory_map = new char[size]; + memoryMap = new char[size]; } catch (std::bad_alloc &) { @@ -54,11 +63,11 @@ Buffer::Buffer(size_t size, const void *data, BufferType type, vertex::Usage usa } if (data != nullptr) - memcpy(memory_map, data, size); + memcpy(memoryMap, data, size); if (!load(data != nullptr)) { - delete[] memory_map; + delete[] memoryMap; throw love::Exception("Could not load vertex buffer (out of VRAM?)"); } } @@ -68,20 +77,20 @@ Buffer::~Buffer() if (vbo != 0) unload(); - delete[] memory_map; + delete[] memoryMap; } void *Buffer::map() { - if (is_mapped) - return memory_map; + if (mapped) + return memoryMap; - is_mapped = true; + mapped = true; - modified_offset = 0; - modified_size = 0; + modifiedOffset = 0; + modifiedSize = 0; - return memory_map; + return memoryMap; } void Buffer::unmapStatic(size_t offset, size_t size) @@ -90,8 +99,8 @@ void Buffer::unmapStatic(size_t offset, size_t size) return; // Upload the mapped data to the buffer. - gl.bindBuffer(type, vbo); - glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, memory_map + offset); + gl.bindBuffer(mapType, vbo); + glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, memoryMap + offset); } void Buffer::unmapStream() @@ -100,40 +109,40 @@ void Buffer::unmapStream() // "orphan" current buffer to avoid implicit synchronisation on the GPU: // http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf - gl.bindBuffer(type, vbo); + gl.bindBuffer(mapType, vbo); glBufferData(target, (GLsizeiptr) getSize(), nullptr, glusage); #if LOVE_WINDOWS // TODO: Verify that this codepath is a useful optimization. if (gl.getVendor() == OpenGL::VENDOR_INTEL) - glBufferData(target, (GLsizeiptr) getSize(), memory_map, glusage); + glBufferData(target, (GLsizeiptr) getSize(), memoryMap, glusage); else #endif - glBufferSubData(target, 0, (GLsizeiptr) getSize(), memory_map); + glBufferSubData(target, 0, (GLsizeiptr) getSize(), memoryMap); } void Buffer::unmap() { - if (!is_mapped) + if (!mapped) return; - if ((map_flags & MAP_EXPLICIT_RANGE_MODIFY) != 0) + if ((mapFlags & MAP_EXPLICIT_RANGE_MODIFY) != 0) { - modified_offset = std::min(modified_offset, getSize() - 1); - modified_size = std::min(modified_size, getSize() - modified_offset); + modifiedOffset = std::min(modifiedOffset, getSize() - 1); + modifiedSize = std::min(modifiedSize, getSize() - modifiedOffset); } else { - modified_offset = 0; - modified_size = getSize(); + modifiedOffset = 0; + modifiedSize = getSize(); } - if (modified_size > 0) + if (modifiedSize > 0) { switch (getUsage()) { case vertex::USAGE_STATIC: - unmapStatic(modified_offset, modified_size); + unmapStatic(modifiedOffset, modifiedSize); break; case vertex::USAGE_STREAM: unmapStream(); @@ -142,45 +151,45 @@ void Buffer::unmap() default: // It's probably more efficient to treat it like a streaming buffer if // at least a third of its contents have been modified during the map(). - if (modified_size >= getSize() / 3) + if (modifiedSize >= getSize() / 3) unmapStream(); else - unmapStatic(modified_offset, modified_size); + unmapStatic(modifiedOffset, modifiedSize); break; } } - modified_offset = 0; - modified_size = 0; + modifiedOffset = 0; + modifiedSize = 0; - is_mapped = false; + mapped = false; } void Buffer::setMappedRangeModified(size_t offset, size_t modifiedsize) { - if (!is_mapped || !(map_flags & MAP_EXPLICIT_RANGE_MODIFY)) + if (!mapped || !(mapFlags & MAP_EXPLICIT_RANGE_MODIFY)) return; // We're being conservative right now by internally marking the whole range // from the start of section a to the end of section b as modified if both // a and b are marked as modified. - size_t old_range_end = modified_offset + modified_size; - modified_offset = std::min(modified_offset, offset); + size_t oldrangeend = modifiedOffset + modifiedSize; + modifiedOffset = std::min(modifiedOffset, offset); - size_t new_range_end = std::max(offset + modifiedsize, old_range_end); - modified_size = new_range_end - modified_offset; + size_t newrangeend = std::max(offset + modifiedsize, oldrangeend); + modifiedSize = newrangeend - modifiedOffset; } void Buffer::fill(size_t offset, size_t size, const void *data) { - memcpy(memory_map + offset, data, size); + memcpy(memoryMap + offset, data, size); - if (is_mapped) + if (mapped) setMappedRangeModified(offset, size); else { - gl.bindBuffer(type, vbo); + gl.bindBuffer(mapType, vbo); glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, data); } } @@ -192,7 +201,7 @@ ptrdiff_t Buffer::getHandle() const void Buffer::copyTo(size_t offset, size_t size, love::graphics::Buffer *other, size_t otheroffset) { - other->fill(otheroffset, size, memory_map + offset); + other->fill(otheroffset, size, memoryMap + offset); } bool Buffer::loadVolatile() @@ -208,13 +217,13 @@ void Buffer::unloadVolatile() bool Buffer::load(bool restore) { glGenBuffers(1, &vbo); - gl.bindBuffer(type, 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 ? memory_map : nullptr; + 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())); @@ -224,7 +233,7 @@ bool Buffer::load(bool restore) void Buffer::unload() { - is_mapped = false; + mapped = false; gl.deleteBuffer(vbo); vbo = 0; } diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index 195f0dfeb..4ca4b14cf 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -39,7 +39,7 @@ class Buffer final : public love::graphics::Buffer, public Volatile { public: - Buffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags); + Buffer(size_t size, const void *data, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags); virtual ~Buffer(); void *map() override; @@ -62,16 +62,17 @@ private: void unmapStatic(size_t offset, size_t size); void unmapStream(); + BufferType mapType; GLenum target; // The VBO identifier. Assigned by OpenGL. GLuint vbo; // A pointer to mapped memory. - char *memory_map; + char *memoryMap; - size_t modified_offset; - size_t modified_size; + size_t modifiedOffset; + size_t modifiedSize; }; // Buffer diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index d636ed1eb..1b354c9c0 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -155,9 +155,15 @@ love::graphics::Shader *Graphics::newShaderInternal(love::graphics::ShaderStage return new Shader(vertex, pixel); } -love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) +love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags) { - return new Buffer(size, data, type, usage, mapflags); + return new Buffer(size, data, typeflags, usage, mapflags); +} + +love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const std::vector &format, size_t arraylength) +{ + // TODO + return nullptr; } void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 4e68acd2d..64b3cf115 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -63,7 +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, BufferType type, vertex::Usage usage, uint32 mapflags) override; + love::graphics::Buffer *newBuffer(size_t size, const void *data, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags) override; + love::graphics::Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, 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 28862602e..f17c3e83b 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -588,6 +588,10 @@ GLenum OpenGL::getGLBufferType(BufferType type) return GL_ARRAY_BUFFER; case BUFFER_INDEX: return GL_ELEMENT_ARRAY_BUFFER; + case BUFFER_UNIFORM: + return GL_UNIFORM_BUFFER; + case BUFFER_SHADER_STORAGE: + return GL_SHADER_STORAGE_BUFFER; case BUFFER_MAX_ENUM: return GL_ZERO; } diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 8d4e75dcc..c9893a19d 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -46,7 +46,7 @@ enum BuiltinVertexAttribute ATTRIB_MAX_ENUM }; -enum BuiltinVertexAttributeFlag +enum BuiltinVertexAttributeFlags { ATTRIBFLAG_POS = 1 << ATTRIB_POS, ATTRIBFLAG_TEXCOORD = 1 << ATTRIB_TEXCOORD, @@ -57,9 +57,19 @@ 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, +}; + enum IndexDataType { INDEX_UINT16, From ee5304ba535134c991cabf88bcda674217077172 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 13 Jan 2020 20:41:05 -0400 Subject: [PATCH 02/26] Remove vertex namespace --- src/modules/graphics/Buffer.cpp | 41 +++++++++-- src/modules/graphics/Buffer.h | 41 +++++++++-- src/modules/graphics/Font.cpp | 4 +- src/modules/graphics/Font.h | 4 +- src/modules/graphics/Graphics.cpp | 30 ++++---- src/modules/graphics/Graphics.h | 42 +++++------ src/modules/graphics/Mesh.cpp | 68 ++++++++---------- src/modules/graphics/Mesh.h | 12 ++-- src/modules/graphics/ParticleSystem.cpp | 8 +-- src/modules/graphics/ParticleSystem.h | 73 +++++++++++++++++++- src/modules/graphics/Polyline.cpp | 8 +-- src/modules/graphics/Polyline.h | 6 +- src/modules/graphics/SpriteBatch.cpp | 16 ++--- src/modules/graphics/SpriteBatch.h | 4 +- src/modules/graphics/Text.cpp | 2 +- src/modules/graphics/Text.h | 4 +- src/modules/graphics/Texture.cpp | 12 ++-- src/modules/graphics/Video.cpp | 8 +-- src/modules/graphics/opengl/Buffer.cpp | 8 +-- src/modules/graphics/opengl/Buffer.h | 2 +- src/modules/graphics/opengl/Graphics.cpp | 22 +++--- src/modules/graphics/opengl/Graphics.h | 6 +- src/modules/graphics/opengl/OpenGL.cpp | 38 +++++----- src/modules/graphics/opengl/OpenGL.h | 6 +- src/modules/graphics/opengl/Shader.cpp | 5 +- src/modules/graphics/vertex.cpp | 19 +++-- src/modules/graphics/vertex.h | 27 +++----- src/modules/graphics/wrap_Graphics.cpp | 42 +++++------ src/modules/graphics/wrap_GraphicsShader.lua | 30 ++++++++ src/modules/graphics/wrap_Mesh.cpp | 72 +++++++++---------- src/modules/graphics/wrap_Mesh.h | 4 +- 31 files changed, 398 insertions(+), 266 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 11df52b0e..c2950272e 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -26,7 +26,16 @@ namespace love namespace graphics { -Buffer::Buffer(size_t size, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags) +static const Buffer::DataTypeInfo dataTypeInfo[] +{ + // baseType, isMatrix, components, rows, columns, componentSize, packedAlign, packedSize + { Buffer::DATA_BASE_FLOAT, false, 1, 0, 0, sizeof(float), 4, 4 }, // DATA_FLOAT + +}; + +love::Type Buffer::type("GraphicsBuffer", &Object::type); + +Buffer::Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) : size(size) , typeFlags(typeflags) , usage(usage) @@ -38,6 +47,11 @@ Buffer::Buffer(size_t size, BufferTypeFlags typeflags, vertex::Usage usage, uint Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, size_t arraylength) : Buffer(0, settings.typeFlags, settings.usage, settings.mapFlags) { + if (format.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; @@ -46,17 +60,36 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector 1) throw love::Exception("test"); + size_t offset = 0; + size_t stride = 0; + for (const auto &member : format) { + DataType type = member.type; + const DataTypeInfo &info = getDataTypeInfo(type); + if (indexbuffer) { - if (member.type != DATA_UINT16 && member.type != DATA_UINT32) - throw love::Exception("test"); + if (type != DATA_UINT16 && type != DATA_UINT32) + throw love::Exception("Index buffers only support uint16 and uint32 data types."); + } + + if (vertexbuffer) + { + if (info.isMatrix) + throw love::Exception("matrix types are not supported in vertex buffers."); + + if (info.baseType == DATA_BASE_BOOL) + throw love::Exception("bool types are not supported in vertex buffers."); + + if ((info.baseType == DATA_BASE_INT || info.baseType == DATA_BASE_UINT) && !supportsGLSL3) + throw love::Exception("Integer vertex attribute data types require GLSL 3 support."); } if (uniformbuffer) { - + if (info.componentSize != 4) + throw love::Exception(""); } } } diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 8c26bb456..712d6fdef 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -23,6 +23,7 @@ // LOVE #include "common/config.h" #include "common/int.h" +#include "common/Object.h" #include "vertex.h" #include "Resource.h" @@ -41,10 +42,12 @@ class Graphics; /** * A block of GPU-owned memory. Currently meant for internal use. **/ -class Buffer : public Resource +class Buffer : public love::Object, public Resource { public: + static love::Type type; + enum MapFlags { MAP_EXPLICIT_RANGE_MODIFY = (1 << 0), // see setMappedRangeModified. @@ -112,6 +115,28 @@ public: DATA_MAX_ENUM }; + enum DataTypeBase + { + DATA_BASE_FLOAT, + DATA_BASE_INT, + DATA_BASE_UINT, + DATA_BASE_SNORM, + DATA_BASE_UNORM, + DATA_BASE_BOOL, + }; + + struct DataTypeInfo + { + DataTypeBase baseType; + bool isMatrix; + int components; + int matrixRows; + int matrixColumns; + size_t componentSize; + size_t packedAlignment; + size_t packedSize; + }; + struct DataMember { std::string name; @@ -123,16 +148,16 @@ public: { BufferTypeFlags typeFlags; MapFlags mapFlags; - vertex::Usage usage; + BufferUsage usage; }; - Buffer(size_t size, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags); + Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags); Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, size_t arraylength); virtual ~Buffer(); size_t getSize() const { return size; } BufferTypeFlags getTypeFlags() const { return typeFlags; } - vertex::Usage getUsage() const { return usage; } + BufferUsage getUsage() const { return usage; } bool isMapped() const { return mapped; } uint32 getMapFlags() const { return mapFlags; } @@ -196,8 +221,14 @@ public: // static size_t getDataTypeSize(DataType type, bool uniform) + const DataTypeInfo &getDataTypeInfo(DataType type); + protected: + std::vector format; + std::vector memberOffsets; + size_t arrayStride; + // The size of the buffer, in bytes. size_t size; @@ -205,7 +236,7 @@ protected: BufferTypeFlags typeFlags; // Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW. - vertex::Usage usage; + BufferUsage usage; uint32 mapFlags; diff --git a/src/modules/graphics/Font.cpp b/src/modules/graphics/Font.cpp index f94adaa05..25b32a60d 100644 --- a/src/modules/graphics/Font.cpp +++ b/src/modules/graphics/Font.cpp @@ -45,7 +45,7 @@ static inline uint16 normToUint16(double n) love::Type Font::type("Font", &Object::type); int Font::fontCount = 0; -const vertex::CommonFormat Font::vertexFormat = vertex::CommonFormat::XYf_STus_RGBAub; +const CommonFormat Font::vertexFormat = CommonFormat::XYf_STus_RGBAub; Font::Font(love::font::Rasterizer *r, const Texture::Filter &f) : rasterizers({r}) @@ -642,7 +642,7 @@ void Font::printv(graphics::Graphics *gfx, const Matrix4 &t, const std::vector Codepoints; - typedef vertex::XYf_STus_RGBAub GlyphVertex; + typedef XYf_STus_RGBAub GlyphVertex; - static const vertex::CommonFormat vertexFormat; + static const CommonFormat vertexFormat; enum AlignMode { diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index f0e580760..27bb1108a 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -173,10 +173,10 @@ void Graphics::createQuadIndexBuffer() return; size_t size = sizeof(uint16) * (LOVE_UINT16_MAX / 4) * 6; - quadIndexBuffer = newBuffer(size, nullptr, BUFFERFLAG_INDEX, vertex::USAGE_STATIC, 0); + quadIndexBuffer = newBuffer(size, nullptr, BUFFERFLAG_INDEX, BUFFERUSAGE_STATIC, 0); Buffer::Mapper map(*quadIndexBuffer); - vertex::fillIndices(vertex::TriangleIndexMode::QUADS, 0, LOVE_UINT16_MAX, (uint16 *) map.get()); + fillIndices(TriangleIndexMode::QUADS, 0, LOVE_UINT16_MAX, (uint16 *) map.get()); } Quad *Graphics::newQuad(Quad::Viewport v, double sw, double sh) @@ -204,7 +204,7 @@ Video *Graphics::newVideo(love::video::VideoStream *stream, float dpiscale) return new Video(this, stream, dpiscale); } -love::graphics::SpriteBatch *Graphics::newSpriteBatch(Texture *texture, int size, vertex::Usage usage) +love::graphics::SpriteBatch *Graphics::newSpriteBatch(Texture *texture, int size, BufferUsage usage) { return new SpriteBatch(this, texture, size, usage); } @@ -260,22 +260,22 @@ Shader *Graphics::newShader(const std::string &vertex, const std::string &pixel) return newShaderInternal(vertexstage.get(), pixelstage.get()); } -Mesh *Graphics::newMesh(const std::vector &vertices, PrimitiveType drawmode, vertex::Usage usage) +Mesh *Graphics::newMesh(const std::vector &vertices, PrimitiveType drawmode, BufferUsage usage) { return newMesh(Mesh::getDefaultVertexFormat(), &vertices[0], vertices.size() * sizeof(Vertex), drawmode, usage); } -Mesh *Graphics::newMesh(int vertexcount, PrimitiveType drawmode, vertex::Usage usage) +Mesh *Graphics::newMesh(int vertexcount, PrimitiveType drawmode, BufferUsage usage) { return newMesh(Mesh::getDefaultVertexFormat(), vertexcount, drawmode, usage); } -love::graphics::Mesh *Graphics::newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, vertex::Usage 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, vertex::Usage 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); } @@ -891,7 +891,7 @@ CullMode Graphics::getMeshCullMode() const return states.back().meshCullMode; } -vertex::Winding Graphics::getFrontFaceWinding() const +Winding Graphics::getFrontFaceWinding() const { return states.back().winding; } @@ -996,8 +996,6 @@ void Graphics::captureScreenshot(const ScreenshotInfo &info) Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand &cmd) { - using namespace vertex; - StreamBufferState &state = streamBufferState; bool shouldflush = false; @@ -1130,8 +1128,6 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & void Graphics::flushStreamDraws() { - using namespace vertex; - auto &sbstate = streamBufferState; if (sbstate.vertexCount == 0 && sbstate.indexCount == 0) @@ -1280,8 +1276,8 @@ void Graphics::points(const Vector2 *positions, const Colorf *colors, size_t num StreamDrawCommand cmd; cmd.primitiveMode = PRIMITIVE_POINTS; - cmd.formats[0] = vertex::getSinglePositionFormat(is2D); - cmd.formats[1] = vertex::CommonFormat::RGBAub; + cmd.formats[0] = getSinglePositionFormat(is2D); + cmd.formats[1] = CommonFormat::RGBAub; cmd.vertexCount = (int) numpoints; StreamVertexData data = requestStreamDraw(cmd); @@ -1575,9 +1571,9 @@ void Graphics::polygon(DrawMode mode, const Vector2 *coords, size_t count, bool bool is2D = t.isAffine2DTransform(); StreamDrawCommand cmd; - cmd.formats[0] = vertex::getSinglePositionFormat(is2D); - cmd.formats[1] = vertex::CommonFormat::RGBAub; - cmd.indexMode = vertex::TriangleIndexMode::FAN; + cmd.formats[0] = getSinglePositionFormat(is2D); + cmd.formats[1] = CommonFormat::RGBAub; + cmd.indexMode = TriangleIndexMode::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 cc87d9431..dd915624c 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -212,8 +212,8 @@ public: { PrimitiveType primitiveType = PRIMITIVE_TRIANGLES; - const vertex::Attributes *attributes; - const vertex::BufferBindings *buffers; + const Attributes *attributes; + const BufferBindings *buffers; int vertexStart = 0; int vertexCount = 0; @@ -224,7 +224,7 @@ public: // TODO: This should be moved out to a state transition API? CullMode cullMode = CULL_NONE; - DrawCommand(const vertex::Attributes *attribs, const vertex::BufferBindings *buffers) + DrawCommand(const Attributes *attribs, const BufferBindings *buffers) : attributes(attribs) , buffers(buffers) {} @@ -234,8 +234,8 @@ public: { PrimitiveType primitiveType = PRIMITIVE_TRIANGLES; - const vertex::Attributes *attributes; - const vertex::BufferBindings *buffers; + const Attributes *attributes; + const BufferBindings *buffers; int indexCount = 0; int instanceCount = 1; @@ -249,7 +249,7 @@ public: // TODO: This should be moved out to a state transition API? CullMode cullMode = CULL_NONE; - DrawIndexedCommand(const vertex::Attributes *attribs, const vertex::BufferBindings *buffers, Resource *indexbuffer) + DrawIndexedCommand(const Attributes *attribs, const BufferBindings *buffers, Resource *indexbuffer) : attributes(attribs) , buffers(buffers) , indexBuffer(indexbuffer) @@ -259,8 +259,8 @@ public: struct StreamDrawCommand { PrimitiveType primitiveMode = PRIMITIVE_TRIANGLES; - vertex::CommonFormat formats[2]; - vertex::TriangleIndexMode indexMode = vertex::TriangleIndexMode::NONE; + CommonFormat formats[2]; + TriangleIndexMode indexMode = TriangleIndexMode::NONE; int vertexCount = 0; Texture *texture = nullptr; Shader::StandardShader standardShaderType = Shader::STANDARD_DEFAULT; @@ -268,7 +268,7 @@ public: StreamDrawCommand() { // VS2013 can't initialize arrays in the above manner... - formats[1] = formats[0] = vertex::CommonFormat::NONE; + formats[1] = formats[0] = CommonFormat::NONE; } }; @@ -437,7 +437,7 @@ public: Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting, const Texture::Filter &filter = Texture::defaultFilter); Video *newVideo(love::video::VideoStream *stream, float dpiscale); - SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage); + SpriteBatch *newSpriteBatch(Texture *texture, int size, BufferUsage usage); ParticleSystem *newParticleSystem(Texture *texture, int size); virtual Canvas *newCanvas(const Canvas::Settings &settings) = 0; @@ -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, vertex::Usage usage, uint32 mapflags) = 0; + 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; // Buffer *newIndexBuffer(IndexDataType dataType, const void *indices, size_t bytesize, vertex::Usage usage, uint32 mapflags) = 0; - Mesh *newMesh(const std::vector &vertices, PrimitiveType drawmode, vertex::Usage usage); - Mesh *newMesh(int vertexcount, PrimitiveType drawmode, vertex::Usage usage); - Mesh *newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, vertex::Usage usage); - Mesh *newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, vertex::Usage usage); + 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); Text *newText(Font *font, const std::vector &text = {}); @@ -597,8 +597,8 @@ public: void setMeshCullMode(CullMode cull); CullMode getMeshCullMode() const; - virtual void setFrontFaceWinding(vertex::Winding winding) = 0; - vertex::Winding getFrontFaceWinding() const; + virtual void setFrontFaceWinding(Winding winding) = 0; + Winding getFrontFaceWinding() const; /** * Sets the enabled color components when rendering. @@ -833,7 +833,7 @@ public: virtual void draw(const DrawCommand &cmd) = 0; virtual void draw(const DrawIndexedCommand &cmd) = 0; - virtual void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture) = 0; + virtual void drawQuads(int start, int count, const Attributes &attributes, const BufferBindings &buffers, Texture *texture) = 0; void flushStreamDraws(); StreamVertexData requestStreamDraw(const StreamDrawCommand &command); @@ -910,7 +910,7 @@ protected: bool depthWrite = false; CullMode meshCullMode = CULL_NONE; - vertex::Winding winding = vertex::WINDING_CCW; + Winding winding = WINDING_CCW; StrongRef font; StrongRef shader; @@ -933,7 +933,7 @@ protected: StreamBuffer *indexBuffer = nullptr; PrimitiveType primitiveMode = PRIMITIVE_TRIANGLES; - vertex::CommonFormat formats[2]; + CommonFormat formats[2]; StrongRef texture; Shader::StandardShader standardShaderType = Shader::STANDARD_DEFAULT; int vertexCount = 0; @@ -945,7 +945,7 @@ protected: StreamBufferState() { vb[0] = vb[1] = nullptr; - formats[0] = formats[1] = vertex::CommonFormat::NONE; + formats[0] = formats[1] = CommonFormat::NONE; vbMap[0] = vbMap[1] = StreamBuffer::MapInfo(); } }; diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 8695f852c..24f90d435 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -37,7 +37,7 @@ namespace graphics static const char *getBuiltinAttribName(BuiltinVertexAttribute attribid) { const char *name = ""; - vertex::getConstant(attribid, name); + getConstant(attribid, name); return name; } @@ -49,9 +49,9 @@ std::vector Mesh::getDefaultVertexFormat() { // Corresponds to the love::Vertex struct. std::vector vertexformat = { - { getBuiltinAttribName(ATTRIB_POS), vertex::DATA_FLOAT, 2 }, - { getBuiltinAttribName(ATTRIB_TEXCOORD), vertex::DATA_FLOAT, 2 }, - { getBuiltinAttribName(ATTRIB_COLOR), vertex::DATA_UNORM8, 4 }, + { getBuiltinAttribName(ATTRIB_POS), DATA_FLOAT, 2 }, + { getBuiltinAttribName(ATTRIB_TEXCOORD), DATA_FLOAT, 2 }, + { getBuiltinAttribName(ATTRIB_COLOR), DATA_UNORM8, 4 }, }; return vertexformat; @@ -59,7 +59,7 @@ 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, vertex::Usage usage) +Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage) : vertexFormat(vertexformat) , vertexBuffer(nullptr) , vertexCount(0) @@ -76,17 +76,18 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma calculateAttributeSizes(gfx); vertexCount = datasize / vertexStride; - indexDataType = vertex::getIndexDataTypeFromMax(vertexCount); + indexDataType = getIndexDataTypeFromMax(vertexCount); if (vertexCount == 0) throw love::Exception("Data size is too small for specified vertex attribute formats."); - vertexBuffer = gfx->newBuffer(datasize, data, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); + 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, vertex::Usage usage) +Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) : vertexFormat(vertexformat) , vertexBuffer(nullptr) , vertexCount((size_t) vertexcount) @@ -94,7 +95,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma , indexBuffer(nullptr) , useIndexBuffer(false) , indexCount(0) - , indexDataType(vertex::getIndexDataTypeFromMax(vertexcount)) + , indexDataType(getIndexDataTypeFromMax(vertexcount)) , primitiveType(drawmode) , rangeStart(-1) , rangeCount(-1) @@ -107,7 +108,8 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma size_t buffersize = vertexCount * vertexStride; - vertexBuffer = gfx->newBuffer(buffersize, nullptr, BUFFERFLAG_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ); + 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); @@ -119,8 +121,6 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexforma Mesh::~Mesh() { - delete vertexBuffer; - delete indexBuffer; delete vertexScratchBuffer; for (const auto &attrib : attachedAttributes) @@ -151,7 +151,7 @@ void Mesh::calculateAttributeSizes(Graphics *gfx) for (const AttribFormat &format : vertexFormat) { - size_t size = vertex::getDataTypeSize(format.type) * format.components; + 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."); @@ -160,7 +160,7 @@ void Mesh::calculateAttributeSizes(Graphics *gfx) if (size % 4 != 0) throw love::Exception("Vertex attributes must have enough components to be a multiple of 32 bits."); - if (vertex::isDataTypeInteger(format.type) && !supportsGLSL3) + 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. @@ -265,7 +265,7 @@ const std::vector &Mesh::getVertexFormat() const return vertexFormat; } -vertex::DataType Mesh::getAttributeInfo(int attribindex, int &components) const +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); @@ -328,8 +328,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); + else if (attachedAttributes.size() + 1 > Attributes::MAX) + throw love::Exception("A maximum of %d attributes can be attached at once.", Attributes::MAX); newattrib.mesh = mesh; newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true; @@ -406,21 +406,15 @@ void Mesh::setVertexMap(const std::vector &map) { size_t maxval = getVertexCount(); - IndexDataType datatype = vertex::getIndexDataTypeFromMax(maxval); + IndexDataType datatype = getIndexDataTypeFromMax(maxval); // Calculate the size in bytes of the index buffer data. - size_t size = map.size() * vertex::getIndexDataSize(datatype); + size_t size = map.size() * getIndexDataSize(datatype); - if (indexBuffer && size > indexBuffer->getSize()) - { - delete indexBuffer; - indexBuffer = nullptr; - } - - if (!indexBuffer && size > 0) + if (indexBuffer.get() == nullptr || size > indexBuffer->getSize()) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - indexBuffer = gfx->newBuffer(size, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ); + indexBuffer.set(gfx->newBuffer(size, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ), Acquire::NORETAIN); } useIndexBuffer = true; @@ -448,19 +442,13 @@ void Mesh::setVertexMap(const std::vector &map) void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasize) { - if (indexBuffer && datasize > indexBuffer->getSize()) - { - delete indexBuffer; - indexBuffer = nullptr; - } - - if (!indexBuffer && datasize > 0) + if (indexBuffer.get() == nullptr || datasize > indexBuffer->getSize()) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - indexBuffer = gfx->newBuffer(datasize, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ); + indexBuffer.set(gfx->newBuffer(datasize, nullptr, BUFFERFLAG_INDEX, vertexBuffer->getUsage(), Buffer::MAP_READ), Acquire::NORETAIN); } - indexCount = datasize / vertex::getIndexDataSize(datatype); + indexCount = datasize / getIndexDataSize(datatype); if (!indexBuffer || indexCount == 0) return; @@ -592,8 +580,8 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) if (Shader::current && texture.get()) Shader::current->checkMainTexture(texture); - vertex::Attributes attributes; - vertex::BufferBindings buffers; + Attributes attributes; + BufferBindings buffers; int activebuffers = 0; @@ -608,7 +596,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) // If the attribute is one of the LOVE-defined ones, use the constant // attribute index for it, otherwise query the index from the shader. BuiltinVertexAttribute builtinattrib; - if (vertex::getConstant(attrib.first.c_str(), builtinattrib)) + if (getConstant(attrib.first.c_str(), builtinattrib)) attributeindex = (int) builtinattrib; else if (Shader::current) attributeindex = Shader::current->getVertexAttributeIndex(attrib.first); @@ -653,7 +641,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) cmd.cullMode = gfx->getMeshCullMode(); int start = std::min(std::max(0, rangeStart), (int) indexCount - 1); - cmd.indexBufferOffset = start * vertex::getIndexDataSize(indexDataType); + cmd.indexBufferOffset = start * getIndexDataSize(indexDataType); cmd.indexCount = (int) indexCount; if (rangeCount > 0) diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 148fc150d..728dc0993 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -55,12 +55,12 @@ public: struct AttribFormat { std::string name; - vertex::DataType type; + DataType type; int components; // max 4 }; - Mesh(Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, vertex::Usage usage); - Mesh(Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, vertex::Usage 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(); @@ -96,7 +96,7 @@ public: * Gets the format of each vertex attribute stored in the Mesh. **/ const std::vector &getVertexFormat() const; - vertex::DataType getAttributeInfo(int attribindex, int &components) const; + DataType getAttributeInfo(int attribindex, int &components) const; int getAttributeIndex(const std::string &name) const; /** @@ -196,7 +196,7 @@ private: std::unordered_map attachedAttributes; // Vertex buffer, for the vertex data. - Buffer *vertexBuffer; + StrongRef vertexBuffer; size_t vertexCount; size_t vertexStride; @@ -205,7 +205,7 @@ private: char *vertexScratchBuffer; // Index buffer, for the vertex map. - Buffer *indexBuffer; + StrongRef indexBuffer; bool useIndexBuffer; size_t indexCount; IndexDataType indexDataType; diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index 6e1d35051..6e1123870 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -93,7 +93,7 @@ ParticleSystem::ParticleSystem(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) + , vertexAttributes(CommonFormat::XYf_STf_RGBAub, 0) , buffer(nullptr) { if (size == 0 || size > MAX_PARTICLES) @@ -191,7 +191,7 @@ 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, vertex::USAGE_STREAM, 0); + buffer = gfx->newBuffer(bytes, nullptr, BUFFERFLAG_VERTEX, BUFFERUSAGE_STREAM, 0); } catch (std::bad_alloc &) { @@ -203,7 +203,7 @@ void ParticleSystem::createBuffers(size_t size) void ParticleSystem::deleteBuffers() { delete[] pMem; - delete buffer; + buffer->release(); pMem = nullptr; buffer = nullptr; @@ -1080,7 +1080,7 @@ void ParticleSystem::draw(Graphics *gfx, const Matrix4 &m) Graphics::TempTransform transform(gfx, m); - vertex::BufferBindings vertexbuffers; + BufferBindings vertexbuffers; vertexbuffers.set(0, buffer, 0); gfx->drawQuads(0, pCount, vertexAttributes, vertexbuffers, texture); diff --git a/src/modules/graphics/ParticleSystem.h b/src/modules/graphics/ParticleSystem.h index b220e6275..1a24266b3 100644 --- a/src/modules/graphics/ParticleSystem.h +++ b/src/modules/graphics/ParticleSystem.h @@ -558,6 +558,77 @@ private: int quadIndex; }; + struct Emitter + { + // Pointer to the beginning of the allocated memory. + Particle *pMem; + + // Pointer to a free particle. + Particle *pFree; + + // Pointer to the start of the linked list. + Particle *pHead; + + // Pointer to the end of the linked list. + Particle *pTail; + + // Whether the particle emitter is active. + bool active; + + // Insert mode of new particles. + InsertMode insertMode; + + // The number of active particles. + uint32 activeParticles; + + // The emission rate (particles/sec). + float emissionRate; + + // Used to determine when a particle should be emitted. + float emitCounter; + + // The relative position of the particle emitter. + love::Vector2 position; + love::Vector2 prevPosition; + + // Emission area spread. + AreaSpreadDistribution emissionAreaDistribution; + love::Vector2 emissionArea; + float emissionAreaAngle; + bool directionRelativeToEmissionCenter; + + // The lifetime of the particle emitter (-1 means infinite) and the life it has left. + float lifetime; + float life; + + // The particle life. + float particleLifeMin; + float particleLifeMax; + + // The direction (and spread) the particles will be emitted in. Measured in radians. + float direction; + float spread; + + // The speed. + float speedMin; + float speedMax; + + // Acceleration along the x and y axes. + love::Vector2 linearAccelerationMin; + love::Vector2 linearAccelerationMax; + + // Acceleration towards the emitter's center + float radialAccelerationMin; + float radialAccelerationMax; + + // Acceleration perpendicular to the particle's direction. + float tangentialAccelerationMin; + float tangentialAccelerationMax; + + float linearDampingMin; + float linearDampingMax; + }; + void resetOffset(); void createBuffers(size_t size); @@ -673,7 +744,7 @@ private: bool relativeRotation; - const vertex::Attributes vertexAttributes; + const Attributes vertexAttributes; Buffer *buffer; static StringMap::Entry distributionsEntries[]; diff --git a/src/modules/graphics/Polyline.cpp b/src/modules/graphics/Polyline.cpp index da1397b42..27035e48b 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 == vertex::TriangleIndexMode::STRIP) + if (triangle_mode == TriangleIndexMode::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 == vertex::TriangleIndexMode::STRIP) + if (triangle_mode == TriangleIndexMode::STRIP) advance -= 2; for (int vertex_start = 0; vertex_start < total_vertex_count; vertex_start += advance) @@ -391,8 +391,8 @@ void Polyline::draw(love::graphics::Graphics *gfx) const Vector2 *verts = vertices + vertex_start; Graphics::StreamDrawCommand cmd; - cmd.formats[0] = vertex::getSinglePositionFormat(is2D); - cmd.formats[1] = vertex::CommonFormat::RGBAub; + cmd.formats[0] = getSinglePositionFormat(is2D); + cmd.formats[1] = CommonFormat::RGBAub; cmd.indexMode = triangle_mode; cmd.vertexCount = std::min(maxvertices, total_vertex_count - vertex_start); diff --git a/src/modules/graphics/Polyline.h b/src/modules/graphics/Polyline.h index 659256b4e..efb42e9e8 100644 --- a/src/modules/graphics/Polyline.h +++ b/src/modules/graphics/Polyline.h @@ -44,7 +44,7 @@ class Polyline { public: - Polyline(vertex::TriangleIndexMode mode = vertex::TriangleIndexMode::STRIP) + Polyline(TriangleIndexMode mode = TriangleIndexMode::STRIP) : vertices(nullptr) , overdraw(nullptr) , vertex_count(0) @@ -94,7 +94,7 @@ protected: Vector2 *overdraw; size_t vertex_count; size_t overdraw_vertex_count; - vertex::TriangleIndexMode triangle_mode; + TriangleIndexMode triangle_mode; size_t overdraw_vertex_start; }; // Polyline @@ -109,7 +109,7 @@ class NoneJoinPolyline : public Polyline public: NoneJoinPolyline() - : Polyline(vertex::TriangleIndexMode::QUADS) + : Polyline(TriangleIndexMode::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 d3155d7a5..aaaf1e7ea 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -40,7 +40,7 @@ namespace graphics love::Type SpriteBatch::type("SpriteBatch", &Drawable::type); -SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage) +SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage usage) : texture(texture) , size(size) , next(0) @@ -57,11 +57,11 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usag throw love::Exception("A texture must be used when creating a SpriteBatch."); if (texture->getTextureType() == TEXTURE_2D_ARRAY) - vertex_format = vertex::CommonFormat::XYf_STPf_RGBAub; + vertex_format = CommonFormat::XYf_STPf_RGBAub; else - vertex_format = vertex::CommonFormat::XYf_STf_RGBAub; + vertex_format = CommonFormat::XYf_STf_RGBAub; - vertex_stride = vertex::getFormatStride(vertex_format); + 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); @@ -79,8 +79,6 @@ int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/) int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/) { - using namespace vertex; - if (vertex_format == CommonFormat::XYf_STPf_RGBAub) return addLayer(quad->getLayer(), quad, m, index); @@ -122,8 +120,6 @@ int SpriteBatch::addLayer(int layer, const Matrix4 &m, int index) int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index) { - using namespace vertex; - if (vertex_format != CommonFormat::XYf_STPf_RGBAub) throw love::Exception("addLayer can only be called on a SpriteBatch that uses an Array Texture!"); @@ -296,8 +292,6 @@ bool SpriteBatch::getDrawRange(int &start, int &count) const void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) { - using namespace vertex; - if (next == 0) return; @@ -345,7 +339,7 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) // If the attribute is one of the LOVE-defined ones, use the constant // attribute index for it, otherwise query the index from the shader. BuiltinVertexAttribute builtinattrib; - if (vertex::getConstant(it.first.c_str(), builtinattrib)) + if (getConstant(it.first.c_str(), builtinattrib)) attributeindex = (int) builtinattrib; else if (Shader::current) attributeindex = Shader::current->getVertexAttributeIndex(it.first); diff --git a/src/modules/graphics/SpriteBatch.h b/src/modules/graphics/SpriteBatch.h index 644a82f03..f5b9db48f 100644 --- a/src/modules/graphics/SpriteBatch.h +++ b/src/modules/graphics/SpriteBatch.h @@ -51,7 +51,7 @@ public: static love::Type type; - SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage); + SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage usage); virtual ~SpriteBatch(); int add(const Matrix4 &m, int index = -1); @@ -128,7 +128,7 @@ private: Color32 color; Colorf colorf; - vertex::CommonFormat vertex_format; + CommonFormat vertex_format; size_t vertex_stride; love::graphics::Buffer *array_buf; diff --git a/src/modules/graphics/Text.cpp b/src/modules/graphics/Text.cpp index 319262446..1909a35cf 100644 --- a/src/modules/graphics/Text.cpp +++ b/src/modules/graphics/Text.cpp @@ -60,7 +60,7 @@ 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, vertex::USAGE_DYNAMIC, 0); + Buffer *new_buffer = gfx->newBuffer(newsize, nullptr, BUFFERFLAG_VERTEX, BUFFERUSAGE_DYNAMIC, 0); if (vertex_buffer != nullptr) vertex_buffer->copyTo(0, vertex_buffer->getSize(), new_buffer, 0); diff --git a/src/modules/graphics/Text.h b/src/modules/graphics/Text.h index ab858f86b..3199b0074 100644 --- a/src/modules/graphics/Text.h +++ b/src/modules/graphics/Text.h @@ -85,8 +85,8 @@ private: StrongRef font; - vertex::Attributes vertexAttributes; - vertex::BufferBindings vertexBuffers; + Attributes vertexAttributes; + BufferBindings vertexBuffers; Buffer *vertex_buffer; diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index cbbbf0b75..f37ef41b6 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -117,8 +117,6 @@ void Texture::draw(Graphics *gfx, const Matrix4 &m) void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform) { - using namespace vertex; - if (!readable) throw love::Exception("Textures with non-readable formats cannot be drawn."); @@ -132,7 +130,7 @@ void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform) bool is2D = tm.isAffine2DTransform(); Graphics::StreamDrawCommand cmd; - cmd.formats[0] = vertex::getSinglePositionFormat(is2D); + cmd.formats[0] = getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::STf_RGBAub; cmd.indexMode = TriangleIndexMode::QUADS; cmd.vertexCount = 4; @@ -148,7 +146,7 @@ void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform) t.transformXY0((Vector3 *) data.stream[0], q->getVertexPositions(), 4); const Vector2 *texcoords = q->getVertexTexCoords(); - vertex::STf_RGBAub *vertexdata = (vertex::STf_RGBAub *) data.stream[1]; + STf_RGBAub *vertexdata = (STf_RGBAub *) data.stream[1]; Color32 c = toColor32(gfx->getColor()); @@ -167,8 +165,6 @@ void Texture::drawLayer(Graphics *gfx, int layer, const Matrix4 &m) void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) { - using namespace vertex; - if (!readable) throw love::Exception("Textures with non-readable formats cannot be drawn."); @@ -186,7 +182,7 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) Matrix4 t(tm, m); Graphics::StreamDrawCommand cmd; - cmd.formats[0] = vertex::getSinglePositionFormat(is2D); + cmd.formats[0] = getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::STPf_RGBAub; cmd.indexMode = TriangleIndexMode::QUADS; cmd.vertexCount = 4; @@ -201,7 +197,7 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) t.transformXY0((Vector3 *) data.stream[0], q->getVertexPositions(), 4); const Vector2 *texcoords = q->getVertexTexCoords(); - vertex::STPf_RGBAub *vertexdata = (vertex::STPf_RGBAub *) data.stream[1]; + STPf_RGBAub *vertexdata = (STPf_RGBAub *) data.stream[1]; for (int i = 0; i < 4; i++) { diff --git a/src/modules/graphics/Video.cpp b/src/modules/graphics/Video.cpp index 201670f6b..e3c71c1ef 100644 --- a/src/modules/graphics/Video.cpp +++ b/src/modules/graphics/Video.cpp @@ -115,9 +115,9 @@ void Video::draw(Graphics *gfx, const Matrix4 &m) Matrix4 t(tm, m); Graphics::StreamDrawCommand cmd; - cmd.formats[0] = vertex::getSinglePositionFormat(is2D); - cmd.formats[1] = vertex::CommonFormat::STf_RGBAub; - cmd.indexMode = vertex::TriangleIndexMode::QUADS; + cmd.formats[0] = getSinglePositionFormat(is2D); + cmd.formats[1] = CommonFormat::STf_RGBAub; + cmd.indexMode = TriangleIndexMode::QUADS; cmd.vertexCount = 4; cmd.standardShaderType = Shader::STANDARD_VIDEO; @@ -128,7 +128,7 @@ void Video::draw(Graphics *gfx, const Matrix4 &m) else t.transformXY0((Vector3 *) data.stream[0], vertices, 4); - vertex::STf_RGBAub *verts = (vertex::STf_RGBAub *) data.stream[1]; + STf_RGBAub *verts = (STf_RGBAub *) data.stream[1]; Color32 c = toColor32(gfx->getColor()); diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 79f5cc8b5..3559a2221 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -35,7 +35,7 @@ namespace graphics namespace opengl { -Buffer::Buffer(size_t size, const void *data, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags) +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) @@ -141,13 +141,13 @@ void Buffer::unmap() { switch (getUsage()) { - case vertex::USAGE_STATIC: + case BUFFERUSAGE_STATIC: unmapStatic(modifiedOffset, modifiedSize); break; - case vertex::USAGE_STREAM: + case BUFFERUSAGE_STREAM: unmapStream(); break; - case vertex::USAGE_DYNAMIC: + case BUFFERUSAGE_DYNAMIC: default: // It's probably more efficient to treat it like a streaming buffer if // at least a third of its contents have been modified during the map(). diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index 4ca4b14cf..60946ddfb 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -39,7 +39,7 @@ class Buffer final : public love::graphics::Buffer, public Volatile { public: - Buffer(size_t size, const void *data, BufferTypeFlags typeflags, vertex::Usage usage, uint32 mapflags); + Buffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags); virtual ~Buffer(); void *map() override; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 1b354c9c0..b2fcba39d 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -155,7 +155,7 @@ 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, vertex::Usage usage, uint32 mapflags) +love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) { return new Buffer(size, data, typeflags, usage, mapflags); } @@ -385,13 +385,13 @@ void Graphics::draw(const DrawIndexedCommand &cmd) ++drawCalls; } -static inline void advanceVertexOffsets(const vertex::Attributes &attributes, vertex::BufferBindings &buffers, int vertexcount) +static inline void advanceVertexOffsets(const Attributes &attributes, BufferBindings &buffers, int vertexcount) { // TODO: Figure out a better way to avoid touching the same buffer multiple // times, if multiple attributes share the buffer. uint32 touchedbuffers = 0; - for (unsigned int i = 0; i < vertex::Attributes::MAX; i++) + for (unsigned int i = 0; i < Attributes::MAX; i++) { if (!attributes.isEnabled(i)) continue; @@ -408,7 +408,7 @@ static inline void advanceVertexOffsets(const vertex::Attributes &attributes, ve } } -void Graphics::drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, love::graphics::Texture *texture) +void Graphics::drawQuads(int start, int count, const Attributes &attributes, const BufferBindings &buffers, love::graphics::Texture *texture) { const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX; const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4; @@ -437,7 +437,7 @@ void Graphics::drawQuads(int start, int count, const vertex::Attributes &attribu } else { - vertex::BufferBindings bufferscopy = buffers; + BufferBindings bufferscopy = buffers; if (start > 0) advanceVertexOffsets(attributes, bufferscopy, start * 4); @@ -525,7 +525,7 @@ void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pix endPass(); bool iswindow = rts.getFirstTarget().canvas == nullptr; - vertex::Winding vertexwinding = state.winding; + Winding vertexwinding = state.winding; if (iswindow) { @@ -543,10 +543,10 @@ void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pix // Flip front face winding when rendering to a canvas, since our // projection matrix is flipped. - vertexwinding = vertexwinding == vertex::WINDING_CW ? vertex::WINDING_CCW : vertex::WINDING_CW; + vertexwinding = vertexwinding == WINDING_CW ? WINDING_CCW : WINDING_CW; } - glFrontFace(vertexwinding == vertex::WINDING_CW ? GL_CW : GL_CCW); + glFrontFace(vertexwinding == WINDING_CW ? GL_CW : GL_CCW); gl.setViewport({0, 0, pixelw, pixelh}); @@ -1241,7 +1241,7 @@ void Graphics::setDepthMode(CompareMode compare, bool write) } } -void Graphics::setFrontFaceWinding(vertex::Winding winding) +void Graphics::setFrontFaceWinding(Winding winding) { DisplayState &state = states.back(); @@ -1251,9 +1251,9 @@ void Graphics::setFrontFaceWinding(vertex::Winding winding) state.winding = winding; if (isCanvasActive()) - winding = winding == vertex::WINDING_CW ? vertex::WINDING_CCW : vertex::WINDING_CW; + winding = winding == WINDING_CW ? WINDING_CCW : WINDING_CW; - glFrontFace(winding == vertex::WINDING_CW ? GL_CW : GL_CCW); + glFrontFace(winding == WINDING_CW ? GL_CW : GL_CCW); } void Graphics::setColor(Colorf c) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 64b3cf115..8f2f69a88 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -63,7 +63,7 @@ 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, vertex::Usage usage, uint32 mapflags) 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; void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; @@ -74,7 +74,7 @@ public: void draw(const DrawCommand &cmd) override; void draw(const DrawIndexedCommand &cmd) override; - void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture) override; + void drawQuads(int start, int count, const Attributes &attributes, const BufferBindings &buffers, Texture *texture) override; void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) override; void clear(const std::vector &colors, OptionalInt stencil, OptionalDouble depth) override; @@ -95,7 +95,7 @@ public: void setDepthMode(CompareMode compare, bool write) override; - void setFrontFaceWinding(vertex::Winding winding) override; + void setFrontFaceWinding(Winding winding) override; void setColorMask(ColorChannelMask mask) override; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index f17c3e83b..601808254 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -186,7 +186,7 @@ void OpenGL::setupContext() state.enabledAttribArrays = (uint32) ((1ull << uint32(maxvertexattribs)) - 1); state.instancedAttribArrays = 0; - setVertexAttributes(vertex::Attributes(), vertex::BufferBindings()); + setVertexAttributes(Attributes(), BufferBindings()); // Get the current viewport. glGetIntegerv(GL_VIEWPORT, (GLint *) &state.viewport.x); @@ -631,62 +631,62 @@ GLenum OpenGL::getGLIndexDataType(IndexDataType type) } } -GLenum OpenGL::getGLVertexDataType(vertex::DataType type, GLboolean &normalized, bool &intformat) +GLenum OpenGL::getGLVertexDataType(DataType type, GLboolean &normalized, bool &intformat) { normalized = GL_FALSE; intformat = false; switch (type) { - case vertex::DATA_SNORM8: + case DATA_SNORM8: normalized = GL_TRUE; return GL_BYTE; - case vertex::DATA_UNORM8: + case DATA_UNORM8: normalized = GL_TRUE; return GL_UNSIGNED_BYTE; - case vertex::DATA_INT8: + case DATA_INT8: intformat = true; return GL_BYTE; - case vertex::DATA_UINT8: + case DATA_UINT8: intformat = true; return GL_UNSIGNED_BYTE; - case vertex::DATA_SNORM16: + case DATA_SNORM16: normalized = GL_TRUE; return GL_SHORT; - case vertex::DATA_UNORM16: + case DATA_UNORM16: normalized = GL_TRUE; return GL_UNSIGNED_SHORT; - case vertex::DATA_INT16: + case DATA_INT16: intformat = true; return GL_SHORT; - case vertex::DATA_UINT16: + case DATA_UINT16: intformat = true; return GL_UNSIGNED_SHORT; - case vertex::DATA_INT32: + case DATA_INT32: intformat = true; return GL_INT; - case vertex::DATA_UINT32: + case DATA_UINT32: intformat = true; return GL_UNSIGNED_INT; - case vertex::DATA_FLOAT: + case DATA_FLOAT: normalized = GL_FALSE; return GL_FLOAT; - case vertex::DATA_MAX_ENUM: + case DATA_MAX_ENUM: return GL_ZERO; } return GL_ZERO; } -GLenum OpenGL::getGLBufferUsage(vertex::Usage usage) +GLenum OpenGL::getGLBufferUsage(BufferUsage usage) { switch (usage) { - case vertex::USAGE_STREAM: + case BUFFERUSAGE_STREAM: return GL_STREAM_DRAW; - case vertex::USAGE_DYNAMIC: + case BUFFERUSAGE_DYNAMIC: return GL_DYNAMIC_DRAW; - case vertex::USAGE_STATIC: + case BUFFERUSAGE_STATIC: return GL_STATIC_DRAW; default: return 0; @@ -713,7 +713,7 @@ void OpenGL::deleteBuffer(GLuint buffer) } } -void OpenGL::setVertexAttributes(const vertex::Attributes &attributes, const vertex::BufferBindings &buffers) +void OpenGL::setVertexAttributes(const Attributes &attributes, const BufferBindings &buffers) { uint32 enablediff = attributes.enableBits ^ state.enabledAttribArrays; uint32 instanceattribbits = 0; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 8dd975cec..f174a0b22 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -238,7 +238,7 @@ public: /** * Set all vertex attribute state. **/ - void setVertexAttributes(const vertex::Attributes &attributes, const vertex::BufferBindings &buffers); + void setVertexAttributes(const Attributes &attributes, const BufferBindings &buffers); /** * Wrapper for glCullFace which eliminates redundant state setting. @@ -404,8 +404,8 @@ public: static GLenum getGLPrimitiveType(PrimitiveType type); static GLenum getGLBufferType(BufferType type); static GLenum getGLIndexDataType(IndexDataType type); - static GLenum getGLVertexDataType(vertex::DataType type, GLboolean &normalized, bool &intformat); - static GLenum getGLBufferUsage(vertex::Usage usage); + static GLenum getGLVertexDataType(DataType type, GLboolean &normalized, bool &intformat); + static GLenum getGLBufferUsage(BufferUsage usage); static GLenum getGLTextureType(TextureType type); static GLint getGLWrapMode(Texture::WrapMode wmode); static GLint getGLCompareMode(CompareMode mode); diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index fca5e22c7..f704764e7 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -23,6 +23,7 @@ #include "Shader.h" #include "Graphics.h" +#include "graphics/vertex.h" // C++ #include @@ -322,7 +323,7 @@ bool Shader::loadVolatile() for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++) { const char *name = nullptr; - if (vertex::getConstant((BuiltinVertexAttribute) i, name)) + if (graphics::getConstant((BuiltinVertexAttribute) i, name)) glBindAttribLocation(program, i, (const GLchar *) name); } @@ -345,7 +346,7 @@ bool Shader::loadVolatile() for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++) { const char *name = nullptr; - if (vertex::getConstant(BuiltinVertexAttribute(i), name)) + if (graphics::getConstant(BuiltinVertexAttribute(i), name)) builtinAttributes[i] = glGetAttribLocation(program, name); else builtinAttributes[i] = -1; diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index e979af478..8366515ce 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -25,8 +25,6 @@ namespace love { namespace graphics { -namespace vertex -{ static_assert(sizeof(Color32) == 4, "sizeof(Color32) incorrect!"); static_assert(sizeof(STf_RGBAub) == sizeof(float)*2 + sizeof(Color32), "sizeof(STf_RGBAub) incorrect!"); @@ -306,14 +304,14 @@ static StringMap::Entry indexTypeEntries[] = static StringMap indexTypes(indexTypeEntries, sizeof(indexTypeEntries)); -static StringMap::Entry usageEntries[] = +static StringMap::Entry usageEntries[] = { - { "stream", USAGE_STREAM }, - { "dynamic", USAGE_DYNAMIC }, - { "static", USAGE_STATIC }, + { "stream", BUFFERUSAGE_STREAM }, + { "dynamic", BUFFERUSAGE_DYNAMIC }, + { "static", BUFFERUSAGE_STATIC }, }; -static StringMap usages(usageEntries, sizeof(usageEntries)); +static StringMap usages(usageEntries, sizeof(usageEntries)); static StringMap::Entry primitiveTypeEntries[] = { @@ -392,17 +390,17 @@ std::vector getConstants(IndexDataType) return indexTypes.getNames(); } -bool getConstant(const char *in, Usage &out) +bool getConstant(const char *in, BufferUsage &out) { return usages.find(in, out); } -bool getConstant(Usage in, const char *&out) +bool getConstant(BufferUsage in, const char *&out) { return usages.find(in, out); } -std::vector getConstants(Usage) +std::vector getConstants(BufferUsage) { return usages.getNames(); } @@ -482,6 +480,5 @@ std::vector getConstants(Winding) return windings.getNames(); } -} // vertex } // graphics } // love diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index c9893a19d..8c8a6aa80 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -102,16 +102,13 @@ enum CullMode CULL_MAX_ENUM }; -namespace vertex +// The expected usage pattern of buffer data. +enum BufferUsage { - -// The expected usage pattern of vertex data. -enum Usage -{ - USAGE_STREAM, - USAGE_DYNAMIC, - USAGE_STATIC, - USAGE_MAX_ENUM + BUFFERUSAGE_STREAM, + BUFFERUSAGE_DYNAMIC, + BUFFERUSAGE_STATIC, + BUFFERUSAGE_MAX_ENUM }; enum DataType @@ -195,6 +192,8 @@ struct XYf_STf_RGBAub Color32 color; }; +typedef XYf_STf_RGBAub Vertex; + struct XYf_STus_RGBAub { float x, y; @@ -334,9 +333,9 @@ bool getConstant(const char *in, IndexDataType &out); bool getConstant(IndexDataType in, const char *&out); std::vector getConstants(IndexDataType); -bool getConstant(const char *in, Usage &out); -bool getConstant(Usage in, const char *&out); -std::vector getConstants(Usage); +bool getConstant(const char *in, BufferUsage &out); +bool getConstant(BufferUsage in, const char *&out); +std::vector getConstants(BufferUsage); bool getConstant(const char *in, PrimitiveType &out); bool getConstant(PrimitiveType in, const char *&out); @@ -358,9 +357,5 @@ bool getConstant(const char *in, Winding &out); bool getConstant(Winding in, const char *&out); std::vector getConstants(Winding); -} // vertex - -typedef vertex::XYf_STf_RGBAub Vertex; - } // graphics } // love diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index f42938b1f..741954b48 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1147,12 +1147,12 @@ int w_newSpriteBatch(lua_State *L) Texture *texture = luax_checktexture(L, 1); int size = (int) luaL_optinteger(L, 2, 1000); - vertex::Usage usage = vertex::USAGE_DYNAMIC; + BufferUsage usage = BUFFERUSAGE_DYNAMIC; if (lua_gettop(L) > 2) { const char *usagestr = luaL_checkstring(L, 3); - if (!vertex::getConstant(usagestr, usage)) - return luax_enumerror(L, "usage hint", vertex::getConstants(usage), usagestr); + if (!getConstant(usagestr, usage)) + return luax_enumerror(L, "usage hint", getConstants(usage), usagestr); } SpriteBatch *t = nullptr; @@ -1421,12 +1421,12 @@ int w_validateShader(lua_State *L) return 1; } -static vertex::Usage luax_optmeshusage(lua_State *L, int idx, vertex::Usage def) +static BufferUsage luax_optmeshusage(lua_State *L, int idx, BufferUsage def) { const char *usagestr = lua_isnoneornil(L, idx) ? nullptr : luaL_checkstring(L, idx); - if (usagestr && !vertex::getConstant(usagestr, def)) - luax_enumerror(L, "usage hint", vertex::getConstants(def), usagestr); + if (usagestr && !getConstant(usagestr, def)) + luax_enumerror(L, "usage hint", getConstants(def), usagestr); return def; } @@ -1435,8 +1435,8 @@ static PrimitiveType luax_optmeshdrawmode(lua_State *L, int idx, PrimitiveType d { const char *modestr = lua_isnoneornil(L, idx) ? nullptr : luaL_checkstring(L, idx); - if (modestr && !vertex::getConstant(modestr, def)) - luax_enumerror(L, "mesh draw mode", vertex::getConstants(def), modestr); + if (modestr && !getConstant(modestr, def)) + luax_enumerror(L, "mesh draw mode", getConstants(def), modestr); return def; } @@ -1446,7 +1446,7 @@ static Mesh *newStandardMesh(lua_State *L) Mesh *t = nullptr; PrimitiveType drawmode = luax_optmeshdrawmode(L, 2, PRIMITIVE_TRIANGLE_FAN); - vertex::Usage usage = luax_optmeshusage(L, 3, vertex::USAGE_DYNAMIC); + BufferUsage usage = luax_optmeshusage(L, 3, BUFFERUSAGE_DYNAMIC); // First argument is a table of standard vertices, or the number of // standard vertices. @@ -1506,7 +1506,7 @@ static Mesh *newCustomMesh(lua_State *L) std::vector vertexformat; PrimitiveType drawmode = luax_optmeshdrawmode(L, 3, PRIMITIVE_TRIANGLE_FAN); - vertex::Usage usage = luax_optmeshusage(L, 4, vertex::USAGE_DYNAMIC); + BufferUsage usage = luax_optmeshusage(L, 4, BUFFERUSAGE_DYNAMIC); lua_rawgeti(L, 1, 1); if (!lua_istable(L, -1)) @@ -1530,10 +1530,10 @@ static Mesh *newCustomMesh(lua_State *L) const char *tname = luaL_checkstring(L, -2); if (strcmp(tname, "byte") == 0) // Legacy name. - format.type = vertex::DATA_UNORM8; - else if (!vertex::getConstant(tname, format.type)) + format.type = DATA_UNORM8; + else if (!getConstant(tname, format.type)) { - luax_enumerror(L, "Mesh vertex data type name", vertex::getConstants(format.type), tname); + luax_enumerror(L, "Mesh vertex data type name", getConstants(format.type), tname); return nullptr; } @@ -2109,8 +2109,8 @@ int w_setMeshCullMode(lua_State *L) const char *str = luaL_checkstring(L, 1); CullMode mode; - if (!vertex::getConstant(str, mode)) - return luax_enumerror(L, "cull mode", vertex::getConstants(mode), str); + if (!getConstant(str, mode)) + return luax_enumerror(L, "cull mode", getConstants(mode), str); luax_catchexcept(L, [&]() { instance()->setMeshCullMode(mode); }); return 0; @@ -2120,7 +2120,7 @@ int w_getMeshCullMode(lua_State *L) { CullMode mode = instance()->getMeshCullMode(); const char *str; - if (!vertex::getConstant(mode, str)) + if (!getConstant(mode, str)) return luaL_error(L, "Unknown cull mode"); lua_pushstring(L, str); return 1; @@ -2129,10 +2129,10 @@ int w_getMeshCullMode(lua_State *L) int w_setFrontFaceWinding(lua_State *L) { const char *str = luaL_checkstring(L, 1); - vertex::Winding winding; + Winding winding; - if (!vertex::getConstant(str, winding)) - return luax_enumerror(L, "vertex winding", vertex::getConstants(winding), str); + if (!getConstant(str, winding)) + return luax_enumerror(L, "vertex winding", getConstants(winding), str); luax_catchexcept(L, [&]() { instance()->setFrontFaceWinding(winding); }); return 0; @@ -2140,9 +2140,9 @@ int w_setFrontFaceWinding(lua_State *L) int w_getFrontFaceWinding(lua_State *L) { - vertex::Winding winding = instance()->getFrontFaceWinding(); + Winding winding = instance()->getFrontFaceWinding(); const char *str; - if (!vertex::getConstant(winding, str)) + if (!getConstant(winding, str)) return luaL_error(L, "Unknown vertex winding"); lua_pushstring(L, str); return 1; diff --git a/src/modules/graphics/wrap_GraphicsShader.lua b/src/modules/graphics/wrap_GraphicsShader.lua index 14a1ba19d..02cb9998b 100644 --- a/src/modules/graphics/wrap_GraphicsShader.lua +++ b/src/modules/graphics/wrap_GraphicsShader.lua @@ -380,6 +380,36 @@ local function isPixelCode(code) end end +local function includeShader(path, dir, global) + +end + +local function preprocessIncludes(code, dir, level) + local output = {} + + local linecount = 0 + for line in code:gmatch("[^\r\n]+") do + linecount = linecount + 1 + + if line:match("^%s*#include") then + local localpath = line:match("^%s*#include%s*\"(.*)\"") + local globalpath = line:match("^%s*#include%s*<(.*)>") + --local + if localpath then + --table_insert(output, ) + elseif globalpath then + + else + + end + else + table_insert(output, line) + end + end + + return table_concat(output, "\n") +end + function love.graphics._shaderCodeToGLSL(gles, arg1, arg2) local vertexcode, pixelcode local is_custompixel = false -- whether pixel code has "effects" function instead of "effect" diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index 9e238dec1..2902dd5ed 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -74,31 +74,31 @@ static inline size_t writeUNormData(lua_State *L, int startidx, int components, return sizeof(T) * components; } -char *luax_writeAttributeData(lua_State *L, int startidx, vertex::DataType type, int components, char *data) +char *luax_writeAttributeData(lua_State *L, int startidx, DataType type, int components, char *data) { switch (type) { - case vertex::DATA_SNORM8: + case DATA_SNORM8: return data + writeSNormData(L, startidx, components, data); - case vertex::DATA_UNORM8: + case DATA_UNORM8: return data + writeUNormData(L, startidx, components, data); - case vertex::DATA_INT8: + case DATA_INT8: return data + writeData(L, startidx, components, data); - case vertex::DATA_UINT8: + case DATA_UINT8: return data + writeData(L, startidx, components, data); - case vertex::DATA_SNORM16: + case DATA_SNORM16: return data + writeSNormData(L, startidx, components, data); - case vertex::DATA_UNORM16: + case DATA_UNORM16: return data + writeUNormData(L, startidx, components, data); - case vertex::DATA_INT16: + case DATA_INT16: return data + writeData(L, startidx, components, data); - case vertex::DATA_UINT16: + case DATA_UINT16: return data + writeData(L, startidx, components, data); - case vertex::DATA_INT32: + case DATA_INT32: return data + writeData(L, startidx, components, data); - case vertex::DATA_UINT32: + case DATA_UINT32: return data + writeData(L, startidx, components, data); - case vertex::DATA_FLOAT: + case DATA_FLOAT: return data + writeData(L, startidx, components, data); default: return data; @@ -140,31 +140,31 @@ static inline size_t readUNormData(lua_State *L, int components, const char *dat return sizeof(T) * components; } -const char *luax_readAttributeData(lua_State *L, vertex::DataType type, int components, const char *data) +const char *luax_readAttributeData(lua_State *L, DataType type, int components, const char *data) { switch (type) { - case vertex::DATA_SNORM8: + case DATA_SNORM8: return data + readSNormData(L, components, data); - case vertex::DATA_UNORM8: + case DATA_UNORM8: return data + readUNormData(L, components, data); - case vertex::DATA_INT8: + case DATA_INT8: return data + readData(L, components, data); - case vertex::DATA_UINT8: + case DATA_UINT8: return data + readData(L, components, data); - case vertex::DATA_SNORM16: + case DATA_SNORM16: return data + readSNormData(L, components, data); - case vertex::DATA_UNORM16: + case DATA_UNORM16: return data + readUNormData(L, components, data); - case vertex::DATA_INT16: + case DATA_INT16: return data + readData(L, components, data); - case vertex::DATA_UINT16: + case DATA_UINT16: return data + readData(L, components, data); - case vertex::DATA_INT32: + case DATA_INT32: return data + readData(L, components, data); - case vertex::DATA_UINT32: + case DATA_UINT32: return data + readData(L, components, data); - case vertex::DATA_FLOAT: + case DATA_FLOAT: return data + readData(L, components, data); default: return data; @@ -321,7 +321,7 @@ 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; - vertex::DataType type; + DataType type; int components; luax_catchexcept(L, [&](){ type = t->getAttributeInfo(attribindex, components); }); @@ -341,7 +341,7 @@ 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; - vertex::DataType type; + DataType type; int components; luax_catchexcept(L, [&](){ type = t->getAttributeInfo(attribindex, components); }); @@ -372,8 +372,8 @@ int w_Mesh_getVertexFormat(lua_State *L) for (size_t i = 0; i < vertexformat.size(); i++) { - if (!vertex::getConstant(vertexformat[i].type, tname)) - return luax_enumerror(L, "vertex attribute data type", vertex::getConstants(vertexformat[i].type), tname); + if (!getConstant(vertexformat[i].type, tname)) + return luax_enumerror(L, "vertex attribute data type", getConstants(vertexformat[i].type), tname); lua_createtable(L, 3, 0); @@ -420,8 +420,8 @@ int w_Mesh_attachAttribute(lua_State *L) AttributeStep step = STEP_PER_VERTEX; const char *stepstr = lua_isnoneornil(L, 4) ? nullptr : luaL_checkstring(L, 4); - if (stepstr != nullptr && !vertex::getConstant(stepstr, step)) - return luax_enumerror(L, "vertex attribute step", vertex::getConstants(step), stepstr); + if (stepstr != nullptr && !getConstant(stepstr, step)) + return luax_enumerror(L, "vertex attribute step", getConstants(step), stepstr); const char *attachname = luaL_optstring(L, 5, name); @@ -463,10 +463,10 @@ int w_Mesh_setVertexMap(lua_State *L) const char *indextypestr = luaL_checkstring(L, 3); IndexDataType indextype; - if (!vertex::getConstant(indextypestr, indextype)) - return luax_enumerror(L, "index data type", vertex::getConstants(indextype), indextypestr); + if (!getConstant(indextypestr, indextype)) + return luax_enumerror(L, "index data type", getConstants(indextype), indextypestr); - size_t datatypesize = vertex::getIndexDataSize(indextype); + size_t datatypesize = getIndexDataSize(indextype); int indexcount = (int) luaL_optinteger(L, 4, d->getSize() / datatypesize); @@ -569,8 +569,8 @@ int w_Mesh_setDrawMode(lua_State *L) const char *str = luaL_checkstring(L, 2); PrimitiveType mode; - if (!vertex::getConstant(str, mode)) - return luax_enumerror(L, "mesh draw mode", vertex::getConstants(mode), str); + if (!getConstant(str, mode)) + return luax_enumerror(L, "mesh draw mode", getConstants(mode), str); t->setDrawMode(mode); return 0; @@ -582,7 +582,7 @@ int w_Mesh_getDrawMode(lua_State *L) PrimitiveType mode = t->getDrawMode(); const char *str; - if (!vertex::getConstant(mode, str)) + if (!getConstant(mode, str)) return luaL_error(L, "Unknown mesh draw mode."); lua_pushstring(L, str); diff --git a/src/modules/graphics/wrap_Mesh.h b/src/modules/graphics/wrap_Mesh.h index 34a18b1b8..b9477c624 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, vertex::DataType type, int components, char *data); -const char *luax_readAttributeData(lua_State *L, vertex::DataType type, int components, const char *data); +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); Mesh *luax_checkmesh(lua_State *L, int idx); extern "C" int luaopen_mesh(lua_State *L); From 1bc2b947fc8521754fcdc1c2e90c9fbf1b32c160 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 13 Jan 2020 20:44:39 -0400 Subject: [PATCH 03/26] Rename Attributes struct to VertexAttributes --- src/modules/graphics/Graphics.cpp | 2 +- src/modules/graphics/Graphics.h | 10 +++++----- src/modules/graphics/Mesh.cpp | 6 +++--- src/modules/graphics/ParticleSystem.h | 2 +- src/modules/graphics/SpriteBatch.cpp | 2 +- src/modules/graphics/Text.h | 2 +- src/modules/graphics/opengl/Graphics.cpp | 6 +++--- src/modules/graphics/opengl/Graphics.h | 2 +- src/modules/graphics/opengl/OpenGL.cpp | 4 ++-- src/modules/graphics/opengl/OpenGL.h | 2 +- src/modules/graphics/vertex.cpp | 2 +- src/modules/graphics/vertex.h | 14 +++++++------- 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 27bb1108a..dd5396912 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -1133,7 +1133,7 @@ void Graphics::flushStreamDraws() if (sbstate.vertexCount == 0 && sbstate.indexCount == 0) return; - Attributes attributes; + VertexAttributes attributes; BufferBindings buffers; size_t usedsizes[3] = {0, 0, 0}; diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index dd915624c..1ea9607c7 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -212,7 +212,7 @@ public: { PrimitiveType primitiveType = PRIMITIVE_TRIANGLES; - const Attributes *attributes; + const VertexAttributes *attributes; const BufferBindings *buffers; int vertexStart = 0; @@ -224,7 +224,7 @@ public: // TODO: This should be moved out to a state transition API? CullMode cullMode = CULL_NONE; - DrawCommand(const Attributes *attribs, const BufferBindings *buffers) + DrawCommand(const VertexAttributes *attribs, const BufferBindings *buffers) : attributes(attribs) , buffers(buffers) {} @@ -234,7 +234,7 @@ public: { PrimitiveType primitiveType = PRIMITIVE_TRIANGLES; - const Attributes *attributes; + const VertexAttributes *attributes; const BufferBindings *buffers; int indexCount = 0; @@ -249,7 +249,7 @@ public: // TODO: This should be moved out to a state transition API? CullMode cullMode = CULL_NONE; - DrawIndexedCommand(const Attributes *attribs, const BufferBindings *buffers, Resource *indexbuffer) + DrawIndexedCommand(const VertexAttributes *attribs, const BufferBindings *buffers, Resource *indexbuffer) : attributes(attribs) , buffers(buffers) , indexBuffer(indexbuffer) @@ -833,7 +833,7 @@ public: virtual void draw(const DrawCommand &cmd) = 0; virtual void draw(const DrawIndexedCommand &cmd) = 0; - virtual void drawQuads(int start, int count, const Attributes &attributes, const BufferBindings &buffers, Texture *texture) = 0; + virtual void drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, Texture *texture) = 0; void flushStreamDraws(); StreamVertexData requestStreamDraw(const StreamDrawCommand &command); diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 24f90d435..913941461 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -328,8 +328,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 > Attributes::MAX) - throw love::Exception("A maximum of %d attributes can be attached at once.", Attributes::MAX); + else if (attachedAttributes.size() + 1 > VertexAttributes::MAX) + throw love::Exception("A maximum of %d attributes can be attached at once.", VertexAttributes::MAX); newattrib.mesh = mesh; newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true; @@ -580,7 +580,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) if (Shader::current && texture.get()) Shader::current->checkMainTexture(texture); - Attributes attributes; + VertexAttributes attributes; BufferBindings buffers; int activebuffers = 0; diff --git a/src/modules/graphics/ParticleSystem.h b/src/modules/graphics/ParticleSystem.h index 1a24266b3..07740a3bd 100644 --- a/src/modules/graphics/ParticleSystem.h +++ b/src/modules/graphics/ParticleSystem.h @@ -744,7 +744,7 @@ private: bool relativeRotation; - const Attributes vertexAttributes; + const VertexAttributes vertexAttributes; Buffer *buffer; static StringMap::Entry distributionsEntries[]; diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index aaaf1e7ea..41da30043 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -315,7 +315,7 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) // Make sure the buffer isn't mapped when we draw (sends data to GPU if needed.) array_buf->unmap(); - Attributes attributes; + VertexAttributes attributes; BufferBindings buffers; { diff --git a/src/modules/graphics/Text.h b/src/modules/graphics/Text.h index 3199b0074..0e3259919 100644 --- a/src/modules/graphics/Text.h +++ b/src/modules/graphics/Text.h @@ -85,7 +85,7 @@ private: StrongRef font; - Attributes vertexAttributes; + VertexAttributes vertexAttributes; BufferBindings vertexBuffers; Buffer *vertex_buffer; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index b2fcba39d..e17028d46 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -385,13 +385,13 @@ void Graphics::draw(const DrawIndexedCommand &cmd) ++drawCalls; } -static inline void advanceVertexOffsets(const Attributes &attributes, BufferBindings &buffers, int vertexcount) +static inline void advanceVertexOffsets(const VertexAttributes &attributes, BufferBindings &buffers, int vertexcount) { // TODO: Figure out a better way to avoid touching the same buffer multiple // times, if multiple attributes share the buffer. uint32 touchedbuffers = 0; - for (unsigned int i = 0; i < Attributes::MAX; i++) + for (unsigned int i = 0; i < VertexAttributes::MAX; i++) { if (!attributes.isEnabled(i)) continue; @@ -408,7 +408,7 @@ static inline void advanceVertexOffsets(const Attributes &attributes, BufferBind } } -void Graphics::drawQuads(int start, int count, const Attributes &attributes, const BufferBindings &buffers, love::graphics::Texture *texture) +void Graphics::drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, love::graphics::Texture *texture) { const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX; const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4; diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 8f2f69a88..36c63d64c 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -74,7 +74,7 @@ public: void draw(const DrawCommand &cmd) override; void draw(const DrawIndexedCommand &cmd) override; - void drawQuads(int start, int count, const Attributes &attributes, const BufferBindings &buffers, Texture *texture) override; + void drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, Texture *texture) override; void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) override; void clear(const std::vector &colors, OptionalInt stencil, OptionalDouble depth) override; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 601808254..a2c36d192 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -186,7 +186,7 @@ void OpenGL::setupContext() state.enabledAttribArrays = (uint32) ((1ull << uint32(maxvertexattribs)) - 1); state.instancedAttribArrays = 0; - setVertexAttributes(Attributes(), BufferBindings()); + setVertexAttributes(VertexAttributes(), BufferBindings()); // Get the current viewport. glGetIntegerv(GL_VIEWPORT, (GLint *) &state.viewport.x); @@ -713,7 +713,7 @@ void OpenGL::deleteBuffer(GLuint buffer) } } -void OpenGL::setVertexAttributes(const Attributes &attributes, const BufferBindings &buffers) +void OpenGL::setVertexAttributes(const VertexAttributes &attributes, const BufferBindings &buffers) { uint32 enablediff = attributes.enableBits ^ state.enabledAttribArrays; uint32 instanceattribbits = 0; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index f174a0b22..264a9fe3b 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -238,7 +238,7 @@ public: /** * Set all vertex attribute state. **/ - void setVertexAttributes(const Attributes &attributes, const BufferBindings &buffers); + void setVertexAttributes(const VertexAttributes &attributes, const BufferBindings &buffers); /** * Wrapper for glCullFace which eliminates redundant state setting. diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 8366515ce..3e3549c64 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -236,7 +236,7 @@ void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, fillIndicesT(mode, vertexStart, vertexCount, indices); } -void Attributes::setCommonFormat(CommonFormat format, uint8 bufferindex) +void VertexAttributes::setCommonFormat(CommonFormat format, uint8 bufferindex) { setBufferLayout(bufferindex, (uint16) getFormatStride(format)); diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 8c8a6aa80..219193489 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -230,7 +230,7 @@ struct BufferBindings void clear() { useBits = 0; } }; -struct AttributeInfo +struct VertexAttributeInfo { uint8 bufferIndex; DataType type : 4; @@ -238,23 +238,23 @@ struct AttributeInfo uint16 offsetFromVertex; }; -struct BufferLayout +struct VertexBufferLayout { uint16 stride; }; -struct Attributes +struct VertexAttributes { static const uint32 MAX = 32; uint32 enableBits = 0; // indexed by attribute uint32 instanceBits = 0; // indexed by buffer - AttributeInfo attribs[MAX]; - BufferLayout bufferLayouts[BufferBindings::MAX]; + VertexAttributeInfo attribs[MAX]; + VertexBufferLayout bufferLayouts[BufferBindings::MAX]; - Attributes() {} - Attributes(CommonFormat format, uint8 bufferindex) + VertexAttributes() {} + VertexAttributes(CommonFormat format, uint8 bufferindex) { setCommonFormat(format, bufferindex); } From d5d50d2e0d3f3f56bab2822ba4a2532f3a4bbaaa Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 13 Jan 2020 23:20:49 -0400 Subject: [PATCH 04/26] Move DataFormat enum to vertex.h --- src/modules/graphics/Buffer.cpp | 17 ++----- src/modules/graphics/Buffer.h | 89 +-------------------------------- src/modules/graphics/vertex.cpp | 65 ++++++++++++++++++++++++ src/modules/graphics/vertex.h | 87 ++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+), 100 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index c2950272e..53458a6ab 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -26,13 +26,6 @@ namespace love namespace graphics { -static const Buffer::DataTypeInfo dataTypeInfo[] -{ - // baseType, isMatrix, components, rows, columns, componentSize, packedAlign, packedSize - { Buffer::DATA_BASE_FLOAT, false, 1, 0, 0, sizeof(float), 4, 4 }, // DATA_FLOAT - -}; - love::Type Buffer::type("GraphicsBuffer", &Object::type); Buffer::Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) @@ -65,12 +58,12 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector format; diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 3e3549c64..c0c13bede 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -101,6 +101,71 @@ int getFormatPositionComponents(CommonFormat format) return 0; } +// Order here relies on order of DataFormat enum. +static const DataFormatInfo dataFormatInfo[] +{ + // baseType, isMatrix, components, rows, columns, componentSize, align, size + { DATA_BASETYPE_FLOAT, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_FLOAT + { DATA_BASETYPE_FLOAT, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_FLOAT_VEC2 + { DATA_BASETYPE_FLOAT, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_FLOAT_VEC3 + { DATA_BASETYPE_FLOAT, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_FLOAT_VEC4 + + { DATA_BASETYPE_FLOAT, true, 0, 2, 2, 4, 4, 16 }, // DATAFORMAT_FLOAT_MAT2X2 + { DATA_BASETYPE_FLOAT, true, 0, 2, 3, 4, 4, 24 }, // DATAFORMAT_FLOAT_MAT2X3 + { DATA_BASETYPE_FLOAT, true, 0, 2, 4, 4, 4, 32 }, // DATAFORMAT_FLOAT_MAT2X4 + + { DATA_BASETYPE_FLOAT, true, 0, 3, 2, 4, 4, 24 }, // DATAFORMAT_FLOAT_MAT3X2 + { DATA_BASETYPE_FLOAT, true, 0, 3, 3, 4, 4, 36 }, // DATAFORMAT_FLOAT_MAT3X3 + { DATA_BASETYPE_FLOAT, true, 0, 3, 4, 4, 4, 48 }, // DATAFORMAT_FLOAT_MAT3X4 + + { DATA_BASETYPE_FLOAT, true, 0, 4, 2, 4, 4, 32 }, // DATAFORMAT_FLOAT_MAT4X2 + { DATA_BASETYPE_FLOAT, true, 0, 4, 3, 4, 4, 48 }, // DATAFORMAT_FLOAT_MAT4X3 + { DATA_BASETYPE_FLOAT, true, 0, 4, 4, 4, 4, 64 }, // DATAFORMAT_FLOAT_MAT4X4 + + { DATA_BASETYPE_INT, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_INT32 + { DATA_BASETYPE_INT, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_INT32_VEC2 + { DATA_BASETYPE_INT, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_INT32_VEC3 + { DATA_BASETYPE_INT, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_INT32_VEC4 + + { DATA_BASETYPE_UINT, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_UINT32 + { DATA_BASETYPE_UINT, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_UINT32_VEC2 + { DATA_BASETYPE_UINT, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_UINT32_VEC3 + { DATA_BASETYPE_UINT, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_UINT32_VEC4 + + { DATA_BASETYPE_SNORM, false, 4, 0, 0, 1, 1, 4 }, // DATAFORMAT_SNORM8_VEC4 + { DATA_BASETYPE_UNORM, false, 4, 0, 0, 1, 1, 4 }, // DATAFORMAT_UNORM8_VEC4 + { 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_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_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_BOOL, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_BOOL + { DATA_BASETYPE_BOOL, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_BOOL_VEC2 + { DATA_BASETYPE_BOOL, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_BOOL_VEC3 + { DATA_BASETYPE_BOOL, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_BOOL_VEC4 +}; + +static_assert((sizeof(dataFormatInfo) / sizeof(DataFormatInfo)) == DATAFORMAT_MAX_ENUM, "dataFormatInfo array size must match number of DataFormat enum values."); + +const DataFormatInfo &getDataFormatInfo(DataFormat format) +{ + return dataFormatInfo[format]; +} + size_t getIndexDataSize(IndexDataType type) { switch (type) diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 219193489..bc5e72301 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -131,6 +131,79 @@ enum DataType DATA_MAX_ENUM }; +// The order of this enum affects the dataFormatInfo array. +enum DataFormat +{ + DATAFORMAT_FLOAT, + DATAFORMAT_FLOAT_VEC2, + DATAFORMAT_FLOAT_VEC3, + DATAFORMAT_FLOAT_VEC4, + + DATAFORMAT_FLOAT_MAT2X2, + DATAFORMAT_FLOAT_MAT2X3, + DATAFORMAT_FLOAT_MAT2X4, + + DATAFORMAT_FLOAT_MAT3X2, + DATAFORMAT_FLOAT_MAT3X3, + DATAFORMAT_FLOAT_MAT3X4, + + DATAFORMAT_FLOAT_MAT4X2, + DATAFORMAT_FLOAT_MAT4X3, + DATAFORMAT_FLOAT_MAT4X4, + + DATAFORMAT_INT32, + DATAFORMAT_INT32_VEC2, + DATAFORMAT_INT32_VEC3, + DATAFORMAT_INT32_VEC4, + + DATAFORMAT_UINT32, + DATAFORMAT_UINT32_VEC2, + DATAFORMAT_UINT32_VEC3, + 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, + + DATAFORMAT_UINT16, + DATAFORMAT_UINT16_VEC2, + DATAFORMAT_UINT16_VEC4, + + DATAFORMAT_BOOL, + DATAFORMAT_BOOL_VEC2, + DATAFORMAT_BOOL_VEC3, + DATAFORMAT_BOOL_VEC4, + + DATAFORMAT_MAX_ENUM +}; + +enum DataBaseType +{ + DATA_BASETYPE_FLOAT, + DATA_BASETYPE_INT, + DATA_BASETYPE_UINT, + DATA_BASETYPE_SNORM, + DATA_BASETYPE_UNORM, + DATA_BASETYPE_BOOL, + DATA_BASETYPE_MAX_ENUM +}; + enum Winding { WINDING_CW, @@ -161,6 +234,18 @@ enum class CommonFormat XYf_STPf_RGBAub, }; +struct DataFormatInfo +{ + DataBaseType baseType; + bool isMatrix; + int components; + int matrixRows; + int matrixColumns; + size_t componentSize; + size_t alignment; + size_t size; +}; + struct STf_RGBAub { float s, t; @@ -315,6 +400,8 @@ inline CommonFormat getSinglePositionFormat(bool is2D) return is2D ? CommonFormat::XYf : CommonFormat::XYZf; } +const DataFormatInfo &getDataFormatInfo(DataFormat format); + size_t getIndexDataSize(IndexDataType type); size_t getDataTypeSize(DataType datatype); bool isDataTypeInteger(DataType datatype); From d597275207d0327b4d19f66b847167485543aec2 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 15 Jan 2020 23:26:24 -0400 Subject: [PATCH 05/26] Add StringMap for DataFormat --- src/common/StringMap.h | 15 ++ src/modules/graphics/vertex.cpp | 238 ++++++++++++-------------------- src/modules/graphics/vertex.h | 42 ++---- 3 files changed, 118 insertions(+), 177 deletions(-) diff --git a/src/common/StringMap.h b/src/common/StringMap.h index b53b46487..97dbe3c8b 100644 --- a/src/common/StringMap.h +++ b/src/common/StringMap.h @@ -182,6 +182,21 @@ private: }; // StringMap +#define DECLARE_STRINGMAP(type) \ +bool getConstant(const char *in, type &out); \ +bool getConstant(type in, const char *&out); \ +std::vector getConstants(type); \ + +#define DEFINE_STRINGMAP_BEGIN(type, count, name) \ +static StringMap::Entry name##Entries[] = + +#define DEFINE_STRINGMAP_END(type, count, name) \ +; \ +static StringMap name##s(name##Entries, sizeof(name##Entries)); \ +bool getConstant(const char *in, type &out) { return name##s.find(in, out); } \ +bool getConstant(type in, const char *&out) { return name##s.find(in, out); } \ +std::vector getConstants(type) { return name##s.getNames(); } + } // love #endif // LOVE_STRING_MAP_H diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index c0c13bede..cfd7acdbb 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -219,8 +219,7 @@ bool isDataTypeInteger(DataType datatype) IndexDataType getIndexDataTypeFromMax(size_t maxvalue) { - IndexDataType types[] = {INDEX_UINT16, INDEX_UINT32}; - return types[maxvalue > LOVE_UINT16_MAX ? 1 : 0]; + return maxvalue > LOVE_UINT16_MAX ? INDEX_UINT32 : INDEX_UINT16; } int getIndexCount(TriangleIndexMode mode, int vertexCount) @@ -352,51 +351,46 @@ void VertexAttributes::setCommonFormat(CommonFormat format, uint8 bufferindex) } } -static StringMap::Entry attribNameEntries[] = +DEFINE_STRINGMAP_BEGIN(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) { { "VertexPosition", ATTRIB_POS }, { "VertexTexCoord", ATTRIB_TEXCOORD }, { "VertexColor", ATTRIB_COLOR }, -}; +} +DEFINE_STRINGMAP_END(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) -static StringMap attribNames(attribNameEntries, sizeof(attribNameEntries)); - -static StringMap::Entry indexTypeEntries[] = +DEFINE_STRINGMAP_BEGIN(IndexDataType, INDEX_MAX_ENUM, indexType) { { "uint16", INDEX_UINT16 }, { "uint32", INDEX_UINT32 }, -}; +} +DEFINE_STRINGMAP_END(IndexDataType, INDEX_MAX_ENUM, indexType) -static StringMap indexTypes(indexTypeEntries, sizeof(indexTypeEntries)); - -static StringMap::Entry usageEntries[] = +DEFINE_STRINGMAP_BEGIN(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) { { "stream", BUFFERUSAGE_STREAM }, { "dynamic", BUFFERUSAGE_DYNAMIC }, { "static", BUFFERUSAGE_STATIC }, -}; +} +DEFINE_STRINGMAP_END(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) -static StringMap usages(usageEntries, sizeof(usageEntries)); - -static StringMap::Entry primitiveTypeEntries[] = +DEFINE_STRINGMAP_BEGIN(PrimitiveType, PRIMITIVE_MAX_ENUM, primitiveType) { { "fan", PRIMITIVE_TRIANGLE_FAN }, { "strip", PRIMITIVE_TRIANGLE_STRIP }, { "triangles", PRIMITIVE_TRIANGLES }, { "points", PRIMITIVE_POINTS }, -}; +} +DEFINE_STRINGMAP_END(PrimitiveType, PRIMITIVE_MAX_ENUM, primitiveType) -static StringMap primitiveTypes(primitiveTypeEntries, sizeof(primitiveTypeEntries)); - -static StringMap::Entry attributeStepEntries[] = +DEFINE_STRINGMAP_BEGIN(AttributeStep, STEP_MAX_ENUM, attributeStep) { { "pervertex", STEP_PER_VERTEX }, { "perinstance", STEP_PER_INSTANCE }, -}; +} +DEFINE_STRINGMAP_END(AttributeStep, STEP_MAX_ENUM, attributeStep) -static StringMap attributeSteps(attributeStepEntries, sizeof(attributeStepEntries)); - -static StringMap::Entry dataTypeEntries[] = +DEFINE_STRINGMAP_BEGIN(DataType, DATA_MAX_ENUM, dataType) { { "snorm8", DATA_SNORM8 }, { "unorm8", DATA_UNORM8 }, @@ -409,141 +403,91 @@ static StringMap::Entry dataTypeEntries[] = { "int32", DATA_INT32 }, { "uint32", DATA_UINT32 }, { "float", DATA_FLOAT }, -}; +} +DEFINE_STRINGMAP_END(DataType, DATA_MAX_ENUM, dataType) -static StringMap dataTypes(dataTypeEntries, sizeof(dataTypeEntries)); +DEFINE_STRINGMAP_BEGIN(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) +{ + { "float", DATAFORMAT_FLOAT }, + { "floatvec2", DATAFORMAT_FLOAT_VEC2 }, + { "floatvec3", DATAFORMAT_FLOAT_VEC3 }, + { "floatvec4", DATAFORMAT_FLOAT_VEC4 }, -static StringMap::Entry cullModeEntries[] = + { "floatmat2x2", DATAFORMAT_FLOAT_MAT2X2 }, + { "floatmat2x3", DATAFORMAT_FLOAT_MAT2X3 }, + { "floatmat2x4", DATAFORMAT_FLOAT_MAT2X4 }, + + { "floatmat3x2", DATAFORMAT_FLOAT_MAT3X2 }, + { "floatmat3x3", DATAFORMAT_FLOAT_MAT3X3 }, + { "floatmat3x4", DATAFORMAT_FLOAT_MAT3X4 }, + + { "floatmat4x2", DATAFORMAT_FLOAT_MAT4X2 }, + { "floatmat4x3", DATAFORMAT_FLOAT_MAT4X3 }, + { "floatmat4x4", DATAFORMAT_FLOAT_MAT4X4 }, + + { "int32", DATAFORMAT_INT32 }, + { "int32vec2", DATAFORMAT_INT32_VEC2 }, + { "int32vec3", DATAFORMAT_INT32_VEC3 }, + { "int32vec4", DATAFORMAT_INT32_VEC4 }, + + { "uint32", DATAFORMAT_UINT32 }, + { "uint32vec2", DATAFORMAT_UINT32_VEC2 }, + { "uint32vec3", DATAFORMAT_UINT32_VEC3 }, + { "uint32vec4", DATAFORMAT_UINT32_VEC4 }, + + { "snorm8vec4", DATAFORMAT_SNORM8_VEC4 }, + { "unorm8vec4", DATAFORMAT_UNORM8_VEC4 }, + { "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 }, + + { "uint16", DATAFORMAT_UINT16 }, + { "uint16vec2", DATAFORMAT_UINT16_VEC2 }, + { "uint16vec4", DATAFORMAT_UINT16_VEC4 }, + + { "bool", DATAFORMAT_BOOL }, + { "boolvec2", DATAFORMAT_BOOL_VEC2 }, + { "boolvec3", DATAFORMAT_BOOL_VEC3 }, + { "boolvec4", DATAFORMAT_BOOL_VEC4 }, +} +DEFINE_STRINGMAP_END(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) + +DEFINE_STRINGMAP_BEGIN(DataBaseType, DATA_BASETYPE_MAX_ENUM, dataBaseType) +{ + { "float", DATA_BASETYPE_FLOAT }, + { "int", DATA_BASETYPE_INT }, + { "uint", DATA_BASETYPE_UINT }, + { "snorm", DATA_BASETYPE_SNORM }, + { "unorm", DATA_BASETYPE_UNORM }, + { "bool", DATA_BASETYPE_BOOL }, +} +DEFINE_STRINGMAP_END(DataBaseType, DATA_BASETYPE_MAX_ENUM, dataBaseType) + +DEFINE_STRINGMAP_BEGIN(CullMode, CULL_MAX_ENUM, cullMode) { { "none", CULL_NONE }, { "back", CULL_BACK }, { "front", CULL_FRONT }, -}; +} +DEFINE_STRINGMAP_END(CullMode, CULL_MAX_ENUM, cullMode) -static StringMap cullModes(cullModeEntries, sizeof(cullModeEntries)); - -static StringMap::Entry windingEntries[] = +DEFINE_STRINGMAP_BEGIN(Winding, WINDING_MAX_ENUM, winding) { { "cw", WINDING_CW }, { "ccw", WINDING_CCW }, -}; - -static StringMap windings(windingEntries, sizeof(windingEntries)); - -bool getConstant(const char *in, BuiltinVertexAttribute &out) -{ - return attribNames.find(in, out); -} - -bool getConstant(BuiltinVertexAttribute in, const char *&out) -{ - return attribNames.find(in, out); -} - -bool getConstant(const char *in, IndexDataType &out) -{ - return indexTypes.find(in, out); -} - -bool getConstant(IndexDataType in, const char *&out) -{ - return indexTypes.find(in, out); -} - -std::vector getConstants(IndexDataType) -{ - return indexTypes.getNames(); -} - -bool getConstant(const char *in, BufferUsage &out) -{ - return usages.find(in, out); -} - -bool getConstant(BufferUsage in, const char *&out) -{ - return usages.find(in, out); -} - -std::vector getConstants(BufferUsage) -{ - return usages.getNames(); -} - -bool getConstant(const char *in, PrimitiveType &out) -{ - return primitiveTypes.find(in, out); -} - -bool getConstant(PrimitiveType in, const char *&out) -{ - return primitiveTypes.find(in, out); -} - -std::vector getConstants(PrimitiveType) -{ - return primitiveTypes.getNames(); -} - -bool getConstant(const char *in, AttributeStep &out) -{ - return attributeSteps.find(in, out); -} - -bool getConstant(AttributeStep in, const char *&out) -{ - return attributeSteps.find(in, out); -} - -std::vector getConstants(AttributeStep) -{ - return attributeSteps.getNames(); -} - -bool getConstant(const char *in, DataType &out) -{ - return dataTypes.find(in, out); -} - -bool getConstant(DataType in, const char *&out) -{ - return dataTypes.find(in, out); -} - -std::vector getConstants(DataType) -{ - return dataTypes.getNames(); -} - -bool getConstant(const char *in, CullMode &out) -{ - return cullModes.find(in, out); -} - -bool getConstant(CullMode in, const char *&out) -{ - return cullModes.find(in, out); -} - -std::vector getConstants(CullMode) -{ - return cullModes.getNames(); -} - -bool getConstant(const char *in, Winding &out) -{ - return windings.find(in, out); -} - -bool getConstant(Winding in, const char *&out) -{ - return windings.find(in, out); -} - -std::vector getConstants(Winding) -{ - return windings.getNames(); } +DEFINE_STRINGMAP_END(Winding, WINDING_MAX_ENUM, winding) } // graphics } // love diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index bc5e72301..ded03f536 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -23,6 +23,7 @@ // LOVE #include "common/int.h" #include "common/Color.h" +#include "common/StringMap.h" // C #include @@ -131,6 +132,7 @@ enum DataType DATA_MAX_ENUM }; +// Value types used when interfacing with the GPU (vertex and shader data). // The order of this enum affects the dataFormatInfo array. enum DataFormat { @@ -413,36 +415,16 @@ int getIndexCount(TriangleIndexMode mode, int vertexCount); void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount, uint16 *indices); void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices); -bool getConstant(const char *in, BuiltinVertexAttribute &out); -bool getConstant(BuiltinVertexAttribute in, const char *&out); - -bool getConstant(const char *in, IndexDataType &out); -bool getConstant(IndexDataType in, const char *&out); -std::vector getConstants(IndexDataType); - -bool getConstant(const char *in, BufferUsage &out); -bool getConstant(BufferUsage in, const char *&out); -std::vector getConstants(BufferUsage); - -bool getConstant(const char *in, PrimitiveType &out); -bool getConstant(PrimitiveType in, const char *&out); -std::vector getConstants(PrimitiveType); - -bool getConstant(const char *in, AttributeStep &out); -bool getConstant(AttributeStep in, const char *&out); -std::vector getConstants(AttributeStep); - -bool getConstant(const char *in, DataType &out); -bool getConstant(DataType in, const char *&out); -std::vector getConstants(DataType); - -bool getConstant(const char *in, CullMode &out); -bool getConstant(CullMode in, const char *&out); -std::vector getConstants(CullMode); - -bool getConstant(const char *in, Winding &out); -bool getConstant(Winding in, const char *&out); -std::vector getConstants(Winding); +DECLARE_STRINGMAP(BuiltinVertexAttribute); +DECLARE_STRINGMAP(IndexDataType); +DECLARE_STRINGMAP(BufferUsage); +DECLARE_STRINGMAP(PrimitiveType); +DECLARE_STRINGMAP(AttributeStep); +DECLARE_STRINGMAP(DataType); +DECLARE_STRINGMAP(DataFormat); +DECLARE_STRINGMAP(DataBaseType); +DECLARE_STRINGMAP(CullMode); +DECLARE_STRINGMAP(Winding); } // graphics } // love From 816f132c9def34a5417f919c2acf5d6e9c2a6d02 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 18 Jan 2020 17:37:03 -0400 Subject: [PATCH 06/26] Expose GraphicsBuffer type to Lua. It currently doesn't have any methods or any way to access it, yet. --- CMakeLists.txt | 2 + .../xcode/liblove.xcodeproj/project.pbxproj | 10 +++++ src/modules/graphics/wrap_Buffer.cpp | 45 +++++++++++++++++++ src/modules/graphics/wrap_Buffer.h | 37 +++++++++++++++ src/modules/graphics/wrap_Graphics.cpp | 1 + src/modules/graphics/wrap_Graphics.h | 1 + 6 files changed, 96 insertions(+) create mode 100644 src/modules/graphics/wrap_Buffer.cpp create mode 100644 src/modules/graphics/wrap_Buffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 72953c5e4..b5fb4786c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -559,6 +559,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT src/modules/graphics/Video.h src/modules/graphics/Volatile.cpp src/modules/graphics/Volatile.h + src/modules/graphics/wrap_Buffer.cpp + src/modules/graphics/wrap_Buffer.h src/modules/graphics/wrap_Canvas.cpp src/modules/graphics/wrap_Canvas.h src/modules/graphics/wrap_Font.cpp diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index 79bc992f1..2fa20c99a 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -781,6 +781,9 @@ FA15DFB01F9B8D6A0042AB22 /* wrap_Data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */; }; FA15DFB11F9B8D820042AB22 /* OggDemuxer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAA54AC91F91660400A8FA7B /* OggDemuxer.cpp */; }; FA15DFB21F9B8D840042AB22 /* TheoraVideoStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAA54AC81F91660400A8FA7B /* TheoraVideoStream.cpp */; }; + FA18CEC523D3AE6700263725 /* wrap_Buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEC323D3AE6700263725 /* wrap_Buffer.cpp */; }; + FA18CEC623D3AE6800263725 /* wrap_Buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEC323D3AE6700263725 /* wrap_Buffer.cpp */; }; + FA18CEC723D3AE6800263725 /* wrap_Buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = FA18CEC423D3AE6700263725 /* wrap_Buffer.h */; }; FA1BA09D1E16CFCE00AA2803 /* Font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA09B1E16CFCE00AA2803 /* Font.cpp */; }; FA1BA09E1E16CFCE00AA2803 /* Font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA09B1E16CFCE00AA2803 /* Font.cpp */; }; FA1BA09F1E16CFCE00AA2803 /* Font.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA09C1E16CFCE00AA2803 /* Font.h */; }; @@ -1801,6 +1804,8 @@ FA1557C11CE90BD200AFF582 /* EXRHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXRHandler.cpp; sourceTree = ""; }; FA1557C21CE90BD200AFF582 /* EXRHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXRHandler.h; sourceTree = ""; }; FA15DFAB1F9B8C850042AB22 /* StringMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringMap.cpp; sourceTree = ""; }; + FA18CEC323D3AE6700263725 /* wrap_Buffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Buffer.cpp; sourceTree = ""; }; + FA18CEC423D3AE6700263725 /* wrap_Buffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wrap_Buffer.h; sourceTree = ""; }; FA1BA09B1E16CFCE00AA2803 /* Font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Font.cpp; sourceTree = ""; }; FA1BA09C1E16CFCE00AA2803 /* Font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Font.h; sourceTree = ""; }; FA1BA0A01E16D97500AA2803 /* wrap_Font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Font.cpp; sourceTree = ""; }; @@ -2879,6 +2884,8 @@ FADF54061E3D78F700012CC0 /* Video.h */, FA0B7BC01A95902C000E1D17 /* Volatile.cpp */, FA0B7BC11A95902C000E1D17 /* Volatile.h */, + FA18CEC323D3AE6700263725 /* wrap_Buffer.cpp */, + FA18CEC423D3AE6700263725 /* wrap_Buffer.h */, FA1BA0AA1E16F9EE00AA2803 /* wrap_Canvas.cpp */, FA1BA0AB1E16F9EE00AA2803 /* wrap_Canvas.h */, FA1BA0A01E16D97500AA2803 /* wrap_Font.cpp */, @@ -3967,6 +3974,7 @@ FA0B7A631A958EA3000E1D17 /* b2ContactManager.h in Headers */, FA0B7E771A95902C000E1D17 /* wrap_WeldJoint.h in Headers */, FA0B7A911A958EA3000E1D17 /* b2FrictionJoint.h in Headers */, + FA18CEC723D3AE6800263725 /* wrap_Buffer.h in Headers */, FA0B7E291A95902C000E1D17 /* PulleyJoint.h in Headers */, FA6BDE5C1F31725300786805 /* Color.h in Headers */, FA0B7E231A95902C000E1D17 /* PolygonShape.h in Headers */, @@ -4539,6 +4547,7 @@ FAF6C9E023C2DE2900D7B5BC /* SpvTools.cpp in Sources */, FAE64A8F2071364200BC7981 /* physfs_platform_unix.c in Sources */, FA0B7A681A958EA3000E1D17 /* b2Island.cpp in Sources */, + FA18CEC623D3AE6800263725 /* wrap_Buffer.cpp in Sources */, FA0B7E2B1A95902C000E1D17 /* RevoluteJoint.cpp in Sources */, FA0B7B291A958EA3000E1D17 /* simplexnoise1234.cpp in Sources */, FA0B7D261A95902C000E1D17 /* wrap_Font.cpp in Sources */, @@ -4794,6 +4803,7 @@ FAF140A91E20934C00F898D2 /* SymbolTable.cpp in Sources */, FA0B7E181A95902C000E1D17 /* MotorJoint.cpp in Sources */, FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */, + FA18CEC523D3AE6700263725 /* wrap_Buffer.cpp in Sources */, FAF6C9F423C2DE2900D7B5BC /* Logger.cpp in Sources */, FA0B7EBE1A95902C000E1D17 /* Thread.cpp in Sources */, FAC7CD8F1FE35E95006A60C7 /* physfs_platform_posix.c in Sources */, diff --git a/src/modules/graphics/wrap_Buffer.cpp b/src/modules/graphics/wrap_Buffer.cpp new file mode 100644 index 000000000..7b69a6519 --- /dev/null +++ b/src/modules/graphics/wrap_Buffer.cpp @@ -0,0 +1,45 @@ +/** +* Copyright (c) 2006-2020 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. +**/ + +#include "wrap_Buffer.h" +#include "Buffer.h" + +namespace love +{ +namespace graphics +{ + +Buffer *luax_checkbuffer(lua_State *L, int idx) +{ + return luax_checktype(L, idx); +} + +static const luaL_Reg w_Buffer_functions[] = +{ + { 0, 0 } +}; + +extern "C" int luaopen_graphicsbuffer(lua_State *L) +{ + return luax_register_type(L, &Buffer::type, w_Buffer_functions, nullptr); +} + +} // graphics +} // love diff --git a/src/modules/graphics/wrap_Buffer.h b/src/modules/graphics/wrap_Buffer.h new file mode 100644 index 000000000..6a0d42412 --- /dev/null +++ b/src/modules/graphics/wrap_Buffer.h @@ -0,0 +1,37 @@ +/** +* Copyright (c) 2006-2020 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 + +// LOVE +#include "common/runtime.h" + +namespace love +{ +namespace graphics +{ + +class Buffer; + +Buffer *luax_checkbuffer(lua_State *L, int idx); +extern "C" int luaopen_graphicsbuffer(lua_State *L); + +} // graphics +} // love diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 741954b48..0ea9e52c0 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3134,6 +3134,7 @@ static const lua_CFunction types[] = luaopen_font, luaopen_image, luaopen_quad, + luaopen_graphicsbuffer, luaopen_spritebatch, luaopen_particlesystem, luaopen_canvas, diff --git a/src/modules/graphics/wrap_Graphics.h b/src/modules/graphics/wrap_Graphics.h index 7359ef652..7876f3040 100644 --- a/src/modules/graphics/wrap_Graphics.h +++ b/src/modules/graphics/wrap_Graphics.h @@ -32,6 +32,7 @@ #include "wrap_Mesh.h" #include "wrap_Text.h" #include "wrap_Video.h" +#include "wrap_Buffer.h" #include "Graphics.h" namespace love From 25d9ae2ba0ed28e5430c2e19cbce5a82d44e486e Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 19 Jan 2020 15:03:19 -0400 Subject: [PATCH 07/26] Meshes expose vertex buffers, part 1 (compiles, but is currently half-implemented and broken) --- src/modules/graphics/Buffer.cpp | 29 +++- src/modules/graphics/Buffer.h | 12 +- src/modules/graphics/Mesh.cpp | 63 ++++---- src/modules/graphics/Mesh.h | 10 +- src/modules/graphics/SpriteBatch.cpp | 34 +++-- src/modules/graphics/SpriteBatch.h | 4 +- src/modules/graphics/opengl/OpenGL.cpp | 175 +++++++++++++++++----- src/modules/graphics/opengl/OpenGL.h | 2 +- src/modules/graphics/vertex.cpp | 40 ++--- src/modules/graphics/vertex.h | 8 +- src/modules/graphics/wrap_Mesh.cpp | 14 +- src/modules/graphics/wrap_SpriteBatch.cpp | 14 +- 12 files changed, 277 insertions(+), 128 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 53458a6ab..d57416564 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -29,7 +29,9 @@ namespace graphics love::Type Buffer::type("GraphicsBuffer", &Object::type); Buffer::Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags) - : size(size) + : arrayLength(0) + , arrayStride(0) + , size(size) , typeFlags(typeflags) , usage(usage) , mapFlags(mapflags) @@ -37,12 +39,14 @@ Buffer::Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 { } -Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, size_t arraylength) +Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &dataMembers, size_t arraylength) : Buffer(0, settings.typeFlags, settings.usage, settings.mapFlags) { - if (format.size() == 0) + if (dataMembers.size() == 0) throw love::Exception("Data format must contain values."); + this->dataMembers = dataMembers; + bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3]; bool uniformbuffer = settings.typeFlags & BUFFERFLAG_UNIFORM; @@ -50,13 +54,13 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector 1) + if (indexbuffer && dataMembers.size() > 1) throw love::Exception("test"); size_t offset = 0; size_t stride = 0; - for (const auto &member : format) + for (const auto &member : dataMembers) { DataFormat format = member.format; const DataFormatInfo &info = getDataFormatInfo(format); @@ -85,11 +89,26 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vectorarrayLength = arraylength; + this->arrayStride = stride; + this->size = stride * arraylength; } Buffer::~Buffer() { } +int Buffer::getDataMemberIndex(const std::string &name) const +{ + for (size_t i = 0; i < dataMembers.size(); i++) + { + if (dataMembers[i].name == name) + return (int) i; + } + + return -1; +} + } // graphics } // love diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 9d16107eb..857444fe0 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -69,7 +69,7 @@ public: }; Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags); - Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, size_t arraylength); + Buffer(Graphics *gfx, const Settings &settings, const std::vector &members, size_t arraylength); virtual ~Buffer(); size_t getSize() const { return size; } @@ -78,6 +78,13 @@ public: bool isMapped() const { return mapped; } uint32 getMapFlags() const { return mapFlags; } + size_t getArrayLength() const { return arrayLength; } + 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]; } + int getDataMemberIndex(const std::string &name) const; + /** * Map the Buffer to client memory. * @@ -138,8 +145,9 @@ public: protected: - std::vector format; + std::vector dataMembers; std::vector memberOffsets; + size_t arrayLength; size_t arrayStride; // The size of the buffer, in bytes. diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 913941461..13c7477a4 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -125,8 +125,8 @@ Mesh::~Mesh() for (const auto &attrib : attachedAttributes) { - if (attrib.second.mesh != this) - attrib.second.mesh->release(); + if (attrib.second.buffer != nullptr && attrib.second.buffer != vertexBuffer.get()) + attrib.second.buffer->release(); } } @@ -139,7 +139,7 @@ void Mesh::setupAttachedAttributes() if (attachedAttributes.find(name) != attachedAttributes.end()) throw love::Exception("Duplicate vertex attribute name: %s", name.c_str()); - attachedAttributes[name] = {this, (int) i, STEP_PER_VERTEX, true}; + attachedAttributes[name] = {nullptr, (int) i, STEP_PER_VERTEX, true}; } } @@ -260,6 +260,11 @@ size_t Mesh::getVertexStride() const return vertexStride; } +Buffer *Mesh::getVertexBuffer() const +{ + return vertexBuffer; +} + const std::vector &Mesh::getVertexFormat() const { return vertexFormat; @@ -305,23 +310,15 @@ bool Mesh::isAttributeEnabled(const std::string &name) const return it->second.enabled; } -void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step) +void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step) { + if ((buffer->getTypeFlags() & BUFFER_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); if (step == STEP_PER_INSTANCE && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING]) throw love::Exception("Vertex attribute instancing is not supported on this system."); - if (mesh != this) - { - for (const auto &it : mesh->attachedAttributes) - { - // If the supplied Mesh has attached attributes of its own, then we - // prevent it from being attached to avoid reference cycles. - if (it.second.mesh != mesh) - throw love::Exception("Cannot attach a Mesh which has attached Meshes of its own."); - } - } - AttachedAttribute oldattrib = {}; AttachedAttribute newattrib = {}; @@ -331,34 +328,33 @@ void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::strin else if (attachedAttributes.size() + 1 > VertexAttributes::MAX) throw love::Exception("A maximum of %d attributes can be attached at once.", VertexAttributes::MAX); - newattrib.mesh = mesh; - newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true; - newattrib.index = mesh->getAttributeIndex(attachname); + newattrib.buffer = buffer; + newattrib.enabled = oldattrib.buffer ? oldattrib.enabled : true; + newattrib.index = buffer->getDataMemberIndex(attachname); newattrib.step = step; if (newattrib.index < 0) - throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", attachname.c_str()); + throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str()); - if (newattrib.mesh != this) - newattrib.mesh->retain(); + newattrib.buffer->retain(); attachedAttributes[name] = newattrib; - if (oldattrib.mesh && oldattrib.mesh != this) - oldattrib.mesh->release(); + if (oldattrib.buffer) + oldattrib.buffer->release(); } bool Mesh::detachAttribute(const std::string &name) { auto it = attachedAttributes.find(name); - if (it != attachedAttributes.end() && it->second.mesh != this) + if (it != attachedAttributes.end() && it->second.buffer != vertexBuffer.get()) { - it->second.mesh->release(); + it->second.buffer->release(); attachedAttributes.erase(it); if (getAttributeIndex(name) != -1) - attachAttribute(name, this, name); + attachAttribute(name, vertexBuffer, name); return true; } @@ -590,7 +586,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) if (!attrib.second.enabled) continue; - Mesh *mesh = attrib.second.mesh; + Buffer *buffer = attrib.second.buffer; int attributeindex = -1; // If the attribute is one of the LOVE-defined ones, use the constant @@ -604,19 +600,18 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) if (attributeindex >= 0) { // Make sure the buffer isn't mapped (sends data to GPU if needed.) - mesh->vertexBuffer->unmap(); + buffer->unmap(); - const auto &formats = mesh->getVertexFormat(); - const auto &format = formats[attrib.second.index]; + const auto &member = buffer->getDataMember(attrib.second.index); - uint16 offset = (uint16) mesh->getAttributeOffset(attrib.second.index); - uint16 stride = (uint16) mesh->getVertexStride(); + uint16 offset = (uint16) buffer->getMemberOffset(attrib.second.index); + uint16 stride = (uint16) buffer->getArrayStride(); - attributes.set(attributeindex, format.type, (uint8) format.components, offset, activebuffers); + attributes.set(attributeindex, member.format, offset, activebuffers); attributes.setBufferLayout(activebuffers, stride, attrib.second.step); // TODO: Ideally we want to reuse buffers with the same stride+step. - buffers.set(activebuffers, mesh->vertexBuffer, 0); + buffers.set(activebuffers, buffer, 0); activebuffers++; } } diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 728dc0993..a0a16bb06 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -92,6 +92,8 @@ public: **/ size_t getVertexStride() const; + Buffer *getVertexBuffer() const; + /** * Gets the format of each vertex attribute stored in the Mesh. **/ @@ -106,10 +108,10 @@ public: bool isAttributeEnabled(const std::string &name) const; /** - * Attaches a vertex attribute from another Mesh to this one. The attribute - * will be used when drawing this Mesh. + * Attaches a vertex attribute from another vertex buffer to this Mesh. The + * attribute will be used when drawing this Mesh. **/ - void attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX); + void attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX); bool detachAttribute(const std::string &name); void *mapVertexData(); @@ -180,7 +182,7 @@ private: struct AttachedAttribute { - Mesh *mesh; + Buffer *buffer; int index; AttributeStep step; bool enabled; diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index 41da30043..50ee28123 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -244,24 +244,27 @@ int SpriteBatch::getBufferSize() const return size; } -void SpriteBatch::attachAttribute(const std::string &name, Mesh *mesh) +void SpriteBatch::attachAttribute(const std::string &name, Buffer *buffer) { + if ((buffer->getTypeFlags() & BUFFER_VERTEX) == 0) + throw love::Exception("GraphicsBuffer must be created with vertex buffer support to be used as a SpriteBatch vertex attribute."); + AttachedAttribute oldattrib = {}; AttachedAttribute newattrib = {}; - if (mesh->getVertexCount() < (size_t) next * 4) - throw love::Exception("Mesh has too few vertices to be attached to this SpriteBatch (at least %d vertices are required)", next*4); + if (buffer->getArrayLength() < (size_t) next * 4) + throw love::Exception("Buffer has too few vertices to be attached to this SpriteBatch (at least %d vertices are required)", next*4); auto it = attached_attributes.find(name); if (it != attached_attributes.end()) oldattrib = it->second; - newattrib.index = mesh->getAttributeIndex(name); + newattrib.index = buffer->getDataMemberIndex(name); if (newattrib.index < 0) - throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", name.c_str()); + throw love::Exception("The specified Buffer does not have a vertex attribute named '%s'", name.c_str()); - newattrib.mesh = mesh; + newattrib.buffer = buffer; attached_attributes[name] = newattrib; } @@ -327,12 +330,12 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) for (const auto &it : attached_attributes) { - Mesh *mesh = it.second.mesh.get(); + Buffer *buffer = it.second.buffer.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()); + if (buffer->getArrayLength() < (size_t) next * 4) + throw love::Exception("Buffer with attribute '%s' attached to this SpriteBatch has too few vertices", it.first.c_str()); int attributeindex = -1; @@ -347,19 +350,18 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) if (attributeindex >= 0) { // Make sure the buffer isn't mapped (sends data to GPU if needed.) - mesh->vertexBuffer->unmap(); + buffer->unmap(); - const auto &formats = mesh->getVertexFormat(); - const auto &format = formats[it.second.index]; + const auto &member = buffer->getDataMember(it.second.index); - uint16 offset = (uint16) mesh->getAttributeOffset(it.second.index); - uint16 stride = (uint16) mesh->getVertexStride(); + uint16 offset = (uint16) buffer->getMemberOffset(it.second.index); + uint16 stride = (uint16) buffer->getArrayStride(); - attributes.set(attributeindex, format.type, (uint8) format.components, offset, activebuffers); + attributes.set(attributeindex, member.format, offset, activebuffers); attributes.setBufferLayout(activebuffers, stride); // TODO: We should reuse buffer bindings with the same buffer+stride+step. - buffers.set(activebuffers, mesh->vertexBuffer, 0); + buffers.set(activebuffers, buffer, 0); activebuffers++; } } diff --git a/src/modules/graphics/SpriteBatch.h b/src/modules/graphics/SpriteBatch.h index f5b9db48f..40fbfd932 100644 --- a/src/modules/graphics/SpriteBatch.h +++ b/src/modules/graphics/SpriteBatch.h @@ -93,7 +93,7 @@ public: * Attaches a specific vertex attribute from a Mesh to this SpriteBatch. * The vertex attribute will be used when drawing the SpriteBatch. **/ - void attachAttribute(const std::string &name, Mesh *mesh); + void attachAttribute(const std::string &name, Buffer *buffer); void setDrawRange(int start, int count); void setDrawRange(); @@ -106,7 +106,7 @@ private: struct AttachedAttribute { - StrongRef mesh; + StrongRef buffer; int index; }; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index a2c36d192..620372012 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -631,47 +631,151 @@ GLenum OpenGL::getGLIndexDataType(IndexDataType type) } } -GLenum OpenGL::getGLVertexDataType(DataType type, GLboolean &normalized, bool &intformat) +GLenum OpenGL::getGLVertexDataType(DataFormat format, int &components, GLboolean &normalized, bool &intformat) { normalized = GL_FALSE; intformat = false; + components = 1; - switch (type) + switch (format) { - case DATA_SNORM8: - normalized = GL_TRUE; - return GL_BYTE; - case DATA_UNORM8: - normalized = GL_TRUE; - return GL_UNSIGNED_BYTE; - case DATA_INT8: - intformat = true; - return GL_BYTE; - case DATA_UINT8: - intformat = true; - return GL_UNSIGNED_BYTE; - case DATA_SNORM16: - normalized = GL_TRUE; - return GL_SHORT; - case DATA_UNORM16: - normalized = GL_TRUE; - return GL_UNSIGNED_SHORT; - case DATA_INT16: - intformat = true; - return GL_SHORT; - case DATA_UINT16: - intformat = true; - return GL_UNSIGNED_SHORT; - case DATA_INT32: + case DATAFORMAT_FLOAT: + components = 1; + return GL_FLOAT; + case DATAFORMAT_FLOAT_VEC2: + components = 2; + return GL_FLOAT; + case DATAFORMAT_FLOAT_VEC3: + components = 3; + return GL_FLOAT; + case DATAFORMAT_FLOAT_VEC4: + components = 4; + return GL_FLOAT; + + case DATAFORMAT_FLOAT_MAT2X2: + case DATAFORMAT_FLOAT_MAT2X3: + case DATAFORMAT_FLOAT_MAT2X4: + case DATAFORMAT_FLOAT_MAT3X2: + case DATAFORMAT_FLOAT_MAT3X3: + case DATAFORMAT_FLOAT_MAT3X4: + case DATAFORMAT_FLOAT_MAT4X2: + case DATAFORMAT_FLOAT_MAT4X3: + case DATAFORMAT_FLOAT_MAT4X4: + return GL_ZERO; + + case DATAFORMAT_INT32: + components = 1; intformat = true; return GL_INT; - case DATA_UINT32: + case DATAFORMAT_INT32_VEC2: + components = 2; + intformat = true; + return GL_INT; + case DATAFORMAT_INT32_VEC3: + components = 3; + intformat = true; + return GL_INT; + case DATAFORMAT_INT32_VEC4: + components = 4; + intformat = true; + return GL_INT; + + case DATAFORMAT_UINT32: + components = 1; intformat = true; return GL_UNSIGNED_INT; - case DATA_FLOAT: - normalized = GL_FALSE; - return GL_FLOAT; - case DATA_MAX_ENUM: + case DATAFORMAT_UINT32_VEC2: + components = 2; + intformat = true; + return GL_UNSIGNED_INT; + case DATAFORMAT_UINT32_VEC3: + components = 3; + intformat = true; + return GL_UNSIGNED_INT; + case DATAFORMAT_UINT32_VEC4: + components = 4; + intformat = true; + return GL_UNSIGNED_INT; + + case DATAFORMAT_SNORM8_VEC4: + components = 4; + normalized = GL_TRUE; + return GL_BYTE; + + case DATAFORMAT_UNORM8_VEC4: + components = 4; + normalized = GL_TRUE; + return GL_UNSIGNED_BYTE; + + case DATAFORMAT_INT8_VEC4: + components = 4; + intformat = true; + return GL_BYTE; + + case DATAFORMAT_UINT8_VEC4: + components = 4; + 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; + return GL_BYTE; + case DATAFORMAT_SNORM16_VEC4: + components = 4; + 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; + return GL_UNSIGNED_SHORT; + case DATAFORMAT_UNORM16_VEC4: + components = 4; + 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; + return GL_SHORT; + case DATAFORMAT_INT16_VEC4: + components = 4; + intformat = true; + return GL_SHORT; + + case DATAFORMAT_UINT16: + components = 1; + intformat = true; + return GL_UNSIGNED_SHORT; + case DATAFORMAT_UINT16_VEC2: + components = 2; + intformat = true; + return GL_UNSIGNED_SHORT; + case DATAFORMAT_UINT16_VEC4: + components = 4; + intformat = true; + return GL_UNSIGNED_SHORT; + + case DATAFORMAT_BOOL: + case DATAFORMAT_BOOL_VEC2: + case DATAFORMAT_BOOL_VEC3: + case DATAFORMAT_BOOL_VEC4: + return GL_ZERO; + + case DATAFORMAT_MAX_ENUM: return GL_ZERO; } @@ -746,18 +850,19 @@ void OpenGL::setVertexAttributes(const VertexAttributes &attributes, const Buffe if ((state.instancedAttribArrays & bit) ^ divisorbit) glVertexAttribDivisor(i, divisor); + int components = 0; GLboolean normalized = GL_FALSE; bool intformat = false; - GLenum gltype = getGLVertexDataType(attrib.type, normalized, intformat); + GLenum gltype = getGLVertexDataType(attrib.format, components, normalized, intformat); const void *offsetpointer = reinterpret_cast(bufferinfo.offset + attrib.offsetFromVertex); bindBuffer(BUFFER_VERTEX, (GLuint) bufferinfo.buffer->getHandle()); if (intformat) - glVertexAttribIPointer(i, attrib.components, gltype, layout.stride, offsetpointer); + glVertexAttribIPointer(i, components, gltype, layout.stride, offsetpointer); else - glVertexAttribPointer(i, attrib.components, gltype, normalized, layout.stride, offsetpointer); + glVertexAttribPointer(i, components, gltype, normalized, layout.stride, offsetpointer); } i++; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 264a9fe3b..01faf8a37 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -404,7 +404,7 @@ public: static GLenum getGLPrimitiveType(PrimitiveType type); static GLenum getGLBufferType(BufferType type); static GLenum getGLIndexDataType(IndexDataType type); - static GLenum getGLVertexDataType(DataType type, GLboolean &normalized, bool &intformat); + static GLenum getGLVertexDataType(DataFormat format, int &components, GLboolean &normalized, bool &intformat); static GLenum getGLBufferUsage(BufferUsage usage); static GLenum getGLTextureType(TextureType type); static GLint getGLWrapMode(Texture::WrapMode wmode); diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index cfd7acdbb..42ab2f153 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -309,44 +309,44 @@ void VertexAttributes::setCommonFormat(CommonFormat format, uint8 bufferindex) case CommonFormat::NONE: break; case CommonFormat::XYf: - set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex); + set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex); break; case CommonFormat::XYZf: - set(ATTRIB_POS, DATA_FLOAT, 3, 0, bufferindex); + set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC3, 0, bufferindex); break; case CommonFormat::RGBAub: - set(ATTRIB_COLOR, DATA_UNORM8, 4, 0, bufferindex); + set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, 0, bufferindex); break; case CommonFormat::STf_RGBAub: - set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, 0, bufferindex); - set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 2), bufferindex); + set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC2, 0, bufferindex); + set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 2), bufferindex); break; case CommonFormat::STPf_RGBAub: - set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, 0, bufferindex); - set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 3), bufferindex); + set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC3, 0, bufferindex); + set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 3), bufferindex); break; case CommonFormat::XYf_STf: - set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex); - set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, uint16(sizeof(float) * 2), bufferindex); + set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex); + set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC2, uint16(sizeof(float) * 2), bufferindex); break; case CommonFormat::XYf_STPf: - set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex); - set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, uint16(sizeof(float) * 2), bufferindex); + set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex); + set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC3, uint16(sizeof(float) * 2), bufferindex); break; case CommonFormat::XYf_STf_RGBAub: - set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex); - set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, uint16(sizeof(float) * 2), bufferindex); - set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 4), bufferindex); + set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex); + set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC2, uint16(sizeof(float) * 2), bufferindex); + set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 4), bufferindex); break; case CommonFormat::XYf_STus_RGBAub: - set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex); - set(ATTRIB_TEXCOORD, DATA_UNORM16, 2, uint16(sizeof(float) * 2), bufferindex); - set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 2 + sizeof(uint16) * 2), bufferindex); + set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex); + set(ATTRIB_TEXCOORD, DATAFORMAT_UNORM16_VEC2, uint16(sizeof(float) * 2), bufferindex); + set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 2 + sizeof(uint16) * 2), bufferindex); break; case CommonFormat::XYf_STPf_RGBAub: - set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex); - set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, uint16(sizeof(float) * 2), bufferindex); - set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 5), bufferindex); + set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex); + set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC3, uint16(sizeof(float) * 2), bufferindex); + set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 5), bufferindex); break; } } diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index ded03f536..aacd0f53f 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -320,8 +320,7 @@ struct BufferBindings struct VertexAttributeInfo { uint8 bufferIndex; - DataType type : 4; - uint8 components : 4; + DataFormat format : 8; uint16 offsetFromVertex; }; @@ -346,13 +345,12 @@ struct VertexAttributes setCommonFormat(format, bufferindex); } - void set(uint32 index, DataType type, uint8 components, uint16 offsetfromvertex, uint8 bufferindex) + void set(uint32 index, DataFormat format, uint16 offsetfromvertex, uint8 bufferindex) { enableBits |= (1u << index); attribs[index].bufferIndex = bufferindex; - attribs[index].type = type; - attribs[index].components = components; + attribs[index].format = format; attribs[index].offsetFromVertex = offsetfromvertex; } diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index 2902dd5ed..8bad4cbfa 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -416,7 +416,17 @@ int w_Mesh_attachAttribute(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); const char *name = luaL_checkstring(L, 2); - Mesh *mesh = luax_checkmesh(L, 3); + + Buffer *buffer = nullptr; + if (luax_istype(L, 3, Buffer::type)) + { + buffer = luax_checktype(L, 3); + } + else + { + Mesh *mesh = luax_checkmesh(L, 3); + buffer = mesh->getVertexBuffer(); + } AttributeStep step = STEP_PER_VERTEX; const char *stepstr = lua_isnoneornil(L, 4) ? nullptr : luaL_checkstring(L, 4); @@ -425,7 +435,7 @@ int w_Mesh_attachAttribute(lua_State *L) const char *attachname = luaL_optstring(L, 5, name); - luax_catchexcept(L, [&](){ t->attachAttribute(name, mesh, attachname, step); }); + luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer, attachname, step); }); return 0; } diff --git a/src/modules/graphics/wrap_SpriteBatch.cpp b/src/modules/graphics/wrap_SpriteBatch.cpp index 7986f042e..598c45d7a 100644 --- a/src/modules/graphics/wrap_SpriteBatch.cpp +++ b/src/modules/graphics/wrap_SpriteBatch.cpp @@ -226,9 +226,19 @@ int w_SpriteBatch_attachAttribute(lua_State *L) { SpriteBatch *t = luax_checkspritebatch(L, 1); const char *name = luaL_checkstring(L, 2); - Mesh *m = luax_checktype(L, 3); - luax_catchexcept(L, [&](){ t->attachAttribute(name, m); }); + Buffer *buffer = nullptr; + if (luax_istype(L, 3, Buffer::type)) + { + buffer = luax_checktype(L, 3); + } + else + { + Mesh *mesh = luax_checktype(L, 3); + buffer = mesh->getVertexBuffer(); + } + + luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer); }); return 0; } From afcb467fa75c8f2d85b9ded21a4e3a9afcf229ea Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 19 Jan 2020 19:03:46 -0400 Subject: [PATCH 08/26] Remove some unrelated code that was accidentally included in previous commits. --- src/modules/graphics/ParticleSystem.h | 71 -------------------- src/modules/graphics/wrap_GraphicsShader.lua | 30 --------- 2 files changed, 101 deletions(-) diff --git a/src/modules/graphics/ParticleSystem.h b/src/modules/graphics/ParticleSystem.h index 07740a3bd..374cd846c 100644 --- a/src/modules/graphics/ParticleSystem.h +++ b/src/modules/graphics/ParticleSystem.h @@ -558,77 +558,6 @@ private: int quadIndex; }; - struct Emitter - { - // Pointer to the beginning of the allocated memory. - Particle *pMem; - - // Pointer to a free particle. - Particle *pFree; - - // Pointer to the start of the linked list. - Particle *pHead; - - // Pointer to the end of the linked list. - Particle *pTail; - - // Whether the particle emitter is active. - bool active; - - // Insert mode of new particles. - InsertMode insertMode; - - // The number of active particles. - uint32 activeParticles; - - // The emission rate (particles/sec). - float emissionRate; - - // Used to determine when a particle should be emitted. - float emitCounter; - - // The relative position of the particle emitter. - love::Vector2 position; - love::Vector2 prevPosition; - - // Emission area spread. - AreaSpreadDistribution emissionAreaDistribution; - love::Vector2 emissionArea; - float emissionAreaAngle; - bool directionRelativeToEmissionCenter; - - // The lifetime of the particle emitter (-1 means infinite) and the life it has left. - float lifetime; - float life; - - // The particle life. - float particleLifeMin; - float particleLifeMax; - - // The direction (and spread) the particles will be emitted in. Measured in radians. - float direction; - float spread; - - // The speed. - float speedMin; - float speedMax; - - // Acceleration along the x and y axes. - love::Vector2 linearAccelerationMin; - love::Vector2 linearAccelerationMax; - - // Acceleration towards the emitter's center - float radialAccelerationMin; - float radialAccelerationMax; - - // Acceleration perpendicular to the particle's direction. - float tangentialAccelerationMin; - float tangentialAccelerationMax; - - float linearDampingMin; - float linearDampingMax; - }; - void resetOffset(); void createBuffers(size_t size); diff --git a/src/modules/graphics/wrap_GraphicsShader.lua b/src/modules/graphics/wrap_GraphicsShader.lua index 02cb9998b..14a1ba19d 100644 --- a/src/modules/graphics/wrap_GraphicsShader.lua +++ b/src/modules/graphics/wrap_GraphicsShader.lua @@ -380,36 +380,6 @@ local function isPixelCode(code) end end -local function includeShader(path, dir, global) - -end - -local function preprocessIncludes(code, dir, level) - local output = {} - - local linecount = 0 - for line in code:gmatch("[^\r\n]+") do - linecount = linecount + 1 - - if line:match("^%s*#include") then - local localpath = line:match("^%s*#include%s*\"(.*)\"") - local globalpath = line:match("^%s*#include%s*<(.*)>") - --local - if localpath then - --table_insert(output, ) - elseif globalpath then - - else - - end - else - table_insert(output, line) - end - end - - return table_concat(output, "\n") -end - function love.graphics._shaderCodeToGLSL(gles, arg1, arg2) local vertexcode, pixelcode local is_custompixel = false -- whether pixel code has "effects" function instead of "effect" From 2572f0c7a18f615e3ac3f3392781cf2ed130285f Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 1 Feb 2020 15:39:59 -0400 Subject: [PATCH 09/26] Meshes expose GraphicsBuffers, part 2 --- src/modules/graphics/Buffer.cpp | 73 ++++--- src/modules/graphics/Buffer.h | 52 ++++- src/modules/graphics/Font.cpp | 2 +- src/modules/graphics/Graphics.cpp | 33 ++-- src/modules/graphics/Graphics.h | 12 +- src/modules/graphics/Mesh.cpp | 127 ++++--------- src/modules/graphics/Mesh.h | 21 +-- src/modules/graphics/ParticleSystem.cpp | 6 +- src/modules/graphics/Polyline.cpp | 4 +- src/modules/graphics/Polyline.h | 4 +- src/modules/graphics/SpriteBatch.cpp | 10 +- src/modules/graphics/Text.cpp | 8 +- src/modules/graphics/Texture.cpp | 4 +- src/modules/graphics/Video.cpp | 2 +- src/modules/graphics/opengl/Buffer.cpp | 105 ++++++----- src/modules/graphics/opengl/Buffer.h | 29 +-- src/modules/graphics/opengl/Graphics.cpp | 19 +- src/modules/graphics/opengl/Graphics.h | 4 +- src/modules/graphics/opengl/OpenGL.cpp | 28 +-- src/modules/graphics/opengl/OpenGL.h | 2 +- src/modules/graphics/vertex.cpp | 100 +++------- src/modules/graphics/vertex.h | 62 ++---- src/modules/graphics/wrap_Graphics.cpp | 47 ++--- src/modules/graphics/wrap_Mesh.cpp | 231 ++++++++++++++--------- src/modules/graphics/wrap_Mesh.h | 4 +- 25 files changed, 491 insertions(+), 498 deletions(-) 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); From c9809d8d827c68ff956adfb9d9aaee4396ebc217 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 1 Feb 2020 15:59:38 -0400 Subject: [PATCH 10/26] Clean up some Mesh code --- src/modules/graphics/Buffer.h | 20 ++++---------------- src/modules/graphics/Graphics.cpp | 2 +- src/modules/graphics/Mesh.cpp | 22 +++++----------------- src/modules/graphics/Mesh.h | 2 +- 4 files changed, 11 insertions(+), 35 deletions(-) diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 12fc2659a..75e999dda 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -158,23 +158,11 @@ public: { public: - Mapper(Buffer &buffer) - : buf(buffer) - { - elems = buf.map(); - } + Mapper(Buffer &buffer) : buffer(buffer) { data = buffer.map(); } + ~Mapper() { buffer.unmap(); } - ~Mapper() - { - buf.unmap(); - } - - void *get() { return elems; } - - private: - - Buffer &buf; - void *elems; + Buffer &buffer; + void *data; }; // Mapper diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index d7e754aee..4369b2bdf 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -176,7 +176,7 @@ void Graphics::createQuadIndexBuffer() quadIndexBuffer = newIndexBuffer(INDEX_UINT16, nullptr, size, BUFFERUSAGE_STATIC, 0); Buffer::Mapper map(*quadIndexBuffer); - fillIndices(TRIANGLEINDEX_QUADS, 0, LOVE_UINT16_MAX, (uint16 *) map.get()); + fillIndices(TRIANGLEINDEX_QUADS, 0, LOVE_UINT16_MAX, (uint16 *) map.data); } Quad *Graphics::newQuad(Quad::Viewport v, double sw, double sh) diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index ef186137e..4396842d1 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -118,12 +118,6 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector & Mesh::~Mesh() { delete vertexScratchBuffer; - - for (const auto &attrib : attachedAttributes) - { - if (attrib.second.buffer != nullptr && attrib.second.buffer != vertexBuffer.get()) - attrib.second.buffer->release(); - } } void Mesh::setupAttachedAttributes() @@ -282,28 +276,22 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::s throw love::Exception("A maximum of %d attributes can be attached at once.", VertexAttributes::MAX); newattrib.buffer = buffer; - newattrib.enabled = oldattrib.buffer ? oldattrib.enabled : true; + newattrib.enabled = oldattrib.buffer.get() ? oldattrib.enabled : true; newattrib.index = buffer->getDataMemberIndex(attachname); newattrib.step = step; if (newattrib.index < 0) throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str()); - newattrib.buffer->retain(); - attachedAttributes[name] = newattrib; - - if (oldattrib.buffer) - oldattrib.buffer->release(); } bool Mesh::detachAttribute(const std::string &name) { auto it = attachedAttributes.find(name); - if (it != attachedAttributes.end() && it->second.buffer != vertexBuffer.get()) + if (it != attachedAttributes.end()) { - it->second.buffer->release(); attachedAttributes.erase(it); if (getAttributeIndex(name) != -1) @@ -340,7 +328,7 @@ void Mesh::flush() template static void copyToIndexBuffer(const std::vector &indices, Buffer::Mapper &buffermap, size_t maxval) { - T *elems = (T *) buffermap.get(); + T *elems = (T *) buffermap.data; for (size_t i = 0; i < indices.size(); i++) { @@ -405,7 +393,7 @@ void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasiz return; Buffer::Mapper ibomap(*indexBuffer); - memcpy(ibomap.get(), data, datasize); + memcpy(ibomap.data, data, datasize); useIndexBuffer = true; indexDataType = datatype; @@ -541,7 +529,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) if (!attrib.second.enabled) continue; - Buffer *buffer = attrib.second.buffer; + Buffer *buffer = attrib.second.buffer.get(); int attributeindex = -1; // If the attribute is one of the LOVE-defined ones, use the constant diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 160dcf66e..7e099f3dc 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -174,7 +174,7 @@ private: struct AttachedAttribute { - Buffer *buffer; + StrongRef buffer; int index; AttributeStep step; bool enabled; From 2828761060a77b23fce5e26151f036462cd9a876 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 22 Feb 2020 18:58:41 -0400 Subject: [PATCH 11/26] Move some code from Mesh wrapper to Buffer wrapper --- src/modules/graphics/Buffer.cpp | 13 +- src/modules/graphics/Buffer.h | 4 +- src/modules/graphics/Graphics.cpp | 15 +- src/modules/graphics/Graphics.h | 3 +- src/modules/graphics/Shader.h | 5 - src/modules/graphics/opengl/Buffer.cpp | 4 - src/modules/graphics/opengl/OpenGL.cpp | 91 ++++------- src/modules/graphics/vertex.cpp | 78 +++++----- src/modules/graphics/vertex.h | 3 - src/modules/graphics/wrap_Buffer.cpp | 154 +++++++++++++++++++ src/modules/graphics/wrap_Buffer.h | 4 +- src/modules/graphics/wrap_Graphics.cpp | 7 +- src/modules/graphics/wrap_Mesh.cpp | 202 ++----------------------- src/modules/graphics/wrap_Mesh.h | 3 - 14 files changed, 251 insertions(+), 335 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index dfe6fedf5..f85205307 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -50,10 +50,8 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vectorgetCapabilities().features[Graphics::FEATURE_GLSL3]; - 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; @@ -89,16 +87,11 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector format = { - { "index", getIndexDataFormat(dataType), 0 } - }; - - return newBuffer(settings, format, indices, size, 0); + std::vector dataformat = {{"", format, 0}}; + return newBuffer(settings, format, data, size, arraylength); } Mesh *Graphics::newMesh(const std::vector &vertices, PrimitiveType drawmode, BufferUsage usage) diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index e9784ad09..e47bc8b65 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -441,8 +441,7 @@ public: 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 size, BufferUsage usage, uint32 mapflags); + virtual Buffer *newBuffer(const Buffer::Settings &settings, DataFormat format, const void *data, size_t size, size_t arraylength); Mesh *newMesh(const std::vector &vertices, PrimitiveType drawmode, BufferUsage usage); Mesh *newMesh(int vertexcount, PrimitiveType drawmode, BufferUsage usage); diff --git a/src/modules/graphics/Shader.h b/src/modules/graphics/Shader.h index 600cffce6..b31e56546 100644 --- a/src/modules/graphics/Shader.h +++ b/src/modules/graphics/Shader.h @@ -33,11 +33,6 @@ #include #include -namespace glslang -{ -class TShader; -} - namespace love { namespace graphics diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 2c94deaee..698aa5352 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -59,10 +59,6 @@ void Buffer::initialize(const void *data) 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); diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 4682ca174..215e33f35 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -562,16 +562,11 @@ GLenum OpenGL::getGLPrimitiveType(PrimitiveType type) { switch (type) { - case PRIMITIVE_TRIANGLES: - return GL_TRIANGLES; - case PRIMITIVE_TRIANGLE_STRIP: - return GL_TRIANGLE_STRIP; - case PRIMITIVE_TRIANGLE_FAN: - return GL_TRIANGLE_FAN; - case PRIMITIVE_POINTS: - return GL_POINTS; - case PRIMITIVE_MAX_ENUM: - return GL_ZERO; + case PRIMITIVE_TRIANGLES: return GL_TRIANGLES; + case PRIMITIVE_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP; + case PRIMITIVE_TRIANGLE_FAN: return GL_TRIANGLE_FAN; + case PRIMITIVE_POINTS: return GL_POINTS; + case PRIMITIVE_MAX_ENUM: return GL_ZERO; } return GL_ZERO; @@ -581,16 +576,9 @@ GLenum OpenGL::getGLBufferType(BufferType type) { switch (type) { - case BUFFERTYPE_VERTEX: - return GL_ARRAY_BUFFER; - case BUFFERTYPE_INDEX: - return GL_ELEMENT_ARRAY_BUFFER; - case BUFFERTYPE_UNIFORM: - return GL_UNIFORM_BUFFER; - case BUFFERTYPE_SHADER_STORAGE: - return GL_SHADER_STORAGE_BUFFER; - case BUFFERTYPE_MAX_ENUM: - return GL_ZERO; + case BUFFERTYPE_VERTEX: return GL_ARRAY_BUFFER; + case BUFFERTYPE_INDEX: return GL_ELEMENT_ARRAY_BUFFER; + case BUFFERTYPE_MAX_ENUM: return GL_ZERO; } return GL_ZERO; @@ -600,16 +588,11 @@ GLenum OpenGL::getGLTextureType(TextureType type) { switch (type) { - case TEXTURE_2D: - return GL_TEXTURE_2D; - case TEXTURE_VOLUME: - return GL_TEXTURE_3D; - case TEXTURE_2D_ARRAY: - return GL_TEXTURE_2D_ARRAY; - case TEXTURE_CUBE: - return GL_TEXTURE_CUBE_MAP; - case TEXTURE_MAX_ENUM: - return GL_ZERO; + case TEXTURE_2D: return GL_TEXTURE_2D; + case TEXTURE_VOLUME: return GL_TEXTURE_3D; + case TEXTURE_2D_ARRAY: return GL_TEXTURE_2D_ARRAY; + case TEXTURE_CUBE: return GL_TEXTURE_CUBE_MAP; + case TEXTURE_MAX_ENUM: return GL_ZERO; } return GL_ZERO; @@ -619,12 +602,9 @@ GLenum OpenGL::getGLIndexDataType(IndexDataType type) { switch (type) { - case INDEX_UINT16: - return GL_UNSIGNED_SHORT; - case INDEX_UINT32: - return GL_UNSIGNED_INT; - default: - return GL_ZERO; + case INDEX_UINT16: return GL_UNSIGNED_SHORT; + case INDEX_UINT32: return GL_UNSIGNED_INT; + default: return GL_ZERO; } } @@ -771,14 +751,10 @@ GLenum OpenGL::getGLBufferUsage(BufferUsage usage) { switch (usage) { - case BUFFERUSAGE_STREAM: - return GL_STREAM_DRAW; - case BUFFERUSAGE_DYNAMIC: - return GL_DYNAMIC_DRAW; - case BUFFERUSAGE_STATIC: - return GL_STATIC_DRAW; - default: - return 0; + case BUFFERUSAGE_STREAM: return GL_STREAM_DRAW; + case BUFFERUSAGE_DYNAMIC: return GL_DYNAMIC_DRAW; + case BUFFERUSAGE_STATIC: return GL_STATIC_DRAW; + default: return 0; } } @@ -1165,24 +1141,15 @@ GLint OpenGL::getGLCompareMode(CompareMode mode) { switch (mode) { - case COMPARE_LESS: - return GL_LESS; - case COMPARE_LEQUAL: - return GL_LEQUAL; - case COMPARE_EQUAL: - return GL_EQUAL; - case COMPARE_GEQUAL: - return GL_GEQUAL; - case COMPARE_GREATER: - return GL_GREATER; - case COMPARE_NOTEQUAL: - return GL_NOTEQUAL; - case COMPARE_ALWAYS: - return GL_ALWAYS; - case COMPARE_NEVER: - return GL_NEVER; - default: - return GL_NEVER; + case COMPARE_LESS: return GL_LESS; + case COMPARE_LEQUAL: return GL_LEQUAL; + case COMPARE_EQUAL: return GL_EQUAL; + case COMPARE_GEQUAL: return GL_GEQUAL; + case COMPARE_GREATER: return GL_GREATER; + case COMPARE_NOTEQUAL: return GL_NOTEQUAL; + case COMPARE_ALWAYS: return GL_ALWAYS; + case COMPARE_NEVER: return GL_NEVER; + default: return GL_NEVER; } } diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 0b6c92e46..c5e3e32dd 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -104,56 +104,56 @@ int getFormatPositionComponents(CommonFormat format) // Order here relies on order of DataFormat enum. static const DataFormatInfo dataFormatInfo[] { - // baseType, isMatrix, components, rows, columns, componentSize, align, size - { DATA_BASETYPE_FLOAT, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_FLOAT - { DATA_BASETYPE_FLOAT, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_FLOAT_VEC2 - { DATA_BASETYPE_FLOAT, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_FLOAT_VEC3 - { DATA_BASETYPE_FLOAT, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_FLOAT_VEC4 + // baseType, isMatrix, components, rows, columns, componentSize, size + { DATA_BASETYPE_FLOAT, false, 1, 0, 0, 4, 4 }, // DATAFORMAT_FLOAT + { DATA_BASETYPE_FLOAT, false, 2, 0, 0, 4, 8 }, // DATAFORMAT_FLOAT_VEC2 + { DATA_BASETYPE_FLOAT, false, 3, 0, 0, 4, 12 }, // DATAFORMAT_FLOAT_VEC3 + { DATA_BASETYPE_FLOAT, false, 4, 0, 0, 4, 16 }, // DATAFORMAT_FLOAT_VEC4 - { DATA_BASETYPE_FLOAT, true, 0, 2, 2, 4, 4, 16 }, // DATAFORMAT_FLOAT_MAT2X2 - { DATA_BASETYPE_FLOAT, true, 0, 2, 3, 4, 4, 24 }, // DATAFORMAT_FLOAT_MAT2X3 - { DATA_BASETYPE_FLOAT, true, 0, 2, 4, 4, 4, 32 }, // DATAFORMAT_FLOAT_MAT2X4 + { DATA_BASETYPE_FLOAT, true, 0, 2, 2, 4, 16 }, // DATAFORMAT_FLOAT_MAT2X2 + { DATA_BASETYPE_FLOAT, true, 0, 2, 3, 4, 24 }, // DATAFORMAT_FLOAT_MAT2X3 + { DATA_BASETYPE_FLOAT, true, 0, 2, 4, 4, 32 }, // DATAFORMAT_FLOAT_MAT2X4 - { DATA_BASETYPE_FLOAT, true, 0, 3, 2, 4, 4, 24 }, // DATAFORMAT_FLOAT_MAT3X2 - { DATA_BASETYPE_FLOAT, true, 0, 3, 3, 4, 4, 36 }, // DATAFORMAT_FLOAT_MAT3X3 - { DATA_BASETYPE_FLOAT, true, 0, 3, 4, 4, 4, 48 }, // DATAFORMAT_FLOAT_MAT3X4 + { DATA_BASETYPE_FLOAT, true, 0, 3, 2, 4, 24 }, // DATAFORMAT_FLOAT_MAT3X2 + { DATA_BASETYPE_FLOAT, true, 0, 3, 3, 4, 36 }, // DATAFORMAT_FLOAT_MAT3X3 + { DATA_BASETYPE_FLOAT, true, 0, 3, 4, 4, 48 }, // DATAFORMAT_FLOAT_MAT3X4 - { DATA_BASETYPE_FLOAT, true, 0, 4, 2, 4, 4, 32 }, // DATAFORMAT_FLOAT_MAT4X2 - { DATA_BASETYPE_FLOAT, true, 0, 4, 3, 4, 4, 48 }, // DATAFORMAT_FLOAT_MAT4X3 - { DATA_BASETYPE_FLOAT, true, 0, 4, 4, 4, 4, 64 }, // DATAFORMAT_FLOAT_MAT4X4 + { DATA_BASETYPE_FLOAT, true, 0, 4, 2, 4, 32 }, // DATAFORMAT_FLOAT_MAT4X2 + { DATA_BASETYPE_FLOAT, true, 0, 4, 3, 4, 48 }, // DATAFORMAT_FLOAT_MAT4X3 + { DATA_BASETYPE_FLOAT, true, 0, 4, 4, 4, 64 }, // DATAFORMAT_FLOAT_MAT4X4 - { DATA_BASETYPE_INT, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_INT32 - { DATA_BASETYPE_INT, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_INT32_VEC2 - { DATA_BASETYPE_INT, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_INT32_VEC3 - { DATA_BASETYPE_INT, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_INT32_VEC4 + { DATA_BASETYPE_INT, false, 1, 0, 0, 4, 4 }, // DATAFORMAT_INT32 + { DATA_BASETYPE_INT, false, 2, 0, 0, 4, 8 }, // DATAFORMAT_INT32_VEC2 + { DATA_BASETYPE_INT, false, 3, 0, 0, 4, 12 }, // DATAFORMAT_INT32_VEC3 + { DATA_BASETYPE_INT, false, 4, 0, 0, 4, 16 }, // DATAFORMAT_INT32_VEC4 - { DATA_BASETYPE_UINT, false, 1, 0, 0, 4, 4, 4 }, // DATAFORMAT_UINT32 - { DATA_BASETYPE_UINT, false, 2, 0, 0, 4, 4, 8 }, // DATAFORMAT_UINT32_VEC2 - { DATA_BASETYPE_UINT, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_UINT32_VEC3 - { DATA_BASETYPE_UINT, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_UINT32_VEC4 + { DATA_BASETYPE_UINT, false, 1, 0, 0, 4, 4 }, // DATAFORMAT_UINT32 + { DATA_BASETYPE_UINT, false, 2, 0, 0, 4, 8 }, // DATAFORMAT_UINT32_VEC2 + { DATA_BASETYPE_UINT, false, 3, 0, 0, 4, 12 }, // DATAFORMAT_UINT32_VEC3 + { DATA_BASETYPE_UINT, false, 4, 0, 0, 4, 16 }, // DATAFORMAT_UINT32_VEC4 - { DATA_BASETYPE_SNORM, false, 4, 0, 0, 1, 1, 4 }, // DATAFORMAT_SNORM8_VEC4 - { DATA_BASETYPE_UNORM, false, 4, 0, 0, 1, 1, 4 }, // DATAFORMAT_UNORM8_VEC4 - { 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, 4, 0, 0, 1, 4 }, // DATAFORMAT_SNORM8_VEC4 + { DATA_BASETYPE_UNORM, false, 4, 0, 0, 1, 4 }, // DATAFORMAT_UNORM8_VEC4 + { DATA_BASETYPE_INT, false, 4, 0, 0, 1, 4 }, // DATAFORMAT_INT8_VEC4 + { DATA_BASETYPE_UINT, false, 4, 0, 0, 1, 4 }, // DATAFORMAT_UINT8_VEC4 - { 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_SNORM, false, 2, 0, 0, 2, 4 }, // DATAFORMAT_SNORM16_VEC2 + { DATA_BASETYPE_SNORM, false, 4, 0, 0, 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_UNORM, false, 2, 0, 0, 2, 4 }, // DATAFORMAT_UNORM16_VEC2 + { DATA_BASETYPE_UNORM, false, 4, 0, 0, 2, 8 }, // DATAFORMAT_UNORM16_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_INT, false, 2, 0, 0, 2, 4 }, // DATAFORMAT_INT16_VEC2 + { DATA_BASETYPE_INT, false, 4, 0, 0, 2, 8 }, // DATAFORMAT_INT16_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_UINT, false, 1, 0, 0, 2, 2 }, // DATAFORMAT_UINT16 + { DATA_BASETYPE_UINT, false, 2, 0, 0, 2, 4 }, // DATAFORMAT_UINT16_VEC2 + { DATA_BASETYPE_UINT, false, 4, 0, 0, 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 - { DATA_BASETYPE_BOOL, false, 3, 0, 0, 4, 4, 12 }, // DATAFORMAT_BOOL_VEC3 - { DATA_BASETYPE_BOOL, false, 4, 0, 0, 4, 4, 16 }, // DATAFORMAT_BOOL_VEC4 + { DATA_BASETYPE_BOOL, false, 1, 0, 0, 4, 4 }, // DATAFORMAT_BOOL + { DATA_BASETYPE_BOOL, false, 2, 0, 0, 4, 8 }, // DATAFORMAT_BOOL_VEC2 + { DATA_BASETYPE_BOOL, false, 3, 0, 0, 4, 12 }, // DATAFORMAT_BOOL_VEC3 + { DATA_BASETYPE_BOOL, false, 4, 0, 0, 4, 16 }, // DATAFORMAT_BOOL_VEC4 }; static_assert((sizeof(dataFormatInfo) / sizeof(DataFormatInfo)) == DATAFORMAT_MAX_ENUM, "dataFormatInfo array size must match number of DataFormat enum values."); diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index cac61989f..a24e92604 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -58,8 +58,6 @@ enum BufferType { BUFFERTYPE_VERTEX = 0, BUFFERTYPE_INDEX, - BUFFERTYPE_UNIFORM, - BUFFERTYPE_SHADER_STORAGE, BUFFERTYPE_MAX_ENUM }; @@ -218,7 +216,6 @@ struct DataFormatInfo int matrixRows; int matrixColumns; size_t componentSize; - size_t alignment; size_t size; }; diff --git a/src/modules/graphics/wrap_Buffer.cpp b/src/modules/graphics/wrap_Buffer.cpp index 7b69a6519..d352c40f8 100644 --- a/src/modules/graphics/wrap_Buffer.cpp +++ b/src/modules/graphics/wrap_Buffer.cpp @@ -26,6 +26,160 @@ namespace love namespace graphics { +static const double defaultComponents[] = {0.0, 0.0, 0.0, 1.0}; + +template +static inline size_t writeData(lua_State *L, int startidx, int components, char *data) +{ + auto componentdata = (T *) data; + + for (int i = 0; i < components; i++) + componentdata[i] = (T) (luaL_optnumber(L, startidx + i, defaultComponents[i])); + + return sizeof(T) * components; +} + +template +static inline size_t writeSNormData(lua_State *L, int startidx, int components, char *data) +{ + auto componentdata = (T *) data; + 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); + + return sizeof(T) * components; +} + +template +static inline size_t writeUNormData(lua_State *L, int startidx, int components, char *data) +{ + auto componentdata = (T *) data; + 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); + + return sizeof(T) * components; +} + +void luax_writebufferdata(lua_State *L, int startidx, DataFormat format, char *data) +{ + switch (format) + { + case DATAFORMAT_FLOAT: writeData(L, startidx, 1, data); break; + case DATAFORMAT_FLOAT_VEC2: writeData(L, startidx, 2, data); break; + case DATAFORMAT_FLOAT_VEC3: writeData(L, startidx, 3, data); break; + case DATAFORMAT_FLOAT_VEC4: writeData(L, startidx, 4, data); break; + + case DATAFORMAT_INT32: writeData(L, startidx, 1, data); break; + case DATAFORMAT_INT32_VEC2: writeData(L, startidx, 2, data); break; + case DATAFORMAT_INT32_VEC3: writeData(L, startidx, 3, data); break; + case DATAFORMAT_INT32_VEC4: writeData(L, startidx, 4, data); break; + + case DATAFORMAT_UINT32: writeData(L, startidx, 1, data); break; + case DATAFORMAT_UINT32_VEC2: writeData(L, startidx, 2, data); break; + case DATAFORMAT_UINT32_VEC3: writeData(L, startidx, 3, data); break; + case DATAFORMAT_UINT32_VEC4: writeData(L, startidx, 4, data); break; + + case DATAFORMAT_SNORM8_VEC4: writeSNormData(L, startidx, 4, data); break; + case DATAFORMAT_UNORM8_VEC4: writeUNormData(L, startidx, 4, data); break; + case DATAFORMAT_INT8_VEC4: writeData(L, startidx, 4, data); break; + case DATAFORMAT_UINT8_VEC4: writeData(L, startidx, 4, data); break; + + case DATAFORMAT_SNORM16_VEC2: writeSNormData(L, startidx, 2, data); break; + case DATAFORMAT_SNORM16_VEC4: writeSNormData(L, startidx, 4, data); break; + + case DATAFORMAT_UNORM16_VEC2: writeUNormData(L, startidx, 2, data); break; + case DATAFORMAT_UNORM16_VEC4: writeUNormData(L, startidx, 4, data); break; + + case DATAFORMAT_INT16_VEC2: writeData(L, startidx, 2, data); break; + case DATAFORMAT_INT16_VEC4: writeData(L, startidx, 4, data); break; + + case DATAFORMAT_UINT16: writeData(L, startidx, 1, data); break; + case DATAFORMAT_UINT16_VEC2: writeData(L, startidx, 2, data); break; + case DATAFORMAT_UINT16_VEC4: writeData(L, startidx, 4, data); break; + + default: break; + } +} + +template +static inline size_t readData(lua_State *L, int components, const char *data) +{ + const auto componentdata = (const T *) data; + + for (int i = 0; i < components; i++) + lua_pushnumber(L, (lua_Number) componentdata[i]); + + return sizeof(T) * components; +} + +template +static inline size_t readSNormData(lua_State *L, int components, const char *data) +{ + 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)); + + return sizeof(T) * components; +} + +template +static inline size_t readUNormData(lua_State *L, int components, const char *data) +{ + 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); + + return sizeof(T) * components; +} + +void luax_readbufferdata(lua_State *L, DataFormat format, const char *data) +{ + switch (format) + { + case DATAFORMAT_FLOAT: readData(L, 1, data); break; + case DATAFORMAT_FLOAT_VEC2: readData(L, 2, data); break; + case DATAFORMAT_FLOAT_VEC3: readData(L, 3, data); break; + case DATAFORMAT_FLOAT_VEC4: readData(L, 4, data); break; + + case DATAFORMAT_INT32: readData(L, 1, data); break; + case DATAFORMAT_INT32_VEC2: readData(L, 2, data); break; + case DATAFORMAT_INT32_VEC3: readData(L, 3, data); break; + case DATAFORMAT_INT32_VEC4: readData(L, 4, data); break; + + case DATAFORMAT_UINT32: readData(L, 1, data); break; + case DATAFORMAT_UINT32_VEC2: readData(L, 2, data); break; + case DATAFORMAT_UINT32_VEC3: readData(L, 3, data); break; + case DATAFORMAT_UINT32_VEC4: readData(L, 4, data); break; + + case DATAFORMAT_SNORM8_VEC4: readSNormData(L, 4, data); break; + case DATAFORMAT_UNORM8_VEC4: readUNormData(L, 4, data); break; + case DATAFORMAT_INT8_VEC4: readData(L, 4, data); break; + case DATAFORMAT_UINT8_VEC4: readData(L, 4, data); break; + + case DATAFORMAT_SNORM16_VEC2: readSNormData(L, 2, data); break; + case DATAFORMAT_SNORM16_VEC4: readSNormData(L, 4, data); break; + + case DATAFORMAT_UNORM16_VEC2: readUNormData(L, 2, data); break; + case DATAFORMAT_UNORM16_VEC4: readUNormData(L, 4, data); break; + + case DATAFORMAT_INT16_VEC2: readData(L, 2, data); break; + case DATAFORMAT_INT16_VEC4: readData(L, 4, data); break; + + case DATAFORMAT_UINT16: readData(L, 1, data); break; + case DATAFORMAT_UINT16_VEC2: readData(L, 2, data); break; + case DATAFORMAT_UINT16_VEC4: readData(L, 4, data); break; + + default: break; + } +} + Buffer *luax_checkbuffer(lua_State *L, int idx) { return luax_checktype(L, idx); diff --git a/src/modules/graphics/wrap_Buffer.h b/src/modules/graphics/wrap_Buffer.h index 6a0d42412..3fdfeb6ca 100644 --- a/src/modules/graphics/wrap_Buffer.h +++ b/src/modules/graphics/wrap_Buffer.h @@ -22,13 +22,15 @@ // LOVE #include "common/runtime.h" +#include "Buffer.h" namespace love { namespace graphics { -class Buffer; +void luax_writebufferdata(lua_State *L, int startidx, DataFormat format, char *data); +void luax_readbufferdata(lua_State *L, DataFormat format, const char *data); Buffer *luax_checkbuffer(lua_State *L, int idx); extern "C" int luaopen_graphicsbuffer(lua_State *L); diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index b2925de82..dc24f7eaf 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1704,19 +1704,18 @@ static Mesh *newCustomMesh(lua_State *L) for (size_t i = 0; i < vertexformat.size(); i++) { const auto &info = getDataFormatInfo(vertexformat[i].format); - int components = info.components; // get vertices[vertindex][n] - for (int c = 0; c < components; c++) + for (int c = 0; c < info.components; c++) { n++; lua_rawgeti(L, -(c + 1), n); } // Fetch the values from Lua and store them in data buffer. - luax_writeAttributeData(L, -components, vertexformat[i].format, components, data); + luax_writebufferdata(L, -info.components, vertexformat[i].format, data); - lua_pop(L, components); + lua_pop(L, info.components); luax_catchexcept(L, [&](){ t->setVertexAttribute(vertindex, i, data, sizeof(float) * 4); }, diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index f6eefe504..f3b132594 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -20,6 +20,7 @@ // LOVE #include "wrap_Mesh.h" +#include "wrap_Buffer.h" #include "Texture.h" #include "wrap_Texture.h" @@ -36,184 +37,6 @@ Mesh *luax_checkmesh(lua_State *L, int idx) return luax_checktype(L, idx); } -static const double defaultComponents[] = {0.0, 0.0, 0.0, 1.0}; - -template -static inline size_t writeData(lua_State *L, int startidx, int components, char *data) -{ - auto componentdata = (T *) data; - - for (int i = 0; i < components; i++) - componentdata[i] = (T) (luaL_optnumber(L, startidx + i, defaultComponents[i])); - - return sizeof(T) * components; -} - -template -static inline size_t writeSNormData(lua_State *L, int startidx, int components, char *data) -{ - auto componentdata = (T *) data; - 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); - - return sizeof(T) * components; -} - -template -static inline size_t writeUNormData(lua_State *L, int startidx, int components, char *data) -{ - auto componentdata = (T *) data; - 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); - - return sizeof(T) * components; -} - -char *luax_writeAttributeData(lua_State *L, int startidx, DataFormat format, int components, char *data) -{ - switch (format) - { - 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; - } -} - -template -static inline size_t readData(lua_State *L, int components, const char *data) -{ - const auto componentdata = (const T *) data; - - for (int i = 0; i < components; i++) - lua_pushnumber(L, (lua_Number) componentdata[i]); - - return sizeof(T) * components; -} - -template -static inline size_t readSNormData(lua_State *L, int components, const char *data) -{ - 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)); - - return sizeof(T) * components; -} - -template -static inline size_t readUNormData(lua_State *L, int components, const char *data) -{ - 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); - - return sizeof(T) * components; -} - -const char *luax_readAttributeData(lua_State *L, DataFormat format, int components, const char *data) -{ - switch (format) - { - 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; - } -} - int w_Mesh_setVertices(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); @@ -282,11 +105,13 @@ int w_Mesh_setVertices(lua_State *L) for (const Buffer::DataMember &member : vertexformat) { // Fetch the values from Lua and store them in data buffer. - data = luax_writeAttributeData(L, idx, member.decl.format, member.info.components, data); + luax_writebufferdata(L, idx, member.decl.format, data + member.offset); idx += member.info.components; } lua_pop(L, ncomponents + 1); + + data += stride; } t->unmapVertexData(byteoffset, vertcount * stride); @@ -301,9 +126,7 @@ int w_Mesh_setVertex(lua_State *L) bool istable = lua_istable(L, 3); const std::vector &vertexformat = t->getVertexFormat(); - char *data = (char *) t->getVertexScratchBuffer(); - char *writtendata = data; int idx = istable ? 1 : 3; @@ -317,7 +140,7 @@ int w_Mesh_setVertex(lua_State *L) lua_rawgeti(L, 3, i); // Fetch the values from Lua and store them in data buffer. - writtendata = luax_writeAttributeData(L, -components, member.decl.format, components, writtendata); + luax_writebufferdata(L, -components, member.decl.format, data + member.offset); idx += components; lua_pop(L, components); @@ -328,9 +151,8 @@ int w_Mesh_setVertex(lua_State *L) for (const Buffer::DataMember &member : vertexformat) { // Fetch the values from Lua and store them in data buffer. - int components = member.info.components; - writtendata = luax_writeAttributeData(L, idx, member.decl.format, components, writtendata); - idx += components; + luax_writebufferdata(L, idx, member.decl.format, data + member.offset); + idx += member.info.components; } } @@ -346,7 +168,6 @@ int w_Mesh_getVertex(lua_State *L) const std::vector &vertexformat = t->getVertexFormat(); char *data = (char *) t->getVertexScratchBuffer(); - const char *readdata = data; luax_catchexcept(L, [&](){ t->getVertex(index, data, t->getVertexStride()); }); @@ -354,9 +175,8 @@ int w_Mesh_getVertex(lua_State *L) for (const Buffer::DataMember &member : vertexformat) { - int components = member.info.components; - readdata = luax_readAttributeData(L, member.decl.format, components, readdata); - n += components; + luax_readbufferdata(L, member.decl.format, data + member.offset); + n += member.info.components; } return n; @@ -379,7 +199,7 @@ int w_Mesh_setVertexAttribute(lua_State *L) char data[sizeof(float) * 4]; // Fetch the values from Lua and store them in the data buffer. - luax_writeAttributeData(L, 4, member.decl.format, member.info.components, data); + luax_writebufferdata(L, 4, member.decl.format, data); luax_catchexcept(L, [&](){ t->setVertexAttribute(vertindex, attribindex, data, sizeof(float) * 4); }); return 0; @@ -403,7 +223,7 @@ int w_Mesh_getVertexAttribute(lua_State *L) luax_catchexcept(L, [&](){ t->getVertexAttribute(vertindex, attribindex, data, sizeof(float) * 4); }); - luax_readAttributeData(L, member.decl.format, member.info.components, data); + luax_readbufferdata(L, member.decl.format, data); return member.info.components; } diff --git a/src/modules/graphics/wrap_Mesh.h b/src/modules/graphics/wrap_Mesh.h index 29bc319bf..08f73f2e9 100644 --- a/src/modules/graphics/wrap_Mesh.h +++ b/src/modules/graphics/wrap_Mesh.h @@ -30,9 +30,6 @@ namespace love namespace graphics { -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); From 1ddfcd4cc88e7c7d1dc26ae8e82a0a255be02950 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 23 Feb 2020 16:30:55 -0400 Subject: [PATCH 12/26] Always use explicitly typed buffers, even in internal code --- src/modules/graphics/Buffer.cpp | 68 +++++++++++++++++++++--- src/modules/graphics/Buffer.h | 5 +- src/modules/graphics/Graphics.cpp | 2 +- src/modules/graphics/Graphics.h | 1 - src/modules/graphics/Mesh.cpp | 11 ++-- src/modules/graphics/ParticleSystem.cpp | 3 +- src/modules/graphics/SpriteBatch.cpp | 6 ++- src/modules/graphics/Text.cpp | 3 +- src/modules/graphics/opengl/Buffer.cpp | 25 +++------ src/modules/graphics/opengl/Buffer.h | 3 -- src/modules/graphics/opengl/Graphics.cpp | 5 -- src/modules/graphics/opengl/Graphics.h | 1 - 12 files changed, 88 insertions(+), 45 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index f85205307..096217780 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -28,7 +28,7 @@ namespace graphics love::Type Buffer::type("GraphicsBuffer", &Object::type); -Buffer::Buffer(const Settings &settings, const void */*data*/, size_t size) +Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &bufferformat, size_t size, size_t arraylength) : arrayLength(0) , arrayStride(0) , size(size) @@ -36,11 +36,6 @@ Buffer::Buffer(const Settings &settings, const void */*data*/, size_t size) , usage(settings.usage) , mapFlags(settings.mapFlags) , mapped(false) -{ -} - -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 (size == 0 && arraylength == 0) throw love::Exception("Size or array length must be specified."); @@ -128,5 +123,66 @@ int Buffer::getDataMemberIndex(const std::string &name) const return -1; } +std::vector Buffer::getCommonFormatDeclaration(CommonFormat format) +{ + switch (format) + { + case CommonFormat::NONE: + return {}; + case CommonFormat::XYf: + return { + {"VertexPosition", DATAFORMAT_FLOAT_VEC2} + }; + case CommonFormat::XYZf: + return { + {"VertexPosition", DATAFORMAT_FLOAT_VEC3} + }; + case CommonFormat::RGBAub: + return { + {"VertexColor", DATAFORMAT_UNORM8_VEC4} + }; + case CommonFormat::STf_RGBAub: + return { + {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, + {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + }; + case CommonFormat::STPf_RGBAub: + return { + {"VertexTexCoord", DATAFORMAT_FLOAT_VEC3}, + {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + }; + case CommonFormat::XYf_STf: + return { + {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, + {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, + }; + case CommonFormat::XYf_STPf: + return { + {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, + {"VertexTexCoord", DATAFORMAT_FLOAT_VEC3}, + }; + case CommonFormat::XYf_STf_RGBAub: + return { + {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, + {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, + {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + }; + case CommonFormat::XYf_STus_RGBAub: + return { + {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, + {"VertexTexCoord", DATAFORMAT_UNORM16_VEC2}, + {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + }; + case CommonFormat::XYf_STPf_RGBAub: + return { + {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, + {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, + {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + }; + } + + return {}; +} + } // graphics } // love diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 86a08698b..68935569a 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -103,8 +103,7 @@ public: {} }; - 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); + Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, size_t size, size_t arraylength); virtual ~Buffer(); size_t getSize() const { return size; } @@ -154,6 +153,8 @@ public: **/ virtual void copyTo(size_t offset, size_t size, Buffer *other, size_t otheroffset) = 0; + static std::vector getCommonFormatDeclaration(CommonFormat format); + class Mapper { public: diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 855a60d08..db1135840 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -265,7 +265,7 @@ Shader *Graphics::newShader(const std::string &vertex, const std::string &pixel) Buffer *Graphics::newBuffer(const Buffer::Settings &settings, DataFormat format, const void *data, size_t size, size_t arraylength) { std::vector dataformat = {{"", format, 0}}; - return newBuffer(settings, format, data, size, arraylength); + return newBuffer(settings, dataformat, data, size, arraylength); } Mesh *Graphics::newMesh(const std::vector &vertices, PrimitiveType drawmode, BufferUsage usage) diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index e47bc8b65..d598ff198 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -439,7 +439,6 @@ public: ShaderStage *newShaderStage(ShaderStage::StageType stage, const std::string &source); Shader *newShader(const std::string &vertex, const std::string &pixel); - 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; virtual Buffer *newBuffer(const Buffer::Settings &settings, DataFormat format, const void *data, size_t size, size_t arraylength); diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 4396842d1..107c11e49 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -344,15 +344,16 @@ void Mesh::setVertexMap(const std::vector &map) size_t maxval = getVertexCount(); IndexDataType datatype = getIndexDataTypeFromMax(maxval); + DataFormat dataformat = getIndexDataFormat(datatype); // Calculate the size in bytes of the index buffer data. size_t size = map.size() * getIndexDataSize(datatype); - if (indexBuffer.get() == nullptr || size > indexBuffer->getSize()) + if (indexBuffer.get() == nullptr || size > indexBuffer->getSize() || indexBuffer->getDataMember(0).decl.format != dataformat) { auto gfx = Module::getInstance(Module::M_GRAPHICS); Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, vertexBuffer->getUsage()); - indexBuffer.set(gfx->newBuffer(settings, nullptr, size), Acquire::NORETAIN); + indexBuffer.set(gfx->newBuffer(settings, dataformat, nullptr, size, 0), Acquire::NORETAIN); } useIndexBuffer = true; @@ -380,11 +381,13 @@ void Mesh::setVertexMap(const std::vector &map) void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasize) { - if (indexBuffer.get() == nullptr || datasize > indexBuffer->getSize()) + DataFormat dataformat = getIndexDataFormat(datatype); + + if (indexBuffer.get() == nullptr || datasize > indexBuffer->getSize() || indexBuffer->getDataMember(0).decl.format != dataformat) { auto gfx = Module::getInstance(Module::M_GRAPHICS); Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, vertexBuffer->getUsage()); - indexBuffer.set(gfx->newBuffer(settings, nullptr, datasize), Acquire::NORETAIN); + indexBuffer.set(gfx->newBuffer(settings, dataformat, nullptr, datasize, 0), Acquire::NORETAIN); } indexCount = datasize / getIndexDataSize(datatype); diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index 0f8a5aa50..8f1396e2c 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -192,7 +192,8 @@ void ParticleSystem::createBuffers(size_t size) size_t bytes = sizeof(Vertex) * size * 4; Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, 0, BUFFERUSAGE_STREAM); - buffer = gfx->newBuffer(settings, nullptr, bytes); + auto decl = Buffer::getCommonFormatDeclaration(CommonFormat::XYf_STf_RGBAub); + buffer = gfx->newBuffer(settings, decl, nullptr, bytes, 0); } catch (std::bad_alloc &) { diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index b8a55f298..3553aa7c0 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -65,7 +65,8 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage size_t vertex_size = vertex_stride * 4 * size; Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY, usage); - array_buf = gfx->newBuffer(settings, nullptr, vertex_size); + auto decl = Buffer::getCommonFormatDeclaration(vertex_format); + array_buf = gfx->newBuffer(settings, decl, nullptr, vertex_size, 0); } SpriteBatch::~SpriteBatch() @@ -220,7 +221,8 @@ void SpriteBatch::setBufferSize(int newsize) { auto gfx = Module::getInstance(Module::M_GRAPHICS); Buffer::Settings settings(array_buf->getTypeFlags(), array_buf->getMapFlags(), array_buf->getUsage()); - new_array_buf = gfx->newBuffer(settings, nullptr, vertex_size); + auto decl = Buffer::getCommonFormatDeclaration(vertex_format); + new_array_buf = gfx->newBuffer(settings, decl, nullptr, vertex_size, 0); // Copy as much of the old data into the new GLBuffer as can fit. size_t copy_size = vertex_stride * 4 * new_next; diff --git a/src/modules/graphics/Text.cpp b/src/modules/graphics/Text.cpp index f9db16d5e..3e2962d39 100644 --- a/src/modules/graphics/Text.cpp +++ b/src/modules/graphics/Text.cpp @@ -62,7 +62,8 @@ void Text::uploadVertices(const std::vector &vertices, size_t auto gfx = Module::getInstance(Module::M_GRAPHICS); Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, 0, BUFFERUSAGE_DYNAMIC); - Buffer *new_buffer = gfx->newBuffer(settings, nullptr, newsize); + auto decl = Buffer::getCommonFormatDeclaration(Font::vertexFormat); + Buffer *new_buffer = gfx->newBuffer(settings, decl, nullptr, newsize, 0); if (vertex_buffer != nullptr) vertex_buffer->copyTo(0, vertex_buffer->getSize(), new_buffer, 0); diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 698aa5352..e94048d6d 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -35,25 +35,8 @@ namespace graphics namespace opengl { -Buffer::Buffer(const Settings &settings, const void *data, size_t size) - : love::graphics::Buffer(settings, data, size) -{ - 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) + : love::graphics::Buffer(gfx, settings, format, size, arraylength) { if (typeFlags & TYPEFLAG_VERTEX) mapType = BUFFERTYPE_VERTEX; @@ -81,6 +64,12 @@ void Buffer::initialize(const void *data) } } +Buffer::~Buffer() +{ + unloadVolatile(); + delete[] memoryMap; +} + bool Buffer::loadVolatile() { return load(true); diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index df74fd982..e3c089ebc 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -42,7 +42,6 @@ class Buffer final : public love::graphics::Buffer, public Volatile { public: - 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(); @@ -60,8 +59,6 @@ public: private: - void initialize(const void *data); - bool load(bool restore); void unmapStatic(size_t offset, size_t size); diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 3fba07d52..988b75f79 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -145,11 +145,6 @@ love::graphics::Shader *Graphics::newShaderInternal(love::graphics::ShaderStage return new Shader(vertex, pixel); } -love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const void *data, size_t size) -{ - return new Buffer(settings, data, size); -} - love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) { return new Buffer(this, settings, format, data, size, arraylength); diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index e40ee702b..d5e2e6bc7 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -60,7 +60,6 @@ public: const char *getName() const override; love::graphics::Texture *newTexture(const Texture::Settings &settings, const Texture::Slices *data = nullptr) 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; From 2c90ccabb39a64b039c87e5ea836a9080d04054d Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 23 Feb 2020 16:49:38 -0400 Subject: [PATCH 13/26] Avoid some hardcoded strings --- src/modules/graphics/Buffer.cpp | 40 ++++++++++++++++----------------- src/modules/graphics/vertex.cpp | 7 ++++++ src/modules/graphics/vertex.h | 2 ++ 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 096217780..211e84500 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -131,53 +131,53 @@ std::vector Buffer::getCommonFormatDeclaration(CommonFo return {}; case CommonFormat::XYf: return { - {"VertexPosition", DATAFORMAT_FLOAT_VEC2} + { getConstant(ATTRIB_POS), DATAFORMAT_FLOAT_VEC2 } }; case CommonFormat::XYZf: return { - {"VertexPosition", DATAFORMAT_FLOAT_VEC3} + { getConstant(ATTRIB_POS), DATAFORMAT_FLOAT_VEC3 } }; case CommonFormat::RGBAub: return { - {"VertexColor", DATAFORMAT_UNORM8_VEC4} + { getConstant(ATTRIB_COLOR), DATAFORMAT_UNORM8_VEC4 } }; case CommonFormat::STf_RGBAub: return { - {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, - {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + { getConstant(ATTRIB_TEXCOORD), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_COLOR), DATAFORMAT_UNORM8_VEC4 }, }; case CommonFormat::STPf_RGBAub: return { - {"VertexTexCoord", DATAFORMAT_FLOAT_VEC3}, - {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + { getConstant(ATTRIB_TEXCOORD), DATAFORMAT_FLOAT_VEC3 }, + { getConstant(ATTRIB_COLOR), DATAFORMAT_UNORM8_VEC4 }, }; case CommonFormat::XYf_STf: return { - {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, - {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, + { getConstant(ATTRIB_POS), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_TEXCOORD), DATAFORMAT_FLOAT_VEC2 }, }; case CommonFormat::XYf_STPf: return { - {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, - {"VertexTexCoord", DATAFORMAT_FLOAT_VEC3}, + { getConstant(ATTRIB_POS), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_TEXCOORD), DATAFORMAT_FLOAT_VEC3 }, }; case CommonFormat::XYf_STf_RGBAub: return { - {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, - {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, - {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + { getConstant(ATTRIB_POS), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_TEXCOORD), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_COLOR), DATAFORMAT_UNORM8_VEC4 }, }; case CommonFormat::XYf_STus_RGBAub: return { - {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, - {"VertexTexCoord", DATAFORMAT_UNORM16_VEC2}, - {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + { getConstant(ATTRIB_POS), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_TEXCOORD), DATAFORMAT_UNORM16_VEC2 }, + { getConstant(ATTRIB_COLOR), DATAFORMAT_UNORM8_VEC4 }, }; case CommonFormat::XYf_STPf_RGBAub: return { - {"VertexPosition", DATAFORMAT_FLOAT_VEC2}, - {"VertexTexCoord", DATAFORMAT_FLOAT_VEC2}, - {"VertexColor", DATAFORMAT_UNORM8_VEC4}, + { getConstant(ATTRIB_POS), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_TEXCOORD), DATAFORMAT_FLOAT_VEC2 }, + { getConstant(ATTRIB_COLOR), DATAFORMAT_UNORM8_VEC4 }, }; } diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index c5e3e32dd..c64496b98 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -320,6 +320,13 @@ DEFINE_STRINGMAP_BEGIN(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) } DEFINE_STRINGMAP_END(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) +const char *getConstant(BuiltinVertexAttribute attrib) +{ + const char *name = nullptr; + getConstant(attrib, name); + return name; +} + DEFINE_STRINGMAP_BEGIN(IndexDataType, INDEX_MAX_ENUM, indexType) { { "uint16", INDEX_UINT16 }, diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index a24e92604..33072939e 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -393,5 +393,7 @@ DECLARE_STRINGMAP(DataBaseType); DECLARE_STRINGMAP(CullMode); DECLARE_STRINGMAP(Winding); +const char *getConstant(BuiltinVertexAttribute attrib); + } // graphics } // love From 4197a364fd43bc06e9f4e0f65d5ba511739ac783 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 23 Feb 2020 22:39:18 -0400 Subject: [PATCH 14/26] Internal restructuring of some Mesh code --- src/modules/graphics/Graphics.cpp | 19 ++- src/modules/graphics/Graphics.h | 3 +- src/modules/graphics/Mesh.cpp | 154 ++++++++++++++++--------- src/modules/graphics/Mesh.h | 22 ++-- src/modules/graphics/vertex.cpp | 8 -- src/modules/graphics/vertex.h | 9 -- src/modules/graphics/wrap_Graphics.cpp | 55 ++++++--- 7 files changed, 158 insertions(+), 112 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index db1135840..2cb470ed3 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -268,26 +268,21 @@ Buffer *Graphics::newBuffer(const Buffer::Settings &settings, DataFormat format, return newBuffer(settings, dataformat, data, size, arraylength); } -Mesh *Graphics::newMesh(const std::vector &vertices, PrimitiveType drawmode, BufferUsage usage) -{ - return newMesh(Mesh::getDefaultVertexFormat(), &vertices[0], vertices.size() * sizeof(Vertex), drawmode, usage); -} - -Mesh *Graphics::newMesh(int vertexcount, PrimitiveType drawmode, BufferUsage usage) -{ - return newMesh(Mesh::getDefaultVertexFormat(), vertexcount, drawmode, usage); -} - -love::graphics::Mesh *Graphics::newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) +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) +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); } +Mesh *Graphics::newMesh(const std::vector &attributes, PrimitiveType drawmode) +{ + return new Mesh(attributes, drawmode); +} + love::graphics::Text *Graphics::newText(graphics::Font *font, const std::vector &text) { return new Text(font, text); diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index d598ff198..83ee68e01 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -442,10 +442,9 @@ public: virtual Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) = 0; virtual Buffer *newBuffer(const Buffer::Settings &settings, DataFormat format, const void *data, size_t size, size_t arraylength); - 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 &attributes, PrimitiveType drawmode); Text *newText(Font *font, const std::vector &text = {}); diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 107c11e49..98fff062d 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -34,27 +34,13 @@ namespace love namespace graphics { -static const char *getBuiltinAttribName(BuiltinVertexAttribute attribid) -{ - const char *name = ""; - getConstant(attribid, name); - return name; -} - static_assert(offsetof(Vertex, x) == sizeof(float) * 0, "Incorrect position offset in Vertex struct"); 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() { - // Corresponds to the love::Vertex struct. - 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; + return Buffer::getCommonFormatDeclaration(CommonFormat::XYf_STf_RGBAub); } love::Type Mesh::type("Mesh", &Drawable::type); @@ -63,6 +49,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector & : vertexBuffer(nullptr) , vertexCount(0) , vertexStride(0) + , vertexScratchBuffer(nullptr) , indexBuffer(nullptr) , useIndexBuffer(false) , indexCount(0) @@ -89,6 +76,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector & : vertexBuffer(nullptr) , vertexCount((size_t) vertexcount) , vertexStride(0) + , vertexScratchBuffer(nullptr) , indexBuffer(nullptr) , useIndexBuffer(false) , indexCount(0) @@ -115,6 +103,37 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector & vertexScratchBuffer = new char[vertexStride]; } +Mesh::Mesh(const std::vector &attributes, PrimitiveType drawmode) + : vertexBuffer(nullptr) + , vertexCount(0) + , vertexStride(0) + , vertexScratchBuffer(nullptr) + , indexBuffer(nullptr) + , useIndexBuffer(false) + , indexCount(0) + , indexDataType(INDEX_UINT16) + , primitiveType(drawmode) + , rangeStart(-1) + , rangeCount(-1) +{ + if (attributes.size() == 0) + throw love::Exception("At least one buffer attribute must be specified in this constructor."); + + attachedAttributes = attributes; + + vertexCount = LOVE_UINT32_MAX; + + for (const auto &attrib : attachedAttributes) + { + if (getAttachedAttributeIndex(attrib.name) != -1) + throw love::Exception("Duplicate vertex attribute name: %s", attrib.name.c_str()); + + vertexCount = std::min(vertexCount, attrib.buffer->getArrayLength()); + } + + indexDataType = getIndexDataTypeFromMax(vertexCount); +} + Mesh::~Mesh() { delete vertexScratchBuffer; @@ -126,18 +145,32 @@ void Mesh::setupAttachedAttributes() { const std::string &name = vertexFormat[i].decl.name; - if (attachedAttributes.find(name) != attachedAttributes.end()) + if (getAttachedAttributeIndex(name) != -1) throw love::Exception("Duplicate vertex attribute name: %s", name.c_str()); - attachedAttributes[name] = {vertexBuffer, (int) i, STEP_PER_VERTEX, true}; + attachedAttributes.push_back({name, vertexBuffer, (int) i, STEP_PER_VERTEX, true}); } } +int Mesh::getAttachedAttributeIndex(const std::string &name) const +{ + for (int i = 0; i < (int) attachedAttributes.size(); i++) + { + if (attachedAttributes[i].name == name) + return i; + } + + return -1; +} + void Mesh::setVertex(size_t vertindex, const void *data, size_t datasize) { if (vertindex >= vertexCount) throw love::Exception("Invalid vertex index: %ld", vertindex + 1); + if (vertexBuffer.get() == nullptr) + throw love::Exception("setVertex can only be called on a Mesh which owns its own vertex buffer."); + size_t offset = vertindex * vertexStride; size_t size = std::min(datasize, vertexStride); @@ -152,6 +185,9 @@ size_t Mesh::getVertex(size_t vertindex, void *data, size_t datasize) if (vertindex >= vertexCount) throw love::Exception("Invalid vertex index: %ld", vertindex + 1); + if (vertexBuffer.get() == nullptr) + throw love::Exception("getVertex can only be called on a Mesh which owns its own vertex buffer."); + size_t offset = vertindex * vertexStride; size_t size = std::min(datasize, vertexStride); @@ -175,6 +211,9 @@ 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); + if (vertexBuffer.get() == nullptr) + throw love::Exception("setVertexAttribute can only be called on a Mesh which owns its own vertex buffer."); + const auto &member = vertexFormat[attribindex]; size_t offset = vertindex * vertexStride + member.offset; @@ -194,6 +233,9 @@ 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); + if (vertexBuffer.get() == nullptr) + throw love::Exception("getVertexAttribute can only be called on a Mesh which owns its own vertex buffer."); + const auto &member = vertexFormat[attribindex]; size_t offset = vertindex * vertexStride + member.offset; @@ -239,39 +281,37 @@ int Mesh::getAttributeIndex(const std::string &name) const void Mesh::setAttributeEnabled(const std::string &name, bool enable) { - auto it = attachedAttributes.find(name); - - if (it == attachedAttributes.end()) + int index = getAttachedAttributeIndex(name); + if (index == -1) throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str()); - it->second.enabled = enable; + attachedAttributes[index].enabled = enable; } bool Mesh::isAttributeEnabled(const std::string &name) const { - const auto it = attachedAttributes.find(name); - - if (it == attachedAttributes.end()) + int index = getAttachedAttributeIndex(name); + if (index == -1) throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str()); - return it->second.enabled; + return attachedAttributes[index].enabled; } void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step) { 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."); + throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute."); auto gfx = Module::getInstance(Module::M_GRAPHICS); if (step == STEP_PER_INSTANCE && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING]) throw love::Exception("Vertex attribute instancing is not supported on this system."); - AttachedAttribute oldattrib = {}; - AttachedAttribute newattrib = {}; + BufferAttribute oldattrib = {}; + BufferAttribute newattrib = {}; - auto it = attachedAttributes.find(name); - if (it != attachedAttributes.end()) - oldattrib = it->second; + int oldindex = getAttachedAttributeIndex(name); + if (oldindex != -1) + oldattrib = attachedAttributes[oldindex]; else if (attachedAttributes.size() + 1 > VertexAttributes::MAX) throw love::Exception("A maximum of %d attributes can be attached at once.", VertexAttributes::MAX); @@ -283,42 +323,46 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::s if (newattrib.index < 0) throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str()); - attachedAttributes[name] = newattrib; + if (oldindex != -1) + attachedAttributes[oldindex] = newattrib; + else + attachedAttributes.push_back(newattrib); } bool Mesh::detachAttribute(const std::string &name) { - auto it = attachedAttributes.find(name); + int index = getAttachedAttributeIndex(name); + if (index == -1) + return false; - if (it != attachedAttributes.end()) - { - attachedAttributes.erase(it); + attachedAttributes.erase(attachedAttributes.begin() + index); - if (getAttributeIndex(name) != -1) - attachAttribute(name, vertexBuffer, name); + if (getAttributeIndex(name) != -1) + attachAttribute(name, vertexBuffer, name); - return true; - } - - return false; + return true; } void *Mesh::mapVertexData() { - return vertexBuffer->map(); + return vertexBuffer.get() != nullptr ? vertexBuffer->map() : nullptr; } void Mesh::unmapVertexData(size_t modifiedoffset, size_t modifiedsize) { + if (!vertexBuffer.get()) + return; + vertexBuffer->setMappedRangeModified(modifiedoffset, modifiedsize); vertexBuffer->unmap(); } void Mesh::flush() { - vertexBuffer->unmap(); + if (vertexBuffer.get()) + vertexBuffer->unmap(); - if (indexBuffer != nullptr) + if (indexBuffer.get()) indexBuffer->unmap(); } @@ -352,7 +396,8 @@ void Mesh::setVertexMap(const std::vector &map) if (indexBuffer.get() == nullptr || size > indexBuffer->getSize() || indexBuffer->getDataMember(0).decl.format != dataformat) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, vertexBuffer->getUsage()); + auto usage = vertexBuffer.get() ? vertexBuffer->getUsage() : BUFFERUSAGE_DYNAMIC; + Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, usage); indexBuffer.set(gfx->newBuffer(settings, dataformat, nullptr, size, 0), Acquire::NORETAIN); } @@ -386,7 +431,8 @@ void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasiz if (indexBuffer.get() == nullptr || datasize > indexBuffer->getSize() || indexBuffer->getDataMember(0).decl.format != dataformat) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, vertexBuffer->getUsage()); + auto usage = vertexBuffer.get() ? vertexBuffer->getUsage() : BUFFERUSAGE_DYNAMIC; + Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_READ, usage); indexBuffer.set(gfx->newBuffer(settings, dataformat, nullptr, datasize, 0), Acquire::NORETAIN); } @@ -529,32 +575,32 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) for (const auto &attrib : attachedAttributes) { - if (!attrib.second.enabled) + if (!attrib.enabled) continue; - Buffer *buffer = attrib.second.buffer.get(); + Buffer *buffer = attrib.buffer.get(); 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. BuiltinVertexAttribute builtinattrib; - if (getConstant(attrib.first.c_str(), builtinattrib)) + if (getConstant(attrib.name.c_str(), builtinattrib)) attributeindex = (int) builtinattrib; else if (Shader::current) - attributeindex = Shader::current->getVertexAttributeIndex(attrib.first); + attributeindex = Shader::current->getVertexAttributeIndex(attrib.name); if (attributeindex >= 0) { // Make sure the buffer isn't mapped (sends data to GPU if needed.) buffer->unmap(); - const auto &member = buffer->getDataMember(attrib.second.index); + const auto &member = buffer->getDataMember(attrib.index); - uint16 offset = (uint16) buffer->getMemberOffset(attrib.second.index); + uint16 offset = (uint16) buffer->getMemberOffset(attrib.index); uint16 stride = (uint16) buffer->getArrayStride(); attributes.set(attributeindex, member.decl.format, offset, activebuffers); - attributes.setBufferLayout(activebuffers, stride, attrib.second.step); + attributes.setBufferLayout(activebuffers, stride, attrib.step); // TODO: Ideally we want to reuse buffers with the same stride+step. buffers.set(activebuffers, buffer, 0); diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 7e099f3dc..0c81642fc 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -50,10 +50,20 @@ class Mesh : public Drawable { public: + struct BufferAttribute + { + std::string name; + StrongRef buffer; + int index; + AttributeStep step; + bool enabled; + }; + static love::Type type; 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(const std::vector &attributes, PrimitiveType drawmode); virtual ~Mesh(); @@ -105,6 +115,7 @@ public: **/ void attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX); bool detachAttribute(const std::string &name); + const std::vector &getAttachedAttributes(); void *mapVertexData(); void unmapVertexData(size_t modifiedoffset = 0, size_t modifiedsize = -1); @@ -172,19 +183,12 @@ private: friend class SpriteBatch; - struct AttachedAttribute - { - StrongRef buffer; - int index; - AttributeStep step; - bool enabled; - }; - void setupAttachedAttributes(); + int getAttachedAttributeIndex(const std::string &name) const; std::vector vertexFormat; - std::unordered_map attachedAttributes; + std::vector attachedAttributes; // Vertex buffer, for the vertex data. StrongRef vertexBuffer; diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index c64496b98..0ecfb7d26 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -358,14 +358,6 @@ DEFINE_STRINGMAP_BEGIN(AttributeStep, STEP_MAX_ENUM, attributeStep) } DEFINE_STRINGMAP_END(AttributeStep, STEP_MAX_ENUM, attributeStep) -DEFINE_STRINGMAP_BEGIN(DataTypeDeprecated, DATADEPRECATED_MAX_ENUM, dataType) -{ - { "unorm8", DATADEPRECATED_UNORM8 }, - { "unorm16", DATADEPRECATED_UNORM16 }, - { "float", DATADEPRECATED_FLOAT }, -} -DEFINE_STRINGMAP_END(DataTypeDeprecated, DATADEPRECATED_MAX_ENUM, dataType) - DEFINE_STRINGMAP_BEGIN(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) { { "float", DATAFORMAT_FLOAT }, diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 33072939e..0c7477579 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -102,14 +102,6 @@ enum BufferUsage BUFFERUSAGE_MAX_ENUM }; -enum DataTypeDeprecated -{ - DATADEPRECATED_UNORM8, - DATADEPRECATED_UNORM16, - DATADEPRECATED_FLOAT, - DATADEPRECATED_MAX_ENUM -}; - // Value types used when interfacing with the GPU (vertex and shader data). // The order of this enum affects the dataFormatInfo array. enum DataFormat @@ -387,7 +379,6 @@ DECLARE_STRINGMAP(IndexDataType); DECLARE_STRINGMAP(BufferUsage); DECLARE_STRINGMAP(PrimitiveType); DECLARE_STRINGMAP(AttributeStep); -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 dc24f7eaf..418a89e23 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1557,6 +1557,8 @@ static Mesh *newStandardMesh(lua_State *L) PrimitiveType drawmode = luax_optmeshdrawmode(L, 2, PRIMITIVE_TRIANGLE_FAN); BufferUsage usage = luax_optmeshusage(L, 3, BUFFERUSAGE_DYNAMIC); + auto format = Mesh::getDefaultVertexFormat(); + // First argument is a table of standard vertices, or the number of // standard vertices. if (lua_istable(L, 1)) @@ -1595,12 +1597,12 @@ static Mesh *newStandardMesh(lua_State *L) vertices.push_back(v); } - luax_catchexcept(L, [&](){ t = instance()->newMesh(vertices, drawmode, usage); }); + luax_catchexcept(L, [&](){ t = instance()->newMesh(format, vertices.data(), vertices.size() * sizeof(Vertex), drawmode, usage); }); } else { int count = (int) luaL_checkinteger(L, 1); - luax_catchexcept(L, [&](){ t = instance()->newMesh(count, drawmode, usage); }); + luax_catchexcept(L, [&](){ t = instance()->newMesh(format, count, drawmode, usage); }); } return t; @@ -1641,24 +1643,41 @@ static Mesh *newCustomMesh(lua_State *L) if (!getConstant(tname, format)) { - 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. + // Check deprecated format names. + if (strcmp(tname, "byte") == 0 || strcmp(tname, "unorm8") == 0) + { + if (components == 4) + format = DATAFORMAT_UNORM8_VEC4; + else + luaL_error(L, "Invalid component count (%d) for vertex data type %s", components, tname); + } + else if (strcmp(tname, "unorm16") == 0) + { + if (components == 2) + format = DATAFORMAT_UNORM16_VEC2; + else if (components == 4) + format = DATAFORMAT_UNORM16_VEC4; + else + luaL_error(L, "Invalid component count (%d) for vertex data type %s", components, tname); + + } + else if (strcmp(tname, "float") == 0) + { + if (components == 1) + format = DATAFORMAT_FLOAT; + else if (components == 2) + format = DATAFORMAT_FLOAT_VEC2; + else if (components == 3) + format = DATAFORMAT_FLOAT_VEC3; + else if (components == 4) + format = DATAFORMAT_FLOAT_VEC4; + else + luaL_error(L, "Invalid component count (%d) for vertex data type %s", components, tname); + } + else + luax_enumerror(L, "vertex data format", getConstants(format), tname); } lua_pop(L, 4); From d77dabaa6bc50705e7fb66bc92111e2d8e00d4a3 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 28 Feb 2020 23:01:35 -0400 Subject: [PATCH 15/26] Add Mesh:getAttachedAttributes. --- src/modules/graphics/Mesh.cpp | 26 ++++++------------ src/modules/graphics/Mesh.h | 3 +- src/modules/graphics/wrap_Graphics.cpp | 2 +- src/modules/graphics/wrap_Mesh.cpp | 38 ++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 98fff062d..8897d6ac1 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -121,10 +121,13 @@ Mesh::Mesh(const std::vector &attributes, PrimitiveType d attachedAttributes = attributes; - vertexCount = LOVE_UINT32_MAX; + vertexCount = attachedAttributes.size() > 0 ? LOVE_UINT32_MAX : 0; for (const auto &attrib : attachedAttributes) { + if ((attrib.buffer->getTypeFlags() & Buffer::TYPEFLAG_VERTEX) == 0) + throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute."); + if (getAttachedAttributeIndex(attrib.name) != -1) throw love::Exception("Duplicate vertex attribute name: %s", attrib.name.c_str()); @@ -268,17 +271,6 @@ const std::vector &Mesh::getVertexFormat() const return vertexFormat; } -int Mesh::getAttributeIndex(const std::string &name) const -{ - for (int i = 0; i < (int) vertexFormat.size(); i++) - { - if (vertexFormat[i].decl.name == name) - return i; - } - - return -1; -} - void Mesh::setAttributeEnabled(const std::string &name, bool enable) { int index = getAttachedAttributeIndex(name); @@ -317,10 +309,10 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::s newattrib.buffer = buffer; newattrib.enabled = oldattrib.buffer.get() ? oldattrib.enabled : true; - newattrib.index = buffer->getDataMemberIndex(attachname); + newattrib.indexInBuffer = buffer->getDataMemberIndex(attachname); newattrib.step = step; - if (newattrib.index < 0) + if (newattrib.indexInBuffer < 0) throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str()); if (oldindex != -1) @@ -337,7 +329,7 @@ bool Mesh::detachAttribute(const std::string &name) attachedAttributes.erase(attachedAttributes.begin() + index); - if (getAttributeIndex(name) != -1) + if (vertexBuffer.get() && vertexBuffer->getDataMemberIndex(name) != -1) attachAttribute(name, vertexBuffer, name); return true; @@ -594,9 +586,9 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) // Make sure the buffer isn't mapped (sends data to GPU if needed.) buffer->unmap(); - const auto &member = buffer->getDataMember(attrib.index); + const auto &member = buffer->getDataMember(attrib.indexInBuffer); - uint16 offset = (uint16) buffer->getMemberOffset(attrib.index); + uint16 offset = (uint16) member.offset; uint16 stride = (uint16) buffer->getArrayStride(); attributes.set(attributeindex, member.decl.format, offset, activebuffers); diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 0c81642fc..83165adf4 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -54,7 +54,7 @@ public: { std::string name; StrongRef buffer; - int index; + int indexInBuffer; AttributeStep step; bool enabled; }; @@ -101,7 +101,6 @@ public: * Gets the format of each vertex attribute stored in the Mesh. **/ const std::vector &getVertexFormat() const; - int getAttributeIndex(const std::string &name) const; /** * Sets whether a specific vertex attribute is used when drawing the Mesh. diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 418a89e23..fa7895535 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1557,7 +1557,7 @@ static Mesh *newStandardMesh(lua_State *L) PrimitiveType drawmode = luax_optmeshdrawmode(L, 2, PRIMITIVE_TRIANGLE_FAN); BufferUsage usage = luax_optmeshusage(L, 3, BUFFERUSAGE_DYNAMIC); - auto format = Mesh::getDefaultVertexFormat(); + std::vector format = Mesh::getDefaultVertexFormat(); // First argument is a table of standard vertices, or the number of // standard vertices. diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index f3b132594..15e32e71d 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -298,6 +298,8 @@ int w_Mesh_attachAttribute(lua_State *L) { Mesh *mesh = luax_checkmesh(L, 3); buffer = mesh->getVertexBuffer(); + if (buffer == nullptr) + return luaL_error(L, "Mesh does not have its own vertex buffer."); } AttributeStep step = STEP_PER_VERTEX; @@ -321,6 +323,41 @@ int w_Mesh_detachAttribute(lua_State *L) return 1; } +int w_Mesh_getAttachedAttributes(lua_State *L) +{ + Mesh *t = luax_checkmesh(L, 1); + const auto &attributes = t->getAttachedAttributes(); + + lua_createtable(L, (int) attributes.size(), 0); + + for (int i = 0; i < (int) attributes.size(); i++) + { + const auto &attrib = attributes[i]; + + lua_createtable(L, 4, 0); + + luax_pushstring(L, attrib.name); + lua_rawseti(L, -1, 1); + + luax_pushtype(L, attrib.buffer.get()); + lua_rawseti(L, -1, 2); + + const char *stepstr = nullptr; + if (!getConstant(attrib.step, stepstr)) + return luaL_error(L, "Invalid vertex attribute step."); + lua_pushstring(L, stepstr); + lua_rawseti(L, -1, 3); + + const Buffer::DataMember &member = attrib.buffer->getDataMember(attrib.indexInBuffer); + luax_pushstring(L, member.decl.name); + lua_rawseti(L, -1, 4); + + lua_rawseti(L, -1, i + 1); + } + + return 1; +} + int w_Mesh_flush(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); @@ -507,6 +544,7 @@ static const luaL_Reg w_Mesh_functions[] = { "isAttributeEnabled", w_Mesh_isAttributeEnabled }, { "attachAttribute", w_Mesh_attachAttribute }, { "detachAttribute", w_Mesh_detachAttribute }, + { "getAttachedAttributes", w_Mesh_getAttachedAttributes }, { "flush", w_Mesh_flush }, { "setVertexMap", w_Mesh_setVertexMap }, { "getVertexMap", w_Mesh_getVertexMap }, From bbdadcba8a998a4c2517edc7e95024a6784420f8 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 28 Feb 2020 23:12:22 -0400 Subject: [PATCH 16/26] Fix build --- src/modules/graphics/Mesh.cpp | 5 +++++ src/modules/graphics/Mesh.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index b39b5388f..816493361 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -335,6 +335,11 @@ bool Mesh::detachAttribute(const std::string &name) return true; } +const std::vector &Mesh::getAttachedAttributes() const +{ + return attachedAttributes; +} + void *Mesh::mapVertexData() { return vertexBuffer.get() != nullptr ? vertexBuffer->map() : nullptr; diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 83165adf4..187f0bc0c 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -114,7 +114,7 @@ public: **/ void attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX); bool detachAttribute(const std::string &name); - const std::vector &getAttachedAttributes(); + const std::vector &getAttachedAttributes() const; void *mapVertexData(); void unmapVertexData(size_t modifiedoffset = 0, size_t modifiedsize = -1); From e60736f5a60c2382fc648d7a61fb189bf91b76ec Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 20 Jul 2020 22:10:08 -0300 Subject: [PATCH 17/26] Add Mesh:set/getIndexBuffer. --- src/common/StringMap.h | 6 ++-- src/modules/graphics/Mesh.cpp | 25 +++++++++++++++- src/modules/graphics/Mesh.h | 8 +++++- src/modules/graphics/vertex.cpp | 46 ++++++++++++++++++------------ src/modules/graphics/vertex.h | 20 +++++++------ src/modules/graphics/wrap_Mesh.cpp | 19 ++++++++++++ 6 files changed, 92 insertions(+), 32 deletions(-) diff --git a/src/common/StringMap.h b/src/common/StringMap.h index 97dbe3c8b..4e6dc25de 100644 --- a/src/common/StringMap.h +++ b/src/common/StringMap.h @@ -182,15 +182,15 @@ private: }; // StringMap -#define DECLARE_STRINGMAP(type) \ +#define STRINGMAP_DECLARE(type) \ bool getConstant(const char *in, type &out); \ bool getConstant(type in, const char *&out); \ std::vector getConstants(type); \ -#define DEFINE_STRINGMAP_BEGIN(type, count, name) \ +#define STRINGMAP_BEGIN(type, count, name) \ static StringMap::Entry name##Entries[] = -#define DEFINE_STRINGMAP_END(type, count, name) \ +#define STRINGMAP_END(type, count, name) \ ; \ static StringMap name##s(name##Entries, sizeof(name##Entries)); \ bool getConstant(const char *in, type &out) { return name##s.find(in, out); } \ diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 816493361..77261e7bb 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -472,6 +472,9 @@ bool Mesh::getVertexMap(std::vector &map) const if (!indexBuffer || indexCount == 0) return true; + if ((indexBuffer->getMapFlags() & Buffer::MAP_READ) == 0) + return false; + // We unmap the buffer in Mesh::draw, Mesh::setVertexMap, and Mesh::flush. void *buffer = indexBuffer->map(); @@ -490,7 +493,27 @@ bool Mesh::getVertexMap(std::vector &map) const return true; } -size_t Mesh::getVertexMapCount() const +void Mesh::setIndexBuffer(Buffer *buffer) +{ + // Buffer constructor does the rest of the validation for index buffers + // (data member formats, etc.) + if (buffer != nullptr && (buffer->getTypeFlags() & Buffer::TYPEFLAG_INDEX) == 0) + throw love::Exception("setIndexBuffer requires a Buffer created as an index buffer."); + + indexBuffer.set(buffer); + useIndexBuffer = buffer != nullptr; + indexCount = buffer != nullptr ? buffer->getArrayLength() : 0; + + if (buffer != nullptr) + indexDataType = getIndexDataType(buffer->getDataMember(0).decl.format); +} + +Buffer *Mesh::getIndexBuffer() const +{ + return indexBuffer; +} + +size_t Mesh::getIndexCount() const { return indexCount; } diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 187f0bc0c..72994f051 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -95,6 +95,9 @@ public: **/ size_t getVertexStride() const; + /** + * Gets the Buffer that holds the Mesh's vertices. + **/ Buffer *getVertexBuffer() const; /** @@ -140,10 +143,13 @@ public: **/ bool getVertexMap(std::vector &map) const; + void setIndexBuffer(Buffer *buffer); + Buffer *getIndexBuffer() const; + /** * Gets the total number of elements in the vertex map array. **/ - size_t getVertexMapCount() const; + size_t getIndexCount() const; /** * Sets the texture used when drawing the Mesh. diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 0ecfb7d26..ea135e0f4 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -183,6 +183,16 @@ DataFormat getIndexDataFormat(IndexDataType type) return type == INDEX_UINT32 ? DATAFORMAT_UINT32 : DATAFORMAT_UINT16; } +IndexDataType getIndexDataType(DataFormat format) +{ + switch (format) + { + case DATAFORMAT_UINT16: return INDEX_UINT16; + case DATAFORMAT_UINT32: return INDEX_UINT32; + default: return INDEX_MAX_ENUM; + } +} + int getIndexCount(TriangleIndexMode mode, int vertexCount) { switch (mode) @@ -312,13 +322,13 @@ void VertexAttributes::setCommonFormat(CommonFormat format, uint8 bufferindex) } } -DEFINE_STRINGMAP_BEGIN(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) +STRINGMAP_BEGIN(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) { { "VertexPosition", ATTRIB_POS }, { "VertexTexCoord", ATTRIB_TEXCOORD }, { "VertexColor", ATTRIB_COLOR }, } -DEFINE_STRINGMAP_END(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) +STRINGMAP_END(BuiltinVertexAttribute, ATTRIB_MAX_ENUM, attribName) const char *getConstant(BuiltinVertexAttribute attrib) { @@ -327,38 +337,38 @@ const char *getConstant(BuiltinVertexAttribute attrib) return name; } -DEFINE_STRINGMAP_BEGIN(IndexDataType, INDEX_MAX_ENUM, indexType) +STRINGMAP_BEGIN(IndexDataType, INDEX_MAX_ENUM, indexType) { { "uint16", INDEX_UINT16 }, { "uint32", INDEX_UINT32 }, } -DEFINE_STRINGMAP_END(IndexDataType, INDEX_MAX_ENUM, indexType) +STRINGMAP_END(IndexDataType, INDEX_MAX_ENUM, indexType) -DEFINE_STRINGMAP_BEGIN(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) +STRINGMAP_BEGIN(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) { { "stream", BUFFERUSAGE_STREAM }, { "dynamic", BUFFERUSAGE_DYNAMIC }, { "static", BUFFERUSAGE_STATIC }, } -DEFINE_STRINGMAP_END(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) +STRINGMAP_END(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) -DEFINE_STRINGMAP_BEGIN(PrimitiveType, PRIMITIVE_MAX_ENUM, primitiveType) +STRINGMAP_BEGIN(PrimitiveType, PRIMITIVE_MAX_ENUM, primitiveType) { { "fan", PRIMITIVE_TRIANGLE_FAN }, { "strip", PRIMITIVE_TRIANGLE_STRIP }, { "triangles", PRIMITIVE_TRIANGLES }, { "points", PRIMITIVE_POINTS }, } -DEFINE_STRINGMAP_END(PrimitiveType, PRIMITIVE_MAX_ENUM, primitiveType) +STRINGMAP_END(PrimitiveType, PRIMITIVE_MAX_ENUM, primitiveType) -DEFINE_STRINGMAP_BEGIN(AttributeStep, STEP_MAX_ENUM, attributeStep) +STRINGMAP_BEGIN(AttributeStep, STEP_MAX_ENUM, attributeStep) { { "pervertex", STEP_PER_VERTEX }, { "perinstance", STEP_PER_INSTANCE }, } -DEFINE_STRINGMAP_END(AttributeStep, STEP_MAX_ENUM, attributeStep) +STRINGMAP_END(AttributeStep, STEP_MAX_ENUM, attributeStep) -DEFINE_STRINGMAP_BEGIN(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) +STRINGMAP_BEGIN(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) { { "float", DATAFORMAT_FLOAT }, { "floatvec2", DATAFORMAT_FLOAT_VEC2 }, @@ -410,9 +420,9 @@ DEFINE_STRINGMAP_BEGIN(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) { "boolvec3", DATAFORMAT_BOOL_VEC3 }, { "boolvec4", DATAFORMAT_BOOL_VEC4 }, } -DEFINE_STRINGMAP_END(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) +STRINGMAP_END(DataFormat, DATAFORMAT_MAX_ENUM, dataFormat) -DEFINE_STRINGMAP_BEGIN(DataBaseType, DATA_BASETYPE_MAX_ENUM, dataBaseType) +STRINGMAP_BEGIN(DataBaseType, DATA_BASETYPE_MAX_ENUM, dataBaseType) { { "float", DATA_BASETYPE_FLOAT }, { "int", DATA_BASETYPE_INT }, @@ -421,22 +431,22 @@ DEFINE_STRINGMAP_BEGIN(DataBaseType, DATA_BASETYPE_MAX_ENUM, dataBaseType) { "unorm", DATA_BASETYPE_UNORM }, { "bool", DATA_BASETYPE_BOOL }, } -DEFINE_STRINGMAP_END(DataBaseType, DATA_BASETYPE_MAX_ENUM, dataBaseType) +STRINGMAP_END(DataBaseType, DATA_BASETYPE_MAX_ENUM, dataBaseType) -DEFINE_STRINGMAP_BEGIN(CullMode, CULL_MAX_ENUM, cullMode) +STRINGMAP_BEGIN(CullMode, CULL_MAX_ENUM, cullMode) { { "none", CULL_NONE }, { "back", CULL_BACK }, { "front", CULL_FRONT }, } -DEFINE_STRINGMAP_END(CullMode, CULL_MAX_ENUM, cullMode) +STRINGMAP_END(CullMode, CULL_MAX_ENUM, cullMode) -DEFINE_STRINGMAP_BEGIN(Winding, WINDING_MAX_ENUM, winding) +STRINGMAP_BEGIN(Winding, WINDING_MAX_ENUM, winding) { { "cw", WINDING_CW }, { "ccw", WINDING_CCW }, } -DEFINE_STRINGMAP_END(Winding, WINDING_MAX_ENUM, winding) +STRINGMAP_END(Winding, WINDING_MAX_ENUM, winding) } // graphics } // love diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 0c7477579..003d4eb9f 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -289,6 +289,7 @@ struct VertexAttributeInfo struct VertexBufferLayout { + // Attribute step rate is stored outside this struct as a bitmask. uint16 stride; }; @@ -368,21 +369,22 @@ const DataFormatInfo &getDataFormatInfo(DataFormat format); size_t getIndexDataSize(IndexDataType type); IndexDataType getIndexDataTypeFromMax(size_t maxvalue); DataFormat getIndexDataFormat(IndexDataType type); +IndexDataType getIndexDataType(DataFormat format); int getIndexCount(TriangleIndexMode mode, int vertexCount); void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount, uint16 *indices); void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices); -DECLARE_STRINGMAP(BuiltinVertexAttribute); -DECLARE_STRINGMAP(IndexDataType); -DECLARE_STRINGMAP(BufferUsage); -DECLARE_STRINGMAP(PrimitiveType); -DECLARE_STRINGMAP(AttributeStep); -DECLARE_STRINGMAP(DataFormat); -DECLARE_STRINGMAP(DataBaseType); -DECLARE_STRINGMAP(CullMode); -DECLARE_STRINGMAP(Winding); +STRINGMAP_DECLARE(BuiltinVertexAttribute); +STRINGMAP_DECLARE(IndexDataType); +STRINGMAP_DECLARE(BufferUsage); +STRINGMAP_DECLARE(PrimitiveType); +STRINGMAP_DECLARE(AttributeStep); +STRINGMAP_DECLARE(DataFormat); +STRINGMAP_DECLARE(DataBaseType); +STRINGMAP_DECLARE(CullMode); +STRINGMAP_DECLARE(Winding); const char *getConstant(BuiltinVertexAttribute attrib); diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index 15e32e71d..5920ae1cb 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -448,6 +448,23 @@ int w_Mesh_getVertexMap(lua_State *L) return 1; } +int w_Mesh_setIndexBuffer(lua_State *L) +{ + Mesh *t = luax_checkmesh(L, 1); + Buffer *b = nullptr; + if (!lua_isnoneornil(L, 2)) + b = luax_checkbuffer(L, 2); + luax_catchexcept(L, [&]() { t->setIndexBuffer(b); }); + return 0; +} + +int w_Mesh_getIndexBuffer(lua_State *L) +{ + Mesh *t = luax_checkmesh(L, 1); + luax_pushtype(L, t->getIndexBuffer()); + return 1; +} + int w_Mesh_setTexture(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); @@ -548,6 +565,8 @@ static const luaL_Reg w_Mesh_functions[] = { "flush", w_Mesh_flush }, { "setVertexMap", w_Mesh_setVertexMap }, { "getVertexMap", w_Mesh_getVertexMap }, + { "setIndexBuffer", w_Mesh_setIndexBuffer }, + { "getIndexBuffer", w_Mesh_getIndexBuffer }, { "setTexture", w_Mesh_setTexture }, { "getTexture", w_Mesh_getTexture }, { "setDrawMode", w_Mesh_setDrawMode }, From 834cddc34ce91b048b1cf3831cceacc371b1c6cb Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 20 Jul 2020 22:13:30 -0300 Subject: [PATCH 18/26] Add Mesh:getVertexBuffer. --- src/modules/graphics/wrap_Mesh.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index 5920ae1cb..d499106c1 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -358,6 +358,13 @@ int w_Mesh_getAttachedAttributes(lua_State *L) return 1; } +int w_Mesh_getVertexBuffer(lua_State *L) +{ + Mesh *t = luax_checkmesh(L, 1); + luax_pushtype(L, t->getVertexBuffer()); + return 1; +} + int w_Mesh_flush(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); @@ -562,6 +569,7 @@ static const luaL_Reg w_Mesh_functions[] = { "attachAttribute", w_Mesh_attachAttribute }, { "detachAttribute", w_Mesh_detachAttribute }, { "getAttachedAttributes", w_Mesh_getAttachedAttributes }, + { "getVertexBuffer", w_Mesh_getVertexBuffer }, { "flush", w_Mesh_flush }, { "setVertexMap", w_Mesh_setVertexMap }, { "getVertexMap", w_Mesh_getVertexMap }, From 3b67db4672bf7b879275faab0841a076d916337f Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 21 Jul 2020 18:57:50 -0300 Subject: [PATCH 19/26] Add love.graphics.newIndexBuffer --- src/modules/graphics/Buffer.cpp | 2 +- src/modules/graphics/Buffer.h | 14 +++- src/modules/graphics/wrap_Graphics.cpp | 91 ++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 211e84500..b839db8f9 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -51,7 +51,7 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vectornewBuffer(settings, format, nullptr, 0, arraylength); }); + + if (lua_istable(L, 1)) + { + Buffer::Mapper mapper(*b); + uint16 *u16data = (uint16 *) mapper.data; + uint32 *u32data = (uint32 *) mapper.data; + + for (int i = 0; i < arraylength; i++) + { + lua_rawgeti(L, 1, i + 1); + lua_Integer v = luaL_checkinteger(L, -1); + lua_pop(L, 1); + if (format == DATAFORMAT_UINT16) + u16data[i] = (uint16) v; + else + u32data[i] = (uint32) v; + } + } + + luax_pushtype(L, b); + b->release(); + return 1; +} + static PrimitiveType luax_optmeshdrawmode(lua_State *L, int idx, PrimitiveType def) { const char *modestr = lua_isnoneornil(L, idx) ? nullptr : luaL_checkstring(L, idx); @@ -1512,7 +1592,7 @@ static Mesh *newStandardMesh(lua_State *L) Mesh *t = nullptr; PrimitiveType drawmode = luax_optmeshdrawmode(L, 2, PRIMITIVE_TRIANGLE_FAN); - BufferUsage usage = luax_optmeshusage(L, 3, BUFFERUSAGE_DYNAMIC); + BufferUsage usage = luax_optbufferusage(L, 3, BUFFERUSAGE_DYNAMIC); std::vector format = Mesh::getDefaultVertexFormat(); @@ -1574,7 +1654,7 @@ static Mesh *newCustomMesh(lua_State *L) std::vector vertexformat; PrimitiveType drawmode = luax_optmeshdrawmode(L, 3, PRIMITIVE_TRIANGLE_FAN); - BufferUsage usage = luax_optmeshusage(L, 4, BUFFERUSAGE_DYNAMIC); + BufferUsage usage = luax_optbufferusage(L, 4, BUFFERUSAGE_DYNAMIC); lua_rawgeti(L, 1, 1); if (!lua_istable(L, -1)) @@ -1598,7 +1678,7 @@ static Mesh *newCustomMesh(lua_State *L) DataFormat format = DATAFORMAT_FLOAT; const char *tname = luaL_checkstring(L, -2); - if (!getConstant(tname, format)) + if (!lua_isnoneornil(L, -1)) { int components = (int) luaL_checkinteger(L, -1); @@ -1633,7 +1713,7 @@ static Mesh *newCustomMesh(lua_State *L) else luaL_error(L, "Invalid component count (%d) for vertex data type %s", components, tname); } - else + else if (!getConstant(tname, format)) luax_enumerror(L, "vertex data format", getConstants(format), tname); } @@ -3096,6 +3176,7 @@ static const luaL_Reg functions[] = { "newSpriteBatch", w_newSpriteBatch }, { "newParticleSystem", w_newParticleSystem }, { "newShader", w_newShader }, + { "newIndexBuffer", w_newIndexBuffer }, { "newMesh", w_newMesh }, { "newText", w_newText }, { "_newVideo", w_newVideo }, From 77834d8e6c87da1902f29cad11bd398b2dc239e8 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 21 Jul 2020 19:09:13 -0300 Subject: [PATCH 20/26] Add a Data object variant of love.graphics.newIndexBuffer --- src/modules/graphics/wrap_Graphics.cpp | 40 +++++++++++++++++++------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index eaf96f810..ff87b05f7 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1519,32 +1519,45 @@ int w_newIndexBuffer(lua_State *L) Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY, BUFFERUSAGE_DYNAMIC); luax_optbuffersettings(L, 3, settings); - int arraylength = 0; + size_t arraylength = 0; + size_t bytesize = 0; DataFormat format = DATAFORMAT_UINT16; + Data *data = nullptr; + + if (luax_istype(L, 1, Data::type)) + { + data = luax_checktype(L, 1); + bytesize = data->getSize(); + } if (lua_istable(L, 1)) { - arraylength = (int) luax_objlen(L, 1); + arraylength = (size_t) luax_objlen(L, 1); // Scan array for invalid types and the max value. lua_Integer maxvalue = 0; - for (int i = 0; i < arraylength; i++) + for (size_t i = 0; i < arraylength; i++) { lua_rawgeti(L, 1, i + 1); - lua_Integer v = luaL_checkinteger(L, -1); + lua_Integer v = luaL_checkinteger(L, -1) - 1; lua_pop(L, 1); if (v < 0) - return luaL_argerror(L, 1, "expected non-negative integer values in array"); + return luaL_argerror(L, 1, "expected positive integer values in array"); else maxvalue = std::max(maxvalue, v); } format = getIndexDataFormat(getIndexDataTypeFromMax(maxvalue)); } - else - arraylength = (int) luaL_checkinteger(L, 1); + else if (data == nullptr) + { + lua_Integer len = luaL_checkinteger(L, 1); + if (len <= 0) + return luaL_argerror(L, 1, "number of elements must be greater than 0"); + arraylength = (size_t) len; + } - if (!lua_isnoneornil(L, 2)) + if (data != nullptr || !lua_isnoneornil(L, 2)) { const char *formatstr = luaL_checkstring(L, 2); if (!getConstant(formatstr, format)) @@ -1552,7 +1565,7 @@ int w_newIndexBuffer(lua_State *L) } Buffer *b = nullptr; - luax_catchexcept(L, [&] { b = instance()->newBuffer(settings, format, nullptr, 0, arraylength); }); + luax_catchexcept(L, [&] { b = instance()->newBuffer(settings, format, nullptr, bytesize, arraylength); }); if (lua_istable(L, 1)) { @@ -1560,10 +1573,10 @@ int w_newIndexBuffer(lua_State *L) uint16 *u16data = (uint16 *) mapper.data; uint32 *u32data = (uint32 *) mapper.data; - for (int i = 0; i < arraylength; i++) + for (size_t i = 0; i < arraylength; i++) { lua_rawgeti(L, 1, i + 1); - lua_Integer v = luaL_checkinteger(L, -1); + lua_Integer v = luaL_checkinteger(L, -1) - 1; lua_pop(L, 1); if (format == DATAFORMAT_UINT16) u16data[i] = (uint16) v; @@ -1571,6 +1584,11 @@ int w_newIndexBuffer(lua_State *L) u32data[i] = (uint32) v; } } + else if (data != nullptr) + { + Buffer::Mapper mapper(*b); + memcpy(mapper.data, data->getData(), std::min(data->getSize(), b->getSize())); + } luax_pushtype(L, b); b->release(); From c2be89f13018136b4fdf915cdc1a4439e4f775c4 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 21 Jul 2020 20:50:49 -0300 Subject: [PATCH 21/26] Fix crashes when creating a Buffer. --- src/modules/graphics/Buffer.cpp | 2 ++ src/modules/graphics/opengl/Buffer.cpp | 3 +++ src/modules/graphics/wrap_Graphics.cpp | 9 +++------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index b839db8f9..257571d22 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -91,6 +91,8 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) : love::graphics::Buffer(gfx, settings, format, size, arraylength) { + size = getSize(); + arraylength = getArrayLength(); + if (typeFlags & TYPEFLAG_VERTEX) mapType = BUFFERTYPE_VERTEX; else if (typeFlags & TYPEFLAG_INDEX) diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index ff87b05f7..5c2bc44c3 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1523,10 +1523,12 @@ int w_newIndexBuffer(lua_State *L) size_t bytesize = 0; DataFormat format = DATAFORMAT_UINT16; Data *data = nullptr; + const void *initialdata = nullptr; if (luax_istype(L, 1, Data::type)) { data = luax_checktype(L, 1); + initialdata = data->getData(); bytesize = data->getSize(); } @@ -1565,7 +1567,7 @@ int w_newIndexBuffer(lua_State *L) } Buffer *b = nullptr; - luax_catchexcept(L, [&] { b = instance()->newBuffer(settings, format, nullptr, bytesize, arraylength); }); + luax_catchexcept(L, [&] { b = instance()->newBuffer(settings, format, initialdata, bytesize, arraylength); }); if (lua_istable(L, 1)) { @@ -1584,11 +1586,6 @@ int w_newIndexBuffer(lua_State *L) u32data[i] = (uint32) v; } } - else if (data != nullptr) - { - Buffer::Mapper mapper(*b); - memcpy(mapper.data, data->getData(), std::min(data->getSize(), b->getSize())); - } luax_pushtype(L, b); b->release(); From 7ad5e5a21ab5c8d0713ad03d97e1bbf1d1e72ff9 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 21 Jul 2020 21:46:45 -0300 Subject: [PATCH 22/26] Fix newMesh(format, ...). Fix Mesh:attachAttribute. Deprecate the mesh argument variant of attachAttribute in favor of the buffer argument variant. --- src/modules/graphics/Mesh.cpp | 1 + src/modules/graphics/wrap_Graphics.cpp | 7 ++++--- src/modules/graphics/wrap_Mesh.cpp | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 77261e7bb..c85662a08 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -307,6 +307,7 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::s else if (attachedAttributes.size() + 1 > VertexAttributes::MAX) throw love::Exception("A maximum of %d attributes can be attached at once.", VertexAttributes::MAX); + newattrib.name = name; newattrib.buffer = buffer; newattrib.enabled = oldattrib.buffer.get() ? oldattrib.enabled : true; newattrib.indexInBuffer = buffer->getDataMemberIndex(attachname); diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 5c2bc44c3..90a1d6595 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1690,7 +1690,7 @@ static Mesh *newCustomMesh(lua_State *L) const char *name = luaL_checkstring(L, -3); - DataFormat format = DATAFORMAT_FLOAT; + DataFormat format = DATAFORMAT_MAX_ENUM; const char *tname = luaL_checkstring(L, -2); if (!lua_isnoneornil(L, -1)) @@ -1728,10 +1728,11 @@ static Mesh *newCustomMesh(lua_State *L) else luaL_error(L, "Invalid component count (%d) for vertex data type %s", components, tname); } - else if (!getConstant(tname, format)) - luax_enumerror(L, "vertex data format", getConstants(format), tname); } + if (format == DATAFORMAT_MAX_ENUM && !getConstant(tname, format)) + luax_enumerror(L, "vertex data format", getConstants(format), tname); + lua_pop(L, 4); vertexformat.emplace_back(name, format); } diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index d499106c1..aa00d4bb2 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -300,6 +300,7 @@ int w_Mesh_attachAttribute(lua_State *L) buffer = mesh->getVertexBuffer(); if (buffer == nullptr) return luaL_error(L, "Mesh does not have its own vertex buffer."); + luax_markdeprecated(L, "Mesh:attachAttribute(name, mesh, ...)", API_METHOD, DEPRECATED_REPLACED, "Mesh:attachAttribute(name, buffer, ...)"); } AttributeStep step = STEP_PER_VERTEX; From 1d087cc5c2cb882424e7d8022ae16740192f36b2 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 21 Jul 2020 21:56:47 -0300 Subject: [PATCH 23/26] Fix Mesh/Buffer:flush uploading more data than it needs to, sometimes. --- src/modules/graphics/opengl/Buffer.cpp | 16 ++++++++++++++-- src/modules/graphics/opengl/Buffer.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 3fd4beaed..2b17dc121 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -112,6 +112,7 @@ void *Buffer::map() modifiedOffset = 0; modifiedSize = 0; + isMappedDataModified = false; return memoryMap; } @@ -149,8 +150,13 @@ void Buffer::unmap() if (!mapped) return; + mapped = false; + if ((mapFlags & MAP_EXPLICIT_RANGE_MODIFY) != 0) { + if (!isMappedDataModified) + return; + modifiedOffset = std::min(modifiedOffset, getSize() - 1); modifiedSize = std::min(modifiedSize, getSize() - modifiedOffset); } @@ -184,8 +190,6 @@ void Buffer::unmap() modifiedOffset = 0; modifiedSize = 0; - - mapped = false; } void Buffer::setMappedRangeModified(size_t offset, size_t modifiedsize) @@ -193,6 +197,14 @@ void Buffer::setMappedRangeModified(size_t offset, size_t modifiedsize) if (!mapped || !(mapFlags & MAP_EXPLICIT_RANGE_MODIFY)) return; + if (!isMappedDataModified) + { + modifiedOffset = offset; + modifiedSize = size; + isMappedDataModified = true; + return; + } + // We're being conservative right now by internally marking the whole range // from the start of section a to the end of section b as modified if both // a and b are marked as modified. diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index e3c089ebc..64fde2f3c 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -75,6 +75,7 @@ private: size_t modifiedOffset = 0; size_t modifiedSize = 0; + bool isMappedDataModified = false; }; // Buffer From d75f5df80d9bfe9f911d7d7367442238d624c8f2 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 25 Jul 2020 19:48:54 -0300 Subject: [PATCH 24/26] Add Buffer methods flush, setArrayData, setElement, getElement, getElementCount, getElementStride, getSize, getFormat --- src/modules/graphics/Buffer.cpp | 2 +- src/modules/graphics/Buffer.h | 6 +- src/modules/graphics/opengl/Buffer.cpp | 2 +- src/modules/graphics/wrap_Buffer.cpp | 255 ++++++++++++++++++++++ src/modules/graphics/wrap_Mesh.cpp | 2 +- src/modules/graphics/wrap_SpriteBatch.cpp | 3 + 6 files changed, 264 insertions(+), 6 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 257571d22..8929eaa57 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -69,7 +69,7 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector 0) + if (decl.arrayLength > 0) throw love::Exception("Arrays are not supported in vertex buffers."); if (info.isMatrix) diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 15b1360a3..6411f9064 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -66,12 +66,12 @@ public: { std::string name; DataFormat format; - int arraySize; + int arrayLength; - DataDeclaration(const std::string &name, DataFormat format, int arraySize = 0) + DataDeclaration(const std::string &name, DataFormat format, int arrayLength = 0) : name(name) , format(format) - , arraySize(arraySize) + , arrayLength(arrayLength) {} }; diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 2b17dc121..fbd8eae95 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -200,7 +200,7 @@ void Buffer::setMappedRangeModified(size_t offset, size_t modifiedsize) if (!isMappedDataModified) { modifiedOffset = offset; - modifiedSize = size; + modifiedSize = modifiedsize; isMappedDataModified = true; return; } diff --git a/src/modules/graphics/wrap_Buffer.cpp b/src/modules/graphics/wrap_Buffer.cpp index d352c40f8..eb0b680e3 100644 --- a/src/modules/graphics/wrap_Buffer.cpp +++ b/src/modules/graphics/wrap_Buffer.cpp @@ -20,6 +20,7 @@ #include "wrap_Buffer.h" #include "Buffer.h" +#include "common/Data.h" namespace love { @@ -185,8 +186,262 @@ Buffer *luax_checkbuffer(lua_State *L, int idx) return luax_checktype(L, idx); } +static int w_Buffer_flush(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + t->unmap(); + return 0; +} + +static int w_Buffer_setArrayData(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + + int startindex = (int) luaL_optnumber(L, 3, 1) - 1; + + int count = -1; + if (!lua_isnoneornil(L, 4)) + { + count = (int) luaL_checknumber(L, 4); + if (count <= 0) + return luaL_error(L, "Element count must be greater than 0."); + } + + size_t stride = t->getArrayStride(); + size_t offset = startindex * stride; + int arraylength = (int) t->getArrayLength(); + + if (startindex >= arraylength || startindex < 0) + return luaL_error(L, "Invalid vertex start index (must be between 1 and %d)", arraylength); + + if (luax_istype(L, 2, Data::type)) + { + Data *d = luax_checktype(L, 2); + + count = count >= 0 ? count : (arraylength - startindex); + if (startindex + count > arraylength) + return luaL_error(L, "Too many array elements (expected at most %d, got %d)", arraylength - startindex, count); + + size_t datasize = std::min(d->getSize(), count * stride); + char *bytedata = (char *) t->map() + offset; + + memcpy(bytedata, d->getData(), datasize); + + t->setMappedRangeModified(offset, datasize); + t->unmap(); + return 0; + } + + const std::vector &members = t->getDataMembers(); + + int ncomponents = 0; + for (const Buffer::DataMember &member : members) + ncomponents += member.info.components; + + luaL_checktype(L, 2, LUA_TTABLE); + int tablelen = (int) luax_objlen(L, 2); + + lua_rawgeti(L, 2, 1); + bool tableoftables = lua_istable(L, -1); + lua_pop(L, 1); + + if (!tableoftables) + { + if (tablelen % ncomponents != 0) + return luaL_error(L, "Array length in flat array variant of Buffer:setArrayData must be a multiple of the number of the total number of components (%d)", ncomponents); + tablelen /= ncomponents; + } + + count = count >= 0 ? std::min(count, tablelen) : tablelen; + if (startindex + count > arraylength) + return luaL_error(L, "Too many array elements (expected at most %d, got %d)", arraylength - startindex, count); + + char *data = (char *) t->map() + offset; + + if (tableoftables) + { + for (int i = 0; i < count; i++) + { + // get arraydata[index] + lua_rawgeti(L, 2, i + 1); + luaL_checktype(L, -1, LUA_TTABLE); + + // get arraydata[index][j] + for (int j = 1; j <= ncomponents; j++) + lua_rawgeti(L, -j, j); + + int idx = -ncomponents; + + for (const Buffer::DataMember &member : members) + { + luax_writebufferdata(L, idx, member.decl.format, data + member.offset); + idx += member.info.components; + } + + lua_pop(L, ncomponents + 1); + + data += stride; + } + } + else // Flat array + { + for (int i = 0; i < count; i++) + { + // get arraydata[arrayindex * ncomponents + componentindex] + for (int componentindex = 1; componentindex <= ncomponents; componentindex++) + lua_rawgeti(L, 2, i * ncomponents + componentindex); + + int idx = -ncomponents; + + for (const Buffer::DataMember &member : members) + { + luax_writebufferdata(L, idx, member.decl.format, data + member.offset); + idx += member.info.components; + } + + lua_pop(L, ncomponents); + + data += stride; + } + } + + t->setMappedRangeModified(offset, count * stride); + t->unmap(); + + return 0; +} + +static int w_Buffer_setElement(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + + size_t index = (size_t) (luaL_checkinteger(L, 2) - 1); + if (index >= t->getArrayLength()) + return luaL_error(L, "Invalid Buffer element index: %ld", index); + + size_t offset = index * t->getArrayStride(); + char *data = (char *) t->map() + offset; + const auto &members = t->getDataMembers(); + + bool istable = lua_istable(L, 3); + int idx = istable ? 1 : 3; + + if (istable) + { + for (const Buffer::DataMember &member : members) + { + int components = member.info.components; + + for (int i = idx; i < idx + components; i++) + lua_rawgeti(L, 3, i); + + luax_writebufferdata(L, -components, member.decl.format, data + member.offset); + + idx += components; + lua_pop(L, components); + } + } + else + { + for (const Buffer::DataMember &member : members) + { + luax_writebufferdata(L, idx, member.decl.format, data + member.offset); + idx += member.info.components; + } + } + + return 0; +} + +static int w_Buffer_getElement(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + if ((t->getMapFlags() & Buffer::MAP_READ) == 0) + return luaL_error(L, "Buffer:getElement requires the buffer to be created with the 'cpureadable' setting set to true."); + + size_t index = (size_t) (luaL_checkinteger(L, 2) - 1); + if (index >= t->getArrayLength()) + return luaL_error(L, "Invalid Buffer element index: %ld", index); + + size_t offset = index * t->getArrayStride(); + const char *data = (const char *) t->map() + offset; + const auto &members = t->getDataMembers(); + + int n = 0; + + for (const Buffer::DataMember &member : members) + { + luax_readbufferdata(L, member.decl.format, data + member.offset); + n += member.info.components; + } + + return n; +} + +static int w_Buffer_getElementCount(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + lua_pushinteger(L, t->getArrayLength()); + return 1; +} + +static int w_Buffer_getElementStride(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + lua_pushinteger(L, t->getArrayStride()); + return 1; +} + +static int w_Buffer_getSize(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + lua_pushinteger(L, t->getSize()); + return 1; +} + +static int w_Buffer_getFormat(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + const auto &members = t->getDataMembers(); + + lua_createtable(L, (int) members.size(), 0); + + for (size_t i = 0; i < members.size(); i++) + { + const Buffer::DataMember &member = members[i]; + + lua_createtable(L, 0, 4); + + lua_pushstring(L, member.decl.name.c_str()); + lua_setfield(L, -2, "name"); + + const char *formatstr = "unknown"; + getConstant(member.decl.format, formatstr); + lua_pushstring(L, formatstr); + lua_setfield(L, -2, "format"); + + lua_pushinteger(L, member.decl.arrayLength); + lua_setfield(L, -2, "arraylength"); + + lua_pushinteger(L, member.offset); + lua_setfield(L, -2, "offset"); + + lua_rawseti(L, -2, i + 1); + } + + return 1; +} + static const luaL_Reg w_Buffer_functions[] = { + { "flush", w_Buffer_flush }, + { "setArrayData", w_Buffer_setArrayData }, + { "setElement", w_Buffer_setElement }, + { "getElement", w_Buffer_getElement }, + { "getElementCount", w_Buffer_getElementCount }, + { "getElementStride", w_Buffer_getElementStride }, + { "getSize", w_Buffer_getSize }, + { "getFormat", w_Buffer_getFormat }, { 0, 0 } }; diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index aa00d4bb2..211463033 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -55,7 +55,7 @@ int w_Mesh_setVertices(lua_State *L) size_t byteoffset = vertstart * stride; int totalverts = (int) t->getVertexCount(); - if (vertstart >= totalverts) + if (vertstart >= totalverts || vertstart < 0) return luaL_error(L, "Invalid vertex start index (must be between 1 and %d)", totalverts); if (luax_istype(L, 2, Data::type)) diff --git a/src/modules/graphics/wrap_SpriteBatch.cpp b/src/modules/graphics/wrap_SpriteBatch.cpp index f9e1fe360..981bcb6dc 100644 --- a/src/modules/graphics/wrap_SpriteBatch.cpp +++ b/src/modules/graphics/wrap_SpriteBatch.cpp @@ -226,6 +226,9 @@ int w_SpriteBatch_attachAttribute(lua_State *L) { Mesh *mesh = luax_checktype(L, 3); buffer = mesh->getVertexBuffer(); + if (buffer == nullptr) + return luaL_error(L, "Mesh does not have its own vertex buffer."); + luax_markdeprecated(L, "SpriteBatch:attachAttribute(name, mesh)", API_METHOD, DEPRECATED_REPLACED, "SpriteBatch:attachAttribute(name, buffer)"); } luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer); }); From 36b0394afcf4456da5f923d8a9c39bc339fbe6df Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 26 Jul 2020 16:32:18 -0300 Subject: [PATCH 25/26] Add love.graphics.newVertexBuffer and love.graphics.newBuffer. --- src/modules/graphics/Buffer.cpp | 3 + src/modules/graphics/wrap_Buffer.cpp | 8 +- src/modules/graphics/wrap_Graphics.cpp | 191 ++++++++++++++++++++++++- 3 files changed, 197 insertions(+), 5 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 8929eaa57..6f4996d10 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -48,6 +48,9 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector= t->getArrayLength()) return luaL_error(L, "Invalid Buffer element index: %ld", index); - size_t offset = index * t->getArrayStride(); + size_t stride = t->getArrayStride(); + size_t offset = index * stride; char *data = (char *) t->map() + offset; const auto &members = t->getDataMembers(); @@ -350,6 +349,7 @@ static int w_Buffer_setElement(lua_State *L) } } + t->setMappedRangeModified(offset, stride); return 0; } diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 90a1d6595..ec897c9ec 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -1514,6 +1515,192 @@ static void luax_optbuffersettings(lua_State *L, int idx, Buffer::Settings &sett settings.mapFlags = (Buffer::MapFlags)(settings.mapFlags & (~Buffer::MAP_READ)); } +static void luax_checkbufferformat(lua_State *L, int idx, std::vector &format) +{ + luaL_checktype(L, idx, LUA_TTABLE); + int tablelen = luax_objlen(L, idx); + + for (int i = 1; i <= tablelen; i++) + { + lua_rawgeti(L, idx, i); + luaL_checktype(L, -1, LUA_TTABLE); + + Buffer::DataDeclaration decl("", DATAFORMAT_MAX_ENUM); + + lua_getfield(L, -1, "name"); + if (lua_type(L, -1) != LUA_TSTRING) + { + std::ostringstream ss; + ss << "'name' field expected in array element #"; + ss << i; + ss << " of format table"; + std::string str = ss.str(); + luaL_argerror(L, idx, str.c_str()); + } + decl.name = luax_checkstring(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "format"); + if (lua_type(L, -1) != LUA_TSTRING) + { + std::ostringstream ss; + ss << "'format' field expected in array element #"; + ss << i; + ss << " of format table"; + std::string str = ss.str(); + luaL_argerror(L, idx, str.c_str()); + } + const char *formatstr = luaL_checkstring(L, -1); + if (!getConstant(formatstr, decl.format)) + luax_enumerror(L, "data format", getConstants(decl.format), formatstr); + lua_pop(L, 1); + + decl.arrayLength = luax_intflag(L, -1, "arraylength", 0); + + format.push_back(decl); + lua_pop(L, 1); + } +} + +static Buffer *luax_newbuffer(lua_State *L, int idx, const Buffer::Settings &settings, const std::vector &format) +{ + size_t arraylength = 0; + size_t bytesize = 0; + Data *data = nullptr; + const void *initialdata = nullptr; + + int ncomponents = 0; + for (const Buffer::DataDeclaration &decl : format) + ncomponents += getDataFormatInfo(decl.format).components; + + if (luax_istype(L, idx, Data::type)) + { + data = luax_checktype(L, idx); + initialdata = data->getData(); + bytesize = data->getSize(); + } + + bool tableoftables = false; + + if (lua_istable(L, idx)) + { + arraylength = luax_objlen(L, idx); + + lua_rawgeti(L, idx, 1); + tableoftables = lua_istable(L, -1); + lua_pop(L, 1); + + if (!tableoftables) + { + if (arraylength % ncomponents != 0) + luaL_error(L, "Array length in flat array variant of newBuffer must be a multiple of the total number of components (%d)", ncomponents); + arraylength /= ncomponents; + } + } + else if (data == nullptr) + { + lua_Integer len = luaL_checkinteger(L, idx); + if (len <= 0) + luaL_argerror(L, idx, "number of elements must be greater than 0"); + arraylength = (size_t) len; + } + + Buffer *b = nullptr; + luax_catchexcept(L, [&] { b = instance()->newBuffer(settings, format, initialdata, bytesize, arraylength); }); + + if (lua_istable(L, idx)) + { + Buffer::Mapper mapper(*b); + char *data = (char *) mapper.data; + const auto &members = b->getDataMembers(); + size_t stride = b->getArrayStride(); + + if (tableoftables) + { + for (size_t i = 0; i < arraylength; i++) + { + // get arraydata[index] + lua_rawgeti(L, 2, i + 1); + luaL_checktype(L, -1, LUA_TTABLE); + + // get arraydata[index][j] + for (int j = 1; j <= ncomponents; j++) + lua_rawgeti(L, -j, j); + + int idx = -ncomponents; + + for (const Buffer::DataMember &member : members) + { + luax_writebufferdata(L, idx, member.decl.format, data + member.offset); + idx += member.info.components; + } + + lua_pop(L, ncomponents + 1); + data += stride; + } + } + else // Flat array + { + for (size_t i = 0; i < arraylength; i++) + { + // get arraydata[arrayindex * ncomponents + componentindex] + for (int componentindex = 1; componentindex <= ncomponents; componentindex++) + lua_rawgeti(L, 2, i * ncomponents + componentindex); + + int idx = -ncomponents; + + for (const Buffer::DataMember &member : members) + { + luax_writebufferdata(L, idx, member.decl.format, data + member.offset); + idx += member.info.components; + } + + lua_pop(L, ncomponents); + data += stride; + } + } + } + + return b; +} + +int w_newBuffer(lua_State *L) +{ + Buffer::Settings settings(0, Buffer::MAP_EXPLICIT_RANGE_MODIFY, BUFFERUSAGE_DYNAMIC); + + luaL_checktype(L, 3, LUA_TTABLE); + if (luax_boolflag(L, 3, "vertex", false)) + settings.typeFlags = (Buffer::TypeFlags)(settings.typeFlags | Buffer::TYPEFLAG_VERTEX); + if (luax_boolflag(L, 3, "index", false)) + settings.typeFlags = (Buffer::TypeFlags)(settings.typeFlags | Buffer::TYPEFLAG_INDEX); + + luax_optbuffersettings(L, 3, settings); + + std::vector format; + luax_checkbufferformat(L, 1, format); + + Buffer *b = luax_newbuffer(L, 2, settings, format); + + luax_pushtype(L, b); + b->release(); + return 1; +} + +int w_newVertexBuffer(lua_State *L) +{ + Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY, BUFFERUSAGE_DYNAMIC); + luax_optbuffersettings(L, 3, settings); + + std::vector format; + luax_checkbufferformat(L, 1, format); + + Buffer *b = luax_newbuffer(L, 2, settings, format); + + luax_pushtype(L, b); + b->release(); + return 1; +} + int w_newIndexBuffer(lua_State *L) { Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY, BUFFERUSAGE_DYNAMIC); @@ -1534,7 +1721,7 @@ int w_newIndexBuffer(lua_State *L) if (lua_istable(L, 1)) { - arraylength = (size_t) luax_objlen(L, 1); + arraylength = luax_objlen(L, 1); // Scan array for invalid types and the max value. lua_Integer maxvalue = 0; @@ -3192,6 +3379,8 @@ static const luaL_Reg functions[] = { "newSpriteBatch", w_newSpriteBatch }, { "newParticleSystem", w_newParticleSystem }, { "newShader", w_newShader }, + { "newBuffer", w_newBuffer }, + { "newVertexBuffer", w_newVertexBuffer }, { "newIndexBuffer", w_newIndexBuffer }, { "newMesh", w_newMesh }, { "newText", w_newText }, From 2d7267a4284ca2f088b289c46bd2c0db6312eaf2 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 26 Jul 2020 16:43:40 -0300 Subject: [PATCH 26/26] Add Buffer:isBufferType and Buffer:isCPUReadable. --- src/modules/graphics/vertex.cpp | 7 +++++++ src/modules/graphics/vertex.h | 1 + src/modules/graphics/wrap_Buffer.cpp | 20 ++++++++++++++++++++ src/modules/graphics/wrap_Graphics.cpp | 14 ++++++++++---- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index ea135e0f4..ffc3e448c 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -337,6 +337,13 @@ const char *getConstant(BuiltinVertexAttribute attrib) return name; } +STRINGMAP_BEGIN(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName) +{ + { "vertex", BUFFERTYPE_VERTEX }, + { "index", BUFFERTYPE_INDEX }, +} +STRINGMAP_END(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName) + STRINGMAP_BEGIN(IndexDataType, INDEX_MAX_ENUM, indexType) { { "uint16", INDEX_UINT16 }, diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 003d4eb9f..5dd74ce47 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -377,6 +377,7 @@ void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount, void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices); STRINGMAP_DECLARE(BuiltinVertexAttribute); +STRINGMAP_DECLARE(BufferType); STRINGMAP_DECLARE(IndexDataType); STRINGMAP_DECLARE(BufferUsage); STRINGMAP_DECLARE(PrimitiveType); diff --git a/src/modules/graphics/wrap_Buffer.cpp b/src/modules/graphics/wrap_Buffer.cpp index 219552258..78813170b 100644 --- a/src/modules/graphics/wrap_Buffer.cpp +++ b/src/modules/graphics/wrap_Buffer.cpp @@ -432,6 +432,24 @@ static int w_Buffer_getFormat(lua_State *L) return 1; } +static int w_Buffer_isBufferType(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + BufferType buffertype = BUFFERTYPE_MAX_ENUM; + const char *typestr = luaL_checkstring(L, 2); + if (!getConstant(typestr, buffertype)) + return luax_enumerror(L, "buffer type", getConstants(buffertype), typestr); + luax_pushboolean(L, (t->getTypeFlags() & (1 << buffertype)) != 0); + return 1; +} + +static int w_Buffer_isCPUReadable(lua_State *L) +{ + Buffer *t = luax_checkbuffer(L, 1); + luax_pushboolean(L, (t->getMapFlags() & Buffer::MAP_READ) != 0); + return 1; +} + static const luaL_Reg w_Buffer_functions[] = { { "flush", w_Buffer_flush }, @@ -442,6 +460,8 @@ static const luaL_Reg w_Buffer_functions[] = { "getElementStride", w_Buffer_getElementStride }, { "getSize", w_Buffer_getSize }, { "getFormat", w_Buffer_getFormat }, + { "isBufferType", w_Buffer_isBufferType }, + { "isCPUReadable", w_Buffer_isCPUReadable }, { 0, 0 } }; diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index ec897c9ec..a479411b3 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1669,10 +1669,16 @@ int w_newBuffer(lua_State *L) Buffer::Settings settings(0, Buffer::MAP_EXPLICIT_RANGE_MODIFY, BUFFERUSAGE_DYNAMIC); luaL_checktype(L, 3, LUA_TTABLE); - if (luax_boolflag(L, 3, "vertex", false)) - settings.typeFlags = (Buffer::TypeFlags)(settings.typeFlags | Buffer::TYPEFLAG_VERTEX); - if (luax_boolflag(L, 3, "index", false)) - settings.typeFlags = (Buffer::TypeFlags)(settings.typeFlags | Buffer::TYPEFLAG_INDEX); + + for (int i = 0; i < BUFFERTYPE_MAX_ENUM; i++) + { + BufferType buffertype = (BufferType) i; + const char *tname = nullptr; + if (!getConstant(buffertype, tname)) + continue; + if (luax_boolflag(L, 3, tname, false)) + settings.typeFlags = (Buffer::TypeFlags)(settings.typeFlags | (1u << i)); + } luax_optbuffersettings(L, 3, settings);