Trying new meshlet gen approach
This commit is contained in:
@@ -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 = [¤t](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, ¤t]() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user