More mesh shading changes

This commit is contained in:
2023-11-22 13:18:54 +01:00
parent 6daaa61641
commit 7f1bc7d090
20 changed files with 353 additions and 228 deletions
+9
View File
@@ -11,6 +11,15 @@
</ArrayItems> </ArrayItems>
</Expand> </Expand>
</Type> </Type>
<Type Name="Seele::StaticArray&lt;*,*&gt;">
<DisplayString>{{ size={$T2} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>$T2</Size>
<ValuePointer>_data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="Seele::List&lt;*&gt;"> <Type Name="Seele::List&lt;*&gt;">
<DisplayString>{{ size={_size} }}</DisplayString> <DisplayString>{{ size={_size} }}</DisplayString>
<Expand> <Expand>
+30 -20
View File
@@ -1,8 +1,8 @@
import Common; import Common;
import BRDF; import BRDF;
import Meshlet; import Meshlet;
import Scene;
import VertexData; import VertexData;
import MaterialParameter;
struct MeshPayload struct MeshPayload
{ {
@@ -47,8 +47,10 @@ void taskMain(
MeshData mesh = pScene.meshData[groupID]; MeshData mesh = pScene.meshData[groupID];
for(uint i = threadID; i < MAX_MESHLETS_PER_MESH; i += TASK_GROUP_SIZE) for(uint i = threadID; i < MAX_MESHLETS_PER_MESH; i += TASK_GROUP_SIZE)
{ {
uint m = mesh.meshletOffset + min(mesh.numMeshlets, i); if(i < mesh.numMeshlets)
MeshletDescription meshlet = pScene.meshlets.meshletInfos[m]; {
uint m = mesh.meshletOffset + i;
MeshletDescription meshlet = pScene.meshletInfos[m];
//if(meshlet.boundingBox.insideFrustum(localToClip, viewFrustum)) //if(meshlet.boundingBox.insideFrustum(localToClip, viewFrustum))
{ {
uint index; uint index;
@@ -57,6 +59,7 @@ void taskMain(
p.instanceId[index] = groupID; p.instanceId[index] = groupID;
} }
} }
}
GroupMemoryBarrierWithGroupSync(); GroupMemoryBarrierWithGroupSync();
DispatchMesh(head, 1, 1, p); DispatchMesh(head, 1, 1, p);
} }
@@ -71,6 +74,12 @@ struct PrimitiveAttributes
uint cull: SV_CullPrimitive; uint cull: SV_CullPrimitive;
}; };
struct MeshOutput
{
FragmentParameter parameter : PARAMETER;
float4 position_CS : SV_Position;
};
[numthreads(MESH_GROUP_SIZE, 1, 1)] [numthreads(MESH_GROUP_SIZE, 1, 1)]
[outputtopology("triangle")] [outputtopology("triangle")]
[shader("mesh")] [shader("mesh")]
@@ -78,7 +87,7 @@ void meshMain(
in uint threadID: SV_GroupIndex, in uint threadID: SV_GroupIndex,
in uint groupID: SV_GroupID, in uint groupID: SV_GroupID,
in payload MeshPayload meshPayload, in payload MeshPayload meshPayload,
out Vertices<VertexAttributes, MAX_VERTICES> vertices, out Vertices<MeshOutput, MAX_VERTICES> vertices,
out Indices<uint3, MAX_PRIMITIVES> indices out Indices<uint3, MAX_PRIMITIVES> indices
){ ){
InstanceData inst = pScene.instances[meshPayload.instanceId[groupID]]; InstanceData inst = pScene.instances[meshPayload.instanceId[groupID]];
@@ -92,10 +101,10 @@ void meshMain(
InterlockedMax(gs_numVertices, v + 1); InterlockedMax(gs_numVertices, v + 1);
{ {
int vertexIndex = pScene.vertexIndices[m.vertexOffset + v]; int vertexIndex = pScene.vertexIndices[m.vertexOffset + v];
gs_vertices[v] = pVertexData.getAttributes(md.indexOffset + vertexIndex, inst); gs_vertices[v] = pVertexData.getAttributes(md.indicesOffset + vertexIndex, inst.transformMatrix);
} }
} }
GroupMemoryBarrierWithGroupSync();
const uint primitiveLoops = (MAX_PRIMITIVES + MESH_GROUP_SIZE - 1) / MESH_GROUP_SIZE; const uint primitiveLoops = (MAX_PRIMITIVES + MESH_GROUP_SIZE - 1) / MESH_GROUP_SIZE;
for(uint loop = 0; loop < primitiveLoops; ++loop) for(uint loop = 0; loop < primitiveLoops; ++loop)
{ {
@@ -103,15 +112,12 @@ void meshMain(
p = min(p, m.primitiveCount - 1); p = min(p, m.primitiveCount - 1);
InterlockedMax(gs_numPrimitives, p + 1); InterlockedMax(gs_numPrimitives, p + 1);
{ {
uint8_t local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0]; uint32_t local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0];
uint8_t local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1]; uint32_t local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1];
uint8_t local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2]; uint32_t local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2];
uint32_t idx0 = pScene.vertexIndices[m.vertexOffset + local_idx0]; gs_indices[p].x = local_idx0;
uint32_t idx1 = pScene.vertexIndices[m.vertexOffset + local_idx1]; gs_indices[p].y = local_idx1;
uint32_t idx2 = pScene.vertexIndices[m.vertexOffset + local_idx2]; gs_indices[p].z = local_idx2;
gs_indices[p * 3 + 0] = idx0;
gs_indices[p * 3 + 1] = idx1;
gs_indices[p * 3 + 2] = idx2;
} }
} }
GroupMemoryBarrierWithGroupSync(); GroupMemoryBarrierWithGroupSync();
@@ -120,12 +126,16 @@ void meshMain(
uint v = threadID; uint v = threadID;
v = min(v, m.vertexCount - 1); v = min(v, m.vertexCount - 1);
vertices[v] = gs_vertices[v]; FragmentParameter parameter = gs_vertices[v].getParameter(inst.transformMatrix);
vertices[v].parameter = parameter;
vertices[v].position_CS = parameter.position_CS;
if(vertexLoops >= 1) if(vertexLoops >= 1)
{ {
uint v = threadID + MESH_GROUP_SIZE; uint v = threadID + MESH_GROUP_SIZE;
v = min(v, m.vertexCount - 1); v = min(v, m.vertexCount - 1);
vertices[v] = gs_vertices[v]; FragmentParameter parameter = gs_vertices[v].getParameter(inst.transformMatrix);
vertices[v].parameter = parameter;
vertices[v].position_CS = parameter.position_CS;
} }
uint p = threadID; uint p = threadID;
@@ -134,19 +144,19 @@ void meshMain(
if(primitiveLoops >= 1) if(primitiveLoops >= 1)
{ {
uint p = threadID + MESH_GROUP_SIZE; p += MESH_GROUP_SIZE;
p = min(p, m.primitiveCount - 1); p = min(p, m.primitiveCount - 1);
indices[p] = gs_indices[p]; indices[p] = gs_indices[p];
} }
if(primitiveLoops >= 2) if(primitiveLoops >= 2)
{ {
uint p = threadID + 2 * MESH_GROUP_SIZE; p += MESH_GROUP_SIZE;
p = min(p, m.primitiveCount - 1); p = min(p, m.primitiveCount - 1);
indices[p] = gs_indices[p]; indices[p] = gs_indices[p];
} }
if(primitiveLoops >= 3) if(primitiveLoops >= 3)
{ {
uint p = threadID + 3 * MESH_GROUP_SIZE; p += MESH_GROUP_SIZE;
p = min(p, m.primitiveCount - 1); p = min(p, m.primitiveCount - 1);
indices[p] = gs_indices[p]; indices[p] = gs_indices[p];
} }
+9 -9
View File
@@ -20,15 +20,15 @@ struct LightingParameter
// data passed to fragment shader // data passed to fragment shader
struct FragmentParameter struct FragmentParameter
{ {
float3 position_TS; float4 position_CS : SV_Position;
float3 viewDir_TS; float3 position_TS : POSITION0;
float3 normal_WS; float3 viewDir_TS : POSITION1;
float3 tangent_WS; float3 normal_WS : NORMAL0;
float3 biTangent_WS; float3 tangent_WS : TANGENT0;
float3 position_WS; float3 biTangent_WS : TANGENT1;
float4 position_CS; float3 position_WS : POSITION2;
float2 texCoords; float2 texCoords : TEXCOORD0;
float3 vertexColor; float3 vertexColor : COLOR0;
MaterialParameter getMaterialParameter() MaterialParameter getMaterialParameter()
{ {
MaterialParameter result; MaterialParameter result;
+1 -60
View File
@@ -194,68 +194,9 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialIns
Array<Meshlet> meshlets; Array<Meshlet> meshlets;
meshlets.reserve(indices.size() / (3ull * Gfx::numPrimitivesPerMeshlet)); meshlets.reserve(indices.size() / (3ull * Gfx::numPrimitivesPerMeshlet));
std::set<uint32> uniqueVertices; Meshlet::buildFromIndexBuffer(indices, meshlets);
Meshlet current = {
.numVertices = 0,
.numPrimitives = 0,
};
auto insertAndGetIndex = [&uniqueVertices, &current](uint32 index) -> int8_t
{
auto [it, inserted] = uniqueVertices.insert(index);
if (inserted)
{
if (current.numVertices == Gfx::numVerticesPerMeshlet)
{
return -1;
}
current.uniqueVertices[current.numVertices] = index;
return current.numVertices++;
}
else
{
for (uint32 i = 0; i < current.numVertices; ++i)
{
if (current.uniqueVertices[i] == index)
{
return i;
}
}
assert(false);
}
};
auto completeMeshlet = [&meshlets, &current, &uniqueVertices]() {
meshlets.add(current);
current = {
.numVertices = 0,
.numPrimitives = 0,
};
uniqueVertices.clear();
};
for (size_t faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex)
{
auto i1 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[0]);
auto i2 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[1]);
auto i3 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[2]);
if (i1 == -1 || i2 == -1 || i3 == -1)
{
completeMeshlet();
}
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();
}
vertexData->loadMesh(id, meshlets); vertexData->loadMesh(id, meshlets);
collider.physicsMesh.addCollider(positions, indices, Matrix4(1.0f)); collider.physicsMesh.addCollider(positions, indices, Matrix4(1.0f));
IndexBufferCreateInfo idxInfo; IndexBufferCreateInfo idxInfo;
+22 -22
View File
@@ -37,39 +37,39 @@ int main()
graphics->init(initializer); graphics->init(initializer);
StaticMeshVertexData* vd = StaticMeshVertexData::getInstance(); StaticMeshVertexData* vd = StaticMeshVertexData::getInstance();
vd->init(graphics); vd->init(graphics);
PWindowManager windowManager = new WindowManager(); OWindowManager windowManager = new WindowManager();
AssetRegistry::init(sourcePath / "Assets", graphics); AssetRegistry::init(sourcePath / "Assets", graphics);
AssetImporter::init(graphics); AssetImporter::init(graphics);
AssetImporter::importFont(FontImportArgs{ AssetImporter::importFont(FontImportArgs{
.filePath = "./fonts/Calibri.ttf", .filePath = "./fonts/Calibri.ttf",
}); });
AssetImporter::importMesh(MeshImportArgs{ //AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "old_resources/models/arena.fbx", // .filePath = sourcePath / "old_resources/models/arena.fbx",
}); // });
AssetImporter::importMesh(MeshImportArgs{ AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "old_resources/models/train.fbx", .filePath = sourcePath / "old_resources/models/train.fbx",
}); });
AssetImporter::importMesh(MeshImportArgs{ //AssetImporter::importMesh(MeshImportArgs{
.filePath= sourcePath / "old_resources/models/bird.fbx", // .filePath= sourcePath / "old_resources/models/bird.fbx",
}); // });
AssetImporter::importMesh(MeshImportArgs{ AssetImporter::importMesh(MeshImportArgs{
.filePath= sourcePath / "old_resources/models/cube.fbx", .filePath= sourcePath / "old_resources/models/cube.fbx",
}); });
AssetImporter::importMesh(MeshImportArgs{ //AssetImporter::importMesh(MeshImportArgs{
.filePath= sourcePath / "old_resources/models/flameThrower.fbx", // .filePath= sourcePath / "old_resources/models/flameThrower.fbx",
}); // });
AssetImporter::importMesh(MeshImportArgs{ //AssetImporter::importMesh(MeshImportArgs{
.filePath= sourcePath / "old_resources/models/player.fbx", // .filePath= sourcePath / "old_resources/models/player.fbx",
}); // });
AssetImporter::importMesh(MeshImportArgs{ //AssetImporter::importMesh(MeshImportArgs{
.filePath= sourcePath / "old_resources/models/shotgun.fbx", // .filePath= sourcePath / "old_resources/models/shotgun.fbx",
}); // });
AssetImporter::importMesh(MeshImportArgs{ //AssetImporter::importMesh(MeshImportArgs{
.filePath= sourcePath / "old_resources/models/track.fbx", // .filePath= sourcePath / "old_resources/models/track.fbx",
}); // });
AssetImporter::importMesh(MeshImportArgs{ //AssetImporter::importMesh(MeshImportArgs{
.filePath= sourcePath / "old_resources/models/zombie.fbx", // .filePath= sourcePath / "old_resources/models/zombie.fbx",
}); // });
AssetImporter::importTexture(TextureImportArgs{ AssetImporter::importTexture(TextureImportArgs{
.filePath= sourcePath / "old_resources/textures/Dirt.png", .filePath= sourcePath / "old_resources/textures/Dirt.png",
+7 -6
View File
@@ -602,17 +602,18 @@ private:
// The array is not big enough, so we make a new one // The array is not big enough, so we make a new one
T *newData = allocateArray(newSize); T *newData = allocateArray(newSize);
if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>)
{
std::memcpy(newData, _data, sizeof(T) * arraySize);
std::memset(&newData[arraySize], 0, sizeof(T) * (newSize - arraySize));
}
else
{
// And move the current elements into that one // And move the current elements into that one
for(size_type i = 0; i < arraySize; ++i) for(size_type i = 0; i < arraySize; ++i)
{ {
newData[i] = std::forward<Type>(_data[i]); newData[i] = std::forward<Type>(_data[i]);
} }
if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>)
{
std::memset(&newData[arraySize], 0, sizeof(T) * (newSize - arraySize));
}
else
{
// As well as default initialize the others // As well as default initialize the others
for (size_type i = arraySize; i < newSize; ++i) for (size_type i = arraySize; i < newSize; ++i)
{ {
@@ -36,8 +36,15 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene)
lightCullingLayout->create(); lightCullingLayout->create();
basePassLayout->addDescriptorLayout(INDEX_LIGHT_CULLING, lightCullingLayout); basePassLayout->addDescriptorLayout(INDEX_LIGHT_CULLING, lightCullingLayout);
if (graphics->supportMeshShading())
{
graphics->getShaderCompiler()->registerRenderPass("BasePass", "MeshletBasePass", true, true, "BasePass", true, true, "MeshletBasePass");
}
else
{
graphics->getShaderCompiler()->registerRenderPass("BasePass", "LegacyBasePass", true, true, "BasePass"); graphics->getShaderCompiler()->registerRenderPass("BasePass", "LegacyBasePass", true, true, "BasePass");
} }
}
BasePass::~BasePass() BasePass::~BasePass()
{ {
@@ -124,6 +131,7 @@ void BasePass::render()
pipelineInfo.pipelineLayout = std::move(layout); pipelineInfo.pipelineLayout = std::move(layout);
pipelineInfo.renderPass = renderPass; pipelineInfo.renderPass = renderPass;
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_LESS_OR_EQUAL; pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_LESS_OR_EQUAL;
pipelineInfo.rasterizationState.lineWidth = 10.f;
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline); command->bindPipeline(pipeline);
} }
@@ -20,8 +20,15 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene)
depthPrepassLayout = graphics->createPipelineLayout(); depthPrepassLayout = graphics->createPipelineLayout();
depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewParamsLayout); depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewParamsLayout);
if (graphics->supportMeshShading())
{
graphics->getShaderCompiler()->registerRenderPass("DepthPass", "MeshletBasePass", false, false, "", true, true, "MeshletBasePass");
}
else
{
graphics->getShaderCompiler()->registerRenderPass("DepthPass", "LegacyBasePass"); graphics->getShaderCompiler()->registerRenderPass("DepthPass", "LegacyBasePass");
} }
}
DepthPrepass::~DepthPrepass() DepthPrepass::~DepthPrepass()
{ {
+1 -1
View File
@@ -111,7 +111,7 @@ void StaticMeshVertexData::deserializeMesh(MeshId id, ArchiveBuffer& buffer)
loadNormals(id, nor); loadNormals(id, nor);
loadTangents(id, tan); loadTangents(id, tan);
loadBiTangents(id, bit); loadBiTangents(id, bit);
loadBiTangents(id, col); loadColors(id, col);
} }
void StaticMeshVertexData::init(Gfx::PGraphics graphics) void StaticMeshVertexData::init(Gfx::PGraphics graphics)
+125 -7
View File
@@ -6,10 +6,11 @@
#include "Graphics/Descriptor.h" #include "Graphics/Descriptor.h"
#include "Component/Mesh.h" #include "Component/Mesh.h"
#include "Graphics/Shader.h" #include "Graphics/Shader.h"
#include <set>
using namespace Seele; using namespace Seele;
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024; constexpr static uint64 NUM_DEFAULT_ELEMENTS = 16 * 1024;
void VertexData::resetMeshData() void VertexData::resetMeshData()
{ {
@@ -17,7 +18,6 @@ void VertexData::resetMeshData()
{ {
mat.material->getDescriptorLayout()->reset(); mat.material->getDescriptorLayout()->reset();
} }
materialData.clear();
if (dirty) if (dirty)
{ {
updateBuffers(); updateBuffers();
@@ -25,7 +25,7 @@ void VertexData::resetMeshData()
} }
} }
void VertexData::updateMesh(const Component::Transform& transform, PMesh mesh) void VertexData::addMesh(PMesh mesh)
{ {
PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial(); PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial();
MaterialData& matData = materialData[mat->getName()]; MaterialData& matData = materialData[mat->getName()];
@@ -34,15 +34,66 @@ void VertexData::updateMesh(const Component::Transform& transform, PMesh mesh)
matInstanceData.meshes.add(MeshInstanceData{ matInstanceData.meshes.add(MeshInstanceData{
.id = mesh->id, .id = mesh->id,
.instance = InstanceData { .instance = InstanceData {
.transformMatrix = transform.toMatrix(), .transformMatrix = Matrix4(),
}, },
.indexBuffer = mesh->indexBuffer, .indexBuffer = mesh->indexBuffer,
}); });
matInstanceData.materialInstance = mesh->referencedMaterial->getHandle(); matInstanceData.materialInstance = mesh->referencedMaterial->getHandle();
matInstanceData.materialInstance->updateDescriptor();
matInstanceData.numMeshes += meshData[mesh->id].size(); matInstanceData.numMeshes += meshData[mesh->id].size();
} }
void VertexData::removeMesh(PMesh mesh)
{
PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial();
MaterialData& matData = materialData[mat->getName()];
matData.material = mat;
MaterialInstanceData& matInstanceData = matData.instances[mesh->referencedMaterial->getHandle()->getId()];
matInstanceData.meshes.remove_if([&mesh](const MeshInstanceData& data) {
return data.id == mesh->id;
});
matInstanceData.materialInstance = mesh->referencedMaterial->getHandle();
matInstanceData.numMeshes -= meshData[mesh->id].size();
}
void VertexData::updateInstances()
{
instanceDataLayout->reset();
for (const auto& [_, mat] : materialData)
{
for (auto& [_, matInst] : mat.instances)
{
Array<InstanceData> instanceData;
for (auto& inst : matInst.meshes)
{
inst.meshes = 0;
for (const auto& mesh : meshData[inst.id])
{
instanceData.add(inst.instance);
inst.meshes++;
}
}
matInst.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(InstanceData) * instanceData.size(),
.data = (uint8*)instanceData.data(),
},
.numElements = instanceData.size(),
.dynamic = false,
});
matInst.descriptorSet = instanceDataLayout->allocateDescriptorSet();
matInst.descriptorSet->updateBuffer(0, matInst.instanceBuffer);
if (graphics->supportMeshShading())
{
matInst.descriptorSet->updateBuffer(1, matInst.meshDataBuffer);
matInst.descriptorSet->updateBuffer(2, meshletBuffer);
matInst.descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
matInst.descriptorSet->updateBuffer(4, vertexIndicesBuffer);
}
matInst.descriptorSet->writeChanges();
}
}
}
void VertexData::createDescriptors() void VertexData::createDescriptors()
{ {
instanceDataLayout->reset(); instanceDataLayout->reset();
@@ -50,14 +101,12 @@ void VertexData::createDescriptors()
{ {
for (auto& [_, matInst] : mat.instances) for (auto& [_, matInst] : mat.instances)
{ {
Array<InstanceData> instanceData;
Array<MeshData> meshes; Array<MeshData> meshes;
for (auto& inst : matInst.meshes) for (auto& inst : matInst.meshes)
{ {
inst.meshes = 0; inst.meshes = 0;
for (const auto& mesh : meshData[inst.id]) for (const auto& mesh : meshData[inst.id])
{ {
instanceData.add(inst.instance);
meshes.add(mesh); meshes.add(mesh);
inst.meshes++; inst.meshes++;
} }
@@ -95,6 +144,9 @@ void VertexData::createDescriptors()
void VertexData::loadMesh(MeshId id, Array<Meshlet> loadedMeshlets) void VertexData::loadMesh(MeshId id, Array<Meshlet> loadedMeshlets)
{ {
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
meshData[id].clear(); meshData[id].clear();
uint32 currentMesh = 0; uint32 currentMesh = 0;
while (currentMesh < loadedMeshlets.size()) while (currentMesh < loadedMeshlets.size())
@@ -239,3 +291,69 @@ void Meshlet::load(ArchiveBuffer& buffer)
Serialization::load(buffer, numVertices); Serialization::load(buffer, numVertices);
Serialization::load(buffer, numPrimitives); Serialization::load(buffer, numPrimitives);
} }
void Seele::Meshlet::buildFromIndexBuffer(const Array<uint32>& indices, Array<Meshlet>& meshlets)
{
std::set<uint32> uniqueVertices;
Meshlet current = {
.numVertices = 0,
.numPrimitives = 0,
};
auto insertAndGetIndex = [&uniqueVertices, &current](uint32 index) -> int8_t
{
auto [it, inserted] = uniqueVertices.insert(index);
if (inserted)
{
if (current.numVertices == Gfx::numVerticesPerMeshlet)
{
return -1;
}
current.uniqueVertices[current.numVertices] = index;
return current.numVertices++;
}
else
{
for (uint32 i = 0; i < current.numVertices; ++i)
{
if (current.uniqueVertices[i] == index)
{
return i;
}
}
assert(false);
}
};
auto completeMeshlet = [&meshlets, &current, &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();
}
}
+9 -2
View File
@@ -17,6 +17,10 @@ struct MeshId
{ {
return id <=> other.id; return id <=> other.id;
} }
bool operator==(const MeshId& other) const
{
return id == other.id;
}
}; };
struct Meshlet struct Meshlet
{ {
@@ -26,6 +30,7 @@ struct Meshlet
uint32 numPrimitives; uint32 numPrimitives;
void save(ArchiveBuffer& buffer) const; void save(ArchiveBuffer& buffer) const;
void load(ArchiveBuffer& buffer); void load(ArchiveBuffer& buffer);
static void buildFromIndexBuffer(const Array<uint32>& indices, Array<Meshlet>& meshlets);
}; };
class VertexData class VertexData
{ {
@@ -47,7 +52,7 @@ public:
Gfx::OShaderBuffer instanceBuffer; Gfx::OShaderBuffer instanceBuffer;
Gfx::OShaderBuffer meshDataBuffer; Gfx::OShaderBuffer meshDataBuffer;
Gfx::PDescriptorSet descriptorSet; Gfx::PDescriptorSet descriptorSet;
uint32 numMeshes; // not necessarily equal to meshes.size() if a MeshId has multiple meshes uint32 numMeshes = 0; // not necessarily equal to meshes.size() if a MeshId has multiple meshes
Array<MeshInstanceData> meshes; Array<MeshInstanceData> meshes;
}; };
struct MaterialData struct MaterialData
@@ -62,7 +67,9 @@ public:
uint32 indicesOffset; uint32 indicesOffset;
}; };
void resetMeshData(); void resetMeshData();
void updateMesh(const Component::Transform& transform, PMesh mesh); void addMesh(PMesh mesh);
void removeMesh(PMesh mesh);
void updateInstances();
void createDescriptors(); void createDescriptors();
void loadMesh(MeshId id, Array<Meshlet> meshlets); void loadMesh(MeshId id, Array<Meshlet> meshlets);
MeshId allocateVertexData(uint64 numVertices); MeshId allocateVertexData(uint64 numVertices);
+1 -1
View File
@@ -327,7 +327,7 @@ OStagingBuffer StagingManager::create(uint64 size)
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.size = size, .size = size,
.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 1, .queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &queueIndex, .pQueueFamilyIndices = &queueIndex,
+11 -12
View File
@@ -359,11 +359,15 @@ void Graphics::pickPhysicalDevice()
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()); vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data());
VkPhysicalDevice bestDevice = VK_NULL_HANDLE; VkPhysicalDevice bestDevice = VK_NULL_HANDLE;
uint32 deviceRating = 0; uint32 deviceRating = 0;
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features.pNext = &features12;
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
features12.pNext = nullptr;
for (auto dev : physicalDevices) for (auto dev : physicalDevices)
{ {
uint32 currentRating = 0; uint32 currentRating = 0;
vkGetPhysicalDeviceProperties(dev, &props); vkGetPhysicalDeviceProperties(dev, &props);
vkGetPhysicalDeviceFeatures(dev, &features); vkGetPhysicalDeviceFeatures2(dev, &features);
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
{ {
std::cout << "found dedicated gpu " << props.deviceName << std::endl; std::cout << "found dedicated gpu " << props.deviceName << std::endl;
@@ -382,8 +386,9 @@ void Graphics::pickPhysicalDevice()
} }
} }
physicalDevice = bestDevice; physicalDevice = bestDevice;
vkGetPhysicalDeviceProperties(physicalDevice, &props); vkGetPhysicalDeviceProperties(physicalDevice, &props);
vkGetPhysicalDeviceFeatures(physicalDevice, &features); vkGetPhysicalDeviceFeatures2(physicalDevice, &features);
if (Gfx::useMeshShading) if (Gfx::useMeshShading)
{ {
uint32 count = 0; uint32 count = 0;
@@ -500,31 +505,25 @@ void Graphics::createDevice(GraphicsInitializer initializer)
*currentPriority++ = 1.0f; *currentPriority++ = 1.0f;
} }
} }
VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexing = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
.descriptorBindingPartiallyBound = VK_TRUE,
.descriptorBindingVariableDescriptorCount = VK_TRUE,
.runtimeDescriptorArray = VK_TRUE,
};
VkPhysicalDeviceMeshShaderFeaturesEXT enabledMeshShaderFeatures = { VkPhysicalDeviceMeshShaderFeaturesEXT enabledMeshShaderFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
.pNext = nullptr,
.taskShader = VK_TRUE, .taskShader = VK_TRUE,
.meshShader = VK_TRUE, .meshShader = VK_TRUE,
}; };
if (supportMeshShading()) if (supportMeshShading())
{ {
descriptorIndexing.pNext = &enabledMeshShaderFeatures; features12.pNext = &enabledMeshShaderFeatures;
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME); initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
} }
VkDeviceCreateInfo deviceInfo = { VkDeviceCreateInfo deviceInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &descriptorIndexing, .pNext = &features12,
.queueCreateInfoCount = (uint32)queueInfos.size(), .queueCreateInfoCount = (uint32)queueInfos.size(),
.pQueueCreateInfos = queueInfos.data(), .pQueueCreateInfos = queueInfos.data(),
.enabledExtensionCount = (uint32)initializer.deviceExtensions.size(), .enabledExtensionCount = (uint32)initializer.deviceExtensions.size(),
.ppEnabledExtensionNames = initializer.deviceExtensions.data(), .ppEnabledExtensionNames = initializer.deviceExtensions.data(),
.pEnabledFeatures = &features, .pEnabledFeatures = &features.features,
}; };
VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle)); VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle));
+2 -1
View File
@@ -91,7 +91,8 @@ protected:
thread_local static OCommandPool transferCommands; thread_local static OCommandPool transferCommands;
thread_local static OCommandPool dedicatedTransferCommands; thread_local static OCommandPool dedicatedTransferCommands;
VkPhysicalDeviceProperties props; VkPhysicalDeviceProperties props;
VkPhysicalDeviceFeatures features; VkPhysicalDeviceFeatures2 features;
VkPhysicalDeviceVulkan12Features features12;
VkDebugReportCallbackEXT callback; VkDebugReportCallbackEXT callback;
Map<uint32, OFramebuffer> allocatedFramebuffers; Map<uint32, OFramebuffer> allocatedFramebuffers;
OAllocator allocator; OAllocator allocator;
@@ -358,7 +358,6 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo gfxI
if (graphicsPipelines.contains(hash)) if (graphicsPipelines.contains(hash))
{ {
std::cout << "Caching pipeline" << std::endl;
return graphicsPipelines[hash]; return graphicsPipelines[hash];
} }
VkPipeline pipelineHandle; VkPipeline pipelineHandle;
+2 -2
View File
@@ -257,14 +257,14 @@ void Window::chooseSwapSurfaceFormat()
void Window::chooseSwapPresentMode() void Window::chooseSwapPresentMode()
{ {
for (const auto& supportedPresentMode : supportedPresentModes) /*for (const auto& supportedPresentMode : supportedPresentModes)
{ {
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
{ {
presentMode = supportedPresentMode; presentMode = supportedPresentMode;
return; return;
} }
} }*/
presentMode = VK_PRESENT_MODE_FIFO_KHR; presentMode = VK_PRESENT_MODE_FIFO_KHR;
} }
+1
View File
@@ -85,6 +85,7 @@ void MaterialInstance::setBaseMaterial(PMaterialAsset asset)
); );
} }
baseMaterial = asset; baseMaterial = asset;
updateDescriptor();
} }
void MaterialInstance::save(ArchiveBuffer& buffer) const void MaterialInstance::save(ArchiveBuffer& buffer) const
+10
View File
@@ -44,6 +44,16 @@ public:
{ {
registry.view<Component...>().each(func); registry.view<Component...>().each(func);
} }
template<typename Component>
auto constructCallback()
{
return registry.on_construct<Component>();
}
template<typename Component>
auto destroyCallback()
{
return registry.on_destroy<Component>();
}
PLightEnvironment getLightEnvironment() { return lightEnv; } PLightEnvironment getLightEnvironment() { return lightEnv; }
Gfx::PGraphics getGraphics() const { return graphics; } Gfx::PGraphics getGraphics() const { return graphics; }
entt::registry registry; entt::registry registry;
+15 -4
View File
@@ -4,18 +4,29 @@ using namespace Seele;
using namespace Seele::System; using namespace Seele::System;
MeshUpdater::MeshUpdater(PScene scene) MeshUpdater::MeshUpdater(PScene scene)
: ComponentSystem<Component::Transform, Component::Mesh>(scene) : SystemBase(scene)
{ {
scene->view<Component::Mesh>([&](entt::entity id, Component::Mesh& mesh) {
meshEntities.add(id);
});
scene->constructCallback<Component::Mesh>().connect<&MeshUpdater::on_construct>(this);
scene->destroyCallback<Component::Mesh>().connect<&MeshUpdater::on_destroy>(this);
} }
MeshUpdater::~MeshUpdater() MeshUpdater::~MeshUpdater()
{ {
} }
void MeshUpdater::update(Component::Transform& transform, Component::Mesh& meshComp) void MeshUpdater::update()
{ {
for(const auto& mesh : meshComp.asset->meshes) }
void MeshUpdater::on_construct(entt::registry& reg, entt::entity id)
{ {
mesh->vertexData->updateMesh(transform, mesh); meshEntities.add(id);
} }
void MeshUpdater::on_destroy(entt::registry& reg, entt::entity id)
{
meshEntities.remove(id, false);
} }
+6 -3
View File
@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "ComponentSystem.h" #include "SystemBase.h"
#include "Component/Transform.h" #include "Component/Transform.h"
#include "Component/Mesh.h" #include "Component/Mesh.h"
@@ -7,13 +7,16 @@ namespace Seele
{ {
namespace System namespace System
{ {
class MeshUpdater : public ComponentSystem<Component::Transform, Component::Mesh> class MeshUpdater : public SystemBase
{ {
public: public:
MeshUpdater(PScene scene); MeshUpdater(PScene scene);
virtual ~MeshUpdater(); virtual ~MeshUpdater();
virtual void update(Component::Transform& transform, Component::Mesh& mesh) override; virtual void update() override;
private: private:
Array<entt::entity> meshEntities;
void on_construct(entt::registry& reg, entt::entity id);
void on_destroy(entt::registry& reg, entt::entity id);
}; };
} // namespace System } // namespace System
} // namespace Seele } // namespace Seele