mirror of
https://github.com/bjornbytes/lovr.git
synced 2024-07-04 21:43:34 +00:00
rm Pass:setVertexFormat and table variant of Pass:mesh;
The complexity/convenience tradeoff isn't satisfactory.
This commit is contained in:
parent
d17232bac5
commit
3804d15184
|
@ -617,19 +617,6 @@ static int l_lovrPassSetStencilWrite(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_lovrPassSetVertexFormat(lua_State* L) {
|
|
||||||
uint32_t count = 0;
|
|
||||||
BufferField fields[16];
|
|
||||||
Pass* pass = luax_checktype(L, 1, Pass);
|
|
||||||
if (lua_isnil(L, 2)) {
|
|
||||||
lovrPassSetVertexFormat(pass, NULL, 0);
|
|
||||||
} else {
|
|
||||||
luax_checkbufferformat(L, 2, fields, &count, COUNTOF(fields));
|
|
||||||
lovrPassSetVertexFormat(pass, fields, count);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_lovrPassSetWinding(lua_State* L) {
|
static int l_lovrPassSetWinding(lua_State* L) {
|
||||||
Pass* pass = luax_checktype(L, 1, Pass);
|
Pass* pass = luax_checktype(L, 1, Pass);
|
||||||
Winding winding = luax_checkenum(L, 2, Winding, NULL);
|
Winding winding = luax_checkenum(L, 2, Winding, NULL);
|
||||||
|
@ -961,27 +948,6 @@ static int l_lovrPassDraw(lua_State* L) {
|
||||||
|
|
||||||
static int l_lovrPassMesh(lua_State* L) {
|
static int l_lovrPassMesh(lua_State* L) {
|
||||||
Pass* pass = luax_checktype(L, 1, Pass);
|
Pass* pass = luax_checktype(L, 1, Pass);
|
||||||
|
|
||||||
if (lua_istable(L, 2)) {
|
|
||||||
lua_rawgeti(L, 2, 1);
|
|
||||||
lovrCheck(lua_type(L, -1) == LUA_TTABLE, "Vertex data must be provided as a table of tables");
|
|
||||||
lua_pop(L, 1);
|
|
||||||
float transform[16];
|
|
||||||
uint32_t vertexCount = luax_len(L, 2);
|
|
||||||
uint32_t indexCount = lua_istable(L, 3) ? luax_len(L, 3) : 0;
|
|
||||||
luax_readmat4(L, indexCount > 0 ? 4 : 3, transform, 1);
|
|
||||||
BufferField* format;
|
|
||||||
void* vertices;
|
|
||||||
void* indices;
|
|
||||||
lovrPassMeshImmediate(pass, vertexCount, &vertices, &format, indexCount, &indices, transform);
|
|
||||||
luax_checkbufferdata(L, 2, format, vertices);
|
|
||||||
if (indexCount > 0) {
|
|
||||||
BufferField indexFormat = { .type = FIELD_INDEX16, .length = indexCount, .stride = 2 };
|
|
||||||
luax_checkbufferdata(L, 3, &indexFormat, indices);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Buffer* vertices = (!lua_toboolean(L, 2) || lua_type(L, 2) == LUA_TNUMBER) ? NULL : luax_checkbuffer(L, 2);
|
Buffer* vertices = (!lua_toboolean(L, 2) || lua_type(L, 2) == LUA_TNUMBER) ? NULL : luax_checkbuffer(L, 2);
|
||||||
Buffer* indices = luax_totype(L, 3, Buffer);
|
Buffer* indices = luax_totype(L, 3, Buffer);
|
||||||
Buffer* indirect = luax_totype(L, 4, Buffer);
|
Buffer* indirect = luax_totype(L, 4, Buffer);
|
||||||
|
@ -1133,7 +1099,6 @@ const luaL_Reg lovrPass[] = {
|
||||||
{ "setShader", l_lovrPassSetShader },
|
{ "setShader", l_lovrPassSetShader },
|
||||||
{ "setStencilTest", l_lovrPassSetStencilTest },
|
{ "setStencilTest", l_lovrPassSetStencilTest },
|
||||||
{ "setStencilWrite", l_lovrPassSetStencilWrite },
|
{ "setStencilWrite", l_lovrPassSetStencilWrite },
|
||||||
{ "setVertexFormat", l_lovrPassSetVertexFormat },
|
|
||||||
{ "setWinding", l_lovrPassSetWinding },
|
{ "setWinding", l_lovrPassSetWinding },
|
||||||
{ "setWireframe", l_lovrPassSetWireframe },
|
{ "setWireframe", l_lovrPassSetWireframe },
|
||||||
|
|
||||||
|
|
|
@ -46,14 +46,14 @@ typedef struct {
|
||||||
|
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
uint32_t ref;
|
uint32_t ref;
|
||||||
uint32_t tick;
|
|
||||||
Sync sync;
|
Sync sync;
|
||||||
char* names;
|
char* names;
|
||||||
char* pointer;
|
|
||||||
gpu_buffer* gpu;
|
gpu_buffer* gpu;
|
||||||
BufferInfo info;
|
BufferInfo info;
|
||||||
uint32_t offset; // Deprecated (temp buffer only)
|
// Deprecated:
|
||||||
uint64_t hash;
|
uint32_t offset;
|
||||||
|
uint32_t tick;
|
||||||
|
char* pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -187,7 +187,6 @@ typedef enum {
|
||||||
VERTEX_GLYPH,
|
VERTEX_GLYPH,
|
||||||
VERTEX_MODEL,
|
VERTEX_MODEL,
|
||||||
VERTEX_EMPTY,
|
VERTEX_EMPTY,
|
||||||
VERTEX_CUSTOM,
|
|
||||||
VERTEX_FORMAX
|
VERTEX_FORMAX
|
||||||
} VertexFormat;
|
} VertexFormat;
|
||||||
|
|
||||||
|
@ -392,9 +391,9 @@ typedef struct {
|
||||||
bool dirty;
|
bool dirty;
|
||||||
MeshMode mode;
|
MeshMode mode;
|
||||||
float color[4];
|
float color[4];
|
||||||
uint64_t formatHash;
|
Buffer* lastVertexBuffer;
|
||||||
|
VertexFormat lastVertexFormat;
|
||||||
gpu_pipeline_info info;
|
gpu_pipeline_info info;
|
||||||
BufferField* vertexFormat;
|
|
||||||
Material* material;
|
Material* material;
|
||||||
Shader* shader;
|
Shader* shader;
|
||||||
Font* font;
|
Font* font;
|
||||||
|
@ -1722,10 +1721,8 @@ Buffer* lovrGraphicsGetBuffer(BufferInfo* info, void** data) {
|
||||||
buffer->info.fields = malloc(info->fieldCount * sizeof(BufferField));
|
buffer->info.fields = malloc(info->fieldCount * sizeof(BufferField));
|
||||||
lovrAssert(buffer->info.fields, "Out of memory");
|
lovrAssert(buffer->info.fields, "Out of memory");
|
||||||
memcpy(buffer->info.fields, info->fields, info->fieldCount * sizeof(BufferField));
|
memcpy(buffer->info.fields, info->fields, info->fieldCount * sizeof(BufferField));
|
||||||
buffer->hash = hash64(info->fields, info->fieldCount * sizeof(BufferField));
|
|
||||||
} else {
|
} else {
|
||||||
buffer->info.fields = NULL;
|
buffer->info.fields = NULL;
|
||||||
buffer->hash = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-array-length detection (used for computing length from Blob size, must happen after field alignment)
|
// Auto-array-length detection (used for computing length from Blob size, must happen after field alignment)
|
||||||
|
@ -1791,7 +1788,6 @@ Buffer* lovrBufferCreate(const BufferInfo* info, void** data) {
|
||||||
fields = buffer->info.fields = malloc(info->fieldCount * sizeof(BufferField));
|
fields = buffer->info.fields = malloc(info->fieldCount * sizeof(BufferField));
|
||||||
lovrAssert(fields, "Out of memory");
|
lovrAssert(fields, "Out of memory");
|
||||||
memcpy(fields, info->fields, info->fieldCount * sizeof(BufferField));
|
memcpy(fields, info->fields, info->fieldCount * sizeof(BufferField));
|
||||||
buffer->hash = hash64(fields, info->fieldCount * sizeof(BufferField));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-array-length detection (used for computing length from Blob size, must happen after field alignment)
|
// Auto-array-length detection (used for computing length from Blob size, must happen after field alignment)
|
||||||
|
@ -4574,6 +4570,7 @@ void lovrPassReset(Pass* pass) {
|
||||||
pass->pipelineIndex = 0;
|
pass->pipelineIndex = 0;
|
||||||
memset(pass->pipeline, 0, sizeof(Pipeline));
|
memset(pass->pipeline, 0, sizeof(Pipeline));
|
||||||
pass->pipeline->mode = MESH_TRIANGLES;
|
pass->pipeline->mode = MESH_TRIANGLES;
|
||||||
|
pass->pipeline->lastVertexFormat = ~0u;
|
||||||
pass->pipeline->color[0] = 1.f;
|
pass->pipeline->color[0] = 1.f;
|
||||||
pass->pipeline->color[1] = 1.f;
|
pass->pipeline->color[1] = 1.f;
|
||||||
pass->pipeline->color[2] = 1.f;
|
pass->pipeline->color[2] = 1.f;
|
||||||
|
@ -5294,8 +5291,11 @@ void lovrPassSetShader(Pass* pass, Shader* shader) {
|
||||||
pass->pipeline->shader = shader;
|
pass->pipeline->shader = shader;
|
||||||
pass->pipeline->dirty = true;
|
pass->pipeline->dirty = true;
|
||||||
|
|
||||||
|
// If the shader changes, all the attribute names need to be wired up again, because attributes
|
||||||
|
// with the same name might have different locations. But if the shader only uses built-in
|
||||||
|
// attributes (which is common), things will remain stable.
|
||||||
if ((shader && shader->hasCustomAttributes) || (previous && previous->hasCustomAttributes)) {
|
if ((shader && shader->hasCustomAttributes) || (previous && previous->hasCustomAttributes)) {
|
||||||
pass->pipeline->formatHash = 0;
|
pass->pipeline->lastVertexBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader && shader->constantSize > 0 && (!previous || previous->constantSize != shader->constantSize)) {
|
if (shader && shader->constantSize > 0 && (!previous || previous->constantSize != shader->constantSize)) {
|
||||||
|
@ -5342,44 +5342,6 @@ void lovrPassSetStencilWrite(Pass* pass, StencilAction actions[3], uint8_t value
|
||||||
pass->pipeline->dirty = true;
|
pass->pipeline->dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrPassSetVertexFormat(Pass* pass, BufferField* fields, uint32_t count) {
|
|
||||||
if (!pass->pipeline->vertexFormat) { // Vertex formats are huge, allocate it lazily only if needed
|
|
||||||
pass->pipeline->vertexFormat = tempAlloc(&state.allocator, (MAX_CUSTOM_ATTRIBUTES + 1) * sizeof(BufferField));
|
|
||||||
memset(pass->pipeline->vertexFormat, 0, (MAX_CUSTOM_ATTRIBUTES + 1) * sizeof(BufferField));
|
|
||||||
pass->pipeline->vertexFormat[0].children = &pass->pipeline->vertexFormat[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferField* array = pass->pipeline->vertexFormat;
|
|
||||||
|
|
||||||
if (count == 0) {
|
|
||||||
array->stride = 32;
|
|
||||||
array->childCount = 3;
|
|
||||||
array->children = array + 1;
|
|
||||||
array->children[0] = (BufferField) { .type = FIELD_F32x3, .offset = 0, .location = LOCATION_POSITION };
|
|
||||||
array->children[1] = (BufferField) { .type = FIELD_F32x3, .offset = 12, .location = LOCATION_NORMAL };
|
|
||||||
array->children[2] = (BufferField) { .type = FIELD_F32x2, .offset = 24, .location = LOCATION_UV };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < fields[0].childCount; i++) {
|
|
||||||
BufferField* attribute = &fields[0].children[i];
|
|
||||||
lovrCheck(attribute->type < FIELD_MAT2, "Currently vertex attributes can not use matrix or index types");
|
|
||||||
lovrCheck(attribute->childCount == 0, "Vertex attributes can not contain nested fields");
|
|
||||||
lovrCheck(attribute->length == 0, "Vertex attributes can not be arrays");
|
|
||||||
}
|
|
||||||
|
|
||||||
lovrCheck(array->childCount <= MAX_CUSTOM_ATTRIBUTES, "Too many vertex attributes (max is %d)", MAX_CUSTOM_ATTRIBUTES);
|
|
||||||
memcpy(array, fields, count * sizeof(BufferField));
|
|
||||||
array->children = array + (fields[0].children - fields);
|
|
||||||
alignField(array, LAYOUT_PACKED);
|
|
||||||
|
|
||||||
lovrCheck(array->stride <= state.limits.vertexBufferStride, "Vertex buffer stride exceeds vertexBufferStride limit");
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < array->childCount; i++) {
|
|
||||||
lovrCheck(array->children[i].offset <= 255, "Max vertex attribute offset is 255");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrPassSetWinding(Pass* pass, Winding winding) {
|
void lovrPassSetWinding(Pass* pass, Winding winding) {
|
||||||
pass->pipeline->dirty |= pass->pipeline->info.rasterizer.winding != (gpu_winding) winding;
|
pass->pipeline->dirty |= pass->pipeline->info.rasterizer.winding != (gpu_winding) winding;
|
||||||
pass->pipeline->info.rasterizer.winding = (gpu_winding) winding;
|
pass->pipeline->info.rasterizer.winding = (gpu_winding) winding;
|
||||||
|
@ -5505,16 +5467,14 @@ static void lovrPassResolvePipeline(Pass* pass, DrawInfo* info, Draw* draw) {
|
||||||
pipeline->dirty = true;
|
pipeline->dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool customVertexFormat = info->vertex.buffer || info->vertex.format == VERTEX_CUSTOM;
|
|
||||||
BufferField* format = info->vertex.buffer ? &info->vertex.buffer->info.fields[0] : pass->pipeline->vertexFormat;
|
|
||||||
uint64_t formatHash = info->vertex.buffer ? info->vertex.buffer->hash : 1 + info->vertex.format;
|
|
||||||
|
|
||||||
// Vertex formats
|
// Vertex formats
|
||||||
if (pipeline->formatHash != formatHash) {
|
if (info->vertex.buffer && pipeline->lastVertexBuffer != info->vertex.buffer) {
|
||||||
pipeline->formatHash = formatHash;
|
pipeline->lastVertexFormat = ~0u;
|
||||||
|
pipeline->lastVertexBuffer = info->vertex.buffer;
|
||||||
pipeline->dirty = true;
|
pipeline->dirty = true;
|
||||||
|
|
||||||
if (customVertexFormat) {
|
BufferField* format = info->vertex.buffer->info.fields;
|
||||||
|
|
||||||
pipeline->info.vertex.bufferCount = 2;
|
pipeline->info.vertex.bufferCount = 2;
|
||||||
pipeline->info.vertex.attributeCount = shader->attributeCount;
|
pipeline->info.vertex.attributeCount = shader->attributeCount;
|
||||||
pipeline->info.vertex.bufferStrides[0] = format->stride;
|
pipeline->info.vertex.bufferStrides[0] = format->stride;
|
||||||
|
@ -5551,8 +5511,11 @@ static void lovrPassResolvePipeline(Pass* pass, DrawInfo* info, Draw* draw) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!info->vertex.buffer && pipeline->lastVertexFormat != info->vertex.format) {
|
||||||
|
pipeline->lastVertexFormat = info->vertex.format;
|
||||||
|
pipeline->lastVertexBuffer = NULL;
|
||||||
pipeline->info.vertex = state.vertexFormats[info->vertex.format];
|
pipeline->info.vertex = state.vertexFormats[info->vertex.format];
|
||||||
|
pipeline->dirty = true;
|
||||||
|
|
||||||
if (shader->hasCustomAttributes) {
|
if (shader->hasCustomAttributes) {
|
||||||
for (uint32_t i = 0; i < shader->attributeCount; i++) {
|
for (uint32_t i = 0; i < shader->attributeCount; i++) {
|
||||||
|
@ -5567,7 +5530,6 @@ static void lovrPassResolvePipeline(Pass* pass, DrawInfo* info, Draw* draw) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (pipeline->dirty) {
|
if (pipeline->dirty) {
|
||||||
pipeline->dirty = false;
|
pipeline->dirty = false;
|
||||||
|
@ -6693,25 +6655,6 @@ void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transfor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrPassMeshImmediate(Pass* pass, uint32_t vertexCount, void** vertices, BufferField** format, uint32_t indexCount, void** indices, float* transform) {
|
|
||||||
if (!pass->pipeline->vertexFormat) {
|
|
||||||
lovrPassSetVertexFormat(pass, NULL, 0); // Ensure vertex format is set up
|
|
||||||
}
|
|
||||||
|
|
||||||
*format = pass->pipeline->vertexFormat;
|
|
||||||
pass->pipeline->vertexFormat[0].length = vertexCount;
|
|
||||||
|
|
||||||
lovrPassDraw(pass, &(DrawInfo) {
|
|
||||||
.mode = pass->pipeline->mode,
|
|
||||||
.vertex.format = VERTEX_CUSTOM,
|
|
||||||
.vertex.pointer = vertices,
|
|
||||||
.vertex.count = vertexCount,
|
|
||||||
.index.pointer = indices,
|
|
||||||
.index.count = indexCount,
|
|
||||||
.transform = transform
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrPassMeshIndirect(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* draws, uint32_t count, uint32_t offset, uint32_t stride) {
|
void lovrPassMeshIndirect(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* draws, uint32_t count, uint32_t offset, uint32_t stride) {
|
||||||
stride = stride ? stride : (indices ? 20 : 16);
|
stride = stride ? stride : (indices ? 20 : 16);
|
||||||
Shader* shader = pass->pipeline->shader;
|
Shader* shader = pass->pipeline->shader;
|
||||||
|
|
|
@ -587,7 +587,6 @@ void lovrPassSetSampler(Pass* pass, Sampler* sampler);
|
||||||
void lovrPassSetShader(Pass* pass, Shader* shader);
|
void lovrPassSetShader(Pass* pass, Shader* shader);
|
||||||
void lovrPassSetStencilTest(Pass* pass, CompareMode test, uint8_t value, uint8_t mask);
|
void lovrPassSetStencilTest(Pass* pass, CompareMode test, uint8_t value, uint8_t mask);
|
||||||
void lovrPassSetStencilWrite(Pass* pass, StencilAction actions[3], uint8_t value, uint8_t mask);
|
void lovrPassSetStencilWrite(Pass* pass, StencilAction actions[3], uint8_t value, uint8_t mask);
|
||||||
void lovrPassSetVertexFormat(Pass* pass, BufferField* fields, uint32_t count);
|
|
||||||
void lovrPassSetWinding(Pass* pass, Winding winding);
|
void lovrPassSetWinding(Pass* pass, Winding winding);
|
||||||
void lovrPassSetWireframe(Pass* pass, bool wireframe);
|
void lovrPassSetWireframe(Pass* pass, bool wireframe);
|
||||||
|
|
||||||
|
@ -614,7 +613,6 @@ void lovrPassMonkey(Pass* pass, float* transform);
|
||||||
void lovrPassDrawModel(Pass* pass, Model* model, float* transform, uint32_t node, bool recurse, uint32_t instances);
|
void lovrPassDrawModel(Pass* pass, Model* model, float* transform, uint32_t node, bool recurse, uint32_t instances);
|
||||||
void lovrPassDrawTexture(Pass* pass, Texture* texture, float* transform);
|
void lovrPassDrawTexture(Pass* pass, Texture* texture, float* transform);
|
||||||
void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transform, uint32_t start, uint32_t count, uint32_t instances, uint32_t base);
|
void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transform, uint32_t start, uint32_t count, uint32_t instances, uint32_t base);
|
||||||
void lovrPassMeshImmediate(Pass* pass, uint32_t vertexCount, void** vertices, BufferField** format, uint32_t indexCount, void** indices, float* transform);
|
|
||||||
void lovrPassMeshIndirect(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* indirect, uint32_t count, uint32_t offset, uint32_t stride);
|
void lovrPassMeshIndirect(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* indirect, uint32_t count, uint32_t offset, uint32_t stride);
|
||||||
|
|
||||||
uint32_t lovrPassBeginTally(Pass* pass);
|
uint32_t lovrPassBeginTally(Pass* pass);
|
||||||
|
|
Loading…
Reference in a new issue