2023-10-24 15:01:09 +02:00
|
|
|
#include "VertexData.h"
|
2023-10-31 23:44:46 +01:00
|
|
|
#include "Graphics/Enums.h"
|
|
|
|
|
#include "Graphics/Initializer.h"
|
2023-10-24 15:01:09 +02:00
|
|
|
#include "Material/Material.h"
|
|
|
|
|
#include "Graphics/Graphics.h"
|
2023-10-26 18:37:29 +02:00
|
|
|
#include "Graphics/Descriptor.h"
|
|
|
|
|
#include "Component/Mesh.h"
|
2023-11-15 17:42:57 +01:00
|
|
|
#include "Graphics/Shader.h"
|
2023-11-22 13:18:54 +01:00
|
|
|
#include <set>
|
2023-10-24 15:01:09 +02:00
|
|
|
|
|
|
|
|
using namespace Seele;
|
|
|
|
|
|
2023-11-30 11:51:53 +01:00
|
|
|
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024;
|
2023-10-31 17:55:30 +01:00
|
|
|
|
2023-10-24 15:01:09 +02:00
|
|
|
void VertexData::resetMeshData()
|
|
|
|
|
{
|
2023-11-17 18:46:37 +01:00
|
|
|
for (auto& [_, mat] : materialData)
|
|
|
|
|
{
|
|
|
|
|
mat.material->getDescriptorLayout()->reset();
|
|
|
|
|
}
|
2023-11-26 09:40:48 +01:00
|
|
|
materialData.clear();
|
2023-10-31 16:16:23 +01:00
|
|
|
if (dirty)
|
|
|
|
|
{
|
|
|
|
|
updateBuffers();
|
2023-11-08 23:27:21 +01:00
|
|
|
dirty = false;
|
2023-10-31 16:16:23 +01:00
|
|
|
}
|
2023-10-24 15:01:09 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-26 09:40:48 +01:00
|
|
|
void VertexData::updateMesh(PMesh mesh, Component::Transform& transform)
|
2023-10-24 15:01:09 +02:00
|
|
|
{
|
2023-11-06 14:47:21 +01:00
|
|
|
PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial();
|
2023-10-24 15:01:09 +02:00
|
|
|
MaterialData& matData = materialData[mat->getName()];
|
2023-11-08 23:27:21 +01:00
|
|
|
matData.material = mat;
|
2023-11-06 14:47:21 +01:00
|
|
|
MaterialInstanceData& matInstanceData = matData.instances[mesh->referencedMaterial->getHandle()->getId()];
|
2023-11-26 11:27:39 +01:00
|
|
|
for (auto& data : meshData[mesh->id])
|
|
|
|
|
{
|
|
|
|
|
matInstanceData.meshes.add(MeshInstanceData{
|
|
|
|
|
.instance = InstanceData {
|
|
|
|
|
.transformMatrix = transform.toMatrix(),
|
|
|
|
|
},
|
|
|
|
|
.data = data
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-11-11 22:39:17 +01:00
|
|
|
matInstanceData.materialInstance = mesh->referencedMaterial->getHandle();
|
2023-10-24 15:01:09 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-26 09:40:48 +01:00
|
|
|
void VertexData::createDescriptors()
|
2023-11-22 13:18:54 +01:00
|
|
|
{
|
|
|
|
|
instanceDataLayout->reset();
|
|
|
|
|
for (const auto& [_, mat] : materialData)
|
|
|
|
|
{
|
|
|
|
|
for (auto& [_, matInst] : mat.instances)
|
|
|
|
|
{
|
|
|
|
|
Array<InstanceData> instanceData;
|
2023-11-26 09:40:48 +01:00
|
|
|
Array<MeshData> meshes;
|
2023-11-22 13:18:54 +01:00
|
|
|
for (auto& inst : matInst.meshes)
|
|
|
|
|
{
|
2023-11-26 11:27:39 +01:00
|
|
|
meshes.add(inst.data);
|
|
|
|
|
instanceData.add(inst.instance);
|
2023-11-22 13:18:54 +01:00
|
|
|
}
|
|
|
|
|
matInst.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
|
|
|
|
.sourceData = {
|
|
|
|
|
.size = sizeof(InstanceData) * instanceData.size(),
|
|
|
|
|
.data = (uint8*)instanceData.data(),
|
|
|
|
|
},
|
|
|
|
|
.numElements = instanceData.size(),
|
|
|
|
|
.dynamic = false,
|
|
|
|
|
});
|
|
|
|
|
matInst.descriptorSet = instanceDataLayout->allocateDescriptorSet();
|
2023-11-26 09:40:48 +01:00
|
|
|
|
|
|
|
|
matInst.meshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
2023-11-10 19:18:09 +01:00
|
|
|
.sourceData = {
|
2023-11-26 09:40:48 +01:00
|
|
|
.size = sizeof(MeshData) * meshes.size(),
|
|
|
|
|
.data = (uint8*)meshes.data(),
|
2023-11-10 19:18:09 +01:00
|
|
|
},
|
2023-11-26 09:40:48 +01:00
|
|
|
.numElements = meshes.size(),
|
2023-11-15 17:42:57 +01:00
|
|
|
.dynamic = false,
|
2023-11-10 19:18:09 +01:00
|
|
|
});
|
2023-11-26 11:27:39 +01:00
|
|
|
matInst.descriptorSet->updateBuffer(0, matInst.instanceBuffer);
|
2023-11-26 09:40:48 +01:00
|
|
|
matInst.descriptorSet->updateBuffer(1, matInst.meshDataBuffer);
|
|
|
|
|
matInst.descriptorSet->updateBuffer(2, meshletBuffer);
|
|
|
|
|
matInst.descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
|
|
|
|
|
matInst.descriptorSet->updateBuffer(4, vertexIndicesBuffer);
|
|
|
|
|
|
2023-11-10 19:18:09 +01:00
|
|
|
matInst.descriptorSet->writeChanges();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-26 11:27:39 +01:00
|
|
|
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets)
|
2023-10-31 16:16:23 +01:00
|
|
|
{
|
2023-11-22 13:18:54 +01:00
|
|
|
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
|
|
|
|
|
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
|
2023-11-26 11:27:39 +01:00
|
|
|
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
|
2023-10-31 17:55:30 +01:00
|
|
|
uint32 currentMesh = 0;
|
|
|
|
|
while (currentMesh < loadedMeshlets.size())
|
2023-10-31 16:16:23 +01:00
|
|
|
{
|
2023-10-31 17:55:30 +01:00
|
|
|
uint32 numMeshlets = std::min<uint32>(512, loadedMeshlets.size() - currentMesh);
|
|
|
|
|
uint32 meshletOffset = meshlets.size();
|
2023-12-11 14:45:37 +01:00
|
|
|
AABB meshAABB;
|
2023-10-31 16:16:23 +01:00
|
|
|
for (uint32 i = 0; i < numMeshlets; ++i)
|
|
|
|
|
{
|
2023-10-31 17:55:30 +01:00
|
|
|
Meshlet& m = loadedMeshlets[currentMesh + i];
|
2023-12-11 14:45:37 +01:00
|
|
|
meshAABB = meshAABB.combine(m.boundingBox);
|
2023-10-31 17:55:30 +01:00
|
|
|
uint32 vertexOffset = vertexIndices.size();
|
|
|
|
|
vertexIndices.resize(vertexOffset + m.numVertices);
|
2023-11-27 22:50:37 +01:00
|
|
|
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
|
2023-10-31 17:55:30 +01:00
|
|
|
uint32 primitiveOffset = primitiveIndices.size();
|
|
|
|
|
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
|
2023-11-27 22:50:37 +01:00
|
|
|
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
|
2023-10-31 17:55:30 +01:00
|
|
|
meshlets.add(MeshletDescription{
|
2023-12-11 14:45:37 +01:00
|
|
|
.boundingBox = m.boundingBox,
|
2023-10-31 16:16:23 +01:00
|
|
|
.vertexCount = m.numVertices,
|
|
|
|
|
.primitiveCount = m.numPrimitives,
|
2023-10-31 17:55:30 +01:00
|
|
|
.vertexOffset = vertexOffset,
|
|
|
|
|
.primitiveOffset = primitiveOffset,
|
2023-10-31 16:16:23 +01:00
|
|
|
});
|
|
|
|
|
}
|
2023-10-31 17:55:30 +01:00
|
|
|
meshData[id].add(MeshData{
|
2023-12-11 14:45:37 +01:00
|
|
|
.boundingBox = meshAABB,
|
2023-10-31 17:55:30 +01:00
|
|
|
.numMeshlets = numMeshlets,
|
|
|
|
|
.meshletOffset = meshletOffset,
|
|
|
|
|
.indicesOffset = static_cast<uint32>(meshOffsets[id]),
|
2023-11-10 19:18:09 +01:00
|
|
|
});
|
2023-10-31 17:55:30 +01:00
|
|
|
currentMesh += numMeshlets;
|
2023-10-31 16:16:23 +01:00
|
|
|
}
|
2023-11-26 11:27:39 +01:00
|
|
|
meshData[id][0].firstIndex = indices.size();
|
|
|
|
|
meshData[id][0].numIndices = loadedIndices.size();
|
|
|
|
|
indices.resize(indices.size() + loadedIndices.size());
|
|
|
|
|
std::memcpy(indices.data() + meshData[id][0].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
|
|
|
|
|
indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
|
|
|
|
|
.sourceData = {
|
|
|
|
|
.size = sizeof(uint32) * indices.size(),
|
|
|
|
|
.data = (uint8*)indices.data(),
|
|
|
|
|
},
|
|
|
|
|
.indexType = Gfx::SE_INDEX_TYPE_UINT32,
|
|
|
|
|
});
|
2023-11-10 19:18:09 +01:00
|
|
|
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
2023-11-01 23:12:30 +01:00
|
|
|
.sourceData = {
|
2023-10-31 23:44:46 +01:00
|
|
|
.size = sizeof(MeshletDescription) * meshlets.size(),
|
|
|
|
|
.data = (uint8*)meshlets.data()
|
|
|
|
|
},
|
2023-11-15 17:42:57 +01:00
|
|
|
.numElements = meshlets.size(),
|
2023-11-26 11:27:39 +01:00
|
|
|
.dynamic = false,
|
2023-11-15 17:42:57 +01:00
|
|
|
});
|
2023-11-10 19:18:09 +01:00
|
|
|
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
2023-11-01 23:12:30 +01:00
|
|
|
.sourceData = {
|
2023-10-31 23:44:46 +01:00
|
|
|
.size = sizeof(uint32) * vertexIndices.size(),
|
|
|
|
|
.data = (uint8*)vertexIndices.data(),
|
|
|
|
|
},
|
2023-11-15 17:42:57 +01:00
|
|
|
.numElements = vertexIndices.size(),
|
2023-11-26 11:27:39 +01:00
|
|
|
.dynamic = false,
|
2023-11-15 17:42:57 +01:00
|
|
|
});
|
2023-11-10 19:18:09 +01:00
|
|
|
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
2023-11-01 23:12:30 +01:00
|
|
|
.sourceData = {
|
2023-10-31 23:44:46 +01:00
|
|
|
.size = sizeof(uint8) * primitiveIndices.size(),
|
|
|
|
|
.data = (uint8*)primitiveIndices.data(),
|
|
|
|
|
},
|
2023-11-15 17:42:57 +01:00
|
|
|
.numElements = primitiveIndices.size(),
|
2023-11-26 11:27:39 +01:00
|
|
|
.dynamic = false,
|
2023-11-15 17:42:57 +01:00
|
|
|
});
|
2023-10-24 15:01:09 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-31 17:55:30 +01:00
|
|
|
MeshId VertexData::allocateVertexData(uint64 numVertices)
|
|
|
|
|
{
|
|
|
|
|
MeshId res{ idCounter++ };
|
|
|
|
|
meshOffsets[res] = head;
|
2023-11-09 22:15:51 +01:00
|
|
|
meshVertexCounts[res] = numVertices;
|
2023-10-31 17:55:30 +01:00
|
|
|
head += numVertices;
|
|
|
|
|
if (head > verticesAllocated)
|
|
|
|
|
{
|
2023-11-30 11:51:53 +01:00
|
|
|
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
|
2023-10-31 17:55:30 +01:00
|
|
|
resizeBuffers();
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-09 22:15:51 +01:00
|
|
|
uint64 VertexData::getMeshOffset(MeshId id)
|
2023-11-06 22:24:40 +01:00
|
|
|
{
|
|
|
|
|
return meshOffsets[id];
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-09 22:15:51 +01:00
|
|
|
uint64 VertexData::getMeshVertexCount(MeshId id)
|
|
|
|
|
{
|
|
|
|
|
return meshVertexCounts[id];
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 15:01:09 +02:00
|
|
|
List<VertexData*> vertexDataList;
|
|
|
|
|
|
|
|
|
|
List<VertexData*> VertexData::getList()
|
|
|
|
|
{
|
|
|
|
|
return vertexDataList;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-01 13:38:49 +01:00
|
|
|
VertexData* Seele::VertexData::findByTypeName(std::string name)
|
|
|
|
|
{
|
|
|
|
|
for (auto vd : vertexDataList)
|
|
|
|
|
{
|
|
|
|
|
if (vd->getTypeName() == name)
|
|
|
|
|
{
|
|
|
|
|
return vd;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-10 22:27:59 +01:00
|
|
|
void Seele::VertexData::init(Gfx::PGraphics _graphics)
|
2023-10-24 15:01:09 +02:00
|
|
|
{
|
2023-12-10 22:27:59 +01:00
|
|
|
graphics = _graphics;
|
2023-10-31 17:55:30 +01:00
|
|
|
verticesAllocated = NUM_DEFAULT_ELEMENTS;
|
2023-10-24 15:01:09 +02:00
|
|
|
instanceDataLayout = graphics->createDescriptorLayout("VertexDataInstanceLayout");
|
|
|
|
|
instanceDataLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
2023-11-26 09:40:48 +01:00
|
|
|
|
|
|
|
|
// meshData
|
|
|
|
|
instanceDataLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
|
|
|
|
// meshletData
|
|
|
|
|
instanceDataLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
|
|
|
|
// primitiveIndices
|
|
|
|
|
instanceDataLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
|
|
|
|
// vetexIndices
|
|
|
|
|
instanceDataLayout->addDescriptorBinding(4, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
|
|
|
|
|
2023-10-24 15:01:09 +02:00
|
|
|
instanceDataLayout->create();
|
2023-10-31 17:55:30 +01:00
|
|
|
resizeBuffers();
|
2023-11-05 10:36:01 +01:00
|
|
|
graphics->getShaderCompiler()->registerVertexData(this);
|
2023-10-29 09:20:23 +01:00
|
|
|
}
|
2023-10-31 16:16:23 +01:00
|
|
|
|
|
|
|
|
VertexData::VertexData()
|
|
|
|
|
: idCounter(0)
|
2023-11-05 10:36:01 +01:00
|
|
|
, head(0)
|
|
|
|
|
, verticesAllocated(0)
|
2023-11-06 14:47:21 +01:00
|
|
|
, dirty(false)
|
2023-10-31 16:16:23 +01:00
|
|
|
{
|
|
|
|
|
}
|
2023-11-01 13:38:49 +01:00
|
|
|
|
2023-12-11 14:45:37 +01:00
|
|
|
void Meshlet::build(const Array<Vector>& positions, const Array<uint32>& indices, Array<Meshlet>& meshlets)
|
2023-11-22 13:18:54 +01:00
|
|
|
{
|
|
|
|
|
std::set<uint32> uniqueVertices;
|
|
|
|
|
Meshlet current = {
|
|
|
|
|
.numVertices = 0,
|
|
|
|
|
.numPrimitives = 0,
|
|
|
|
|
};
|
2023-12-11 14:45:37 +01:00
|
|
|
auto insertAndGetIndex = [&positions, &uniqueVertices, ¤t](uint32 index) -> int8_t
|
2023-11-22 13:18:54 +01:00
|
|
|
{
|
|
|
|
|
auto [it, inserted] = uniqueVertices.insert(index);
|
|
|
|
|
if (inserted)
|
|
|
|
|
{
|
|
|
|
|
if (current.numVertices == Gfx::numVerticesPerMeshlet)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
current.uniqueVertices[current.numVertices] = index;
|
2023-12-11 14:45:37 +01:00
|
|
|
current.boundingBox.adjust(positions[index]);
|
2023-11-22 13:18:54 +01:00
|
|
|
return current.numVertices++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (uint32 i = 0; i < current.numVertices; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (current.uniqueVertices[i] == index)
|
|
|
|
|
{
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-26 11:27:39 +01:00
|
|
|
// it could be in unique vertices but not in meshlet vertices
|
|
|
|
|
return -1;
|
2023-11-22 13:18:54 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
auto completeMeshlet = [&meshlets, ¤t, &uniqueVertices]() {
|
|
|
|
|
meshlets.add(current);
|
|
|
|
|
current = {
|
|
|
|
|
.numVertices = 0,
|
|
|
|
|
.numPrimitives = 0,
|
|
|
|
|
};
|
|
|
|
|
uniqueVertices.clear();
|
|
|
|
|
};
|
|
|
|
|
for (size_t faceIndex = 0; faceIndex < indices.size() / 3; ++faceIndex)
|
|
|
|
|
{
|
|
|
|
|
auto i1 = insertAndGetIndex(indices[faceIndex * 3 + 0]);
|
|
|
|
|
auto i2 = insertAndGetIndex(indices[faceIndex * 3 + 1]);
|
|
|
|
|
auto i3 = insertAndGetIndex(indices[faceIndex * 3 + 2]);
|
|
|
|
|
if (i1 == -1 || i2 == -1 || i3 == -1)
|
|
|
|
|
{
|
|
|
|
|
completeMeshlet();
|
|
|
|
|
i1 = insertAndGetIndex(indices[faceIndex * 3 + 0]);
|
|
|
|
|
i2 = insertAndGetIndex(indices[faceIndex * 3 + 1]);
|
|
|
|
|
i3 = insertAndGetIndex(indices[faceIndex * 3 + 2]);
|
|
|
|
|
}
|
|
|
|
|
current.primitiveLayout[current.numPrimitives * 3 + 0] = i1;
|
|
|
|
|
current.primitiveLayout[current.numPrimitives * 3 + 1] = i2;
|
|
|
|
|
current.primitiveLayout[current.numPrimitives * 3 + 2] = i3;
|
|
|
|
|
current.numPrimitives++;
|
|
|
|
|
if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet)
|
|
|
|
|
{
|
|
|
|
|
completeMeshlet();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!uniqueVertices.empty())
|
|
|
|
|
{
|
|
|
|
|
completeMeshlet();
|
|
|
|
|
}
|
|
|
|
|
}
|