Adding transparency support

This commit is contained in:
Dynamitos
2024-06-20 21:57:26 +02:00
parent 2dc9d57c71
commit bd63b14260
27 changed files with 578 additions and 282 deletions
+213 -150
View File
@@ -17,6 +17,8 @@ uint64 VertexData::meshletCount = 0;
void VertexData::resetMeshData() {
std::unique_lock l(materialDataLock);
transparentInstanceData.clear();
transparentMeshData.clear();
for (auto& mat : materialData) {
for (auto& inst : mat.instances) {
inst.instanceData.clear();
@@ -36,6 +38,32 @@ void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Compo
std::unique_lock l(materialDataLock);
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
PMaterial mat = referencedInstance->getBaseMaterial();
const auto& data = meshData[mesh->id];
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
InstanceData inst = InstanceData{
.transformMatrix = transformMatrix,
.inverseTransformMatrix = glm::inverse(transformMatrix),
};
if (mat->hasTransparency()) {
auto params = referencedInstance->getMaterialOffsets();
transparentData.add(TransparentDraw{
.matInst = referencedInstance,
.vertexData = this,
.offsets =
{
.instanceOffset = static_cast<uint32>(transparentInstanceData.size()),
.textureOffset = params.textureOffset,
.samplerOffset = params.samplerOffset,
.floatOffset = params.floatOffset,
},
.worldPosition = Vector(inst.transformMatrix[3]),
});
transparentInstanceData.add(inst);
transparentMeshData.add(data);
return;
}
if (materialData.size() <= mat->getId()) {
materialData.resize(mat->getId() + 1);
}
@@ -47,12 +75,7 @@ void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Compo
BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()];
matInstanceData.materialInstance = referencedInstance;
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
matInstanceData.instanceData.add(InstanceData{
.transformMatrix = transformMatrix,
.inverseTransformMatrix = glm::inverse(transformMatrix),
});
const auto& data = meshData[mesh->id];
matInstanceData.instanceData.add(inst);
auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets);
matInstanceData.instanceMeshData.add(data);
matInstanceData.cullingOffsets.add(meshletOffset);
@@ -157,6 +180,25 @@ void VertexData::createDescriptors() {
});
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);
transparentInstanceDataBuffer->rotateBuffer(sizeof(InstanceData) * transparentInstanceData.size());
transparentInstanceDataBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(InstanceData) * transparentInstanceData.size(),
.data = (uint8*)transparentInstanceData.data(),
},
});
transparentMeshDataBuffer->rotateBuffer(sizeof(MeshData) * transparentMeshData.size());
transparentMeshDataBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(MeshData) * transparentMeshData.size(),
.data = (uint8*)transparentMeshData.data(),
},
});
instanceDataLayout->reset();
descriptorSet = instanceDataLayout->allocateDescriptorSet();
descriptorSet->updateBuffer(0, instanceBuffer);
@@ -169,176 +211,197 @@ void VertexData::createDescriptors() {
}
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) {
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],
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(),
};
indices.resize(indices.size() + loadedIndices.size());
std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
}
void VertexData::commitMeshes() {
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",
});
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * vertexIndices.size(),
.data = (uint8*)vertexIndices.data(),
},
.numElements = vertexIndices.size(),
.dynamic = false,
.name = "VertexIndicesBuffer",
});
}
meshData[id] = MeshData{
.bounding = meshAABB, //.toSphere(),
.numMeshlets = (uint32)loadedMeshlets.size(),
.meshletOffset = meshletOffset,
.firstIndex = (uint32)indices.size(),
.numIndices = (uint32)loadedIndices.size(),
};
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"});
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",
});
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint8) * primitiveIndices.size(),
.data = (uint8*)primitiveIndices.data(),
},
.numElements = primitiveIndices.size(),
.dynamic = false,
.name = "PrimitiveIndicesBuffer",
});
}
MeshId VertexData::allocateVertexData(uint64 numVertices) {
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;
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;
}
uint64 VertexData::getMeshOffset(MeshId id) { return meshOffsets[id]; }
uint64 VertexData::getMeshOffset(MeshId id) {
return meshOffsets[id]; }
uint64 VertexData::getMeshVertexCount(MeshId id) { return meshVertexCounts[id]; }
uint64 VertexData::getMeshVertexCount(MeshId id) {
return meshVertexCounts[id]; }
List<VertexData*> vertexDataList;
List<VertexData*> VertexData::getList() { return vertexDataList; }
List<VertexData*> VertexData::getList() {
return vertexDataList; }
VertexData* VertexData::findByTypeName(std::string name) {
for (auto vd : vertexDataList) {
if (vd->getTypeName() == name) {
return vd;
for (auto vd : vertexDataList) {
if (vd->getTypeName() == name) {
return vd;
}
}
}
return nullptr;
return nullptr;
}
void VertexData::init(Gfx::PGraphics _graphics) {
graphics = _graphics;
verticesAllocated = NUM_DEFAULT_ELEMENTS;
instanceDataLayout = graphics->createDescriptorLayout("pScene");
graphics = _graphics;
verticesAllocated = NUM_DEFAULT_ELEMENTS;
instanceDataLayout = graphics->createDescriptorLayout("pScene");
// 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});
// cullingOffset
instanceDataLayout->addDescriptorBinding(
Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingInfos
instanceDataLayout->addDescriptorBinding(
Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// 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});
// cullingOffset
instanceDataLayout->addDescriptorBinding(
Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingInfos
instanceDataLayout->addDescriptorBinding(
Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
instanceDataLayout->create();
instanceDataLayout->create();
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "MeshletOffset",
});
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "InstanceBuffer",
});
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "MeshDataBuffer",
});
resizeBuffers();
graphics->getShaderCompiler()->registerVertexData(this);
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "MeshletOffset",
});
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "InstanceBuffer",
});
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "MeshDataBuffer",
});
transparentInstanceDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "TransparentInstanceBuffer",
});
transparentMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true,
.name = "TransparentMeshBuffer",
});
resizeBuffers();
graphics->getShaderCompiler()->registerVertexData(this);
}
void VertexData::destroy() {
instanceBuffer = nullptr;
instanceMeshDataBuffer = nullptr;
instanceDataLayout = nullptr;
meshletBuffer = nullptr;
vertexIndicesBuffer = nullptr;
primitiveIndicesBuffer = nullptr;
indexBuffer = nullptr;
meshData.clear();
materialData.clear();
instanceBuffer = nullptr;
instanceMeshDataBuffer = nullptr;
instanceDataLayout = nullptr;
meshletBuffer = nullptr;
vertexIndicesBuffer = nullptr;
primitiveIndicesBuffer = nullptr;
indexBuffer = nullptr;
meshData.clear();
materialData.clear();
}
VertexData::CullingMapping VertexData::getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets) {
MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex};
if (!instanceIdMap.contains(key)) {
instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)};
meshletCount += numMeshlets;
}
return instanceIdMap[key];
MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex};
if (!instanceIdMap.contains(key)) {
instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)};
meshletCount += numMeshlets;
}
return instanceIdMap[key];
}
VertexData::VertexData() : idCounter(0), head(0), verticesAllocated(0), dirty(false) {}