VertexData refactor

This commit is contained in:
Dynamitos
2025-04-14 22:26:33 +02:00
parent d0899355c5
commit 47360714a5
10 changed files with 76 additions and 63 deletions
+1 -1
+7 -5
View File
@@ -1,14 +1,16 @@
#pragma once #pragma once
#include "Math/AABB.h" #include "Math/AABB.h"
namespace Seele { namespace Seele {
struct PoolRange {
uint32 offset;
uint32 size;
};
struct MeshData { struct MeshData {
AABB bounding; AABB bounding;
uint32 numMeshlets = 0; PoolRange meshletRange;
uint32 meshletOffset = 0;
// offset into the global index buffer // offset into the global index buffer
uint32 firstIndex = 0; PoolRange indicesRange;
// number of indices in the global index buffer
uint32 numIndices = 0;
}; };
struct InstanceData { struct InstanceData {
Matrix4 transformMatrix; Matrix4 transformMatrix;
+2 -2
View File
@@ -232,8 +232,8 @@ void BasePass::render() {
command->bindIndexBuffer(vertexData->getIndexBuffer()); command->bindIndexBuffer(vertexData->getIndexBuffer());
for (const auto& meshData : drawCall.instanceMeshData) { for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset // all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletOffset), 0); vertexData->getIndicesOffset(meshData.meshletRange.offset), 0);
} }
} }
} }
@@ -124,8 +124,8 @@ void CachedDepthPass::render() {
uint32 inst = drawCall.offsets.instanceOffset; uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) { for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset // all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletOffset), inst++); vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
} }
} }
} }
@@ -195,8 +195,8 @@ void DepthCullingPass::render() {
uint32 inst = drawCall.offsets.instanceOffset; uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) { for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset // all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletOffset), inst++); vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
} }
} }
} }
+3 -3
View File
@@ -58,8 +58,8 @@ void StaticMeshVertexData::serializeMesh(MeshId id, ArchiveBuffer& buffer) {
uint64 numVertices; uint64 numVertices;
{ {
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
offset = meshOffsets[id]; offset = registeredMeshes[id].vertexOffset;
numVertices = meshVertexCounts[id]; numVertices = registeredMeshes[id].vertexCount;
} }
Array<TexCoordType> tex[MAX_TEXCOORDS]; Array<TexCoordType> tex[MAX_TEXCOORDS];
for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { for (size_t i = 0; i < MAX_TEXCOORDS; ++i) {
@@ -89,7 +89,7 @@ uint64 StaticMeshVertexData::deserializeMesh(MeshId id, ArchiveBuffer& buffer) {
uint64 offset; uint64 offset;
{ {
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
offset = meshOffsets[id]; offset = registeredMeshes[id].vertexOffset;
} }
Array<TexCoordType> tex[MAX_TEXCOORDS]; Array<TexCoordType> tex[MAX_TEXCOORDS];
for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { for (size_t i = 0; i < MAX_TEXCOORDS; ++i) {
+40 -31
View File
@@ -58,7 +58,7 @@ void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transfo
} }
BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()]; BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()];
matInstanceData.materialInstance = referencedInstance; matInstanceData.materialInstance = referencedInstance;
for (const auto& data : meshData[mesh->id]) { for (const auto& data : registeredMeshes[mesh->id].meshData) {
if (mat->hasTransparency()) { if (mat->hasTransparency()) {
auto params = referencedInstance->getMaterialOffsets(); auto params = referencedInstance->getMaterialOffsets();
transparentData.add(TransparentDraw{ transparentData.add(TransparentDraw{
@@ -140,6 +140,7 @@ void VertexData::createDescriptors() {
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) { void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) {
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
RegisteredMesh& mesh = registeredMeshes[id];
uint32 numChunks = (loadedMeshlets.size() + 2047) / 2048; uint32 numChunks = (loadedMeshlets.size() + 2047) / 2048;
for (uint32 chunkIdx = 0; chunkIdx < numChunks; ++chunkIdx) { for (uint32 chunkIdx = 0; chunkIdx < numChunks; ++chunkIdx) {
uint32 meshletOffset = (uint32)meshlets.size(); uint32 meshletOffset = (uint32)meshlets.size();
@@ -160,33 +161,40 @@ void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet>
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8)); std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
meshlets.add(MeshletDescription{ meshlets.add(MeshletDescription{
.bounding = m.boundingBox, //.toSphere(), .bounding = m.boundingBox, //.toSphere(),
.vertexCount = m.numVertices, .vertexIndices =
.primitiveCount = m.numPrimitives, {
.vertexOffset = vertexOffset, .offset = vertexOffset,
.primitiveOffset = primitiveOffset, .size = m.numVertices,
},
.primitiveIndices =
{
.offset = primitiveOffset,
.size = m.numPrimitives,
},
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX), .color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
.indicesOffset = (uint32)meshOffsets[id], .indicesOffset = (uint32)registeredMeshes[id].indicesRange.offset,
}); });
} }
meshData[id].add(MeshData{ registeredMeshes[id].meshData.add(MeshData{
.bounding = meshAABB, //.toSphere(), .bounding = meshAABB, //.toSphere(),
.numMeshlets = numMeshlets, .meshletRange =
.meshletOffset = meshletOffset, {
.offset = meshletOffset,
.size = numMeshlets,
},
}); });
} }
// todo: in case of a index split for 16 bit, do something here // todo: in case of a index split for 16 bit, do something here
meshData[id][0].firstIndex = (uint32)indices.size(); registeredMeshes[id].meshData[0].indicesRange = {
meshData[id][0].numIndices = (uint32)loadedIndices.size(); .offset = (uint32)indices.size(),
.size = (uint32)loadedIndices.size(),
};
indices.resize(indices.size() + loadedIndices.size()); indices.resize(indices.size() + loadedIndices.size());
std::memcpy(indices.data() + meshData[id][0].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32)); std::memcpy(indices.data() + registeredMeshes[id].meshData[0].indicesRange.offset, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
} }
void VertexData::updateMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets) { void VertexData::updateMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets) {
uint32 numMeshlets = 0; uint32 numMeshlets = 0;
for (const auto& dat : meshData[id]) {
numMeshlets += dat.numMeshlets;
}
int32 difference = meshlets.size() - numMeshlets;
} }
void VertexData::commitMeshes() { void VertexData::commitMeshes() {
@@ -235,9 +243,10 @@ void VertexData::commitMeshes() {
MeshId VertexData::allocateVertexData(uint64 numVertices) { MeshId VertexData::allocateVertexData(uint64 numVertices) {
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
MeshId res{idCounter++}; MeshId res{idCounter++};
meshOffsets.add(head); registeredMeshes.add({
meshVertexCounts.add(numVertices); .vertexOffset = head,
meshData.add({}); .vertexCount = numVertices,
});
head += numVertices; head += numVertices;
if (head > verticesAllocated) { if (head > verticesAllocated) {
verticesAllocated = 2 * head; // double capacity verticesAllocated = 2 * head; // double capacity
@@ -250,21 +259,21 @@ MeshId VertexData::allocateVertexData(uint64 numVertices) {
void VertexData::serializeMesh(MeshId id, ArchiveBuffer& buffer) { void VertexData::serializeMesh(MeshId id, ArchiveBuffer& buffer) {
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
Array<Meshlet> out; Array<Meshlet> out;
for (uint32 n = 0; n < meshData[id].size(); ++n) { for (uint32 n = 0; n < registeredMeshes[id].meshData.size(); ++n) {
MeshData data = meshData[id][n]; MeshData data = registeredMeshes[id].meshData[n];
for (size_t i = 0; i < data.numMeshlets; ++i) { for (size_t i = 0; i < data.meshletRange.size; ++i) {
MeshletDescription& desc = meshlets[i + data.meshletOffset]; MeshletDescription& desc = meshlets[i + data.meshletRange.offset];
Meshlet m; Meshlet m;
std::memcpy(m.uniqueVertices, &vertexIndices[desc.vertexOffset], desc.vertexCount * sizeof(uint32)); std::memcpy(m.uniqueVertices, &vertexIndices[desc.vertexIndices.offset], desc.vertexIndices.size * sizeof(uint32));
std::memcpy(m.primitiveLayout, &primitiveIndices[desc.primitiveOffset], desc.primitiveCount * 3 * sizeof(uint8)); std::memcpy(m.primitiveLayout, &primitiveIndices[desc.primitiveIndices.offset], desc.primitiveIndices.size * 3 * sizeof(uint8));
m.numPrimitives = desc.primitiveCount; m.numPrimitives = desc.primitiveIndices.size;
m.numVertices = desc.vertexCount; m.numVertices = desc.vertexIndices.size;
m.boundingBox = desc.bounding; m.boundingBox = desc.bounding;
out.add(std::move(m)); out.add(std::move(m));
} }
} }
Array<uint32> ind(meshData[id][0].numIndices); Array<uint32> ind(registeredMeshes[id].meshData[0].indicesRange.size);
std::memcpy(ind.data(), &indices[meshData[id][0].firstIndex], meshData[id][0].numIndices * sizeof(uint32)); std::memcpy(ind.data(), &indices[registeredMeshes[id].meshData[0].indicesRange.offset], registeredMeshes[id].meshData[0].indicesRange.size * sizeof(uint32));
Serialization::save(buffer, out); Serialization::save(buffer, out);
Serialization::save(buffer, ind); Serialization::save(buffer, ind);
} }
@@ -360,14 +369,14 @@ void VertexData::destroy() {
vertexIndicesBuffer = nullptr; vertexIndicesBuffer = nullptr;
primitiveIndicesBuffer = nullptr; primitiveIndicesBuffer = nullptr;
indexBuffer = nullptr; indexBuffer = nullptr;
meshData.clear(); registeredMeshes.clear();
materialData.clear(); materialData.clear();
} }
uint32 VertexData::addCullingMapping(MeshId id) { uint32 VertexData::addCullingMapping(MeshId id) {
uint32 result = (uint32)meshletCount; uint32 result = (uint32)meshletCount;
for (const auto& md : getMeshData(id)) { for (const auto& md : getMeshData(id)) {
meshletCount += md.numMeshlets; meshletCount += md.meshletRange.size;
} }
return result; return result;
} }
+16 -14
View File
@@ -61,8 +61,8 @@ class VertexData {
void updateMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets); void updateMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
void commitMeshes(); void commitMeshes();
MeshId allocateVertexData(uint64 numVertices); MeshId allocateVertexData(uint64 numVertices);
uint64 getMeshOffset(MeshId id) const { return meshOffsets[id]; } uint64 getMeshOffset(MeshId id) const { return registeredMeshes[id].vertexOffset; }
uint64 getMeshVertexCount(MeshId id) { return meshVertexCounts[id]; } uint64 getMeshVertexCount(MeshId id) { return registeredMeshes[id].vertexCount; }
virtual void serializeMesh(MeshId id, ArchiveBuffer& buffer); virtual void serializeMesh(MeshId id, ArchiveBuffer& buffer);
virtual uint64 deserializeMesh(MeshId id, ArchiveBuffer& buffer); virtual uint64 deserializeMesh(MeshId id, ArchiveBuffer& buffer);
virtual Gfx::PDescriptorLayout getVertexDataLayout() = 0; virtual Gfx::PDescriptorLayout getVertexDataLayout() = 0;
@@ -76,7 +76,7 @@ class VertexData {
const Array<MaterialData>& getMaterialData() const { return materialData; } const Array<MaterialData>& getMaterialData() const { return materialData; }
const Array<TransparentDraw>& getTransparentData() const { return transparentData; } const Array<TransparentDraw>& getTransparentData() const { return transparentData; }
const Array<Gfx::PBottomLevelAS>& getRayTracingData() const { return rayTracingScene; } const Array<Gfx::PBottomLevelAS>& getRayTracingData() const { return rayTracingScene; }
const Array<MeshData>& getMeshData(MeshId id) const { return meshData[id]; } const Array<MeshData>& getMeshData(MeshId id) const { return registeredMeshes[id].meshData; }
void registerBottomLevelAccelerationStructure(Gfx::PBottomLevelAS blas) { dataToBuild.add(blas); } void registerBottomLevelAccelerationStructure(Gfx::PBottomLevelAS blas) { dataToBuild.add(blas); }
uint32 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; } uint32 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; }
uint64 getNumInstances() const { return instanceData.size(); } uint64 getNumInstances() const { return instanceData.size(); }
@@ -96,14 +96,10 @@ class VertexData {
VertexData(); VertexData();
struct MeshletDescription { struct MeshletDescription {
AABB bounding; AABB bounding;
// number of relevant entries in the vertexIndices array // range into vertexIndices array
uint32 vertexCount; PoolRange vertexIndices;
// number of relevant entries in the primitiveIndices array // range into primitiveIndices array
uint32 primitiveCount; PoolRange primitiveIndices;
// starting offset into the vertexIndices array
uint32 vertexOffset;
// starting offset into the primitiveIndices array
uint32 primitiveOffset;
Vector color; Vector color;
// gets added to vertex indices so that they reference the global mesh bool // gets added to vertex indices so that they reference the global mesh bool
uint32 indicesOffset = 0; uint32 indicesOffset = 0;
@@ -114,10 +110,16 @@ class VertexData {
Array<TransparentDraw> transparentData; Array<TransparentDraw> transparentData;
std::mutex vertexDataLock; std::mutex vertexDataLock;
struct RegisteredMesh
{
// each mesh id can have multiple meshdata, in case it needs to be split for having too many meshlets // each mesh id can have multiple meshdata, in case it needs to be split for having too many meshlets
Array<Array<MeshData>> meshData; Array<MeshData> meshData;
Array<uint64> meshOffsets; uint64 vertexOffset;
Array<uint64> meshVertexCounts; uint64 vertexCount;
PoolRange meshletRange;
PoolRange indicesRange;
};
Array<RegisteredMesh> registeredMeshes;
Array<MeshletDescription> meshlets; Array<MeshletDescription> meshlets;
Array<uint8> primitiveIndices; Array<uint8> primitiveIndices;
+1 -1
View File
@@ -3,7 +3,7 @@
#include "Enums.h" #include "Enums.h"
#include "Graphics/Enums.h" #include "Graphics/Enums.h"
#include <fmt/format.h> #include <fmt/format.h>
#include <vma/vk_mem_alloc.h> #include <vk_mem_alloc.h>
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
+2 -2
View File
@@ -26,8 +26,8 @@ BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateI
MeshData meshData = vertexData->getMeshData(createInfo.mesh->id)[0]; MeshData meshData = vertexData->getMeshData(createInfo.mesh->id)[0];
vertexOffset = vertexData->getMeshOffset(createInfo.mesh->id) * sizeof(Vector); vertexOffset = vertexData->getMeshOffset(createInfo.mesh->id) * sizeof(Vector);
vertexCount = vertexData->getMeshVertexCount(createInfo.mesh->id); vertexCount = vertexData->getMeshVertexCount(createInfo.mesh->id);
indexOffset = meshData.firstIndex * sizeof(uint32); indexOffset = meshData.indicesRange.offset * sizeof(uint32);
primitiveCount = meshData.numIndices / 3; primitiveCount = meshData.indicesRange.size / 3;
// todo: compact // todo: compact
} }