Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize MorphTargetBindingMerger with minimum Dictionary usage #2135

Merged
merged 7 commits into from
Aug 17, 2023

Conversation

Santarh
Copy link
Contributor

@Santarh Santarh commented Aug 17, 2023

VRM10 のランタイムの処理高速化実装です。

スマートフォンやスタンドアロン VR デバイスといったモバイル環境においては Expression に関する毎フレームの定常処理の負荷は無視できない程度に大きい。

#2130 においてそもそもの呼び出し回数を半分に減らせたので x2 Faster となったが、さらに内部の処理も高速化を行う。

Process master This PR
ExpressionMerger.SetValues() in Editor 3.16ms 1.93ms
MorphTargetBindingMerger.AccumulateValue() 1.79ms 1.13ms
MorphTargetBindingMerger.Apply() 1.19ms 0.46ms

この PR では MorphTarget 、つまり Unity では BlendShape を対象とした Expression 処理の負荷軽減を行った。
一般的にセットアップされた VRM モデルにおいては #2130 と合わせて x3 Faster となったと期待できる。

@Santarh Santarh requested a review from notargs August 17, 2023 08:11

public void AccumulateValue(ExpressionKey key, float value)
{
if (!_keyIndexReverseMap.TryGetValue(key, out var idx)) return;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

毎フレーム処理での、唯一の Dictionary 呼び出し場所。
1モデルあたり、そのモデルが持つ ExpressionClip の数(デフォルト18)だけ呼ばれる。

@@ -156,7 +156,7 @@ public bool Equals(ExpressionKey other)

if (Preset != other.Preset) return false;
if (Preset != ExpressionPreset.custom) return true;
return Name == other.Name;
return Name.Equals(other.Name, StringComparison.Ordinal);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

string の比較は、デフォルトだと Culture を考慮しており、低速かつ他言語で予期せぬ動作になる恐れがある。
この Name はカルチャを考慮する必要はない。

Comment on lines +25 to +26
public int TargetRendererInstanceId { get; }
public int TargetBlendShapeIndex { get; }
Copy link
Contributor Author

@Santarh Santarh Aug 17, 2023

Choose a reason for hiding this comment

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

レンダラの InstanceID と BlendShape Index の組み合わせで、操作対象箇所を Identity する。
レンダラは UnityEngine.Object の == null になる可能性があるが、この struct の同値判定においては考慮しない。

Copy link
Contributor

@notargs notargs left a comment

Choose a reason for hiding this comment

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

LGTM 👍

_expressions = expressionAvatar.Clips.ToDictionary(
x => expressionAvatar.CreateKey(x.Clip),
x => x.Clip,
ExpressionKey.Comparer
Copy link
Contributor

Choose a reason for hiding this comment

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

ExpressionKey.Comparerを渡す
keysは改行しただけ

/// Dictionary を使用すると、その GetEnumerator()(foreach) や get/set を 100,1000 オーダーで呼び出すことになる。
/// するとモバイル環境ではかなりの定常負荷になってしまうため、その使用を避けて実装する。
/// </summary>
internal sealed class MorphTargetBindingMerger
Copy link
Contributor

Choose a reason for hiding this comment

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

Expression/MorphTargetBindingManager.cs -> Expression/MorphTargetBindingManager/MorphTargetBindingManager.cs
に移動

/// <summary>
/// index access with [_keyOrder][*]
/// </summary>
private readonly RuntimeMorphTargetBinding[][] _bindings;
Copy link
Contributor

Choose a reason for hiding this comment

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

[質問] 2次元配列ではなくジャグ配列を用いているのは要素ごとにサイズが違う可能性があるから?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

そうです!

@Santarh Santarh merged commit e6633dc into vrm-c:master Aug 17, 2023
1 check passed
@Santarh Santarh deleted the expressionFaster branch August 17, 2023 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants