Trying new meshlet gen approach

This commit is contained in:
Dynamitos
2024-04-05 10:41:59 +02:00
parent 7eedaf61ba
commit 505e7d6547
19 changed files with 219 additions and 216 deletions
+80 -47
View File
@@ -5,62 +5,95 @@
using namespace Seele;
struct Triangle
{
StaticArray<uint32, 3> indices;
};
int findIndex(Meshlet& current, uint32 index)
{
for (uint32 i = 0; i < current.numVertices; ++i)
{
if (current.uniqueVertices[i] == index)
{
return i;
}
}
if (current.numVertices == Gfx::numVerticesPerMeshlet)
{
return -1;
}
current.uniqueVertices[current.numVertices] = index;
return current.numVertices++;
}
void completeMeshlet(Array<Meshlet>& meshlets, Meshlet& current)
{
meshlets.add(current);
current = {
.numVertices = 0,
.numPrimitives = 0,
};
}
void addTriangle(Array<Meshlet>& meshlets, Meshlet& current, Triangle tri)
{
int f1 = findIndex(current, tri.indices[0]);
int f2 = findIndex(current, tri.indices[1]);
int f3 = findIndex(current, tri.indices[2]);
if (f1 == -1 || f2 == -1 || f3 == -1)
{
completeMeshlet(meshlets, current);
f1 = findIndex(current, tri.indices[0]);
f2 = findIndex(current, tri.indices[1]);
f3 = findIndex(current, tri.indices[2]);
}
current.primitiveLayout[current.numPrimitives * 3 + 0] = uint8(f1);
current.primitiveLayout[current.numPrimitives * 3 + 1] = uint8(f2);
current.primitiveLayout[current.numPrimitives * 3 + 2] = uint8(f3);
current.numPrimitives++;
if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet)
{
completeMeshlet(meshlets, current);
}
}
void Meshlet::build(const Array<Vector>& positions, const Array<uint32>& indices, Array<Meshlet>& meshlets)
{
Meshlet current = {
.numVertices = 0,
.numPrimitives = 0,
};
auto findIndex = [&current](uint32 index) -> int {
for (uint32 i = 0; i < current.numVertices; ++i)
Array<Triangle> triangles(indices.size() / 3);
for (size_t i = 0; i < triangles.size(); ++i)
{
triangles[i].indices[0] = indices[i * 3 + 0];
triangles[i].indices[1] = indices[i * 3 + 1];
triangles[i].indices[2] = indices[i * 3 + 2];
}
while (!triangles.empty())
{
uint32 best = 0;
float lowestSurface = std::numeric_limits<float>::max();
AABB newAABB;
for (uint32 i = 0; i < triangles.size(); ++i)
{
if (current.uniqueVertices[i] == index)
AABB adjusted = current.boundingBox;
adjusted.adjust(positions[triangles[i].indices[0]]);
adjusted.adjust(positions[triangles[i].indices[1]]);
adjusted.adjust(positions[triangles[i].indices[2]]);
float surface = adjusted.surfaceArea();
if (surface < lowestSurface)
{
return i;
lowestSurface = surface;
best = i;
newAABB = adjusted;
}
}
if (current.numVertices == Gfx::numVerticesPerMeshlet)
{
return -1;
}
current.uniqueVertices[current.numVertices] = index;
return current.numVertices++;
};
auto completeMeshlet = [&positions, &meshlets, &current]() {
for (uint32 i = 0; i < current.numVertices; ++i)
{
current.boundingBox.adjust(positions[current.uniqueVertices[i]]);
}
meshlets.add(current);
current = {
.numVertices = 0,
.numPrimitives = 0,
};
};
for (size_t faceIndex = 0; faceIndex < indices.size() / 3; ++faceIndex)
{
int f1 = findIndex(indices[faceIndex * 3 + 0]);
int f2 = findIndex(indices[faceIndex * 3 + 1]);
int f3 = findIndex(indices[faceIndex * 3 + 2]);
if (f1 == -1 || f2 == -1 || f3 == -1)
{
completeMeshlet();
f1 = findIndex(indices[faceIndex * 3 + 0]);
f2 = findIndex(indices[faceIndex * 3 + 1]);
f3 = findIndex(indices[faceIndex * 3 + 2]);
}
current.primitiveLayout[current.numPrimitives * 3 + 0] = uint8(f1);
current.primitiveLayout[current.numPrimitives * 3 + 1] = uint8(f2);
current.primitiveLayout[current.numPrimitives * 3 + 2] = uint8(f3);
current.numPrimitives++;
if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet)
{
completeMeshlet();
}
}
if (current.numVertices > 0)
{
completeMeshlet();
current.boundingBox = newAABB;
addTriangle(meshlets, current, triangles[best]);
triangles.removeAt(best);
}
}
+1 -1
View File
@@ -194,7 +194,7 @@ void BasePass::publishOutputs()
void BasePass::createRenderPass()
{
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR);
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
@@ -177,6 +177,14 @@ void DepthPrepass::createRenderPass()
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
},
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
}
};
renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport);
+37 -76
View File
@@ -3,93 +3,54 @@
namespace Seele
{
template<typename... RenderPasses>
class RenderGraph;
template<>
class RenderGraph<>
class RenderGraph
{
public:
RenderGraph(PRenderGraphResources) {}
void updatePassData() {}
protected:
void setViewport(Gfx::PViewport) {}
void createRenderPass() {}
void beginFrame(const Component::Camera&) {}
void render() {}
void endFrame() {}
};
template<typename This, typename... Rest>
class RenderGraph<This, Rest...> : private RenderGraph<Rest...>
{
public:
RenderGraph(PRenderGraphResources resources, This pass, Rest... rest)
: RenderGraph<Rest...>(resources, std::move(rest)...)
, resources(resources)
, rp(std::move(pass))
RenderGraph()
{
rp.setResources(resources);
res = new RenderGraphResources();
}
template<typename PassData, typename... OtherData>
void updatePassData(PassData passData, OtherData... otherData)
{
rp.updateViewFrame(std::move(passData));
RenderGraph<Rest...>::updatePassData(otherData...);
void addPass(ORenderPass pass)
{
pass->setResources(res);
passes.add(std::move(pass));
}
void updateViewport(Gfx::PViewport viewport)
void setViewport(Gfx::PViewport viewport)
{
setViewport(viewport);
createRenderPass();
for (auto& pass : passes)
{
pass->setViewport(viewport);
}
}
void createRenderPass()
{
for (auto& pass : passes)
{
pass->publishOutputs();
}
for (auto& pass : passes)
{
pass->createRenderPass();
}
}
void render(const Component::Camera& cam)
{
beginFrame(cam);
render();
endFrame();
}
protected:
void setViewport(Gfx::PViewport viewport)
{
rp.setViewport(viewport);
RenderGraph<Rest...>::setViewport(viewport);
}
void createRenderPass()
{
rp.createRenderPass();
RenderGraph<Rest...>::createRenderPass();
}
void beginFrame(const Component::Camera& cam)
{
rp.beginFrame(cam);
RenderGraph<Rest...>::beginFrame(cam);
}
void render()
{
rp.render();
RenderGraph<Rest...>::render();
}
void endFrame()
{
rp.endFrame();
RenderGraph<Rest...>::endFrame();
for (auto& pass : passes)
{
pass->beginFrame(cam);
}
for (auto& pass : passes)
{
pass->render();
}
for (auto& pass : passes)
{
pass->endFrame();
}
}
private:
PRenderGraphResources resources;
This rp;
};
class RenderGraphBuilder
{
public:
template<typename... RenderPasses>
static RenderGraph<RenderPasses...> build(RenderPasses... renderPasses)
{
PRenderGraphResources resources = new RenderGraphResources();
return RenderGraph<RenderPasses...>(resources, std::move(renderPasses)...);
}
private:
RenderGraphBuilder() = delete;
PRenderGraphResources res;
List<ORenderPass> passes;
};
} // namespace Seele
@@ -44,6 +44,7 @@ protected:
Gfx::PViewport viewport;
PScene scene;
};
DEFINE_REF(RenderPass)
template<typename RP>
concept RenderPassType = std::derived_from<RP, RenderPass>;
+8 -8
View File
@@ -80,17 +80,17 @@ public:
constexpr void setStencilStoreOp(SeAttachmentStoreOp val) { stencilStoreOp = val; }
constexpr void setInitialLayout(SeImageLayout val) { initialLayout = val; }
constexpr void setFinalLayout(SeImageLayout val) { finalLayout = val; }
SeClearValue clear;
SeColorComponentFlags componentFlags;
SeClearValue clear = { 0 };
SeColorComponentFlags componentFlags = 0;
protected:
PTexture2D texture = nullptr;
PViewport viewport = nullptr;
SeImageLayout initialLayout;
SeImageLayout finalLayout;
SeAttachmentLoadOp loadOp;
SeAttachmentStoreOp storeOp;
SeAttachmentLoadOp stencilLoadOp;
SeAttachmentStoreOp stencilStoreOp;
SeImageLayout initialLayout = SE_IMAGE_LAYOUT_BEGIN_RANGE;
SeImageLayout finalLayout = SE_IMAGE_LAYOUT_BEGIN_RANGE;
SeAttachmentLoadOp loadOp = SE_ATTACHMENT_LOAD_OP_BEGIN_RANGE;
SeAttachmentStoreOp storeOp = SE_ATTACHMENT_STORE_OP_BEGIN_RANGE;
SeAttachmentLoadOp stencilLoadOp = SE_ATTACHMENT_LOAD_OP_BEGIN_RANGE;
SeAttachmentStoreOp stencilStoreOp = SE_ATTACHMENT_STORE_OP_BEGIN_RANGE;
};
struct RenderTargetLayout