mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Meshes expose GraphicsBuffers, part 2
This commit is contained in:
@@ -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<DataMember> &dataMembers, size_t arraylength)
|
||||
: Buffer(0, settings.typeFlags, settings.usage, settings.mapFlags)
|
||||
Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataDeclaration> &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<DataMe
|
||||
if (info.componentSize != 4)
|
||||
throw love::Exception("");
|
||||
}
|
||||
|
||||
|
||||
// TODO: alignment
|
||||
member.offset = offset;
|
||||
offset += member.info.size;
|
||||
|
||||
dataMembers.push_back(member);
|
||||
}
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
size_t remainder = size % stride;
|
||||
if (remainder > 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<DataMember> &members, size_t arraylength);
|
||||
Buffer(const Settings &settings, const void *data, size_t size);
|
||||
Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataDeclaration> &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<DataMember> &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<DataMember> dataMembers;
|
||||
std::vector<size_t> 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;
|
||||
|
||||
@@ -642,7 +642,7 @@ void Font::printv(graphics::Graphics *gfx, const Matrix4 &t, const std::vector<D
|
||||
{
|
||||
Graphics::StreamDrawCommand streamcmd;
|
||||
streamcmd.formats[0] = vertexFormat;
|
||||
streamcmd.indexMode = TriangleIndexMode::QUADS;
|
||||
streamcmd.indexMode = TRIANGLEINDEX_QUADS;
|
||||
streamcmd.vertexCount = cmd.vertexcount;
|
||||
streamcmd.texture = cmd.texture;
|
||||
|
||||
|
||||
@@ -173,10 +173,10 @@ void Graphics::createQuadIndexBuffer()
|
||||
return;
|
||||
|
||||
size_t size = sizeof(uint16) * (LOVE_UINT16_MAX / 4) * 6;
|
||||
quadIndexBuffer = newBuffer(size, nullptr, BUFFERFLAG_INDEX, BUFFERUSAGE_STATIC, 0);
|
||||
quadIndexBuffer = newIndexBuffer(INDEX_UINT16, nullptr, size, BUFFERUSAGE_STATIC, 0);
|
||||
|
||||
Buffer::Mapper map(*quadIndexBuffer);
|
||||
fillIndices(TriangleIndexMode::QUADS, 0, LOVE_UINT16_MAX, (uint16 *) map.get());
|
||||
fillIndices(TRIANGLEINDEX_QUADS, 0, LOVE_UINT16_MAX, (uint16 *) map.get());
|
||||
}
|
||||
|
||||
Quad *Graphics::newQuad(Quad::Viewport v, double sw, double sh)
|
||||
@@ -260,6 +260,17 @@ Shader *Graphics::newShader(const std::string &vertex, const std::string &pixel)
|
||||
return newShaderInternal(vertexstage.get(), pixelstage.get());
|
||||
}
|
||||
|
||||
Buffer *Graphics::newIndexBuffer(IndexDataType dataType, const void *indices, size_t size, BufferUsage usage, uint32 mapflags)
|
||||
{
|
||||
Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, mapflags, usage);
|
||||
|
||||
std::vector<Buffer::DataDeclaration> format = {
|
||||
{ "index", getIndexDataFormat(dataType), 0 }
|
||||
};
|
||||
|
||||
return newBuffer(settings, format, indices, size, 0);
|
||||
}
|
||||
|
||||
Mesh *Graphics::newMesh(const std::vector<Vertex> &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<Mesh::AttribFormat> &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage)
|
||||
love::graphics::Mesh *Graphics::newMesh(const std::vector<Buffer::DataDeclaration> &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage)
|
||||
{
|
||||
return new Mesh(this, vertexformat, vertexcount, drawmode, usage);
|
||||
}
|
||||
|
||||
love::graphics::Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage)
|
||||
love::graphics::Mesh *Graphics::newMesh(const std::vector<Buffer::DataDeclaration> &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);
|
||||
|
||||
@@ -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<Buffer::DataMember> &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<Buffer::DataDeclaration> &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<Vertex> &vertices, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh *newMesh(int vertexcount, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh *newMesh(const std::vector<Buffer::DataDeclaration> &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh *newMesh(const std::vector<Buffer::DataDeclaration> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage);
|
||||
|
||||
Text *newText(Font *font, const std::vector<Font::ColoredString> &text = {});
|
||||
|
||||
|
||||
@@ -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::AttribFormat> Mesh::getDefaultVertexFormat()
|
||||
std::vector<Buffer::DataDeclaration> Mesh::getDefaultVertexFormat()
|
||||
{
|
||||
// Corresponds to the love::Vertex struct.
|
||||
std::vector<Mesh::AttribFormat> vertexformat = {
|
||||
{ getBuiltinAttribName(ATTRIB_POS), DATA_FLOAT, 2 },
|
||||
{ getBuiltinAttribName(ATTRIB_TEXCOORD), DATA_FLOAT, 2 },
|
||||
{ getBuiltinAttribName(ATTRIB_COLOR), DATA_UNORM8, 4 },
|
||||
std::vector<Buffer::DataDeclaration> 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::AttribFormat> Mesh::getDefaultVertexFormat()
|
||||
|
||||
love::Type Mesh::type("Mesh", &Drawable::type);
|
||||
|
||||
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage)
|
||||
: vertexFormat(vertexformat)
|
||||
, vertexBuffer(nullptr)
|
||||
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<Buffer::DataDeclaration> &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<AttribFormat> &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<AttribFormat> &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage)
|
||||
: vertexFormat(vertexformat)
|
||||
, vertexBuffer(nullptr)
|
||||
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<Buffer::DataDeclaration> &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<AttribFormat> &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::AttribFormat> &Mesh::getVertexFormat() const
|
||||
const std::vector<Buffer::DataMember> &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<Graphics>(Module::M_GRAPHICS);
|
||||
@@ -410,7 +363,8 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
|
||||
if (indexBuffer.get() == nullptr || size > indexBuffer->getSize())
|
||||
{
|
||||
auto gfx = Module::getInstance<graphics::Graphics>(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<graphics::Graphics>(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.
|
||||
|
||||
@@ -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<AttribFormat> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh(Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh(Graphics *gfx, const std::vector<Buffer::DataDeclaration> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage);
|
||||
Mesh(Graphics *gfx, const std::vector<Buffer::DataDeclaration> &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<AttribFormat> &getVertexFormat() const;
|
||||
DataType getAttributeInfo(int attribindex, int &components) const;
|
||||
const std::vector<Buffer::DataMember> &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<AttribFormat> getDefaultVertexFormat();
|
||||
static std::vector<Buffer::DataDeclaration> getDefaultVertexFormat();
|
||||
|
||||
private:
|
||||
|
||||
@@ -189,11 +181,8 @@ private:
|
||||
};
|
||||
|
||||
void setupAttachedAttributes();
|
||||
void calculateAttributeSizes(Graphics *gfx);
|
||||
size_t getAttributeOffset(size_t attribindex) const;
|
||||
|
||||
std::vector<AttribFormat> vertexFormat;
|
||||
std::vector<size_t> attributeSizes;
|
||||
std::vector<Buffer::DataMember> vertexFormat;
|
||||
|
||||
std::unordered_map<std::string, AttachedAttribute> attachedAttributes;
|
||||
|
||||
|
||||
@@ -191,7 +191,8 @@ void ParticleSystem::createBuffers(size_t size)
|
||||
auto gfx = Module::getInstance<Graphics>(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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<graphics::Graphics>(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.
|
||||
|
||||
@@ -42,7 +42,8 @@ Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
|
||||
|
||||
Text::~Text()
|
||||
{
|
||||
delete vertex_buffer;
|
||||
if (vertex_buffer)
|
||||
vertex_buffer->release();
|
||||
}
|
||||
|
||||
void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset)
|
||||
@@ -60,12 +61,13 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
|
||||
newsize = std::max(size_t(vertex_buffer->getSize() * 1.5), newsize);
|
||||
|
||||
auto gfx = Module::getInstance<Graphics>(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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<DataDeclaration> &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
|
||||
|
||||
@@ -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<DataDeclaration> &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
|
||||
|
||||
|
||||
@@ -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<Buffer::DataMember> &format, size_t arraylength)
|
||||
love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const std::vector<Buffer::DataDeclaration> &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())
|
||||
{
|
||||
|
||||
@@ -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<Buffer::DataMember> &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<Buffer::DataDeclaration> &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;
|
||||
|
||||
@@ -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<void*>(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);
|
||||
|
||||
@@ -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<GLuint> boundTextures[TEXTURE_MAX_ENUM];
|
||||
|
||||
@@ -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 },
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Mesh::AttribFormat> vertexformat;
|
||||
std::vector<Buffer::DataDeclaration> 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);
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ template <typename T>
|
||||
static inline size_t writeSNormData(lua_State *L, int startidx, int components, char *data)
|
||||
{
|
||||
auto componentdata = (T *) data;
|
||||
auto maxval = std::numeric_limits<T>::max();
|
||||
const auto maxval = std::numeric_limits<T>::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 <typename T>
|
||||
static inline size_t writeUNormData(lua_State *L, int startidx, int components, char *data)
|
||||
{
|
||||
auto componentdata = (T *) data;
|
||||
auto maxval = std::numeric_limits<T>::max();
|
||||
const auto maxval = std::numeric_limits<T>::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<int8>(L, startidx, components, data);
|
||||
case DATA_UNORM8:
|
||||
return data + writeUNormData<uint8>(L, startidx, components, data);
|
||||
case DATA_INT8:
|
||||
return data + writeData<int8>(L, startidx, components, data);
|
||||
case DATA_UINT8:
|
||||
return data + writeData<uint8>(L, startidx, components, data);
|
||||
case DATA_SNORM16:
|
||||
return data + writeSNormData<int16>(L, startidx, components, data);
|
||||
case DATA_UNORM16:
|
||||
return data + writeUNormData<uint16>(L, startidx, components, data);
|
||||
case DATA_INT16:
|
||||
return data + writeData<int16>(L, startidx, components, data);
|
||||
case DATA_UINT16:
|
||||
return data + writeData<uint16>(L, startidx, components, data);
|
||||
case DATA_INT32:
|
||||
return data + writeData<int32>(L, startidx, components, data);
|
||||
case DATA_UINT32:
|
||||
return data + writeData<uint32>(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<float>(L, startidx, components, data);
|
||||
|
||||
case DATAFORMAT_INT32:
|
||||
case DATAFORMAT_INT32_VEC2:
|
||||
case DATAFORMAT_INT32_VEC3:
|
||||
case DATAFORMAT_INT32_VEC4:
|
||||
return data + writeData<int32>(L, startidx, components, data);
|
||||
|
||||
case DATAFORMAT_UINT32:
|
||||
case DATAFORMAT_UINT32_VEC2:
|
||||
case DATAFORMAT_UINT32_VEC3:
|
||||
case DATAFORMAT_UINT32_VEC4:
|
||||
return data + writeData<uint32>(L, startidx, components, data);
|
||||
|
||||
case DATAFORMAT_SNORM8_VEC4:
|
||||
return data + writeSNormData<int8>(L, startidx, 4, data);
|
||||
case DATAFORMAT_UNORM8_VEC4:
|
||||
return data + writeUNormData<uint8>(L, startidx, 4, data);
|
||||
case DATAFORMAT_INT8_VEC4:
|
||||
return data + writeData<int8>(L, startidx, 4, data);
|
||||
case DATAFORMAT_UINT8_VEC4:
|
||||
return data + writeData<uint8>(L, startidx, 4, data);
|
||||
|
||||
case DATAFORMAT_SNORM16_VEC2:
|
||||
case DATAFORMAT_SNORM16_VEC4:
|
||||
return data + writeSNormData<int16>(L, startidx, components, data);
|
||||
|
||||
case DATAFORMAT_UNORM16_VEC2:
|
||||
case DATAFORMAT_UNORM16_VEC4:
|
||||
return data + writeUNormData<uint16>(L, startidx, components, data);
|
||||
|
||||
case DATAFORMAT_INT16_VEC2:
|
||||
case DATAFORMAT_INT16_VEC4:
|
||||
return data + writeData<int16>(L, startidx, components, data);
|
||||
|
||||
case DATAFORMAT_UINT16:
|
||||
case DATAFORMAT_UINT16_VEC2:
|
||||
case DATAFORMAT_UINT16_VEC4:
|
||||
return data + writeData<uint16>(L, startidx, components, data);
|
||||
|
||||
default:
|
||||
return data;
|
||||
}
|
||||
@@ -108,7 +130,7 @@ char *luax_writeAttributeData(lua_State *L, int startidx, DataType type, int com
|
||||
template <typename T>
|
||||
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 <typename T>
|
||||
static inline size_t readSNormData(lua_State *L, int components, const char *data)
|
||||
{
|
||||
auto componentdata = (const T *) data;
|
||||
auto maxval = std::numeric_limits<T>::max();
|
||||
const auto componentdata = (const T *) data;
|
||||
const auto maxval = std::numeric_limits<T>::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 <typename T>
|
||||
static inline size_t readUNormData(lua_State *L, int components, const char *data)
|
||||
{
|
||||
auto componentdata = (const T *) data;
|
||||
auto maxval = std::numeric_limits<T>::max();
|
||||
const auto componentdata = (const T *) data;
|
||||
const auto maxval = std::numeric_limits<T>::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<int8>(L, components, data);
|
||||
case DATA_UNORM8:
|
||||
return data + readUNormData<uint8>(L, components, data);
|
||||
case DATA_INT8:
|
||||
return data + readData<int8>(L, components, data);
|
||||
case DATA_UINT8:
|
||||
return data + readData<uint8>(L, components, data);
|
||||
case DATA_SNORM16:
|
||||
return data + readSNormData<int16>(L, components, data);
|
||||
case DATA_UNORM16:
|
||||
return data + readUNormData<uint16>(L, components, data);
|
||||
case DATA_INT16:
|
||||
return data + readData<int16>(L, components, data);
|
||||
case DATA_UINT16:
|
||||
return data + readData<uint16>(L, components, data);
|
||||
case DATA_INT32:
|
||||
return data + readData<int32>(L, components, data);
|
||||
case DATA_UINT32:
|
||||
return data + readData<uint32>(L, components, data);
|
||||
case DATA_FLOAT:
|
||||
case DATAFORMAT_FLOAT:
|
||||
case DATAFORMAT_FLOAT_VEC2:
|
||||
case DATAFORMAT_FLOAT_VEC3:
|
||||
case DATAFORMAT_FLOAT_VEC4:
|
||||
return data + readData<float>(L, components, data);
|
||||
|
||||
case DATAFORMAT_INT32:
|
||||
case DATAFORMAT_INT32_VEC2:
|
||||
case DATAFORMAT_INT32_VEC3:
|
||||
case DATAFORMAT_INT32_VEC4:
|
||||
return data + readData<int32>(L, components, data);
|
||||
|
||||
case DATAFORMAT_UINT32:
|
||||
case DATAFORMAT_UINT32_VEC2:
|
||||
case DATAFORMAT_UINT32_VEC3:
|
||||
case DATAFORMAT_UINT32_VEC4:
|
||||
return data + readData<uint32>(L, components, data);
|
||||
|
||||
case DATAFORMAT_SNORM8_VEC4:
|
||||
return data + readSNormData<int8>(L, 4, data);
|
||||
case DATAFORMAT_UNORM8_VEC4:
|
||||
return data + readUNormData<uint8>(L, 4, data);
|
||||
case DATAFORMAT_INT8_VEC4:
|
||||
return data + readData<int8>(L, 4, data);
|
||||
case DATAFORMAT_UINT8_VEC4:
|
||||
return data + readData<uint8>(L, 4, data);
|
||||
|
||||
case DATAFORMAT_SNORM16_VEC2:
|
||||
case DATAFORMAT_SNORM16_VEC4:
|
||||
return data + readSNormData<int16>(L, components, data);
|
||||
|
||||
case DATAFORMAT_UNORM16_VEC2:
|
||||
case DATAFORMAT_UNORM16_VEC4:
|
||||
return data + readUNormData<uint16>(L, components, data);
|
||||
|
||||
case DATAFORMAT_INT16_VEC2:
|
||||
case DATAFORMAT_INT16_VEC4:
|
||||
return data + readData<int16>(L, components, data);
|
||||
|
||||
case DATAFORMAT_UINT16:
|
||||
case DATAFORMAT_UINT16_VEC2:
|
||||
case DATAFORMAT_UINT16_VEC4:
|
||||
return data + readData<uint16>(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<Mesh::AttribFormat> &vertexformat = t->getVertexFormat();
|
||||
const std::vector<Buffer::DataMember> &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<Mesh::AttribFormat> &vertexformat = t->getVertexFormat();
|
||||
const std::vector<Buffer::DataMember> &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<Mesh::AttribFormat> &vertexformat = t->getVertexFormat();
|
||||
const std::vector<Buffer::DataMember> &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<Mesh::AttribFormat> &vertexformat = t->getVertexFormat();
|
||||
const std::vector<Buffer::DataMember> &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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user