Resolve WES-90 "Integrate signpredictor in courses"

This commit is contained in:
Louis Adriaens
2023-03-18 19:53:17 +00:00
committed by Jerome Coudron
parent 1a75791d62
commit 746906294b
463 changed files with 99422 additions and 1187 deletions

View File

@@ -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

View File

@@ -4,7 +4,9 @@
"references": [
"Unity.TextMeshPro",
"AccountsScripts",
"InterfacesScripts"
"InterfacesScripts",
"SignPredictor",
"Tween"
],
"includePlatforms": [],
"excludePlatforms": [],

View 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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 44e682a32ee15cc489bf50f3a06f717b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 40ff941e1b34847bdb160c6950f35aec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "MediaPipeUnityScripts",
"rootNamespace": "",
"references": [
"GUID:04c4d86a70aa56c55a78c61f1ab1a56d"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: edc93f477bb73a743a97d6882ed330b3
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1c318b35315a4ef44be1df6f27b8b582
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1275314861c48ed40a9f02557c8ca10d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d0b6b39a21908f94fbbd9f2c196a9725
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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();
}
}
}

View File

@@ -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"
}

View File

@@ -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();
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7992d1284c7de4b089f4155b3e4ada83
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d2a1acaa9722345fb8f9d335700ccb30
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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]}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f2f3eb6345d7543f893098c608366c3e
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View 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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bbae634e9481aea4ab4c36f614fbb04f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 63f6070ee724f1c469760f5ff86c865c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f5d6bfc025cef9c42baa4347252a7b0c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ef68f630eddb21842a6203b9e5dfe09b
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d7ead4f028994eb438023908d60d667c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,2 @@
Left
Right

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fce7a788474e214438428ef836e0bb36
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c51c620cdc2fe524fa2692079cd198e6
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 713df1fb4455ae74e8a3bcd90a547855
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Tween.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4d5851cbb0190ab4f8ed2b8be18e705d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tween/Demo.meta Normal file
View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 9f5880b033929b7478e7b3a9ed6c5ee7
folderAsset: yes
timeCreated: 1455295494
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View 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();
}
}
}
}

View 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:

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View 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:

View 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: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2d994b80f30361c449f5504b6ddb859a
timeCreated: 1455295548
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View 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}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ad948b3082b546f4e8f3565bdfe0abf6
timeCreated: 1455295598
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View 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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 493623c166a735445b4283396018d38b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4890085278179872738
userData:
assetBundleName:
assetBundleVariant:

24
Assets/Tween/Readme.txt Normal file
View 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.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d536e9d2e2dc3f94cb6ca36e79a2d583
timeCreated: 1455298832
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
{
"name": "Tween"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 58e104b97fb3752438ada2902a36dcbf
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

1096
Assets/Tween/Tween.cs Normal file

File diff suppressed because it is too large Load Diff

View 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
View 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
View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9b758111ae1c33e4b9fdbe46d5d9a118
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f6ebab52a13ea425ba87006839f1d776
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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) + "}";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 92cb0e57f8c0c4255a2d2d93f844424d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View 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:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19ed1486aa27d4903b34839f37b8f69f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View 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:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 683b6cb6d0a474744822c888b46772c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08ecb3218a86c6741aed5b2a299b203b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9f1e7d835703842dda0e25142ed6c3c9
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a03a1fa0e3b784e19a9e9d31b945b252
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5bec48e8f6ff349488387cf35fbae752
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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")]

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f7f9574517c146ada866c486dc392731
timeCreated: 1533296387

View 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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67f00a1befd4144eca5685250d893f09
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 355dc370391814b1c874848bb843b91c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f44c1c453c1754aaeb1e8608df82452b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5071bbeadb81d034f827f20e95c52ee6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5211ff135b3b87f42be25a8505a28df7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d05274a6ecc82404abe715a573ea8e74
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 417ca864422a2384ab3013114bf9f845
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 30d1de61c64693a4895a66fecf45a004
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -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