Files
Seele/src/Engine/Graphics/VertexData.cpp
T

384 lines
15 KiB
C++
Raw Normal View History

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"
2024-01-24 23:10:33 +01:00
#include "Graphics/Mesh.h"
2023-12-22 19:46:07 +01:00
#include "Containers/Set.h"
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()
{
2024-05-30 16:56:22 +02:00
std::unique_lock l(materialDataLock);
for (auto &mat : materialData)
{
for (auto &inst : mat.instances)
2023-11-17 18:46:37 +01:00
{
2024-05-30 16:56:22 +02:00
inst.instanceData.clear();
inst.instanceMeshData.clear();
2023-11-17 18:46:37 +01:00
}
2024-05-30 16:56:22 +02:00
if (mat.material != nullptr)
2023-10-31 16:16:23 +01:00
{
2024-05-30 16:56:22 +02:00
mat.material->getDescriptorLayout()->reset();
2023-10-31 16:16:23 +01:00
}
2024-05-30 16:56:22 +02:00
}
if (dirty)
{
updateBuffers();
dirty = false;
}
2023-10-24 15:01:09 +02:00
}
2024-05-30 16:56:22 +02:00
void VertexData::updateMesh(PMesh mesh, Component::Transform &transform)
2023-10-24 15:01:09 +02:00
{
2024-05-30 16:56:22 +02:00
std::unique_lock l(materialDataLock);
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
PMaterial mat = referencedInstance->getBaseMaterial();
if (materialData.size() <= mat->getId())
{
materialData.resize(mat->getId() + 1);
}
MaterialData &matData = materialData[mat->getId()];
matData.material = mat;
if (matData.instances.size() <= referencedInstance->getId())
{
matData.instances.resize(referencedInstance->getId() + 1);
}
BatchedDrawCall &matInstanceData = matData.instances[referencedInstance->getId()];
matInstanceData.materialInstance = referencedInstance;
2024-05-12 19:36:32 +02:00
2024-05-30 16:56:22 +02:00
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
matInstanceData.instanceData.add(InstanceData{
.transformMatrix = transformMatrix,
.inverseTransformMatrix = glm::inverse(transformMatrix),
});
const auto &data = meshData[mesh->id];
matInstanceData.instanceMeshData.add(data);
referencedInstance->updateDescriptor();
for (size_t i = 0; i < 0; ++i)
{
auto bounding = meshlets[data.meshletOffset + i].bounding;
StaticArray<Vector, 8> corners;
Vector min = bounding.min; // bounding.center - bounding.radius * Vector(1, 1, 1);
Vector max = bounding.max; // bounding.center + bounding.radius * Vector(1, 1, 1);
corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1);
corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1);
corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1);
corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1);
corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1);
corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1);
corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1);
corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1);
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
}
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
{
2024-05-30 16:56:22 +02:00
std::unique_lock l(materialDataLock);
2024-05-12 19:36:32 +02:00
2024-05-30 16:56:22 +02:00
instanceData.clear();
instanceMeshData.clear();
2024-05-12 19:36:32 +02:00
2024-05-30 16:56:22 +02:00
uint32 numMeshlets = 0;
Array<uint32> cullingOffsets;
for (auto &mat : materialData)
{
for (auto &instance : mat.instances)
2024-05-12 19:36:32 +02:00
{
2024-05-30 16:56:22 +02:00
instance.offsets.instanceOffset = instanceData.size();
// instance.offsets.cullingCounterOffset = cullingOffsets.size();
// instance.numMeshlets = 0;
for (size_t i = 0; i < instance.instanceData.size(); ++i)
{
cullingOffsets.add(numMeshlets);
instanceData.add(instance.instanceData[i]);
instanceMeshData.add(instance.instanceMeshData[i]);
// instance.numMeshlets += instance.instanceMeshData[i].numMeshlets;
// cullingOffsets.add(numMeshlets);
numMeshlets += instance.instanceMeshData[i].numMeshlets;
}
2024-05-12 19:36:32 +02:00
}
2024-05-30 16:56:22 +02:00
}
Array<MeshletCullingInfo> cullingData(numMeshlets);
std::memset(cullingData.data(), 0xff, cullingData.size());
cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32));
cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = {
.size = cullingOffsets.size() * sizeof(uint32),
.data = (uint8 *)cullingOffsets.data(),
},
.numElements = cullingOffsets.size()});
cullingOffsetBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
2024-05-30 16:56:22 +02:00
cullingBuffer->rotateBuffer(numMeshlets * sizeof(MeshletCullingInfo));
cullingBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = {
.size = numMeshlets * sizeof(MeshletCullingInfo),
.data = (uint8 *)cullingData.data(),
},
.numElements = numMeshlets});
cullingBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData));
instanceBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = {
.size = instanceData.size() * sizeof(InstanceData),
.data = (uint8 *)instanceData.data(),
},
.numElements = instanceData.size()});
instanceBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
2024-05-30 16:56:22 +02:00
instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size());
instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(MeshData) * instanceMeshData.size(),
.data = (uint8 *)instanceMeshData.data(),
},
.numElements = instanceMeshData.size()});
instanceMeshDataBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
instanceDataLayout->reset();
descriptorSet = instanceDataLayout->allocateDescriptorSet();
descriptorSet->updateBuffer(0, instanceBuffer);
descriptorSet->updateBuffer(1, instanceMeshDataBuffer);
descriptorSet->updateBuffer(2, meshletBuffer);
descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
descriptorSet->updateBuffer(4, vertexIndicesBuffer);
descriptorSet->updateBuffer(5, cullingBuffer);
descriptorSet->updateBuffer(6, cullingOffsetBuffer);
descriptorSet->writeChanges();
2023-11-10 19:18:09 +01:00
}
2024-04-07 16:33:32 +02:00
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets)
2023-10-31 16:16:23 +01:00
{
2024-05-30 16:56:22 +02:00
assert(loadedMeshlets.size() < 2048);
std::unique_lock l(vertexDataLock);
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
uint32 meshletOffset = meshlets.size();
AABB meshAABB;
for (uint32 i = 0; i < loadedMeshlets.size(); ++i)
{
Meshlet &m = loadedMeshlets[i];
meshAABB = meshAABB.combine(m.boundingBox);
uint32 vertexOffset = vertexIndices.size();
vertexIndices.resize(vertexOffset + m.numVertices);
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
uint32 primitiveOffset = primitiveIndices.size();
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
meshlets.add(MeshletDescription{
.bounding = m.boundingBox, //.toSphere(),
.vertexCount = m.numVertices,
.primitiveCount = m.numPrimitives,
.vertexOffset = vertexOffset,
.primitiveOffset = primitiveOffset,
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
.indicesOffset = (uint32)meshOffsets[id],
});
}
meshData[id] = MeshData{
.bounding = meshAABB, //.toSphere(),
.numMeshlets = (uint32)loadedMeshlets.size(),
.meshletOffset = meshletOffset,
.firstIndex = (uint32)indices.size(),
.numIndices = (uint32)loadedIndices.size(),
};
2024-05-30 16:56:22 +02:00
if (!graphics->supportMeshShading())
{
indices.resize(indices.size() + loadedIndices.size());
std::memcpy(indices.data() + meshData[id].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,
.name = "IndexBuffer",
});
}
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(MeshletDescription) * meshlets.size(),
.data = (uint8 *)meshlets.data()},
.numElements = meshlets.size(),
.dynamic = false,
.name = "MeshletBuffer"});
2024-05-30 16:56:22 +02:00
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(uint32) * vertexIndices.size(),
.data = (uint8 *)vertexIndices.data(),
},
.numElements = vertexIndices.size(),
.dynamic = false,
.name = "VertexIndicesBuffer"});
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(uint8) * primitiveIndices.size(),
.data = (uint8 *)primitiveIndices.data(),
},
.numElements = primitiveIndices.size(),
.dynamic = false,
.name = "PrimitiveIndicesBuffer",
});
2023-10-24 15:01:09 +02:00
}
2023-10-31 17:55:30 +01:00
MeshId VertexData::allocateVertexData(uint64 numVertices)
{
2024-05-30 16:56:22 +02:00
std::unique_lock l(vertexDataLock);
MeshId res{idCounter++};
meshOffsets[res] = head;
meshVertexCounts[res] = numVertices;
head += numVertices;
if (head > verticesAllocated)
{
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
resizeBuffers();
}
return res;
2023-10-31 17:55:30 +01:00
}
2023-11-09 22:15:51 +01:00
uint64 VertexData::getMeshOffset(MeshId id)
{
2024-05-30 16:56:22 +02:00
return meshOffsets[id];
}
2023-11-09 22:15:51 +01:00
uint64 VertexData::getMeshVertexCount(MeshId id)
{
2024-05-30 16:56:22 +02:00
return meshVertexCounts[id];
2023-11-09 22:15:51 +01:00
}
2024-05-30 16:56:22 +02:00
List<VertexData *> vertexDataList;
2023-10-24 15:01:09 +02:00
2024-05-30 16:56:22 +02:00
List<VertexData *> VertexData::getList()
2023-10-24 15:01:09 +02:00
{
2024-05-30 16:56:22 +02:00
return vertexDataList;
2023-10-24 15:01:09 +02:00
}
2024-05-30 16:56:22 +02:00
VertexData *VertexData::findByTypeName(std::string name)
2023-11-01 13:38:49 +01:00
{
2024-05-30 16:56:22 +02:00
for (auto vd : vertexDataList)
{
if (vd->getTypeName() == name)
2023-11-01 13:38:49 +01:00
{
2024-05-30 16:56:22 +02:00
return vd;
2023-11-01 13:38:49 +01:00
}
2024-05-30 16:56:22 +02:00
}
return nullptr;
2023-11-01 13:38:49 +01:00
}
void VertexData::init(Gfx::PGraphics _graphics)
2023-10-24 15:01:09 +02:00
{
2024-05-30 16:56:22 +02:00
graphics = _graphics;
verticesAllocated = NUM_DEFAULT_ELEMENTS;
instanceDataLayout = graphics->createDescriptorLayout("pScene");
2023-11-26 09:40:48 +01:00
2024-05-30 16:56:22 +02:00
// instanceData
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
// meshData
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 1,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
// meshletData
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// primitiveIndices
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// vertexIndices
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingList
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingOffset
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
2024-05-30 16:56:22 +02:00
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "MeshletOffset",
});
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "MeshletCulling",
});
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "InstanceBuffer",
});
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "MeshDataBuffer",
});
instanceDataLayout->create();
resizeBuffers();
graphics->getShaderCompiler()->registerVertexData(this);
2023-10-29 09:20:23 +01:00
}
2023-10-31 16:16:23 +01:00
2023-12-12 11:37:00 +01:00
void VertexData::destroy()
{
2024-05-30 16:56:22 +02:00
instanceBuffer = nullptr;
instanceMeshDataBuffer = nullptr;
instanceDataLayout = nullptr;
meshletBuffer = nullptr;
vertexIndicesBuffer = nullptr;
primitiveIndicesBuffer = nullptr;
indexBuffer = nullptr;
meshData.clear();
materialData.clear();
2023-12-12 11:37:00 +01:00
}
2023-10-31 16:16:23 +01:00
VertexData::VertexData()
2024-05-30 16:56:22 +02:00
: idCounter(0), head(0), verticesAllocated(0), dirty(false)
2023-10-31 16:16:23 +01:00
{
}