-
Notifications
You must be signed in to change notification settings - Fork 409
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
Conversation
|
||
public void AccumulateValue(ExpressionKey key, float value) | ||
{ | ||
if (!_keyIndexReverseMap.TryGetValue(key, out var idx)) return; |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
string
の比較は、デフォルトだと Culture を考慮しており、低速かつ他言語で予期せぬ動作になる恐れがある。
この Name
はカルチャを考慮する必要はない。
public int TargetRendererInstanceId { get; } | ||
public int TargetBlendShapeIndex { get; } |
There was a problem hiding this comment.
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 の同値判定においては考慮しない。
There was a problem hiding this 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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[質問] 2次元配列ではなくジャグ配列を用いているのは要素ごとにサイズが違う可能性があるから?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
そうです!
VRM10 のランタイムの処理高速化実装です。
スマートフォンやスタンドアロン VR デバイスといったモバイル環境においては Expression に関する毎フレームの定常処理の負荷は無視できない程度に大きい。
#2130 においてそもそもの呼び出し回数を半分に減らせたので x2 Faster となったが、さらに内部の処理も高速化を行う。
ExpressionMerger.SetValues()
in EditorMorphTargetBindingMerger.AccumulateValue()
MorphTargetBindingMerger.Apply()
この PR では MorphTarget 、つまり Unity では BlendShape を対象とした Expression 処理の負荷軽減を行った。
一般的にセットアップされた VRM モデルにおいては #2130 と合わせて x3 Faster となったと期待できる。