Basic meshlet generation algorithm
This commit is contained in:
@@ -167,6 +167,10 @@ static constexpr bool useAsyncCompute = true;
|
||||
static constexpr bool waitIdleOnSubmit = true;
|
||||
static constexpr bool useMeshShading = true;
|
||||
static constexpr uint32 numFramesBuffered = 8;
|
||||
|
||||
// meshlet dimensions curated by NVIDIA
|
||||
static constexpr uint32 numVerticesPerMeshlet = 64;
|
||||
static constexpr uint32 numPrimitivesPerMeshlet = 126;
|
||||
double getCurrentFrameDelta();
|
||||
|
||||
enum class RenderPassType : uint8
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/List.h"
|
||||
#include "Initializer.h"
|
||||
#include "Buffer.h"
|
||||
#include "CRC.h"
|
||||
#include <functional>
|
||||
|
||||
|
||||
@@ -15,12 +15,4 @@ ShaderCompiler::~ShaderCompiler()
|
||||
|
||||
}
|
||||
|
||||
void ShaderCompiler::registerMaterial(PMaterial material)
|
||||
{
|
||||
for(auto& type : VertexInputType::getTypeList())
|
||||
{
|
||||
material->createShaders(graphics, Gfx::RenderPassType::DepthPrepass, type);
|
||||
material->createShaders(graphics, Gfx::RenderPassType::BasePass, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@ class ShaderCompiler
|
||||
public:
|
||||
ShaderCompiler(PGraphics graphics);
|
||||
~ShaderCompiler();
|
||||
void registerMaterial(PMaterial material);
|
||||
private:
|
||||
Array<PMaterial> pendingCompiles;
|
||||
PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(ShaderCompiler)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include "StaticMeshVertexData.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
extern List<VertexData*> vertexDataList;
|
||||
|
||||
StaticMeshVertexData::StaticMeshVertexData(Gfx::PGraphics graphics)
|
||||
: VertexData(graphics)
|
||||
, head(0)
|
||||
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024;
|
||||
|
||||
StaticMeshVertexData::StaticMeshVertexData()
|
||||
: head(0)
|
||||
, verticesAllocated(NUM_DEFAULT_ELEMENTS)
|
||||
{
|
||||
vertexDataList.add(this);
|
||||
}
|
||||
@@ -14,10 +17,120 @@ StaticMeshVertexData::StaticMeshVertexData(Gfx::PGraphics graphics)
|
||||
StaticMeshVertexData::~StaticMeshVertexData()
|
||||
{}
|
||||
|
||||
StaticMeshVertexData* Seele::StaticMeshVertexData::getInstance()
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
MeshId StaticMeshVertexData::allocateVertexData(uint64 numVertices)
|
||||
{
|
||||
MeshId res{idCounter++};
|
||||
MeshId res{ idCounter++ };
|
||||
meshOffsets[res] = head;
|
||||
head += numVertices;
|
||||
if (head > verticesAllocated)
|
||||
{
|
||||
ShaderBufferCreateInfo createInfo = {
|
||||
.resourceData = {
|
||||
.size = head * sizeof(Vector),
|
||||
},
|
||||
.stride = sizeof(Vector),
|
||||
.bDynamic = true,
|
||||
};
|
||||
positions = graphics->createShaderBuffer(createInfo);
|
||||
normals = graphics->createShaderBuffer(createInfo);
|
||||
tangents = graphics->createShaderBuffer(createInfo);
|
||||
biTangents = graphics->createShaderBuffer(createInfo);
|
||||
createInfo.resourceData.size = head * sizeof(Vector2);
|
||||
createInfo.stride = sizeof(Vector2);
|
||||
texCoords = graphics->createShaderBuffer(createInfo);
|
||||
}
|
||||
positionData.resize(head);
|
||||
texCoordsData.resize(head);
|
||||
normalData.resize(head);
|
||||
tangentData.resize(head);
|
||||
biTangentData.resize(head);
|
||||
return res;
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::loadPositions(MeshId id, const Array<Vector>& data)
|
||||
{
|
||||
uint64 offset = meshOffsets[id];
|
||||
assert(offset + data.size() < head);
|
||||
std::memcpy(positionData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::loadTexCoords(MeshId id, const Array<Vector2>& data)
|
||||
{
|
||||
uint64 offset = meshOffsets[id];
|
||||
assert(offset + data.size() < head);
|
||||
std::memcpy(texCoordsData.data() + offset, data.data(), data.size() * sizeof(Vector2));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::loadNormals(MeshId id, const Array<Vector>& data)
|
||||
{
|
||||
uint64 offset = meshOffsets[id];
|
||||
assert(offset + data.size() < head);
|
||||
std::memcpy(normalData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::loadTangents(MeshId id, const Array<Vector>& data)
|
||||
{
|
||||
uint64 offset = meshOffsets[id];
|
||||
assert(offset + data.size() < head);
|
||||
std::memcpy(tangentData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::loadBiTangents(MeshId id, const Array<Vector>& data)
|
||||
{
|
||||
uint64 offset = meshOffsets[id];
|
||||
assert(offset + data.size() < head);
|
||||
std::memcpy(biTangentData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::init(Gfx::PGraphics graphics)
|
||||
{
|
||||
VertexData::init(graphics);
|
||||
ShaderBufferCreateInfo createInfo = {
|
||||
.resourceData = {
|
||||
.size = NUM_DEFAULT_ELEMENTS * sizeof(Vector),
|
||||
},
|
||||
.stride = sizeof(Vector),
|
||||
.bDynamic = true,
|
||||
};
|
||||
positions = graphics->createShaderBuffer(createInfo);
|
||||
normals = graphics->createShaderBuffer(createInfo);
|
||||
tangents = graphics->createShaderBuffer(createInfo);
|
||||
biTangents = graphics->createShaderBuffer(createInfo);
|
||||
createInfo.resourceData.size = NUM_DEFAULT_ELEMENTS * sizeof(Vector2);
|
||||
createInfo.stride = sizeof(Vector2);
|
||||
texCoords = graphics->createShaderBuffer(createInfo);
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::updateBuffers()
|
||||
{
|
||||
positions->updateContents(BulkResourceData{
|
||||
.size = positionData.size() * sizeof(Vector),
|
||||
.data = (uint8*)positionData.data(),
|
||||
});
|
||||
texCoords->updateContents(BulkResourceData{
|
||||
.size = texCoordsData.size() * sizeof(Vector2),
|
||||
.data = (uint8*)texCoordsData.data(),
|
||||
});
|
||||
normals->updateContents(BulkResourceData{
|
||||
.size = normalData.size() * sizeof(Vector),
|
||||
.data = (uint8*)normalData.data(),
|
||||
});
|
||||
tangents->updateContents(BulkResourceData{
|
||||
.size = tangentData.size() * sizeof(Vector),
|
||||
.data = (uint8*)tangentData.data(),
|
||||
});
|
||||
biTangents->updateContents(BulkResourceData{
|
||||
.size = biTangentData.size() * sizeof(Vector),
|
||||
.data = (uint8*)biTangentData.data(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,26 +6,30 @@ namespace Seele
|
||||
class StaticMeshVertexData : public VertexData
|
||||
{
|
||||
public:
|
||||
StaticMeshVertexData(Gfx::PGraphics graphics);
|
||||
StaticMeshVertexData();
|
||||
virtual ~StaticMeshVertexData();
|
||||
static StaticMeshVertexData* getInstance();
|
||||
virtual MeshId allocateVertexData(uint64 numVertices) override;
|
||||
void loadPositions(MeshId id, const Array<Vector>& data);
|
||||
void loadTexCoords(MeshId id, const Array<Vector2>& data);
|
||||
void loadNormals(MeshId id, const Array<Vector>& data);
|
||||
void loadTangents(MeshId id, const Array<Vector>& data);
|
||||
void loadBiTangents(MeshId id, const Array<Vector>& data);
|
||||
void loadPositions(MeshId id, const Array<Vector>& data);
|
||||
void loadTexCoords(MeshId id, const Array<Vector2>& data);
|
||||
void loadNormals(MeshId id, const Array<Vector>& data);
|
||||
void loadTangents(MeshId id, const Array<Vector>& data);
|
||||
void loadBiTangents(MeshId id, const Array<Vector>& data);
|
||||
virtual void init(Gfx::PGraphics graphics) override;
|
||||
private:
|
||||
virtual void updateBuffers() override;
|
||||
Gfx::PShaderBuffer positions;
|
||||
Array<Vector> positionData;
|
||||
Array<Vector> positionData;
|
||||
Gfx::PShaderBuffer texCoords;
|
||||
Array<Vector2> texCoordsData;
|
||||
Array<Vector2> texCoordsData;
|
||||
Gfx::PShaderBuffer normals;
|
||||
Array<Vector> normalData;
|
||||
Array<Vector> normalData;
|
||||
Gfx::PShaderBuffer tangents;
|
||||
Array<Vector> tangentData;
|
||||
Array<Vector> tangentData;
|
||||
Gfx::PShaderBuffer biTangents;
|
||||
Array<Vector> biTangentData;
|
||||
Array<Vector> biTangentData;
|
||||
Map<MeshId, uint64_t> meshOffsets;
|
||||
uint64 head;
|
||||
uint64 head;
|
||||
uint64 verticesAllocated;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@ using namespace Seele;
|
||||
void VertexData::resetMeshData()
|
||||
{
|
||||
materialData.clear();
|
||||
if (dirty)
|
||||
{
|
||||
updateBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
void VertexData::updateMesh(const Component::Transform& transform, const Component::Mesh& mesh)
|
||||
@@ -24,6 +28,30 @@ void VertexData::updateMesh(const Component::Transform& transform, const Compone
|
||||
});
|
||||
}
|
||||
|
||||
void VertexData::loadMesh(MeshId id, Array<Meshlet> meshlets)
|
||||
{
|
||||
meshData[id].clear();
|
||||
uint32 head = 0;
|
||||
while (head < meshlets.size())
|
||||
{
|
||||
uint32 numMeshlets = std::min<uint32>(512, meshlets.size() - head);
|
||||
Array<MeshletDescription> desc(numMeshlets);
|
||||
for (uint32 i = 0; i < numMeshlets; ++i)
|
||||
{
|
||||
Meshlet& m = meshlets[head + i];
|
||||
|
||||
vertexIndices.resize()
|
||||
desc.add(MeshletDescription{
|
||||
.boundingBox = MeshletAABB(),
|
||||
.vertexCount = m.numVertices,
|
||||
.primitiveCount = m.numPrimitives,
|
||||
});
|
||||
}
|
||||
meshData[id].add();
|
||||
head += numMeshlets;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexData::createDescriptors()
|
||||
{
|
||||
for (const auto& [_, mat] : materialData)
|
||||
@@ -74,10 +102,9 @@ List<VertexData*> VertexData::getList()
|
||||
return vertexDataList;
|
||||
}
|
||||
|
||||
VertexData::VertexData(Gfx::PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
, idCounter(0)
|
||||
void Seele::VertexData::init(Gfx::PGraphics graphics)
|
||||
{
|
||||
this->graphics = graphics;
|
||||
instanceDataLayout = graphics->createDescriptorLayout("VertexDataInstanceLayout");
|
||||
instanceDataLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
if (Gfx::useMeshShading)
|
||||
@@ -96,3 +123,9 @@ VertexData::VertexData(Gfx::PGraphics graphics)
|
||||
}
|
||||
instanceDataLayout->create();
|
||||
}
|
||||
|
||||
VertexData::VertexData()
|
||||
: idCounter(0)
|
||||
, dirty(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -15,6 +15,17 @@ namespace Component
|
||||
struct MeshId
|
||||
{
|
||||
uint64 id;
|
||||
std::strong_ordering operator<=>(const MeshId& other) const
|
||||
{
|
||||
return id <=> other.id;
|
||||
}
|
||||
};
|
||||
struct Meshlet
|
||||
{
|
||||
uint32 uniqueVertices[Gfx::numVerticesPerMeshlet]; // unique vertiex indices in the vertex data
|
||||
uint8 primitiveLayout[Gfx::numPrimitivesPerMeshlet * 3]; // indices into the uniqueVertices array, only uint8 needed
|
||||
uint32 numVertices;
|
||||
uint32 numPrimitives;
|
||||
};
|
||||
class VertexData
|
||||
{
|
||||
@@ -44,9 +55,11 @@ public:
|
||||
{
|
||||
uint32 numMeshlets;
|
||||
uint32 meshletOffset;
|
||||
uint32 vertexOffset;
|
||||
};
|
||||
void resetMeshData();
|
||||
void updateMesh(const Component::Transform& transform, const Component::Mesh& mesh);
|
||||
void loadMesh(MeshId id, Array<Meshlet> meshlets);
|
||||
void createDescriptors();
|
||||
virtual MeshId allocateVertexData(uint64 numVertices) = 0;
|
||||
virtual void bindBuffers(Gfx::PRenderCommand command) = 0;
|
||||
@@ -57,7 +70,10 @@ public:
|
||||
const Map<std::string, MaterialData>& getMaterialData() const { return materialData; }
|
||||
const Array<MeshData>& getMeshData(MeshId id) { return meshData[id]; }
|
||||
static List<VertexData*> getList();
|
||||
virtual void init(Gfx::PGraphics graphics);
|
||||
protected:
|
||||
virtual void updateBuffers() = 0;
|
||||
VertexData();
|
||||
struct MeshletAABB
|
||||
{
|
||||
Vector min;
|
||||
@@ -65,24 +81,26 @@ protected:
|
||||
Vector max;
|
||||
float pad1;
|
||||
};
|
||||
struct MeshletData
|
||||
struct MeshletDescription
|
||||
{
|
||||
MeshletAABB boundingBox;
|
||||
uint32_t vertexCount;
|
||||
uint32_t primiticeCount;
|
||||
uint32_t primitiveCount;
|
||||
uint32_t vertexOffset;
|
||||
uint32_t primitiveOffset;
|
||||
};
|
||||
Map<std::string, MaterialData> materialData;
|
||||
Map<MeshId, Array<MeshData>> meshData;
|
||||
Array<MeshletData> meshlets;
|
||||
Gfx::PDescriptorLayout instanceDataLayout;
|
||||
Array<MeshletDescription> meshlets;
|
||||
Array<uint8> primitiveIndices;
|
||||
Array<uint32> vertexIndices;
|
||||
Gfx::PGraphics graphics;
|
||||
Gfx::PDescriptorLayout instanceDataLayout;
|
||||
// for mesh shading
|
||||
Gfx::PShaderBuffer meshletBuffer;
|
||||
// for legacy pipeline
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
VertexData(Gfx::PGraphics graphics);
|
||||
uint64 idCounter;
|
||||
bool dirty;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user