From 3d83d0fcfe68e1aa5437e7e557ac2ff214f9a0f6 Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 9 Jun 2022 23:38:33 -0700 Subject: [PATCH] Pass:multimesh; IT'S ALIVE --- src/api/l_graphics_pass.c | 13 +++++++++ src/modules/graphics/graphics.c | 50 +++++++++++++++++++++++---------- src/modules/graphics/graphics.h | 1 + 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/api/l_graphics_pass.c b/src/api/l_graphics_pass.c index 84c63e9d..7b7eaa17 100644 --- a/src/api/l_graphics_pass.c +++ b/src/api/l_graphics_pass.c @@ -519,6 +519,18 @@ static int l_lovrPassMesh(lua_State* L) { return 0; } +static int l_lovrPassMultimesh(lua_State* L) { + Pass* pass = luax_checktype(L, 1, Pass); + Buffer* vertices = !lua_toboolean(L, 2) ? NULL : luax_totype(L, 2, Buffer); + Buffer* indices = luax_totype(L, 3, Buffer); + Buffer* draws = luax_checktype(L, 4, Buffer); + uint32_t count = luax_optu32(L, 5, 1); + uint32_t offset = luax_optu32(L, 6, 0); + uint32_t stride = luax_optu32(L, 7, 0); + lovrPassMultimesh(pass, vertices, indices, draws, count, offset, stride); + return 0; +} + static int l_lovrPassCompute(lua_State* L) { Pass* pass = luax_checktype(L, 1, Pass); Buffer* buffer = luax_totype(L, 2, Buffer); @@ -720,6 +732,7 @@ const luaL_Reg lovrPass[] = { { "box", l_lovrPassBox }, { "circle", l_lovrPassCircle }, { "mesh", l_lovrPassMesh }, + { "multimesh", l_lovrPassMultimesh }, { "compute", l_lovrPassCompute }, diff --git a/src/modules/graphics/graphics.c b/src/modules/graphics/graphics.c index 07ddeb0e..f5b3aad8 100644 --- a/src/modules/graphics/graphics.c +++ b/src/modules/graphics/graphics.c @@ -195,8 +195,6 @@ typedef struct { uint32_t count; uint32_t instances; uint32_t base; - Buffer* indirect; - uint32_t offset; } Draw; typedef struct { @@ -2154,25 +2152,15 @@ static void lovrPassDraw(Pass* pass, Draw* draw) { flushBuiltins(pass, draw, shader); flushBuffers(pass, draw); - bool indexed = draw->index.buffer || draw->index.count > 0; uint32_t defaultCount = draw->index.count > 0 ? draw->index.count : draw->vertex.count; uint32_t count = draw->count > 0 ? draw->count : defaultCount; uint32_t instances = MAX(draw->instances, 1); uint32_t id = pass->drawCount & 0xff; - if (draw->indirect) { - trackBuffer(pass, draw->indirect, GPU_PHASE_INDIRECT, GPU_CACHE_INDIRECT); - if (indexed) { - gpu_draw_indirect_indexed(pass->stream, draw->indirect->gpu, draw->offset, count); - } else { - gpu_draw_indirect(pass->stream, draw->indirect->gpu, draw->offset, count); - } + if (draw->index.buffer || draw->index.count > 0) { + gpu_draw_indexed(pass->stream, count, instances, draw->start, draw->base, id); } else { - if (indexed) { - gpu_draw_indexed(pass->stream, count, instances, draw->start, draw->base, id); - } else { - gpu_draw(pass->stream, count, instances, draw->start, id); - } + gpu_draw(pass->stream, count, instances, draw->start, id); } pass->drawCount++; @@ -2360,6 +2348,38 @@ void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transfor }); } +void lovrPassMultimesh(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* draws, uint32_t count, uint32_t offset, uint32_t stride) { + lovrCheck(pass->info.type == PASS_RENDER, "This function can only be called on a render pass"); + lovrCheck(offset % 4 == 0, "Multimesh draw buffer offset must be a multiple of 4"); + uint32_t commandSize = indices ? 20 : 16; + stride = stride ? stride : commandSize; + uint32_t totalSize = stride * (count - 1) + commandSize; + lovrCheck(offset + totalSize < draws->size, "Multimesh draw range exceeds size of draw buffer"); + + Draw draw = (Draw) { + .mode = pass->pipeline->drawMode, + .vertex.buffer = vertices, + .index.buffer = indices + }; + + Shader* shader = pass->pipeline->shader; + lovrCheck(shader, "A custom Shader must be bound to draw a multimesh"); + + flushPipeline(pass, &draw, shader); + flushConstants(pass, shader); + flushBindings(pass, shader); + flushBuiltins(pass, &draw, shader); + flushBuffers(pass, &draw); + + if (indices) { + gpu_draw_indirect_indexed(pass->stream, draws->gpu, offset, count, stride); + } else { + gpu_draw_indirect(pass->stream, draws->gpu, offset, count, stride); + } + + trackBuffer(pass, draws, GPU_PHASE_INDIRECT, GPU_CACHE_INDIRECT); +} + void lovrPassCompute(Pass* pass, uint32_t x, uint32_t y, uint32_t z, Buffer* indirect, uint32_t offset) { lovrCheck(pass->info.type == PASS_COMPUTE, "This function can only be called on a compute pass"); diff --git a/src/modules/graphics/graphics.h b/src/modules/graphics/graphics.h index 98d0da27..39dd44bc 100644 --- a/src/modules/graphics/graphics.h +++ b/src/modules/graphics/graphics.h @@ -406,6 +406,7 @@ void lovrPassPlane(Pass* pass, float* transform, uint32_t cols, uint32_t rows); void lovrPassBox(Pass* pass, float* transform); void lovrPassCircle(Pass* pass, float* transform, float angle1, float angle2, uint32_t segments); void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transform, uint32_t start, uint32_t count, uint32_t instances); +void lovrPassMultimesh(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* indirect, uint32_t count, uint32_t offset, uint32_t stride); void lovrPassCompute(Pass* pass, uint32_t x, uint32_t y, uint32_t z, Buffer* indirect, uint32_t offset); void lovrPassClearBuffer(Pass* pass, Buffer* buffer, uint32_t offset, uint32_t extent); void lovrPassClearTexture(Pass* pass, Texture* texture, float value[4], uint32_t layer, uint32_t layerCount, uint32_t level, uint32_t levelCount);