Resolve WES-90 "Integrate signpredictor in courses"
This commit is contained in:
committed by
Jerome Coudron
parent
1a75791d62
commit
746906294b
@@ -14,12 +14,10 @@
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll",
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS",
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,9 @@
|
||||
"references": [
|
||||
"Unity.TextMeshPro",
|
||||
"AccountsScripts",
|
||||
"InterfacesScripts"
|
||||
"InterfacesScripts",
|
||||
"SignPredictor",
|
||||
"Tween"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
123
Assets/Courses/Scripts/Feedback.cs
Normal file
123
Assets/Courses/Scripts/Feedback.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
//using Mediapipe.Unity.Tutorial;
|
||||
using Mediapipe.Unity.Tutorial;
|
||||
using System.Collections;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
// for your own scripts make sure to add the following line:
|
||||
using DigitalRuby.Tween;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Assets.Courses.Scripts
|
||||
{
|
||||
public class Feedback : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the feedback field
|
||||
/// </summary>
|
||||
public TMP_Text feedback;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the sign predictor
|
||||
/// </summary>
|
||||
public Wesign_extractor signPredictor;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the TemplateCourse
|
||||
/// </summary>
|
||||
public TemplateCourse templateCourse;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the progress bar
|
||||
/// </summary>
|
||||
public GameObject progress;
|
||||
|
||||
/// <summary>
|
||||
/// Start is called before the first frame update
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
// Start the coroutine to update the scale every 200 milliseconds
|
||||
StartCoroutine(UpdateFeedback());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdateScale updates the progress bar every 200ms, updated the feedback text, and progress bar color
|
||||
/// If a high enough accuracy is detected, it will go to the next sign
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerator UpdateFeedback()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Get current sign
|
||||
char currentSign = (char)(65 + templateCourse.GetWordIndex());
|
||||
//Debug.Log(currentSign);
|
||||
// Get the predicted sign
|
||||
if (signPredictor != null && signPredictor.letterProbabilities != null && signPredictor.letterProbabilities.ContainsKey(currentSign))
|
||||
{
|
||||
int accuracy = (int)(signPredictor.letterProbabilities[currentSign] * 100);
|
||||
if (accuracy > 98)
|
||||
{
|
||||
feedback.text = "Perfect!!!";
|
||||
feedback.color = Color.green;
|
||||
progress.GetComponent<Image>().color = Color.green;
|
||||
}
|
||||
else if (accuracy > 95)
|
||||
{
|
||||
feedback.text = "Super!";
|
||||
feedback.color = Color.green;
|
||||
progress.GetComponent<Image>().color = Color.green;
|
||||
}
|
||||
else if (accuracy > 90)
|
||||
{
|
||||
feedback.text = "Goed";
|
||||
feedback.color = Color.green;
|
||||
progress.GetComponent<Image>().color = Color.green;
|
||||
}
|
||||
else if (accuracy > 80)
|
||||
{
|
||||
feedback.text = "Bijna...";
|
||||
feedback.color = new Color(0xFF, 0xE5, 0x00);
|
||||
progress.GetComponent<Image>().color = new Color(0xFF, 0xE5, 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
feedback.text = "Detecteren ...";
|
||||
feedback.color = Color.red;
|
||||
progress.GetComponent<Image>().color = Color.red;
|
||||
}
|
||||
// use an exponential scale
|
||||
float newScale = Mathf.Exp(((float)accuracy / 24.5f) - 4);
|
||||
Vector3 newScaleVector = new Vector3(newScale,
|
||||
progress.transform.localScale.y,
|
||||
progress.transform.localScale.z);
|
||||
System.Action<ITween<Vector3>> updateProgressScale = (t) =>
|
||||
{
|
||||
if (progress != null)
|
||||
{
|
||||
progress.transform.localScale = t.CurrentValue;
|
||||
}
|
||||
|
||||
};
|
||||
progress.Tween("ScaleProgress", progress.transform.localScale, newScaleVector, 0.2f, TweenScaleFunctions.CubicEaseInOut, updateProgressScale);
|
||||
|
||||
if (accuracy > 90)
|
||||
{
|
||||
// Wait and go to next sign
|
||||
yield return new WaitForSeconds(1);
|
||||
templateCourse.NextSign();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
progress.transform.localScale = new Vector3(0f, progress.transform.localScale.y, progress.transform.localScale.z);
|
||||
//Debug.Log("doesn't contain A");
|
||||
}
|
||||
|
||||
// Wait for 200 milliseconds before updating the scale again
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Courses/Scripts/Feedback.cs.meta
Normal file
11
Assets/Courses/Scripts/Feedback.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44e682a32ee15cc489bf50f3a06f717b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -29,10 +29,6 @@ public class TemplateCourse : MonoBehaviour
|
||||
/// </summary>
|
||||
public Button feedback;
|
||||
|
||||
/// <summary>
|
||||
/// This is a reference to the PANEL that holds the feedbackwindow
|
||||
/// </summary>
|
||||
public GameObject feedbackPopup;
|
||||
|
||||
/// <summary>
|
||||
/// This is a reference to the textfield that holds the part of the feedback-window that will change: bad/good/excellent
|
||||
@@ -134,15 +130,15 @@ public class TemplateCourse : MonoBehaviour
|
||||
void Awake()
|
||||
{
|
||||
// Setting up Webcam
|
||||
feedbackPopup.SetActive(false);
|
||||
if (WebCamTexture.devices.Length > 0)
|
||||
{
|
||||
WebCamDevice device = WebCamTexture.devices[camdex];
|
||||
tex = new WebCamTexture(device.name);
|
||||
webcamDisplay.texture = tex;
|
||||
// feedbackPopup.SetActive(false);
|
||||
//if (WebCamTexture.devices.Length > 0)
|
||||
//{
|
||||
// WebCamDevice device = WebCamTexture.devices[camdex];
|
||||
// tex = new WebCamTexture(device.name);
|
||||
// webcamDisplay.texture = tex;
|
||||
|
||||
tex.Play();
|
||||
}
|
||||
// tex.Play();
|
||||
//}
|
||||
|
||||
// Setting up course
|
||||
course = courselist.courses[courselist.currentCourseIndex];
|
||||
@@ -160,6 +156,9 @@ public class TemplateCourse : MonoBehaviour
|
||||
}
|
||||
userList.Save();
|
||||
|
||||
// Force the videoplayer to add bars to preserve aspect ratio
|
||||
player.aspectRatio = VideoAspectRatio.FitInside;
|
||||
|
||||
// Setup UI
|
||||
button.image.sprite = pauseSprite;
|
||||
title.text = course.name;
|
||||
@@ -305,9 +304,9 @@ public class TemplateCourse : MonoBehaviour
|
||||
/// <param name="sceneName"> The path for the scene you want to travel to, assuming root-directory is Assets</param>
|
||||
public void Back()
|
||||
{
|
||||
webcamDisplay.texture = null;
|
||||
tex.Stop();
|
||||
tex = null;
|
||||
//webcamDisplay.texture = null;
|
||||
//tex.Stop();
|
||||
//tex = null;
|
||||
|
||||
SystemController.GetInstance().BackToPreviousScene();
|
||||
}
|
||||
@@ -316,27 +315,34 @@ public class TemplateCourse : MonoBehaviour
|
||||
/// This function toggles between inactivity and activity for the popup panel.
|
||||
/// This will be changed later when the model gets integrated, probably being timed to dissapear.
|
||||
/// </summary>
|
||||
public void ShowFeedback()
|
||||
//public void ShowFeedback()
|
||||
//{
|
||||
// if (feedbackPopup.activeSelf)
|
||||
// {
|
||||
// dynamic.text = "";
|
||||
// feedbackPopup.SetActive(false);
|
||||
// return;
|
||||
// }
|
||||
// double index = UnityEngine.Random.value;
|
||||
// if (index < 0.5)
|
||||
// {
|
||||
// dynamic.text = "Poor";
|
||||
// }
|
||||
// else if (index > 0.8)
|
||||
// {
|
||||
// dynamic.text = "Excellent";
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dynamic.text = "Good";
|
||||
// }
|
||||
// feedbackPopup.SetActive(true);
|
||||
//}
|
||||
|
||||
// Get currentWordIndex
|
||||
public int GetWordIndex()
|
||||
{
|
||||
if (feedbackPopup.activeSelf)
|
||||
{
|
||||
dynamic.text = "";
|
||||
feedbackPopup.SetActive(false);
|
||||
return;
|
||||
}
|
||||
double index = UnityEngine.Random.value;
|
||||
if (index < 0.5)
|
||||
{
|
||||
dynamic.text = "Poor";
|
||||
}
|
||||
else if (index > 0.8)
|
||||
{
|
||||
dynamic.text = "Excellent";
|
||||
}
|
||||
else
|
||||
{
|
||||
dynamic.text = "Good";
|
||||
}
|
||||
feedbackPopup.SetActive(true);
|
||||
return currentWordIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
147
Assets/MediaPipeUnity/Common/Scripts/KeypointManager.cs
Normal file
147
Assets/MediaPipeUnity/Common/Scripts/KeypointManager.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
public class ModelInfo
|
||||
{
|
||||
public List<int> pose_landmarks;
|
||||
public List<int> hand_landmarks;
|
||||
}
|
||||
|
||||
public class KeypointManager
|
||||
{
|
||||
|
||||
private ModelInfo model_info;
|
||||
private List<List<float>> keypoints_buffer;
|
||||
|
||||
public KeypointManager()
|
||||
{
|
||||
TextAsset model_info_json = Resources.Load<TextAsset>("Models/FingerSpelling/landmarks");
|
||||
this.model_info = JsonUtility.FromJson<ModelInfo>(model_info_json.text);
|
||||
this.keypoints_buffer = new List<List<float>>();
|
||||
}
|
||||
|
||||
private (List<float>, List<float>) normalizeHand(List<float> hand_x, List<float> hand_y)
|
||||
{
|
||||
|
||||
float min_x = hand_x.Min();
|
||||
float min_y = hand_y.Min();
|
||||
|
||||
float max_x = hand_x.Max();
|
||||
float max_y = hand_y.Max();
|
||||
|
||||
float width = max_x - min_x;
|
||||
float height = max_y - min_y;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
return (hand_x, hand_y);
|
||||
}
|
||||
|
||||
float center_x = (min_x + max_x) / 2;
|
||||
float center_y = (min_y + max_y) / 2;
|
||||
|
||||
List<float> normalized_x = new List<float>();
|
||||
List<float> normalized_y = new List<float>();
|
||||
|
||||
for (int i = 0; i < hand_x.Count; i++)
|
||||
{
|
||||
normalized_x.Add((hand_x[i] - center_x) / width);
|
||||
normalized_y.Add((hand_y[i] - center_y) / height);
|
||||
}
|
||||
|
||||
return (normalized_x, normalized_y);
|
||||
}
|
||||
|
||||
public void addLandmarks(Mediapipe.NormalizedLandmarkList poseLandmarks, Mediapipe.NormalizedLandmarkList leftHandLandmarks, Mediapipe.NormalizedLandmarkList rightHandLandmarks)
|
||||
{
|
||||
List<float> pose_x = new List<float>();
|
||||
List<float> pose_y = new List<float>();
|
||||
List<float> left_hand_x = new List<float>();
|
||||
List<float> left_hand_y = new List<float>();
|
||||
List<float> right_hand_x = new List<float>();
|
||||
List<float> right_hand_y = new List<float>();
|
||||
|
||||
if (poseLandmarks != null)
|
||||
{
|
||||
foreach (var landmark_index in model_info.pose_landmarks)
|
||||
{
|
||||
pose_x.Add(poseLandmarks.Landmark[landmark_index].X);
|
||||
pose_y.Add(poseLandmarks.Landmark[landmark_index].Y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var landmark_index in model_info.pose_landmarks)
|
||||
{
|
||||
pose_x.Add(0);
|
||||
pose_y.Add(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach (var landmark_index in model_info.hand_landmarks)
|
||||
{
|
||||
if (leftHandLandmarks == null)
|
||||
{
|
||||
left_hand_x.Add(0);
|
||||
left_hand_y.Add(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
left_hand_x.Add(leftHandLandmarks.Landmark[landmark_index].X);
|
||||
left_hand_y.Add(leftHandLandmarks.Landmark[landmark_index].Y);
|
||||
}
|
||||
if (rightHandLandmarks == null)
|
||||
{
|
||||
right_hand_x.Add(0);
|
||||
right_hand_y.Add(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
right_hand_x.Add(rightHandLandmarks.Landmark[landmark_index].X);
|
||||
right_hand_y.Add(rightHandLandmarks.Landmark[landmark_index].Y);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add normalization
|
||||
(left_hand_x, left_hand_y) = normalizeHand(left_hand_x, left_hand_y);
|
||||
(right_hand_x, right_hand_y) = normalizeHand(right_hand_x, right_hand_y);
|
||||
|
||||
|
||||
if (keypoints_buffer.Count >= 10)
|
||||
{
|
||||
keypoints_buffer.RemoveAt(0);
|
||||
}
|
||||
|
||||
List<float> keypoints = new List<float>();
|
||||
for (int i = 0; i < pose_x.Count; i++)
|
||||
{
|
||||
keypoints.Add(pose_x[i]);
|
||||
keypoints.Add(pose_y[i]);
|
||||
}
|
||||
for (int i = 0; i < left_hand_x.Count; i++)
|
||||
{
|
||||
keypoints.Add(left_hand_x[i]);
|
||||
keypoints.Add(left_hand_y[i]);
|
||||
}
|
||||
for (int i = 0; i < right_hand_x.Count; i++)
|
||||
{
|
||||
keypoints.Add(right_hand_x[i]);
|
||||
keypoints.Add(right_hand_y[i]);
|
||||
}
|
||||
|
||||
keypoints_buffer.Add(keypoints);
|
||||
}
|
||||
|
||||
public List<List<float>> getAllKeypoints()
|
||||
{
|
||||
if (keypoints_buffer.Count < 10)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return keypoints_buffer;
|
||||
}
|
||||
}
|
||||
11
Assets/MediaPipeUnity/Common/Scripts/KeypointManager.cs.meta
Normal file
11
Assets/MediaPipeUnity/Common/Scripts/KeypointManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40ff941e1b34847bdb160c6950f35aec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "MediaPipeUnityScripts",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:04c4d86a70aa56c55a78c61f1ab1a56d"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edc93f477bb73a743a97d6882ed330b3
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/MediaPipeUnity/Scenes.meta
Normal file
8
Assets/MediaPipeUnity/Scenes.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c318b35315a4ef44be1df6f27b8b582
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -154,14 +154,14 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1475592761}
|
||||
- {fileID: 2014139443}
|
||||
m_Father: {fileID: 884590458}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 100, y: 100}
|
||||
m_SizeDelta: {x: 1450.822, y: 920.907}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &560904346
|
||||
MonoBehaviour:
|
||||
@@ -325,10 +325,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
_configAsset: {fileID: 4900000, guid: 6288c43cdca97374782dac1ea87aa029, type: 3}
|
||||
_screen: {fileID: 560904347}
|
||||
_width: 640
|
||||
_height: 480
|
||||
_fps: 30
|
||||
_poseLandmarkListAnnotationController: {fileID: 1475592763}
|
||||
_poseLandmarkListAnnotationController: {fileID: 0}
|
||||
_letter: {fileID: 2014139444}
|
||||
--- !u!1 &884590454
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -405,7 +403,7 @@ Canvas:
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_AdditionalShaderChannelsFlag: 25
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
@@ -430,115 +428,6 @@ RectTransform:
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!1001 &937709944
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 1475592761}
|
||||
m_Modifications:
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1915238444563462411, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: PoseLandmarkList Annotation
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
--- !u!4 &937709945 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 1915238444563462410, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
m_PrefabInstance: {fileID: 937709944}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &1475592760
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1475592761}
|
||||
- component: {fileID: 1475592763}
|
||||
m_Layer: 5
|
||||
m_Name: AnnotationLayer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1475592761
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1475592760}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 937709945}
|
||||
m_Father: {fileID: 560904345}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &1475592763
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1475592760}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 70c2b36b394190968977c6493e60e0af, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
annotation: {fileID: 2100643019}
|
||||
_visualizeZ: 0
|
||||
--- !u!1 &1522608646
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -717,14 +606,140 @@ Transform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
|
||||
--- !u!114 &2100643019 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 1915238444563462421, guid: 4418f6a92856c5b51b58a36e3be7ed5c, type: 3}
|
||||
m_PrefabInstance: {fileID: 937709944}
|
||||
--- !u!1 &2014139442
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2014139443}
|
||||
- component: {fileID: 2014139445}
|
||||
- component: {fileID: 2014139444}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2014139443
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2014139442}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 560904345}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 219.5, y: 35.5}
|
||||
m_SizeDelta: {x: 191.357, y: 150.453}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &2014139444
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2014139442}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 39bac9dd52c31ae7aa01a7383bc44853, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: '?
|
||||
|
||||
'
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4278225934
|
||||
m_fontColor: {r: 0.055272277, g: 0.5471698, b: 0, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 79.46
|
||||
m_fontSizeBase: 79.46
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 256
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!222 &2014139445
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2014139442}
|
||||
m_CullTransparentMesh: 1
|
||||
8
Assets/MediaPipeUnity/Scripts.meta
Normal file
8
Assets/MediaPipeUnity/Scripts.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1275314861c48ed40a9f02557c8ca10d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/MediaPipeUnity/Scripts/SignPredictor.asmdef
Normal file
19
Assets/MediaPipeUnity/Scripts/SignPredictor.asmdef
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "SignPredictor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:5c2b5ba89f9e74e418232e154bc5cc7a",
|
||||
"GUID:04c4d86a70aa56c55a78c61f1ab1a56d",
|
||||
"GUID:edc93f477bb73a743a97d6882ed330b3"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/MediaPipeUnity/Scripts/SignPredictor.asmdef.meta
Normal file
7
Assets/MediaPipeUnity/Scripts/SignPredictor.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0b6b39a21908f94fbbd9f2c196a9725
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
343
Assets/MediaPipeUnity/Scripts/Wesign_extractor.cs
Normal file
343
Assets/MediaPipeUnity/Scripts/Wesign_extractor.cs
Normal file
@@ -0,0 +1,343 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
// ATTENTION!: This code is for a tutorial.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using Unity.Barracuda;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace Mediapipe.Unity.Tutorial
|
||||
{
|
||||
public class Wesign_extractor : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Config file to set up the graph
|
||||
/// </summary>
|
||||
[SerializeField] private TextAsset _configAsset;
|
||||
|
||||
/// <summary>
|
||||
/// The screen object on which the video is displayed
|
||||
/// </summary>
|
||||
[SerializeField] private RawImage _screen;
|
||||
|
||||
/// <summary>
|
||||
/// MediaPipe graph
|
||||
/// </summary>
|
||||
private CalculatorGraph _graph;
|
||||
|
||||
/// <summary>
|
||||
/// Resource manager for graph resources
|
||||
/// </summary>
|
||||
private ResourceManager _resourceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Webcam texture
|
||||
/// </summary>
|
||||
private WebCamTexture _webCamTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Input texture
|
||||
/// </summary>
|
||||
private Texture2D _inputTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Screen pixel data
|
||||
/// </summary>
|
||||
private Color32[] _pixelData;
|
||||
|
||||
/// <summary>
|
||||
/// Stopwatch to give a timestamp to video frames
|
||||
/// </summary>
|
||||
private Stopwatch _stopwatch;
|
||||
|
||||
/// <summary>
|
||||
/// The mediapipe stream which contains the pose landmarks
|
||||
/// </summary>
|
||||
private OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList> posestream;
|
||||
|
||||
/// <summary>
|
||||
/// The mediapipe stream which contains the left hand landmarks
|
||||
/// </summary>
|
||||
private OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList> leftstream;
|
||||
|
||||
/// <summary>
|
||||
/// The mediapipe stream which contains the right hand landmarks
|
||||
/// </summary>
|
||||
private OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList> rightstream;
|
||||
|
||||
/// <summary>
|
||||
/// create precense stream
|
||||
/// </summary>
|
||||
public OutputStream<DetectionVectorPacket, List<Detection>> _presenceStream;
|
||||
|
||||
/// <summary>
|
||||
/// A keypointmanager which does normalization stuff, keeps track of the landmarks
|
||||
/// </summary>
|
||||
private KeypointManager k;
|
||||
|
||||
/// <summary>
|
||||
/// The worker on which we schedule the signpredictor model execution
|
||||
/// </summary>
|
||||
private IWorker worker;
|
||||
|
||||
/// <summary>
|
||||
/// Width of th webcam
|
||||
/// </summary>
|
||||
private int _width;
|
||||
|
||||
/// <summary>
|
||||
/// Height of the webcam
|
||||
/// </summary>
|
||||
private int _height;
|
||||
|
||||
/// <summary>
|
||||
/// ?The mediapipe stream which contains the tracked detections
|
||||
/// </summary>
|
||||
private const string _TrackedDetectionsStreamName = "tracked_detections";
|
||||
|
||||
/// <summary>
|
||||
/// ?The mediapipe stream which contains the tracked detections
|
||||
/// </summary>
|
||||
private OutputStream<DetectionVectorPacket, List<Detection>> _trackedDetectionsStream;
|
||||
|
||||
/// <summary>
|
||||
/// The enumerator of the worker which executes the sign predictor model
|
||||
/// </summary>
|
||||
private IEnumerator enumerator;
|
||||
|
||||
/// <summary>
|
||||
/// The prediction of the sign predictor model
|
||||
/// </summary>
|
||||
public Dictionary<char, float> letterProbabilities;
|
||||
|
||||
/// <summary>
|
||||
/// Bool indicating whether or not the resource manager has already been initialized
|
||||
/// </summary>
|
||||
private static bool resourceManagerIsInitialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// an inputTensor for the sign predictor
|
||||
/// </summary>
|
||||
private Tensor inputTensor;
|
||||
|
||||
/// <summary>
|
||||
/// Google Mediapipe setup & run
|
||||
/// </summary>
|
||||
/// <returns> IEnumerator </returns>
|
||||
/// <exception cref="System.Exception"></exception>
|
||||
private IEnumerator Start()
|
||||
{
|
||||
|
||||
Debug.Log("starting ...");
|
||||
// Webcam setup
|
||||
if (WebCamTexture.devices.Length == 0)
|
||||
{
|
||||
throw new System.Exception("Web Camera devices are not found");
|
||||
}
|
||||
// Start the webcam
|
||||
WebCamDevice webCamDevice = WebCamTexture.devices[0];
|
||||
_webCamTexture = new WebCamTexture(webCamDevice.name);
|
||||
|
||||
_webCamTexture.Play();
|
||||
|
||||
yield return new WaitUntil(() => _webCamTexture.width > 16);
|
||||
|
||||
// Set webcam aspect ratio
|
||||
_width = _webCamTexture.width;
|
||||
_height = _webCamTexture.height;
|
||||
float webcamAspect = (float)_webCamTexture.width / (float)_webCamTexture.height;
|
||||
_screen.rectTransform.sizeDelta = new Vector2(_screen.rectTransform.sizeDelta.y * webcamAspect, (_screen.rectTransform.sizeDelta.y));
|
||||
_screen.texture = _webCamTexture;
|
||||
|
||||
// TODO this method is kinda meh you should use
|
||||
_inputTexture = new Texture2D(_width, _height, TextureFormat.RGBA32, false);
|
||||
_pixelData = new Color32[_width * _height];
|
||||
|
||||
if (!resourceManagerIsInitialized)
|
||||
{
|
||||
_resourceManager = new StreamingAssetsResourceManager();
|
||||
yield return _resourceManager.PrepareAssetAsync("pose_detection.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("pose_landmark_full.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("face_landmark.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("hand_landmark_full.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("face_detection_short_range.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("hand_recrop.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("handedness.txt");
|
||||
resourceManagerIsInitialized = true;
|
||||
}
|
||||
|
||||
_stopwatch = new Stopwatch();
|
||||
|
||||
// Setting up the graph
|
||||
_graph = new CalculatorGraph(_configAsset.text);
|
||||
|
||||
posestream = new OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList>(_graph, "pose_landmarks", "pose_landmarks_presence");
|
||||
leftstream = new OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList>(_graph, "left_hand_landmarks", "left_hand_landmarks_presence");
|
||||
rightstream = new OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList>(_graph, "right_hand_landmarks", "right_hand_landmarks_presence");
|
||||
|
||||
posestream.StartPolling().AssertOk();
|
||||
leftstream.StartPolling().AssertOk();
|
||||
rightstream.StartPolling().AssertOk();
|
||||
|
||||
_graph.StartRun().AssertOk();
|
||||
_stopwatch.Start();
|
||||
|
||||
|
||||
k = new KeypointManager();
|
||||
|
||||
// check if model exists at path
|
||||
var model = ModelLoader.Load(Resources.Load<NNModel>("Models/Fingerspelling/model_A-L"));
|
||||
worker = model.CreateWorker();
|
||||
|
||||
StartCoroutine(SignRecognitionCoroutine());
|
||||
StartCoroutine(MediapipeCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine which executes the mediapipe pipeline
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerator MediapipeCoroutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_inputTexture.SetPixels32(_webCamTexture.GetPixels32(_pixelData));
|
||||
var imageFrame = new ImageFrame(ImageFormat.Types.Format.Srgba, _width, _height, _width * 4, _inputTexture.GetRawTextureData<byte>());
|
||||
var currentTimestamp = _stopwatch.ElapsedTicks / (System.TimeSpan.TicksPerMillisecond / 1000);
|
||||
_graph.AddPacketToInputStream("input_video", new ImageFramePacket(imageFrame, new Timestamp(currentTimestamp))).AssertOk();
|
||||
//Debug.Log(Time.timeAsDouble + " Added new packet to mediapipe graph");
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
Mediapipe.NormalizedLandmarkList _poseLandmarks = null;
|
||||
Mediapipe.NormalizedLandmarkList _leftHandLandmarks = null;
|
||||
Mediapipe.NormalizedLandmarkList _rightHandLandmarks = null;
|
||||
|
||||
//Debug.Log("Extracting keypoints");
|
||||
|
||||
yield return new WaitUntil(() => { posestream.TryGetNext(out _poseLandmarks, false); return true;});
|
||||
yield return new WaitUntil(() => { leftstream.TryGetNext(out _leftHandLandmarks, false); return true; });
|
||||
yield return new WaitUntil(() => { rightstream.TryGetNext(out _rightHandLandmarks, false); return true; });
|
||||
//Debug.Log(Time.timeAsDouble + " Retrieved landmarks ");
|
||||
|
||||
k.addLandmarks(_poseLandmarks, _leftHandLandmarks, _rightHandLandmarks);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine which calls the sign predictor model
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerator SignRecognitionCoroutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
List<List<float>> input = k.getAllKeypoints();
|
||||
if (input != null)
|
||||
{
|
||||
|
||||
//UnityEngine.Debug.Log("input: " + input.Count);
|
||||
|
||||
int frameCount = input.Count;
|
||||
int keypoints_per_frame = input[0].Count;
|
||||
|
||||
// Create a tensor with the input
|
||||
inputTensor = new Tensor(frameCount, keypoints_per_frame);
|
||||
|
||||
// Fill the tensor with the input
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
{
|
||||
for (int j = 0; j < keypoints_per_frame; j++)
|
||||
{
|
||||
inputTensor[i, j] = input[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
int stepsPerFrame = 190;
|
||||
enumerator = worker.StartManualSchedule(inputTensor);
|
||||
int step = 0;
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
if (++step % stepsPerFrame == 0)
|
||||
{
|
||||
//Debug.Log(Time.timeAsDouble + " : " + step);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
var output = worker.PeekOutput();
|
||||
|
||||
inputTensor.Dispose();
|
||||
|
||||
// Get the output as an array
|
||||
float[] outputArray = output.ToReadOnlyArray();
|
||||
|
||||
// Calculate the softmax of the output
|
||||
float max = outputArray.Max();
|
||||
float[] softmaxedOutput = outputArray.Select(x => Mathf.Exp(x - max)).ToArray();
|
||||
float sum = softmaxedOutput.Sum();
|
||||
float[] softmaxedOutput2 = softmaxedOutput.Select(x => x / sum).ToArray();
|
||||
|
||||
// Get the index of the highest probability
|
||||
int maxIndex = softmaxedOutput2.ToList().IndexOf(softmaxedOutput2.Max());
|
||||
|
||||
// Get the letter from the index
|
||||
char letter = (char)(maxIndex + 65);
|
||||
float accuracy = (Mathf.RoundToInt(softmaxedOutput2[maxIndex] * 100));
|
||||
|
||||
// Set the letterProbabilities, currently used by Courses
|
||||
letterProbabilities = new Dictionary<char, float>();
|
||||
for (int i = 0; i < softmaxedOutput2.Length; i++)
|
||||
{
|
||||
letterProbabilities.Add((char)(i + 65), softmaxedOutput2[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wait until next frame
|
||||
//Debug.Log(Time.timeAsDouble + "No landmarks!");
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Propper destruction on the Mediapipegraph
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_webCamTexture != null)
|
||||
{
|
||||
_webCamTexture.Stop();
|
||||
}
|
||||
|
||||
if (_graph != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_graph.CloseInputStream("input_video").AssertOk();
|
||||
_graph.WaitUntilDone().AssertOk();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
_graph.Dispose();
|
||||
}
|
||||
}
|
||||
// inputTensor must still be disposed, if it exists
|
||||
inputTensor?.Dispose();
|
||||
worker.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -32,6 +32,10 @@ output_stream: "face_landmarks"
|
||||
output_stream: "left_hand_landmarks"
|
||||
output_stream: "right_hand_landmarks"
|
||||
|
||||
output_stream: "pose_landmarks_presence"
|
||||
output_stream: "left_hand_landmarks_presence"
|
||||
output_stream: "right_hand_landmarks_presence"
|
||||
|
||||
# Throttles the images flowing downstream for flow control. It passes through
|
||||
# the very first incoming image unaltered, and waits for downstream nodes
|
||||
# (calculators and subgraphs) in the graph to finish their tasks before it
|
||||
@@ -91,4 +95,22 @@ node: {
|
||||
calculator: "ImageTransformationCalculator"
|
||||
input_stream: "IMAGE:segmentation_mask_rotated"
|
||||
output_stream: "IMAGE:segmentation_mask"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "PacketPresenceCalculator"
|
||||
input_stream: "PACKET:pose_landmarks"
|
||||
output_stream: "PRESENCE:pose_landmarks_presence"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "PacketPresenceCalculator"
|
||||
input_stream: "PACKET:left_hand_landmarks"
|
||||
output_stream: "PRESENCE:left_hand_landmarks_presence"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "PacketPresenceCalculator"
|
||||
input_stream: "PACKET:right_hand_landmarks"
|
||||
output_stream: "PRESENCE:right_hand_landmarks_presence"
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
// ATTENTION!: This code is for a tutorial.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Mediapipe.Unity.CoordinateSystem;
|
||||
|
||||
|
||||
namespace Mediapipe.Unity.Tutorial
|
||||
{
|
||||
public class Wesign_extractor : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Config file to set up the graph
|
||||
/// </summary>
|
||||
[SerializeField] private TextAsset _configAsset;
|
||||
|
||||
/// <summary>
|
||||
/// The screen object on which the video is displayed
|
||||
/// </summary>
|
||||
[SerializeField] private RawImage _screen;
|
||||
|
||||
/// <summary>
|
||||
/// width of the screen
|
||||
/// </summary>
|
||||
[SerializeField] private int _width;
|
||||
|
||||
/// <summary>
|
||||
/// height of the screen
|
||||
/// </summary>
|
||||
[SerializeField] private int _height;
|
||||
|
||||
/// <summary>
|
||||
/// fps of the screen
|
||||
/// </summary>
|
||||
[SerializeField] private int _fps;
|
||||
|
||||
/// <summary>
|
||||
/// Landmark annotation controller to show the landmarks on the screen
|
||||
/// </summary>
|
||||
[SerializeField] private PoseLandmarkListAnnotationController _poseLandmarkListAnnotationController;
|
||||
|
||||
/// <summary>
|
||||
/// MediaPipe graph
|
||||
/// </summary>
|
||||
private CalculatorGraph _graph;
|
||||
|
||||
/// <summary>
|
||||
/// Resource manager for graph resources
|
||||
/// </summary>
|
||||
private ResourceManager _resourceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Webcam texture
|
||||
/// </summary>
|
||||
private WebCamTexture _webCamTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Input texture
|
||||
/// </summary>
|
||||
private Texture2D _inputTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Screen pixel data
|
||||
/// </summary>
|
||||
private Color32[] _pixelData;
|
||||
|
||||
/// <summary>
|
||||
/// Stopwatch to give a timestamp to video frames
|
||||
/// </summary>
|
||||
private Stopwatch _stopwatch;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Google Mediapipe setup & run
|
||||
/// </summary>
|
||||
/// <returns> IEnumerator </returns>
|
||||
/// <exception cref="System.Exception"></exception>
|
||||
private IEnumerator Start()
|
||||
{
|
||||
// Webcam setup
|
||||
if (WebCamTexture.devices.Length == 0)
|
||||
{
|
||||
throw new System.Exception("Web Camera devices are not found");
|
||||
}
|
||||
var webCamDevice = WebCamTexture.devices[0];
|
||||
_webCamTexture = new WebCamTexture(webCamDevice.name, _width, _height, _fps);
|
||||
_webCamTexture.Play();
|
||||
|
||||
yield return new WaitUntil(() => _webCamTexture.width > 16);
|
||||
|
||||
_screen.rectTransform.sizeDelta = new Vector2(_width, _height);
|
||||
_screen.texture = _webCamTexture;
|
||||
|
||||
// TODO this method is kinda meh you should use ImageFrame
|
||||
_inputTexture = new Texture2D(_width, _height, TextureFormat.RGBA32, false);
|
||||
_pixelData = new Color32[_width * _height];
|
||||
|
||||
//_resourceManager = new LocalResourceManager();
|
||||
_resourceManager = new StreamingAssetsResourceManager();
|
||||
yield return _resourceManager.PrepareAssetAsync("pose_detection.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("pose_landmark_full.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("face_landmark.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("hand_landmark_full.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("face_detection_short_range.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("hand_recrop.bytes");
|
||||
yield return _resourceManager.PrepareAssetAsync("handedness.txt");
|
||||
|
||||
_stopwatch = new Stopwatch();
|
||||
|
||||
// Setting up the graph
|
||||
_graph = new CalculatorGraph(_configAsset.text);
|
||||
var posestream = new OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList>(_graph, "pose_landmarks");
|
||||
var leftstream = new OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList>(_graph, "left_hand_landmarks");
|
||||
var rightstream = new OutputStream<NormalizedLandmarkListPacket, NormalizedLandmarkList>(_graph, "right_hand_landmarks");
|
||||
posestream.StartPolling().AssertOk();
|
||||
leftstream.StartPolling().AssertOk();
|
||||
rightstream.StartPolling().AssertOk();
|
||||
_graph.StartRun().AssertOk();
|
||||
_stopwatch.Start();
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
_inputTexture.SetPixels32(_webCamTexture.GetPixels32(_pixelData));
|
||||
var imageFrame = new ImageFrame(ImageFormat.Types.Format.Srgba, _width, _height, _width * 4, _inputTexture.GetRawTextureData<byte>());
|
||||
var currentTimestamp = _stopwatch.ElapsedTicks / (System.TimeSpan.TicksPerMillisecond / 1000);
|
||||
_graph.AddPacketToInputStream("input_video", new ImageFramePacket(imageFrame, new Timestamp(currentTimestamp))).AssertOk();
|
||||
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
//posestream.TryGetNext(out var poseLandmarks);
|
||||
if (posestream.TryGetNext(out var poseLandmarks))
|
||||
{
|
||||
if (poseLandmarks != null)
|
||||
{
|
||||
// Draw the poseLandmarks on the screen
|
||||
_poseLandmarkListAnnotationController.DrawNow(poseLandmarks);
|
||||
var x = poseLandmarks.Landmark[0];
|
||||
UnityEngine.Debug.Log($"Pose Coordinates: {x}");
|
||||
|
||||
}
|
||||
}
|
||||
if (leftstream.TryGetNext(out var leftLandmarks))
|
||||
{
|
||||
if (leftLandmarks != null)
|
||||
{
|
||||
|
||||
var x = leftLandmarks.Landmark[0];
|
||||
UnityEngine.Debug.Log($"Pose left Coordinates: {x}");
|
||||
|
||||
}
|
||||
}
|
||||
if (rightstream.TryGetNext(out var rightLandmarks))
|
||||
{
|
||||
if (rightLandmarks != null)
|
||||
{
|
||||
|
||||
var x = rightLandmarks.Landmark[0];
|
||||
UnityEngine.Debug.Log($"Pose right Coordinates: {x}");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Propper destruction on the Mediapipegraph
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_webCamTexture != null)
|
||||
{
|
||||
_webCamTexture.Stop();
|
||||
}
|
||||
|
||||
if (_graph != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_graph.CloseInputStream("input_video").AssertOk();
|
||||
_graph.WaitUntilDone().AssertOk();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
_graph.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Assets/Resources/Models.meta
Normal file
8
Assets/Resources/Models.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7992d1284c7de4b089f4155b3e4ada83
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Resources/Models/FingerSpelling.meta
Normal file
8
Assets/Resources/Models/FingerSpelling.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2a1acaa9722345fb8f9d335700ccb30
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Resources/Models/FingerSpelling/landmarks.json
Normal file
1
Assets/Resources/Models/FingerSpelling/landmarks.json
Normal file
@@ -0,0 +1 @@
|
||||
{"pose_landmarks": [0, 2, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16], "hand_landmarks": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2f3eb6345d7543f893098c608366c3e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Resources/Models/FingerSpelling/model_A-L.onnx
Normal file
BIN
Assets/Resources/Models/FingerSpelling/model_A-L.onnx
Normal file
Binary file not shown.
16
Assets/Resources/Models/FingerSpelling/model_A-L.onnx.meta
Normal file
16
Assets/Resources/Models/FingerSpelling/model_A-L.onnx.meta
Normal file
@@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a08fc4c667eb4434f8b3405907070b2c
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 683b6cb6d0a474744822c888b46772c9, type: 3}
|
||||
optimizeModel: 1
|
||||
forceArbitraryBatchSize: 1
|
||||
treatErrorsAsWarnings: 0
|
||||
importMode: 1
|
||||
weightsTypeMode: 0
|
||||
activationTypeMode: 0
|
||||
8
Assets/StreamingAssets.meta
Normal file
8
Assets/StreamingAssets.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbae634e9481aea4ab4c36f614fbb04f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/StreamingAssets/face_detection_short_range.bytes
Normal file
BIN
Assets/StreamingAssets/face_detection_short_range.bytes
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63f6070ee724f1c469760f5ff86c865c
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/StreamingAssets/face_landmark.bytes
Normal file
BIN
Assets/StreamingAssets/face_landmark.bytes
Normal file
Binary file not shown.
7
Assets/StreamingAssets/face_landmark.bytes.meta
Normal file
7
Assets/StreamingAssets/face_landmark.bytes.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5d6bfc025cef9c42baa4347252a7b0c
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/StreamingAssets/hand_landmark_full.bytes
Normal file
BIN
Assets/StreamingAssets/hand_landmark_full.bytes
Normal file
Binary file not shown.
7
Assets/StreamingAssets/hand_landmark_full.bytes.meta
Normal file
7
Assets/StreamingAssets/hand_landmark_full.bytes.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef68f630eddb21842a6203b9e5dfe09b
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/StreamingAssets/hand_recrop.bytes
Normal file
BIN
Assets/StreamingAssets/hand_recrop.bytes
Normal file
Binary file not shown.
7
Assets/StreamingAssets/hand_recrop.bytes.meta
Normal file
7
Assets/StreamingAssets/hand_recrop.bytes.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7ead4f028994eb438023908d60d667c
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
2
Assets/StreamingAssets/handedness.txt
Normal file
2
Assets/StreamingAssets/handedness.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Left
|
||||
Right
|
||||
7
Assets/StreamingAssets/handedness.txt.meta
Normal file
7
Assets/StreamingAssets/handedness.txt.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fce7a788474e214438428ef836e0bb36
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/StreamingAssets/pose_detection.bytes
Normal file
BIN
Assets/StreamingAssets/pose_detection.bytes
Normal file
Binary file not shown.
7
Assets/StreamingAssets/pose_detection.bytes.meta
Normal file
7
Assets/StreamingAssets/pose_detection.bytes.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c51c620cdc2fe524fa2692079cd198e6
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/StreamingAssets/pose_landmark_full.bytes
Normal file
BIN
Assets/StreamingAssets/pose_landmark_full.bytes
Normal file
Binary file not shown.
7
Assets/StreamingAssets/pose_landmark_full.bytes.meta
Normal file
7
Assets/StreamingAssets/pose_landmark_full.bytes.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 713df1fb4455ae74e8a3bcd90a547855
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Tween.meta
Normal file
8
Assets/Tween.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d5851cbb0190ab4f8ed2b8be18e705d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Tween/Demo.meta
Normal file
9
Assets/Tween/Demo.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f5880b033929b7478e7b3a9ed6c5ee7
|
||||
folderAsset: yes
|
||||
timeCreated: 1455295494
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
113
Assets/Tween/Demo/TweenDemo.cs
Normal file
113
Assets/Tween/Demo/TweenDemo.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Digital Ruby, LLC
|
||||
http://www.digitalruby.com
|
||||
Created by Jeff Johnson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
// for your own scripts make sure to add the following line:
|
||||
using DigitalRuby.Tween;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace DigitalRuby.Tween
|
||||
{
|
||||
public class TweenDemo : MonoBehaviour
|
||||
{
|
||||
public GameObject Circle;
|
||||
public Light Light;
|
||||
|
||||
private SpriteRenderer spriteRenderer;
|
||||
|
||||
private void TweenMove()
|
||||
{
|
||||
System.Action<ITween<Vector3>> updateCirclePos = (t) =>
|
||||
{
|
||||
Circle.gameObject.transform.position = t.CurrentValue;
|
||||
};
|
||||
|
||||
System.Action<ITween<Vector3>> circleMoveCompleted = (t) =>
|
||||
{
|
||||
Debug.Log("Circle move completed");
|
||||
};
|
||||
|
||||
Vector3 currentPos = Circle.transform.position;
|
||||
Vector3 startPos = Camera.main.ViewportToWorldPoint(Vector3.zero);
|
||||
Vector3 midPos = Camera.main.ViewportToWorldPoint(Vector3.one);
|
||||
Vector3 endPos = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 0.5f));
|
||||
currentPos.z = startPos.z = midPos.z = endPos.z = 0.0f;
|
||||
|
||||
// completion defaults to null if not passed in
|
||||
Circle.gameObject.Tween("MoveCircle", currentPos, startPos, 1.75f, TweenScaleFunctions.CubicEaseIn, updateCirclePos)
|
||||
.ContinueWith(new Vector3Tween().Setup(startPos, midPos, 1.75f, TweenScaleFunctions.Linear, updateCirclePos))
|
||||
.ContinueWith(new Vector3Tween().Setup(midPos, endPos, 1.75f, TweenScaleFunctions.CubicEaseOut, updateCirclePos, circleMoveCompleted));
|
||||
}
|
||||
|
||||
private void TweenColor()
|
||||
{
|
||||
System.Action<ITween<Color>> updateColor = (t) =>
|
||||
{
|
||||
spriteRenderer.color = t.CurrentValue;
|
||||
};
|
||||
|
||||
Color endColor = UnityEngine.Random.ColorHSV(0.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// completion defaults to null if not passed in
|
||||
Circle.gameObject.Tween("ColorCircle", spriteRenderer.color, endColor, 1.0f, TweenScaleFunctions.QuadraticEaseOut, updateColor);
|
||||
}
|
||||
|
||||
private void TweenRotate()
|
||||
{
|
||||
System.Action<ITween<float>> circleRotate = (t) =>
|
||||
{
|
||||
// start rotation from identity to ensure no stuttering
|
||||
Circle.transform.rotation = Quaternion.identity;
|
||||
Circle.transform.Rotate(Camera.main.transform.forward, t.CurrentValue);
|
||||
};
|
||||
|
||||
float startAngle = Circle.transform.rotation.eulerAngles.z;
|
||||
float endAngle = startAngle + 720.0f;
|
||||
|
||||
// completion defaults to null if not passed in
|
||||
Circle.gameObject.Tween("RotateCircle", startAngle, endAngle, 2.0f, TweenScaleFunctions.CubicEaseInOut, circleRotate);
|
||||
}
|
||||
|
||||
private void TweenReset()
|
||||
{
|
||||
SceneManager.LoadScene(0, LoadSceneMode.Single);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// for demo purposes, clear all tweens when new level loads, default is false
|
||||
TweenFactory.ClearTweensOnLevelLoad = true;
|
||||
spriteRenderer = Circle.GetComponent<SpriteRenderer>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Alpha1))
|
||||
{
|
||||
TweenMove();
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Alpha2))
|
||||
{
|
||||
TweenColor();
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Alpha3))
|
||||
{
|
||||
TweenRotate();
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
TweenReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Tween/Demo/TweenDemo.cs.meta
Normal file
12
Assets/Tween/Demo/TweenDemo.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85997561a67b3e740be145c96c4a0b37
|
||||
timeCreated: 1455294104
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Tween/Demo/TweenDemoCircle.png
Normal file
BIN
Assets/Tween/Demo/TweenDemoCircle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
135
Assets/Tween/Demo/TweenDemoCircle.png.meta
Normal file
135
Assets/Tween/Demo/TweenDemoCircle.png.meta
Normal file
@@ -0,0 +1,135 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df831354d51eda74491b6ef6cfbbc4d0
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 16
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 32
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 1
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
85
Assets/Tween/Demo/TweenDemoMaterial.mat
Normal file
85
Assets/Tween/Demo/TweenDemoMaterial.mat
Normal file
@@ -0,0 +1,85 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: TweenDemoMaterial
|
||||
m_Shader: {fileID: 10800, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ValidKeywords:
|
||||
- ETC1_EXTERNAL_ALPHA
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 5
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: 3000
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _AlphaTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- PixelSnap: 0
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EnableExternalAlpha: 0
|
||||
- _Glossiness: 0.5
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _Flip: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _RendererColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
8
Assets/Tween/Demo/TweenDemoMaterial.mat.meta
Normal file
8
Assets/Tween/Demo/TweenDemoMaterial.mat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d994b80f30361c449f5504b6ddb859a
|
||||
timeCreated: 1455295548
|
||||
licenseType: Store
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
669
Assets/Tween/Demo/TweenDemoScene.unity
Normal file
669
Assets/Tween/Demo/TweenDemoScene.unity
Normal file
@@ -0,0 +1,669 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_AmbientEquatorColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_AmbientGroundColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_AmbientIntensity: 0
|
||||
m_AmbientMode: 3
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_GIWorkflowMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 0
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 1024
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 1
|
||||
m_BakeBackend: 0
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 512
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_LightingSettings: {fileID: 4890085278179872738, guid: 493623c166a735445b4283396018d38b, type: 2}
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &279954674
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 279954676}
|
||||
- component: {fileID: 279954675}
|
||||
m_Layer: 0
|
||||
m_Name: Circle
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!212 &279954675
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 279954674}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 0
|
||||
m_ReflectionProbeUsage: 0
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 2d994b80f30361c449f5504b6ddb859a, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_Sprite: {fileID: 21300000, guid: df831354d51eda74491b6ef6cfbbc4d0, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 1, y: 1}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!4 &279954676
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 279954674}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &309942542
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 309942543}
|
||||
- component: {fileID: 309942545}
|
||||
- component: {fileID: 309942544}
|
||||
m_Layer: 5
|
||||
m_Name: Commands
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &309942543
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 309942542}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2081690836}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 266, y: -8}
|
||||
m_SizeDelta: {x: 500, y: -16}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &309942544
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 309942542}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 20
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 0
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 0
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: 'Commands:
|
||||
|
||||
1] Tween Move
|
||||
|
||||
2] Tween Color
|
||||
|
||||
3] Tween Rotate
|
||||
|
||||
R]
|
||||
Reset'
|
||||
--- !u!222 &309942545
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 309942542}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &464777571
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 464777577}
|
||||
- component: {fileID: 464777576}
|
||||
- component: {fileID: 464777574}
|
||||
- component: {fileID: 464777573}
|
||||
- component: {fileID: 464777572}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &464777572
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 464777571}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 85997561a67b3e740be145c96c4a0b37, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Circle: {fileID: 279954674}
|
||||
Light: {fileID: 1462085731}
|
||||
--- !u!81 &464777573
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 464777571}
|
||||
m_Enabled: 1
|
||||
--- !u!124 &464777574
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 464777571}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &464777576
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 464777571}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 2
|
||||
m_BackGroundColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_FocalLength: 50
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 1
|
||||
orthographic size: 10
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 0
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &464777577
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 464777571}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1462085730
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1462085732}
|
||||
- component: {fileID: 1462085731}
|
||||
m_Layer: 0
|
||||
m_Name: Point light
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!108 &1462085731
|
||||
Light:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1462085730}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 10
|
||||
m_Type: 2
|
||||
m_Shape: 0
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Intensity: 2
|
||||
m_Range: 500
|
||||
m_SpotAngle: 30
|
||||
m_InnerSpotAngle: 21.80208
|
||||
m_CookieSize: 10
|
||||
m_Shadows:
|
||||
m_Type: 0
|
||||
m_Resolution: -1
|
||||
m_CustomResolution: -1
|
||||
m_Strength: 1
|
||||
m_Bias: 0.05
|
||||
m_NormalBias: 0.4
|
||||
m_NearPlane: 0.2
|
||||
m_CullingMatrixOverride:
|
||||
e00: 1
|
||||
e01: 0
|
||||
e02: 0
|
||||
e03: 0
|
||||
e10: 0
|
||||
e11: 1
|
||||
e12: 0
|
||||
e13: 0
|
||||
e20: 0
|
||||
e21: 0
|
||||
e22: 1
|
||||
e23: 0
|
||||
e30: 0
|
||||
e31: 0
|
||||
e32: 0
|
||||
e33: 1
|
||||
m_UseCullingMatrixOverride: 0
|
||||
m_Cookie: {fileID: 0}
|
||||
m_DrawHalo: 0
|
||||
m_Flare: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingLayerMask: 1
|
||||
m_Lightmapping: 4
|
||||
m_LightShadowCasterMode: 0
|
||||
m_AreaSize: {x: 1, y: 1}
|
||||
m_BounceIntensity: 0
|
||||
m_ColorTemperature: 6570
|
||||
m_UseColorTemperature: 0
|
||||
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_UseBoundingSphereOverride: 0
|
||||
m_UseViewFrustumForShadowCasterCull: 1
|
||||
m_ShadowRadius: 0
|
||||
m_ShadowAngle: 0
|
||||
--- !u!4 &1462085732
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1462085730}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -100}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1986219434
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1986219437}
|
||||
- component: {fileID: 1986219436}
|
||||
- component: {fileID: 1986219435}
|
||||
m_Layer: 0
|
||||
m_Name: EventSystem
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1986219435
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1986219434}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_SendPointerHoverToParent: 1
|
||||
m_HorizontalAxis: Horizontal
|
||||
m_VerticalAxis: Vertical
|
||||
m_SubmitButton: Submit
|
||||
m_CancelButton: Cancel
|
||||
m_InputActionsPerSecond: 10
|
||||
m_RepeatDelay: 0.5
|
||||
m_ForceModuleActive: 0
|
||||
--- !u!114 &1986219436
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1986219434}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_FirstSelected: {fileID: 0}
|
||||
m_sendNavigationEvents: 1
|
||||
m_DragThreshold: 5
|
||||
--- !u!4 &1986219437
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1986219434}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 4
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &2081690832
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2081690836}
|
||||
- component: {fileID: 2081690835}
|
||||
- component: {fileID: 2081690834}
|
||||
- component: {fileID: 2081690833}
|
||||
m_Layer: 5
|
||||
m_Name: UICanvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &2081690833
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2081690832}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreReversedGraphics: 1
|
||||
m_BlockingObjects: 0
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
--- !u!114 &2081690834
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2081690832}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 1
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 800, y: 600}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
m_PresetInfoIsWorld: 0
|
||||
--- !u!223 &2081690835
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2081690832}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_AdditionalShaderChannelsFlag: 25
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!224 &2081690836
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2081690832}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 309942543}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 3
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
8
Assets/Tween/Demo/TweenDemoScene.unity.meta
Normal file
8
Assets/Tween/Demo/TweenDemoScene.unity.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad948b3082b546f4e8f3565bdfe0abf6
|
||||
timeCreated: 1455295598
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
64
Assets/Tween/Demo/TweenDemoSceneSettings.lighting
Normal file
64
Assets/Tween/Demo/TweenDemoSceneSettings.lighting
Normal file
@@ -0,0 +1,64 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!850595691 &4890085278179872738
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: TweenDemoSceneSettings
|
||||
serializedVersion: 4
|
||||
m_GIWorkflowMode: 1
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 0
|
||||
m_BakeBackend: 0
|
||||
m_LightmapMaxSize: 1024
|
||||
m_BakeResolution: 40
|
||||
m_Padding: 2
|
||||
m_LightmapCompression: 3
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 0
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 1
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 2
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 1024
|
||||
m_FinalGatherFiltering: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVREnvironmentSampleCount: 512
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_PVRTiledBaking: 0
|
||||
8
Assets/Tween/Demo/TweenDemoSceneSettings.lighting.meta
Normal file
8
Assets/Tween/Demo/TweenDemoSceneSettings.lighting.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 493623c166a735445b4283396018d38b
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 4890085278179872738
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Assets/Tween/Readme.txt
Normal file
24
Assets/Tween/Readme.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
Tween for Unity
|
||||
(c) 2016 Digital Ruby, LLC
|
||||
https://www.digitalruby.com/unity-plugins/
|
||||
Created by Jeff Johnson
|
||||
|
||||
Version 1.0.4
|
||||
|
||||
Tween for Unity is the easiest and simplest Tween script for Unity. In a matter of seconds you can be tweening and animating your game objects.
|
||||
|
||||
Tween supports float, Vector2, Vector3, Vector4 and Quaternion tweens.
|
||||
|
||||
TweenFactory is the class you will want to use to initiate tweens. There is no need to add any scripts to game objects. TweenFactory takes care of everything.
|
||||
|
||||
Simply call TweenFactory.Tween(...) and pass in your parameters and callback functions.
|
||||
|
||||
TweenFactory.DefaultTimeFunc can be set to your desired time function, default is Time.deltaTime.
|
||||
|
||||
Tweens may have a key, or null for no key. If adding a tween with a non-null key, existing tweens with the same key will be removed. Use the AddKeyStopBehavior field of TweenFactory to determine what to do in these cases.
|
||||
|
||||
Set Tween.ForceUpdate = true; if you want Tween to continue to run on objects that are not visible.
|
||||
|
||||
Make sure to add a "using DigitalRuby.Tween" to your scripts.
|
||||
|
||||
See TweenDemoScene for a demo scene, and look in TweenDemo.cs for code samples.
|
||||
8
Assets/Tween/Readme.txt.meta
Normal file
8
Assets/Tween/Readme.txt.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d536e9d2e2dc3f94cb6ca36e79a2d583
|
||||
timeCreated: 1455298832
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Tween/Tween.asmdef
Normal file
3
Assets/Tween/Tween.asmdef
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "Tween"
|
||||
}
|
||||
7
Assets/Tween/Tween.asmdef.meta
Normal file
7
Assets/Tween/Tween.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58e104b97fb3752438ada2902a36dcbf
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1096
Assets/Tween/Tween.cs
Normal file
1096
Assets/Tween/Tween.cs
Normal file
File diff suppressed because it is too large
Load Diff
12
Assets/Tween/Tween.cs.meta
Normal file
12
Assets/Tween/Tween.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96aee4e6410e5c149aa48287d2bb7112
|
||||
timeCreated: 1455294094
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/users.json
Normal file
1
Assets/users.json
Normal file
@@ -0,0 +1 @@
|
||||
{"currentUserIndex":1,"storedUsers":[{"username":"proefkonijn","avatar":{"instanceID":24288},"playtime":0.0,"courses":[{"entries":[{"key":"courseIndex","bytes":[0,1,0,0,0,255,255,255,255,1,0,0,0,0,0,0,0,12,2,0,0,0,72,73,110,116,101,114,102,97,99,101,115,83,99,114,105,112,116,115,44,32,86,101,114,115,105,111,110,61,48,46,48,46,48,46,48,44,32,67,117,108,116,117,114,101,61,110,101,117,116,114,97,108,44,32,80,117,98,108,105,99,75,101,121,84,111,107,101,110,61,110,117,108,108,5,1,0,0,0,11,67,111,117,114,115,101,73,110,100,101,120,1,0,0,0,7,118,97,108,117,101,95,95,0,8,2,0,0,0,0,0,0,0,11]},{"key":"courseProgress","bytes":[0,1,0,0,0,255,255,255,255,1,0,0,0,0,0,0,0,4,1,0,0,0,13,83,121,115,116,101,109,46,83,105,110,103,108,101,1,0,0,0,7,109,95,118,97,108,117,101,0,11,0,0,128,63,11]}]}],"minigames":[]},{"username":"girafproef","avatar":{"instanceID":24840},"playtime":0.0,"courses":[{"entries":[{"key":"courseIndex","bytes":[0,1,0,0,0,255,255,255,255,1,0,0,0,0,0,0,0,12,2,0,0,0,72,73,110,116,101,114,102,97,99,101,115,83,99,114,105,112,116,115,44,32,86,101,114,115,105,111,110,61,48,46,48,46,48,46,48,44,32,67,117,108,116,117,114,101,61,110,101,117,116,114,97,108,44,32,80,117,98,108,105,99,75,101,121,84,111,107,101,110,61,110,117,108,108,5,1,0,0,0,11,67,111,117,114,115,101,73,110,100,101,120,1,0,0,0,7,118,97,108,117,101,95,95,0,8,2,0,0,0,0,0,0,0,11]},{"key":"courseProgress","bytes":[0,1,0,0,0,255,255,255,255,1,0,0,0,0,0,0,0,4,1,0,0,0,13,83,121,115,116,101,109,46,83,105,110,103,108,101,1,0,0,0,7,109,95,118,97,108,117,101,0,11,205,204,76,62,11]}]}],"minigames":[]}]}
|
||||
7
Assets/users.json.meta
Normal file
7
Assets/users.json.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b758111ae1c33e4b9fdbe46d5d9a118
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.unity.barracuda/Editor.meta
Normal file
8
Packages/com.unity.barracuda/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6ebab52a13ea425ba87006839f1d776
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
148
Packages/com.unity.barracuda/Editor/BarracudaAnalytics.cs
Normal file
148
Packages/com.unity.barracuda/Editor/BarracudaAnalytics.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Onnx;
|
||||
using UnityEditor;
|
||||
using UnityEngine.Analytics;
|
||||
|
||||
namespace Unity.Barracuda.Editor
|
||||
{
|
||||
internal class BarracudaAnalytics
|
||||
{
|
||||
static bool s_EventRegistered = false;
|
||||
const int k_MaxEventsPerHour = 1000;
|
||||
const int k_MaxNumberOfElements = 1000;
|
||||
const string k_VendorKey = "unity.barracuda";
|
||||
const string k_ImportEventName = "uBarracudaImport";
|
||||
|
||||
static bool EnableAnalytics()
|
||||
{
|
||||
AnalyticsResult result = EditorAnalytics.RegisterEventWithLimit(k_ImportEventName, k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey);
|
||||
if (result == AnalyticsResult.Ok)
|
||||
s_EventRegistered = true;
|
||||
|
||||
return s_EventRegistered;
|
||||
}
|
||||
|
||||
struct BarracudaImportAnalyticsData
|
||||
{
|
||||
public string model_type;
|
||||
public string original_layers;
|
||||
public string imported_layers;
|
||||
public string import_warnings;
|
||||
}
|
||||
|
||||
public static void SendBarracudaImportEvent(object originalModel, Model importedModel)
|
||||
{
|
||||
//The event shouldn't be able to report if this is disabled but if we know we're not going to report
|
||||
//Lets early out and not waste time gathering all the data
|
||||
if (!EditorAnalytics.enabled)
|
||||
return;
|
||||
|
||||
if (!EnableAnalytics())
|
||||
return;
|
||||
|
||||
|
||||
var data = new BarracudaImportAnalyticsData();
|
||||
|
||||
try
|
||||
{
|
||||
data.original_layers = AnalyzeONNXModel(originalModel);
|
||||
data.imported_layers = AnalyzeNNModel(importedModel);
|
||||
data.model_type = string.IsNullOrEmpty(data.original_layers) ? "NN" : "ONNX";
|
||||
data.import_warnings = AnalyzeWarnings(importedModel);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
D.LogError($"Failed collecting Barracuda analytics: {e}");
|
||||
}
|
||||
|
||||
EditorAnalytics.SendEventWithLimit(k_ImportEventName, data);
|
||||
}
|
||||
|
||||
static string AnalyzeONNXModel(object originalModel)
|
||||
{
|
||||
if (!(originalModel is ModelProto))
|
||||
return "";
|
||||
|
||||
var layers = new Dictionary<string, int>();
|
||||
|
||||
var onnxModel = originalModel as ModelProto;
|
||||
foreach (var node in onnxModel.Graph.Node)
|
||||
{
|
||||
var layerDescription = node.OpType;
|
||||
|
||||
if (!layers.ContainsKey(layerDescription))
|
||||
layers[layerDescription] = 1;
|
||||
else
|
||||
layers[layerDescription] += 1;
|
||||
}
|
||||
|
||||
return DictionaryToJson(layers);
|
||||
}
|
||||
|
||||
static string AnalyzeNNModel(Model importedModel)
|
||||
{
|
||||
var layers = new Dictionary<string, int>();
|
||||
|
||||
foreach (Layer layer in importedModel.layers)
|
||||
{
|
||||
var layerDescription = LayerToString(layer);
|
||||
|
||||
if (!layers.ContainsKey(layerDescription))
|
||||
layers[layerDescription] = 1;
|
||||
else
|
||||
layers[layerDescription] += 1;
|
||||
}
|
||||
|
||||
return DictionaryToJson(layers);
|
||||
}
|
||||
|
||||
static string LayerToString(Layer layer)
|
||||
{
|
||||
var layerDescription = layer.type.ToString();
|
||||
|
||||
if (layer.type == Layer.Type.Conv2D || layer.type == Layer.Type.Conv2DTrans ||
|
||||
layer.type == Layer.Type.Conv3D || layer.type == Layer.Type.Conv3DTrans ||
|
||||
layer.type == Layer.Type.DepthwiseConv2D)
|
||||
{
|
||||
layerDescription += "_" + ConvShapeToString(layer);
|
||||
}
|
||||
|
||||
if (layer.activation != Layer.Activation.None)
|
||||
layerDescription += "_" + layer.activation.ToString();
|
||||
|
||||
return layerDescription;
|
||||
}
|
||||
|
||||
static string ConvShapeToString(Layer layer)
|
||||
{
|
||||
if (layer.type == Layer.Type.Conv2D ||
|
||||
layer.type == Layer.Type.DepthwiseConv2D ||
|
||||
layer.type == Layer.Type.Conv2DTrans)
|
||||
return string.Join("_",
|
||||
layer.datasets.Where(d => d.name.EndsWith("/K")).Select(it =>
|
||||
$"{it.shape.kernelHeight}x{it.shape.kernelWidth}x{it.shape.kernelDepth}x{it.shape.kernelCount}"));
|
||||
|
||||
if (layer.type == Layer.Type.Conv3D ||
|
||||
layer.type == Layer.Type.Conv3DTrans)
|
||||
return string.Join("_",
|
||||
layer.datasets.Where(d => d.name.EndsWith("/K")).Select(it =>
|
||||
$"{it.shape.kernelSpatialDepth}x{it.shape.kernelHeight}x{it.shape.kernelWidth}x{it.shape.kernelDepth}x{it.shape.kernelCount}"));
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static string AnalyzeWarnings(Model importedModel)
|
||||
{
|
||||
return "[" + string.Join(",",importedModel.Warnings.Select(item => $"'{item.LayerName}:{item.Message}'")) + "]";
|
||||
}
|
||||
|
||||
static string DictionaryToJson(Dictionary<string, int> dict)
|
||||
{
|
||||
var entries = dict.Select(d => $"\"{d.Key}\":{string.Join(",", d.Value)}");
|
||||
return "{" + string.Join(",", entries) + "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92cb0e57f8c0c4255a2d2d93f844424d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.unity.barracuda/Editor/NNModelIcon.png
Normal file
BIN
Packages/com.unity.barracuda/Editor/NNModelIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
106
Packages/com.unity.barracuda/Editor/NNModelIcon.png.meta
Normal file
106
Packages/com.unity.barracuda/Editor/NNModelIcon.png.meta
Normal file
@@ -0,0 +1,106 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8682ff569c4c7457a8a8e3a527aad537
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
63
Packages/com.unity.barracuda/Editor/NNModelImporter.cs
Normal file
63
Packages/com.unity.barracuda/Editor/NNModelImporter.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.IO;
|
||||
using Unity.Barracuda.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
using UnityEditor.AssetImporters;
|
||||
using UnityEditor.Experimental.AssetImporters;
|
||||
#else
|
||||
using UnityEditor.Experimental.AssetImporters;
|
||||
#endif
|
||||
|
||||
namespace Unity.Barracuda
|
||||
{
|
||||
/// <summary>
|
||||
/// Asset Importer of barracuda models.
|
||||
/// </summary>
|
||||
[ScriptedImporter(3, new[] {"nn"})]
|
||||
public class NNModelImporter : ScriptedImporter {
|
||||
private const string iconName = "NNModelIcon";
|
||||
|
||||
private Texture2D iconTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Scripted importer callback
|
||||
/// </summary>
|
||||
/// <param name="ctx">Asset import context</param>
|
||||
public override void OnImportAsset(AssetImportContext ctx)
|
||||
{
|
||||
var model = File.ReadAllBytes(ctx.assetPath);
|
||||
|
||||
// Analyze model and send analytics if enabled
|
||||
var nnModel = ModelLoader.Load(ctx.assetPath, skipWeights:true);
|
||||
BarracudaAnalytics.SendBarracudaImportEvent(null, nnModel);
|
||||
|
||||
var assetData = ScriptableObject.CreateInstance<NNModelData>();
|
||||
assetData.Value = model;
|
||||
assetData.name = "Data";
|
||||
assetData.hideFlags = HideFlags.HideInHierarchy;
|
||||
|
||||
var asset = ScriptableObject.CreateInstance<NNModel>();
|
||||
asset.modelData = assetData;
|
||||
ctx.AddObjectToAsset("main obj", asset, LoadIconTexture());
|
||||
ctx.AddObjectToAsset("model data", assetData);
|
||||
|
||||
ctx.SetMainObject(asset);
|
||||
}
|
||||
|
||||
private Texture2D LoadIconTexture()
|
||||
{
|
||||
if (iconTexture == null)
|
||||
{
|
||||
string[] allCandidates = AssetDatabase.FindAssets(iconName);
|
||||
|
||||
if (allCandidates.Length > 0)
|
||||
{
|
||||
iconTexture = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(allCandidates[0]), typeof(Texture2D)) as Texture2D;
|
||||
}
|
||||
}
|
||||
return iconTexture;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
Packages/com.unity.barracuda/Editor/NNModelImporter.cs.meta
Normal file
11
Packages/com.unity.barracuda/Editor/NNModelImporter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19ed1486aa27d4903b34839f37b8f69f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Packages/com.unity.barracuda/Editor/ONNXModelIcon.png
Normal file
BIN
Packages/com.unity.barracuda/Editor/ONNXModelIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
165
Packages/com.unity.barracuda/Editor/ONNXModelIcon.png.meta
Normal file
165
Packages/com.unity.barracuda/Editor/ONNXModelIcon.png.meta
Normal file
@@ -0,0 +1,165 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44179f4142e33e24ca4feb8dfe55e56c
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: tvOS
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: PS4
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Packages/com.unity.barracuda/Editor/ONNXModelImporter.cs
Normal file
106
Packages/com.unity.barracuda/Editor/ONNXModelImporter.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
using UnityEditor.AssetImporters;
|
||||
using UnityEditor.Experimental.AssetImporters;
|
||||
#else
|
||||
using UnityEditor.Experimental.AssetImporters;
|
||||
#endif
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Barracuda.Editor;
|
||||
using Unity.Barracuda.ONNX;
|
||||
|
||||
[assembly: InternalsVisibleToAttribute("Barracuda.EditorTests")]
|
||||
[assembly: InternalsVisibleToAttribute("Unity.Barracuda.Tests")]
|
||||
|
||||
namespace Unity.Barracuda
|
||||
{
|
||||
/// <summary>
|
||||
/// Asset Importer for Open Neural Network Exchange (ONNX) files.
|
||||
/// For more information about ONNX file format see: https://github.com/onnx/onnx
|
||||
/// </summary>
|
||||
[ScriptedImporter(34, new[] { "onnx" })]
|
||||
public class ONNXModelImporter : ScriptedImporter
|
||||
{
|
||||
// Configuration
|
||||
/// <summary>
|
||||
/// Enable ONNX model optimization during import. Set via importer UI
|
||||
/// </summary>
|
||||
public bool optimizeModel = true;
|
||||
|
||||
/// <summary>
|
||||
/// Fix batch size for ONNX models. Set via importer UI
|
||||
/// </summary>
|
||||
public bool forceArbitraryBatchSize = true;
|
||||
|
||||
/// <summary>
|
||||
/// Treat errors as warnings. Set via importer UI
|
||||
/// </summary>
|
||||
public bool treatErrorsAsWarnings = false;
|
||||
|
||||
[SerializeField, HideInInspector]
|
||||
internal ONNXModelConverter.ImportMode importMode = ONNXModelConverter.ImportMode.Standard;
|
||||
|
||||
[SerializeField, HideInInspector]
|
||||
internal ONNXModelConverter.DataTypeMode weightsTypeMode = ONNXModelConverter.DataTypeMode.Default;
|
||||
[SerializeField, HideInInspector]
|
||||
internal ONNXModelConverter.DataTypeMode activationTypeMode = ONNXModelConverter.DataTypeMode.Default;
|
||||
|
||||
internal const string iconName = "ONNXModelIcon";
|
||||
|
||||
|
||||
private Texture2D m_IconTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Scripted importer callback
|
||||
/// </summary>
|
||||
/// <param name="ctx">Asset import context</param>
|
||||
public override void OnImportAsset(AssetImportContext ctx)
|
||||
{
|
||||
ONNXModelConverter.ModelImported += BarracudaAnalytics.SendBarracudaImportEvent;
|
||||
var converter = new ONNXModelConverter(optimizeModel, treatErrorsAsWarnings, forceArbitraryBatchSize, importMode);
|
||||
|
||||
var model = converter.Convert(ctx.assetPath);
|
||||
|
||||
if (weightsTypeMode == ONNXModelConverter.DataTypeMode.ForceHalf)
|
||||
model.ConvertWeights(DataType.Half);
|
||||
else if (weightsTypeMode == ONNXModelConverter.DataTypeMode.ForceFloat)
|
||||
model.ConvertWeights(DataType.Float);
|
||||
|
||||
NNModelData assetData = ScriptableObject.CreateInstance<NNModelData>();
|
||||
using (var memoryStream = new MemoryStream())
|
||||
using (var writer = new BinaryWriter(memoryStream))
|
||||
{
|
||||
ModelWriter.Save(writer, model);
|
||||
assetData.Value = memoryStream.ToArray();
|
||||
}
|
||||
assetData.name = "Data";
|
||||
assetData.hideFlags = HideFlags.HideInHierarchy;
|
||||
|
||||
NNModel asset = ScriptableObject.CreateInstance<NNModel>();
|
||||
asset.modelData = assetData;
|
||||
|
||||
ctx.AddObjectToAsset("main obj", asset, LoadIconTexture());
|
||||
ctx.AddObjectToAsset("model data", assetData);
|
||||
|
||||
ctx.SetMainObject(asset);
|
||||
}
|
||||
|
||||
// Icon helper
|
||||
private Texture2D LoadIconTexture()
|
||||
{
|
||||
if (m_IconTexture == null)
|
||||
{
|
||||
string[] allCandidates = AssetDatabase.FindAssets(iconName);
|
||||
|
||||
if (allCandidates.Length > 0)
|
||||
{
|
||||
m_IconTexture = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(allCandidates[0]), typeof(Texture2D)) as Texture2D;
|
||||
}
|
||||
}
|
||||
return m_IconTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 683b6cb6d0a474744822c888b46772c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
461
Packages/com.unity.barracuda/Editor/ONNXModelImporterEditor.cs
Normal file
461
Packages/com.unity.barracuda/Editor/ONNXModelImporterEditor.cs
Normal file
@@ -0,0 +1,461 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
using UnityEditor.AssetImporters;
|
||||
using UnityEditor.Experimental.AssetImporters;
|
||||
#else
|
||||
using UnityEditor.Experimental.AssetImporters;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Unity.Barracuda.ONNX;
|
||||
using ImportMode=Unity.Barracuda.ONNX.ONNXModelConverter.ImportMode;
|
||||
using DataTypeMode=Unity.Barracuda.ONNX.ONNXModelConverter.DataTypeMode;
|
||||
|
||||
namespace Unity.Barracuda.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Asset Importer Editor of ONNX models
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(ONNXModelImporter))]
|
||||
[CanEditMultipleObjects]
|
||||
public class ONNXModelImporterEditor : ScriptedImporterEditor
|
||||
{
|
||||
static PropertyInfo s_InspectorModeInfo;
|
||||
static ONNXModelImporterEditor()
|
||||
{
|
||||
s_InspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scripted importer editor UI callback
|
||||
/// </summary>
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
var onnxModelImporter = target as ONNXModelImporter;
|
||||
if (onnxModelImporter == null)
|
||||
return;
|
||||
|
||||
InspectorMode inspectorMode = InspectorMode.Normal;
|
||||
if (s_InspectorModeInfo != null)
|
||||
inspectorMode = (InspectorMode)s_InspectorModeInfo.GetValue(assetSerializedObject);
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
bool debugView = inspectorMode != InspectorMode.Normal;
|
||||
SerializedProperty iterator = serializedObject.GetIterator();
|
||||
for (bool enterChildren = true; iterator.NextVisible(enterChildren); enterChildren = false)
|
||||
{
|
||||
if (iterator.propertyPath != "m_Script")
|
||||
EditorGUILayout.PropertyField(iterator, true);
|
||||
}
|
||||
|
||||
// Additional options exposed from ImportMode
|
||||
SerializedProperty importModeProperty = serializedObject.FindProperty(nameof(onnxModelImporter.importMode));
|
||||
bool skipMetadataImport = ((ImportMode)importModeProperty.intValue).HasFlag(ImportMode.SkipMetadataImport);
|
||||
if (EditorGUILayout.Toggle("Skip Metadata Import", skipMetadataImport) != skipMetadataImport)
|
||||
{
|
||||
importModeProperty.intValue ^= (int)ImportMode.SkipMetadataImport;
|
||||
}
|
||||
|
||||
if (debugView)
|
||||
{
|
||||
importModeProperty.intValue = (int)(ImportMode)EditorGUILayout.EnumFlagsField("Import Mode", (ImportMode)importModeProperty.intValue);
|
||||
|
||||
SerializedProperty weightsTypeMode = serializedObject.FindProperty(nameof(onnxModelImporter.weightsTypeMode));
|
||||
SerializedProperty activationTypeMode = serializedObject.FindProperty(nameof(onnxModelImporter.activationTypeMode));
|
||||
weightsTypeMode.intValue = (int)(DataTypeMode)EditorGUILayout.EnumPopup("Weights type", (DataTypeMode)weightsTypeMode.intValue);
|
||||
activationTypeMode.intValue = (int)(DataTypeMode)EditorGUILayout.EnumPopup("Activation type", (DataTypeMode)activationTypeMode.intValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (onnxModelImporter.optimizeModel)
|
||||
EditorGUILayout.HelpBox("Model optimizations are on\nRemove and re-import model if you observe incorrect behavior", MessageType.Info);
|
||||
|
||||
if (onnxModelImporter.importMode == ImportMode.Legacy)
|
||||
EditorGUILayout.HelpBox("Legacy importer is in use", MessageType.Warning);
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
ApplyRevertGUI();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asset Importer Editor of NNModel (the serialized file generated by ONNXModelImporter)
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(NNModel))]
|
||||
public class NNModelEditor : UnityEditor.Editor
|
||||
{
|
||||
// Use a static store for the foldouts, so it applies to all inspectors
|
||||
static Dictionary<string, bool> s_UIHelperFoldouts = new Dictionary<string, bool>();
|
||||
|
||||
private Model m_Model;
|
||||
private List<string> m_Inputs = new List<string>();
|
||||
private List<string> m_InputsDesc = new List<string>();
|
||||
private List<string> m_Outputs = new List<string>();
|
||||
private List<string> m_OutputsDesc = new List<string>();
|
||||
private List<string> m_Memories = new List<string>();
|
||||
private List<string> m_MemoriesDesc = new List<string>();
|
||||
private List<string> m_Layers = new List<string>();
|
||||
private List<string> m_LayersDesc = new List<string>();
|
||||
private List<string> m_Constants = new List<string>();
|
||||
private List<string> m_ConstantsDesc = new List<string>();
|
||||
|
||||
Dictionary<string, string> m_Metadata = new Dictionary<string, string>();
|
||||
Vector2 m_MetadataScrollPosition = Vector2.zero;
|
||||
// warnings
|
||||
private Dictionary<string, string> m_WarningsNeutral = new Dictionary<string, string>();
|
||||
private Dictionary<string, string> m_WarningsInfo = new Dictionary<string, string>();
|
||||
private Dictionary<string, string> m_WarningsWarning = new Dictionary<string, string>();
|
||||
private Dictionary<string, string> m_WarningsError = new Dictionary<string, string>();
|
||||
private Vector2 m_WarningsNeutralScrollPosition = Vector2.zero;
|
||||
private Vector2 m_WarningsInfoScrollPosition = Vector2.zero;
|
||||
private Vector2 m_WarningsWarningScrollPosition = Vector2.zero;
|
||||
private Vector2 m_WarningsErrorScrollPosition = Vector2.zero;
|
||||
|
||||
|
||||
private long m_NumEmbeddedWeights;
|
||||
private long m_NumConstantWeights;
|
||||
private long m_TotalWeightsSizeInBytes;
|
||||
|
||||
private Vector2 m_InputsScrollPosition = Vector2.zero;
|
||||
private Vector2 m_OutputsScrollPosition = Vector2.zero;
|
||||
private Vector2 m_MemoriesScrollPosition = Vector2.zero;
|
||||
private Vector2 m_LayerScrollPosition = Vector2.zero;
|
||||
private Vector2 m_ConstantScrollPosition = Vector2.zero;
|
||||
private const float k_Space = 5f;
|
||||
|
||||
private Texture2D m_IconTexture;
|
||||
private Texture2D LoadIconTexture()
|
||||
{
|
||||
if (m_IconTexture != null)
|
||||
return m_IconTexture;
|
||||
|
||||
string[] allCandidates = AssetDatabase.FindAssets(ONNXModelImporter.iconName);
|
||||
if (allCandidates.Length > 0)
|
||||
m_IconTexture = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(allCandidates[0]), typeof(Texture2D)) as Texture2D;
|
||||
|
||||
return m_IconTexture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Editor static preview rendering callback
|
||||
/// </summary>
|
||||
/// <param name="assetPath">Asset path</param>
|
||||
/// <param name="subAssets">Child assets</param>
|
||||
/// <param name="width">width</param>
|
||||
/// <param name="height">height</param>
|
||||
/// <returns></returns>
|
||||
public override Texture2D RenderStaticPreview(string assetPath, UnityEngine.Object[] subAssets, int width, int height)
|
||||
{
|
||||
Texture2D icon = LoadIconTexture();
|
||||
if (icon == null)
|
||||
return null;
|
||||
Texture2D tex = new Texture2D(width, height);
|
||||
EditorUtility.CopySerialized(icon, tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
private void AddDimension(StringBuilder stringBuilder, string name, int value, bool lastDim=false)
|
||||
{
|
||||
string strValue = (value >= 1) ? value.ToString() : "*";
|
||||
stringBuilder.AppendFormat("{0}:{1}", name, strValue);
|
||||
if (!lastDim)
|
||||
stringBuilder.Append(", ");
|
||||
}
|
||||
|
||||
private string GetUIStringFromShape(int[] shape)
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder("shape: (", 50);
|
||||
if (shape.Length == 8)
|
||||
{
|
||||
bool is8D = (shape[0] > 1 || shape[1] > 1 || shape[3] > 1 || shape[4] > 1);
|
||||
if (is8D) AddDimension(stringBuilder, "s", shape[0]);
|
||||
if (is8D) AddDimension(stringBuilder, "r", shape[1]);
|
||||
AddDimension(stringBuilder, "n", shape[2]);
|
||||
if (is8D) AddDimension(stringBuilder, "t", shape[3]);
|
||||
if (is8D) AddDimension(stringBuilder, "d", shape[4]);
|
||||
AddDimension(stringBuilder, "h", shape[5]);
|
||||
AddDimension(stringBuilder, "w", shape[6]);
|
||||
AddDimension(stringBuilder, "c", shape[7], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.Assert(shape.Length == 4);
|
||||
AddDimension(stringBuilder, "n", shape[0]);
|
||||
AddDimension(stringBuilder, "h", shape[1]);
|
||||
AddDimension(stringBuilder, "w", shape[2]);
|
||||
AddDimension(stringBuilder, "c", shape[3], true);
|
||||
}
|
||||
stringBuilder.Append(")");
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
var nnModel = target as NNModel;
|
||||
if (nnModel == null)
|
||||
return;
|
||||
if (nnModel.modelData == null)
|
||||
return;
|
||||
|
||||
m_Model = nnModel.GetDeserializedModel();
|
||||
if (m_Model == null)
|
||||
return;
|
||||
|
||||
m_Inputs = m_Model.inputs.Select(i => i.name).ToList();
|
||||
m_InputsDesc = m_Model.inputs.Select(i => GetUIStringFromShape(i.shape)).ToList();
|
||||
m_Outputs = m_Model.outputs.ToList();
|
||||
|
||||
bool allKnownInputShapes = true;
|
||||
var inputShapes = new Dictionary<string, TensorShape>();
|
||||
foreach (var i in m_Model.inputs)
|
||||
{
|
||||
allKnownInputShapes = allKnownInputShapes && ModelAnalyzer.IsInputShapeAcceptablyKnowForShapeInference(i);
|
||||
if (!allKnownInputShapes)
|
||||
break;
|
||||
inputShapes.Add(i.name, new TensorShape(i.shape));
|
||||
}
|
||||
if (allKnownInputShapes)
|
||||
{
|
||||
m_OutputsDesc = m_Model.outputs.Select(i => {
|
||||
string output = "shape: (n:*, h:*, w:*, c:*)";
|
||||
try
|
||||
{
|
||||
TensorShape shape;
|
||||
if (ModelAnalyzer.TryGetOutputTensorShape(m_Model, inputShapes, i, out shape))
|
||||
output = GetUIStringFromShape(shape.ToArray());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Unexpected error while evaluating model output {i}. {e}");
|
||||
}
|
||||
return output; }).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OutputsDesc = m_Model.outputs.Select(i => "shape: (n:*, h:*, w:*, c:*)").ToList();
|
||||
}
|
||||
|
||||
m_Memories = m_Model.memories.Select(i => i.input).ToList();
|
||||
m_MemoriesDesc = m_Model.memories.Select(i => $"shape:{i.shape.ToString()} output:{i.output}").ToList();
|
||||
|
||||
var layers = m_Model.layers.Where(i => i.type != Layer.Type.Load);
|
||||
var constants = m_Model.layers.Where(i => i.type == Layer.Type.Load);
|
||||
|
||||
m_Layers = layers.Select(i => i.type.ToString()).ToList();
|
||||
m_LayersDesc = layers.Select(i => i.ToString()).ToList();
|
||||
m_Constants = constants.Select(i => i.type.ToString()).ToList();
|
||||
m_ConstantsDesc = constants.Select(i => i.ToString()).ToList();
|
||||
|
||||
m_NumEmbeddedWeights = layers.Sum(l => (long)l.datasets.Sum(ds => (long)ds.length));
|
||||
m_NumConstantWeights = constants.Sum(l => (long)l.datasets.Sum(ds => (long)ds.length));
|
||||
|
||||
// weights are not loaded for UI, recompute size
|
||||
m_TotalWeightsSizeInBytes = 0;
|
||||
for (var l = 0; l < m_Model.layers.Count; ++l)
|
||||
for (var d = 0; d < m_Model.layers[l].datasets.Length; ++d)
|
||||
m_TotalWeightsSizeInBytes += m_Model.layers[l].datasets[d].length * m_Model.layers[l].datasets[d].itemSizeInBytes;
|
||||
|
||||
m_Metadata = new Dictionary<string, string>(m_Model.Metadata);
|
||||
|
||||
for (int i = 0; i < m_Model.Warnings.Count; i++)
|
||||
{
|
||||
var warning = m_Model.Warnings[i].LayerName;
|
||||
var warningDesc = m_Model.Warnings[i].Message;
|
||||
MessageType messageType = MessageType.Warning;
|
||||
if(warningDesc.StartsWith("MessageType"))
|
||||
{
|
||||
messageType = (MessageType)(warningDesc[12] - '0');
|
||||
warningDesc = warningDesc.Substring(13);
|
||||
}
|
||||
|
||||
switch (messageType)
|
||||
{
|
||||
case MessageType.None:
|
||||
m_WarningsNeutral[warning] = warningDesc;
|
||||
break;
|
||||
case MessageType.Info:
|
||||
m_WarningsInfo[warning] = warningDesc;
|
||||
break;
|
||||
case MessageType.Warning:
|
||||
m_WarningsWarning[warning] = warningDesc;
|
||||
break;
|
||||
case MessageType.Error:
|
||||
m_WarningsError[warning] = warningDesc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenNNModelAsTempFileButton(NNModel nnModel)
|
||||
{
|
||||
if (nnModel == null)
|
||||
return;
|
||||
if (nnModel.modelData == null)
|
||||
return;
|
||||
|
||||
if (GUILayout.Button("Open imported NN model as temp file"))
|
||||
{
|
||||
string tempPath = Application.temporaryCachePath;
|
||||
string filePath = Path.Combine(tempPath, nnModel.name);
|
||||
string filePathWithExtension = Path.ChangeExtension(filePath, "nn");
|
||||
File.WriteAllBytes(filePathWithExtension, nnModel.modelData.Value);
|
||||
System.Diagnostics.Process.Start(filePathWithExtension);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Editor UI rendering callback
|
||||
/// </summary>
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (m_Model == null)
|
||||
return;
|
||||
|
||||
// HACK: When inspector settings are applied and the file is re-imported there doesn't seem to be a clean way to
|
||||
// get a notification from Unity, so we detect this change
|
||||
var nnModel = target as NNModel;
|
||||
if (nnModel && m_Model != nnModel.GetDeserializedModel())
|
||||
OnEnable(); // Model data changed underneath while inspector was active, so reload
|
||||
|
||||
GUI.enabled = true;
|
||||
OpenNNModelAsTempFileButton(nnModel);
|
||||
GUILayout.Label($"Source: {m_Model.IrSource}");
|
||||
GUILayout.Label($"Version: {m_Model.IrVersion}");
|
||||
GUILayout.Label($"Producer Name: {m_Model.ProducerName}");
|
||||
|
||||
if (m_Metadata.Any())
|
||||
{
|
||||
ListUIHelper($"Metadata {m_Metadata.Count}",
|
||||
m_Metadata.Keys.ToList(), m_Metadata.Values.ToList(), ref m_MetadataScrollPosition);
|
||||
}
|
||||
|
||||
if(m_WarningsError.Any())
|
||||
{
|
||||
ListUIHelper($"Errors {m_WarningsError.Count.ToString()}", m_WarningsError.Keys.ToList(), m_WarningsError.Values.ToList(), ref m_WarningsErrorScrollPosition);
|
||||
EditorGUILayout.HelpBox("Model contains errors. Behavior might be incorrect", MessageType.Error, true);
|
||||
}
|
||||
if(m_WarningsWarning.Any())
|
||||
{
|
||||
ListUIHelper($"Warnings {m_WarningsWarning.Count.ToString()}", m_WarningsWarning.Keys.ToList(), m_WarningsWarning.Values.ToList(), ref m_WarningsWarningScrollPosition);
|
||||
EditorGUILayout.HelpBox("Model contains warnings. Behavior might be incorrect", MessageType.Warning, true);
|
||||
}
|
||||
if(m_WarningsInfo.Any())
|
||||
{
|
||||
ListUIHelper($"Information: ", m_WarningsInfo.Keys.ToList(), m_WarningsInfo.Values.ToList(), ref m_WarningsInfoScrollPosition);
|
||||
EditorGUILayout.HelpBox("Model contains import information.", MessageType.Info, true);
|
||||
}
|
||||
if(m_WarningsNeutral.Any())
|
||||
{
|
||||
ListUIHelper($"Comments: ", m_WarningsNeutral.Keys.ToList(), m_WarningsNeutral.Values.ToList(), ref m_WarningsNeutralScrollPosition);
|
||||
}
|
||||
var constantWeightInfo = m_Constants.Count > 0 ? $" using {m_NumConstantWeights:n0} weights" : "";
|
||||
ListUIHelper($"Inputs ({m_Inputs.Count})", m_Inputs, m_InputsDesc, ref m_InputsScrollPosition);
|
||||
ListUIHelper($"Outputs ({m_Outputs.Count})", m_Outputs, m_OutputsDesc, ref m_OutputsScrollPosition);
|
||||
ListUIHelper($"Memories ({m_Memories.Count})", m_Memories, m_MemoriesDesc, ref m_MemoriesScrollPosition);
|
||||
ListUIHelper($"Layers ({m_Layers.Count} using {m_NumEmbeddedWeights:n0} embedded weights)", m_Layers, m_LayersDesc, ref m_LayerScrollPosition, m_Constants.Count == 0 ? 1.5f: 1f);
|
||||
ListUIHelper($"Constants ({m_Constants.Count}{constantWeightInfo})", m_Constants, m_ConstantsDesc, ref m_ConstantScrollPosition);
|
||||
|
||||
GUILayout.Label($"Total weight size: {m_TotalWeightsSizeInBytes:n0} bytes");
|
||||
}
|
||||
|
||||
private static void ListUIHelper(string sectionTitle, IReadOnlyList<string> names, IReadOnlyList<string> descriptions, ref Vector2 scrollPosition, float maxHeightMultiplier = 1f)
|
||||
{
|
||||
int n = names.Count();
|
||||
UnityEngine.Debug.Assert(descriptions.Count == n);
|
||||
if (descriptions.Count < n)
|
||||
return;
|
||||
|
||||
GUILayout.Space(k_Space);
|
||||
if (!s_UIHelperFoldouts.TryGetValue(sectionTitle, out bool foldout))
|
||||
foldout = true;
|
||||
|
||||
foldout = EditorGUILayout.Foldout(foldout, sectionTitle, true, EditorStyles.foldoutHeader);
|
||||
s_UIHelperFoldouts[sectionTitle] = foldout;
|
||||
if (foldout)
|
||||
{
|
||||
// GUILayout.Label(sectionTitle, EditorStyles.boldLabel);
|
||||
float height = Mathf.Min(n * 20f + 2f, 150f * maxHeightMultiplier);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUI.skin.box, GUILayout.MinHeight(height));
|
||||
Event e = Event.current;
|
||||
float lineHeight = 16.0f;
|
||||
|
||||
StringBuilder fullText = new StringBuilder();
|
||||
fullText.Append(sectionTitle);
|
||||
fullText.AppendLine();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
string name = names[i];
|
||||
string description = descriptions[i];
|
||||
fullText.Append($"{name} {description}");
|
||||
fullText.AppendLine();
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
Rect r = EditorGUILayout.GetControlRect(false, lineHeight);
|
||||
|
||||
string name = names[i];
|
||||
string description = descriptions[i];
|
||||
|
||||
// Context menu, "Copy"
|
||||
if (e.type == EventType.ContextClick && r.Contains(e.mousePosition))
|
||||
{
|
||||
e.Use();
|
||||
var menu = new GenericMenu();
|
||||
|
||||
// need to copy current value to be used in delegate
|
||||
// (C# closures close over variables, not their values)
|
||||
menu.AddItem(new GUIContent($"Copy current line"), false, delegate
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = $"{name} {description}";
|
||||
});
|
||||
menu.AddItem(new GUIContent($"Copy section"), false, delegate
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = fullText.ToString();
|
||||
});
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
// Color even line for readability
|
||||
if (e.type == EventType.Repaint)
|
||||
{
|
||||
GUIStyle st = "CN EntryBackEven";
|
||||
if ((i & 1) == 0)
|
||||
st.Draw(r, false, false, false, false);
|
||||
}
|
||||
|
||||
// layer name on the right side
|
||||
Rect locRect = r;
|
||||
locRect.xMax = locRect.xMin;
|
||||
GUIContent gc = new GUIContent(name.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
// calculate size so we can left-align it
|
||||
Vector2 size = EditorStyles.miniBoldLabel.CalcSize(gc);
|
||||
locRect.xMax += size.x;
|
||||
GUI.Label(locRect, gc, EditorStyles.miniBoldLabel);
|
||||
locRect.xMax += 2;
|
||||
|
||||
// message
|
||||
Rect msgRect = r;
|
||||
msgRect.xMin = locRect.xMax;
|
||||
GUI.Label(msgRect, new GUIContent(description.ToString(CultureInfo.InvariantCulture)), EditorStyles.miniLabel);
|
||||
}
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08ecb3218a86c6741aed5b2a299b203b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Unity.Barracuda.Editor",
|
||||
"references": [
|
||||
"Unity.Barracuda",
|
||||
"Unity.Barracuda.ONNX"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f1e7d835703842dda0e25142ed6c3c9
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.unity.barracuda/Runtime.meta
Normal file
8
Packages/com.unity.barracuda/Runtime.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a03a1fa0e3b784e19a9e9d31b945b252
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.unity.barracuda/Runtime/Core.meta
Normal file
8
Packages/com.unity.barracuda/Runtime/Core.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bec48e8f6ff349488387cf35fbae752
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
using System.Reflection;
|
||||
|
||||
// DON'T EDIT
|
||||
// Will be replaced by Tools/Build/build.py
|
||||
[assembly: AssemblyVersion("3.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("3.0.0.0")]
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7f9574517c146ada866c486dc392731
|
||||
timeCreated: 1533296387
|
||||
8
Packages/com.unity.barracuda/Runtime/Core/Backends.meta
Normal file
8
Packages/com.unity.barracuda/Runtime/Core/Backends.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12a6bedd18899cd4189f66d8188f29ff
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67f00a1befd4144eca5685250d893f09
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq; // ToList()
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace Unity.Barracuda {
|
||||
|
||||
|
||||
internal class BarracudaBackendsFactory
|
||||
{
|
||||
public static WorkerFactory.Type ResolveAutoType(WorkerFactory.Type type)
|
||||
{
|
||||
if (type != WorkerFactory.Type.Auto)
|
||||
return type;
|
||||
return GetBestTypeForDevice(WorkerFactory.Device.Auto);
|
||||
}
|
||||
|
||||
internal static WorkerFactory.Type GetBestTypeForDevice(WorkerFactory.Device device)
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case WorkerFactory.Device.Auto:
|
||||
case WorkerFactory.Device.GPU:
|
||||
return WorkerFactory.Type.ComputePrecompiled;
|
||||
default:
|
||||
return WorkerFactory.Type.CSharpBurst;
|
||||
}
|
||||
}
|
||||
|
||||
internal static WorkerFactory.Type ValidateType(WorkerFactory.Type type)
|
||||
{
|
||||
type = ResolveAutoType(type);
|
||||
Assert.AreNotEqual(type, WorkerFactory.Type.Auto);
|
||||
|
||||
if (WorkerFactory.IsType(type, WorkerFactory.Device.GPU) && !ComputeShaderSingleton.Instance.supported)
|
||||
{
|
||||
type = WorkerFactory.Type.PixelShader;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private static IOps CreateOps(WorkerFactory.Type type, ITensorAllocator allocator, bool verbose)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case WorkerFactory.Type.ComputePrecompiled:
|
||||
return new PrecompiledComputeOps(allocator, verbose);
|
||||
|
||||
case WorkerFactory.Type.Compute:
|
||||
return new ComputeOps(allocator, verbose);
|
||||
|
||||
case WorkerFactory.Type.ComputeRef:
|
||||
return new ReferenceComputeOps(allocator);
|
||||
|
||||
case WorkerFactory.Type.PixelShader:
|
||||
return new PixelShaderOps(allocator);
|
||||
|
||||
case WorkerFactory.Type.CSharpBurst:
|
||||
return new BurstCPUOps(allocator);
|
||||
|
||||
case WorkerFactory.Type.CSharp:
|
||||
return new UnsafeArrayCPUOps(allocator);
|
||||
|
||||
default:
|
||||
return new ReferenceCPUOps(allocator);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IWorker CreateWorker(WorkerFactory.Type type, Model model, string[] additionalOutputs, string[] trimOutputs, WorkerFactory.WorkerConfiguration workerConfiguration, IModelExecutionsReporter modelExecutionsReporter = null)
|
||||
{
|
||||
type = ResolveAutoType(type);
|
||||
var compareAgainstType = ResolveAutoType(workerConfiguration.compareAgainstType);
|
||||
Assert.AreNotEqual(type, WorkerFactory.Type.Auto);
|
||||
Assert.AreNotEqual(compareAgainstType, WorkerFactory.Type.Auto);
|
||||
|
||||
bool compare = type != compareAgainstType;
|
||||
|
||||
if (WorkerFactory.IsType(type, WorkerFactory.Device.GPU) && !SystemInfo.supportsComputeShaders && !Application.isEditor)
|
||||
{
|
||||
type = WorkerFactory.Type.PixelShader;
|
||||
}
|
||||
|
||||
IVars vars;
|
||||
// PixelShader worker uses Blit/Textures, cannot re-use vars unless the dispatch mechanism allows rendering to sub part of the texture
|
||||
if ((type == WorkerFactory.Type.PixelShader) || (compareAgainstType == WorkerFactory.Type.PixelShader))
|
||||
vars = new GenericVarsWithReuse();
|
||||
else
|
||||
{
|
||||
if (WorkerFactory.IsType(type, WorkerFactory.Device.GPU) || WorkerFactory.IsType(compareAgainstType, WorkerFactory.Device.GPU))
|
||||
vars = new ComputeVarsWithSharedModel();
|
||||
else
|
||||
vars = new DefaultVars();
|
||||
}
|
||||
|
||||
ITensorAllocator allocator = vars.GetAllocator();
|
||||
if ((type == WorkerFactory.Type.PixelShader) || (compareAgainstType == WorkerFactory.Type.PixelShader))
|
||||
allocator = new TensorCachingByShapeAllocator();
|
||||
|
||||
if (workerConfiguration.verbose)
|
||||
D.Log($"Storage type: {vars.GetType()}. Allocator type: {allocator.GetType()}.");
|
||||
|
||||
IOps ops = CreateOps(type, allocator, workerConfiguration.verbose);
|
||||
|
||||
if (compare)
|
||||
ops = new CompareOps(ops,
|
||||
CreateOps(compareAgainstType, allocator, workerConfiguration.verbose), workerConfiguration.compareLogLevel, workerConfiguration.compareEpsilon);
|
||||
|
||||
if (workerConfiguration.verbose || modelExecutionsReporter != null)
|
||||
ops = new VerboseOps(ops, workerConfiguration.verbose);
|
||||
|
||||
if (Application.isEditor || modelExecutionsReporter != null)
|
||||
ops = new StatsOps(ops);
|
||||
|
||||
model = ValidateModel(
|
||||
PatchModel(model, additionalOutputs, trimOutputs));
|
||||
|
||||
ops.SetModelExecutionsReporter(modelExecutionsReporter);
|
||||
return new GenericWorker(model, ops, vars, workerConfiguration.verbose, workerConfiguration.takeoverWeights);
|
||||
}
|
||||
|
||||
internal static Model PatchModel(Model model, string[] additionalOutputs, string[] trimOutputs = null)
|
||||
{
|
||||
bool trimModel = trimOutputs != null;
|
||||
|
||||
if (trimOutputs != null)
|
||||
{
|
||||
foreach (var o in trimOutputs.Except(model.outputs))
|
||||
if (additionalOutputs == null || !additionalOutputs.Contains(o))
|
||||
D.LogWarning($"Output specified in trimOutputs was not found in the model: {o}");
|
||||
|
||||
var newModel = model.ShallowCopy();
|
||||
newModel.outputs = trimOutputs.Intersect(model.outputs).ToList();
|
||||
model = newModel;
|
||||
}
|
||||
|
||||
if (additionalOutputs != null)
|
||||
{
|
||||
foreach (var o in additionalOutputs.Except(model.layers.Select(l => l.name)))
|
||||
D.LogWarning($"Layer specified in additionalOutputs was not found in the model: {o}");
|
||||
|
||||
// 'new' means that output name does not yet exist in model.outputs
|
||||
// 'valid' means that output name matches one of the existing model.layer names
|
||||
var newAndValidAdditionalOutputs =
|
||||
additionalOutputs.Except(model.outputs).Intersect(model.layers.Select(l => l.name));
|
||||
|
||||
var newModel = model.ShallowCopy();
|
||||
newModel.outputs.AddRange(newAndValidAdditionalOutputs);
|
||||
model = newModel;
|
||||
}
|
||||
|
||||
if (trimModel)
|
||||
{
|
||||
var newModel = model.ShallowCopy();
|
||||
var upstream = ModelAnalyzer.FindUpstreamLayers(model, newModel.outputs.ToArray());
|
||||
foreach (var l in model.layers)
|
||||
if (!upstream.Contains(l))
|
||||
newModel.layers.Remove(l);
|
||||
|
||||
model = newModel;
|
||||
}
|
||||
|
||||
model = ModelOptimizer.RemoveNoop(model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
internal static Model ValidateModel(Model model)
|
||||
{
|
||||
// validate, model contains no broken links
|
||||
var brokenLinks = ModelAnalyzer.FindBrokenLinks(model);
|
||||
if (brokenLinks.Length > 0)
|
||||
D.LogWarning($"Model contains {brokenLinks.Length} broken links: {string.Join(",", brokenLinks)}");
|
||||
|
||||
// validate, all model outputs are unique
|
||||
// https://stackoverflow.com/questions/18547354/c-sharp-linq-find-duplicates-in-list
|
||||
var duplicateOutputs = model.outputs.GroupBy(x => x)
|
||||
.Where(g => g.Count() > 1)
|
||||
.Select(y => y.Key);
|
||||
foreach (var o in duplicateOutputs)
|
||||
D.LogWarning($"Output is specified more than once in the model: {o}");
|
||||
|
||||
// validate, model contains no unconnected layers
|
||||
var unconnectedOutputs = ModelAnalyzer.FindUnconnectedOutputs(model);
|
||||
foreach (var o in unconnectedOutputs)
|
||||
D.LogWarning($"Layer is specified as output, but is missing in the model: {o}");
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Unity.Barracuda
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 355dc370391814b1c874848bb843b91c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,245 @@
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
using Unity.Jobs;
|
||||
|
||||
namespace Unity.Barracuda {
|
||||
|
||||
// BarracudaBurstCPU.Core.cs -- definition of class BurstCPUOps, Pin(), BurstTensorData
|
||||
// BarracudaBurstCPU.Ops.cs -- impl. IOps, job schedulers
|
||||
// BarracudaBurstCPU.Jobs.cs -- impl. jobs
|
||||
|
||||
/// <summary>
|
||||
/// Burst specific internal `Tensor` data storage
|
||||
/// </summary>
|
||||
public class BurstTensorData : UnsafeArrayTensorData, IDependableTensorData
|
||||
{
|
||||
private JobHandle m_ReadFence;
|
||||
private JobHandle m_WriteFence;
|
||||
private bool m_SafeToDispose = true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public JobHandle fence { get { return m_ReadFence; } set { m_ReadFence = value; m_WriteFence = value; m_SafeToDispose = false; } }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public JobHandle reuse { get { return m_WriteFence; } set { m_WriteFence = BurstCPUOps.Dependencies(value, m_WriteFence); m_SafeToDispose = false; } }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public unsafe void* rawPtr => array.RawAddressAt(offset);
|
||||
|
||||
/// <summary>
|
||||
/// Creates new array
|
||||
/// </summary>
|
||||
/// <param name="count">count</param>
|
||||
public BurstTensorData(int count, DataType dataType) : base(count, dataType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates new array
|
||||
/// </summary>
|
||||
/// <param name="shape">shape</param>
|
||||
public BurstTensorData(TensorShape shape, DataType dataType) : base(shape, dataType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses shared array
|
||||
/// </summary>
|
||||
/// <param name="sharedArray">shared array</param>
|
||||
public BurstTensorData(ArrayTensorData sharedArray) : base(sharedArray)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses shared array
|
||||
/// </summary>
|
||||
/// <param name="sharedArray">shared array</param>
|
||||
public BurstTensorData(SharedArrayTensorData sharedArray) : base(sharedArray)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses unsafe array
|
||||
/// </summary>
|
||||
/// <param name="unsafeArray">unsafe array</param>
|
||||
public BurstTensorData(UnsafeArrayTensorData unsafeArray) : base(unsafeArray.array, unsafeArray.offset, unsafeArray.count, unsafeArray.m_Readonly)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~BurstTensorData()
|
||||
{
|
||||
if (!m_SafeToDispose)
|
||||
D.LogWarning($"Found unreferenced, but undisposed Tensor data that potentially participates in an unfinished job and might lead to hazardous memory overwrites: {ToString()}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose contents
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
// It isn't safe to Complete jobs from a finalizer thread, so
|
||||
if (Thread.CurrentThread == BurstCPUOps.MainThread)
|
||||
CompleteAllPendingOperations();
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
internal void CompleteAllPendingOperations()
|
||||
{
|
||||
fence.Complete();
|
||||
reuse.Complete();
|
||||
m_SafeToDispose = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reserve (allocate) storage for `count` elements
|
||||
/// </summary>
|
||||
/// <param name="count">count</param>
|
||||
public override void Reserve(int count)
|
||||
{
|
||||
if (count > maxCapacity)
|
||||
{
|
||||
// going to reallocate memory in base.Reserve()
|
||||
// thus need to finish current work
|
||||
CompleteAllPendingOperations();
|
||||
}
|
||||
|
||||
base.Reserve(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload data to internal storage
|
||||
/// </summary>
|
||||
/// <param name="data">data</param>
|
||||
/// <param name="shape">shape</param>
|
||||
/// <param name="managedBufferStartIndex">`data` start index</param>
|
||||
public override void Upload(float[] data, TensorShape shape, int managedBufferStartIndex = 0)
|
||||
{
|
||||
CompleteAllPendingOperations();
|
||||
base.Upload(data, shape, managedBufferStartIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return data from internal storage
|
||||
/// </summary>
|
||||
/// <param name="shape">shape</param>
|
||||
/// <returns>managed array</returns>
|
||||
public override float[] Download(TensorShape shape)
|
||||
{
|
||||
// Download() as optimization gives direct access to the internal buffer
|
||||
// thus need to prepare internal buffer for potential writes
|
||||
CompleteAllPendingOperations();
|
||||
return base.Download(shape);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return shared array from internal storage
|
||||
/// </summary>
|
||||
/// <returns>shared array from internal storage</returns>
|
||||
public override BarracudaArray SharedAccess(out int offset)
|
||||
{
|
||||
// SharedAccess() by design gives direct access to the interna
|
||||
// thus need to prepare internal buffer for potential writes
|
||||
CompleteAllPendingOperations();
|
||||
return base.SharedAccess(out offset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Schedule async internal data download
|
||||
/// </summary>
|
||||
/// <param name="count">count to download</param>
|
||||
/// <returns>`true` if download is completed</returns>
|
||||
public override bool ScheduleAsyncDownload(int count)
|
||||
{
|
||||
return fence.IsCompleted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Object summary as string
|
||||
/// </summary>
|
||||
/// <returns>object summary</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
string readyToRead = m_SafeToDispose ? "true": "unknown";
|
||||
string readyForReuse = m_SafeToDispose ? "true": "unknown";
|
||||
try
|
||||
{
|
||||
readyToRead = fence.IsCompleted.ToString();
|
||||
readyForReuse = reuse.IsCompleted.ToString();
|
||||
}
|
||||
catch (UnityException) {}
|
||||
return string.Format("(CPU burst: {0} length: {1} offset: {2} uploaded: {3} ready-to-read: {4} ready-for-reuse: {5})",
|
||||
GetHashCode(), m_Array?.Length, m_Offset, m_Count, readyToRead, readyForReuse);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Burst specific implementation of `IOps`
|
||||
/// </summary>
|
||||
public partial class BurstCPUOps : UnsafeArrayCPUOps
|
||||
{
|
||||
/// <summary>
|
||||
/// Create `BurstCPUOps`
|
||||
/// </summary>
|
||||
/// <param name="allocator">allocator</param>
|
||||
public BurstCPUOps(ITensorAllocator allocator = null)
|
||||
: base(allocator)
|
||||
{
|
||||
if (PreferBLAS == BLAS.Native && !blas.IsNative())
|
||||
PreferBLAS = BLAS.Disabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pin `Tensor` to Burst backend device, if `uploadCache` is false, data is not uploaded to device
|
||||
/// </summary>
|
||||
/// <param name="X">`Tensor`</param>
|
||||
/// <param name="uploadCache">`bool`</param>
|
||||
/// <returns>`BurstTensorData`</returns>
|
||||
new public static BurstTensorData Pin(Tensor X, bool uploadCache = true)
|
||||
{
|
||||
X.FlushCache(uploadCache);
|
||||
|
||||
var onDevice = X.tensorOnDevice as BurstTensorData;
|
||||
if (onDevice == null)
|
||||
{
|
||||
// try to adopt CPU arrays
|
||||
var asUnsafeArray = X.tensorOnDevice as UnsafeArrayTensorData;
|
||||
var asSharedArray = X.tensorOnDevice as SharedArrayTensorData;
|
||||
var asArray = X.tensorOnDevice as ArrayTensorData;
|
||||
if (asUnsafeArray != null) X.AttachToDevice(new BurstTensorData(asUnsafeArray));
|
||||
else if (asSharedArray != null) X.AttachToDevice(new BurstTensorData(asSharedArray));
|
||||
else if (asArray != null) X.AttachToDevice(new BurstTensorData(asArray));
|
||||
else
|
||||
{
|
||||
if (uploadCache)
|
||||
X.UploadToDevice(new BurstTensorData(X.shape, X.dataType)); // device is not compatible, create new array and upload
|
||||
else
|
||||
X.AllocateOnDevice(new BurstTensorData(X.shape, X.dataType)); // device is not compatible, create new array but do not upload
|
||||
}
|
||||
}
|
||||
|
||||
return X.tensorOnDevice as BurstTensorData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepare `Tensor` for use with Burst backend
|
||||
/// </summary>
|
||||
/// <param name="X">`Tensor`</param>
|
||||
/// <returns>`Tensor`</returns>
|
||||
public override Tensor Prepare(Tensor X)
|
||||
{
|
||||
Pin(X);
|
||||
return X;
|
||||
}
|
||||
|
||||
public override Tensor PrepareNoAlloc(Tensor X)
|
||||
{
|
||||
Pin(X, uploadCache: false);
|
||||
return X;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Barracuda
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f44c1c453c1754aaeb1e8608df82452b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,471 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace Unity.Barracuda {
|
||||
|
||||
//#region Job output context helper
|
||||
|
||||
internal static class BurstSchedulingHelper
|
||||
{
|
||||
#region Private scheduling helpers with pointer aliasing verification
|
||||
|
||||
private static unsafe JobHandle ScheduleXSBOInternal<T>(T jobData,
|
||||
JobHandle fenceBeforeJobStart,
|
||||
void* ptrX,
|
||||
void* ptrS,
|
||||
void* ptrB,
|
||||
void* ptrO,
|
||||
int arrayLength, int innerloopBatchCount)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXSBO
|
||||
{
|
||||
T jobDataInternalCopy = jobData;
|
||||
jobDataInternalCopy.X = new BurstCPUOps.ReadOnlyMemResource() {ptr = ptrX};
|
||||
jobDataInternalCopy.S = new BurstCPUOps.ReadOnlyMemResource() {ptr = ptrS};
|
||||
jobDataInternalCopy.B = new BurstCPUOps.ReadOnlyMemResource() {ptr = ptrB};
|
||||
jobDataInternalCopy.O = new BurstCPUOps.ReadWriteMemResource() {ptr = ptrO};
|
||||
return jobDataInternalCopy.Schedule(arrayLength, innerloopBatchCount, fenceBeforeJobStart);
|
||||
}
|
||||
|
||||
private static unsafe JobHandle ScheduleXBOInternal<T>(T jobData,
|
||||
JobHandle fenceBeforeJobStart,
|
||||
void* ptrX,
|
||||
void* ptrB,
|
||||
void* ptrO,
|
||||
int arrayLength, int innerloopBatchCount)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXBO
|
||||
{
|
||||
T jobDataInternalCopy = jobData;
|
||||
jobDataInternalCopy.X = new BurstCPUOps.ReadOnlyMemResource() {ptr = ptrX};
|
||||
jobDataInternalCopy.B = new BurstCPUOps.ReadOnlyMemResource() {ptr = ptrB};
|
||||
jobDataInternalCopy.O = new BurstCPUOps.ReadWriteMemResource() {ptr = ptrO};
|
||||
return jobDataInternalCopy.Schedule(arrayLength, innerloopBatchCount, fenceBeforeJobStart);
|
||||
}
|
||||
|
||||
private static unsafe JobHandle ScheduleXOInternal<T>(T jobData,
|
||||
JobHandle fenceBeforeJobStart,
|
||||
void* ptrX,
|
||||
void* ptrO,
|
||||
int arrayLength, int innerloopBatchCount)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXO
|
||||
{
|
||||
T jobDataInternalCopy = jobData;
|
||||
jobDataInternalCopy.X = new BurstCPUOps.ReadOnlyMemResource() {ptr = ptrX};
|
||||
jobDataInternalCopy.O = new BurstCPUOps.ReadWriteMemResource() {ptr = ptrO};
|
||||
return jobDataInternalCopy.Schedule(arrayLength, innerloopBatchCount, fenceBeforeJobStart);
|
||||
}
|
||||
|
||||
private static unsafe JobHandle ScheduleXOInternal<T>(T jobData,
|
||||
JobHandle fenceBeforeJobStart,
|
||||
void* ptrX,
|
||||
void* ptrO)
|
||||
where T : struct, IJob, BurstCPUOps.IJobResourceDeclarationXO
|
||||
{
|
||||
Assert.IsTrue(ptrO != ptrX);
|
||||
T jobDataInternalCopy = jobData;
|
||||
jobDataInternalCopy.X = new BurstCPUOps.ReadOnlyMemResource() {ptr = ptrX};
|
||||
jobDataInternalCopy.O = new BurstCPUOps.ReadWriteMemResource() {ptr = ptrO};
|
||||
return jobDataInternalCopy.Schedule(fenceBeforeJobStart);
|
||||
}
|
||||
|
||||
private static unsafe JobHandle ScheduleOInternal<T>(T jobData,
|
||||
JobHandle fenceBeforeJobStart,
|
||||
void* ptrO)
|
||||
where T : struct, IJob, BurstCPUOps.IJobResourceDeclarationO
|
||||
{
|
||||
T jobDataInternalCopy = jobData;
|
||||
jobDataInternalCopy.O = new BurstCPUOps.ReadWriteMemResource() {ptr = ptrO};
|
||||
return jobDataInternalCopy.Schedule(fenceBeforeJobStart);
|
||||
}
|
||||
|
||||
private static unsafe JobHandle ScheduleOInternal<T>(T jobData,
|
||||
JobHandle fenceBeforeJobStart,
|
||||
void* ptrO,
|
||||
int arrayLength, int innerloopBatchCount)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationO
|
||||
{
|
||||
T jobDataInternalCopy = jobData;
|
||||
jobDataInternalCopy.O = new BurstCPUOps.ReadWriteMemResource() {ptr = ptrO};
|
||||
return jobDataInternalCopy.Schedule(arrayLength, innerloopBatchCount, fenceBeforeJobStart);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private fencing helper for readability
|
||||
private static JobHandle GetFenceBeforeJobStartXSBO(
|
||||
IDependableMemoryResource pinX,
|
||||
IDependableMemoryResource pinS,
|
||||
IDependableMemoryResource pinB,
|
||||
IDependableMemoryResource pinO)
|
||||
{
|
||||
return BurstCPUOps.Dependencies(pinX.fence, pinS.fence, pinB.fence, pinO.reuse);
|
||||
}
|
||||
|
||||
private static JobHandle GetFenceBeforeJobStartXBO(
|
||||
IDependableMemoryResource pinX,
|
||||
IDependableMemoryResource pinB,
|
||||
IDependableMemoryResource pinO)
|
||||
{
|
||||
return BurstCPUOps.Dependencies(pinX.fence, pinB.fence, pinO.reuse);
|
||||
}
|
||||
|
||||
private static JobHandle GetFenceBeforeJobStartXO(
|
||||
IDependableMemoryResource pinX,
|
||||
IDependableMemoryResource pinO)
|
||||
{
|
||||
return BurstCPUOps.Dependencies(pinX.fence, pinO.reuse);
|
||||
}
|
||||
|
||||
private static void SetXSBOFences(this JobHandle jobFence,
|
||||
IDependableMemoryResource pinX,
|
||||
IDependableMemoryResource pinS,
|
||||
IDependableMemoryResource pinB,
|
||||
IDependableMemoryResource pinO)
|
||||
{
|
||||
pinX.reuse = jobFence;
|
||||
pinS.reuse = jobFence;
|
||||
pinB.reuse = jobFence;
|
||||
pinO.fence = jobFence;
|
||||
}
|
||||
|
||||
private static void SetXBOFences(this JobHandle jobFence,
|
||||
IDependableMemoryResource pinX,
|
||||
IDependableMemoryResource pinB,
|
||||
IDependableMemoryResource pinO)
|
||||
{
|
||||
pinX.reuse = jobFence;
|
||||
pinB.reuse = jobFence;
|
||||
pinO.fence = jobFence;
|
||||
}
|
||||
|
||||
private static void SetXOFences(this JobHandle jobFence,
|
||||
IDependableMemoryResource pinX,
|
||||
IDependableMemoryResource pinO)
|
||||
{
|
||||
pinX.reuse = jobFence;
|
||||
pinO.fence = jobFence;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Immediate scheduling helper
|
||||
internal enum FencingHelperMode
|
||||
{
|
||||
UpdateResourcesFencesOnScheduling,
|
||||
CustomResourcesFencesHandling,
|
||||
}
|
||||
|
||||
internal static unsafe JobHandle ScheduleXSBO<T>(this T jobData,
|
||||
IDependableMemoryResource rX,
|
||||
IDependableMemoryResource rS,
|
||||
IDependableMemoryResource rB,
|
||||
IDependableMemoryResource rO,
|
||||
int arrayLength, int innerloopBatchCount,
|
||||
FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXSBO
|
||||
{
|
||||
var fenceBeforeJobStart = GetFenceBeforeJobStartXSBO(rX, rS, rB, rO);
|
||||
|
||||
JobHandle jobFence;
|
||||
{
|
||||
jobFence = ScheduleXSBOInternal(jobData, fenceBeforeJobStart, rX.rawPtr, rS.rawPtr, rB.rawPtr, rO.rawPtr, arrayLength, innerloopBatchCount);
|
||||
}
|
||||
|
||||
if (fencingMode==FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
jobFence.SetXSBOFences(rX, rS, rB, rO);
|
||||
}
|
||||
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
internal static unsafe JobHandle ScheduleXBO<T>(this T jobData,
|
||||
IDependableMemoryResource X,
|
||||
IDependableMemoryResource B,
|
||||
IDependableMemoryResource O,
|
||||
int arrayLength, int innerloopBatchCount,
|
||||
FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXBO
|
||||
{
|
||||
var fenceBeforeJobStart = GetFenceBeforeJobStartXBO(X, B, O);
|
||||
|
||||
JobHandle jobFence;
|
||||
{
|
||||
jobFence = ScheduleXBOInternal(jobData, fenceBeforeJobStart, X.rawPtr, B.rawPtr, O.rawPtr, arrayLength, innerloopBatchCount);
|
||||
}
|
||||
|
||||
if (fencingMode==FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
jobFence.SetXBOFences(X, B, O);
|
||||
}
|
||||
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
internal static unsafe JobHandle ScheduleO<T>(this T jobData,
|
||||
IDependableMemoryResource O,
|
||||
FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
where T : struct, IJob, BurstCPUOps.IJobResourceDeclarationO
|
||||
{
|
||||
var fenceBeforeJobStart = O.reuse;
|
||||
|
||||
JobHandle jobFence;
|
||||
{
|
||||
jobFence = ScheduleOInternal(jobData, fenceBeforeJobStart, O.rawPtr);
|
||||
}
|
||||
|
||||
if (fencingMode==FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
O.fence = jobFence;
|
||||
}
|
||||
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
internal static unsafe JobHandle ScheduleXO<T>(this T jobData,
|
||||
IDependableMemoryResource X,
|
||||
IDependableMemoryResource O,
|
||||
int arrayLength, int innerloopBatchCount,
|
||||
FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXO
|
||||
{
|
||||
var fenceBeforeJobStart = GetFenceBeforeJobStartXO(X, O);
|
||||
|
||||
JobHandle jobFence;
|
||||
{
|
||||
jobFence = ScheduleXOInternal(jobData, fenceBeforeJobStart, X.rawPtr, O.rawPtr, arrayLength, innerloopBatchCount);
|
||||
}
|
||||
|
||||
if (fencingMode==FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
jobFence.SetXOFences(X, O);
|
||||
}
|
||||
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
internal static unsafe JobHandle ScheduleO<T>(this T jobData,
|
||||
BurstTensorData pinO,
|
||||
int offsetO,
|
||||
int arrayLength, int innerloopBatchCount,
|
||||
FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationO
|
||||
{
|
||||
var fenceBeforeJobStart = pinO.reuse;
|
||||
|
||||
JobHandle jobFence;
|
||||
{
|
||||
void* ptrO = pinO.array.RawAddressAt(pinO.offset+offsetO);
|
||||
jobFence = ScheduleOInternal(jobData, fenceBeforeJobStart, ptrO, arrayLength, innerloopBatchCount);
|
||||
}
|
||||
|
||||
if (fencingMode==FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
pinO.fence = jobFence;
|
||||
}
|
||||
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
internal static unsafe JobHandle ScheduleXO<T>(this T jobData,
|
||||
BurstTensorData pinX,
|
||||
int offsetX,
|
||||
BurstTensorData pinO,
|
||||
int offsetO,
|
||||
FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
where T : struct, IJob, BurstCPUOps.IJobResourceDeclarationXO
|
||||
{
|
||||
var fenceBeforeJobStart = GetFenceBeforeJobStartXO(pinX, pinO);
|
||||
|
||||
JobHandle jobFence;
|
||||
{
|
||||
void* ptrX = pinX.array.RawAddressAt(pinX.offset+offsetX);
|
||||
void* ptrO = pinO.array.RawAddressAt(pinO.offset+offsetO);
|
||||
jobFence = ScheduleXOInternal(jobData, fenceBeforeJobStart, ptrX, ptrO);
|
||||
}
|
||||
|
||||
if (fencingMode==FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
jobFence.SetXOFences(pinX, pinO);
|
||||
}
|
||||
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
internal static unsafe JobHandle ScheduleXO<T>(this T jobData,
|
||||
IDependableMemoryResource X,
|
||||
IDependableMemoryResource O,
|
||||
FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
where T : struct, IJob, BurstCPUOps.IJobResourceDeclarationXO
|
||||
{
|
||||
var fenceBeforeJobStart = GetFenceBeforeJobStartXO(X, O);
|
||||
|
||||
JobHandle jobFence;
|
||||
{
|
||||
jobFence = ScheduleXOInternal(jobData, fenceBeforeJobStart, X.rawPtr, O.rawPtr);
|
||||
}
|
||||
|
||||
if (fencingMode==FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
jobFence.SetXOFences(X, O);
|
||||
}
|
||||
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Schedulling helper for parrallel jobs
|
||||
|
||||
internal struct ParallelJobsContext : IDisposable
|
||||
{
|
||||
internal static Dictionary<IDependableMemoryResource, JobHandle> s_ReadDependencyTracker =
|
||||
new Dictionary<IDependableMemoryResource, JobHandle>(100);
|
||||
|
||||
private readonly IDependableMemoryResource outputResource;
|
||||
private JobHandle combinedJobFence;
|
||||
|
||||
public ParallelJobsContext(IDependableMemoryResource output)
|
||||
{
|
||||
outputResource = output;
|
||||
combinedJobFence = new JobHandle();
|
||||
Assert.AreEqual(0, s_ReadDependencyTracker.Count,
|
||||
"s_ReadDependencyTracker should be empty meaning ParrallelJobs was not disposed properly.");
|
||||
}
|
||||
|
||||
//For now only CopyStrideJobHelper and tests need ParallelJobsContext. If this code need to be duplicated for more case in the future:
|
||||
//- Maybe add generic version by having CopyStrideJobHelper and other helper struct implement an interface (but beware of GC).
|
||||
//- Or make ParallelJobsContext partial and code generated by jobs template.
|
||||
public JobHandle ScheduleXO(
|
||||
BurstCPUOps.CopyStrideJobHelper jobData,//See comment above.
|
||||
BurstTensorData pinX, int offsetX,
|
||||
BurstTensorData pinO, int offsetO)
|
||||
{
|
||||
Assert.IsTrue(pinO == outputResource);
|
||||
var jobFence = jobData.ScheduleXO(pinX, offsetX, pinO, offsetO, BurstSchedulingHelper.FencingHelperMode.CustomResourcesFencesHandling);
|
||||
TrackJobReadDependencies(pinX, jobFence);
|
||||
AddJobDependencyToOutputFence(jobFence);
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
public JobHandle ScheduleXO<T>(
|
||||
T jobData,
|
||||
BurstTensorData pinX,
|
||||
BurstTensorData pinO,
|
||||
int arrayLength, int innerloopBatchCount)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXO
|
||||
{
|
||||
Assert.IsTrue(pinO == outputResource);
|
||||
var jobFence = jobData.ScheduleXO(pinX, pinO, arrayLength, innerloopBatchCount, BurstSchedulingHelper.FencingHelperMode.CustomResourcesFencesHandling);
|
||||
TrackJobReadDependencies(pinX, jobFence);
|
||||
AddJobDependencyToOutputFence(jobFence);
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
|
||||
public JobHandle ScheduleXBO<T>(
|
||||
T jobData,
|
||||
BurstTensorData pinX,
|
||||
BurstTensorData pinB,
|
||||
BurstTensorData pinO,
|
||||
int arrayLength, int innerloopBatchCount)
|
||||
where T : struct, IJobParallelFor, BurstCPUOps.IJobResourceDeclarationXBO
|
||||
{
|
||||
Assert.IsTrue(pinO == outputResource);
|
||||
var jobFence = jobData.ScheduleXBO(pinX, pinB, pinO, arrayLength, innerloopBatchCount, BurstSchedulingHelper.FencingHelperMode.CustomResourcesFencesHandling);
|
||||
TrackJobReadDependencies(pinX, jobFence);
|
||||
TrackJobReadDependencies(pinB, jobFence);
|
||||
AddJobDependencyToOutputFence(jobFence);
|
||||
return jobFence;
|
||||
}
|
||||
|
||||
internal void AddJobDependencyToOutputFence(JobHandle jobFence)
|
||||
{
|
||||
//Once all jobs writing to O will be done, further jobs will be able to read from O.
|
||||
//We combine job fences from all job writing to O here and assign to O.fence in Dispose().
|
||||
combinedJobFence = JobHandle.CombineDependencies(combinedJobFence, jobFence);
|
||||
}
|
||||
|
||||
internal void TrackJobReadDependencies(IDependableMemoryResource T, JobHandle jobFence)
|
||||
{
|
||||
//Once all jobs reading from T will be done, further jobs will be able to write to T.
|
||||
//We combine job fences from all jobs reading from T here and assign to T.reuse in Dispose().
|
||||
if (T != null)
|
||||
{
|
||||
if (s_ReadDependencyTracker.ContainsKey(T))
|
||||
s_ReadDependencyTracker[T] = JobHandle.CombineDependencies(s_ReadDependencyTracker[T], jobFence);
|
||||
else
|
||||
s_ReadDependencyTracker[T] = jobFence;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var key in s_ReadDependencyTracker.Keys)
|
||||
{
|
||||
key.reuse = s_ReadDependencyTracker[key];
|
||||
}
|
||||
outputResource.fence = combinedJobFence;
|
||||
s_ReadDependencyTracker.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Memory allocation wrapper usable by job fencing helpers
|
||||
|
||||
internal unsafe class FencedMemoryAlloc : IDependableMemoryResource
|
||||
{
|
||||
private JobHandle m_ReadFence;
|
||||
private JobHandle m_WriteFence;
|
||||
private void* data;
|
||||
public void* rawPtr => data;
|
||||
public half* halfdata { get { Assert.AreEqual(DataType.Half, type); return (half*) data; } }
|
||||
public float* floatdata { get { Assert.AreEqual(DataType.Float, type);return (float*) data; } }
|
||||
public DataType type;
|
||||
public int elementCount;
|
||||
public int elementSize;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public JobHandle fence { get { return m_ReadFence; } set { m_ReadFence = value; m_WriteFence = value; } }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public JobHandle reuse { get { return m_WriteFence; } set { m_WriteFence = value; } }
|
||||
|
||||
public void Allocate(int numElement, DataType dataType, int alignment, Allocator allocator)
|
||||
{
|
||||
m_ReadFence = new JobHandle();
|
||||
m_WriteFence = new JobHandle();
|
||||
elementCount = numElement;
|
||||
elementSize = BarracudaArray.DataItemSize(dataType);
|
||||
type = dataType;
|
||||
Assert.IsTrue(data == null, "Please call ClearState() when freeing underlying memory.");
|
||||
Assert.IsTrue(alignment % elementSize == 0);
|
||||
data = UnsafeUtility.Malloc(elementCount * elementSize, alignment, allocator);
|
||||
Assert.IsTrue(data != null);
|
||||
}
|
||||
|
||||
public void ClearState()
|
||||
{
|
||||
m_ReadFence = new JobHandle();
|
||||
m_WriteFence = new JobHandle();
|
||||
elementCount = 0;
|
||||
elementSize = 0;
|
||||
type = DataType.Float;
|
||||
data = null;
|
||||
}
|
||||
|
||||
public FencedMemoryAlloc()
|
||||
{
|
||||
ClearState();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
} // namespace Barracuda
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5071bbeadb81d034f827f20e95c52ee6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5211ff135b3b87f42be25a8505a28df7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d05274a6ecc82404abe715a573ea8e74
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,864 @@
|
||||
// This is auto-generated -- do not modify directly
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using Unity.Burst;
|
||||
using Unity.Burst.Intrinsics;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
using static Unity.Burst.Intrinsics.X86.Avx;
|
||||
using static Unity.Burst.Intrinsics.X86.Fma;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using Unity.Jobs.LowLevel.Unsafe;
|
||||
using FencingHelperMode = Unity.Barracuda.BurstSchedulingHelper.FencingHelperMode;
|
||||
|
||||
namespace Unity.Barracuda {
|
||||
public partial class BurstCPUOps
|
||||
{
|
||||
#region Dense/Conv jobs declaration for mode: _Full_Float
|
||||
|
||||
internal partial struct DepthwiseConv2DJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXSBO(Tensor X, Tensor S, Tensor B, Tensor O, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
var pinX = Pin(X);
|
||||
var pinS = Pin(S);
|
||||
var pinB = Pin(B);
|
||||
var pinO = Pin(O, uploadCache: false);
|
||||
return ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
public JobHandle ScheduleXSBO(BurstTensorData pinX, BurstTensorData pinS, BurstTensorData pinB, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool WHalf = pinS.array.Type == DataType.Half;
|
||||
bool BHalf = pinB.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
UnityEngine.Assertions.Assert.AreEqual(WHalf, BHalf);
|
||||
if (AHalf && WHalf)
|
||||
{
|
||||
var job = new DepthwiseConv2DJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && WHalf)
|
||||
{
|
||||
var job = new DepthwiseConv2DJob_ActAsFloat_WeightAsHalf();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && !WHalf)
|
||||
{
|
||||
var job = new DepthwiseConv2DJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else //if (AHalf && !WHalf)
|
||||
{
|
||||
UnityEngine.Assertions.Assert.IsTrue(false, "DepthwiseConv2DJob does not support activation as half while weights are floats.");
|
||||
return new JobHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct DepthwiseConv2DJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } float* Sptr => S.ptrfloat;
|
||||
public ReadOnlyMemResource B { get; set; } float* Bptr => B.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public DepthwiseConv2DJobHelper data;
|
||||
|
||||
const int unrollSize = 16;
|
||||
public void Execute(int y)
|
||||
{
|
||||
int accumulatorMemSize = data.kernelCount * sizeof(float);
|
||||
float* outputAccumulators = (float*)UnsafeUtility.Malloc(accumulatorMemSize, JobsUtility.CacheLineSize, Allocator.TempJob);
|
||||
for (int n = 0; n < data.outBatch; ++n)
|
||||
for (int x = 0; x < data.outWidth; ++x)
|
||||
{
|
||||
// reset accumulators to 0
|
||||
UnsafeUtility.MemClear(outputAccumulators, accumulatorMemSize);
|
||||
|
||||
// gather X * K results in accumulators
|
||||
for (int dy = 0; dy < data.kernelHeight; ++dy)
|
||||
{
|
||||
int readY = y * data.strideY + dy - data.padY;
|
||||
if (readY < 0) continue;
|
||||
if (readY >= data.inHeight) continue;
|
||||
|
||||
for (int dx = 0; dx < data.kernelWidth; ++dx)
|
||||
{
|
||||
int readX = x * data.strideX + dx - data.padY;
|
||||
if (readX < 0) continue;
|
||||
if (readX >= data.inWidth) continue;
|
||||
|
||||
float* dst = outputAccumulators;
|
||||
float* src = Xptr + n * data.inStrideN + readY * data.inStrideH + readX * data.inStrideW;
|
||||
float* kernel = Sptr + dy * data.kernelStrideH + dx * data.kernelStrideW;
|
||||
|
||||
int k = 0;
|
||||
for (; k < data.kernelCount - unrollSize + 1; k += unrollSize) // unroll of kernelCount loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++, kernel++)
|
||||
*dst += (float)((*src) * (*kernel));
|
||||
for (; k < data.kernelCount; k++, src++, dst++, kernel++) // remainder of kernelCount loop
|
||||
*dst += (float)((*src) * (*kernel));
|
||||
}
|
||||
}
|
||||
|
||||
{ // write accumulators to memory and add bias
|
||||
int k = 0;
|
||||
float* src = outputAccumulators;
|
||||
float* dst = Optr + n * data.outStrideN + y * data.outStrideH + x * data.outStrideW;
|
||||
float* bias = Bptr;
|
||||
for (; k < data.kernelCount - unrollSize + 1; k += unrollSize) // unroll of kernelCount loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++, bias++)
|
||||
*dst = (float)((*src) + (*bias));
|
||||
for (; k < data.kernelCount; k++, src++, dst++, bias++) // remainder of kernelCount loop
|
||||
*dst = (float)((*src) + (*bias));
|
||||
}
|
||||
}
|
||||
|
||||
UnsafeUtility.Free(outputAccumulators, Allocator.TempJob);
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct Dense3JobHelper
|
||||
{
|
||||
public JobHandle ScheduleXSBO(Tensor X, Tensor S, Tensor B, Tensor O, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
var pinX = Pin(X);
|
||||
var pinS = Pin(S);
|
||||
var pinB = Pin(B);
|
||||
var pinO = Pin(O, uploadCache: false);
|
||||
return ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
public JobHandle ScheduleXSBO(BurstTensorData pinX, BurstTensorData pinS, BurstTensorData pinB, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool WHalf = pinS.array.Type == DataType.Half;
|
||||
bool BHalf = pinB.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
UnityEngine.Assertions.Assert.AreEqual(WHalf, BHalf);
|
||||
if (AHalf && WHalf)
|
||||
{
|
||||
var job = new Dense3Job_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && WHalf)
|
||||
{
|
||||
var job = new Dense3Job_ActAsFloat_WeightAsHalf();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && !WHalf)
|
||||
{
|
||||
var job = new Dense3Job_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else //if (AHalf && !WHalf)
|
||||
{
|
||||
UnityEngine.Assertions.Assert.IsTrue(false, "Dense3Job does not support activation as half while weights are floats.");
|
||||
return new JobHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct Dense3Job_Full_Float : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } float* Sptr => S.ptrfloat;
|
||||
public ReadOnlyMemResource B { get; set; } float* Bptr => B.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public Dense3JobHelper data;
|
||||
|
||||
public const int blockSize = 16;
|
||||
public void Execute(int threadID)
|
||||
{
|
||||
float* A = this.Xptr;
|
||||
float* B = this.Sptr;
|
||||
float* C = this.Bptr;
|
||||
float* S = this.Optr;
|
||||
int AM = data.AM;
|
||||
int BM = data.BM;
|
||||
int SM = data.SM;
|
||||
int AN = data.AN;
|
||||
int BN = data.BN;
|
||||
int SN = data.SN;
|
||||
|
||||
int dispatchThreadXY = data.dispatchThreadX * data.dispatchThreadY;
|
||||
|
||||
int batch = (threadID / dispatchThreadXY);
|
||||
int i = (threadID % dispatchThreadXY) % data.dispatchThreadX;
|
||||
int j = (threadID % dispatchThreadXY) / data.dispatchThreadX;
|
||||
|
||||
int batchOffSetA = (batch * AM * AN);
|
||||
int batchOffSetS = (batch * SM * SN);
|
||||
|
||||
int rowA = i * blockSize;
|
||||
int colB = j * blockSize;
|
||||
|
||||
unsafe
|
||||
{
|
||||
float* blockTempA = null;
|
||||
float* blockTempB = null;
|
||||
float* blockTempS = null;
|
||||
|
||||
float* blockS = S + rowA + SM * colB + batchOffSetS;
|
||||
int strideS = SM;
|
||||
|
||||
if (rowA + blockSize > SM || colB + blockSize > SN) // copy remainder of C into zero-padded block
|
||||
{
|
||||
blockTempS = AllocBlock(blockSize, blockSize);
|
||||
strideS = blockSize;
|
||||
blockS = blockTempS;
|
||||
}
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockS[x + strideS * y] = (float)((colB + y) < BN ? C[colB + y] : 0.0f);
|
||||
|
||||
for (int l = 0; l < AN; l += blockSize) // inner-loop
|
||||
{
|
||||
float* blockA = A + rowA + AM * l + batchOffSetA;
|
||||
float* blockB = B + l * BN + colB;
|
||||
int strideA = AM;
|
||||
int strideB = BN;
|
||||
|
||||
if (rowA + blockSize > AM || l + blockSize > AN) // copy remainder of A into zero-padded block
|
||||
{
|
||||
if (blockTempA == null)
|
||||
blockTempA = AllocBlock(blockSize, blockSize);
|
||||
strideA = blockSize;
|
||||
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockTempA[x + blockSize * y] = (float)(((rowA + x) < AM && (l + y < AN)) ? blockA[x + AM * y] : 0.0f);
|
||||
|
||||
blockA = blockTempA;
|
||||
}
|
||||
|
||||
if (colB + blockSize > BN || l + blockSize > BM) // copy remainder of B into zero-padded block
|
||||
{
|
||||
if (blockTempB == null)
|
||||
blockTempB = AllocBlock(blockSize, blockSize);
|
||||
strideB = blockSize;
|
||||
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockTempB[x + blockSize * y] = (float)(((colB + x) < BN && (l + y < BM)) ? blockB[x + BN * y] : 0.0f);
|
||||
|
||||
blockB = blockTempB;
|
||||
}
|
||||
|
||||
MultiplyBlockUnrollHx16(blockA, strideA, blockB, strideB, blockS, strideS);
|
||||
}
|
||||
|
||||
if (blockS == blockTempS) // copy back
|
||||
{
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
{
|
||||
if (((rowA + x) < SM) && ((colB + y) < SN))
|
||||
S[(rowA + x) + SM * (colB + y) + batchOffSetS] = blockTempS[x + blockSize * y];
|
||||
}
|
||||
}
|
||||
|
||||
FreeBlock(blockTempA);
|
||||
FreeBlock(blockTempB);
|
||||
FreeBlock(blockTempS);
|
||||
}
|
||||
}
|
||||
|
||||
static void MultiplyBlockUnrollHx16(float* Ap, int Astride, float* Bp, int Bstride, float* Sp, int Sstride)
|
||||
{
|
||||
for (int i = 0; i < blockSize; i++)
|
||||
{
|
||||
float sum0 = *(Sp + i + Sstride * 0);
|
||||
float sum1 = *(Sp + i + Sstride * 1);
|
||||
float sum2 = *(Sp + i + Sstride * 2);
|
||||
float sum3 = *(Sp + i + Sstride * 3);
|
||||
float sum4 = *(Sp + i + Sstride * 4);
|
||||
float sum5 = *(Sp + i + Sstride * 5);
|
||||
float sum6 = *(Sp + i + Sstride * 6);
|
||||
float sum7 = *(Sp + i + Sstride * 7);
|
||||
float sum8 = *(Sp + i + Sstride * 8);
|
||||
float sum9 = *(Sp + i + Sstride * 9);
|
||||
float sumA = *(Sp + i + Sstride * 10);
|
||||
float sumB = *(Sp + i + Sstride * 11);
|
||||
float sumC = *(Sp + i + Sstride * 12);
|
||||
float sumD = *(Sp + i + Sstride * 13);
|
||||
float sumE = *(Sp + i + Sstride * 14);
|
||||
float sumF = *(Sp + i + Sstride * 15);
|
||||
|
||||
for (int l = 0; l < blockSize; l++)
|
||||
{
|
||||
float A = *(Ap + i + Astride * l);
|
||||
|
||||
float B0 = *(Bp + l * Bstride + 0);
|
||||
float B1 = *(Bp + l * Bstride + 1);
|
||||
float B2 = *(Bp + l * Bstride + 2);
|
||||
float B3 = *(Bp + l * Bstride + 3);
|
||||
float B4 = *(Bp + l * Bstride + 4);
|
||||
float B5 = *(Bp + l * Bstride + 5);
|
||||
float B6 = *(Bp + l * Bstride + 6);
|
||||
float B7 = *(Bp + l * Bstride + 7);
|
||||
float B8 = *(Bp + l * Bstride + 8);
|
||||
float B9 = *(Bp + l * Bstride + 9);
|
||||
float BA = *(Bp + l * Bstride + 10);
|
||||
float BB = *(Bp + l * Bstride + 11);
|
||||
float BC = *(Bp + l * Bstride + 12);
|
||||
float BD = *(Bp + l * Bstride + 13);
|
||||
float BE = *(Bp + l * Bstride + 14);
|
||||
float BF = *(Bp + l * Bstride + 15);
|
||||
|
||||
|
||||
sum0 += A * B0;
|
||||
sum1 += A * B1;
|
||||
sum2 += A * B2;
|
||||
sum3 += A * B3;
|
||||
sum4 += A * B4;
|
||||
sum5 += A * B5;
|
||||
sum6 += A * B6;
|
||||
sum7 += A * B7;
|
||||
sum8 += A * B8;
|
||||
sum9 += A * B9;
|
||||
sumA += A * BA;
|
||||
sumB += A * BB;
|
||||
sumC += A * BC;
|
||||
sumD += A * BD;
|
||||
sumE += A * BE;
|
||||
sumF += A * BF;
|
||||
}
|
||||
|
||||
*(Sp + i + Sstride * 0 ) = (float)(sum0);
|
||||
*(Sp + i + Sstride * 1 ) = (float)(sum1);
|
||||
*(Sp + i + Sstride * 2 ) = (float)(sum2);
|
||||
*(Sp + i + Sstride * 3 ) = (float)(sum3);
|
||||
*(Sp + i + Sstride * 4 ) = (float)(sum4);
|
||||
*(Sp + i + Sstride * 5 ) = (float)(sum5);
|
||||
*(Sp + i + Sstride * 6 ) = (float)(sum6);
|
||||
*(Sp + i + Sstride * 7 ) = (float)(sum7);
|
||||
*(Sp + i + Sstride * 8 ) = (float)(sum8);
|
||||
*(Sp + i + Sstride * 9 ) = (float)(sum9);
|
||||
*(Sp + i + Sstride * 10) = (float)(sumA);
|
||||
*(Sp + i + Sstride * 11) = (float)(sumB);
|
||||
*(Sp + i + Sstride * 12) = (float)(sumC);
|
||||
*(Sp + i + Sstride * 13) = (float)(sumD);
|
||||
*(Sp + i + Sstride * 14) = (float)(sumE);
|
||||
*(Sp + i + Sstride * 15) = (float)(sumF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Dense/Conv jobs declaration for mode: _ActAsFloat_WeightAsHalf
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct DepthwiseConv2DJob_ActAsFloat_WeightAsHalf : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public DepthwiseConv2DJobHelper data;
|
||||
|
||||
const int unrollSize = 16;
|
||||
public void Execute(int y)
|
||||
{
|
||||
int accumulatorMemSize = data.kernelCount * sizeof(float);
|
||||
float* outputAccumulators = (float*)UnsafeUtility.Malloc(accumulatorMemSize, JobsUtility.CacheLineSize, Allocator.TempJob);
|
||||
for (int n = 0; n < data.outBatch; ++n)
|
||||
for (int x = 0; x < data.outWidth; ++x)
|
||||
{
|
||||
// reset accumulators to 0
|
||||
UnsafeUtility.MemClear(outputAccumulators, accumulatorMemSize);
|
||||
|
||||
// gather X * K results in accumulators
|
||||
for (int dy = 0; dy < data.kernelHeight; ++dy)
|
||||
{
|
||||
int readY = y * data.strideY + dy - data.padY;
|
||||
if (readY < 0) continue;
|
||||
if (readY >= data.inHeight) continue;
|
||||
|
||||
for (int dx = 0; dx < data.kernelWidth; ++dx)
|
||||
{
|
||||
int readX = x * data.strideX + dx - data.padY;
|
||||
if (readX < 0) continue;
|
||||
if (readX >= data.inWidth) continue;
|
||||
|
||||
float* dst = outputAccumulators;
|
||||
float* src = Xptr + n * data.inStrideN + readY * data.inStrideH + readX * data.inStrideW;
|
||||
half* kernel = Sptr + dy * data.kernelStrideH + dx * data.kernelStrideW;
|
||||
|
||||
int k = 0;
|
||||
for (; k < data.kernelCount - unrollSize + 1; k += unrollSize) // unroll of kernelCount loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++, kernel++)
|
||||
*dst += (float)((*src) * (*kernel));
|
||||
for (; k < data.kernelCount; k++, src++, dst++, kernel++) // remainder of kernelCount loop
|
||||
*dst += (float)((*src) * (*kernel));
|
||||
}
|
||||
}
|
||||
|
||||
{ // write accumulators to memory and add bias
|
||||
int k = 0;
|
||||
float* src = outputAccumulators;
|
||||
float* dst = Optr + n * data.outStrideN + y * data.outStrideH + x * data.outStrideW;
|
||||
half* bias = Bptr;
|
||||
for (; k < data.kernelCount - unrollSize + 1; k += unrollSize) // unroll of kernelCount loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++, bias++)
|
||||
*dst = (float)((*src) + (*bias));
|
||||
for (; k < data.kernelCount; k++, src++, dst++, bias++) // remainder of kernelCount loop
|
||||
*dst = (float)((*src) + (*bias));
|
||||
}
|
||||
}
|
||||
|
||||
UnsafeUtility.Free(outputAccumulators, Allocator.TempJob);
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct Dense3Job_ActAsFloat_WeightAsHalf : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public Dense3JobHelper data;
|
||||
|
||||
public const int blockSize = 16;
|
||||
public void Execute(int threadID)
|
||||
{
|
||||
float* A = this.Xptr;
|
||||
half* B = this.Sptr;
|
||||
half* C = this.Bptr;
|
||||
float* S = this.Optr;
|
||||
int AM = data.AM;
|
||||
int BM = data.BM;
|
||||
int SM = data.SM;
|
||||
int AN = data.AN;
|
||||
int BN = data.BN;
|
||||
int SN = data.SN;
|
||||
|
||||
int dispatchThreadXY = data.dispatchThreadX * data.dispatchThreadY;
|
||||
|
||||
int batch = (threadID / dispatchThreadXY);
|
||||
int i = (threadID % dispatchThreadXY) % data.dispatchThreadX;
|
||||
int j = (threadID % dispatchThreadXY) / data.dispatchThreadX;
|
||||
|
||||
int batchOffSetA = (batch * AM * AN);
|
||||
int batchOffSetS = (batch * SM * SN);
|
||||
|
||||
int rowA = i * blockSize;
|
||||
int colB = j * blockSize;
|
||||
|
||||
unsafe
|
||||
{
|
||||
float* blockTempA = null;
|
||||
half* blockTempB = null;
|
||||
float* blockTempS = null;
|
||||
|
||||
float* blockS = S + rowA + SM * colB + batchOffSetS;
|
||||
int strideS = SM;
|
||||
|
||||
if (rowA + blockSize > SM || colB + blockSize > SN) // copy remainder of C into zero-padded block
|
||||
{
|
||||
blockTempS = AllocBlock(blockSize, blockSize);
|
||||
strideS = blockSize;
|
||||
blockS = blockTempS;
|
||||
}
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockS[x + strideS * y] = (float)((colB + y) < BN ? C[colB + y] : 0.0f);
|
||||
|
||||
for (int l = 0; l < AN; l += blockSize) // inner-loop
|
||||
{
|
||||
float* blockA = A + rowA + AM * l + batchOffSetA;
|
||||
half* blockB = B + l * BN + colB;
|
||||
int strideA = AM;
|
||||
int strideB = BN;
|
||||
|
||||
if (rowA + blockSize > AM || l + blockSize > AN) // copy remainder of A into zero-padded block
|
||||
{
|
||||
if (blockTempA == null)
|
||||
blockTempA = AllocBlock(blockSize, blockSize);
|
||||
strideA = blockSize;
|
||||
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockTempA[x + blockSize * y] = (float)(((rowA + x) < AM && (l + y < AN)) ? blockA[x + AM * y] : 0.0f);
|
||||
|
||||
blockA = blockTempA;
|
||||
}
|
||||
|
||||
if (colB + blockSize > BN || l + blockSize > BM) // copy remainder of B into zero-padded block
|
||||
{
|
||||
if (blockTempB == null)
|
||||
blockTempB = AllocBlockHalf(blockSize, blockSize);
|
||||
strideB = blockSize;
|
||||
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockTempB[x + blockSize * y] = (half)(((colB + x) < BN && (l + y < BM)) ? blockB[x + BN * y] : 0.0f);
|
||||
|
||||
blockB = blockTempB;
|
||||
}
|
||||
|
||||
MultiplyBlockUnrollHx16(blockA, strideA, blockB, strideB, blockS, strideS);
|
||||
}
|
||||
|
||||
if (blockS == blockTempS) // copy back
|
||||
{
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
{
|
||||
if (((rowA + x) < SM) && ((colB + y) < SN))
|
||||
S[(rowA + x) + SM * (colB + y) + batchOffSetS] = blockTempS[x + blockSize * y];
|
||||
}
|
||||
}
|
||||
|
||||
FreeBlock(blockTempA);
|
||||
FreeBlock(blockTempB);
|
||||
FreeBlock(blockTempS);
|
||||
}
|
||||
}
|
||||
|
||||
static void MultiplyBlockUnrollHx16(float* Ap, int Astride, half* Bp, int Bstride, float* Sp, int Sstride)
|
||||
{
|
||||
for (int i = 0; i < blockSize; i++)
|
||||
{
|
||||
float sum0 = *(Sp + i + Sstride * 0);
|
||||
float sum1 = *(Sp + i + Sstride * 1);
|
||||
float sum2 = *(Sp + i + Sstride * 2);
|
||||
float sum3 = *(Sp + i + Sstride * 3);
|
||||
float sum4 = *(Sp + i + Sstride * 4);
|
||||
float sum5 = *(Sp + i + Sstride * 5);
|
||||
float sum6 = *(Sp + i + Sstride * 6);
|
||||
float sum7 = *(Sp + i + Sstride * 7);
|
||||
float sum8 = *(Sp + i + Sstride * 8);
|
||||
float sum9 = *(Sp + i + Sstride * 9);
|
||||
float sumA = *(Sp + i + Sstride * 10);
|
||||
float sumB = *(Sp + i + Sstride * 11);
|
||||
float sumC = *(Sp + i + Sstride * 12);
|
||||
float sumD = *(Sp + i + Sstride * 13);
|
||||
float sumE = *(Sp + i + Sstride * 14);
|
||||
float sumF = *(Sp + i + Sstride * 15);
|
||||
|
||||
for (int l = 0; l < blockSize; l++)
|
||||
{
|
||||
float A = *(Ap + i + Astride * l);
|
||||
|
||||
float B0 = *(Bp + l * Bstride + 0);
|
||||
float B1 = *(Bp + l * Bstride + 1);
|
||||
float B2 = *(Bp + l * Bstride + 2);
|
||||
float B3 = *(Bp + l * Bstride + 3);
|
||||
float B4 = *(Bp + l * Bstride + 4);
|
||||
float B5 = *(Bp + l * Bstride + 5);
|
||||
float B6 = *(Bp + l * Bstride + 6);
|
||||
float B7 = *(Bp + l * Bstride + 7);
|
||||
float B8 = *(Bp + l * Bstride + 8);
|
||||
float B9 = *(Bp + l * Bstride + 9);
|
||||
float BA = *(Bp + l * Bstride + 10);
|
||||
float BB = *(Bp + l * Bstride + 11);
|
||||
float BC = *(Bp + l * Bstride + 12);
|
||||
float BD = *(Bp + l * Bstride + 13);
|
||||
float BE = *(Bp + l * Bstride + 14);
|
||||
float BF = *(Bp + l * Bstride + 15);
|
||||
|
||||
|
||||
sum0 += A * B0;
|
||||
sum1 += A * B1;
|
||||
sum2 += A * B2;
|
||||
sum3 += A * B3;
|
||||
sum4 += A * B4;
|
||||
sum5 += A * B5;
|
||||
sum6 += A * B6;
|
||||
sum7 += A * B7;
|
||||
sum8 += A * B8;
|
||||
sum9 += A * B9;
|
||||
sumA += A * BA;
|
||||
sumB += A * BB;
|
||||
sumC += A * BC;
|
||||
sumD += A * BD;
|
||||
sumE += A * BE;
|
||||
sumF += A * BF;
|
||||
}
|
||||
|
||||
*(Sp + i + Sstride * 0 ) = (float)(sum0);
|
||||
*(Sp + i + Sstride * 1 ) = (float)(sum1);
|
||||
*(Sp + i + Sstride * 2 ) = (float)(sum2);
|
||||
*(Sp + i + Sstride * 3 ) = (float)(sum3);
|
||||
*(Sp + i + Sstride * 4 ) = (float)(sum4);
|
||||
*(Sp + i + Sstride * 5 ) = (float)(sum5);
|
||||
*(Sp + i + Sstride * 6 ) = (float)(sum6);
|
||||
*(Sp + i + Sstride * 7 ) = (float)(sum7);
|
||||
*(Sp + i + Sstride * 8 ) = (float)(sum8);
|
||||
*(Sp + i + Sstride * 9 ) = (float)(sum9);
|
||||
*(Sp + i + Sstride * 10) = (float)(sumA);
|
||||
*(Sp + i + Sstride * 11) = (float)(sumB);
|
||||
*(Sp + i + Sstride * 12) = (float)(sumC);
|
||||
*(Sp + i + Sstride * 13) = (float)(sumD);
|
||||
*(Sp + i + Sstride * 14) = (float)(sumE);
|
||||
*(Sp + i + Sstride * 15) = (float)(sumF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Dense/Conv jobs declaration for mode: _Full_Half
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct DepthwiseConv2DJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public DepthwiseConv2DJobHelper data;
|
||||
|
||||
const int unrollSize = 16;
|
||||
public void Execute(int y)
|
||||
{
|
||||
int accumulatorMemSize = data.kernelCount * sizeof(half);
|
||||
half* outputAccumulators = (half*)UnsafeUtility.Malloc(accumulatorMemSize, JobsUtility.CacheLineSize, Allocator.TempJob);
|
||||
for (int n = 0; n < data.outBatch; ++n)
|
||||
for (int x = 0; x < data.outWidth; ++x)
|
||||
{
|
||||
// reset accumulators to 0
|
||||
UnsafeUtility.MemClear(outputAccumulators, accumulatorMemSize);
|
||||
|
||||
// gather X * K results in accumulators
|
||||
for (int dy = 0; dy < data.kernelHeight; ++dy)
|
||||
{
|
||||
int readY = y * data.strideY + dy - data.padY;
|
||||
if (readY < 0) continue;
|
||||
if (readY >= data.inHeight) continue;
|
||||
|
||||
for (int dx = 0; dx < data.kernelWidth; ++dx)
|
||||
{
|
||||
int readX = x * data.strideX + dx - data.padY;
|
||||
if (readX < 0) continue;
|
||||
if (readX >= data.inWidth) continue;
|
||||
|
||||
half* dst = outputAccumulators;
|
||||
half* src = Xptr + n * data.inStrideN + readY * data.inStrideH + readX * data.inStrideW;
|
||||
half* kernel = Sptr + dy * data.kernelStrideH + dx * data.kernelStrideW;
|
||||
|
||||
int k = 0;
|
||||
for (; k < data.kernelCount - unrollSize + 1; k += unrollSize) // unroll of kernelCount loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++, kernel++)
|
||||
*dst += (half)((*src) * (*kernel));
|
||||
for (; k < data.kernelCount; k++, src++, dst++, kernel++) // remainder of kernelCount loop
|
||||
*dst += (half)((*src) * (*kernel));
|
||||
}
|
||||
}
|
||||
|
||||
{ // write accumulators to memory and add bias
|
||||
int k = 0;
|
||||
half* src = outputAccumulators;
|
||||
half* dst = Optr + n * data.outStrideN + y * data.outStrideH + x * data.outStrideW;
|
||||
half* bias = Bptr;
|
||||
for (; k < data.kernelCount - unrollSize + 1; k += unrollSize) // unroll of kernelCount loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++, bias++)
|
||||
*dst = (half)((*src) + (*bias));
|
||||
for (; k < data.kernelCount; k++, src++, dst++, bias++) // remainder of kernelCount loop
|
||||
*dst = (half)((*src) + (*bias));
|
||||
}
|
||||
}
|
||||
|
||||
UnsafeUtility.Free(outputAccumulators, Allocator.TempJob);
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct Dense3Job_Full_Half : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public Dense3JobHelper data;
|
||||
|
||||
public const int blockSize = 16;
|
||||
public void Execute(int threadID)
|
||||
{
|
||||
half* A = this.Xptr;
|
||||
half* B = this.Sptr;
|
||||
half* C = this.Bptr;
|
||||
half* S = this.Optr;
|
||||
int AM = data.AM;
|
||||
int BM = data.BM;
|
||||
int SM = data.SM;
|
||||
int AN = data.AN;
|
||||
int BN = data.BN;
|
||||
int SN = data.SN;
|
||||
|
||||
int dispatchThreadXY = data.dispatchThreadX * data.dispatchThreadY;
|
||||
|
||||
int batch = (threadID / dispatchThreadXY);
|
||||
int i = (threadID % dispatchThreadXY) % data.dispatchThreadX;
|
||||
int j = (threadID % dispatchThreadXY) / data.dispatchThreadX;
|
||||
|
||||
int batchOffSetA = (batch * AM * AN);
|
||||
int batchOffSetS = (batch * SM * SN);
|
||||
|
||||
int rowA = i * blockSize;
|
||||
int colB = j * blockSize;
|
||||
|
||||
unsafe
|
||||
{
|
||||
half* blockTempA = null;
|
||||
half* blockTempB = null;
|
||||
half* blockTempS = null;
|
||||
|
||||
half* blockS = S + rowA + SM * colB + batchOffSetS;
|
||||
int strideS = SM;
|
||||
|
||||
if (rowA + blockSize > SM || colB + blockSize > SN) // copy remainder of C into zero-padded block
|
||||
{
|
||||
blockTempS = AllocBlockHalf(blockSize, blockSize);
|
||||
strideS = blockSize;
|
||||
blockS = blockTempS;
|
||||
}
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockS[x + strideS * y] = (half)((colB + y) < BN ? C[colB + y] : 0.0f);
|
||||
|
||||
for (int l = 0; l < AN; l += blockSize) // inner-loop
|
||||
{
|
||||
half* blockA = A + rowA + AM * l + batchOffSetA;
|
||||
half* blockB = B + l * BN + colB;
|
||||
int strideA = AM;
|
||||
int strideB = BN;
|
||||
|
||||
if (rowA + blockSize > AM || l + blockSize > AN) // copy remainder of A into zero-padded block
|
||||
{
|
||||
if (blockTempA == null)
|
||||
blockTempA = AllocBlockHalf(blockSize, blockSize);
|
||||
strideA = blockSize;
|
||||
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockTempA[x + blockSize * y] = (half)(((rowA + x) < AM && (l + y < AN)) ? blockA[x + AM * y] : 0.0f);
|
||||
|
||||
blockA = blockTempA;
|
||||
}
|
||||
|
||||
if (colB + blockSize > BN || l + blockSize > BM) // copy remainder of B into zero-padded block
|
||||
{
|
||||
if (blockTempB == null)
|
||||
blockTempB = AllocBlockHalf(blockSize, blockSize);
|
||||
strideB = blockSize;
|
||||
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
blockTempB[x + blockSize * y] = (half)(((colB + x) < BN && (l + y < BM)) ? blockB[x + BN * y] : 0.0f);
|
||||
|
||||
blockB = blockTempB;
|
||||
}
|
||||
|
||||
MultiplyBlockUnrollHx16(blockA, strideA, blockB, strideB, blockS, strideS);
|
||||
}
|
||||
|
||||
if (blockS == blockTempS) // copy back
|
||||
{
|
||||
for (int y = 0; y < blockSize; y++)
|
||||
for (int x = 0; x < blockSize; x++)
|
||||
{
|
||||
if (((rowA + x) < SM) && ((colB + y) < SN))
|
||||
S[(rowA + x) + SM * (colB + y) + batchOffSetS] = blockTempS[x + blockSize * y];
|
||||
}
|
||||
}
|
||||
|
||||
FreeBlock(blockTempA);
|
||||
FreeBlock(blockTempB);
|
||||
FreeBlock(blockTempS);
|
||||
}
|
||||
}
|
||||
|
||||
static void MultiplyBlockUnrollHx16(half* Ap, int Astride, half* Bp, int Bstride, half* Sp, int Sstride)
|
||||
{
|
||||
for (int i = 0; i < blockSize; i++)
|
||||
{
|
||||
float sum0 = *(Sp + i + Sstride * 0);
|
||||
float sum1 = *(Sp + i + Sstride * 1);
|
||||
float sum2 = *(Sp + i + Sstride * 2);
|
||||
float sum3 = *(Sp + i + Sstride * 3);
|
||||
float sum4 = *(Sp + i + Sstride * 4);
|
||||
float sum5 = *(Sp + i + Sstride * 5);
|
||||
float sum6 = *(Sp + i + Sstride * 6);
|
||||
float sum7 = *(Sp + i + Sstride * 7);
|
||||
float sum8 = *(Sp + i + Sstride * 8);
|
||||
float sum9 = *(Sp + i + Sstride * 9);
|
||||
float sumA = *(Sp + i + Sstride * 10);
|
||||
float sumB = *(Sp + i + Sstride * 11);
|
||||
float sumC = *(Sp + i + Sstride * 12);
|
||||
float sumD = *(Sp + i + Sstride * 13);
|
||||
float sumE = *(Sp + i + Sstride * 14);
|
||||
float sumF = *(Sp + i + Sstride * 15);
|
||||
|
||||
for (int l = 0; l < blockSize; l++)
|
||||
{
|
||||
float A = *(Ap + i + Astride * l);
|
||||
|
||||
float B0 = *(Bp + l * Bstride + 0);
|
||||
float B1 = *(Bp + l * Bstride + 1);
|
||||
float B2 = *(Bp + l * Bstride + 2);
|
||||
float B3 = *(Bp + l * Bstride + 3);
|
||||
float B4 = *(Bp + l * Bstride + 4);
|
||||
float B5 = *(Bp + l * Bstride + 5);
|
||||
float B6 = *(Bp + l * Bstride + 6);
|
||||
float B7 = *(Bp + l * Bstride + 7);
|
||||
float B8 = *(Bp + l * Bstride + 8);
|
||||
float B9 = *(Bp + l * Bstride + 9);
|
||||
float BA = *(Bp + l * Bstride + 10);
|
||||
float BB = *(Bp + l * Bstride + 11);
|
||||
float BC = *(Bp + l * Bstride + 12);
|
||||
float BD = *(Bp + l * Bstride + 13);
|
||||
float BE = *(Bp + l * Bstride + 14);
|
||||
float BF = *(Bp + l * Bstride + 15);
|
||||
|
||||
|
||||
sum0 += A * B0;
|
||||
sum1 += A * B1;
|
||||
sum2 += A * B2;
|
||||
sum3 += A * B3;
|
||||
sum4 += A * B4;
|
||||
sum5 += A * B5;
|
||||
sum6 += A * B6;
|
||||
sum7 += A * B7;
|
||||
sum8 += A * B8;
|
||||
sum9 += A * B9;
|
||||
sumA += A * BA;
|
||||
sumB += A * BB;
|
||||
sumC += A * BC;
|
||||
sumD += A * BD;
|
||||
sumE += A * BE;
|
||||
sumF += A * BF;
|
||||
}
|
||||
|
||||
*(Sp + i + Sstride * 0 ) = (half)(sum0);
|
||||
*(Sp + i + Sstride * 1 ) = (half)(sum1);
|
||||
*(Sp + i + Sstride * 2 ) = (half)(sum2);
|
||||
*(Sp + i + Sstride * 3 ) = (half)(sum3);
|
||||
*(Sp + i + Sstride * 4 ) = (half)(sum4);
|
||||
*(Sp + i + Sstride * 5 ) = (half)(sum5);
|
||||
*(Sp + i + Sstride * 6 ) = (half)(sum6);
|
||||
*(Sp + i + Sstride * 7 ) = (half)(sum7);
|
||||
*(Sp + i + Sstride * 8 ) = (half)(sum8);
|
||||
*(Sp + i + Sstride * 9 ) = (half)(sum9);
|
||||
*(Sp + i + Sstride * 10) = (half)(sumA);
|
||||
*(Sp + i + Sstride * 11) = (half)(sumB);
|
||||
*(Sp + i + Sstride * 12) = (half)(sumC);
|
||||
*(Sp + i + Sstride * 13) = (half)(sumD);
|
||||
*(Sp + i + Sstride * 14) = (half)(sumE);
|
||||
*(Sp + i + Sstride * 15) = (half)(sumF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 417ca864422a2384ab3013114bf9f845
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30d1de61c64693a4895a66fecf45a004
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,890 @@
|
||||
// This is auto-generated -- do not modify directly
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using Unity.Burst;
|
||||
using Unity.Burst.Intrinsics;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
using static Unity.Burst.Intrinsics.X86.Avx;
|
||||
using static Unity.Burst.Intrinsics.X86.Fma;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using Unity.Jobs.LowLevel.Unsafe;
|
||||
using FencingHelperMode = Unity.Barracuda.BurstSchedulingHelper.FencingHelperMode;
|
||||
|
||||
namespace Unity.Barracuda {
|
||||
public partial class BurstCPUOps
|
||||
{
|
||||
#region Reduce jobs declaration for mode: _Full_Float
|
||||
|
||||
internal partial struct ReduceMaxJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXO(BurstTensorData pinX, FencedMemoryAlloc pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
if (AHalf)
|
||||
{
|
||||
var job = new ReduceMaxJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var job = new ReduceMaxJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal partial struct ReduceMaxJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXO(Tensor X, Tensor O, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
var pinX = Pin(X);
|
||||
var pinO = Pin(O, uploadCache: false);
|
||||
return ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
public JobHandle ScheduleXO(BurstTensorData pinX, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
if (AHalf)
|
||||
{
|
||||
var job = new ReduceMaxJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var job = new ReduceMaxJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ReduceMaxJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public ReduceMaxJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float maxV = float.MinValue;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
maxV = math.max(maxV, v);
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (float)maxV;
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct ReduceSumJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXO(Tensor X, Tensor O, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
var pinX = Pin(X);
|
||||
var pinO = Pin(O, uploadCache: false);
|
||||
return ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
public JobHandle ScheduleXO(BurstTensorData pinX, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
if (AHalf)
|
||||
{
|
||||
var job = new ReduceSumJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var job = new ReduceSumJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ReduceSumJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public ReduceSumJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float sumV = 0;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
sumV += v;
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (float)(sumV);
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct ReduceMeanJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXO(Tensor X, Tensor O, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
var pinX = Pin(X);
|
||||
var pinO = Pin(O, uploadCache: false);
|
||||
return ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
public JobHandle ScheduleXO(BurstTensorData pinX, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
if (AHalf)
|
||||
{
|
||||
var job = new ReduceMeanJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var job = new ReduceMeanJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ReduceMeanJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public ReduceMeanJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float sumV = 0;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
sumV += v;
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (float)(sumV / (float)data.reduceDim);
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct ExpBiasReduceJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXBO(BurstTensorData pinX, FencedMemoryAlloc pinB, FencedMemoryAlloc pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool WHalf = pinB.type == DataType.Half;
|
||||
bool OHalf = pinO.type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
if (AHalf && WHalf)
|
||||
{
|
||||
var job = new ExpBiasReduceJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXBO(pinX, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && WHalf)
|
||||
{
|
||||
var job = new ExpBiasReduceJob_ActAsFloat_WeightAsHalf();
|
||||
job.data = this;
|
||||
return job.ScheduleXBO(pinX, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && !WHalf)
|
||||
{
|
||||
var job = new ExpBiasReduceJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXBO(pinX, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else //if (AHalf && !WHalf)
|
||||
{
|
||||
UnityEngine.Assertions.Assert.IsTrue(false, "ExpBiasReduceJob does not support activation as half while weights are floats.");
|
||||
return new JobHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ExpBiasReduceJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource B { get; set; } float* Bptr => B.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public ExpBiasReduceJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float accum = 0.0f;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
float b = Bptr[y * data.offsetReduce + x];
|
||||
accum += math.exp(v - b);
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (float)accum;
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct SoftmaxEndJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXSBO(BurstTensorData pinX, FencedMemoryAlloc pinS, FencedMemoryAlloc pinB, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool WHalf = pinS.type == DataType.Half;
|
||||
bool BHalf = pinB.type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
UnityEngine.Assertions.Assert.AreEqual(WHalf, BHalf);
|
||||
if (AHalf && WHalf)
|
||||
{
|
||||
var job = new SoftmaxEndJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && WHalf)
|
||||
{
|
||||
var job = new SoftmaxEndJob_ActAsFloat_WeightAsHalf();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && !WHalf)
|
||||
{
|
||||
var job = new SoftmaxEndJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else //if (AHalf && !WHalf)
|
||||
{
|
||||
UnityEngine.Assertions.Assert.IsTrue(false, "SoftmaxEndJob does not support activation as half while weights are floats.");
|
||||
return new JobHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Default, FloatPrecision = FloatPrecision.Standard)]
|
||||
unsafe struct SoftmaxEndJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } float* Sptr => S.ptrfloat;
|
||||
public ReadOnlyMemResource B { get; set; } float* Bptr => B.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public SoftmaxEndJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = ((i / data.offsetReduce) % data.reduceDim);
|
||||
int z = ((i / data.offsetReduce) / data.reduceDim);
|
||||
|
||||
Optr[i] = (float)(math.exp(Xptr[i] - Bptr[z * data.offsetReduce + x]) / Sptr[z * data.offsetReduce + x]);
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct LogSoftmaxEndJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXSBO(BurstTensorData pinX, FencedMemoryAlloc pinS, FencedMemoryAlloc pinB, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool WHalf = pinS.type == DataType.Half;
|
||||
bool BHalf = pinB.type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
UnityEngine.Assertions.Assert.AreEqual(WHalf, BHalf);
|
||||
if (AHalf && WHalf)
|
||||
{
|
||||
var job = new LogSoftmaxEndJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && WHalf)
|
||||
{
|
||||
var job = new LogSoftmaxEndJob_ActAsFloat_WeightAsHalf();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else if (!AHalf && !WHalf)
|
||||
{
|
||||
var job = new LogSoftmaxEndJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXSBO(pinX, pinS, pinB, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else //if (AHalf && !WHalf)
|
||||
{
|
||||
UnityEngine.Assertions.Assert.IsTrue(false, "LogSoftmaxEndJob does not support activation as half while weights are floats.");
|
||||
return new JobHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Default, FloatPrecision = FloatPrecision.Standard)]
|
||||
unsafe struct LogSoftmaxEndJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } float* Sptr => S.ptrfloat;
|
||||
public ReadOnlyMemResource B { get; set; } float* Bptr => B.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public LogSoftmaxEndJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = ((i / data.offsetReduce) % data.reduceDim);
|
||||
int z = ((i / data.offsetReduce) / data.reduceDim);
|
||||
|
||||
Optr[i] = (float)((Xptr[i] - Bptr[z * data.offsetReduce + x]) - math.log(Sptr[z * data.offsetReduce + x]));
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct MaxPool2DJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXO(Tensor X, Tensor O, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
var pinX = Pin(X);
|
||||
var pinO = Pin(O, uploadCache: false);
|
||||
return ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
public JobHandle ScheduleXO(BurstTensorData pinX, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
if (AHalf)
|
||||
{
|
||||
var job = new MaxPool2DJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var job = new MaxPool2DJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct MaxPool2DJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public MaxPool2DJobHelper data;
|
||||
|
||||
const int unrollSize = 16;
|
||||
public void Execute(int y)
|
||||
{
|
||||
int accumulatorMemSize = data.inChannels * sizeof(float);
|
||||
float* outputAccumulators = (float*)UnsafeUtility.Malloc(accumulatorMemSize, JobsUtility.CacheLineSize, Allocator.TempJob);
|
||||
for (int n = 0; n < data.outBatch; ++n)
|
||||
for (int x = 0; x < data.outWidth; ++x)
|
||||
{
|
||||
bool firstNotRejectedPixelInKernel = true;
|
||||
// gather max results in accumulators
|
||||
for (int dy = 0; dy < data.kernelHeight; ++dy)
|
||||
{
|
||||
int readY = y * data.strideY + dy - data.padY;
|
||||
if (readY < 0) continue;
|
||||
if (readY >= data.inHeight) continue;
|
||||
|
||||
for (int dx = 0; dx < data.kernelWidth; ++dx)
|
||||
{
|
||||
int readX = x * data.strideX + dx - data.padY;
|
||||
if (readX < 0) continue;
|
||||
if (readX >= data.inWidth) continue;
|
||||
|
||||
float* dst = outputAccumulators;
|
||||
float* src = Xptr + n * data.inStrideN + readY * data.inStrideH + readX * data.inStrideW;
|
||||
|
||||
int k = 0;
|
||||
if (firstNotRejectedPixelInKernel) // first pass, write-through
|
||||
{
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = *src;
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = *src;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = (*dst) > (*src) ? (*dst) : (*src);
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = (*dst) > (*src) ? (*dst) : (*src);
|
||||
}
|
||||
firstNotRejectedPixelInKernel = false;
|
||||
}
|
||||
}
|
||||
|
||||
// safety net, if kernel was completely outside of X
|
||||
// fill with padding_value (0) to avoid uninitialized memory
|
||||
if (firstNotRejectedPixelInKernel)
|
||||
UnsafeUtility.MemClear(outputAccumulators, accumulatorMemSize);
|
||||
|
||||
{ // write accumulators to memory
|
||||
int k = 0;
|
||||
float* src = outputAccumulators;
|
||||
float* dst = Optr + n * data.outStrideN + y * data.outStrideH + x * data.outStrideW;
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = *src;
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = *src;
|
||||
}
|
||||
}
|
||||
|
||||
UnsafeUtility.Free(outputAccumulators, Allocator.TempJob);
|
||||
}
|
||||
}
|
||||
|
||||
internal partial struct AvgPool2DJobHelper
|
||||
{
|
||||
public JobHandle ScheduleXO(Tensor X, Tensor O, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
var pinX = Pin(X);
|
||||
var pinO = Pin(O, uploadCache: false);
|
||||
return ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
public JobHandle ScheduleXO(BurstTensorData pinX, BurstTensorData pinO, int arrayLength, int innerBatchCount, FencingHelperMode fencingMode=FencingHelperMode.UpdateResourcesFencesOnScheduling)
|
||||
{
|
||||
bool AHalf = pinX.array.Type == DataType.Half;
|
||||
bool OHalf = pinO.array.Type == DataType.Half;
|
||||
UnityEngine.Assertions.Assert.AreEqual(AHalf, OHalf);
|
||||
if (AHalf)
|
||||
{
|
||||
var job = new AvgPool2DJob_Full_Half();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var job = new AvgPool2DJob_Full_Float();
|
||||
job.data = this;
|
||||
return job.ScheduleXO(pinX, pinO, arrayLength, innerBatchCount, fencingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct AvgPool2DJob_Full_Float : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public AvgPool2DJobHelper data;
|
||||
|
||||
const int unrollSize = 16;
|
||||
public void Execute(int y)
|
||||
{
|
||||
int accumulatorMemSize = data.inChannels * sizeof(float);
|
||||
float* outputAccumulators = (float*)UnsafeUtility.Malloc(accumulatorMemSize, JobsUtility.CacheLineSize, Allocator.TempJob);
|
||||
|
||||
for (int n = 0; n < data.outBatch; ++n)
|
||||
for (int x = 0; x < data.outWidth; ++x)
|
||||
{
|
||||
// reset accumulators & counter
|
||||
int counter = 0;
|
||||
UnsafeUtility.MemClear(outputAccumulators, accumulatorMemSize);
|
||||
|
||||
// gather sums in accumulators
|
||||
for (int dy = 0; dy < data.kernelHeight; ++dy)
|
||||
{
|
||||
int readY = y * data.strideY + dy - data.padY;
|
||||
if (readY < 0) continue;
|
||||
if (readY >= data.inHeight) continue;
|
||||
|
||||
for (int dx = 0; dx < data.kernelWidth; ++dx)
|
||||
{
|
||||
int readX = x * data.strideX + dx - data.padY;
|
||||
if (readX < 0) continue;
|
||||
if (readX >= data.inWidth) continue;
|
||||
|
||||
float* dst = outputAccumulators;
|
||||
float* src = Xptr + n * data.inStrideN + readY * data.inStrideH + readX * data.inStrideW;
|
||||
|
||||
int k = 0;
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst += *src;
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst += *src;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
// safety net, if kernel was completely outside of X
|
||||
counter = math.max(1, counter);
|
||||
|
||||
{ // write accumulators to memory
|
||||
int k = 0;
|
||||
float invCounter = 1f / counter;
|
||||
float* src = outputAccumulators;
|
||||
float* dst = Optr + n * data.outStrideN + y * data.outStrideH + x * data.outStrideW;
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = (float)(*src * invCounter);
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = (float)(*src * invCounter);
|
||||
}
|
||||
}
|
||||
|
||||
UnsafeUtility.Free(outputAccumulators, Allocator.TempJob);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Reduce jobs declaration for mode: _ActAsFloat_WeightAsHalf
|
||||
|
||||
|
||||
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ExpBiasReduceJob_ActAsFloat_WeightAsHalf : IJobParallelFor, IJobResourceDeclarationXBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public ExpBiasReduceJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float accum = 0.0f;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
float b = Bptr[y * data.offsetReduce + x];
|
||||
accum += math.exp(v - b);
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (float)accum;
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Default, FloatPrecision = FloatPrecision.Standard)]
|
||||
unsafe struct SoftmaxEndJob_ActAsFloat_WeightAsHalf : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public SoftmaxEndJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = ((i / data.offsetReduce) % data.reduceDim);
|
||||
int z = ((i / data.offsetReduce) / data.reduceDim);
|
||||
|
||||
Optr[i] = (float)(math.exp(Xptr[i] - Bptr[z * data.offsetReduce + x]) / Sptr[z * data.offsetReduce + x]);
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Default, FloatPrecision = FloatPrecision.Standard)]
|
||||
unsafe struct LogSoftmaxEndJob_ActAsFloat_WeightAsHalf : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } float* Xptr => X.ptrfloat;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } float* Optr => O.ptrfloat;
|
||||
public LogSoftmaxEndJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = ((i / data.offsetReduce) % data.reduceDim);
|
||||
int z = ((i / data.offsetReduce) / data.reduceDim);
|
||||
|
||||
Optr[i] = (float)((Xptr[i] - Bptr[z * data.offsetReduce + x]) - math.log(Sptr[z * data.offsetReduce + x]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
#region Reduce jobs declaration for mode: _Full_Half
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ReduceMaxJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public ReduceMaxJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float maxV = float.MinValue;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
maxV = math.max(maxV, v);
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (half)maxV;
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ReduceSumJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public ReduceSumJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float sumV = 0;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
sumV += v;
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (half)(sumV);
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ReduceMeanJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public ReduceMeanJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float sumV = 0;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
sumV += v;
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (half)(sumV / (float)data.reduceDim);
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct ExpBiasReduceJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public ExpBiasReduceJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = i / data.offsetReduce;
|
||||
|
||||
float accum = 0.0f;
|
||||
for (int z = 0; z < data.reduceDim; ++z)
|
||||
{
|
||||
float v = Xptr[y * data.offsetReduce * data.reduceDim + z * data.offsetReduce + x];
|
||||
float b = Bptr[y * data.offsetReduce + x];
|
||||
accum += math.exp(v - b);
|
||||
}
|
||||
Optr[y * data.offsetReduce + x] = (half)accum;
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Default, FloatPrecision = FloatPrecision.Standard)]
|
||||
unsafe struct SoftmaxEndJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public SoftmaxEndJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = ((i / data.offsetReduce) % data.reduceDim);
|
||||
int z = ((i / data.offsetReduce) / data.reduceDim);
|
||||
|
||||
Optr[i] = (half)(math.exp(Xptr[i] - Bptr[z * data.offsetReduce + x]) / Sptr[z * data.offsetReduce + x]);
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Default, FloatPrecision = FloatPrecision.Standard)]
|
||||
unsafe struct LogSoftmaxEndJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXSBO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadOnlyMemResource S { get; set; } half* Sptr => S.ptrhalf;
|
||||
public ReadOnlyMemResource B { get; set; } half* Bptr => B.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public LogSoftmaxEndJobHelper data;
|
||||
|
||||
public void Execute(int i)
|
||||
{
|
||||
int x = i % data.offsetReduce;
|
||||
int y = ((i / data.offsetReduce) % data.reduceDim);
|
||||
int z = ((i / data.offsetReduce) / data.reduceDim);
|
||||
|
||||
Optr[i] = (half)((Xptr[i] - Bptr[z * data.offsetReduce + x]) - math.log(Sptr[z * data.offsetReduce + x]));
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct MaxPool2DJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public MaxPool2DJobHelper data;
|
||||
|
||||
const int unrollSize = 16;
|
||||
public void Execute(int y)
|
||||
{
|
||||
int accumulatorMemSize = data.inChannels * sizeof(half);
|
||||
half* outputAccumulators = (half*)UnsafeUtility.Malloc(accumulatorMemSize, JobsUtility.CacheLineSize, Allocator.TempJob);
|
||||
for (int n = 0; n < data.outBatch; ++n)
|
||||
for (int x = 0; x < data.outWidth; ++x)
|
||||
{
|
||||
bool firstNotRejectedPixelInKernel = true;
|
||||
// gather max results in accumulators
|
||||
for (int dy = 0; dy < data.kernelHeight; ++dy)
|
||||
{
|
||||
int readY = y * data.strideY + dy - data.padY;
|
||||
if (readY < 0) continue;
|
||||
if (readY >= data.inHeight) continue;
|
||||
|
||||
for (int dx = 0; dx < data.kernelWidth; ++dx)
|
||||
{
|
||||
int readX = x * data.strideX + dx - data.padY;
|
||||
if (readX < 0) continue;
|
||||
if (readX >= data.inWidth) continue;
|
||||
|
||||
half* dst = outputAccumulators;
|
||||
half* src = Xptr + n * data.inStrideN + readY * data.inStrideH + readX * data.inStrideW;
|
||||
|
||||
int k = 0;
|
||||
if (firstNotRejectedPixelInKernel) // first pass, write-through
|
||||
{
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = *src;
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = *src;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = (*dst) > (*src) ? (*dst) : (*src);
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = (*dst) > (*src) ? (*dst) : (*src);
|
||||
}
|
||||
firstNotRejectedPixelInKernel = false;
|
||||
}
|
||||
}
|
||||
|
||||
// safety net, if kernel was completely outside of X
|
||||
// fill with padding_value (0) to avoid uninitialized memory
|
||||
if (firstNotRejectedPixelInKernel)
|
||||
UnsafeUtility.MemClear(outputAccumulators, accumulatorMemSize);
|
||||
|
||||
{ // write accumulators to memory
|
||||
int k = 0;
|
||||
half* src = outputAccumulators;
|
||||
half* dst = Optr + n * data.outStrideN + y * data.outStrideH + x * data.outStrideW;
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = *src;
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = *src;
|
||||
}
|
||||
}
|
||||
|
||||
UnsafeUtility.Free(outputAccumulators, Allocator.TempJob);
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile(OptimizeFor = OptimizeFor.Performance, FloatMode = FloatMode.Fast, FloatPrecision = FloatPrecision.Low)]
|
||||
unsafe struct AvgPool2DJob_Full_Half : IJobParallelFor, IJobResourceDeclarationXO
|
||||
{
|
||||
public ReadOnlyMemResource X { get; set; } half* Xptr => X.ptrhalf;
|
||||
public ReadWriteMemResource O { get; set; } half* Optr => O.ptrhalf;
|
||||
public AvgPool2DJobHelper data;
|
||||
|
||||
const int unrollSize = 16;
|
||||
public void Execute(int y)
|
||||
{
|
||||
int accumulatorMemSize = data.inChannels * sizeof(half);
|
||||
half* outputAccumulators = (half*)UnsafeUtility.Malloc(accumulatorMemSize, JobsUtility.CacheLineSize, Allocator.TempJob);
|
||||
|
||||
for (int n = 0; n < data.outBatch; ++n)
|
||||
for (int x = 0; x < data.outWidth; ++x)
|
||||
{
|
||||
// reset accumulators & counter
|
||||
int counter = 0;
|
||||
UnsafeUtility.MemClear(outputAccumulators, accumulatorMemSize);
|
||||
|
||||
// gather sums in accumulators
|
||||
for (int dy = 0; dy < data.kernelHeight; ++dy)
|
||||
{
|
||||
int readY = y * data.strideY + dy - data.padY;
|
||||
if (readY < 0) continue;
|
||||
if (readY >= data.inHeight) continue;
|
||||
|
||||
for (int dx = 0; dx < data.kernelWidth; ++dx)
|
||||
{
|
||||
int readX = x * data.strideX + dx - data.padY;
|
||||
if (readX < 0) continue;
|
||||
if (readX >= data.inWidth) continue;
|
||||
|
||||
half* dst = outputAccumulators;
|
||||
half* src = Xptr + n * data.inStrideN + readY * data.inStrideH + readX * data.inStrideW;
|
||||
|
||||
int k = 0;
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst += *src;
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst += *src;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
// safety net, if kernel was completely outside of X
|
||||
counter = math.max(1, counter);
|
||||
|
||||
{ // write accumulators to memory
|
||||
int k = 0;
|
||||
float invCounter = 1f / counter;
|
||||
half* src = outputAccumulators;
|
||||
half* dst = Optr + n * data.outStrideN + y * data.outStrideH + x * data.outStrideW;
|
||||
for (; k < data.inChannels - unrollSize + 1; k += unrollSize) // unroll of inChannels loop
|
||||
for (int q = 0; q < unrollSize; q++, src++, dst++)
|
||||
*dst = (half)(*src * invCounter);
|
||||
for (; k < data.inChannels; k++, src++, dst++) // remainder of inChannels loop
|
||||
*dst = (half)(*src * invCounter);
|
||||
}
|
||||
}
|
||||
|
||||
UnsafeUtility.Free(outputAccumulators, Allocator.TempJob);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f555ca3db5aa9674f9cdba4d5b715e79
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user