Split Meshlets to Groups.
Return one group with all meshlets.
Return if less than 8 meshlets.
xadj.
adjncy. Stores Meshlets Index.
Connect meshlets Count of each meshlet.
Skip if edge is internal edge.
Iter connected edge's meshlets.
Get a connect other meshlet.
Split Meshlets to Part.
Return groups.
Return one group with all meshlets.
Return if less than 8 meshlets.
xadj.
adjncy. Stores Meshlets Index.
Connect meshlets Count of each meshlet.
Skip if edge is internal edge.
Iter connected edge's meshlets.
Get a connect other meshlet.
Split Meshlets to Part.
Return groups.
318 {
320
324 auto groupWithMeshlets = [&]()
325 {
326 MeshletGroup group;
327 for (int i = 0; i < meshlets.size(); ++i)
328 {
329 group.meshlets.push_back(i);
330 }
331 return std::vector{ group };
332 };
333
337 if (meshlets.size() < 8)
338 {
339 return groupWithMeshlets();
340 }
341
342 std::unordered_map<Edge, std::set<size_t>> edges2Meshlets;
343 std::unordered_map<size_t, std::vector<Edge>> meshlets2Edges;
344
345 for (size_t meshletIndex = 0; meshletIndex < meshlets.size(); meshletIndex++)
346 {
347 const auto& meshlet = meshlets[meshletIndex];
348
349 for (size_t triangleIndex = 0; triangleIndex < meshlet.nPrimitives; triangleIndex++)
350 {
351 const glm::uvec3& primPts = (*meshPack->m_MeshResource.primitivePoints.attributes)[meshlet.primitiveOffset + triangleIndex];
352
353 Edge edge0{ primPts.x , primPts.y };
354 Edge edge1{ primPts.y , primPts.z };
355 Edge edge2{ primPts.z , primPts.x };
356
357 edges2Meshlets[edge0].insert(meshletIndex);
358 edges2Meshlets[edge1].insert(meshletIndex);
359 edges2Meshlets[edge2].insert(meshletIndex);
360
361 meshlets2Edges[meshletIndex].push_back(edge0);
362 meshlets2Edges[meshletIndex].push_back(edge1);
363 meshlets2Edges[meshletIndex].push_back(edge2);
364 }
365 }
366
367
368
369
370 for (auto first = edges2Meshlets.begin(), last = edges2Meshlets.end(); first != last;)
371 {
372 if ((*first).second.size() <= 1)
373 {
374 first = edges2Meshlets.erase(first);
375 }
376 else
377 {
378 ++first;
379 }
380 }
381
382
383
384
385 if (edges2Meshlets.empty())
386 {
387 return groupWithMeshlets();
388 }
389
390 idx_t vertexCount = meshlets.size();
391 idx_t ncon = 1;
392 idx_t nparts = meshlets.size() / 4;
393 assert(nparts > 1);
394
395 idx_t options[METIS_NOPTIONS];
396 METIS_SetDefaultOptions(options);
397
398 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;
399 options[METIS_OPTION_CCORDER] = 1;
400
401 std::vector<idx_t> partition;
402 partition.resize(vertexCount);
403
407 std::vector<idx_t> xadjacency;
408 xadjacency.reserve(vertexCount + 1);
409
414 std::vector<idx_t> edgeAdjacency;
415
419 std::vector<idx_t> edgeWeights;
420
421 for (size_t meshletIndex = 0; meshletIndex < meshlets.size(); meshletIndex++)
422 {
423 size_t startIndexInEdgeAdjacency = edgeAdjacency.size();
424 for (const auto& edge : meshlets2Edges[meshletIndex])
425 {
429 auto connectionsIter = edges2Meshlets.find(edge);
430 if (connectionsIter == edges2Meshlets.end())
431 {
432 continue;
433 }
434
438 const auto& connections = connectionsIter->second;
439 for (const auto& connectedMeshlet : connections)
440 {
444 if (connectedMeshlet != meshletIndex)
445 {
446 auto existingEdgeIter = std::find(edgeAdjacency.begin() + startIndexInEdgeAdjacency, edgeAdjacency.end(), connectedMeshlet);
447 if (existingEdgeIter == edgeAdjacency.end())
448 {
449 edgeAdjacency.emplace_back(connectedMeshlet);
450 edgeWeights.emplace_back(1);
451 }
452 else
453 {
454 std::ptrdiff_t
d = std::distance(edgeAdjacency.begin(), existingEdgeIter);
455 assert(d >= 0 && d < edgeWeights.size());
457 }
458 }
459 }
460 }
461 xadjacency.push_back(startIndexInEdgeAdjacency);
462 }
463 xadjacency.push_back(edgeAdjacency.size());
464
465 assert(xadjacency.size() == meshlets.size() + 1);
466 assert(edgeAdjacency.size() == edgeWeights.size());
467
471 idx_t edgeCut;
472 int result = METIS_PartGraphKway(
473 &vertexCount,
474 &ncon,
475 xadjacency.data(),
476 edgeAdjacency.data(),
477 nullptr,
478 nullptr,
479 edgeWeights.data(),
480 &nparts,
481 nullptr,
482 nullptr,
483 options,
484 &edgeCut,
485 partition.data()
486 );
487
488 assert(result == METIS_OK);
489
493 std::vector<MeshletGroup> groups;
494 groups.resize(nparts);
495 for (size_t i = 0; i < meshlets.size(); i++)
496 {
497 idx_t partitionNumber = partition[i];
498 groups[partitionNumber].meshlets.push_back(i);
499 }
500
501 return groups;
502 }
#define SPICES_PROFILE_ZONE