Skip to content

Export Pointcache: Optimize forced shader assignments when writing face sets#442

Open
BigRoy wants to merge 8 commits into
developfrom
enhancement/maya_force_shader_assignments_to_faces_use_api
Open

Export Pointcache: Optimize forced shader assignments when writing face sets#442
BigRoy wants to merge 8 commits into
developfrom
enhancement/maya_force_shader_assignments_to_faces_use_api

Conversation

@BigRoy

@BigRoy BigRoy commented May 23, 2026

Copy link
Copy Markdown
Member

Changelog Description

Export Pointcache: Optimize forced shader assignments when writing face sets

Additional review information

Fix #441

To performance test:

import datetime

from ayon_maya.api.lib import force_shader_assignments_to_faces
from maya import cmds


##############################################

prev_time = datetime.datetime.now()

def log(*args, reset=False):
    global prev_time
    if reset:
        prev_time = datetime.datetime.now()

    now = datetime.datetime.now()

    ts = now.strftime("%H:%M:%S")
    diff = now - prev_time
    diff_s = diff.total_seconds() % 60
    diff_m = diff.total_seconds() // 60
    diff_str = f"{diff_m:.0f}m {diff_s:5.2f}s"
    print(f"[{ts} +{diff_str}]", *args)
    prev_time = now


##############################################

def add_cubes(count=100):
    root = cmds.group(empty=True, name="root")
    for i in range(count):
        transform, _ = cmds.polyCube(name=f"cube{i:02d}")
        cmds.parent(transform, root)


def main():
    cmds.file(newFile=True, force=True)
    log("start", reset=True)

    log("add cubes")
    add_cubes(5_000)
    log("cubes added")

    meshes = cmds.ls("cube*", type="mesh", long=True)
    log("found", len(meshes), "cubes")

    log("pre enter")
    with force_shader_assignments_to_faces(meshes):
        log("in")
        pass
    log("out")


if __name__ == "__main__":
    main()

Testing notes:

  1. Publishing with write face sets should still work and produce correct results.
  2. It should be faster.

@BigRoy BigRoy requested a review from moonyuet May 23, 2026 18:52
@BigRoy BigRoy self-assigned this May 23, 2026
@BigRoy BigRoy added type: enhancement Improvement of existing functionality or minor addition sponsored This is directly sponsored by a client or community member labels May 23, 2026
@BigRoy BigRoy requested review from LiborBatek and Copilot May 25, 2026 21:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets the performance bottleneck in force_shader_assignments_to_faces used during pointcache export (write face sets), by replacing slow cmds.sets(clear=...) / cmds.sets(..., forceElement=...) operations with Maya API 2.0 (OpenMaya) set membership operations and a custom “fast clear” implementation.

Changes:

  • Added _get_mobject and _fast_clear_set helpers to work with sets via OpenMaya and clear set membership by disconnecting dagSetMembers.
  • Reworked force_shader_assignments_to_faces to gather/apply/revert set members using OpenMaya.MFnSet.getMembers / addMembers and MSelectionList instead of cmds.sets member lists.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

override_assignments[shading_engine].append(member)
else:
# Preserve component assignment
override_assignments[shading_engine].add((dag, component))
Comment on lines +4700 to 4704
# Convert to face assignment
override_assignments[shading_engine].add(
f'{shape_path}.f[*]'
)
has_conversions = True
Comment on lines +4641 to +4649
fn = OpenMaya.MFnDependencyNode(_get_mobject(object_set))
dag_set_members = fn.findPlug("dagSetMembers", False)
mod = OpenMaya.MDGModifier()
for i in range(dag_set_members.numElements()):
elem = dag_set_members.elementByPhysicalIndex(i)
if elem.isConnected:
src_plugs = elem.connectedTo(True, False)
for src in src_plugs:
mod.disconnect(src, elem)

@moonyuet moonyuet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested successfully in Maya 2027

@LiborBatek LiborBatek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldnt achieve an alembic containing any face sets no matter how hard I have tried...I also tried not just pointcache but also model in alembic repre but no luck...

Image

interestingly even if I deviated from the default values for Write Face Sets which were Disabled by default...it start to validate only if publishing the pointcache but not when trying to produce a model and Alembic repre...which brings me feeling that while trying to use it for model it still sticks to the defaults (AYON didnt fail on validation when overriding those defaults - or these arent triggered and gracefully ignored) As I was inspecting my published pointcache and model I havent found any face sets whatsoever...

Here is my hierachy and graph before and after loading resulting product:

Image Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sponsored This is directly sponsored by a client or community member type: enhancement Improvement of existing functionality or minor addition

Projects

None yet

Development

Successfully merging this pull request may close these issues.

YN-0765: Extract Pointcache: forced shader assignment slow performance

5 participants